@mnci/cli 1.11.2 → 1.12.1

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 CHANGED
@@ -146,9 +146,17 @@ same options `new` would have and calls the exact same `applyOverlay` `new`
146
146
  itself calls — the one function that does every bit of `mnci`-owned file
147
147
  writing (`nx.json`'s `release`/`sync`/`generators`/`mnci` blocks, `.npmrc`,
148
148
  `eslint.config.mjs`, `.prettierrc.json`, `commitlint.config.mjs`,
149
- `.husky/commit-msg`, the CI pipeline file(s), and the curated root
150
- `package.json` scripts). Nothing else in the workspace — app/lib source,
151
- `project.json` targets from `mnci add` — is ever touched.
149
+ `.husky/commit-msg`, the CI pipeline file(s), the
150
+ `<workspace-name>.code-workspace` file, and the curated root `package.json`
151
+ scripts). Nothing else in the workspace — app/lib source, `project.json` targets
152
+ from `mnci add` — is ever touched, and it finishes by running Prettier over the
153
+ result, the same way `new` and every `add` do.
154
+
155
+ The `.code-workspace` file is the one partial case, and deliberately so: its
156
+ folders, settings and extensions are regenerated, but the **`tasks` array is read
157
+ back and carried through unchanged**. Those tasks are per-project state written by
158
+ `mnci add`, not overlay-owned, so regenerating them wholesale would wipe every
159
+ project's build/qa/start entry on upgrade.
152
160
 
153
161
  `upgrade` also **deletes** things, which is stronger than the overwriting it
154
162
  has always done — one more reason to run `git diff` first, as the command's own
package/dist/cli.js CHANGED
@@ -150,6 +150,13 @@ var import_node_path = require("path");
150
150
  function readJson(path) {
151
151
  return JSON.parse((0, import_node_fs.readFileSync)(path, "utf8"));
152
152
  }
