@mnci/cli 4.10.5 → 4.10.7

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
@@ -1371,8 +1371,21 @@ pipeline installs `golangci-lint` itself (see below).
1371
1371
  generators, in that order — `convert-to-one-mod` refuses once `go.work`
1372
1372
  lists any module, so it has to happen before the first Go project exists.
1373
1373
  Every Go project then shares that module and imports its siblings as
1374
- `<module>/libs/<name>`, with no per-project manifests and no `replace`
1375
- directives.
1374
+ `<module>/libs/<name>/<slice>`, with no per-project manifests and no
1375
+ `replace` directives.
1376
+ - **A Go library is a capability of slice packages.** The plugin's library
1377
+ generator writes `<name>.go` at the project root, which makes the root
1378
+ package the whole library. mnci replaces it with a root `doc.go` and moves
1379
+ the sample into one starter slice package (`libs/markdown-workspace/
1380
+ markdownworkspace/markdown_workspace_use_case.go`), the Go spelling of the
1381
+ `<kebab>.<role>.ts` files the TypeScript scaffolds get. Rename the starter
1382
+ after the outcome it delivers and add one package per further outcome.
1383
+ - **`test` and `lint` reach every slice package.** The plugin's executors run
1384
+ `go test ./...` and `golangci-lint run ./...` from the project root
1385
+ (measured on `@nx-go/nx-go` 4.1.1), so mnci passes no package list. The e2e
1386
+ plants a failing test and a lint finding in a nested package and asserts
1387
+ both fail the project target, so a plugin change that stopped recursing
1388
+ would surface there rather than as a silently green lib.
1376
1389
  - **The `go.work` multi-module layout was rejected deliberately.** Besides
1377
1390
  splitting dependencies across per-project manifests, it is brittle: a
1378
1391
  single stale `use` entry — a project directory removed by hand — makes
package/dist/cli.js CHANGED
@@ -614,7 +614,7 @@ var ESLINT_PEER_OVERRIDES = {
614
614
  // both — and forcing those to v5 breaks them. So the blast radius is one
615
615
  // dependency edge per named parent, and a test asserts there is no top-level
616
616
  // entry.
617
- "nx": { "brace-expansion": "^5.0.9", "smol-toml": "^1.7.1" },
617
+ "nx": { "brace-expansion": "^5.0.9", "smol-toml": "^1.7.1", "axios": "^1.20.0" },
618
618
  "@nx/js": { "brace-expansion": "^5.0.9" },
619
619
  "@nx/eslint": { "brace-expansion": "^5.0.9" },
620
620
  "@nx/eslint-plugin": { "brace-expansion": "^5.0.9" },
@@ -857,7 +857,7 @@ function vscodeWorkspace(workspaceName, existingTasks, existingLaunch, existingS
857
857
  (configuration) => !String(configuration.name ?? "").startsWith(LAUNCH_CONFIG_PREFIX)
858
858
  );
859
859
  const settings = { ...existingSettings, ...vscodeSettings() };
860
- return JSON.stringify(
860
+ return toJson(
861
861
  {
862
862
  folders: [{ path: ".", name: workspaceName }],
863
863
  settings,
@@ -870,9 +870,7 @@ function vscodeWorkspace(workspaceName, existingTasks, existingLaunch, existingS
870
870
  version: existingLaunch?.version ?? "0.2.0",
871
871
  configurations: [...launchConfigurations(workspaceName), ...userConfigurations]
872
872
  }
873
- },
874
- null,
875
- 2
873
+ }
876
874
  );
877
875
  }
