@clearlydev/nx-archweave 0.3.2 → 0.4.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 +1 -1
- package/dist/bin/review-verdict.js +8 -249
- package/dist/eslint/index.js +28 -321
- package/dist/generators/_chunks/chunk-2WSX5YNB.js +274 -0
- package/dist/generators/_chunks/chunk-34V6HAJT.js +55 -0
- package/dist/generators/_chunks/chunk-3A6RZUCZ.js +114 -0
- package/dist/generators/_chunks/chunk-47T7NOPP.js +30 -0
- package/dist/generators/_chunks/chunk-4FJ7CLEU.js +189 -0
- package/dist/generators/_chunks/chunk-5MI3O4VZ.js +99 -0
- package/dist/generators/_chunks/chunk-6ZTIUBB2.js +139 -0
- package/dist/generators/_chunks/chunk-AIJCJ7JK.js +203 -0
- package/dist/generators/_chunks/chunk-ALSXKTLM.js +1098 -0
- package/dist/generators/_chunks/chunk-AQHV7DJS.js +656 -0
- package/dist/generators/_chunks/chunk-C2VVUWBA.js +386 -0
- package/dist/generators/_chunks/chunk-EXYZLL7A.js +234 -0
- package/dist/generators/_chunks/chunk-FQHFT5IH.js +50 -0
- package/dist/generators/_chunks/chunk-H222FPLK.js +80 -0
- package/dist/generators/_chunks/chunk-IIDOBI42.js +616 -0
- package/dist/generators/_chunks/chunk-L2RZ2LBO.js +132 -0
- package/dist/generators/_chunks/chunk-MQNQJOWA.js +217 -0
- package/dist/generators/_chunks/chunk-QQNDYJTR.js +243 -0
- package/dist/generators/_chunks/chunk-SFXU6IUS.js +0 -0
- package/dist/generators/_chunks/chunk-SNBIVIMI.js +89 -0
- package/dist/generators/_chunks/chunk-TUN34LAQ.js +8 -0
- package/dist/generators/_chunks/chunk-TXAQ2GJC.js +20 -0
- package/dist/generators/_chunks/chunk-U6LAFHSF.js +49 -0
- package/dist/generators/_chunks/chunk-URV6FLUH.js +73 -0
- package/dist/generators/_chunks/chunk-YNMLB4DL.js +25 -0
- package/dist/generators/_chunks/chunk-YY2UESLM.js +282 -0
- package/dist/generators/add-agent-rules/generator.js +11 -842
- package/dist/generators/add-backend/generator.js +11 -906
- package/dist/generators/add-fsd-lite/generator.js +12 -801
- package/dist/generators/add-github-templates/generator.js +13 -116
- package/dist/generators/add-integration/generator.js +15 -743
- package/dist/generators/add-review/generator.js +12 -1231
- package/dist/generators/allow-builds/generator.js +7 -71
- package/dist/generators/doctor/generator.js +106 -2044
- package/dist/generators/entity/generator.js +15 -604
- package/dist/generators/feature/generator.js +15 -604
- package/dist/generators/init/generator.js +68 -3376
- package/dist/generators/install-integration/generator.js +35 -871
- package/dist/generators/page/generator.js +15 -604
- package/dist/generators/record-integration/generator.js +12 -778
- package/dist/generators/shared/generator.js +15 -604
- package/dist/generators/widget/generator.js +15 -604
- package/dist/index.js +5 -663
- package/package.json +1 -1
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SEGMENT_NAME_PATTERN,
|
|
3
|
+
isEssenceSegmentName,
|
|
4
|
+
isUsableSliceApiName,
|
|
5
|
+
profileById,
|
|
6
|
+
resolveFrontendApp,
|
|
7
|
+
resolveSlicePublicApiName
|
|
8
|
+
} from "./chunk-2WSX5YNB.js";
|
|
9
|
+
import {
|
|
10
|
+
generatorFilesDir,
|
|
11
|
+
renderTemplateFiles
|
|
12
|
+
} from "./chunk-YNMLB4DL.js";
|
|
13
|
+
import {
|
|
14
|
+
RECORDED_FRONTENDS,
|
|
15
|
+
readToolkitConfig,
|
|
16
|
+
recordedFrontends,
|
|
17
|
+
resolveLocaleOption
|
|
18
|
+
} from "./chunk-EXYZLL7A.js";
|
|
19
|
+
|
|
20
|
+
// src/generators/slice/core.ts
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
function composeSlice(input) {
|
|
23
|
+
const files = generatorFilesDir("slice", import.meta.url);
|
|
24
|
+
const directory = `${input.sourceRoot}/${input.layerDirName}/${input.group === void 0 ? "" : `${input.group}/`}${input.name}`;
|
|
25
|
+
const shared = input.layer === "shared";
|
|
26
|
+
const values = {
|
|
27
|
+
name: input.name,
|
|
28
|
+
publicApiName: input.publicApiName,
|
|
29
|
+
layer: input.layer,
|
|
30
|
+
locale: input.locale,
|
|
31
|
+
modulePath: shared ? `./${input.name}` : `./model/${input.name}`
|
|
32
|
+
};
|
|
33
|
+
const module = renderTemplateFiles(join(files, "module"), shared ? directory : `${directory}/model`, values).filter((file) => input.withSpec !== false || !file.filePath.endsWith(".spec.ts")).sort((a, b) => Number(a.filePath.endsWith(".spec.ts")) - Number(b.filePath.endsWith(".spec.ts")));
|
|
34
|
+
const segments = shared ? [] : Array.from(new Set(input.segments)).filter((segment) => segment !== "model").flatMap((segment) => renderTemplateFiles(join(files, "segment"), `${directory}/${segment}`, { ...values, segment }));
|
|
35
|
+
return {
|
|
36
|
+
directory,
|
|
37
|
+
publicApiName: input.publicApiName,
|
|
38
|
+
files: [...renderTemplateFiles(join(files, "index"), directory, values), ...module, ...segments]
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
var KEBAB_CASE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
42
|
+
function layerDirNameFor(layer, frontend) {
|
|
43
|
+
return profileById(frontend).layerDirs[layer] ?? layer;
|
|
44
|
+
}
|
|
45
|
+
function layerDirFor(layer, sourceRoot, frontend = "react-vite") {
|
|
46
|
+
return `${sourceRoot}/${layerDirNameFor(layer, frontend)}`;
|
|
47
|
+
}
|
|
48
|
+
function resolveFrontendForApp(option, config, detected) {
|
|
49
|
+
if (option !== void 0) return option;
|
|
50
|
+
const recorded = config?.["frontend"];
|
|
51
|
+
if (typeof recorded === "string" && RECORDED_FRONTENDS.includes(recorded) && recorded !== "none") {
|
|
52
|
+
return recorded;
|
|
53
|
+
}
|
|
54
|
+
return detected;
|
|
55
|
+
}
|
|
56
|
+
function listFilesUnder(tree, dir, prefix = "") {
|
|
57
|
+
return tree.children(dir).flatMap((child) => {
|
|
58
|
+
const path = `${dir}/${child}`;
|
|
59
|
+
return tree.isFile(path) ? [`${prefix}${child}`] : listFilesUnder(tree, path, `${prefix}${child}/`);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function computeSliceAction(tree, plan) {
|
|
63
|
+
if (!tree.exists(plan.directory)) return "created";
|
|
64
|
+
const expectedNames = plan.files.map((f) => f.filePath.slice(plan.directory.length + 1)).sort();
|
|
65
|
+
const actualNames = listFilesUnder(tree, plan.directory).sort();
|
|
66
|
+
if (actualNames.length !== expectedNames.length || !actualNames.every((n, i) => n === expectedNames[i])) {
|
|
67
|
+
return "skipped";
|
|
68
|
+
}
|
|
69
|
+
const allMatch = plan.files.every((f) => tree.read(f.filePath, "utf-8") === f.content);
|
|
70
|
+
return allMatch ? "unchanged" : "skipped";
|
|
71
|
+
}
|
|
72
|
+
function refusal(reason, dryRun, layer, name, app, extra = {}) {
|
|
73
|
+
const layerDir = layerDirFor(layer, app.sourceRoot);
|
|
74
|
+
return {
|
|
75
|
+
dryRun,
|
|
76
|
+
layer,
|
|
77
|
+
name,
|
|
78
|
+
project: app.project,
|
|
79
|
+
layerDir,
|
|
80
|
+
directory: `${layerDir}/${name}`,
|
|
81
|
+
publicApiName: null,
|
|
82
|
+
refused: true,
|
|
83
|
+
refusalReason: reason,
|
|
84
|
+
action: null,
|
|
85
|
+
files: [],
|
|
86
|
+
...extra
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function runFsdSlice(tree, layer, options) {
|
|
90
|
+
const dryRun = options.dryRun ?? false;
|
|
91
|
+
const unresolved = { project: null, sourceRoot: "<app>/src" };
|
|
92
|
+
if (!KEBAB_CASE.test(options.name)) {
|
|
93
|
+
return refusal("invalid-name", dryRun, layer, options.name, unresolved);
|
|
94
|
+
}
|
|
95
|
+
if (!isUsableSliceApiName(resolveSlicePublicApiName(options.name, options.publicApiName))) {
|
|
96
|
+
return refusal("invalid-public-api-name", dryRun, layer, options.name, unresolved);
|
|
97
|
+
}
|
|
98
|
+
if (layer === "shared" && isEssenceSegmentName(options.name)) {
|
|
99
|
+
return refusal("segment-by-essence", dryRun, layer, options.name, unresolved);
|
|
100
|
+
}
|
|
101
|
+
const segments = Array.from(new Set(options.segments ?? []));
|
|
102
|
+
if (segments.length > 0 && layer === "shared") {
|
|
103
|
+
return refusal("segments-on-shared", dryRun, layer, options.name, unresolved);
|
|
104
|
+
}
|
|
105
|
+
const badSegment = segments.find((segment) => !SEGMENT_NAME_PATTERN.test(segment));
|
|
106
|
+
if (badSegment !== void 0) return refusal("invalid-segment", dryRun, layer, options.name, unresolved, { detail: badSegment });
|
|
107
|
+
const essenceSegment = segments.find((segment) => isEssenceSegmentName(segment));
|
|
108
|
+
if (essenceSegment !== void 0) return refusal("segment-by-essence", dryRun, layer, options.name, unresolved, { detail: essenceSegment });
|
|
109
|
+
if (options.group !== void 0 && layer === "shared") return refusal("group-on-shared", dryRun, layer, options.name, unresolved);
|
|
110
|
+
if (options.group !== void 0 && (!KEBAB_CASE.test(options.group) || SEGMENT_FOLDERS.includes(options.group) || isEssenceSegmentName(options.group))) {
|
|
111
|
+
return refusal("invalid-group", dryRun, layer, options.name, unresolved, { detail: options.group });
|
|
112
|
+
}
|
|
113
|
+
const app = resolveFrontendApp(tree, options.project);
|
|
114
|
+
if (app.kind === "not-found") return refusal("project-not-found", dryRun, layer, options.name, { project: app.project, sourceRoot: unresolved.sourceRoot });
|
|
115
|
+
if (app.kind === "ambiguous") {
|
|
116
|
+
return refusal("ambiguous-frontend", dryRun, layer, options.name, unresolved, { candidates: app.candidates, recordedFrontends: recordedFrontends(readToolkitConfig(tree)) });
|
|
117
|
+
}
|
|
118
|
+
if (app.kind === "invalid-project-json") return refusal("invalid-project-json", dryRun, layer, options.name, unresolved, { detail: app.detail });
|
|
119
|
+
if (app.kind === "none") return refusal("no-frontend-app", dryRun, layer, options.name, unresolved, { candidates: app.otherProjects });
|
|
120
|
+
const config = readToolkitConfig(tree);
|
|
121
|
+
const frontend = resolveFrontendForApp(options.frontend, config, app.framework);
|
|
122
|
+
const layerDir = layerDirFor(layer, app.sourceRoot, frontend);
|
|
123
|
+
const locale = resolveLocaleOption(options.locale, config);
|
|
124
|
+
const requested = options.unitTestRunner !== void 0 && options.unitTestRunner !== "auto" ? options.unitTestRunner : recordedUnitTestRunner(config);
|
|
125
|
+
const runner = requested ?? detectUnitTestRunner(tree, app.root);
|
|
126
|
+
const plan = composeSlice({
|
|
127
|
+
layer,
|
|
128
|
+
name: options.name,
|
|
129
|
+
publicApiName: resolveSlicePublicApiName(options.name, options.publicApiName),
|
|
130
|
+
locale,
|
|
131
|
+
sourceRoot: app.sourceRoot,
|
|
132
|
+
layerDirName: layerDirNameFor(layer, frontend),
|
|
133
|
+
segments,
|
|
134
|
+
group: options.group,
|
|
135
|
+
withSpec: runner !== "none"
|
|
136
|
+
});
|
|
137
|
+
const action = computeSliceAction(tree, plan);
|
|
138
|
+
if (action === "created" && !dryRun) {
|
|
139
|
+
for (const file of plan.files) tree.write(file.filePath, file.content);
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
dryRun,
|
|
143
|
+
layer,
|
|
144
|
+
name: options.name,
|
|
145
|
+
project: app.project,
|
|
146
|
+
layerDir,
|
|
147
|
+
directory: plan.directory,
|
|
148
|
+
publicApiName: plan.publicApiName,
|
|
149
|
+
refused: false,
|
|
150
|
+
refusalReason: null,
|
|
151
|
+
action,
|
|
152
|
+
files: plan.files,
|
|
153
|
+
...runner === "none" ? { specSkipped: requested === "none" ? "none-requested" : "no-test-runner" } : {}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
var SEGMENT_FOLDERS = ["ui", "model", "api", "lib", "config"];
|
|
157
|
+
function recordedUnitTestRunner(config) {
|
|
158
|
+
const fsd = config?.["fsd"];
|
|
159
|
+
const value = typeof fsd === "object" && fsd !== null ? fsd["unitTestRunner"] : void 0;
|
|
160
|
+
return value === "jest" || value === "vitest" || value === "none" ? value : void 0;
|
|
161
|
+
}
|
|
162
|
+
function hasDependency(tree, manifest, name) {
|
|
163
|
+
const raw = tree.read(manifest, "utf-8");
|
|
164
|
+
if (raw === null) return false;
|
|
165
|
+
try {
|
|
166
|
+
const parsed = JSON.parse(raw);
|
|
167
|
+
return parsed["dependencies"]?.[name] !== void 0 || parsed["devDependencies"]?.[name] !== void 0;
|
|
168
|
+
} catch {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function detectUnitTestRunner(tree, projectRoot) {
|
|
173
|
+
const prefix = projectRoot === "" || projectRoot === "." ? "" : `${projectRoot}/`;
|
|
174
|
+
const project = tree.read(`${prefix}project.json`, "utf-8");
|
|
175
|
+
if (project !== null) {
|
|
176
|
+
try {
|
|
177
|
+
const targets = JSON.parse(project).targets ?? {};
|
|
178
|
+
for (const target of Object.values(targets)) {
|
|
179
|
+
if (target?.executor?.startsWith("@nx/jest:")) return "jest";
|
|
180
|
+
if (target?.executor?.startsWith("@nx/vite:test") || target?.executor?.startsWith("@nx/vitest:")) return "vitest";
|
|
181
|
+
}
|
|
182
|
+
} catch {
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
for (const dir of prefix === "" ? [""] : [prefix, ""]) {
|
|
186
|
+
if (["ts", "mts", "cts", "js", "mjs", "cjs"].some((ext) => tree.exists(`${dir}jest.config.${ext}`))) return "jest";
|
|
187
|
+
if (["ts", "mts", "js", "mjs"].some((ext) => tree.exists(`${dir}vitest.config.${ext}`) || tree.exists(`${dir}vitest.workspace.${ext}`))) return "vitest";
|
|
188
|
+
for (const ext of ["ts", "mts", "js", "mjs"]) {
|
|
189
|
+
const vite = tree.read(`${dir}vite.config.${ext}`, "utf-8");
|
|
190
|
+
if (vite !== null && /\btest\s*:/.test(vite)) return "vitest";
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
for (const manifest of prefix === "" ? ["package.json"] : [`${prefix}package.json`, "package.json"]) {
|
|
194
|
+
if (hasDependency(tree, manifest, "vitest")) return "vitest";
|
|
195
|
+
if (hasDependency(tree, manifest, "jest")) return "jest";
|
|
196
|
+
}
|
|
197
|
+
return "none";
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export {
|
|
201
|
+
runFsdSlice,
|
|
202
|
+
detectUnitTestRunner
|
|
203
|
+
};
|