153
+ function readCodeWorkspace(path) {
154
+ try {
155
+ return JSON.parse((0, import_node_fs.readFileSync)(path, "utf8").replaceAll(/,(\s*[}\]])/g, "$1"));
156
+ } catch {
157
+ return void 0;
158
+ }
159
+ }
153
160
  function toJson(value) {
154
161
  return `${JSON.stringify(value, void 0, 2)}
155
162
  `;
@@ -167,9 +174,9 @@ function fileExists(path) {
167
174
 
168
175
  // src/util/names.ts
169
176
  function assertValidProjectName(name, label) {
170
- if (!/^[a-z][a-z0-9-]*$/.test(name)) {
177
+ if (!/^[a-z][a-z0-9-]*(?:\.[a-z0-9-]+)*$/.test(name)) {
171
178
  throw new Error(
172
- `${label} '${name}' is invalid \u2014 use lowercase letters, digits and hyphens, starting with a letter (e.g. 'my-project').`
179
+ `${label} '${name}' is invalid \u2014 use lowercase letters, digits, hyphens and dots, starting with a letter, with no leading, trailing or repeated dot (e.g. 'my-project', 'my.service').`
173
180
  );
174
181
  }
175
182
  }
@@ -234,10 +241,6 @@ function findCodeWorkspaceFile(workspaceRoot) {
234
241
  return void 0;
235
242
  }
236
243
  }
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
244
  function projectTask(name, kind) {
242
245
  const script = `${name}:${kind}`;
243
246
  const base = { label: `${name}: ${kind}`, type: "npm", script, problemMatcher: [] };
@@ -264,7 +267,7 @@ function registerProjectCommands(workspaceRoot, name, commands) {
264
267
  if (!codeWorkspacePath) {
265
268
  return;
266
269
  }
267
- const workspaceFile = readCodeWorkspaceFile(codeWorkspacePath);
270
+ const workspaceFile = readCodeWorkspace(codeWorkspacePath) ?? {};
268
271
  const label = (task) => task.label ?? "";
269
272
  const existingTasks = (workspaceFile.tasks?.tasks ?? []).filter(
270
273
  (task) => !label(task).startsWith(`${name}: `)
@@ -1269,8 +1272,14 @@ out
1269
1272
  tmp
1270
1273
  package-lock.json
1271
1274
  *.lock
1275
+ .venv
1276
+ venv
1277
+ __pycache__
1278
+ .pytest_cache
1279
+ .ruff_cache
1280
+ .dart_tool
1272
1281
  `;
1273
- function vscodeWorkspace(workspaceName) {
1282
+ function vscodeWorkspace(workspaceName, existingTasks) {
1274
1283
  return JSON.stringify(
1275
1284
  {
1276
1285
  folders: [{ path: ".", name: workspaceName }],
@@ -1308,7 +1317,10 @@ function vscodeWorkspace(workspaceName) {
1308
1317
  "firsttris.vscode-jest-runner"
1309
1318
  ]
1310
1319
  },
1311
- tasks: { version: "2.0.0", tasks: [] }
1320
+ tasks: {
1321
+ version: existingTasks?.version ?? "2.0.0",
1322
+ tasks: existingTasks?.tasks ?? []
1323
+ }
1312
1324
  },
1313
1325
  null,
1314
1326
  2
@@ -1350,6 +1362,12 @@ function generatorDefaults(stack) {
1350
1362
  }
1351
1363
  function mnciConfig(options) {
1352
1364
  return {
1365
+ // Persisted so `mnci upgrade` can name the `<name>.code-workspace` file it
1366
+ // rewrites. Its absence is why upgrade used to write a file literally called
1367
+ // `undefined.code-workspace` and therefore never refreshed the real one —
1368
+ // see `resolveWorkspaceName` in `commands/upgrade.ts`, which still needs a
1369
+ // fallback chain for workspaces generated before this field existed.
1370
+ workspaceName: options.workspaceName,
1353
1371
  scope: options.scope,
1354
1372
  registry: options.registry,
1355
1373
  agent: options.agent,
@@ -1850,10 +1868,12 @@ function applyOverlay(workspaceRoot, options) {
1850
1868
  writeFileEnsured((0, import_node_path10.join)(workspaceRoot, ".prettierrc.json"), PRETTIER_CONFIG);
1851
1869
  writeFileEnsured((0, import_node_path10.join)(workspaceRoot, ".prettierignore"), PRETTIER_IGNORE);
1852
1870
  removeNxScaffolding(workspaceRoot);
1853
- writeFileEnsured(
1854
- (0, import_node_path10.join)(workspaceRoot, `${options.workspaceName}.code-workspace`),
1855
- vscodeWorkspace(options.workspaceName)
1856
- );
1871
+ const codeWorkspacePath = (0, import_node_path10.join)(workspaceRoot, `${options.workspaceName}.code-workspace`);
1872
+ const existing = readCodeWorkspace(codeWorkspacePath);
1873
+ writeFileEnsured(codeWorkspacePath, vscodeWorkspace(options.workspaceName, existing?.tasks));
1874
+ if (options.workspaceName !== "undefined") {
1875
+ (0, import_node_fs6.rmSync)((0, import_node_path10.join)(workspaceRoot, "undefined.code-workspace"), { force: true });
1876
+ }
1857
1877
  const publishUrl = pythonPublishUrl(options.registry);
1858
1878
  if (options.ci === "azure" || options.ci === "both") {
1859
1879
  writeFileEnsured(
@@ -1970,6 +1990,7 @@ async function runNew(name, options) {
1970
1990
  }
1971
1991
 
1972
1992
  // src/commands/upgrade.ts
1993
+ var import_node_fs7 = require("fs");
1973
1994
  var import_node_path12 = require("path");
1974
1995
  function resolveRegistry2(options, persisted) {
1975
1996
  if (options.registry === "azure-artifacts" || options.organization && options.artifactsFeed) {
@@ -1994,7 +2015,22 @@ function resolveRegistry2(options, persisted) {
1994
2015
  "No registry found in nx.json's persisted config. Pass --registry npm or --registry azure-artifacts (with --organization/--project/--artifacts-feed)."
1995
2016
  );
1996
2017
  }
1997
- function resolveOverlayOptions(options, persisted) {
2018
+ function resolveWorkspaceName(workspaceRoot, persisted) {
2019
+ if (persisted.workspaceName) {
2020
+ return persisted.workspaceName;
2021
+ }
2022
+ try {
2023
+ const existing = (0, import_node_fs7.readdirSync)(workspaceRoot).find(
2024
+ (file) => file.endsWith(".code-workspace") && file !== "undefined.code-workspace"
2025
+ );
2026
+ if (existing) {
2027
+ return existing.replace(/\.code-workspace$/, "");
2028
+ }
2029
+ } catch {
2030
+ }
2031
+ return (0, import_node_path12.basename)(workspaceRoot);
2032
+ }
2033
+ function resolveOverlayOptions(workspaceRoot, options, persisted) {
1998
2034
  const scope = options.scope ?? persisted.scope;
1999
2035
  if (!scope) {
2000
2036
  throw new Error("No npm scope found in nx.json's persisted config. Pass --scope explicitly.");
@@ -2019,7 +2055,15 @@ function resolveOverlayOptions(options, persisted) {
2019
2055
  "No testRunner found in nx.json's persisted config. Pass --test-runner explicitly."
2020
2056
  );
2021
2057
  }
2022
- return { scope, registry, agent, variableGroup, ci, stack: { testRunner } };
2058
+ return {
2059
+ workspaceName: resolveWorkspaceName(workspaceRoot, persisted),
2060
+ scope,
2061
+ registry,
2062
+ agent,
2063
+ variableGroup,
2064
+ ci,
2065
+ stack: { testRunner }
2066
+ };
2023
2067
  }
2024
2068
  function runUpgrade(workspaceRoot, options) {
2025
2069
  if (!fileExists((0, import_node_path12.join)(workspaceRoot, "nx.json"))) {
@@ -2028,11 +2072,12 @@ function runUpgrade(workspaceRoot, options) {
2028
2072
  );
2029
2073
  }
2030
2074
  const persisted = readMnciConfig(workspaceRoot);
2031
- const resolved = resolveOverlayOptions(options, persisted);
2075
+ const resolved = resolveOverlayOptions(workspaceRoot, options, persisted);
2032
2076
  logger.step(
2033
2077
  "Re-applying the MoNecromanCI overlay (release config, .npmrc, commitlint, pipeline, stack)"
2034
2078
  );
2035
2079
  applyOverlay(workspaceRoot, resolved);
2080
+ runPrettier(workspaceRoot);
2036
2081
  logger.success("Done. Review the changes with `git diff` before committing.");
2037
2082
  }
2038
2083
 
@@ -2059,7 +2104,7 @@ async function runInteractive() {
2059
2104
  }
2060
2105
 
2061
2106
  // src/util/versionChecker.ts
2062
- var import_node_fs7 = require("fs");
2107
+ var import_node_fs8 = require("fs");
2063
2108
  var import_node_path14 = require("path");
2064
2109
  var import_cross_spawn2 = __toESM(require("cross-spawn"));
2065
2110
  var PACKAGE_NAME = "@mnci/cli";
@@ -2117,7 +2162,7 @@ function releaseTriple(version) {
2117
2162
  function readCliVersion(packageDirectory) {
2118
2163
  try {
2119
2164
  const manifestPath = (0, import_node_path14.join)(packageDirectory, "..", "package.json");
2120
- const manifest = JSON.parse((0, import_node_fs7.readFileSync)(manifestPath, "utf8"));
2165
+ const manifest = JSON.parse((0, import_node_fs8.readFileSync)(manifestPath, "utf8"));
2121
2166
  return manifest.version ?? "0.0.0";
2122
2167
  } catch {
2123
2168
  return "0.0.0";