@clearlydev/nx-archweave 0.3.1 → 0.3.3
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/dist/bin/review-verdict.js +5 -248
- 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-5MI3O4VZ.js +99 -0
- package/dist/generators/_chunks/chunk-67INEVWL.js +1068 -0
- package/dist/generators/_chunks/chunk-6ZTIUBB2.js +139 -0
- package/dist/generators/_chunks/chunk-AIJCJ7JK.js +203 -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-JHRTVURZ.js +189 -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 +74 -2042
- 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 +2 -2
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_BOUNDARY_TAGS
|
|
3
|
+
} from "./chunk-6ZTIUBB2.js";
|
|
4
|
+
|
|
5
|
+
// ../templates/dist/backend/shared-types.js
|
|
6
|
+
function sharedTypesIndexContent() {
|
|
7
|
+
return `export * from './lib/api-types.js';
|
|
8
|
+
`;
|
|
9
|
+
}
|
|
10
|
+
function sharedTypesApiTypesContent() {
|
|
11
|
+
return [
|
|
12
|
+
"// Types shared between the frontend and the backend live here.",
|
|
13
|
+
"// Example: the api app returns this from GET /api/health, and the",
|
|
14
|
+
"// frontend consumes the same shape \u2014 one definition, no drift.",
|
|
15
|
+
"export interface ApiHealthResponse {",
|
|
16
|
+
" status: 'ok';",
|
|
17
|
+
"}",
|
|
18
|
+
""
|
|
19
|
+
].join("\n");
|
|
20
|
+
}
|
|
21
|
+
function sharedTypesPackageJsonContent(packageName, sharedTag = "scope:shared") {
|
|
22
|
+
return `${JSON.stringify({
|
|
23
|
+
name: packageName,
|
|
24
|
+
version: "0.0.1",
|
|
25
|
+
private: true,
|
|
26
|
+
type: "module",
|
|
27
|
+
main: "./src/index.ts",
|
|
28
|
+
types: "./src/index.ts",
|
|
29
|
+
exports: {
|
|
30
|
+
".": {
|
|
31
|
+
types: "./src/index.ts",
|
|
32
|
+
import: "./src/index.ts",
|
|
33
|
+
default: "./src/index.ts"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
nx: {
|
|
37
|
+
projectType: "library",
|
|
38
|
+
tags: [sharedTag],
|
|
39
|
+
targets: {}
|
|
40
|
+
}
|
|
41
|
+
}, null, 2)}
|
|
42
|
+
`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ../template-engine/dist/backend/compose-backend-wiring.js
|
|
46
|
+
var DEFAULT_SHARED_TYPES_ROOT = "libs/shared-types";
|
|
47
|
+
function readSharedTypesConfig(config) {
|
|
48
|
+
const value = config?.["sharedTypes"];
|
|
49
|
+
if (value === false)
|
|
50
|
+
return false;
|
|
51
|
+
if (typeof value !== "object" || value === null)
|
|
52
|
+
return { path: DEFAULT_SHARED_TYPES_ROOT };
|
|
53
|
+
const record = value;
|
|
54
|
+
const path = typeof record["path"] === "string" && record["path"].trim() !== "" ? record["path"].replace(/\/+$/, "") : DEFAULT_SHARED_TYPES_ROOT;
|
|
55
|
+
const importPath = typeof record["importPath"] === "string" && record["importPath"].trim() !== "" ? record["importPath"] : void 0;
|
|
56
|
+
return importPath === void 0 ? { path } : { path, importPath };
|
|
57
|
+
}
|
|
58
|
+
function composeBackendWiring(input) {
|
|
59
|
+
const scoped = /^@([^/]+)\//.exec(input.workspaceName);
|
|
60
|
+
const scope = scoped ? `@${scoped[1]}` : `@${input.workspaceName.split("/").pop() || "workspace"}`;
|
|
61
|
+
const sharedTypesRoot = input.sharedTypes?.path ?? DEFAULT_SHARED_TYPES_ROOT;
|
|
62
|
+
const sharedTypesPackageName = input.sharedTypes?.importPath ?? `${scope}/shared-types`;
|
|
63
|
+
const tagByRole = input.tags ?? DEFAULT_BOUNDARY_TAGS;
|
|
64
|
+
return {
|
|
65
|
+
sharedTypesFiles: [
|
|
66
|
+
{ filePath: `${sharedTypesRoot}/package.json`, content: sharedTypesPackageJsonContent(sharedTypesPackageName, tagByRole.shared) },
|
|
67
|
+
{ filePath: `${sharedTypesRoot}/src/index.ts`, content: sharedTypesIndexContent() },
|
|
68
|
+
{ filePath: `${sharedTypesRoot}/src/lib/api-types.ts`, content: sharedTypesApiTypesContent() }
|
|
69
|
+
],
|
|
70
|
+
sharedTypesPackageName,
|
|
71
|
+
sharedTypesRoot,
|
|
72
|
+
tagByRole
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function addSharedTypesNpmWorkspace(packageJsonText, entry = DEFAULT_SHARED_TYPES_ROOT) {
|
|
76
|
+
let parsed;
|
|
77
|
+
try {
|
|
78
|
+
parsed = JSON.parse(packageJsonText);
|
|
79
|
+
} catch {
|
|
80
|
+
return { status: "unrecognized" };
|
|
81
|
+
}
|
|
82
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
83
|
+
return { status: "unrecognized" };
|
|
84
|
+
const pkg = parsed;
|
|
85
|
+
const field = pkg["workspaces"];
|
|
86
|
+
let target;
|
|
87
|
+
if (field === void 0) {
|
|
88
|
+
target = [];
|
|
89
|
+
} else if (Array.isArray(field)) {
|
|
90
|
+
target = field;
|
|
91
|
+
} else if (field !== null && typeof field === "object" && Array.isArray(field.packages)) {
|
|
92
|
+
target = field.packages;
|
|
93
|
+
} else {
|
|
94
|
+
return { status: "unrecognized" };
|
|
95
|
+
}
|
|
96
|
+
const parentGlob = `${entry.split("/").slice(0, -1).join("/")}/*`;
|
|
97
|
+
if (target.some((existing) => existing === entry || existing === parentGlob))
|
|
98
|
+
return { status: "present" };
|
|
99
|
+
const surgical = insertSharedTypesWorkspace(packageJsonText, field === void 0 ? "absent" : Array.isArray(field) ? "array" : "object", JSON.stringify(entry));
|
|
100
|
+
if (surgical !== null)
|
|
101
|
+
return { status: "added", text: surgical };
|
|
102
|
+
if (field === void 0)
|
|
103
|
+
pkg["workspaces"] = target;
|
|
104
|
+
target.push(entry);
|
|
105
|
+
const indent = /\n([ \t]+)"/.exec(packageJsonText)?.[1] ?? " ";
|
|
106
|
+
const trailing = packageJsonText.endsWith("\n") ? "\n" : "";
|
|
107
|
+
return { status: "added", text: `${JSON.stringify(pkg, null, indent)}${trailing}` };
|
|
108
|
+
}
|
|
109
|
+
function skipJsonValue(text, start) {
|
|
110
|
+
if (text[start] === '"') {
|
|
111
|
+
let i = start + 1;
|
|
112
|
+
while (i < text.length && text[i] !== '"')
|
|
113
|
+
i += text[i] === "\\" ? 2 : 1;
|
|
114
|
+
return i + 1;
|
|
115
|
+
}
|
|
116
|
+
if (text[start] === "[" || text[start] === "{") {
|
|
117
|
+
let depth = 0;
|
|
118
|
+
let i = start;
|
|
119
|
+
while (i < text.length) {
|
|
120
|
+
const c = text[i];
|
|
121
|
+
if (c === '"') {
|
|
122
|
+
i = skipJsonValue(text, i);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (c === "[" || c === "{")
|
|
126
|
+
depth++;
|
|
127
|
+
if (c === "]" || c === "}") {
|
|
128
|
+
depth--;
|
|
129
|
+
if (depth === 0)
|
|
130
|
+
return i + 1;
|
|
131
|
+
}
|
|
132
|
+
i++;
|
|
133
|
+
}
|
|
134
|
+
return -1;
|
|
135
|
+
}
|
|
136
|
+
const literal = /^[^,}\]\s]+/.exec(text.slice(start));
|
|
137
|
+
return literal ? start + literal[0].length : -1;
|
|
138
|
+
}
|
|
139
|
+
function objectMembers(text, open) {
|
|
140
|
+
const members = [];
|
|
141
|
+
let i = open + 1;
|
|
142
|
+
for (; ; ) {
|
|
143
|
+
while (/[\s,]/.test(text[i] ?? ""))
|
|
144
|
+
i++;
|
|
145
|
+
if (text[i] === "}")
|
|
146
|
+
return members;
|
|
147
|
+
if (text[i] !== '"')
|
|
148
|
+
return null;
|
|
149
|
+
const keyEnd = skipJsonValue(text, i);
|
|
150
|
+
const key = JSON.parse(text.slice(i, keyEnd));
|
|
151
|
+
i = keyEnd;
|
|
152
|
+
while (/\s/.test(text[i] ?? ""))
|
|
153
|
+
i++;
|
|
154
|
+
if (text[i] !== ":")
|
|
155
|
+
return null;
|
|
156
|
+
i++;
|
|
157
|
+
while (/\s/.test(text[i] ?? ""))
|
|
158
|
+
i++;
|
|
159
|
+
const valueEnd = skipJsonValue(text, i);
|
|
160
|
+
if (valueEnd === -1)
|
|
161
|
+
return null;
|
|
162
|
+
members.push({ key, valueStart: i, valueEnd });
|
|
163
|
+
i = valueEnd;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function appendToArray(text, open, close, eol, quoted) {
|
|
167
|
+
const inner = text.slice(open + 1, close - 1);
|
|
168
|
+
if (inner.trim() === "")
|
|
169
|
+
return `${text.slice(0, open + 1)}${quoted}${text.slice(close - 1)}`;
|
|
170
|
+
if (!inner.includes("\n")) {
|
|
171
|
+
const body = inner.replace(/\s+$/, "");
|
|
172
|
+
return `${text.slice(0, open + 1)}${body}, ${quoted}${inner.slice(body.length)}${text.slice(close - 1)}`;
|
|
173
|
+
}
|
|
174
|
+
const lastEntryLineStart = text.lastIndexOf("\n", open + 1 + inner.trimEnd().length - 1) + 1;
|
|
175
|
+
const itemIndent = /^[ \t]*/.exec(text.slice(lastEntryLineStart))?.[0] ?? " ";
|
|
176
|
+
const bodyEnd = open + 1 + inner.trimEnd().length;
|
|
177
|
+
return `${text.slice(0, bodyEnd)},${eol}${itemIndent}${quoted}${text.slice(bodyEnd)}`;
|
|
178
|
+
}
|
|
179
|
+
function insertSharedTypesWorkspace(text, form, quoted) {
|
|
180
|
+
const eol = text.includes("\r\n") ? "\r\n" : "\n";
|
|
181
|
+
const rootOpen = text.indexOf("{");
|
|
182
|
+
if (rootOpen === -1)
|
|
183
|
+
return null;
|
|
184
|
+
const members = objectMembers(text, rootOpen);
|
|
185
|
+
if (members === null)
|
|
186
|
+
return null;
|
|
187
|
+
const workspaces = members.find((member) => member.key === "workspaces");
|
|
188
|
+
if (form === "absent") {
|
|
189
|
+
const last = members[members.length - 1];
|
|
190
|
+
const indent = /\n([ \t]+)"/.exec(text)?.[1] ?? " ";
|
|
191
|
+
if (last === void 0) {
|
|
192
|
+
const close = skipJsonValue(text, rootOpen) - 1;
|
|
193
|
+
return `${text.slice(0, rootOpen + 1)}${eol}${indent}"workspaces": [${quoted}]${eol}${text.slice(close)}`;
|
|
194
|
+
}
|
|
195
|
+
return `${text.slice(0, last.valueEnd)},${eol}${indent}"workspaces": [${quoted}]${text.slice(last.valueEnd)}`;
|
|
196
|
+
}
|
|
197
|
+
if (workspaces === void 0)
|
|
198
|
+
return null;
|
|
199
|
+
if (form === "array") {
|
|
200
|
+
if (text[workspaces.valueStart] !== "[")
|
|
201
|
+
return null;
|
|
202
|
+
return appendToArray(text, workspaces.valueStart, workspaces.valueEnd, eol, quoted);
|
|
203
|
+
}
|
|
204
|
+
if (text[workspaces.valueStart] !== "{")
|
|
205
|
+
return null;
|
|
206
|
+
const packages = objectMembers(text, workspaces.valueStart)?.find((member) => member.key === "packages");
|
|
207
|
+
if (packages === void 0 || text[packages.valueStart] !== "[")
|
|
208
|
+
return null;
|
|
209
|
+
return appendToArray(text, packages.valueStart, packages.valueEnd, eol, quoted);
|
|
210
|
+
}
|
|
211
|
+
function addSharedTypesWorkspaceGlob(yamlText, entry = DEFAULT_SHARED_TYPES_ROOT) {
|
|
212
|
+
const escape = (value) => value.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
|
|
213
|
+
const parentGlob = `${entry.split("/").slice(0, -1).join("/")}/*`;
|
|
214
|
+
if (new RegExp(`^\\s*-\\s*['"]?(${escape(entry)}|${escape(parentGlob)})['"]?\\s*$`, "m").test(yamlText)) {
|
|
215
|
+
return { status: "present" };
|
|
216
|
+
}
|
|
217
|
+
const lines = yamlText.split("\n");
|
|
218
|
+
const packagesIndex = lines.findIndex((line) => /^packages:\s*$/.test(line));
|
|
219
|
+
if (packagesIndex === -1)
|
|
220
|
+
return { status: "unrecognized" };
|
|
221
|
+
let lastEntry = packagesIndex;
|
|
222
|
+
for (let i = packagesIndex + 1; i < lines.length; i++) {
|
|
223
|
+
if (/^\s+-\s+\S/.test(lines[i])) {
|
|
224
|
+
lastEntry = i;
|
|
225
|
+
} else if (lines[i].trim() === "") {
|
|
226
|
+
continue;
|
|
227
|
+
} else {
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (lastEntry === packagesIndex)
|
|
232
|
+
return { status: "unrecognized" };
|
|
233
|
+
const indent = /^(\s+)-/.exec(lines[lastEntry])?.[1] ?? " ";
|
|
234
|
+
lines.splice(lastEntry + 1, 0, `${indent}- '${entry}'`);
|
|
235
|
+
return { status: "added", text: lines.join("\n") };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export {
|
|
239
|
+
readSharedTypesConfig,
|
|
240
|
+
composeBackendWiring,
|
|
241
|
+
addSharedTypesNpmWorkspace,
|
|
242
|
+
addSharedTypesWorkspaceGlob
|
|
243
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {
|
|
2
|
+
generatorFilesDir,
|
|
3
|
+
renderTemplateFiles
|
|
4
|
+
} from "./chunk-YNMLB4DL.js";
|
|
5
|
+
import {
|
|
6
|
+
resolveDryRun
|
|
7
|
+
} from "./chunk-TUN34LAQ.js";
|
|
8
|
+
import {
|
|
9
|
+
readToolkitConfig,
|
|
10
|
+
resolveLocaleOption
|
|
11
|
+
} from "./chunk-EXYZLL7A.js";
|
|
12
|
+
|
|
13
|
+
// src/generators/add-github-templates/generator.ts
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
|
|
16
|
+
// src/generators/add-github-templates/render.ts
|
|
17
|
+
var ACTION_LINES = {
|
|
18
|
+
created: "created",
|
|
19
|
+
unchanged: "unchanged (already matches the generated version)",
|
|
20
|
+
skipped: "left as-is (a different file already exists there \u2014 never overwritten)"
|
|
21
|
+
};
|
|
22
|
+
function renderAddGithubTemplatesReport(report) {
|
|
23
|
+
const lines = [];
|
|
24
|
+
if (report.files.length === 0) {
|
|
25
|
+
lines.push("add-github-templates: nothing selected (issue/pr/codeowners all false) \u2014 no files to install.");
|
|
26
|
+
return lines.join("\n");
|
|
27
|
+
}
|
|
28
|
+
if (report.dryRun) {
|
|
29
|
+
lines.push("add-github-templates dry-run \u2014 no files were written.");
|
|
30
|
+
lines.push("");
|
|
31
|
+
for (const file of report.files) {
|
|
32
|
+
lines.push(`${file.filePath}:`);
|
|
33
|
+
lines.push(file.content);
|
|
34
|
+
lines.push("");
|
|
35
|
+
}
|
|
36
|
+
lines.push("Effective decision:");
|
|
37
|
+
}
|
|
38
|
+
for (const file of report.files) {
|
|
39
|
+
lines.push(` ${file.filePath}: ${ACTION_LINES[file.action]}`);
|
|
40
|
+
}
|
|
41
|
+
return lines.join("\n");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// src/generators/add-github-templates/generator.ts
|
|
45
|
+
var BUG_REPORT_PATH = ".github/ISSUE_TEMPLATE/bug-report.yml";
|
|
46
|
+
var FEATURE_REQUEST_PATH = ".github/ISSUE_TEMPLATE/feature-request.yml";
|
|
47
|
+
var PULL_REQUEST_TEMPLATE_PATH = ".github/PULL_REQUEST_TEMPLATE.md";
|
|
48
|
+
var CODEOWNERS_PATH = ".github/CODEOWNERS";
|
|
49
|
+
function composeGithubTemplates(groups, locale) {
|
|
50
|
+
const files = generatorFilesDir("add-github-templates", import.meta.url);
|
|
51
|
+
return ["issue", "pr", "codeowners"].filter((group) => groups[group]).flatMap((group) => renderTemplateFiles(join(files, locale, group), ".", {}));
|
|
52
|
+
}
|
|
53
|
+
function runAddGithubTemplates(tree, options) {
|
|
54
|
+
const locale = resolveLocaleOption(options.locale, readToolkitConfig(tree));
|
|
55
|
+
const plan = composeGithubTemplates(
|
|
56
|
+
{ issue: options.issue ?? false, pr: options.pr ?? true, codeowners: options.codeowners ?? false },
|
|
57
|
+
locale
|
|
58
|
+
);
|
|
59
|
+
const dryRun = options.dryRun ?? false;
|
|
60
|
+
const files = plan.map(({ filePath, content }) => {
|
|
61
|
+
const existing = tree.read(filePath, "utf-8");
|
|
62
|
+
let action;
|
|
63
|
+
if (existing === null) {
|
|
64
|
+
action = "created";
|
|
65
|
+
if (!dryRun) tree.write(filePath, content);
|
|
66
|
+
} else if (existing === content) {
|
|
67
|
+
action = "unchanged";
|
|
68
|
+
} else {
|
|
69
|
+
action = "skipped";
|
|
70
|
+
}
|
|
71
|
+
return { filePath, action, content };
|
|
72
|
+
});
|
|
73
|
+
return { dryRun, files };
|
|
74
|
+
}
|
|
75
|
+
async function addGithubTemplatesGenerator(tree, options) {
|
|
76
|
+
console.log(renderAddGithubTemplatesReport(runAddGithubTemplates(tree, { ...options, dryRun: resolveDryRun(options) })));
|
|
77
|
+
}
|
|
78
|
+
var generator_default = addGithubTemplatesGenerator;
|
|
79
|
+
|
|
80
|
+
export {
|
|
81
|
+
renderAddGithubTemplatesReport,
|
|
82
|
+
BUG_REPORT_PATH,
|
|
83
|
+
FEATURE_REQUEST_PATH,
|
|
84
|
+
PULL_REQUEST_TEMPLATE_PATH,
|
|
85
|
+
CODEOWNERS_PATH,
|
|
86
|
+
runAddGithubTemplates,
|
|
87
|
+
addGithubTemplatesGenerator,
|
|
88
|
+
generator_default
|
|
89
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/generators/shared/project-type.ts
|
|
2
|
+
import { parseJson } from "@nx/devkit";
|
|
3
|
+
function resolveProjectType(tree, root, declared) {
|
|
4
|
+
if (declared) return declared === "library" ? "library" : "application";
|
|
5
|
+
const prefix = root === "" || root === "." ? "" : `${root}/`;
|
|
6
|
+
if (tree.exists(`${prefix}tsconfig.lib.json`)) return "library";
|
|
7
|
+
if (tree.exists(`${prefix}tsconfig.app.json`)) return "application";
|
|
8
|
+
const raw = tree.read(`${prefix}package.json`, "utf-8");
|
|
9
|
+
if (raw === null) return "library";
|
|
10
|
+
try {
|
|
11
|
+
const manifest = parseJson(raw);
|
|
12
|
+
if (manifest && !["exports", "main", "module", "bin"].some((key) => Boolean(manifest[key]))) return "application";
|
|
13
|
+
} catch {
|
|
14
|
+
}
|
|
15
|
+
return "library";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
resolveProjectType
|
|
20
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// ../integrations/dist/manifest/manifest.js
|
|
2
|
+
import { existsSync, lstatSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { randomBytes } from "node:crypto";
|
|
5
|
+
var MANIFEST_FILENAME = "archweave-integrations.json";
|
|
6
|
+
function createEmptyManifest() {
|
|
7
|
+
return { integrations: {} };
|
|
8
|
+
}
|
|
9
|
+
function loadManifest(root) {
|
|
10
|
+
const manifestPath = join(root, MANIFEST_FILENAME);
|
|
11
|
+
if (!existsSync(manifestPath)) {
|
|
12
|
+
return createEmptyManifest();
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
const parsed = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
16
|
+
if (parsed && typeof parsed === "object" && typeof parsed.integrations === "object") {
|
|
17
|
+
return { integrations: parsed.integrations ?? {} };
|
|
18
|
+
}
|
|
19
|
+
return createEmptyManifest();
|
|
20
|
+
} catch {
|
|
21
|
+
return createEmptyManifest();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function serializeManifest(manifest) {
|
|
25
|
+
return `${JSON.stringify(manifest, null, 2)}
|
|
26
|
+
`;
|
|
27
|
+
}
|
|
28
|
+
function writeManifestAtomic(root, manifest) {
|
|
29
|
+
const finalPath = join(root, MANIFEST_FILENAME);
|
|
30
|
+
if (existsSync(finalPath) && lstatSync(finalPath).isSymbolicLink()) {
|
|
31
|
+
throw new Error(`Refusing to write ${MANIFEST_FILENAME}: the path is a symlink. Remove or replace it with a regular file first.`);
|
|
32
|
+
}
|
|
33
|
+
const suffix = randomBytes(6).toString("hex");
|
|
34
|
+
const tempPath = join(root, `.${MANIFEST_FILENAME}.tmp-${suffix}`);
|
|
35
|
+
try {
|
|
36
|
+
writeFileSync(tempPath, serializeManifest(manifest));
|
|
37
|
+
renameSync(tempPath, finalPath);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
if (existsSync(tempPath)) {
|
|
40
|
+
unlinkSync(tempPath);
|
|
41
|
+
}
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export {
|
|
47
|
+
loadManifest,
|
|
48
|
+
writeManifestAtomic
|
|
49
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadManifest,
|
|
3
|
+
writeManifestAtomic
|
|
4
|
+
} from "./chunk-U6LAFHSF.js";
|
|
5
|
+
import {
|
|
6
|
+
getCatalogEntry,
|
|
7
|
+
recordMetadataFor,
|
|
8
|
+
verifyClaudeMarketplacePlugin
|
|
9
|
+
} from "./chunk-AQHV7DJS.js";
|
|
10
|
+
|
|
11
|
+
// ../integrations/dist/manifest/record-plan.js
|
|
12
|
+
function entriesEqual(a, b) {
|
|
13
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
14
|
+
}
|
|
15
|
+
function buildRecordPlan(input) {
|
|
16
|
+
const isRecordable = input.verification.verified && input.verificationSource === "claude-cli";
|
|
17
|
+
const proposedEntry = isRecordable ? {
|
|
18
|
+
source: input.metadata.source,
|
|
19
|
+
repository: input.metadata.repository,
|
|
20
|
+
version: input.verification.resolvedVersion,
|
|
21
|
+
method: input.metadata.method,
|
|
22
|
+
managedBy: "nx-archweave",
|
|
23
|
+
verification: "passed",
|
|
24
|
+
target: input.target,
|
|
25
|
+
evidenceKind: "claude-cli"
|
|
26
|
+
} : void 0;
|
|
27
|
+
const hasConflict = input.existingEntry !== void 0 && proposedEntry !== void 0 && !entriesEqual(input.existingEntry, proposedEntry);
|
|
28
|
+
return {
|
|
29
|
+
id: input.id,
|
|
30
|
+
target: input.target,
|
|
31
|
+
verificationSource: input.verificationSource,
|
|
32
|
+
currentVerification: input.verification,
|
|
33
|
+
existingEntry: input.existingEntry,
|
|
34
|
+
proposedEntry,
|
|
35
|
+
hasConflict
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/generators/shared/record-pipeline.ts
|
|
40
|
+
async function runRecordPipeline(input) {
|
|
41
|
+
const entry = getCatalogEntry(input.id);
|
|
42
|
+
const metadata = entry === void 0 ? void 0 : recordMetadataFor(entry);
|
|
43
|
+
if (!entry || !metadata) {
|
|
44
|
+
throw new Error(`No manifest metadata is defined for "${input.id}".`);
|
|
45
|
+
}
|
|
46
|
+
const { result: verification, source: verificationSource } = await verifyClaudeMarketplacePlugin(
|
|
47
|
+
entry,
|
|
48
|
+
{ runner: input.runner },
|
|
49
|
+
{ workspaceRoot: input.workspaceRoot, targetEnvironment: input.target }
|
|
50
|
+
);
|
|
51
|
+
const manifest = loadManifest(input.workspaceRoot);
|
|
52
|
+
const existingEntry = manifest.integrations[input.id];
|
|
53
|
+
const plan = buildRecordPlan({ id: input.id, target: input.target, verificationSource, verification, existingEntry, metadata });
|
|
54
|
+
let wasWritten = false;
|
|
55
|
+
if (input.write && plan.proposedEntry) {
|
|
56
|
+
writeManifestAtomic(input.workspaceRoot, {
|
|
57
|
+
integrations: { ...manifest.integrations, [input.id]: plan.proposedEntry }
|
|
58
|
+
});
|
|
59
|
+
wasWritten = true;
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
verificationSource,
|
|
63
|
+
verification,
|
|
64
|
+
existingEntry,
|
|
65
|
+
proposedEntry: plan.proposedEntry,
|
|
66
|
+
hasConflict: plan.hasConflict,
|
|
67
|
+
wasWritten
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export {
|
|
72
|
+
runRecordPipeline
|
|
73
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/generators/shared/template-files.ts
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { generateFiles } from "@nx/devkit";
|
|
5
|
+
import { createTree } from "@nx/devkit/testing";
|
|
6
|
+
function generatorFilesDir(generator, fromUrl) {
|
|
7
|
+
for (const relative of [`../${generator}/files`, `./generators/${generator}/files`]) {
|
|
8
|
+
const dir = fileURLToPath(new URL(relative, fromUrl));
|
|
9
|
+
if (existsSync(dir)) return dir;
|
|
10
|
+
}
|
|
11
|
+
throw new Error(`The "${generator}" generator's template files are missing next to ${fileURLToPath(fromUrl)}`);
|
|
12
|
+
}
|
|
13
|
+
function renderTemplateFiles(srcFolder, target, substitutions) {
|
|
14
|
+
const scratch = createTree();
|
|
15
|
+
const seeded = new Set(scratch.listChanges().map((change) => change.path));
|
|
16
|
+
generateFiles(scratch, srcFolder, target, substitutions);
|
|
17
|
+
return scratch.listChanges().flatMap(
|
|
18
|
+
(change) => change.type === "CREATE" && change.content !== null && !seeded.has(change.path) ? [{ filePath: change.path, content: change.content.toString("utf-8") }] : []
|
|
19
|
+
).sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
generatorFilesDir,
|
|
24
|
+
renderTemplateFiles
|
|
25
|
+
};
|