@create-node-app/core 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +39 -0
- package/dist/index.js +867 -0
- package/dist/index.mjs +839 -0
- package/package.json +49 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,839 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined")
|
|
5
|
+
return require.apply(this, arguments);
|
|
6
|
+
throw new Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
// index.ts
|
|
10
|
+
import chalk4 from "chalk";
|
|
11
|
+
import envinfo from "envinfo";
|
|
12
|
+
|
|
13
|
+
// installer.ts
|
|
14
|
+
import _2 from "underscore";
|
|
15
|
+
import path3 from "path";
|
|
16
|
+
import fs4 from "fs";
|
|
17
|
+
import chalk3 from "chalk";
|
|
18
|
+
import os3 from "os";
|
|
19
|
+
import semver2 from "semver";
|
|
20
|
+
import spawn2 from "cross-spawn";
|
|
21
|
+
import { execSync as execSync2 } from "child_process";
|
|
22
|
+
|
|
23
|
+
// helpers.ts
|
|
24
|
+
import { execSync } from "child_process";
|
|
25
|
+
import spawn from "cross-spawn";
|
|
26
|
+
import chalk from "chalk";
|
|
27
|
+
import semver from "semver";
|
|
28
|
+
import dns from "dns";
|
|
29
|
+
import { URL as URL2 } from "url";
|
|
30
|
+
var shouldUseYarn = () => {
|
|
31
|
+
try {
|
|
32
|
+
execSync("yarnpkg --version", { stdio: "ignore" });
|
|
33
|
+
return true;
|
|
34
|
+
} catch (e) {
|
|
35
|
+
console.log(e);
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
var checkThatNpmCanReadCwd = () => {
|
|
40
|
+
const cwd = process.cwd();
|
|
41
|
+
let childOutput = null;
|
|
42
|
+
try {
|
|
43
|
+
childOutput = spawn.sync("npm", ["config", "list"]).output.join("");
|
|
44
|
+
} catch (err) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
if (typeof childOutput !== "string") {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
const lines = childOutput.split("\n");
|
|
51
|
+
const prefix = " cwd = ";
|
|
52
|
+
const line = lines.find((l) => l.indexOf(prefix) === 0);
|
|
53
|
+
if (typeof line !== "string") {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
const npmCWD = line.substring(prefix.length);
|
|
57
|
+
if (npmCWD === cwd) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
console.error(
|
|
61
|
+
chalk.red(
|
|
62
|
+
`Could not start an npm process in the right directory.
|
|
63
|
+
|
|
64
|
+
The current directory is: ${chalk.bold(cwd)}
|
|
65
|
+
However, a newly started npm process runs in: ${chalk.bold(
|
|
66
|
+
npmCWD
|
|
67
|
+
)}
|
|
68
|
+
|
|
69
|
+
This is probably caused by a misconfigured system terminal shell.`
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
if (process.platform === "win32") {
|
|
73
|
+
console.error(
|
|
74
|
+
chalk.red(`On Windows, this can usually be fixed by running:
|
|
75
|
+
|
|
76
|
+
`) + ` ${chalk.cyan(
|
|
77
|
+
"reg"
|
|
78
|
+
)} delete "HKCU\\Software\\Microsoft\\Command Processor" /v AutoRun /f
|
|
79
|
+
${chalk.cyan(
|
|
80
|
+
"reg"
|
|
81
|
+
)} delete "HKLM\\Software\\Microsoft\\Command Processor" /v AutoRun /f
|
|
82
|
+
|
|
83
|
+
` + chalk.red(`Try to run the above two lines in the terminal.
|
|
84
|
+
`) + chalk.red(
|
|
85
|
+
`To learn more about this problem, read: https://blogs.msdn.microsoft.com/oldnewthing/20071121-00/?p=24433/`
|
|
86
|
+
)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
};
|
|
91
|
+
var checkNpmVersion = () => {
|
|
92
|
+
let hasMinNpm = false;
|
|
93
|
+
let npmVersion = void 0;
|
|
94
|
+
try {
|
|
95
|
+
npmVersion = execSync("npm --version").toString().trim();
|
|
96
|
+
hasMinNpm = semver.gte(npmVersion, "3.0.0");
|
|
97
|
+
} catch (err) {
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
hasMinNpm,
|
|
101
|
+
npmVersion
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
var getProxy = () => {
|
|
105
|
+
if (process.env.HTTPS_PROXY) {
|
|
106
|
+
return process.env.HTTPS_PROXY;
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const httpsProxy = execSync("npm config get https-proxy").toString().trim();
|
|
110
|
+
return httpsProxy !== "null" ? httpsProxy : void 0;
|
|
111
|
+
} catch (e) {
|
|
112
|
+
}
|
|
113
|
+
return "";
|
|
114
|
+
};
|
|
115
|
+
var checkIfOnline = (useYarn) => {
|
|
116
|
+
if (!useYarn) {
|
|
117
|
+
return Promise.resolve(true);
|
|
118
|
+
}
|
|
119
|
+
return new Promise((resolve) => {
|
|
120
|
+
dns.lookup("registry.yarnpkg.com", (err) => {
|
|
121
|
+
let proxy;
|
|
122
|
+
if (err != null && (proxy = getProxy())) {
|
|
123
|
+
dns.lookup(new URL2(proxy).hostname, (proxyErr) => {
|
|
124
|
+
resolve(!proxyErr);
|
|
125
|
+
});
|
|
126
|
+
} else {
|
|
127
|
+
resolve(!err);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// package.ts
|
|
134
|
+
import { existsSync } from "fs";
|
|
135
|
+
import merge from "lodash.merge";
|
|
136
|
+
|
|
137
|
+
// paths.ts
|
|
138
|
+
import fs2 from "fs";
|
|
139
|
+
import os2 from "os";
|
|
140
|
+
import path2 from "path";
|
|
141
|
+
|
|
142
|
+
// git.ts
|
|
143
|
+
import os from "os";
|
|
144
|
+
import childProcess from "child_process";
|
|
145
|
+
import path from "path";
|
|
146
|
+
import { promisify } from "util";
|
|
147
|
+
import fs from "fs";
|
|
148
|
+
import download from "download";
|
|
149
|
+
import debug from "debug";
|
|
150
|
+
var log = debug("cna:git");
|
|
151
|
+
var exec = promisify(childProcess.exec);
|
|
152
|
+
var filterGit = (src) => {
|
|
153
|
+
return !/(\\|\/)\.git\b/.test(src);
|
|
154
|
+
};
|
|
155
|
+
var clone = (git, target, branch) => {
|
|
156
|
+
const command = ["git", "clone", "--depth=1", "-b", branch, git, target];
|
|
157
|
+
return exec(command.join(" "));
|
|
158
|
+
};
|
|
159
|
+
var pull = async (cwd) => {
|
|
160
|
+
await exec("git checkout -f", { cwd });
|
|
161
|
+
await exec("git pull", { cwd });
|
|
162
|
+
};
|
|
163
|
+
var downloadRepository = async ({
|
|
164
|
+
git = "",
|
|
165
|
+
zip,
|
|
166
|
+
offline = false,
|
|
167
|
+
target = "./",
|
|
168
|
+
branch = "main",
|
|
169
|
+
way = "git",
|
|
170
|
+
targetId,
|
|
171
|
+
cacheDir: optsCacheDir
|
|
172
|
+
}) => {
|
|
173
|
+
const absoluteTarget = path.isAbsolute(target) ? target : path.resolve(target);
|
|
174
|
+
const isGithub = /^[^/]+\/[^/]+$/.test(git);
|
|
175
|
+
const gitUrl = isGithub ? `https://github.com/${git}` : git;
|
|
176
|
+
const zipUrl = isGithub ? `https://github.com/${git}/archive/${branch}.zip` : zip;
|
|
177
|
+
const id = targetId || Buffer.from(`${git}@${branch}`).toString("base64");
|
|
178
|
+
let cacheDir = optsCacheDir || path.join(os.homedir(), ".cache", "cna", id);
|
|
179
|
+
cacheDir = path.isAbsolute(cacheDir) ? cacheDir : path.resolve(cacheDir);
|
|
180
|
+
log("cache folder: %s", cacheDir);
|
|
181
|
+
log("git url: %s", gitUrl);
|
|
182
|
+
log("zip url: %s", zipUrl);
|
|
183
|
+
const cached = fs.existsSync(cacheDir);
|
|
184
|
+
const createByGit = async () => {
|
|
185
|
+
log("git mode");
|
|
186
|
+
if (!cached) {
|
|
187
|
+
if (!gitUrl) {
|
|
188
|
+
throw new Error(
|
|
189
|
+
`Expect parameter opts.git when opts.way is 'git', but got ${gitUrl}`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
await clone(gitUrl, cacheDir, branch);
|
|
193
|
+
}
|
|
194
|
+
if (offline) {
|
|
195
|
+
fs.cpSync(cacheDir, absoluteTarget, {
|
|
196
|
+
force: true,
|
|
197
|
+
filter: filterGit,
|
|
198
|
+
recursive: true
|
|
199
|
+
});
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
await pull(cacheDir);
|
|
203
|
+
setTimeout(() => {
|
|
204
|
+
fs.cpSync(cacheDir, absoluteTarget, {
|
|
205
|
+
force: true,
|
|
206
|
+
filter: filterGit,
|
|
207
|
+
recursive: true
|
|
208
|
+
});
|
|
209
|
+
}, 400);
|
|
210
|
+
};
|
|
211
|
+
const createByZip = async () => {
|
|
212
|
+
log("zip mode");
|
|
213
|
+
if (!zipUrl) {
|
|
214
|
+
throw new Error(
|
|
215
|
+
`Expect parameter opts.zip when opts.way is 'zip', but got ${zipUrl}`
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
await download(zipUrl, target, { extract: true });
|
|
219
|
+
};
|
|
220
|
+
switch (way) {
|
|
221
|
+
case "git":
|
|
222
|
+
return createByGit();
|
|
223
|
+
case "zip":
|
|
224
|
+
return createByZip();
|
|
225
|
+
default:
|
|
226
|
+
throw new Error(`Expect parameter opts.way is 'git' or 'zip'`);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// paths.ts
|
|
231
|
+
var solveValuesFromAddonUrl = (addon) => {
|
|
232
|
+
const url = new URL(addon);
|
|
233
|
+
const origin = `${url.protocol}//${url.host}`;
|
|
234
|
+
const [org, repo, , branch = "", ...subdir] = url.pathname.slice(1).split("/");
|
|
235
|
+
const ignorePackage = url.searchParams.get("ignorePackage") === "true";
|
|
236
|
+
return {
|
|
237
|
+
url: `${origin}/${org}/${repo}`,
|
|
238
|
+
branch,
|
|
239
|
+
subdir: subdir.join("/"),
|
|
240
|
+
protocol: url.protocol,
|
|
241
|
+
host: url.host,
|
|
242
|
+
pathname: url.pathname,
|
|
243
|
+
ignorePackage
|
|
244
|
+
};
|
|
245
|
+
};
|
|
246
|
+
var solveRepositoryPath = async ({
|
|
247
|
+
url,
|
|
248
|
+
branch,
|
|
249
|
+
subdir
|
|
250
|
+
}) => {
|
|
251
|
+
const targetId = Buffer.from(`${url}#${branch}#${subdir}`).toString("base64");
|
|
252
|
+
const target = path2.join(os2.homedir(), ".cna", targetId);
|
|
253
|
+
try {
|
|
254
|
+
await downloadRepository({
|
|
255
|
+
git: url,
|
|
256
|
+
branch,
|
|
257
|
+
target,
|
|
258
|
+
targetId
|
|
259
|
+
});
|
|
260
|
+
} catch {
|
|
261
|
+
}
|
|
262
|
+
return { dir: target, subdir };
|
|
263
|
+
};
|
|
264
|
+
var solveAddonPath = async (addon) => {
|
|
265
|
+
try {
|
|
266
|
+
const { url, branch, subdir, protocol, host, pathname, ignorePackage } = solveValuesFromAddonUrl(addon);
|
|
267
|
+
if (protocol === "file:") {
|
|
268
|
+
return {
|
|
269
|
+
dir: path2.resolve(host, pathname),
|
|
270
|
+
subdir
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
const gitData = await solveRepositoryPath({
|
|
274
|
+
url,
|
|
275
|
+
branch,
|
|
276
|
+
subdir
|
|
277
|
+
});
|
|
278
|
+
return { ...gitData, ignorePackage };
|
|
279
|
+
} catch {
|
|
280
|
+
return {
|
|
281
|
+
dir: path2.resolve(__dirname, "..", "addons", addon),
|
|
282
|
+
ignorePackage: void 0
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
var getAddonPackagePath = async (addon, name = "package", ignorePackage = false) => {
|
|
287
|
+
const {
|
|
288
|
+
dir,
|
|
289
|
+
subdir,
|
|
290
|
+
ignorePackage: addonIgnorePackage
|
|
291
|
+
} = await solveAddonPath(addon);
|
|
292
|
+
if (name === "package.json" && (ignorePackage || addonIgnorePackage)) {
|
|
293
|
+
throw new Error("package.json should be ignored for file addon");
|
|
294
|
+
}
|
|
295
|
+
if (subdir) {
|
|
296
|
+
return path2.resolve(dir, subdir, name);
|
|
297
|
+
}
|
|
298
|
+
return path2.resolve(dir, name);
|
|
299
|
+
};
|
|
300
|
+
var getAddonTemplateDirPath = async (addonUrl) => {
|
|
301
|
+
const { dir, subdir = "" } = await solveAddonPath(addonUrl);
|
|
302
|
+
let templateDirPath = path2.resolve(dir, subdir);
|
|
303
|
+
const templateDirPathWithTemplate = path2.resolve(templateDirPath, "template");
|
|
304
|
+
return new Promise((resolve, reject) => {
|
|
305
|
+
fs2.stat(templateDirPathWithTemplate, (err, stats) => {
|
|
306
|
+
if (err) {
|
|
307
|
+
return reject(err);
|
|
308
|
+
}
|
|
309
|
+
if (stats.isDirectory()) {
|
|
310
|
+
templateDirPath = templateDirPathWithTemplate;
|
|
311
|
+
}
|
|
312
|
+
resolve(templateDirPath);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
// package.ts
|
|
318
|
+
var getInstallableSetup = ({
|
|
319
|
+
dependencies,
|
|
320
|
+
devDependencies,
|
|
321
|
+
...packageJson
|
|
322
|
+
}) => {
|
|
323
|
+
const getInstallableDeps = (deps = {}) => Object.entries(deps).map(([dep, version]) => `${dep}@${version}`);
|
|
324
|
+
return {
|
|
325
|
+
packageJson,
|
|
326
|
+
dependencies: getInstallableDeps(dependencies),
|
|
327
|
+
devDependencies: getInstallableDeps(devDependencies)
|
|
328
|
+
};
|
|
329
|
+
};
|
|
330
|
+
var requireIfExists = (path4) => {
|
|
331
|
+
if (existsSync(path4)) {
|
|
332
|
+
return __require(path4);
|
|
333
|
+
}
|
|
334
|
+
throw new Error(`file ${path4} not exists`);
|
|
335
|
+
};
|
|
336
|
+
var loadAddonsPackages = async ({
|
|
337
|
+
addons = [],
|
|
338
|
+
ignorePackage: globalIgnorePackage = false,
|
|
339
|
+
...config
|
|
340
|
+
}) => {
|
|
341
|
+
const setup = await addons.reduce(
|
|
342
|
+
async (setupPromise, { url: addon, ignorePackage }) => {
|
|
343
|
+
let packageJson = await setupPromise;
|
|
344
|
+
try {
|
|
345
|
+
const template = requireIfExists(
|
|
346
|
+
await getAddonPackagePath(addon, "template.json")
|
|
347
|
+
);
|
|
348
|
+
packageJson = merge(packageJson, template.package || {});
|
|
349
|
+
} catch {
|
|
350
|
+
}
|
|
351
|
+
try {
|
|
352
|
+
const addonPackageJson = requireIfExists(
|
|
353
|
+
await getAddonPackagePath(
|
|
354
|
+
addon,
|
|
355
|
+
"package.json",
|
|
356
|
+
globalIgnorePackage || ignorePackage
|
|
357
|
+
)
|
|
358
|
+
);
|
|
359
|
+
return merge(packageJson, addonPackageJson);
|
|
360
|
+
} catch {
|
|
361
|
+
}
|
|
362
|
+
try {
|
|
363
|
+
const resolveAddonPackage = requireIfExists(
|
|
364
|
+
await getAddonPackagePath(addon)
|
|
365
|
+
);
|
|
366
|
+
packageJson = resolveAddonPackage(packageJson, config);
|
|
367
|
+
} catch {
|
|
368
|
+
}
|
|
369
|
+
return packageJson;
|
|
370
|
+
},
|
|
371
|
+
Promise.resolve({
|
|
372
|
+
name: config.appName,
|
|
373
|
+
dependencies: {},
|
|
374
|
+
devDependencies: {},
|
|
375
|
+
scripts: {}
|
|
376
|
+
})
|
|
377
|
+
);
|
|
378
|
+
return getInstallableSetup(setup);
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
// loaders.ts
|
|
382
|
+
import _ from "underscore";
|
|
383
|
+
import fs3 from "fs";
|
|
384
|
+
import chalk2 from "chalk";
|
|
385
|
+
import readdirp from "readdirp";
|
|
386
|
+
import { dirname } from "path";
|
|
387
|
+
var SRC_PATH_PATTERN = "[src]/";
|
|
388
|
+
var DEFAULT_SRC_PATH = "src/";
|
|
389
|
+
var getSrcDirPattern = (srcDir) => `${srcDir === "." ? "" : srcDir}/`;
|
|
390
|
+
var copyFile = async (src, dest, verbose = false) => {
|
|
391
|
+
try {
|
|
392
|
+
const parentDir = dirname(dest);
|
|
393
|
+
if (parentDir) {
|
|
394
|
+
fs3.mkdirSync(parentDir, { recursive: true });
|
|
395
|
+
}
|
|
396
|
+
fs3.cpSync(src, dest, { force: true, recursive: true });
|
|
397
|
+
if (verbose) {
|
|
398
|
+
console.log(chalk2.green(`Added "${dest}" from "${src}" successfully`));
|
|
399
|
+
}
|
|
400
|
+
} catch (err) {
|
|
401
|
+
console.log(chalk2.red(`Cannot copy file ${src} to ${dest}`));
|
|
402
|
+
if (verbose) {
|
|
403
|
+
console.log(chalk2.red(err));
|
|
404
|
+
}
|
|
405
|
+
throw err;
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
var writeFile = async (path4, content, flag = "w", verbose = false) => {
|
|
409
|
+
try {
|
|
410
|
+
const parentDir = dirname(path4);
|
|
411
|
+
if (parentDir) {
|
|
412
|
+
fs3.mkdirSync(parentDir, { recursive: true });
|
|
413
|
+
}
|
|
414
|
+
fs3.writeFileSync(path4, content, { flag });
|
|
415
|
+
if (verbose) {
|
|
416
|
+
console.log(chalk2.green(`Added "${path4}" successfully`));
|
|
417
|
+
}
|
|
418
|
+
} catch (err) {
|
|
419
|
+
console.log(chalk2.red(`Cannot write file ${path4}`));
|
|
420
|
+
if (verbose) {
|
|
421
|
+
console.log(chalk2.red(err));
|
|
422
|
+
}
|
|
423
|
+
throw err;
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
var appendFile = async (src, dest, verbose = false) => {
|
|
427
|
+
const content = fs3.readFileSync(src, "utf8");
|
|
428
|
+
return writeFile(dest, content, "a+", verbose);
|
|
429
|
+
};
|
|
430
|
+
var getModeFromPath = (path4 = "") => {
|
|
431
|
+
const matchExts = (...exts) => exts.find((ext) => path4.endsWith(ext));
|
|
432
|
+
if (matchExts(".append")) {
|
|
433
|
+
return "append";
|
|
434
|
+
}
|
|
435
|
+
if (matchExts(".append.template", ".template.append")) {
|
|
436
|
+
return "appendTemplate";
|
|
437
|
+
}
|
|
438
|
+
if (matchExts(".template")) {
|
|
439
|
+
return "copyTemplate";
|
|
440
|
+
}
|
|
441
|
+
return "copy";
|
|
442
|
+
};
|
|
443
|
+
var copyLoader = ({ root, templateDir, verbose, srcDir }) => ({ path: path4 }) => {
|
|
444
|
+
return copyFile(
|
|
445
|
+
`${templateDir}/${path4}`,
|
|
446
|
+
`${root}/${path4}`.replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir)),
|
|
447
|
+
verbose
|
|
448
|
+
);
|
|
449
|
+
};
|
|
450
|
+
var appendLoader = ({ root, templateDir, verbose, srcDir }) => ({ path: path4 }) => {
|
|
451
|
+
const newPath = path4.replace(/.append$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
|
|
452
|
+
return appendFile(`${templateDir}/${path4}`, `${root}/${newPath}`, verbose);
|
|
453
|
+
};
|
|
454
|
+
var templateLoader = ({
|
|
455
|
+
root,
|
|
456
|
+
templateDir,
|
|
457
|
+
appName,
|
|
458
|
+
alias,
|
|
459
|
+
verbose,
|
|
460
|
+
mode = "",
|
|
461
|
+
srcDir,
|
|
462
|
+
runCommand,
|
|
463
|
+
installCommand
|
|
464
|
+
}) => async ({ path: path4 }) => {
|
|
465
|
+
const flag = mode.includes("append") ? "a+" : "w";
|
|
466
|
+
const file = fs3.readFileSync(`${templateDir}/${path4}`, "utf8");
|
|
467
|
+
const newFile = _.template(file);
|
|
468
|
+
const newPath = path4.replace(/.template$/, "").replace(/.append$/, "").replace(SRC_PATH_PATTERN, getSrcDirPattern(srcDir));
|
|
469
|
+
return writeFile(
|
|
470
|
+
`${root}/${newPath}`,
|
|
471
|
+
newFile({
|
|
472
|
+
project: alias,
|
|
473
|
+
projectImport: alias,
|
|
474
|
+
projectImportPath: alias === "" ? "" : `${alias}/`,
|
|
475
|
+
projectName: appName,
|
|
476
|
+
srcDir: srcDir || ".",
|
|
477
|
+
runCommand,
|
|
478
|
+
installCommand
|
|
479
|
+
}),
|
|
480
|
+
flag,
|
|
481
|
+
verbose
|
|
482
|
+
);
|
|
483
|
+
};
|
|
484
|
+
var fileLoader = ({
|
|
485
|
+
root,
|
|
486
|
+
templateDir,
|
|
487
|
+
appName,
|
|
488
|
+
originalDirectory,
|
|
489
|
+
alias,
|
|
490
|
+
verbose,
|
|
491
|
+
srcDir = DEFAULT_SRC_PATH,
|
|
492
|
+
runCommand,
|
|
493
|
+
installCommand
|
|
494
|
+
}) => ({ path: path4 }) => {
|
|
495
|
+
const mode = getModeFromPath(path4);
|
|
496
|
+
const loaders = {
|
|
497
|
+
copy: copyLoader,
|
|
498
|
+
append: appendLoader,
|
|
499
|
+
copyTemplate: templateLoader,
|
|
500
|
+
appendTemplate: appendLoader
|
|
501
|
+
};
|
|
502
|
+
return loaders[mode]({
|
|
503
|
+
root,
|
|
504
|
+
templateDir,
|
|
505
|
+
appName,
|
|
506
|
+
originalDirectory,
|
|
507
|
+
alias,
|
|
508
|
+
verbose,
|
|
509
|
+
mode,
|
|
510
|
+
srcDir,
|
|
511
|
+
runCommand,
|
|
512
|
+
installCommand
|
|
513
|
+
})({
|
|
514
|
+
path: path4
|
|
515
|
+
});
|
|
516
|
+
};
|
|
517
|
+
var loadFiles = async ({
|
|
518
|
+
root,
|
|
519
|
+
addons = [],
|
|
520
|
+
appName,
|
|
521
|
+
originalDirectory,
|
|
522
|
+
alias,
|
|
523
|
+
verbose,
|
|
524
|
+
srcDir = DEFAULT_SRC_PATH,
|
|
525
|
+
runCommand,
|
|
526
|
+
installCommand
|
|
527
|
+
}) => {
|
|
528
|
+
for await (const { url: addonUrl } of addons) {
|
|
529
|
+
const templateDir = await getAddonTemplateDirPath(addonUrl);
|
|
530
|
+
if (!fs3.statSync(templateDir).isDirectory()) {
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
for await (const entry of readdirp(templateDir, {
|
|
534
|
+
fileFilter: [
|
|
535
|
+
"!package.js",
|
|
536
|
+
"!package.json",
|
|
537
|
+
"!package-lock.json",
|
|
538
|
+
"!template.json",
|
|
539
|
+
"!yarn.lock",
|
|
540
|
+
"!pnpm-lock.yaml"
|
|
541
|
+
],
|
|
542
|
+
directoryFilter: ["!package"]
|
|
543
|
+
})) {
|
|
544
|
+
try {
|
|
545
|
+
await fileLoader({
|
|
546
|
+
root,
|
|
547
|
+
templateDir,
|
|
548
|
+
appName,
|
|
549
|
+
originalDirectory,
|
|
550
|
+
alias,
|
|
551
|
+
verbose,
|
|
552
|
+
srcDir,
|
|
553
|
+
runCommand,
|
|
554
|
+
installCommand
|
|
555
|
+
})(entry);
|
|
556
|
+
} catch (err) {
|
|
557
|
+
if (verbose) {
|
|
558
|
+
console.log(err);
|
|
559
|
+
}
|
|
560
|
+
throw err;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
// installer.ts
|
|
567
|
+
var install = (root, useYarn = false, dependencies = [], verbose = false, isOnline = true, isDevDependencies = false) => {
|
|
568
|
+
return new Promise((resolve, reject) => {
|
|
569
|
+
let command;
|
|
570
|
+
let args;
|
|
571
|
+
if (useYarn) {
|
|
572
|
+
command = "yarnpkg";
|
|
573
|
+
args = ["add"];
|
|
574
|
+
if (!isOnline) {
|
|
575
|
+
args.push("--offline");
|
|
576
|
+
}
|
|
577
|
+
if (isDevDependencies) {
|
|
578
|
+
args.push("--dev");
|
|
579
|
+
}
|
|
580
|
+
args.push(...dependencies);
|
|
581
|
+
args.push("--cwd");
|
|
582
|
+
args.push(root);
|
|
583
|
+
if (!isOnline) {
|
|
584
|
+
console.log(chalk3.yellow("You appear to be offline."));
|
|
585
|
+
console.log(chalk3.yellow("Falling back to the local Yarn cache."));
|
|
586
|
+
console.log();
|
|
587
|
+
}
|
|
588
|
+
} else {
|
|
589
|
+
command = "npm";
|
|
590
|
+
args = ["install", "--loglevel", "error"];
|
|
591
|
+
if (isDevDependencies) {
|
|
592
|
+
args.push("--save-dev");
|
|
593
|
+
} else {
|
|
594
|
+
args.push("--save");
|
|
595
|
+
}
|
|
596
|
+
args.push(...dependencies);
|
|
597
|
+
}
|
|
598
|
+
if (verbose) {
|
|
599
|
+
args.push("--verbose");
|
|
600
|
+
}
|
|
601
|
+
const child = spawn2(command, args, { stdio: "inherit", cwd: root });
|
|
602
|
+
child.on("close", (code) => {
|
|
603
|
+
if (code !== 0) {
|
|
604
|
+
reject(new Error(`${command} ${args.join(" ")}`));
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
resolve();
|
|
608
|
+
});
|
|
609
|
+
});
|
|
610
|
+
};
|
|
611
|
+
var run = async ({
|
|
612
|
+
root,
|
|
613
|
+
appName,
|
|
614
|
+
originalDirectory,
|
|
615
|
+
verbose = false,
|
|
616
|
+
useYarn = false,
|
|
617
|
+
addons = [],
|
|
618
|
+
dependencies = [],
|
|
619
|
+
devDependencies = [],
|
|
620
|
+
alias = "",
|
|
621
|
+
installDependencies = true,
|
|
622
|
+
srcDir = "",
|
|
623
|
+
runCommand = "",
|
|
624
|
+
installCommand = ""
|
|
625
|
+
}) => {
|
|
626
|
+
let isOnline = true;
|
|
627
|
+
if (useYarn) {
|
|
628
|
+
isOnline = await checkIfOnline(useYarn);
|
|
629
|
+
}
|
|
630
|
+
if (_2.isEmpty(addons)) {
|
|
631
|
+
console.log();
|
|
632
|
+
console.log(chalk3.yellow("No addons specified to bootstrap application."));
|
|
633
|
+
console.log();
|
|
634
|
+
process.exit(0);
|
|
635
|
+
}
|
|
636
|
+
await loadFiles({
|
|
637
|
+
root,
|
|
638
|
+
addons,
|
|
639
|
+
appName,
|
|
640
|
+
originalDirectory,
|
|
641
|
+
alias,
|
|
642
|
+
verbose,
|
|
643
|
+
srcDir,
|
|
644
|
+
runCommand,
|
|
645
|
+
installCommand
|
|
646
|
+
});
|
|
647
|
+
if (installDependencies) {
|
|
648
|
+
console.log(
|
|
649
|
+
chalk3.green("Installing packages. This might take a couple of minutes.")
|
|
650
|
+
);
|
|
651
|
+
console.log(chalk3.green("Installing dependencies..."));
|
|
652
|
+
console.log();
|
|
653
|
+
await install(root, useYarn, dependencies, verbose, isOnline, false);
|
|
654
|
+
if (devDependencies.length > 0) {
|
|
655
|
+
console.log();
|
|
656
|
+
console.log(chalk3.green("Installing devDependencies..."));
|
|
657
|
+
console.log();
|
|
658
|
+
await install(root, useYarn, devDependencies, verbose, isOnline, true);
|
|
659
|
+
}
|
|
660
|
+
} else {
|
|
661
|
+
console.log(chalk3.yellow("Skip package installation."));
|
|
662
|
+
console.log(chalk3.yellow("Run npm install/yarn in your project."));
|
|
663
|
+
const packageJson = JSON.parse(
|
|
664
|
+
fs4.readFileSync(`${root}/package.json`, "utf8")
|
|
665
|
+
);
|
|
666
|
+
packageJson.dependencies = dependencies.reduce((dep, elem) => {
|
|
667
|
+
const nextDep = dep;
|
|
668
|
+
if (/.+@(\^|~)?[0-9a-zA-Z-.]+$/.test(elem)) {
|
|
669
|
+
const [name, version] = elem.split("@");
|
|
670
|
+
nextDep[name] = `${version}`;
|
|
671
|
+
} else {
|
|
672
|
+
nextDep[elem] = "*";
|
|
673
|
+
}
|
|
674
|
+
return nextDep;
|
|
675
|
+
}, {});
|
|
676
|
+
packageJson.devDependencies = devDependencies.reduce((dep, elem) => {
|
|
677
|
+
const nextDep = dep;
|
|
678
|
+
if (/.+@(\^|~)?[0-9a-zA-Z-.]+$/.test(elem)) {
|
|
679
|
+
const [name, version] = elem.split("@");
|
|
680
|
+
nextDep[name] = `${version}`;
|
|
681
|
+
} else {
|
|
682
|
+
nextDep[elem] = "*";
|
|
683
|
+
}
|
|
684
|
+
return nextDep;
|
|
685
|
+
}, {});
|
|
686
|
+
fs4.writeFileSync(
|
|
687
|
+
path3.join(root, "package.json"),
|
|
688
|
+
JSON.stringify(packageJson, null, 2) + os3.EOL
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
spawn2("git", ["init"], {
|
|
692
|
+
cwd: root
|
|
693
|
+
});
|
|
694
|
+
if (installDependencies && isOnline) {
|
|
695
|
+
const packageJson = JSON.parse(
|
|
696
|
+
fs4.readFileSync(`${root}/package.json`, "utf8")
|
|
697
|
+
);
|
|
698
|
+
if (packageJson.scripts && packageJson.scripts["lint:fix"]) {
|
|
699
|
+
spawn2(runCommand, ["lint:fix"], { stdio: "inherit", cwd: root });
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
};
|
|
703
|
+
var createApp = async ({
|
|
704
|
+
name,
|
|
705
|
+
verbose = false,
|
|
706
|
+
useNpm = false,
|
|
707
|
+
addons = [],
|
|
708
|
+
alias = "",
|
|
709
|
+
installDependencies = true,
|
|
710
|
+
ignorePackage = false,
|
|
711
|
+
srcDir = ""
|
|
712
|
+
}) => {
|
|
713
|
+
const root = path3.resolve(name);
|
|
714
|
+
const appName = path3.basename(root);
|
|
715
|
+
fs4.mkdirSync(name, {
|
|
716
|
+
recursive: true
|
|
717
|
+
});
|
|
718
|
+
console.log(`Creating a new Node app in ${chalk3.green(root)}.`);
|
|
719
|
+
console.log();
|
|
720
|
+
const useYarn = useNpm ? false : shouldUseYarn();
|
|
721
|
+
const command = useYarn ? "yarn" : "npm run";
|
|
722
|
+
const { packageJson, dependencies, devDependencies } = await loadAddonsPackages({
|
|
723
|
+
addons,
|
|
724
|
+
appName,
|
|
725
|
+
command,
|
|
726
|
+
ignorePackage,
|
|
727
|
+
srcDir
|
|
728
|
+
});
|
|
729
|
+
fs4.writeFileSync(
|
|
730
|
+
path3.join(root, "package.json"),
|
|
731
|
+
JSON.stringify(packageJson, null, 2) + os3.EOL
|
|
732
|
+
);
|
|
733
|
+
const originalDirectory = process.cwd();
|
|
734
|
+
process.chdir(root);
|
|
735
|
+
if (!useYarn && !checkThatNpmCanReadCwd()) {
|
|
736
|
+
process.exit(1);
|
|
737
|
+
}
|
|
738
|
+
if (!semver2.satisfies(process.version, ">=16.0.0")) {
|
|
739
|
+
console.log(
|
|
740
|
+
chalk3.yellow(
|
|
741
|
+
`You are using Node ${process.version} so the project will be bootstrapped with an old unsupported version of tools.
|
|
742
|
+
|
|
743
|
+
Please update to Node 16 or higher for a better, fully supported experience.
|
|
744
|
+
`
|
|
745
|
+
)
|
|
746
|
+
);
|
|
747
|
+
}
|
|
748
|
+
if (!useYarn) {
|
|
749
|
+
const npmInfo = checkNpmVersion();
|
|
750
|
+
if (!npmInfo.hasMinNpm) {
|
|
751
|
+
if (npmInfo.npmVersion) {
|
|
752
|
+
console.log(
|
|
753
|
+
chalk3.yellow(
|
|
754
|
+
`You are using npm ${npmInfo.npmVersion} so the project will be bootstrapped with an old unsupported version of tools.
|
|
755
|
+
|
|
756
|
+
Please update to npm 3 or higher for a better, fully supported experience.
|
|
757
|
+
`
|
|
758
|
+
)
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
if (useYarn) {
|
|
764
|
+
let yarnUsesDefaultRegistry = true;
|
|
765
|
+
try {
|
|
766
|
+
yarnUsesDefaultRegistry = execSync2("yarnpkg config get registry").toString().trim() === "https://registry.yarnpkg.com";
|
|
767
|
+
} catch (e) {
|
|
768
|
+
}
|
|
769
|
+
if (false) {
|
|
770
|
+
fs4.cpSync(
|
|
771
|
+
__require.resolve("./yarn.lock.cached"),
|
|
772
|
+
path3.join(root, "yarn.lock"),
|
|
773
|
+
{ force: true }
|
|
774
|
+
);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
return run({
|
|
778
|
+
root,
|
|
779
|
+
appName,
|
|
780
|
+
originalDirectory,
|
|
781
|
+
verbose,
|
|
782
|
+
useYarn,
|
|
783
|
+
addons,
|
|
784
|
+
dependencies,
|
|
785
|
+
devDependencies,
|
|
786
|
+
alias,
|
|
787
|
+
installDependencies,
|
|
788
|
+
srcDir,
|
|
789
|
+
runCommand: command,
|
|
790
|
+
installCommand: useYarn ? "yarn" : "npm install"
|
|
791
|
+
});
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
// index.ts
|
|
795
|
+
var printEnvInfo = async () => {
|
|
796
|
+
console.log(chalk4.bold("\nEnvironment Info:"));
|
|
797
|
+
const info = await envinfo.run(
|
|
798
|
+
{
|
|
799
|
+
System: ["OS", "CPU"],
|
|
800
|
+
Binaries: ["Node", "npm", "Yarn"],
|
|
801
|
+
Browsers: ["Chrome", "Edge", "Internet Explorer", "Firefox", "Safari"]
|
|
802
|
+
},
|
|
803
|
+
{
|
|
804
|
+
duplicates: true,
|
|
805
|
+
showNotFound: true
|
|
806
|
+
}
|
|
807
|
+
);
|
|
808
|
+
console.log(info);
|
|
809
|
+
process.exit(0);
|
|
810
|
+
};
|
|
811
|
+
var createNodeApp = async (programName, options, transformOptions) => {
|
|
812
|
+
if (options.info) {
|
|
813
|
+
await printEnvInfo();
|
|
814
|
+
}
|
|
815
|
+
if (typeof options.projectName === "undefined") {
|
|
816
|
+
console.error("Please specify the project directory:");
|
|
817
|
+
console.log(
|
|
818
|
+
` ${chalk4.cyan(programName)} ${chalk4.green("[project-directory]")}`
|
|
819
|
+
);
|
|
820
|
+
console.log();
|
|
821
|
+
console.log("For example:");
|
|
822
|
+
console.log(` ${chalk4.cyan(programName)} ${chalk4.green("my-app")}`);
|
|
823
|
+
console.log();
|
|
824
|
+
console.log(
|
|
825
|
+
`Run ${chalk4.cyan(`${programName} --help`)} to see all options.`
|
|
826
|
+
);
|
|
827
|
+
process.exit(1);
|
|
828
|
+
}
|
|
829
|
+
const appOptions = await transformOptions(options);
|
|
830
|
+
await createApp({
|
|
831
|
+
...appOptions,
|
|
832
|
+
name: appOptions.projectName,
|
|
833
|
+
installDependencies: !options.nodeps
|
|
834
|
+
});
|
|
835
|
+
};
|
|
836
|
+
export {
|
|
837
|
+
createNodeApp,
|
|
838
|
+
printEnvInfo
|
|
839
|
+
};
|