- Notifications
You must be signed in to change notification settings - Fork 12k
/
Copy pathcreate.mts
112 lines (89 loc) · 3.38 KB
/
create.mts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
importassertfrom'node:assert';
import*aschild_processfrom'node:child_process';
import{copyFile,readFile,rm,writeFile}from'node:fs/promises';
import*aspathfrom'node:path';
import{fileURLToPath,pathToFileURL}from'node:url';
importbuildfrom'./build.mjs';
import{packages}from'./packages.mjs';
exportinterfaceCreateOptionsextendsRecord<string,unknown>{
_: string[];
}
const__dirname=path.dirname(fileURLToPath(import.meta.url));
asyncfunction_exec(command: string,args: string[],opts: {cwd?: string}){
const{ status, error, stderr, stdout }=child_process.spawnSync(command,args,{ ...opts});
if(status!=0){
console.error(`Command failed: ${command}${args.map((x)=>JSON.stringify(x)).join(', ')}`);
if(error){
console.error('Error: '+(error ? error.message : 'undefined'));
}else{
console.error(`STDERR:\n${stderr}`);
}
throwerror;
}
return{ stdout };
}
exportdefaultasyncfunction(args: CreateOptions,cwd: string): Promise<number>{
const{ _, ...otherArgOptions}=args;
constprojectName=_[0];
assert(projectName,'Project name must be provided.');
constngNewAdditionalOptions=Object.entries(otherArgOptions).map(
([key,value])=>`--${key}=${value}`,
);
constoldCwd=process.cwd();
console.info('Building...');
constbuildResult=awaitbuild({local: true});
constcliBuild=buildResult.find(({ name })=>name==='angular/cli');
assert(cliBuild);
process.chdir(cwd);
// The below is needed as NPX does not guarantee that the updated version is used unless the file name changes.
constnewTarballName=cliBuild.tarPath.replace('.tgz','-'+Date.now()+'.tgz');
awaitcopyFile(cliBuild.tarPath,newTarballName);
console.info('Creating project...');
try{
await_exec(
'npx',
[
'--yes',
pathToFileURL(newTarballName).toString(),
'new',
projectName,
'--skip-install',
'--skip-git',
'--no-interactive',
...ngNewAdditionalOptions,
],
{ cwd },
);
}finally{
awaitrm(newTarballName,{maxRetries: 3});
}
console.info('Updating package.json...');
constpackageJsonPath=path.join(projectName,'package.json');
constpackageJson=JSON.parse(awaitreadFile(packageJsonPath,'utf-8'));
packageJson['dependencies']??={};
packageJson['devDependencies']??={};
packageJson['overrides']??={};
// Set the dependencies to the new build we just used.
for(constpackageNameofpackages.map(({ name })=>name)){
consttar=path.join(__dirname,'../dist',packageName.replace(/\/|@/g,'_')+'.tgz');
if(packageNameinpackageJson['dependencies']){
packageJson['dependencies'][packageName]=tar;
}elseif(packageNameinpackageJson['devDependencies']){
packageJson['devDependencies'][packageName]=tar;
}else{
packageJson['overrides'][packageName]=tar;
}
}
awaitwriteFile(packageJsonPath,JSON.stringify(packageJson,null,2),'utf-8');
console.info('Installing npm packages...');
await_exec('npm',['install'],{cwd: path.join(cwd,projectName)});
process.chdir(oldCwd);
return0;
}