@clearlydev/nx-archweave 0.0.0-stage → 0.1.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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +265 -2
  3. package/dist/bin/review-verdict.js +330 -0
  4. package/dist/eslint/fsd-boundaries.d.ts +119 -0
  5. package/dist/eslint/fsd-boundaries.js +144 -0
  6. package/dist/eslint/index.d.ts +78 -0
  7. package/dist/eslint/index.js +256 -0
  8. package/dist/eslint/tsconfig-aliases.d.ts +18 -0
  9. package/dist/eslint/tsconfig-aliases.js +114 -0
  10. package/dist/generators/add-agent-rules/generator.js +550 -0
  11. package/dist/generators/add-agent-rules/render.js +46 -0
  12. package/dist/generators/add-backend/generator.js +784 -0
  13. package/dist/generators/add-backend/render.js +102 -0
  14. package/dist/generators/add-fsd-lite/generator.js +553 -0
  15. package/dist/generators/add-fsd-lite/render.js +72 -0
  16. package/dist/generators/add-github-templates/files/en/codeowners/.github/CODEOWNERS.template +4 -0
  17. package/dist/generators/add-github-templates/files/en/issue/.github/ISSUE_TEMPLATE/bug-report.yml.template +28 -0
  18. package/dist/generators/add-github-templates/files/en/issue/.github/ISSUE_TEMPLATE/feature-request.yml.template +17 -0
  19. package/dist/generators/add-github-templates/files/en/pr/.github/PULL_REQUEST_TEMPLATE.md.template +12 -0
  20. package/dist/generators/add-github-templates/files/ko/codeowners/.github/CODEOWNERS.template +4 -0
  21. package/dist/generators/add-github-templates/files/ko/issue/.github/ISSUE_TEMPLATE/bug-report.yml.template +28 -0
  22. package/dist/generators/add-github-templates/files/ko/issue/.github/ISSUE_TEMPLATE/feature-request.yml.template +17 -0
  23. package/dist/generators/add-github-templates/files/ko/pr/.github/PULL_REQUEST_TEMPLATE.md.template +12 -0
  24. package/dist/generators/add-github-templates/generator.js +125 -0
  25. package/dist/generators/add-github-templates/render.js +26 -0
  26. package/dist/generators/add-integration/generator.js +818 -0
  27. package/dist/generators/add-integration/render.js +34 -0
  28. package/dist/generators/add-review/generator.js +921 -0
  29. package/dist/generators/add-review/render.js +96 -0
  30. package/dist/generators/allow-builds/generator.js +436 -0
  31. package/dist/generators/allow-builds/render.js +82 -0
  32. package/dist/generators/doctor/generator.js +2431 -0
  33. package/dist/generators/doctor/integration-report.js +70 -0
  34. package/dist/generators/doctor/render.js +10 -0
  35. package/dist/generators/entity/generator.js +395 -0
  36. package/dist/generators/feature/generator.js +395 -0
  37. package/dist/generators/init/generator.js +3211 -0
  38. package/dist/generators/init/render.js +125 -0
  39. package/dist/generators/init/validation.js +74 -0
  40. package/dist/generators/install-integration/generator.js +1233 -0
  41. package/dist/generators/install-integration/render.js +128 -0
  42. package/dist/generators/page/generator.js +395 -0
  43. package/dist/generators/record-integration/generator.js +852 -0
  44. package/dist/generators/record-integration/render.js +31 -0
  45. package/dist/generators/shared/dry-run.js +12 -0
  46. package/dist/generators/shared/frontend-app.js +57 -0
  47. package/dist/generators/shared/generator.js +395 -0
  48. package/dist/generators/shared/project-type.js +39 -0
  49. package/dist/generators/shared/record-pipeline.js +34 -0
  50. package/dist/generators/shared/run-nx.js +24 -0
  51. package/dist/generators/shared/template-files.js +38 -0
  52. package/dist/generators/shared/toolkit-config-file.js +110 -0
  53. package/dist/generators/slice/core.js +185 -0
  54. package/dist/generators/slice/files/index/index.ts.template +14 -0
  55. package/dist/generators/slice/files/module/__name__.spec.ts.template +11 -0
  56. package/dist/generators/slice/files/module/__name__.ts.template +11 -0
  57. package/dist/generators/slice/files/segment/index.ts.template +20 -0
  58. package/dist/generators/slice/render.js +70 -0
  59. package/dist/generators/widget/generator.js +395 -0
  60. package/dist/index.d.ts +2 -0
  61. package/dist/index.js +680 -0
  62. package/dist/lib/nx-plugin.d.ts +2 -0
  63. package/dist/lib/nx-plugin.js +7 -0
  64. package/dist/runtime/integrations-composition-root.js +20 -0
  65. package/dist/runtime/node-command-runner.js +81 -0
  66. package/generators.json +85 -0
  67. package/package.json +95 -4
  68. package/src/generators/add-agent-rules/schema.json +43 -0
  69. package/src/generators/add-backend/schema.json +39 -0
  70. package/src/generators/add-fsd-lite/schema.json +43 -0
  71. package/src/generators/add-github-templates/schema.json +35 -0
  72. package/src/generators/add-integration/schema.json +35 -0
  73. package/src/generators/add-review/schema.json +72 -0
  74. package/src/generators/allow-builds/schema.json +20 -0
  75. package/src/generators/doctor/schema.json +20 -0
  76. package/src/generators/entity/schema.json +37 -0
  77. package/src/generators/feature/schema.json +37 -0
  78. package/src/generators/init/schema.json +98 -0
  79. package/src/generators/install-integration/schema.json +35 -0
  80. package/src/generators/page/schema.json +53 -0
  81. package/src/generators/record-integration/schema.json +26 -0
  82. package/src/generators/shared/schema.json +32 -0
  83. package/src/generators/widget/schema.json +45 -0