878
876
  var ROOT_SCRIPTS = {
@@ -1760,6 +1758,10 @@ function removeNxScaffolding(workspaceRoot) {
1760
1758
  }
1761
1759
  function removeNxAuthoredAgentFiles(workspaceRoot) {
1762
1760
  (0, import_node_fs2.rmSync)((0, import_node_path2.join)(workspaceRoot, NX_CLAUDE_SETTINGS), { force: true });
1761
+ const claudeDirectory = (0, import_node_path2.join)(workspaceRoot, (0, import_node_path2.dirname)(NX_CLAUDE_SETTINGS));
1762
+ if ((0, import_node_fs2.existsSync)(claudeDirectory) && (0, import_node_fs2.readdirSync)(claudeDirectory).length === 0) {
1763
+ (0, import_node_fs2.rmSync)(claudeDirectory, { recursive: true, force: true });
1764
+ }
1763
1765
  for (const name of NX_AUTHORED_AGENT_FILES) {
1764
1766
  const path = (0, import_node_path2.join)(workspaceRoot, name);
1765
1767
  if (!(0, import_node_fs2.existsSync)(path)) continue;
@@ -2638,6 +2640,65 @@ function goStartTarget(name) {
2638
2640
  options: { command: "go run .", cwd: `apps/${name}` }
2639
2641
  };
2640
2642
  }
2643
+ function goLibraryIdentifiers(projectName) {
2644
+ const words = projectName.split(/[^a-z0-9]+/i).filter((word) => word.length > 0);
2645
+ return {
2646
+ packageName: words.join("").toLowerCase(),
2647
+ functionName: words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(""),
2648
+ fileStem: words.join("_").toLowerCase()
2649
+ };
2650
+ }
2651
+ function reshapeGoLibraryScaffold(projectRoot, projectName) {
2652
+ const { packageName, functionName, fileStem } = goLibraryIdentifiers(projectName);
2653
+ (0, import_node_fs5.rmSync)((0, import_node_path6.join)(projectRoot, `${projectName}.go`), { force: true });
2654
+ (0, import_node_fs5.rmSync)((0, import_node_path6.join)(projectRoot, `${projectName}_test.go`), { force: true });
2655
+ const files = [
2656
+ [
2657
+ "doc.go",
2658
+ `// Package ${packageName} is the ${projectName} capability. Its code lives in the
2659
+ // slice packages below this directory, one package per outcome.
2660
+ package ${packageName}
2661
+ `
2662
+ ],
2663
+ [
2664
+ (0, import_node_path6.join)(packageName, "doc.go"),
2665
+ `// Package ${packageName} is the starter slice of ${projectName}: rename it after
2666
+ // the outcome it delivers, and add one package per further outcome.
2667
+ package ${packageName}
2668
+ `
2669
+ ],
2670
+ [
2671
+ (0, import_node_path6.join)(packageName, `${fileStem}_use_case.go`),
2672
+ `package ${packageName}
2673
+
2674
+ // ${functionName} is the generator's sample behaviour, kept so the slice builds and tests.
2675
+ func ${functionName}(name string) string {
2676
+ return "${functionName} " + name
2677
+ }
2678
+ `
2679
+ ],
2680
+ [
2681
+ (0, import_node_path6.join)(packageName, `${fileStem}_use_case_test.go`),
2682
+ `package ${packageName}
2683
+
2684
+ import "testing"
2685
+
2686
+ func Test${functionName}(t *testing.T) {
2687
+ if got := ${functionName}("works"); got != "${functionName} works" {
2688
+ t.Fatalf("got %q", got)
2689
+ }
2690
+ }
2691
+ `
2692
+ ]
2693
+ ];
2694
+ for (const [relativePath, content] of files) {
2695
+ const path = (0, import_node_path6.join)(projectRoot, relativePath);
2696
+ if (!fileExists(path)) {
2697
+ writeFileEnsured(path, content);
2698
+ }
2699
+ }
2700
+ return packageName;
2701
+ }
2641
2702
  function prepareGo(workspaceRoot) {
2642
2703
  ensureGo(workspaceRoot);
2643
2704
  warnIfNoGolangciLint(workspaceRoot);
@@ -2706,10 +2767,11 @@ function addGoLib(workspaceRoot, name) {
2706
2767
  test: goTestTarget(),
2707
2768
  lint: goLintTarget()
2708
2769
  });
2770
+ const slice = reshapeGoLibraryScaffold((0, import_node_path6.join)(workspaceRoot, "packages", name), name);
2709
2771
  registerProjectCommands(workspaceRoot, name, { build: false });
2710
2772
  const module2 = goModulePath(workspaceRoot);
2711
2773
  if (module2) {
2712
- logger.step(`Import it as ${module2}/packages/${name}`);
2774
+ logger.step(`Import its starter slice as ${module2}/packages/${name}/${slice}`);
2713
2775
  }
2714
2776
  }
2715
2777
  function addGoInternalLib(workspaceRoot, name) {
@@ -2729,10 +2791,11 @@ function addGoInternalLib(workspaceRoot, name) {
2729
2791
  test: goTestTarget(),
2730
2792
  lint: goLintTarget()
2731
2793
  });
2794
+ const slice = reshapeGoLibraryScaffold((0, import_node_path6.join)(workspaceRoot, "libs", name), name);
2732
2795
  registerProjectCommands(workspaceRoot, name, { build: false });
2733
2796
  const module2 = goModulePath(workspaceRoot);
2734
2797
  if (module2) {
2735
- logger.step(`Import it as ${module2}/libs/${name}`);
2798
+ logger.step(`Import its starter slice as ${module2}/libs/${name}/${slice}`);
2736
2799
  }
2737
2800
  }
