6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
9
- import assert from 'assert' ;
10
- import * as child_process from 'child_process' ;
11
- import * as fs from 'fs ' ;
12
- import * as path from 'path' ;
13
- import { fileURLToPath , pathToFileURL } from 'url' ;
9
+ import assert from 'node: assert' ;
10
+ import * as child_process from 'node: child_process' ;
11
+ import { copyFile , readFile , rm , writeFile } from 'node:fs/promises ' ;
12
+ import * as path from 'node: path' ;
13
+ import { fileURLToPath , pathToFileURL } from 'node: url' ;
14
14
import build from './build.mjs' ;
15
15
import { packages } from './packages.mjs' ;
16
16
17
- export interface CreateOptions {
17
+ export interface CreateOptions extends Record < string , unknown > {
18
18
_ : string [ ] ;
19
19
}
20
20
@@ -37,34 +37,52 @@ async function _exec(command: string, args: string[], opts: { cwd?: string }) {
37
37
}
38
38
39
39
export default async function ( args : CreateOptions , cwd : string ) : Promise < number > {
40
- const projectName = args . _ [ 0 ] ;
40
+ const { _, ...otherArgOptions } = args ;
41
+ const projectName = _ [ 0 ] ;
42
+ assert ( projectName , 'Project name must be provided.' ) ;
43
+
44
+ const ngNewAdditionalOptions = Object . entries ( otherArgOptions ) . map (
45
+ ( [ key , value ] ) => `--${ key } =${ value } ` ,
46
+ ) ;
41
47
42
48
const oldCwd = process . cwd ( ) ;
43
49
console . info ( 'Building...' ) ;
44
- await build ( { local : true } ) ;
50
+
51
+ const buildResult = await build ( { local : true } ) ;
52
+ const cliBuild = buildResult . find ( ( { name } ) => name === 'angular/cli' ) ;
53
+
54
+ assert ( cliBuild ) ;
45
55
46
56
process . chdir ( cwd ) ;
47
- console . info ( 'Creating project...' ) ;
48
57
49
- assert ( projectName , 'Project name must be provided.' ) ;
58
+ // The below is needed as NPX does not guarantee that the updated version is used unless the file name changes.
59
+ const newTarballName = cliBuild . tarPath . replace ( '.tgz' , '-' + Date . now ( ) + '.tgz' ) ;
60
+ await copyFile ( cliBuild . tarPath , newTarballName ) ;
50
61
51
- await _exec (
52
- 'npx' ,
53
- [
54
- '--yes' ,
55
- pathToFileURL ( path . join ( __dirname , '../dist/_angular_cli.tgz' ) ) . toString ( ) ,
56
- 'new' ,
57
- projectName ,
58
- '--skip-install' ,
59
- '--skip-git' ,
60
- '--no-interactive' ,
61
- ] ,
62
- { cwd } ,
63
- ) ;
62
+ console . info ( 'Creating project...' ) ;
63
+
64
+ try {
65
+ await _exec (
66
+ 'npx' ,
67
+ [
68
+ '--yes' ,
69
+ pathToFileURL ( newTarballName ) . toString ( ) ,
70
+ 'new' ,
71
+ projectName ,
72
+ '--skip-install' ,
73
+ '--skip-git' ,
74
+ '--no-interactive' ,
75
+ ...ngNewAdditionalOptions ,
76
+ ] ,
77
+ { cwd } ,
78
+ ) ;
79
+ } finally {
80
+ await rm ( newTarballName , { maxRetries : 3 } ) ;
81
+ }
64
82
65
83
console . info ( 'Updating package.json...' ) ;
66
84
const packageJsonPath = path . join ( projectName , 'package.json' ) ;
67
- const packageJson = JSON . parse ( fs . readFileSync ( packageJsonPath , 'utf-8' ) ) ;
85
+ const packageJson = JSON . parse ( await readFile ( packageJsonPath , 'utf-8' ) ) ;
68
86
69
87
if ( ! packageJson [ 'dependencies' ] ) {
70
88
packageJson [ 'dependencies' ] = { } ;
@@ -84,7 +102,7 @@ export default async function (args: CreateOptions, cwd: string): Promise<number
84
102
}
85
103
}
86
104
87
- fs . writeFileSync ( packageJsonPath , JSON . stringify ( packageJson , null , 2 ) , 'utf-8' ) ;
105
+ await writeFile ( packageJsonPath , JSON . stringify ( packageJson , null , 2 ) , 'utf-8' ) ;
88
106
89
107
console . info ( 'Installing npm packages...' ) ;
90
108
await _exec ( 'npm' , [ 'install' ] , { cwd : path . join ( cwd , projectName ) } ) ;
0 commit comments