@@ -0,0 +1,125 @@
1
+ import { packageManagerCommands } from '@nx-archweave/template-engine';
2
+ import { renderAddFsdLiteReport } from "../add-fsd-lite/render.js";
3
+ import { renderAddAgentRulesReport } from "../add-agent-rules/render.js";
4
+ import { renderAddGithubTemplatesReport } from "../add-github-templates/render.js";
5
+ import { renderAddReviewReport } from "../add-review/render.js";
6
+ import { renderAddBackendBody } from "../add-backend/render.js";
7
+ const SECTION_TITLES = {
8
+ fsd: 'add-fsd-lite',
9
+ agentRules: 'add-agent-rules',
10
+ githubTemplates: 'add-github-templates',
11
+ review: 'add-review',
12
+ backend: 'add-backend',
13
+ };
14
+ function renderSectionReport(report) {
15
+ switch (report.kind) {
16
+ case 'fsd':
17
+ return renderAddFsdLiteReport(report.report);
18
+ case 'agentRules':
19
+ return renderAddAgentRulesReport(report.report);
20
+ case 'githubTemplates':
21
+ return renderAddGithubTemplatesReport(report.report);
22
+ case 'review':
23
+ return renderAddReviewReport(report.report);
24
+ case 'backend':
25
+ return renderAddBackendBody(report.report);
26
+ }
27
+ }
28
+ /** Whether a section left the run in a state that only a `git restore .` can cleanly
29
+ * undo — i.e. it aborted outright. Sections that merely proposed/skipped a file (no
30
+ * write happened) do not count: there is nothing of theirs to roll back. */
31
+ function sectionAborted(section) {
32
+ if (section.thrownError !== undefined)
33
+ return true;
34
+ if (section.report === null)
35
+ return false;
36
+ if (section.report.kind === 'fsd')
37
+ return section.report.report.aborted;
38
+ if (section.report.kind === 'review')
39
+ return section.report.report.workflowAction === 'aborted';
40
+ return false;
41
+ }
42
+ export function renderInitReport(report) {
43
+ const lines = [];
44
+ const backendSuffix = report.backend === 'none' ? '' : `, backend: ${report.backend}`;
45
+ const header = `init (preset: ${report.preset}, frontend: ${report.frontend}${backendSuffix})`;
46
+ lines.push(report.dryRun ? `${header} — dry run` : header);
47
+ if (report.refused) {
48
+ lines.push('');
49
+ lines.push('Refused: the working tree has uncommitted changes.');
50
+ lines.push(' init only runs against a clean working tree, so a partial run can always be undone');
51
+ lines.push(' with a single `git restore .` — commit or stash your changes, then rerun.');
52
+ return lines.join('\n');
53
+ }
54
+ for (const section of report.sections) {
55
+ // backend 'none' must leave the output byte-identical to the frontend-only
56
+ // era (silence guarantee) — a disabled backend section is omitted
57
+ // entirely, not shown as skipped.
58
+ if (section.id === 'backend' && !section.enabled)
59
+ continue;
60
+ lines.push('');
61
+ lines.push(`## ${SECTION_TITLES[section.id]}`);
62
+ if (!section.enabled) {
63
+ lines.push(section.id === 'fsd' && report.frontend === 'none'
64
+ ? ' skipped (backend-only workspace — no frontend to structure)'
65
+ : ' skipped (disabled for this run)');
66
+ continue;
67
+ }
68
+ if (section.thrownError !== undefined) {
69
+ lines.push(` aborted — unexpected error: ${section.thrownError}`);
70
+ lines.push(' Nothing was written for this section. Rerun add-fsd-lite directly once resolved.');
71
+ continue;
72
+ }
73
+ if (section.report !== null) {
74
+ lines.push(renderSectionReport(section.report));
75
+ }
76
+ }
77
+ if (report.config !== undefined && (report.config.action !== 'skipped' || report.config.notRecorded.length > 0)) {
78
+ lines.push('');
79
+ lines.push('## toolkit.config.json');
80
+ const fieldList = report.config.fields.join(', ');
81
+ switch (report.config.action) {
82
+ case 'created':
83
+ case 'updated':
84
+ lines.push(` ${report.dryRun ? 'would record' : 'recorded'} ${fieldList} (${report.config.action})`);
85
+ break;
86
+ case 'unchanged':
87
+ lines.push(` already records ${fieldList} (unchanged)`);
88
+ break;
89
+ case 'unrecognized':
90
+ lines.push(` not updated — the file is not a JSON object, so init left it alone (it never rewrites a shape it`);
91
+ lines.push(` does not recognize). Add ${fieldList} by hand so standalone reruns resolve the same values.`);
92
+ break;
93
+ case 'skipped':
94
+ break;
95
+ }
96
+ if (report.config.notRecorded.length > 0) {
97
+ lines.push(` not recorded: ${report.config.notRecorded.map((n) => n.field).join(', ')} — that section did not apply cleanly`);
98
+ lines.push(' this run (aborted, or written as an alternate file). Once resolved, record it with:');
99
+ const runNx = packageManagerCommands(report.packageManager ?? 'pnpm').runNx;
100
+ for (const entry of report.config.notRecorded)
101
+ lines.push(` ${runNx} g @clearlydev/nx-archweave:${entry.rerun}`);
102
+ }
103
+ }
104
+ const ranDirty = report.allowDirty === true && !report.cleanTree && !report.dryRun;
105
+ if (ranDirty) {
106
+ lines.push('');
107
+ lines.push('Note: --allowDirty was set and the working tree already had uncommitted changes —');
108
+ lines.push('`git restore .` also reverts those pre-existing changes, not only what this run wrote.');
109
+ }
110
+ const hadAbort = report.sections.some(sectionAborted);
111
+ if (!report.dryRun && hadAbort) {
112
+ lines.push('');
113
+ if (ranDirty) {
114
+ lines.push('One or more sections aborted. Everything this run wrote can be undone with:');
115
+ lines.push(' git restore .');
116
+ lines.push(' (--allowDirty: this also reverts the pre-existing uncommitted changes noted above.)');
117
+ }
118
+ else {
119
+ lines.push('One or more sections aborted. init never runs against a dirty tree (see above), so everything');
120
+ lines.push('this run wrote can be undone in one step:');
121
+ lines.push(' git restore .');
122
+ }
123
+ }
124
+ return lines.join('\n');
125
+ }
@@ -0,0 +1,74 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { spawnableCommand } from '@nx-archweave/shared';
3
+ export function createProcessExec() {
4
+ return (command, args, options) => {
5
+ // nx / actionlint may be .cmd shims on Windows, which Node cannot start without cmd.exe.
6
+ const spawnable = spawnableCommand(command, args);
7
+ const result = spawnSync(spawnable.command, spawnable.args, {
8
+ cwd: options?.cwd,
9
+ encoding: 'utf-8',
10
+ windowsVerbatimArguments: spawnable.windowsVerbatimArguments,
11
+ });
12
+ return { status: result.status ?? null, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };
13
+ };
14
+ }
15
+ /** Runs `exec`, catching anything it throws (e.g. a stub or an unforeseen environment
16
+ * failure) so a single check can never take down the rest of validation — the "never
17
+ * throws" half of the best-effort contract applies even to the injected dependency, not
18
+ * just to non-zero exit codes. */
19
+ function safeExec(exec, command, args, options) {
20
+ try {
21
+ return exec(command, args, options);
22
+ }
23
+ catch (error) {
24
+ return { status: null, stdout: '', stderr: error instanceof Error ? error.message : String(error) };
25
+ }
26
+ }
27
+ /** Post-flush, best-effort validation: never throws, only
28
+ * reports via console. Runs after the generator's `GeneratorCallback` fires, once every
29
+ * file this run wrote is actually on disk. Neither actionlint nor nx are added as
30
+ * dependencies — both are invoked as external binaries, detected at call time. */
31
+ export function runPostInitValidation(input, exec) {
32
+ console.log('');
33
+ console.log('Post-run validation (best-effort):');
34
+ if (input.workflowPaths.length === 0) {
35
+ console.log(' actionlint: skipped (no GitHub Actions workflow files were written this run)');
36
+ }
37
+ else {
38
+ const versionCheck = safeExec(exec, 'actionlint', ['--version'], { cwd: input.root });
39
+ if (versionCheck.status !== 0) {
40
+ console.log(' actionlint: not found on PATH — skipped.');
41
+ console.log(' Install it from https://github.com/rhysd/actionlint to validate workflow files locally.');
42
+ }
43
+ else {
44
+ const lintResult = safeExec(exec, 'actionlint', input.workflowPaths, { cwd: input.root });
45
+ if (lintResult.status === 0) {
46
+ console.log(` actionlint: passed (${input.workflowPaths.join(', ')})`);
47
+ }
48
+ else {
49
+ console.log(' actionlint: reported issues —');
50
+ for (const line of (lintResult.stdout || lintResult.stderr).split('\n')) {
51
+ if (line.length > 0)
52
+ console.log(` ${line}`);
53
+ }
54
+ }
55
+ }
56
+ }
57
+ const nxVersionCheck = safeExec(exec, 'nx', ['--version'], { cwd: input.root });
58
+ if (nxVersionCheck.status !== 0) {
59
+ console.log(' nx graph: nx not found on PATH — skipped.');
60
+ console.log(' Run it via your package manager instead, e.g. `pnpm nx graph`, `yarn nx graph`, `bun nx graph` or `npm exec nx graph`.');
61
+ return;
62
+ }
63
+ const graphResult = safeExec(exec, 'nx', ['graph', `--file=${input.graphOutputFile}`], { cwd: input.root });
64
+ if (graphResult.status === 0) {
65
+ console.log(` nx graph: valid (written to ${input.graphOutputFile})`);
66
+ }
67
+ else {
68
+ console.log(' nx graph: failed —');
69
+ for (const line of (graphResult.stdout || graphResult.stderr).split('\n')) {
70
+ if (line.length > 0)
71
+ console.log(` ${line}`);
72
+ }
73
+ }
74
+ }