@mnci/cli 1.9.1 → 1.11.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/README.md +97 -16
- package/dist/cli.js +343 -203
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -38,11 +38,32 @@ module.exports = __toCommonJS(cli_exports);
|
|
|
38
38
|
var import_commander = require("commander");
|
|
39
39
|
|
|
40
40
|
// src/commands/add.ts
|
|
41
|
-
var
|
|
41
|
+
var import_node_path9 = require("path");
|
|
42
42
|
var import_prompts4 = require("@inquirer/prompts");
|
|
43
43
|
|
|
44
44
|
// src/nx.ts
|
|
45
45
|
var import_cross_spawn = __toESM(require("cross-spawn"));
|
|
46
|
+
|
|
47
|
+
// src/util/logger.ts
|
|
48
|
+
var logger = {
|
|
49
|
+
info(message) {
|
|
50
|
+
console.log(message);
|
|
51
|
+
},
|
|
52
|
+
step(message) {
|
|
53
|
+
console.log(`\u2192 ${message}`);
|
|
54
|
+
},
|
|
55
|
+
success(message) {
|
|
56
|
+
console.log(`\u2713 ${message}`);
|
|
57
|
+
},
|
|
58
|
+
warn(message) {
|
|
59
|
+
console.warn(`! ${message}`);
|
|
60
|
+
},
|
|
61
|
+
error(message) {
|
|
62
|
+
console.error(`\u2717 ${message}`);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// src/nx.ts
|
|
46
67
|
function runShell(command, arguments_, cwd) {
|
|
47
68
|
const result = import_cross_spawn.default.sync(command, arguments_, { stdio: "inherit", cwd });
|
|
48
69
|
return result.status ?? 1;
|
|
@@ -59,6 +80,14 @@ function runNpx(arguments_, cwd) {
|
|
|
59
80
|
throw new Error(`npx ${arguments_.join(" ")} failed with exit code ${status}`);
|
|
60
81
|
}
|
|
61
82
|
}
|
|
83
|
+
function runPrettier(cwd, target = ".") {
|
|
84
|
+
const status = runShell("npx", ["prettier", "--write", "--log-level", "warn", target], cwd);
|
|
85
|
+
if (status !== 0) {
|
|
86
|
+
logger.warn(
|
|
87
|
+
`Prettier could not format '${target}' (exit code ${status}). The project was generated; run 'npm run format' to normalise it.`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
62
91
|
|
|
63
92
|
// src/prompts.ts
|
|
64
93
|
var import_prompts = require("@inquirer/prompts");
|
|
@@ -136,25 +165,6 @@ function fileExists(path) {
|
|
|
136
165
|
return (0, import_node_fs.existsSync)(path);
|
|
137
166
|
}
|
|
138
167
|
|
|
139
|
-
// src/util/logger.ts
|
|
140
|
-
var logger = {
|
|
141
|
-
info(message) {
|
|
142
|
-
console.log(message);
|
|
143
|
-
},
|
|
144
|
-
step(message) {
|
|
145
|
-
console.log(`\u2192 ${message}`);
|
|
146
|
-
},
|
|
147
|
-
success(message) {
|
|
148
|
-
console.log(`\u2713 ${message}`);
|
|
149
|
-
},
|
|
150
|
-
warn(message) {
|
|
151
|
-
console.warn(`! ${message}`);
|
|
152
|
-
},
|
|
153
|
-
error(message) {
|
|
154
|
-
console.error(`\u2717 ${message}`);
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
|
|
158
168
|
// src/util/names.ts
|
|
159
169
|
function assertValidProjectName(name, label) {
|
|
160
170
|
if (!/^[a-z][a-z0-9-]*$/.test(name)) {
|
|
@@ -164,7 +174,11 @@ function assertValidProjectName(name, label) {
|
|
|
164
174
|
}
|
|
165
175
|
}
|
|
166
176
|
|
|
177
|
+
// src/commands/add/flutter.ts
|
|
178
|
+
var import_node_path3 = require("path");
|
|
179
|
+
|
|
167
180
|
// src/commands/add/shared.ts
|
|
181
|
+
var import_node_fs2 = require("fs");
|
|
168
182
|
var import_node_path2 = require("path");
|
|
169
183
|
function hasPlugin(workspaceRoot, packageName) {
|
|
170
184
|
const manifest = readJson((0, import_node_path2.join)(workspaceRoot, "package.json"));
|
|
@@ -198,8 +212,93 @@ function addNxTargets(manifestPath, newTargets) {
|
|
|
198
212
|
toJson({ ...manifest, nx: { ...nx, targets: { ...targets, ...newTargets } } })
|
|
199
213
|
);
|
|
200
214
|
}
|
|
215
|
+
var ESLINT_CONFIG_FILENAMES = [
|
|
216
|
+
"eslint.config.js",
|
|
217
|
+
"eslint.config.mjs",
|
|
218
|
+
"eslint.config.cjs",
|
|
219
|
+
"eslint.config.ts",
|
|
220
|
+
"eslint.config.mts",
|
|
221
|
+
"eslint.config.cts"
|
|
222
|
+
];
|
|
223
|
+
function removeGeneratedEslintConfig(workspaceRoot, projectRoot) {
|
|
224
|
+
for (const filename of ESLINT_CONFIG_FILENAMES) {
|
|
225
|
+
(0, import_node_fs2.rmSync)((0, import_node_path2.join)(workspaceRoot, projectRoot, filename), { force: true });
|
|
226
|
+
}
|
|
227
|
+
(0, import_node_fs2.rmSync)((0, import_node_path2.join)(workspaceRoot, ".vscode"), { recursive: true, force: true });
|
|
228
|
+
}
|
|
229
|
+
function findCodeWorkspaceFile(workspaceRoot) {
|
|
230
|
+
try {
|
|
231
|
+
const entry = (0, import_node_fs2.readdirSync)(workspaceRoot).find((file) => file.endsWith(".code-workspace"));
|
|
232
|
+
return entry ? (0, import_node_path2.join)(workspaceRoot, entry) : void 0;
|
|
233
|
+
} catch {
|
|
234
|
+
return void 0;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function readCodeWorkspaceFile(path) {
|
|
238
|
+
const contents = (0, import_node_fs2.readFileSync)(path, "utf8").replaceAll(/,(\s*[}\]])/g, "$1");
|
|
239
|
+
return JSON.parse(contents);
|
|
240
|
+
}
|
|
241
|
+
function projectTask(name, kind) {
|
|
242
|
+
const script = `${name}:${kind}`;
|
|
243
|
+
const base = { label: `${name}: ${kind}`, type: "npm", script, problemMatcher: [] };
|
|
244
|
+
return kind === "start" ? { ...base, isBackground: true } : { ...base, group: kind };
|
|
245
|
+
}
|
|
246
|
+
function registerProjectCommands(workspaceRoot, name, commands) {
|
|
247
|
+
const scripts = {
|
|
248
|
+
[`${name}:qa`]: `nx run ${name}:lint && nx run ${name}:test`
|
|
249
|
+
};
|
|
250
|
+
if (commands.build) {
|
|
251
|
+
scripts[`${name}:build`] = `nx run ${name}:build`;
|
|
252
|
+
}
|
|
253
|
+
if (commands.start) {
|
|
254
|
+
scripts[`${name}:start`] = commands.start;
|
|
255
|
+
}
|
|
256
|
+
const manifestPath = (0, import_node_path2.join)(workspaceRoot, "package.json");
|
|
257
|
+
const manifest = readJson(manifestPath);
|
|
258
|
+
const existingScripts = manifest.scripts ?? {};
|
|
259
|
+
writeFileEnsured(
|
|
260
|
+
manifestPath,
|
|
261
|
+
toJson({ ...manifest, scripts: { ...existingScripts, ...scripts } })
|
|
262
|
+
);
|
|
263
|
+
const codeWorkspacePath = findCodeWorkspaceFile(workspaceRoot);
|
|
264
|
+
if (!codeWorkspacePath) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const workspaceFile = readCodeWorkspaceFile(codeWorkspacePath);
|
|
268
|
+
const label = (task) => task.label ?? "";
|
|
269
|
+
const existingTasks = (workspaceFile.tasks?.tasks ?? []).filter(
|
|
270
|
+
(task) => !label(task).startsWith(`${name}: `)
|
|
271
|
+
);
|
|
272
|
+
const newTasks = [
|
|
273
|
+
projectTask(name, "qa"),
|
|
274
|
+
...commands.build ? [projectTask(name, "build")] : [],
|
|
275
|
+
...commands.start ? [projectTask(name, "start")] : []
|
|
276
|
+
];
|
|
277
|
+
writeFileEnsured(
|
|
278
|
+
codeWorkspacePath,
|
|
279
|
+
toJson({
|
|
280
|
+
...workspaceFile,
|
|
281
|
+
tasks: {
|
|
282
|
+
version: workspaceFile.tasks?.version ?? "2.0.0",
|
|
283
|
+
tasks: [...existingTasks, ...newTasks]
|
|
284
|
+
}
|
|
285
|
+
})
|
|
286
|
+
);
|
|
287
|
+
}
|
|
201
288
|
|
|
202
289
|
// src/commands/add/flutter.ts
|
|
290
|
+
function addProjectJsonTargets(projectJsonPath, newTargets) {
|
|
291
|
+
const project = readJson(projectJsonPath);
|
|
292
|
+
const targets = project.targets ?? {};
|
|
293
|
+
writeFileEnsured(projectJsonPath, toJson({ ...project, targets: { ...targets, ...newTargets } }));
|
|
294
|
+
}
|
|
295
|
+
function flutterAppStartTarget(name) {
|
|
296
|
+
return {
|
|
297
|
+
executor: "nx:run-commands",
|
|
298
|
+
continuous: true,
|
|
299
|
+
options: { command: "flutter run -d chrome", cwd: `apps/${name}` }
|
|
300
|
+
};
|
|
301
|
+
}
|
|
203
302
|
function ensureFlutter(workspaceRoot) {
|
|
204
303
|
if (runShell("flutter", ["--version"], workspaceRoot) !== 0) {
|
|
205
304
|
throw new Error(
|
|
@@ -228,19 +327,25 @@ function addFlutterApp(workspaceRoot, name) {
|
|
|
228
327
|
prepareFlutter(workspaceRoot);
|
|
229
328
|
ensureAdmZip(workspaceRoot);
|
|
230
329
|
runNx(["g", "@mnci/nx-flutter:application", name, "--no-interactive"], workspaceRoot);
|
|
330
|
+
addProjectJsonTargets((0, import_node_path3.join)(workspaceRoot, "apps", name, "project.json"), {
|
|
331
|
+
start: flutterAppStartTarget(name)
|
|
332
|
+
});
|
|
333
|
+
registerProjectCommands(workspaceRoot, name, { build: true, start: `nx run ${name}:start` });
|
|
231
334
|
}
|
|
232
335
|
function addFlutterLib(workspaceRoot, name) {
|
|
233
336
|
prepareFlutter(workspaceRoot);
|
|
234
337
|
runNx(["g", "@mnci/nx-flutter:library", name, "--no-interactive"], workspaceRoot);
|
|
338
|
+
registerProjectCommands(workspaceRoot, name, { build: false });
|
|
235
339
|
}
|
|
236
340
|
function addFlutterInternalLib(workspaceRoot, name) {
|
|
237
341
|
prepareFlutter(workspaceRoot);
|
|
238
342
|
runNx(["g", "@mnci/nx-flutter:internal-library", name, "--no-interactive"], workspaceRoot);
|
|
343
|
+
registerProjectCommands(workspaceRoot, name, { build: false });
|
|
239
344
|
}
|
|
240
345
|
|
|
241
346
|
// src/commands/add/go.ts
|
|
242
|
-
var
|
|
243
|
-
var
|
|
347
|
+
var import_node_fs3 = require("fs");
|
|
348
|
+
var import_node_path4 = require("path");
|
|
244
349
|
function ensureGo(workspaceRoot) {
|
|
245
350
|
if (runShell("go", ["version"], workspaceRoot) !== 0) {
|
|
246
351
|
throw new Error("Go not found. Install Go 1.21+ first: https://go.dev/dl/");
|
|
@@ -267,7 +372,7 @@ function ensureNxGoPlugin(workspaceRoot) {
|
|
|
267
372
|
}
|
|
268
373
|
}
|
|
269
374
|
function ensureGoModule(workspaceRoot) {
|
|
270
|
-
if (fileExists((0,
|
|
375
|
+
if (fileExists((0, import_node_path4.join)(workspaceRoot, "go.mod"))) {
|
|
271
376
|
return;
|
|
272
377
|
}
|
|
273
378
|
logger.step("Bootstrapping the workspace Go module (single root go.mod)");
|
|
@@ -276,13 +381,13 @@ function ensureGoModule(workspaceRoot) {
|
|
|
276
381
|
}
|
|
277
382
|
function goModulePath(workspaceRoot) {
|
|
278
383
|
try {
|
|
279
|
-
const contents = (0,
|
|
384
|
+
const contents = (0, import_node_fs3.readFileSync)((0, import_node_path4.join)(workspaceRoot, "go.mod"), "utf8");
|
|
280
385
|
return /^module\s+(\S+)/m.exec(contents)?.[1];
|
|
281
386
|
} catch {
|
|
282
387
|
return void 0;
|
|
283
388
|
}
|
|
284
389
|
}
|
|
285
|
-
function
|
|
390
|
+
function addProjectJsonTargets2(projectJsonPath, newTargets) {
|
|
286
391
|
const project = readJson(projectJsonPath);
|
|
287
392
|
const targets = project.targets ?? {};
|
|
288
393
|
writeFileEnsured(projectJsonPath, toJson({ ...project, targets: { ...targets, ...newTargets } }));
|
|
@@ -296,7 +401,6 @@ function goLintTarget() {
|
|
|
296
401
|
function goBuildTarget(name) {
|
|
297
402
|
return {
|
|
298
403
|
executor: "@nx-go/nx-go:build",
|
|
299
|
-
// eslint-disable-next-line unicorn/no-incorrect-template-string-interpolation -- {workspaceRoot} is an Nx output token
|
|
300
404
|
outputs: [`{workspaceRoot}/dist/apps/${name}`],
|
|
301
405
|
options: { outputPath: `../../dist/apps/${name}/${name}` }
|
|
302
406
|
};
|
|
@@ -307,11 +411,17 @@ function goPackageTarget(tag, name) {
|
|
|
307
411
|
return {
|
|
308
412
|
executor: "nx:run-commands",
|
|
309
413
|
dependsOn: ["build"],
|
|
310
|
-
// eslint-disable-next-line unicorn/no-incorrect-template-string-interpolation -- {workspaceRoot} is an Nx output token
|
|
311
414
|
outputs: [`{workspaceRoot}/${zip}`],
|
|
312
415
|
options: { command }
|
|
313
416
|
};
|
|
314
417
|
}
|
|
418
|
+
function goStartTarget(name) {
|
|
419
|
+
return {
|
|
420
|
+
executor: "nx:run-commands",
|
|
421
|
+
continuous: true,
|
|
422
|
+
options: { command: "go run .", cwd: `apps/${name}` }
|
|
423
|
+
};
|
|
424
|
+
}
|
|
315
425
|
function prepareGo(workspaceRoot) {
|
|
316
426
|
ensureGo(workspaceRoot);
|
|
317
427
|
warnIfNoGolangciLint(workspaceRoot);
|
|
@@ -332,12 +442,14 @@ function addGoApp(workspaceRoot, name) {
|
|
|
332
442
|
],
|
|
333
443
|
workspaceRoot
|
|
334
444
|
);
|
|
335
|
-
|
|
445
|
+
addProjectJsonTargets2((0, import_node_path4.join)(workspaceRoot, "apps", name, "project.json"), {
|
|
336
446
|
build: goBuildTarget(name),
|
|
337
447
|
test: goTestTarget(),
|
|
338
448
|
lint: goLintTarget(),
|
|
339
|
-
package: goPackageTarget("go-app", name)
|
|
449
|
+
package: goPackageTarget("go-app", name),
|
|
450
|
+
start: goStartTarget(name)
|
|
340
451
|
});
|
|
452
|
+
registerProjectCommands(workspaceRoot, name, { build: true, start: `nx run ${name}:start` });
|
|
341
453
|
}
|
|
342
454
|
function addGoFunctionApp(workspaceRoot, name) {
|
|
343
455
|
prepareGo(workspaceRoot);
|
|
@@ -353,12 +465,13 @@ function addGoFunctionApp(workspaceRoot, name) {
|
|
|
353
465
|
],
|
|
354
466
|
workspaceRoot
|
|
355
467
|
);
|
|
356
|
-
|
|
468
|
+
addProjectJsonTargets2((0, import_node_path4.join)(workspaceRoot, "apps", name, "project.json"), {
|
|
357
469
|
build: goBuildTarget(name),
|
|
358
470
|
test: goTestTarget(),
|
|
359
471
|
lint: goLintTarget(),
|
|
360
472
|
package: goPackageTarget("go-function-app", name)
|
|
361
473
|
});
|
|
474
|
+
registerProjectCommands(workspaceRoot, name, { build: true });
|
|
362
475
|
}
|
|
363
476
|
function addGoLib(workspaceRoot, name) {
|
|
364
477
|
prepareGo(workspaceRoot);
|
|
@@ -373,10 +486,11 @@ function addGoLib(workspaceRoot, name) {
|
|
|
373
486
|
],
|
|
374
487
|
workspaceRoot
|
|
375
488
|
);
|
|
376
|
-
|
|
489
|
+
addProjectJsonTargets2((0, import_node_path4.join)(workspaceRoot, "packages", name, "project.json"), {
|
|
377
490
|
test: goTestTarget(),
|
|
378
491
|
lint: goLintTarget()
|
|
379
492
|
});
|
|
493
|
+
registerProjectCommands(workspaceRoot, name, { build: false });
|
|
380
494
|
const module2 = goModulePath(workspaceRoot);
|
|
381
495
|
if (module2) {
|
|
382
496
|
logger.step(`Import it as ${module2}/packages/${name}`);
|
|
@@ -395,10 +509,11 @@ function addGoInternalLib(workspaceRoot, name) {
|
|
|
395
509
|
],
|
|
396
510
|
workspaceRoot
|
|
397
511
|
);
|
|
398
|
-
|
|
512
|
+
addProjectJsonTargets2((0, import_node_path4.join)(workspaceRoot, "libs", name, "project.json"), {
|
|
399
513
|
test: goTestTarget(),
|
|
400
514
|
lint: goLintTarget()
|
|
401
515
|
});
|
|
516
|
+
registerProjectCommands(workspaceRoot, name, { build: false });
|
|
402
517
|
const module2 = goModulePath(workspaceRoot);
|
|
403
518
|
if (module2) {
|
|
404
519
|
logger.step(`Import it as ${module2}/libs/${name}`);
|
|
@@ -406,7 +521,7 @@ function addGoInternalLib(workspaceRoot, name) {
|
|
|
406
521
|
}
|
|
407
522
|
|
|
408
523
|
// src/commands/add/node.ts
|
|
409
|
-
var
|
|
524
|
+
var import_node_path5 = require("path");
|
|
410
525
|
function ensurePlugin(workspaceRoot, packageName) {
|
|
411
526
|
if (hasPlugin(workspaceRoot, packageName)) {
|
|
412
527
|
return;
|
|
@@ -423,7 +538,7 @@ function runNodeApp(workspaceRoot, name, stack, framework) {
|
|
|
423
538
|
`apps/${name}`,
|
|
424
539
|
"--bundler=esbuild",
|
|
425
540
|
`--unitTestRunner=${stack.testRunner}`,
|
|
426
|
-
"--linter=
|
|
541
|
+
"--linter=none",
|
|
427
542
|
"--e2eTestRunner=none",
|
|
428
543
|
`--framework=${framework}`,
|
|
429
544
|
"--no-interactive"
|
|
@@ -437,7 +552,6 @@ function nodeAppPackageTarget(name) {
|
|
|
437
552
|
return {
|
|
438
553
|
executor: "nx:run-commands",
|
|
439
554
|
dependsOn: ["build"],
|
|
440
|
-
// eslint-disable-next-line unicorn/no-incorrect-template-string-interpolation -- {workspaceRoot} is an Nx output token
|
|
441
555
|
outputs: [`{workspaceRoot}/${zip}`],
|
|
442
556
|
options: { command }
|
|
443
557
|
};
|
|
@@ -445,9 +559,11 @@ function nodeAppPackageTarget(name) {
|
|
|
445
559
|
function addNodeApp(workspaceRoot, name, stack, framework = "none") {
|
|
446
560
|
runNodeApp(workspaceRoot, name, stack, framework);
|
|
447
561
|
ensureAdmZip(workspaceRoot);
|
|
448
|
-
addNxTargets((0,
|
|
562
|
+
addNxTargets((0, import_node_path5.join)(workspaceRoot, "apps", name, "package.json"), {
|
|
449
563
|
package: nodeAppPackageTarget(name)
|
|
450
564
|
});
|
|
565
|
+
removeGeneratedEslintConfig(workspaceRoot, `apps/${name}`);
|
|
566
|
+
registerProjectCommands(workspaceRoot, name, { build: true, start: `nx run ${name}:serve` });
|
|
451
567
|
}
|
|
452
568
|
function ensureAzureFunctionsPackage(workspaceRoot) {
|
|
453
569
|
if (hasPlugin(workspaceRoot, "@azure/functions")) {
|
|
@@ -470,10 +586,11 @@ var NODE_FUNCTION_APP_HOST_JSON = `{
|
|
|
470
586
|
}
|
|
471
587
|
}
|
|
472
588
|
`;
|
|
473
|
-
var NODE_FUNCTION_APP_HELLO = `import { app
|
|
589
|
+
var NODE_FUNCTION_APP_HELLO = `import { app } from '@azure/functions'
|
|
590
|
+
import type { HttpRequest, HttpResponseInit } from '@azure/functions'
|
|
474
591
|
import { buildGreeting } from './greeting'
|
|
475
592
|
|
|
476
|
-
async function hello
|
|
593
|
+
async function hello(request: HttpRequest): Promise<HttpResponseInit> {
|
|
477
594
|
const name = request.query.get('name') ?? 'world'
|
|
478
595
|
return { body: buildGreeting(name) }
|
|
479
596
|
}
|
|
@@ -498,17 +615,17 @@ describe('buildGreeting', () => {
|
|
|
498
615
|
})
|
|
499
616
|
`;
|
|
500
617
|
function repairNodeFunctionAppManifest(nodeFunctionAppRoot, workspaceRoot) {
|
|
501
|
-
const manifestPath = (0,
|
|
618
|
+
const manifestPath = (0, import_node_path5.join)(nodeFunctionAppRoot, "package.json");
|
|
502
619
|
const manifest = readJson(manifestPath);
|
|
503
620
|
const azureFunctionsVersion = readJson(
|
|
504
|
-
(0,
|
|
621
|
+
(0, import_node_path5.join)(workspaceRoot, "node_modules/@azure/functions/package.json")
|
|
505
622
|
).version;
|
|
506
623
|
const dependencies = manifest.dependencies ?? {};
|
|
507
624
|
writeFileEnsured(
|
|
508
625
|
manifestPath,
|
|
509
626
|
toJson({
|
|
510
627
|
...manifest,
|
|
511
|
-
main: "main.js",
|
|
628
|
+
main: "dist/main.js",
|
|
512
629
|
dependencies: { ...dependencies, "@azure/functions": `^${azureFunctionsVersion}` }
|
|
513
630
|
})
|
|
514
631
|
);
|
|
@@ -516,90 +633,49 @@ function repairNodeFunctionAppManifest(nodeFunctionAppRoot, workspaceRoot) {
|
|
|
516
633
|
function nodeFunctionAppPackageTarget(name) {
|
|
517
634
|
const zip = `dist/drop/node-function-app-${name}.zip`;
|
|
518
635
|
const root = `apps/${name}`;
|
|
519
|
-
const command = `node -e "const fs=require('node:fs');fs.mkdirSync('dist/drop',{recursive:true});const A=require('adm-zip');const z=new A();z.addLocalFolder('${root}/dist');z.addLocalFile('${root}/host.json');z.addLocalFile('${root}/package.json');z.writeZip('${zip}')"`;
|
|
636
|
+
const command = `node -e "const fs=require('node:fs');fs.mkdirSync('dist/drop',{recursive:true});const A=require('adm-zip');const z=new A();z.addLocalFolder('${root}/dist','dist');z.addLocalFile('${root}/host.json');z.addLocalFile('${root}/package.json');z.writeZip('${zip}')"`;
|
|
520
637
|
return {
|
|
521
638
|
executor: "nx:run-commands",
|
|
522
639
|
dependsOn: ["build"],
|
|
523
|
-
// eslint-disable-next-line unicorn/no-incorrect-template-string-interpolation -- {workspaceRoot} is an Nx output token
|
|
524
640
|
outputs: [`{workspaceRoot}/${zip}`],
|
|
525
641
|
options: { command }
|
|
526
642
|
};
|
|
527
643
|
}
|
|
644
|
+
function nodeFunctionAppStartTarget(name) {
|
|
645
|
+
return {
|
|
646
|
+
executor: "nx:run-commands",
|
|
647
|
+
dependsOn: ["build"],
|
|
648
|
+
continuous: true,
|
|
649
|
+
options: { command: "func start", cwd: `apps/${name}` }
|
|
650
|
+
};
|
|
651
|
+
}
|
|
528
652
|
function addNodeFunctionApp(workspaceRoot, name, stack) {
|
|
529
653
|
runNodeApp(workspaceRoot, name, stack, "none");
|
|
530
654
|
ensureAzureFunctionsPackage(workspaceRoot);
|
|
531
|
-
const nodeFunctionAppRoot = (0,
|
|
532
|
-
writeFileEnsured((0,
|
|
533
|
-
writeFileEnsured((0,
|
|
655
|
+
const nodeFunctionAppRoot = (0, import_node_path5.join)(workspaceRoot, "apps", name);
|
|
656
|
+
writeFileEnsured((0, import_node_path5.join)(nodeFunctionAppRoot, "src/main.ts"), NODE_FUNCTION_APP_MAIN);
|
|
657
|
+
writeFileEnsured((0, import_node_path5.join)(nodeFunctionAppRoot, "src/functions/hello.ts"), NODE_FUNCTION_APP_HELLO);
|
|
534
658
|
writeFileEnsured(
|
|
535
|
-
(0,
|
|
659
|
+
(0, import_node_path5.join)(nodeFunctionAppRoot, "src/functions/greeting.ts"),
|
|
536
660
|
NODE_FUNCTION_APP_GREETING
|
|
537
661
|
);
|
|
538
662
|
writeFileEnsured(
|
|
539
|
-
(0,
|
|
663
|
+
(0, import_node_path5.join)(nodeFunctionAppRoot, "src/functions/greeting.spec.ts"),
|
|
540
664
|
NODE_FUNCTION_APP_GREETING_SPEC
|
|
541
665
|
);
|
|
542
|
-
writeFileEnsured((0,
|
|
666
|
+
writeFileEnsured((0, import_node_path5.join)(nodeFunctionAppRoot, "host.json"), NODE_FUNCTION_APP_HOST_JSON);
|
|
543
667
|
repairNodeFunctionAppManifest(nodeFunctionAppRoot, workspaceRoot);
|
|
544
668
|
ensureAdmZip(workspaceRoot);
|
|
545
|
-
addNxTargets((0,
|
|
546
|
-
package: nodeFunctionAppPackageTarget(name)
|
|
669
|
+
addNxTargets((0, import_node_path5.join)(nodeFunctionAppRoot, "package.json"), {
|
|
670
|
+
package: nodeFunctionAppPackageTarget(name),
|
|
671
|
+
start: nodeFunctionAppStartTarget(name)
|
|
547
672
|
});
|
|
673
|
+
removeGeneratedEslintConfig(workspaceRoot, `apps/${name}`);
|
|
674
|
+
registerProjectCommands(workspaceRoot, name, { build: true, start: `nx run ${name}:start` });
|
|
548
675
|
}
|
|
549
676
|
|
|
550
677
|
// src/commands/add/npmLib.ts
|
|
551
|
-
var
|
|
552
|
-
var NPM_LIB_ESLINT_CONFIG = `import { globSync, readFileSync } from 'node:fs';
|
|
553
|
-
import { dirname, join } from 'node:path';
|
|
554
|
-
import { fileURLToPath } from 'node:url';
|
|
555
|
-
import baseConfig from '../../eslint.config.mjs';
|
|
556
|
-
|
|
557
|
-
// Private workspace libs are compiled INTO this package's rollup bundle and
|
|
558
|
-
// never declared in the manifest (a consumer could not install them), so the
|
|
559
|
-
// dependency check must ignore them. Computed at lint time: adding a new
|
|
560
|
-
// internal lib never requires touching this file.
|
|
561
|
-
const workspaceRoot = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
562
|
-
const privateWorkspacePackages = globSync(['libs/*/package.json', 'packages/*/package.json'], { cwd: workspaceRoot })
|
|
563
|
-
.map((manifestPath) => JSON.parse(readFileSync(join(workspaceRoot, manifestPath), 'utf8')))
|
|
564
|
-
.filter((manifest) => manifest.private === true)
|
|
565
|
-
.map((manifest) => manifest.name);
|
|
566
|
-
|
|
567
|
-
export default [
|
|
568
|
-
...baseConfig,
|
|
569
|
-
{
|
|
570
|
-
files: ['**/*.json'],
|
|
571
|
-
rules: {
|
|
572
|
-
'@nx/dependency-checks': [
|
|
573
|
-
'error',
|
|
574
|
-
{
|
|
575
|
-
ignoredDependencies: privateWorkspacePackages,
|
|
576
|
-
ignoredFiles: [
|
|
577
|
-
'{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}',
|
|
578
|
-
'{projectRoot}/rollup.config.{js,ts,mjs,mts,cjs,cts}',
|
|
579
|
-
// Same reasoning as the two config files above, extended to the test
|
|
580
|
-
// toolchain: rollup bundles from the entry point only, so neither the
|
|
581
|
-
// Vitest config nor the spec files reach the published package \u2014 their
|
|
582
|
-
// imports must not drive the published manifest.
|
|
583
|
-
//
|
|
584
|
-
// Without this, a vitest-stack workspace fails \`npm run lint\` on a
|
|
585
|
-
// freshly generated npm-lib: Nx's own spec imports \`vitest\`, and
|
|
586
|
-
// @nx/dependency-checks then demands it be declared as a runtime
|
|
587
|
-
// dependency of a package that never uses it at runtime.
|
|
588
|
-
'{projectRoot}/vitest.config.{js,ts,mjs,mts,cjs,cts}',
|
|
589
|
-
'{projectRoot}/**/*.spec.{js,ts,jsx,tsx}',
|
|
590
|
-
],
|
|
591
|
-
},
|
|
592
|
-
],
|
|
593
|
-
},
|
|
594
|
-
languageOptions: {
|
|
595
|
-
parser: await import('jsonc-eslint-parser'),
|
|
596
|
-
},
|
|
597
|
-
},
|
|
598
|
-
{
|
|
599
|
-
ignores: ['**/out-tsc'],
|
|
600
|
-
},
|
|
601
|
-
];
|
|
602
|
-
`;
|
|
678
|
+
var import_node_path6 = require("path");
|
|
603
679
|
async function addNpmLib(workspaceRoot, name, options, kindProvided, stack) {
|
|
604
680
|
const scope = options.scope ?? (kindProvided ? defaultScope(workspaceRoot) : await promptText("npm scope for the published package", defaultScope(workspaceRoot)));
|
|
605
681
|
runNx(
|
|
@@ -611,16 +687,14 @@ async function addNpmLib(workspaceRoot, name, options, kindProvided, stack) {
|
|
|
611
687
|
`--importPath=${scope}/${name}`,
|
|
612
688
|
"--bundler=rollup",
|
|
613
689
|
`--unitTestRunner=${stack.testRunner}`,
|
|
614
|
-
"--linter=
|
|
690
|
+
"--linter=none",
|
|
615
691
|
"--no-interactive"
|
|
616
692
|
],
|
|
617
693
|
workspaceRoot
|
|
618
694
|
);
|
|
619
|
-
markPublic((0,
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
NPM_LIB_ESLINT_CONFIG
|
|
623
|
-
);
|
|
695
|
+
markPublic((0, import_node_path6.join)(workspaceRoot, "packages", name, "package.json"));
|
|
696
|
+
removeGeneratedEslintConfig(workspaceRoot, `packages/${name}`);
|
|
697
|
+
registerProjectCommands(workspaceRoot, name, { build: true });
|
|
624
698
|
}
|
|
625
699
|
function markPublic(manifestPath) {
|
|
626
700
|
const manifest = readJson(manifestPath);
|
|
@@ -628,8 +702,8 @@ function markPublic(manifestPath) {
|
|
|
628
702
|
}
|
|
629
703
|
|
|
630
704
|
// src/commands/add/python.ts
|
|
631
|
-
var
|
|
632
|
-
var
|
|
705
|
+
var import_node_fs4 = require("fs");
|
|
706
|
+
var import_node_path7 = require("path");
|
|
633
707
|
function ensurePython(workspaceRoot) {
|
|
634
708
|
const hasPython = runShell("python3", ["--version"], workspaceRoot) === 0 || runShell("python", ["--version"], workspaceRoot) === 0;
|
|
635
709
|
if (!hasPython) {
|
|
@@ -658,7 +732,7 @@ pytest
|
|
|
658
732
|
pip-audit
|
|
659
733
|
`;
|
|
660
734
|
function ensureRequirementsDev(workspaceRoot) {
|
|
661
|
-
const requirementsDevPath = (0,
|
|
735
|
+
const requirementsDevPath = (0, import_node_path7.join)(workspaceRoot, "requirements-dev.txt");
|
|
662
736
|
if (!fileExists(requirementsDevPath)) {
|
|
663
737
|
writeFileEnsured(requirementsDevPath, PYTHON_REQUIREMENTS_DEV);
|
|
664
738
|
}
|
|
@@ -666,18 +740,40 @@ function ensureRequirementsDev(workspaceRoot) {
|
|
|
666
740
|
function pythonModuleDirectory(name) {
|
|
667
741
|
return name.replaceAll("-", "_");
|
|
668
742
|
}
|
|
669
|
-
function
|
|
743
|
+
function addProjectJsonTargets3(projectJsonPath, newTargets) {
|
|
670
744
|
const project = readJson(projectJsonPath);
|
|
671
745
|
const targets = project.targets ?? {};
|
|
672
746
|
writeFileEnsured(projectJsonPath, toJson({ ...project, targets: { ...targets, ...newTargets } }));
|
|
673
747
|
}
|
|
748
|
+
function pythonAppMain(name) {
|
|
749
|
+
return `def main() -> None:
|
|
750
|
+
print('${name} is running')
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
if __name__ == '__main__':
|
|
754
|
+
main()
|
|
755
|
+
`;
|
|
756
|
+
}
|
|
757
|
+
function pythonAppStartTarget(name) {
|
|
758
|
+
return {
|
|
759
|
+
executor: "nx:run-commands",
|
|
760
|
+
continuous: true,
|
|
761
|
+
options: { command: "python3 main.py", cwd: `apps/${name}` }
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
function pythonFunctionAppStartTarget(name) {
|
|
765
|
+
return {
|
|
766
|
+
executor: "nx:run-commands",
|
|
767
|
+
continuous: true,
|
|
768
|
+
options: { command: "func start", cwd: `apps/${name}` }
|
|
769
|
+
};
|
|
770
|
+
}
|
|
674
771
|
function pythonAppPackageTarget(name) {
|
|
675
772
|
const zip = `dist/drop/python-app-${name}.zip`;
|
|
676
773
|
const command = `node -e "const fs=require('node:fs');fs.mkdirSync('dist/drop',{recursive:true});const A=require('adm-zip');const z=new A();z.addLocalFolder('apps/${name}/dist');z.writeZip('${zip}')"`;
|
|
677
774
|
return {
|
|
678
775
|
executor: "nx:run-commands",
|
|
679
776
|
dependsOn: ["build"],
|
|
680
|
-
// eslint-disable-next-line unicorn/no-incorrect-template-string-interpolation -- {workspaceRoot} is an Nx output token
|
|
681
777
|
outputs: [`{workspaceRoot}/${zip}`],
|
|
682
778
|
options: { command }
|
|
683
779
|
};
|
|
@@ -688,7 +784,6 @@ function pythonFunctionAppPackageTarget(name, moduleDirectory) {
|
|
|
688
784
|
const command = `node -e "const fs=require('node:fs');fs.mkdirSync('dist/drop',{recursive:true});const A=require('adm-zip');const z=new A();z.addLocalFile('${root}/function_app.py');z.addLocalFile('${root}/host.json');z.addLocalFile('${root}/requirements.txt');z.addLocalFolder('${root}/${moduleDirectory}','${moduleDirectory}');z.writeZip('${zip}')"`;
|
|
689
785
|
return {
|
|
690
786
|
executor: "nx:run-commands",
|
|
691
|
-
// eslint-disable-next-line unicorn/no-incorrect-template-string-interpolation -- {workspaceRoot} is an Nx output token
|
|
692
787
|
outputs: [`{workspaceRoot}/${zip}`],
|
|
693
788
|
options: { command }
|
|
694
789
|
};
|
|
@@ -702,9 +797,12 @@ function addPythonApp(workspaceRoot, name) {
|
|
|
702
797
|
["g", "@mnci/nx-python-pip:application", name, `--directory=apps/${name}`, "--no-interactive"],
|
|
703
798
|
workspaceRoot
|
|
704
799
|
);
|
|
705
|
-
|
|
706
|
-
|
|
800
|
+
writeFileEnsured((0, import_node_path7.join)(workspaceRoot, "apps", name, "main.py"), pythonAppMain(name));
|
|
801
|
+
addProjectJsonTargets3((0, import_node_path7.join)(workspaceRoot, "apps", name, "project.json"), {
|
|
802
|
+
package: pythonAppPackageTarget(name),
|
|
803
|
+
start: pythonAppStartTarget(name)
|
|
707
804
|
});
|
|
805
|
+
registerProjectCommands(workspaceRoot, name, { build: true, start: `nx run ${name}:start` });
|
|
708
806
|
}
|
|
709
807
|
function addPythonFunctionApp(workspaceRoot, name) {
|
|
710
808
|
ensurePython(workspaceRoot);
|
|
@@ -722,9 +820,11 @@ function addPythonFunctionApp(workspaceRoot, name) {
|
|
|
722
820
|
workspaceRoot
|
|
723
821
|
);
|
|
724
822
|
const moduleDirectory = pythonModuleDirectory(name);
|
|
725
|
-
|
|
726
|
-
package: pythonFunctionAppPackageTarget(name, moduleDirectory)
|
|
823
|
+
addProjectJsonTargets3((0, import_node_path7.join)(workspaceRoot, "apps", name, "project.json"), {
|
|
824
|
+
package: pythonFunctionAppPackageTarget(name, moduleDirectory),
|
|
825
|
+
start: pythonFunctionAppStartTarget(name)
|
|
727
826
|
});
|
|
827
|
+
registerProjectCommands(workspaceRoot, name, { build: false, start: `nx run ${name}:start` });
|
|
728
828
|
}
|
|
729
829
|
function addPythonLib(workspaceRoot, name) {
|
|
730
830
|
ensurePython(workspaceRoot);
|
|
@@ -740,6 +840,7 @@ function addPythonLib(workspaceRoot, name) {
|
|
|
740
840
|
],
|
|
741
841
|
workspaceRoot
|
|
742
842
|
);
|
|
843
|
+
registerProjectCommands(workspaceRoot, name, { build: true });
|
|
743
844
|
}
|
|
744
845
|
function addPythonInternalLib(workspaceRoot, name) {
|
|
745
846
|
ensurePython(workspaceRoot);
|
|
@@ -755,11 +856,12 @@ function addPythonInternalLib(workspaceRoot, name) {
|
|
|
755
856
|
],
|
|
756
857
|
workspaceRoot
|
|
757
858
|
);
|
|
859
|
+
registerProjectCommands(workspaceRoot, name, { build: false });
|
|
758
860
|
}
|
|
759
861
|
var PYTHON_PROJECT_DIRS = ["apps", "python-packages", "libs"];
|
|
760
862
|
function findPythonProjectDirectory(workspaceRoot, name) {
|
|
761
863
|
return PYTHON_PROJECT_DIRS.find(
|
|
762
|
-
(directory) => fileExists((0,
|
|
864
|
+
(directory) => fileExists((0, import_node_path7.join)(workspaceRoot, directory, name, "pyproject.toml"))
|
|
763
865
|
);
|
|
764
866
|
}
|
|
765
867
|
function parseVendorEntries(pyprojectToml) {
|
|
@@ -798,7 +900,7 @@ async function addPythonVendor(workspaceRoot, consumer, options, kindProvided) {
|
|
|
798
900
|
`No Python project named '${consumer}' with a pyproject.toml found (checked apps/, python-packages/, libs/). A Python function app has no pyproject.toml \u2014 there is nothing to vendor into.`
|
|
799
901
|
);
|
|
800
902
|
}
|
|
801
|
-
if (!fileExists((0,
|
|
903
|
+
if (!fileExists((0, import_node_path7.join)(workspaceRoot, "libs", lib, "pyproject.toml"))) {
|
|
802
904
|
throw new Error(
|
|
803
905
|
`No internal Python library named '${lib}' found at libs/${lib}/pyproject.toml. Only an internal library (added via 'mnci add python-internal-lib') can be vendored.`
|
|
804
906
|
);
|
|
@@ -806,8 +908,8 @@ async function addPythonVendor(workspaceRoot, consumer, options, kindProvided) {
|
|
|
806
908
|
if (consumerDirectory === "libs" && consumer === lib) {
|
|
807
909
|
throw new Error(`'${consumer}' cannot vendor itself.`);
|
|
808
910
|
}
|
|
809
|
-
const pyprojectPath = (0,
|
|
810
|
-
const pyprojectToml = (0,
|
|
911
|
+
const pyprojectPath = (0, import_node_path7.join)(workspaceRoot, consumerDirectory, consumer, "pyproject.toml");
|
|
912
|
+
const pyprojectToml = (0, import_node_fs4.readFileSync)(pyprojectPath, "utf8");
|
|
811
913
|
if (parseVendorEntries(pyprojectToml).includes(lib)) {
|
|
812
914
|
logger.info(`'${consumer}' already vendors '${lib}' \u2014 nothing to do.`);
|
|
813
915
|
return;
|
|
@@ -819,8 +921,8 @@ async function addPythonVendor(workspaceRoot, consumer, options, kindProvided) {
|
|
|
819
921
|
}
|
|
820
922
|
|
|
821
923
|
// src/commands/add/reactApp.ts
|
|
822
|
-
var
|
|
823
|
-
var
|
|
924
|
+
var import_node_fs5 = require("fs");
|
|
925
|
+
var import_node_path8 = require("path");
|
|
824
926
|
function ensurePlugin2(workspaceRoot, packageName) {
|
|
825
927
|
if (hasPlugin(workspaceRoot, packageName)) {
|
|
826
928
|
return;
|
|
@@ -841,7 +943,6 @@ function reactAppTargets(name) {
|
|
|
841
943
|
for (const environment of REACT_ENVIRONMENTS) {
|
|
842
944
|
targets[`build-${environment}`] = {
|
|
843
945
|
executor: "nx:run-commands",
|
|
844
|
-
// eslint-disable-next-line unicorn/no-incorrect-template-string-interpolation -- {workspaceRoot} is an Nx output token
|
|
845
946
|
outputs: [`{workspaceRoot}/apps/${name}/dist-${environment}`],
|
|
846
947
|
options: {
|
|
847
948
|
command: `vite build --mode ${environment} --outDir dist-${environment}`,
|
|
@@ -856,7 +957,6 @@ function reactAppTargets(name) {
|
|
|
856
957
|
executor: "nx:run-commands",
|
|
857
958
|
dependsOn: REACT_ENVIRONMENTS.map((environment) => `build-${environment}`),
|
|
858
959
|
outputs: REACT_ENVIRONMENTS.map(
|
|
859
|
-
// eslint-disable-next-line unicorn/no-incorrect-template-string-interpolation
|
|
860
960
|
(environment) => `{workspaceRoot}/dist/drop/react-app-${name}-${environment}.zip`
|
|
861
961
|
),
|
|
862
962
|
options: {
|
|
@@ -866,12 +966,12 @@ function reactAppTargets(name) {
|
|
|
866
966
|
return targets;
|
|
867
967
|
}
|
|
868
968
|
function allowEnvFiles(workspaceRoot) {
|
|
869
|
-
const gitignorePath = (0,
|
|
969
|
+
const gitignorePath = (0, import_node_path8.join)(workspaceRoot, ".gitignore");
|
|
870
970
|
if (!fileExists(gitignorePath)) {
|
|
871
971
|
return;
|
|
872
972
|
}
|
|
873
973
|
const marker = "# MoNecromanCI: keep the committed per-environment Vite config (public VITE_ values)";
|
|
874
|
-
const current = (0,
|
|
974
|
+
const current = (0, import_node_fs5.readFileSync)(gitignorePath, "utf8");
|
|
875
975
|
if (current.includes(marker)) {
|
|
876
976
|
return;
|
|
877
977
|
}
|
|
@@ -890,7 +990,7 @@ function addReactApp(workspaceRoot, name, stack) {
|
|
|
890
990
|
`apps/${name}`,
|
|
891
991
|
"--bundler=vite",
|
|
892
992
|
`--unitTestRunner=${stack.testRunner}`,
|
|
893
|
-
"--linter=
|
|
993
|
+
"--linter=none",
|
|
894
994
|
"--style=css",
|
|
895
995
|
"--e2eTestRunner=none",
|
|
896
996
|
"--no-interactive"
|
|
@@ -898,12 +998,14 @@ function addReactApp(workspaceRoot, name, stack) {
|
|
|
898
998
|
workspaceRoot
|
|
899
999
|
);
|
|
900
1000
|
ensureAdmZip(workspaceRoot);
|
|
901
|
-
const reactAppRoot = (0,
|
|
1001
|
+
const reactAppRoot = (0, import_node_path8.join)(workspaceRoot, "apps", name);
|
|
902
1002
|
for (const environment of REACT_ENVIRONMENTS) {
|
|
903
|
-
writeFileEnsured((0,
|
|
1003
|
+
writeFileEnsured((0, import_node_path8.join)(reactAppRoot, `.env.${environment}`), reactEnvironmentFile(environment));
|
|
904
1004
|
}
|
|
905
1005
|
allowEnvFiles(workspaceRoot);
|
|
906
|
-
addNxTargets((0,
|
|
1006
|
+
addNxTargets((0, import_node_path8.join)(reactAppRoot, "package.json"), reactAppTargets(name));
|
|
1007
|
+
removeGeneratedEslintConfig(workspaceRoot, `apps/${name}`);
|
|
1008
|
+
registerProjectCommands(workspaceRoot, name, { build: true, start: `nx run ${name}:serve` });
|
|
907
1009
|
}
|
|
908
1010
|
|
|
909
1011
|
// src/commands/add.ts
|
|
@@ -928,7 +1030,7 @@ var PROJECT_KINDS = [
|
|
|
928
1030
|
];
|
|
929
1031
|
async function runAdd(kind, name, options) {
|
|
930
1032
|
const workspaceRoot = process.cwd();
|
|
931
|
-
if (!fileExists((0,
|
|
1033
|
+
if (!fileExists((0, import_node_path9.join)(workspaceRoot, "nx.json"))) {
|
|
932
1034
|
throw new Error("No nx.json found here. Run `add` from the workspace root.");
|
|
933
1035
|
}
|
|
934
1036
|
const stack = readWorkspaceStack(workspaceRoot);
|
|
@@ -964,12 +1066,14 @@ async function runAdd(kind, name, options) {
|
|
|
964
1066
|
`libs/${resolvedName}`,
|
|
965
1067
|
"--bundler=tsc",
|
|
966
1068
|
`--unitTestRunner=${stack.testRunner}`,
|
|
967
|
-
"--linter=
|
|
1069
|
+
"--linter=none",
|
|
968
1070
|
"--no-interactive"
|
|
969
1071
|
],
|
|
970
1072
|
workspaceRoot
|
|
971
1073
|
);
|
|
972
|
-
markPrivate((0,
|
|
1074
|
+
markPrivate((0, import_node_path9.join)(workspaceRoot, "libs", resolvedName, "package.json"));
|
|
1075
|
+
removeGeneratedEslintConfig(workspaceRoot, `libs/${resolvedName}`);
|
|
1076
|
+
registerProjectCommands(workspaceRoot, resolvedName, { build: true });
|
|
973
1077
|
break;
|
|
974
1078
|
}
|
|
975
1079
|
case "python-app": {
|
|
@@ -1019,6 +1123,7 @@ async function runAdd(kind, name, options) {
|
|
|
1019
1123
|
case "python-vendor": {
|
|
1020
1124
|
await addPythonVendor(workspaceRoot, resolvedName, options, kindProvided);
|
|
1021
1125
|
syncProjectReferences(workspaceRoot);
|
|
1126
|
+
runPrettier(workspaceRoot);
|
|
1022
1127
|
return;
|
|
1023
1128
|
}
|
|
1024
1129
|
default: {
|
|
@@ -1029,6 +1134,7 @@ async function runAdd(kind, name, options) {
|
|
|
1029
1134
|
}
|
|
1030
1135
|
}
|
|
1031
1136
|
syncProjectReferences(workspaceRoot);
|
|
1137
|
+
runPrettier(workspaceRoot);
|
|
1032
1138
|
logger.success(`Added ${resolvedKind} '${resolvedName}'.`);
|
|
1033
1139
|
}
|
|
1034
1140
|
function syncProjectReferences(workspaceRoot) {
|
|
@@ -1041,7 +1147,7 @@ function syncProjectReferences(workspaceRoot) {
|
|
|
1041
1147
|
}
|
|
1042
1148
|
function readWorkspaceStack(workspaceRoot) {
|
|
1043
1149
|
const nxJson = readJson(
|
|
1044
|
-
(0,
|
|
1150
|
+
(0, import_node_path9.join)(workspaceRoot, "nx.json")
|
|
1045
1151
|
);
|
|
1046
1152
|
const stack = nxJson.mnci?.stack;
|
|
1047
1153
|
return {
|
|
@@ -1054,48 +1160,31 @@ function markPrivate(manifestPath) {
|
|
|
1054
1160
|
}
|
|
1055
1161
|
|
|
1056
1162
|
// src/commands/interactive.ts
|
|
1057
|
-
var
|
|
1163
|
+
var import_node_path13 = require("path");
|
|
1058
1164
|
var import_prompts7 = require("@inquirer/prompts");
|
|
1059
1165
|
|
|
1060
1166
|
// src/commands/new.ts
|
|
1061
|
-
var
|
|
1167
|
+
var import_node_path11 = require("path");
|
|
1062
1168
|
|
|
1063
1169
|
// src/overlay.ts
|
|
1064
|
-
var
|
|
1170
|
+
var import_node_fs6 = require("fs");
|
|
1171
|
+
var import_node_path10 = require("path");
|
|
1065
1172
|
var DEFAULT_STACK = { testRunner: "jest" };
|
|
1066
1173
|
var PRETTIER_VERSION = "^3.8.1";
|
|
1067
1174
|
var TS_COMPILER_DEPENDENCIES = {
|
|
1068
1175
|
"@typescript/native": "npm:typescript@^7.0.2",
|
|
1069
1176
|
typescript: "npm:@typescript/typescript6@^6.0.2"
|
|
1070
1177
|
};
|
|
1071
|
-
function npmrcContent(
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
const registryHost = `${base}/npm/registry/`.replace(/^https:\/\//, "");
|
|
1082
|
-
const feedHost = `${base}/`.replace(/^https:\/\//, "");
|
|
1083
|
-
lines.push(
|
|
1084
|
-
`@${scopeName}:registry=${base}/npm/registry/`,
|
|
1085
|
-
"; Azure Artifacts auth \u2014 the base64 PAT is expanded at runtime from the",
|
|
1086
|
-
"; PAT env var (CI: your PAT variable group; locally: export PAT=<base64 token>).",
|
|
1087
|
-
`//${registryHost}:username=${registry.organization}`,
|
|
1088
|
-
`//${registryHost}:_password=\${PAT}`,
|
|
1089
|
-
`//${registryHost}:email=npm@example.com`,
|
|
1090
|
-
`//${feedHost}:username=${registry.organization}`,
|
|
1091
|
-
`//${feedHost}:_password=\${PAT}`,
|
|
1092
|
-
`//${feedHost}:email=npm@example.com`
|
|
1093
|
-
);
|
|
1094
|
-
} else {
|
|
1095
|
-
lines.push(`//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}`);
|
|
1096
|
-
}
|
|
1097
|
-
lines.push("");
|
|
1098
|
-
return lines.join("\n");
|
|
1178
|
+
function npmrcContent(_registry, _scope) {
|
|
1179
|
+
return `; Intentionally empty.
|
|
1180
|
+
;
|
|
1181
|
+
; Publish authentication is not configured yet. The generated CI exports a
|
|
1182
|
+
; token for the release step (NODE_AUTH_TOKEN for public npm, PAT for Azure
|
|
1183
|
+
; Artifacts), but nothing here consumes it, so 'npm publish' will not
|
|
1184
|
+
; authenticate until this is wired up.
|
|
1185
|
+
;
|
|
1186
|
+
; See "Known gaps" in the @mnci/cli README.
|
|
1187
|
+
`;
|
|
1099
1188
|
}
|
|
1100
1189
|
function releaseConfig(ci) {
|
|
1101
1190
|
const githubReleases = ci === "github";
|
|
@@ -1122,6 +1211,18 @@ function releaseConfig(ci) {
|
|
|
1122
1211
|
};
|
|
1123
1212
|
}
|
|
1124
1213
|
var SYNC_CONFIG = { applyChanges: true };
|
|
1214
|
+
var ESLINT_PLUGIN_CONFIG = {
|
|
1215
|
+
plugin: "@nx/eslint/plugin",
|
|
1216
|
+
options: { targetName: "lint" }
|
|
1217
|
+
};
|
|
1218
|
+
function pluginName(entry) {
|
|
1219
|
+
return typeof entry === "string" ? entry : entry.plugin;
|
|
1220
|
+
}
|
|
1221
|
+
function withEslintPlugin(nxJson) {
|
|
1222
|
+
const plugins = nxJson.plugins ?? [];
|
|
1223
|
+
const registered = plugins.some((entry) => pluginName(entry) === ESLINT_PLUGIN_CONFIG.plugin);
|
|
1224
|
+
return registered ? { ...nxJson, plugins } : { ...nxJson, plugins: [...plugins, ESLINT_PLUGIN_CONFIG] };
|
|
1225
|
+
}
|
|
1125
1226
|
function withReleaseConfig(nxJson, ci) {
|
|
1126
1227
|
return { ...nxJson, defaultBase: "main", release: releaseConfig(ci) };
|
|
1127
1228
|
}
|
|
@@ -1132,13 +1233,30 @@ var COMMIT_MSG_HOOK = `npx --no -- commitlint --edit "$1"
|
|
|
1132
1233
|
var PRETTIER_CONFIG = `{
|
|
1133
1234
|
"semi": false,
|
|
1134
1235
|
"singleQuote": true,
|
|
1135
|
-
"trailingComma": "
|
|
1236
|
+
"trailingComma": "none",
|
|
1136
1237
|
"arrowParens": "avoid",
|
|
1137
1238
|
"printWidth": 100,
|
|
1138
1239
|
"tabWidth": 2,
|
|
1139
1240
|
"useTabs": false
|
|
1140
1241
|
}
|
|
1141
1242
|
`;
|
|
1243
|
+
var ESLINT_CONFIG_VERSION = "^0.1.0";
|
|
1244
|
+
function eslintConfigSpec() {
|
|
1245
|
+
return process.env.MNCI_ESLINT_CONFIG_SPEC ?? ESLINT_CONFIG_VERSION;
|
|
1246
|
+
}
|
|
1247
|
+
var ESLINT_VERSION = "^9.39.0";
|
|
1248
|
+
function eslintToolchainDependencies(nxVersion) {
|
|
1249
|
+
return {
|
|
1250
|
+
eslint: ESLINT_VERSION,
|
|
1251
|
+
"@nx/eslint": nxVersion,
|
|
1252
|
+
"@nx/eslint-plugin": nxVersion,
|
|
1253
|
+
"@mnci/eslint-config": eslintConfigSpec()
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
var ESLINT_CONFIG = `import mnci from '@mnci/eslint-config'
|
|
1257
|
+
|
|
1258
|
+
export default mnci({ workspaceRoot: import.meta.dirname })
|
|
1259
|
+
`;
|
|
1142
1260
|
var PRETTIER_IGNORE = `node_modules
|
|
1143
1261
|
dist
|
|
1144
1262
|
dist-dev
|
|
@@ -1155,12 +1273,7 @@ package-lock.json
|
|
|
1155
1273
|
function vscodeWorkspace(workspaceName) {
|
|
1156
1274
|
return JSON.stringify(
|
|
1157
1275
|
{
|
|
1158
|
-
folders: [
|
|
1159
|
-
{ path: ".", name: workspaceName },
|
|
1160
|
-
{ path: "packages/cli", name: "@mnci/cli" },
|
|
1161
|
-
{ path: "packages/nx-python-pip", name: "@mnci/nx-python-pip" },
|
|
1162
|
-
{ path: "libs/monecromanci-v2", name: "@mnci/monecromanci" }
|
|
1163
|
-
],
|
|
1276
|
+
folders: [{ path: ".", name: workspaceName }],
|
|
1164
1277
|
settings: {
|
|
1165
1278
|
"eslint.validate": [
|
|
1166
1279
|
"javascript",
|
|
@@ -1194,7 +1307,8 @@ function vscodeWorkspace(workspaceName) {
|
|
|
1194
1307
|
"nrwl.angular-console",
|
|
1195
1308
|
"firsttris.vscode-jest-runner"
|
|
1196
1309
|
]
|
|
1197
|
-
}
|
|
1310
|
+
},
|
|
1311
|
+
tasks: { version: "2.0.0", tasks: [] }
|
|
1198
1312
|
},
|
|
1199
1313
|
null,
|
|
1200
1314
|
2
|
|
@@ -1219,7 +1333,13 @@ function rootScripts() {
|
|
|
1219
1333
|
}
|
|
1220
1334
|
function generatorDefaults(stack) {
|
|
1221
1335
|
const shared = {
|
|
1222
|
-
|
|
1336
|
+
// `none`, not `eslint`, and the workspace is still fully linted. The root
|
|
1337
|
+
// config plus `@nx/eslint/plugin` ({@link ESLINT_PLUGIN_CONFIG}) give every
|
|
1338
|
+
// project its `lint` target; `eslint` here would only make the generator
|
|
1339
|
+
// scaffold a per-project config mnci deletes anyway — and drag in
|
|
1340
|
+
// `eslint-plugin-import@2.31.0`, which peer-caps at ESLint 9 and breaks the
|
|
1341
|
+
// install outright on this workspace's ESLint 10.
|
|
1342
|
+
linter: "none",
|
|
1223
1343
|
unitTestRunner: stack.testRunner
|
|
1224
1344
|
};
|
|
1225
1345
|
return {
|
|
@@ -1239,7 +1359,7 @@ function mnciConfig(options) {
|
|
|
1239
1359
|
};
|
|
1240
1360
|
}
|
|
1241
1361
|
function readMnciConfig(workspaceRoot) {
|
|
1242
|
-
const nxJson = readJson((0,
|
|
1362
|
+
const nxJson = readJson((0, import_node_path10.join)(workspaceRoot, "nx.json"));
|
|
1243
1363
|
return nxJson.mnci ?? {};
|
|
1244
1364
|
}
|
|
1245
1365
|
function pythonPublishUrl(registry) {
|
|
@@ -1664,8 +1784,23 @@ updates:
|
|
|
1664
1784
|
schedule:
|
|
1665
1785
|
interval: weekly
|
|
1666
1786
|
`;
|
|
1787
|
+
var NX_SCAFFOLDING_TO_REMOVE = [".prettierrc", ".vscode"];
|
|
1788
|
+
function removeNxScaffolding(workspaceRoot) {
|
|
1789
|
+
for (const entry of NX_SCAFFOLDING_TO_REMOVE) {
|
|
1790
|
+
(0, import_node_fs6.rmSync)((0, import_node_path10.join)(workspaceRoot, entry), { recursive: true, force: true });
|
|
1791
|
+
}
|
|
1792
|
+
removeProjectEslintConfigs(workspaceRoot);
|
|
1793
|
+
}
|
|
1794
|
+
function removeProjectEslintConfigs(workspaceRoot) {
|
|
1795
|
+
const matches = (0, import_node_fs6.globSync)("{apps,libs,packages}/*/eslint.config.{js,mjs,cjs,ts,mts,cts}", {
|
|
1796
|
+
cwd: workspaceRoot
|
|
1797
|
+
});
|
|
1798
|
+
for (const match of matches) {
|
|
1799
|
+
(0, import_node_fs6.rmSync)((0, import_node_path10.join)(workspaceRoot, match), { force: true });
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1667
1802
|
function applyOverlay(workspaceRoot, options) {
|
|
1668
|
-
const nxJsonPath = (0,
|
|
1803
|
+
const nxJsonPath = (0, import_node_path10.join)(workspaceRoot, "nx.json");
|
|
1669
1804
|
const nxJson = readJson(nxJsonPath);
|
|
1670
1805
|
const generators = {
|
|
1671
1806
|
...nxJson.generators,
|
|
@@ -1673,49 +1808,52 @@ function applyOverlay(workspaceRoot, options) {
|
|
|
1673
1808
|
};
|
|
1674
1809
|
const sync = { ...nxJson.sync, ...SYNC_CONFIG };
|
|
1675
1810
|
const mnci = { ...nxJson.mnci, ...mnciConfig(options) };
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
);
|
|
1680
|
-
const manifestPath = (0, import_node_path9.join)(workspaceRoot, "package.json");
|
|
1811
|
+
const patched = withEslintPlugin(withReleaseConfig(nxJson, options.ci));
|
|
1812
|
+
writeFileEnsured(nxJsonPath, toJson({ ...patched, generators, sync, mnci }));
|
|
1813
|
+
const manifestPath = (0, import_node_path10.join)(workspaceRoot, "package.json");
|
|
1681
1814
|
const manifest = readJson(manifestPath);
|
|
1682
1815
|
const scripts = {
|
|
1683
1816
|
...manifest.scripts,
|
|
1684
1817
|
...rootScripts()
|
|
1685
1818
|
};
|
|
1819
|
+
const existingDevDeps = manifest.devDependencies;
|
|
1686
1820
|
const devDeps = {
|
|
1687
|
-
...
|
|
1821
|
+
...existingDevDeps,
|
|
1688
1822
|
...TS_COMPILER_DEPENDENCIES,
|
|
1823
|
+
// The preset pins `nx` itself; the ESLint plugins must match it exactly.
|
|
1824
|
+
...eslintToolchainDependencies(existingDevDeps?.nx ?? "latest"),
|
|
1689
1825
|
prettier: PRETTIER_VERSION
|
|
1690
1826
|
};
|
|
1691
1827
|
writeFileEnsured(
|
|
1692
1828
|
manifestPath,
|
|
1693
1829
|
toJson({ ...manifest, name: `${options.scope}/source`, scripts, devDependencies: devDeps })
|
|
1694
1830
|
);
|
|
1695
|
-
writeFileEnsured((0,
|
|
1696
|
-
writeFileEnsured((0,
|
|
1697
|
-
const hookPath = (0,
|
|
1831
|
+
writeFileEnsured((0, import_node_path10.join)(workspaceRoot, ".npmrc"), npmrcContent(options.registry, options.scope));
|
|
1832
|
+
writeFileEnsured((0, import_node_path10.join)(workspaceRoot, "commitlint.config.mjs"), COMMITLINT_CONFIG);
|
|
1833
|
+
const hookPath = (0, import_node_path10.join)(workspaceRoot, ".husky/commit-msg");
|
|
1698
1834
|
writeFileEnsured(hookPath, COMMIT_MSG_HOOK);
|
|
1699
1835
|
markExecutable(hookPath);
|
|
1700
|
-
writeFileEnsured((0,
|
|
1701
|
-
writeFileEnsured((0,
|
|
1836
|
+
writeFileEnsured((0, import_node_path10.join)(workspaceRoot, "eslint.config.mjs"), ESLINT_CONFIG);
|
|
1837
|
+
writeFileEnsured((0, import_node_path10.join)(workspaceRoot, ".prettierrc.json"), PRETTIER_CONFIG);
|
|
1838
|
+
writeFileEnsured((0, import_node_path10.join)(workspaceRoot, ".prettierignore"), PRETTIER_IGNORE);
|
|
1839
|
+
removeNxScaffolding(workspaceRoot);
|
|
1702
1840
|
writeFileEnsured(
|
|
1703
|
-
(0,
|
|
1841
|
+
(0, import_node_path10.join)(workspaceRoot, `${options.workspaceName}.code-workspace`),
|
|
1704
1842
|
vscodeWorkspace(options.workspaceName)
|
|
1705
1843
|
);
|
|
1706
1844
|
const publishUrl = pythonPublishUrl(options.registry);
|
|
1707
1845
|
if (options.ci === "azure" || options.ci === "both") {
|
|
1708
1846
|
writeFileEnsured(
|
|
1709
|
-
(0,
|
|
1847
|
+
(0, import_node_path10.join)(workspaceRoot, "azure-pipelines.yml"),
|
|
1710
1848
|
azurePipelinesYaml(options.agent, options.variableGroup, publishUrl, options.registry.kind)
|
|
1711
1849
|
);
|
|
1712
1850
|
}
|
|
1713
1851
|
if (options.ci === "github" || options.ci === "both") {
|
|
1714
1852
|
writeFileEnsured(
|
|
1715
|
-
(0,
|
|
1853
|
+
(0, import_node_path10.join)(workspaceRoot, ".github/workflows/ci.yml"),
|
|
1716
1854
|
githubActionsYaml(options.agent, publishUrl, options.registry.kind, options.ci)
|
|
1717
1855
|
);
|
|
1718
|
-
writeFileEnsured((0,
|
|
1856
|
+
writeFileEnsured((0, import_node_path10.join)(workspaceRoot, ".github/dependabot.yml"), DEPENDABOT_CONFIG);
|
|
1719
1857
|
}
|
|
1720
1858
|
}
|
|
1721
1859
|
|
|
@@ -1784,12 +1922,12 @@ async function runNew(name, options) {
|
|
|
1784
1922
|
],
|
|
1785
1923
|
process.cwd()
|
|
1786
1924
|
);
|
|
1787
|
-
const workspaceRoot = (0,
|
|
1925
|
+
const workspaceRoot = (0, import_node_path11.join)(process.cwd(), workspaceName);
|
|
1788
1926
|
logger.step(
|
|
1789
1927
|
"Applying MoNecromanCI overlay (VS Code workspace, release config, .npmrc, commitlint, pipeline, stack)"
|
|
1790
1928
|
);
|
|
1791
1929
|
applyOverlay(workspaceRoot, { workspaceName, scope, registry, agent, variableGroup, ci, stack });
|
|
1792
|
-
logger.step("Installing the toolchain (commitlint + husky)");
|
|
1930
|
+
logger.step("Installing the toolchain (commitlint + husky + linting/formatting)");
|
|
1793
1931
|
const installStatus = runShell(
|
|
1794
1932
|
"npm",
|
|
1795
1933
|
["install", "--save-dev", "husky", "@commitlint/cli", "@commitlint/config-conventional"],
|
|
@@ -1799,6 +1937,8 @@ async function runNew(name, options) {
|
|
|
1799
1937
|
throw new Error(`npm install of the toolchain failed with exit code ${installStatus}`);
|
|
1800
1938
|
}
|
|
1801
1939
|
runShell("npx", ["husky"], workspaceRoot);
|
|
1940
|
+
logger.step("Formatting the workspace (Prettier, JavaScript Standard Style)");
|
|
1941
|
+
runPrettier(workspaceRoot);
|
|
1802
1942
|
logger.success("Done. Next steps:");
|
|
1803
1943
|
logger.info(` cd ${workspaceName}`);
|
|
1804
1944
|
logger.info(
|
|
@@ -1817,7 +1957,7 @@ async function runNew(name, options) {
|
|
|
1817
1957
|
}
|
|
1818
1958
|
|
|
1819
1959
|
// src/commands/upgrade.ts
|
|
1820
|
-
var
|
|
1960
|
+
var import_node_path12 = require("path");
|
|
1821
1961
|
function resolveRegistry2(options, persisted) {
|
|
1822
1962
|
if (options.registry === "azure-artifacts" || options.organization && options.artifactsFeed) {
|
|
1823
1963
|
const persistedAzure = persisted?.kind === "azure-artifacts" ? persisted : void 0;
|
|
@@ -1869,7 +2009,7 @@ function resolveOverlayOptions(options, persisted) {
|
|
|
1869
2009
|
return { scope, registry, agent, variableGroup, ci, stack: { testRunner } };
|
|
1870
2010
|
}
|
|
1871
2011
|
function runUpgrade(workspaceRoot, options) {
|
|
1872
|
-
if (!fileExists((0,
|
|
2012
|
+
if (!fileExists((0, import_node_path12.join)(workspaceRoot, "nx.json"))) {
|
|
1873
2013
|
throw new Error(
|
|
1874
2014
|
`No nx.json found in ${workspaceRoot} \u2014 this does not look like an Nx workspace. Run 'mnci upgrade' from the workspace root.`
|
|
1875
2015
|
);
|
|
@@ -1885,7 +2025,7 @@ function runUpgrade(workspaceRoot, options) {
|
|
|
1885
2025
|
|
|
1886
2026
|
// src/commands/interactive.ts
|
|
1887
2027
|
async function runInteractive() {
|
|
1888
|
-
const inWorkspace = fileExists((0,
|
|
2028
|
+
const inWorkspace = fileExists((0, import_node_path13.join)(process.cwd(), "nx.json"));
|
|
1889
2029
|
const newChoice = { name: "Create a new monorepo", value: "new" };
|
|
1890
2030
|
const addChoice = { name: "Add a project to this workspace", value: "add" };
|
|
1891
2031
|
const upgradeChoice = {
|
|
@@ -1906,8 +2046,8 @@ async function runInteractive() {
|
|
|
1906
2046
|
}
|
|
1907
2047
|
|
|
1908
2048
|
// src/util/versionChecker.ts
|
|
1909
|
-
var
|
|
1910
|
-
var
|
|
2049
|
+
var import_node_fs7 = require("fs");
|
|
2050
|
+
var import_node_path14 = require("path");
|
|
1911
2051
|
var import_cross_spawn2 = __toESM(require("cross-spawn"));
|
|
1912
2052
|
var PACKAGE_NAME = "@mnci/cli";
|
|
1913
2053
|
var REGISTRY_TIMEOUT_MS = 2e3;
|
|
@@ -1963,8 +2103,8 @@ function releaseTriple(version) {
|
|
|
1963
2103
|
}
|
|
1964
2104
|
function readCliVersion(packageDirectory) {
|
|
1965
2105
|
try {
|
|
1966
|
-
const manifestPath = (0,
|
|
1967
|
-
const manifest = JSON.parse((0,
|
|
2106
|
+
const manifestPath = (0, import_node_path14.join)(packageDirectory, "..", "package.json");
|
|
2107
|
+
const manifest = JSON.parse((0, import_node_fs7.readFileSync)(manifestPath, "utf8"));
|
|
1968
2108
|
return manifest.version ?? "0.0.0";
|
|
1969
2109
|
} catch {
|
|
1970
2110
|
return "0.0.0";
|