2738
2801
 
@@ -5271,7 +5334,25 @@ function runDoctor(workspaceRoot) {
5271
5334
  var import_node_fs13 = require("fs");
5272
5335
  var import_node_path20 = require("path");
5273
5336
  var NEVER_COPIED = /* @__PURE__ */ new Set([".git", "node_modules"]);
5274
- var EXISTING_WINS = /* @__PURE__ */ new Set(["README.md", "LICENSE", "LICENSE.md", "LICENSE.txt"]);
5337
+ var AGENT_AND_CI_ENTRIES = [
5338
+ "AGENTS.md",
5339
+ "CLAUDE.md",
5340
+ ".claude",
5341
+ ".agents",
5342
+ ".codex",
5343
+ ".cursor",
5344
+ ".gemini",
5345
+ ".opencode",
5346
+ "opencode.json",
5347
+ ".github"
5348
+ ];
5349
+ var EXISTING_WINS = /* @__PURE__ */ new Set([
5350
+ "README.md",
5351
+ "LICENSE",
5352
+ "LICENSE.md",
5353
+ "LICENSE.txt",
5354
+ ...AGENT_AND_CI_ENTRIES
5355
+ ]);
5275
5356
  var PREFLIGHT_BLOCKERS = [
5276
5357
  "package.json",
5277
5358
  "nx.json",
@@ -5398,27 +5479,30 @@ async function runNew(name, options) {
5398
5479
  const stack = await resolveStack(options);
5399
5480
  const nxCloud = options.nxCloud ?? (options.yes ? false : await promptNxCloud());
5400
5481
  const stagingParent = adoptTarget === void 0 ? process.cwd() : (0, import_node_fs14.mkdtempSync)((0, import_node_path21.join)((0, import_node_os.tmpdir)(), "mnci-new-"));
5401
- logger.step(`Creating Nx workspace '${workspaceName}' (preset: ts)`);
5402
- runNpx(
5403
- [
5404
- "--yes",
5405
- "create-nx-workspace@latest",
5406
- workspaceName,
5407
- "--preset=ts",
5408
- "--pm=npm",
5409
- nxCloud ? `--nxCloud=${nxCloudProviderValue(ci)}` : "--nxCloud=skip",
5410
- "--no-interactive"
5411
- ],
5412
- stagingParent
5413
- );
5414
5482
  let workspaceRoot = (0, import_node_path21.join)(stagingParent, workspaceName);
5415
- if (adoptTarget !== void 0) {
5416
- logger.step(`Adopting ${adoptTarget} (keeping its .git)`);
5417
- const adoption = adoptGeneratedWorkspace(workspaceRoot, adoptTarget);
5418
- for (const kept of adoption.kept) logger.detail(`kept the existing ${kept}`);
5419
- if (adoption.mergedGitignore) logger.detail("merged the generated .gitignore into the existing one");
5420
- (0, import_node_fs14.rmSync)(stagingParent, { recursive: true, force: true });
5421
- workspaceRoot = adoptTarget;
5483
+ try {
5484
+ logger.step(`Creating Nx workspace '${workspaceName}' (preset: ts)`);
5485
+ runNpx(
5486
+ [
5487
+ "--yes",
5488
+ "create-nx-workspace@latest",
5489
+ workspaceName,
5490
+ "--preset=ts",
5491
+ "--pm=npm",
5492
+ nxCloud ? `--nxCloud=${nxCloudProviderValue(ci)}` : "--nxCloud=skip",
5493
+ "--no-interactive"
5494
+ ],
5495
+ stagingParent
5496
+ );
5497
+ if (adoptTarget !== void 0) {
5498
+ logger.step(`Adopting ${adoptTarget} (keeping its .git)`);
5499
+ const adoption = adoptGeneratedWorkspace(workspaceRoot, adoptTarget);
5500
+ for (const kept of adoption.kept) logger.detail(`kept the existing ${kept}`);
5501
+ if (adoption.mergedGitignore) logger.detail("merged the generated .gitignore into the existing one");
5502
+ workspaceRoot = adoptTarget;
5503
+ }
5504
+ } finally {
5505
+ if (adoptTarget !== void 0) (0, import_node_fs14.rmSync)(stagingParent, { recursive: true, force: true });
5422
5506
  }
5423
5507
  logger.step(
5424
5508
  "Applying MoNecromanCI overlay (VS Code workspace, release config, .npmrc, commitlint, pipeline, stack)"