@kb-labs/scaffold-core 2.34.0 → 2.35.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/dist/index.js +104 -34
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.js
CHANGED
|
@@ -56,9 +56,13 @@ async function loadEntity(templatesRoot, entityId) {
|
|
|
56
56
|
if (await pathExists(blocksDir)) {
|
|
57
57
|
const entries = await readdir(blocksDir, { withFileTypes: true });
|
|
58
58
|
for (const entry of entries) {
|
|
59
|
-
if (!entry.isDirectory())
|
|
59
|
+
if (!entry.isDirectory()) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
60
62
|
const blockDir = join(blocksDir, entry.name);
|
|
61
|
-
if (!await pathExists(join(blockDir, "block.yaml")))
|
|
63
|
+
if (!await pathExists(join(blockDir, "block.yaml"))) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
62
66
|
blocks.push(await loadBlock(blockDir));
|
|
63
67
|
}
|
|
64
68
|
}
|
|
@@ -74,11 +78,15 @@ async function loadEntity(templatesRoot, entityId) {
|
|
|
74
78
|
};
|
|
75
79
|
}
|
|
76
80
|
async function listEntities(templatesRoot) {
|
|
77
|
-
if (!await pathExists(templatesRoot))
|
|
81
|
+
if (!await pathExists(templatesRoot)) {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
78
84
|
const entries = await readdir(templatesRoot, { withFileTypes: true });
|
|
79
85
|
const result = [];
|
|
80
86
|
for (const entry of entries) {
|
|
81
|
-
if (!entry.isDirectory())
|
|
87
|
+
if (!entry.isDirectory()) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
82
90
|
if (await pathExists(join(templatesRoot, entry.name, "entity.yaml"))) {
|
|
83
91
|
result.push(entry.name);
|
|
84
92
|
}
|
|
@@ -89,7 +97,9 @@ async function listEntities(templatesRoot) {
|
|
|
89
97
|
// src/resolver/resolve-blocks.ts
|
|
90
98
|
function resolveBlocks(all, selected) {
|
|
91
99
|
const byId = /* @__PURE__ */ new Map();
|
|
92
|
-
for (const b of all)
|
|
100
|
+
for (const b of all) {
|
|
101
|
+
byId.set(b.id, b);
|
|
102
|
+
}
|
|
93
103
|
const missing = selected.filter((id) => !byId.has(id));
|
|
94
104
|
if (missing.length > 0) {
|
|
95
105
|
throw new Error(`Unknown block(s): ${missing.join(", ")}`);
|
|
@@ -98,17 +108,23 @@ function resolveBlocks(all, selected) {
|
|
|
98
108
|
const queue = [...selected];
|
|
99
109
|
while (queue.length > 0) {
|
|
100
110
|
const id = queue.shift();
|
|
101
|
-
if (expanded.has(id))
|
|
111
|
+
if (expanded.has(id)) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
102
114
|
expanded.add(id);
|
|
103
115
|
const block = byId.get(id);
|
|
104
|
-
if (!block)
|
|
116
|
+
if (!block) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
105
119
|
for (const dep of block.requires ?? []) {
|
|
106
120
|
if (!byId.has(dep)) {
|
|
107
121
|
throw new Error(
|
|
108
122
|
`Block "${id}" requires unknown block "${dep}"`
|
|
109
123
|
);
|
|
110
124
|
}
|
|
111
|
-
if (!expanded.has(dep))
|
|
125
|
+
if (!expanded.has(dep)) {
|
|
126
|
+
queue.push(dep);
|
|
127
|
+
}
|
|
112
128
|
}
|
|
113
129
|
}
|
|
114
130
|
for (const id of expanded) {
|
|
@@ -130,13 +146,19 @@ function resolveBlocks(all, selected) {
|
|
|
130
146
|
for (const id of expanded) {
|
|
131
147
|
const block = byId.get(id);
|
|
132
148
|
for (const dep of block.requires ?? []) {
|
|
133
|
-
if (!expanded.has(dep))
|
|
149
|
+
if (!expanded.has(dep)) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
134
152
|
edges.get(dep).add(id);
|
|
135
153
|
inDegree.set(id, (inDegree.get(id) ?? 0) + 1);
|
|
136
154
|
}
|
|
137
155
|
}
|
|
138
156
|
const ready = [];
|
|
139
|
-
for (const [id, deg] of inDegree)
|
|
157
|
+
for (const [id, deg] of inDegree) {
|
|
158
|
+
if (deg === 0) {
|
|
159
|
+
ready.push(id);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
140
162
|
ready.sort();
|
|
141
163
|
const ordered = [];
|
|
142
164
|
while (ready.length > 0) {
|
|
@@ -191,7 +213,9 @@ async function renderFilesDir(filesDir, ctx) {
|
|
|
191
213
|
const renderedRel = renderPath(rel, ctx);
|
|
192
214
|
const raw = await readFile(abs, "utf8");
|
|
193
215
|
const body = abs.endsWith(ETA_SUFFIX) ? renderString(raw, ctx) : raw;
|
|
194
|
-
if (body.trim() === SKIP_MARKER)
|
|
216
|
+
if (body.trim() === SKIP_MARKER) {
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
195
219
|
const st = await stat(abs);
|
|
196
220
|
rendered.push({
|
|
197
221
|
path: renderedRel,
|
|
@@ -208,8 +232,12 @@ function mergeArrays(a, b) {
|
|
|
208
232
|
const allObjects = a.every(isPlainObject) && b.every(isPlainObject) && a.length + b.length > 0;
|
|
209
233
|
if (allObjects) {
|
|
210
234
|
const keyOf = (x) => {
|
|
211
|
-
if (typeof x.id === "string")
|
|
212
|
-
|
|
235
|
+
if (typeof x.id === "string") {
|
|
236
|
+
return `id:${x.id}`;
|
|
237
|
+
}
|
|
238
|
+
if (typeof x.name === "string") {
|
|
239
|
+
return `name:${x.name}`;
|
|
240
|
+
}
|
|
213
241
|
return null;
|
|
214
242
|
};
|
|
215
243
|
const allKeyed = a.every((x) => keyOf(x) !== null) && b.every((x) => keyOf(x) !== null);
|
|
@@ -227,7 +255,9 @@ function mergeArrays(a, b) {
|
|
|
227
255
|
const out = [];
|
|
228
256
|
for (const item of [...a, ...b]) {
|
|
229
257
|
const key = JSON.stringify(item);
|
|
230
|
-
if (seen.has(key))
|
|
258
|
+
if (seen.has(key)) {
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
231
261
|
seen.add(key);
|
|
232
262
|
out.push(item);
|
|
233
263
|
}
|
|
@@ -251,7 +281,9 @@ async function loadPatch(path, ctx) {
|
|
|
251
281
|
const raw = await readFile(path, "utf8");
|
|
252
282
|
const rendered = renderString(raw, ctx);
|
|
253
283
|
const parsed = parse(rendered);
|
|
254
|
-
if (parsed == null)
|
|
284
|
+
if (parsed == null) {
|
|
285
|
+
return {};
|
|
286
|
+
}
|
|
255
287
|
if (!isPlainObject(parsed)) {
|
|
256
288
|
throw new Error(`Patch at ${path} must be a YAML object`);
|
|
257
289
|
}
|
|
@@ -261,7 +293,9 @@ async function loadSnippets(path, ctx) {
|
|
|
261
293
|
const raw = await readFile(path, "utf8");
|
|
262
294
|
const rendered = renderString(raw, ctx);
|
|
263
295
|
const parsed = parse(rendered);
|
|
264
|
-
if (parsed == null)
|
|
296
|
+
if (parsed == null) {
|
|
297
|
+
return {};
|
|
298
|
+
}
|
|
265
299
|
if (!isPlainObject(parsed)) {
|
|
266
300
|
throw new Error(`Snippets at ${path} must be a YAML object`);
|
|
267
301
|
}
|
|
@@ -287,7 +321,9 @@ function dedupe(items) {
|
|
|
287
321
|
async function inspectTarget(outRoot) {
|
|
288
322
|
try {
|
|
289
323
|
const st = await stat(outRoot);
|
|
290
|
-
if (!st.isDirectory())
|
|
324
|
+
if (!st.isDirectory()) {
|
|
325
|
+
return { exists: true, empty: false };
|
|
326
|
+
}
|
|
291
327
|
const entries = await readdir(outRoot);
|
|
292
328
|
return { exists: true, empty: entries.length === 0 };
|
|
293
329
|
} catch {
|
|
@@ -412,7 +448,9 @@ async function walkSources(dir) {
|
|
|
412
448
|
const out = [];
|
|
413
449
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
414
450
|
for (const entry of entries) {
|
|
415
|
-
if (entry.name === "node_modules" || entry.name === "dist")
|
|
451
|
+
if (entry.name === "node_modules" || entry.name === "dist") {
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
416
454
|
const p = join(dir, entry.name);
|
|
417
455
|
if (entry.isDirectory()) {
|
|
418
456
|
out.push(...await walkSources(p));
|
|
@@ -464,7 +502,9 @@ async function scanPackage(pkgDir) {
|
|
|
464
502
|
for (const file of sources) {
|
|
465
503
|
const raw = await readFile(file, "utf8");
|
|
466
504
|
for (const match of raw.matchAll(INTERNAL_IMPORT_RE)) {
|
|
467
|
-
if (match[1])
|
|
505
|
+
if (match[1]) {
|
|
506
|
+
offenders.add(match[1]);
|
|
507
|
+
}
|
|
468
508
|
}
|
|
469
509
|
}
|
|
470
510
|
if (offenders.size > 0) {
|
|
@@ -491,7 +531,9 @@ async function scanPackage(pkgDir) {
|
|
|
491
531
|
}
|
|
492
532
|
async function readLock(workspaceRoot) {
|
|
493
533
|
const lockPath = join(workspaceRoot, ".kb", "marketplace.lock");
|
|
494
|
-
if (!await exists(lockPath))
|
|
534
|
+
if (!await exists(lockPath)) {
|
|
535
|
+
return null;
|
|
536
|
+
}
|
|
495
537
|
try {
|
|
496
538
|
const raw = await readFile(lockPath, "utf8");
|
|
497
539
|
return JSON.parse(raw);
|
|
@@ -503,16 +545,26 @@ async function findEntryPackageDir(pkgDir) {
|
|
|
503
545
|
const pkgJsonPath = join(pkgDir, "package.json");
|
|
504
546
|
if (await exists(pkgJsonPath)) {
|
|
505
547
|
const pkg = await readJson(pkgJsonPath);
|
|
506
|
-
if (pkg.kb?.manifest)
|
|
548
|
+
if (pkg.kb?.manifest) {
|
|
549
|
+
return pkgDir;
|
|
550
|
+
}
|
|
507
551
|
}
|
|
508
552
|
const packagesDir = join(pkgDir, "packages");
|
|
509
|
-
if (!await exists(packagesDir))
|
|
553
|
+
if (!await exists(packagesDir)) {
|
|
554
|
+
return null;
|
|
555
|
+
}
|
|
510
556
|
const entries = await readdir(packagesDir, { withFileTypes: true });
|
|
511
557
|
for (const entry of entries) {
|
|
512
|
-
if (!entry.isDirectory())
|
|
513
|
-
|
|
558
|
+
if (!entry.isDirectory()) {
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
if (!entry.name.endsWith("-entry")) {
|
|
562
|
+
continue;
|
|
563
|
+
}
|
|
514
564
|
const candidate = join(packagesDir, entry.name);
|
|
515
|
-
if (await exists(join(candidate, "package.json")))
|
|
565
|
+
if (await exists(join(candidate, "package.json"))) {
|
|
566
|
+
return candidate;
|
|
567
|
+
}
|
|
516
568
|
}
|
|
517
569
|
return null;
|
|
518
570
|
}
|
|
@@ -529,7 +581,9 @@ async function scanRoot(root, opts = {}) {
|
|
|
529
581
|
if (await exists(packagesDir)) {
|
|
530
582
|
const entries2 = await readdir(packagesDir, { withFileTypes: true });
|
|
531
583
|
for (const entry of entries2) {
|
|
532
|
-
if (entry.isDirectory())
|
|
584
|
+
if (entry.isDirectory()) {
|
|
585
|
+
await visit(join(packagesDir, entry.name));
|
|
586
|
+
}
|
|
533
587
|
}
|
|
534
588
|
}
|
|
535
589
|
}
|
|
@@ -547,7 +601,9 @@ async function scanRoot(root, opts = {}) {
|
|
|
547
601
|
}
|
|
548
602
|
const entries = await readdir(root, { withFileTypes: true });
|
|
549
603
|
for (const entry of entries) {
|
|
550
|
-
if (entry.isDirectory())
|
|
604
|
+
if (entry.isDirectory()) {
|
|
605
|
+
await visit(join(root, entry.name));
|
|
606
|
+
}
|
|
551
607
|
}
|
|
552
608
|
if (opts.workspaceRoot) {
|
|
553
609
|
findings.push(...await checkLockSync(root, opts.workspaceRoot));
|
|
@@ -559,10 +615,14 @@ async function checkLockSync(scaffoldRoot, workspaceRoot) {
|
|
|
559
615
|
const lock = await readLock(workspaceRoot);
|
|
560
616
|
const entries = await readdir(scaffoldRoot, { withFileTypes: true });
|
|
561
617
|
for (const entry of entries) {
|
|
562
|
-
if (!entry.isDirectory())
|
|
618
|
+
if (!entry.isDirectory()) {
|
|
619
|
+
continue;
|
|
620
|
+
}
|
|
563
621
|
const pluginDir = join(scaffoldRoot, entry.name);
|
|
564
622
|
const entryPkgDir = await findEntryPackageDir(pluginDir);
|
|
565
|
-
if (!entryPkgDir)
|
|
623
|
+
if (!entryPkgDir) {
|
|
624
|
+
continue;
|
|
625
|
+
}
|
|
566
626
|
const pkg = await readJson(join(entryPkgDir, "package.json"));
|
|
567
627
|
const id = typeof pkg.name === "string" ? pkg.name : entry.name;
|
|
568
628
|
if (!lock || !lock.installed) {
|
|
@@ -623,16 +683,24 @@ var RESERVED_NAMES = /* @__PURE__ */ new Set([
|
|
|
623
683
|
"nul"
|
|
624
684
|
]);
|
|
625
685
|
function validatePackageName(name) {
|
|
626
|
-
if (!name)
|
|
627
|
-
|
|
686
|
+
if (!name) {
|
|
687
|
+
return "name is required";
|
|
688
|
+
}
|
|
689
|
+
if (name.length > 214) {
|
|
690
|
+
return "name must be <= 214 chars";
|
|
691
|
+
}
|
|
628
692
|
if (!NAME_RE.test(name)) {
|
|
629
693
|
return "name must be lowercase, start with a letter, and contain only a-z 0-9 -";
|
|
630
694
|
}
|
|
631
|
-
if (RESERVED_NAMES.has(name))
|
|
695
|
+
if (RESERVED_NAMES.has(name)) {
|
|
696
|
+
return `name "${name}" is reserved`;
|
|
697
|
+
}
|
|
632
698
|
return null;
|
|
633
699
|
}
|
|
634
700
|
function validateScope(scope) {
|
|
635
|
-
if (!scope)
|
|
701
|
+
if (!scope) {
|
|
702
|
+
return null;
|
|
703
|
+
}
|
|
636
704
|
if (!SCOPE_RE.test(scope)) {
|
|
637
705
|
return 'scope must look like "@acme" (lowercase, starts with @, a-z 0-9 -)';
|
|
638
706
|
}
|
|
@@ -645,7 +713,9 @@ function validateIdentifier(v) {
|
|
|
645
713
|
return IDENTIFIER_RE.test(v) ? null : "expected a JS identifier";
|
|
646
714
|
}
|
|
647
715
|
function runValidator(kind, value) {
|
|
648
|
-
if (typeof value !== "string")
|
|
716
|
+
if (typeof value !== "string") {
|
|
717
|
+
return "expected a string";
|
|
718
|
+
}
|
|
649
719
|
switch (kind) {
|
|
650
720
|
case "npmName":
|
|
651
721
|
return validatePackageName(value);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/loader/load-entity.ts","../src/resolver/resolve-blocks.ts","../src/render/eta-renderer.ts","../src/patch/apply-patch.ts","../src/writer/write-files.ts","../src/emit/emit-manifest.ts","../src/engine.ts","../src/doctor/scan.ts","../src/validators.ts"],"names":["parseYaml","readdir","join","readFile","stat","resolve","entries","relative","resolvePath"],"mappings":"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","file":"index.js","sourcesContent":["import { readFile, readdir, stat } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type {\n BlockDefinition,\n EntityDefinition,\n Variable,\n} from '@kb-labs/scaffold-contracts';\n\ninterface RawBlockYaml {\n id?: string;\n describe?: string;\n requires?: string[];\n conflicts?: string[];\n variables?: Variable[];\n manifestPatch?: string;\n snippets?: string;\n}\n\ninterface RawEntityYaml {\n id?: string;\n displayName?: string;\n description?: string;\n variables?: Variable[];\n defaults?: { blocks?: string[] };\n output?: string;\n manifestTarget?: string;\n}\n\nasync function pathExists(p: string): Promise<boolean> {\n try {\n await stat(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function loadBlock(blockDir: string): Promise<BlockDefinition> {\n const blockYamlPath = join(blockDir, 'block.yaml');\n const raw = await readFile(blockYamlPath, 'utf8');\n const parsed = parseYaml(raw) as RawBlockYaml;\n\n if (!parsed.id) {\n throw new Error(`block.yaml at ${blockYamlPath} is missing \"id\"`);\n }\n\n const filesDir = join(blockDir, 'files');\n const manifestPatchFile =\n parsed.manifestPatch ?? 'manifest.patch.yaml';\n const snippetsFile = parsed.snippets ?? 'manifest.snippets.yaml';\n\n const manifestPatchPath = join(blockDir, manifestPatchFile);\n const snippetsPath = join(blockDir, snippetsFile);\n\n const [hasFiles, hasPatch, hasSnippets] = await Promise.all([\n pathExists(filesDir),\n pathExists(manifestPatchPath),\n pathExists(snippetsPath),\n ]);\n\n return {\n id: parsed.id,\n describe: parsed.describe ?? parsed.id,\n requires: parsed.requires,\n conflicts: parsed.conflicts,\n variables: parsed.variables,\n filesDir: hasFiles ? filesDir : blockDir,\n manifestPatch: hasPatch ? manifestPatchPath : undefined,\n snippetsPath: hasSnippets ? snippetsPath : undefined,\n };\n}\n\n/**\n * Load an entity definition from a templates directory.\n *\n * @param templatesRoot directory containing `<entity>/entity.yaml` and `<entity>/blocks/*`\n * @param entityId e.g. 'plugin', 'adapter'\n */\nexport async function loadEntity(\n templatesRoot: string,\n entityId: string,\n): Promise<EntityDefinition> {\n const entityDir = resolve(templatesRoot, entityId);\n const entityYamlPath = join(entityDir, 'entity.yaml');\n\n if (!(await pathExists(entityYamlPath))) {\n throw new Error(\n `Entity \"${entityId}\" not found: ${entityYamlPath} does not exist`,\n );\n }\n\n const raw = await readFile(entityYamlPath, 'utf8');\n const parsed = (parseYaml(raw) ?? {}) as RawEntityYaml;\n\n const id = parsed.id ?? entityId;\n const blocksDir = join(entityDir, 'blocks');\n const blocks: BlockDefinition[] = [];\n\n if (await pathExists(blocksDir)) {\n const entries = await readdir(blocksDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const blockDir = join(blocksDir, entry.name);\n if (!(await pathExists(join(blockDir, 'block.yaml')))) continue;\n blocks.push(await loadBlock(blockDir));\n }\n }\n\n return {\n id,\n displayName: parsed.displayName ?? id,\n description: parsed.description,\n variables: parsed.variables ?? [],\n blocks,\n defaults: parsed.defaults,\n output: parsed.output,\n manifestTarget: parsed.manifestTarget,\n };\n}\n\n/**\n * List entity ids available in the templates root (directories with `entity.yaml`).\n */\nexport async function listEntities(templatesRoot: string): Promise<string[]> {\n if (!(await pathExists(templatesRoot))) return [];\n const entries = await readdir(templatesRoot, { withFileTypes: true });\n const result: string[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (await pathExists(join(templatesRoot, entry.name, 'entity.yaml'))) {\n result.push(entry.name);\n }\n }\n return result.sort();\n}\n","import type { BlockDefinition } from '@kb-labs/scaffold-contracts';\n\nexport interface ResolveResult {\n /** Block ids in topological order (dependencies first). */\n ordered: string[];\n /** Full block definitions in the same order. */\n blocks: BlockDefinition[];\n}\n\n/**\n * Resolve a user-selected set of block ids into a topologically sorted list,\n * expanding `requires` and rejecting cycles or `conflicts` violations.\n */\nexport function resolveBlocks(\n all: BlockDefinition[],\n selected: string[],\n): ResolveResult {\n const byId = new Map<string, BlockDefinition>();\n for (const b of all) byId.set(b.id, b);\n\n const missing = selected.filter((id) => !byId.has(id));\n if (missing.length > 0) {\n throw new Error(`Unknown block(s): ${missing.join(', ')}`);\n }\n\n // Expand requires (BFS).\n const expanded = new Set<string>();\n const queue = [...selected];\n while (queue.length > 0) {\n const id = queue.shift()!;\n if (expanded.has(id)) continue;\n expanded.add(id);\n const block = byId.get(id);\n if (!block) continue;\n for (const dep of block.requires ?? []) {\n if (!byId.has(dep)) {\n throw new Error(\n `Block \"${id}\" requires unknown block \"${dep}\"`,\n );\n }\n if (!expanded.has(dep)) queue.push(dep);\n }\n }\n\n // Conflict check against the final expanded set.\n for (const id of expanded) {\n const block = byId.get(id)!;\n for (const other of block.conflicts ?? []) {\n if (expanded.has(other)) {\n throw new Error(\n `Block \"${id}\" conflicts with \"${other}\" — both selected`,\n );\n }\n }\n }\n\n // Topological sort (Kahn's algorithm).\n const inDegree = new Map<string, number>();\n const edges = new Map<string, Set<string>>();\n for (const id of expanded) {\n inDegree.set(id, 0);\n edges.set(id, new Set());\n }\n for (const id of expanded) {\n const block = byId.get(id)!;\n for (const dep of block.requires ?? []) {\n if (!expanded.has(dep)) continue;\n edges.get(dep)!.add(id);\n inDegree.set(id, (inDegree.get(id) ?? 0) + 1);\n }\n }\n\n const ready: string[] = [];\n for (const [id, deg] of inDegree) if (deg === 0) ready.push(id);\n ready.sort();\n\n const ordered: string[] = [];\n while (ready.length > 0) {\n const id = ready.shift()!;\n ordered.push(id);\n for (const next of edges.get(id) ?? []) {\n const d = (inDegree.get(next) ?? 0) - 1;\n inDegree.set(next, d);\n if (d === 0) {\n ready.push(next);\n ready.sort();\n }\n }\n }\n\n if (ordered.length !== expanded.size) {\n throw new Error('Cycle detected in block requires graph');\n }\n\n return { ordered, blocks: ordered.map((id) => byId.get(id)!) };\n}\n","import { readFile, readdir, stat } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport { Eta } from 'eta';\nimport type {\n RenderContext,\n RenderedFile,\n} from '@kb-labs/scaffold-contracts';\n\nconst eta = new Eta({\n autoEscape: false,\n useWith: true,\n tags: ['<%', '%>'],\n});\n\nconst ETA_SUFFIX = '.eta';\n\n/**\n * Render a single template string through eta using the given context.\n */\nexport function renderString(template: string, ctx: RenderContext): string {\n return eta.renderString(template, ctx);\n}\n\nasync function walk(dir: string): Promise<string[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n const out: string[] = [];\n for (const entry of entries) {\n const p = join(dir, entry.name);\n if (entry.isDirectory()) {\n out.push(...(await walk(p)));\n } else if (entry.isFile()) {\n out.push(p);\n }\n }\n return out;\n}\n\nfunction renderPath(relPath: string, ctx: RenderContext): string {\n // Use simple __var__ substitution for path segments — eta's `<% %>`\n // tags are illegal on Windows and awkward on Unix.\n const substituted = relPath\n .replace(/__name__/g, ctx.name)\n .replace(/__scope__/g, ctx.scope.replace(/^@/, ''));\n return substituted.endsWith(ETA_SUFFIX)\n ? substituted.slice(0, -ETA_SUFFIX.length)\n : substituted;\n}\n\n/**\n * Render all files under `filesDir`. File bodies AND path segments go through\n * eta. A trailing `.eta` extension on the file name is stripped after render.\n *\n * Returned paths are relative to `filesDir`. The caller decides the output root.\n */\nconst SKIP_MARKER = '<!--@@scaffold:skip@@-->';\n\nexport async function renderFilesDir(\n filesDir: string,\n ctx: RenderContext,\n): Promise<RenderedFile[]> {\n const absolutes = await walk(filesDir);\n const rendered: RenderedFile[] = [];\n for (const abs of absolutes) {\n const rel = relative(filesDir, abs);\n const renderedRel = renderPath(rel, ctx);\n const raw = await readFile(abs, 'utf8');\n const body = abs.endsWith(ETA_SUFFIX)\n ? renderString(raw, ctx)\n : raw;\n\n // Templates can opt out of a given file by emitting a skip marker.\n // Useful for files that should only exist in some modes (e.g.\n // pnpm-workspace.yaml only for standalone mode).\n if (body.trim() === SKIP_MARKER) continue;\n\n const st = await stat(abs);\n rendered.push({\n path: renderedRel,\n contents: body,\n executable: (st.mode & 0o111) !== 0,\n });\n }\n return rendered;\n}\n","import { readFile } from 'node:fs/promises';\nimport { parse as parseYaml } from 'yaml';\nimport type {\n ManifestPatch,\n ManifestSnippets,\n RenderContext,\n} from '@kb-labs/scaffold-contracts';\nimport { renderString } from '../render/eta-renderer.js';\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return (\n typeof v === 'object' &&\n v !== null &&\n !Array.isArray(v) &&\n Object.getPrototypeOf(v) === Object.prototype\n );\n}\n\nfunction mergeArrays(a: unknown[], b: unknown[]): unknown[] {\n const allObjects =\n a.every(isPlainObject) && b.every(isPlainObject) && a.length + b.length > 0;\n\n if (allObjects) {\n const keyOf = (x: Record<string, unknown>): string | null => {\n if (typeof x.id === 'string') return `id:${x.id}`;\n if (typeof x.name === 'string') return `name:${x.name}`;\n return null;\n };\n const allKeyed =\n a.every((x) => keyOf(x as Record<string, unknown>) !== null) &&\n b.every((x) => keyOf(x as Record<string, unknown>) !== null);\n\n if (allKeyed) {\n const byKey = new Map<string, Record<string, unknown>>();\n for (const item of [...a, ...b] as Record<string, unknown>[]) {\n const k = keyOf(item)!;\n const prev = byKey.get(k);\n byKey.set(k, prev ? deepMerge(prev, item) : item);\n }\n return [...byKey.values()];\n }\n }\n\n // Primitive or mixed: Set-dedupe where possible.\n const seen = new Set<string>();\n const out: unknown[] = [];\n for (const item of [...a, ...b]) {\n const key = JSON.stringify(item);\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(item);\n }\n return out;\n}\n\nexport function deepMerge(\n target: Record<string, unknown>,\n patch: Record<string, unknown>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = { ...target };\n for (const [key, value] of Object.entries(patch)) {\n const existing = out[key];\n if (isPlainObject(existing) && isPlainObject(value)) {\n out[key] = deepMerge(existing, value);\n } else if (Array.isArray(existing) && Array.isArray(value)) {\n out[key] = mergeArrays(existing, value);\n } else {\n out[key] = value;\n }\n }\n return out;\n}\n\n/**\n * Load a manifest.patch.yaml from disk, render it through eta with the\n * render context, parse as YAML, and return the resulting object.\n */\nexport async function loadPatch(\n path: string,\n ctx: RenderContext,\n): Promise<ManifestPatch> {\n const raw = await readFile(path, 'utf8');\n const rendered = renderString(raw, ctx);\n const parsed = parseYaml(rendered);\n if (parsed == null) return {};\n if (!isPlainObject(parsed)) {\n throw new Error(`Patch at ${path} must be a YAML object`);\n }\n return parsed;\n}\n\nexport async function loadSnippets(\n path: string,\n ctx: RenderContext,\n): Promise<ManifestSnippets> {\n const raw = await readFile(path, 'utf8');\n const rendered = renderString(raw, ctx);\n const parsed = parseYaml(rendered);\n if (parsed == null) return {};\n if (!isPlainObject(parsed)) {\n throw new Error(`Snippets at ${path} must be a YAML object`);\n }\n return parsed as ManifestSnippets;\n}\n\nexport function mergeSnippets(\n a: ManifestSnippets,\n b: ManifestSnippets,\n): ManifestSnippets {\n const mergedExtras: Record<string, string[]> = { ...(a.extras ?? {}) };\n for (const [k, v] of Object.entries(b.extras ?? {})) {\n mergedExtras[k] = dedupe([...(mergedExtras[k] ?? []), ...v]);\n }\n return {\n imports: dedupe([...(a.imports ?? []), ...(b.imports ?? [])]),\n permissions: dedupe([\n ...(a.permissions ?? []),\n ...(b.permissions ?? []),\n ]),\n extras: Object.keys(mergedExtras).length > 0 ? mergedExtras : undefined,\n };\n}\n\nfunction dedupe(items: string[]): string[] {\n return [...new Set(items)];\n}\n","import { mkdir, writeFile, chmod, stat, readdir, rm } from 'node:fs/promises';\nimport { dirname, join, resolve } from 'node:path';\nimport type { RenderedFile } from '@kb-labs/scaffold-contracts';\n\nexport interface WriteOptions {\n outRoot: string;\n files: RenderedFile[];\n /** If set, wipe the root first. */\n force?: boolean;\n}\n\nexport interface TargetState {\n exists: boolean;\n empty: boolean;\n}\n\nexport async function inspectTarget(outRoot: string): Promise<TargetState> {\n try {\n const st = await stat(outRoot);\n if (!st.isDirectory()) return { exists: true, empty: false };\n const entries = await readdir(outRoot);\n return { exists: true, empty: entries.length === 0 };\n } catch {\n return { exists: false, empty: true };\n }\n}\n\n/**\n * Detect intra-batch path collisions. Two blocks writing the same path is a\n * configuration bug, not a merge case.\n */\nexport function detectCollisions(files: RenderedFile[]): string[] {\n const seen = new Map<string, number>();\n for (const f of files) {\n seen.set(f.path, (seen.get(f.path) ?? 0) + 1);\n }\n return [...seen.entries()]\n .filter(([, n]) => n > 1)\n .map(([p]) => p);\n}\n\n/**\n * Write the rendered file set to disk. If `force` is set and the root\n * exists, it is wiped first. Otherwise the caller is responsible for\n * ensuring the root is absent or empty — see `inspectTarget`.\n */\nexport async function writeFiles(opts: WriteOptions): Promise<void> {\n const { outRoot, files, force } = opts;\n const abs = resolve(outRoot);\n\n const collisions = detectCollisions(files);\n if (collisions.length > 0) {\n throw new Error(\n `Block path collisions detected: ${collisions.join(', ')}`,\n );\n }\n\n if (force) {\n await rm(abs, { recursive: true, force: true });\n }\n\n await mkdir(abs, { recursive: true });\n\n for (const file of files) {\n const target = join(abs, file.path);\n await mkdir(dirname(target), { recursive: true });\n await writeFile(target, file.contents, 'utf8');\n if (file.executable) {\n await chmod(target, 0o755);\n }\n }\n}\n\n/**\n * Produce a human-readable tree of the files that would be written.\n */\nexport function formatTree(files: RenderedFile[]): string {\n return files\n .map((f) => f.path)\n .sort()\n .map((p) => ` ${p}`)\n .join('\\n');\n}\n","import type {\n ManifestPatch,\n ManifestSnippets,\n} from '@kb-labs/scaffold-contracts';\n\n/**\n * Emit a TypeScript source file for the plugin V3 manifest.\n *\n * The manifest object is stringified as a JSON literal. A `permissions`\n * expression is assembled from `combinePermissions()` snippets contributed\n * by blocks and spread in alongside. Imports are deduped at the top.\n */\nexport function emitManifest(\n manifest: ManifestPatch,\n snippets: ManifestSnippets,\n): string {\n const importLines = [...(snippets.imports ?? [])];\n const hasCombine = importLines.some((l) =>\n /\\bcombinePermissions\\b/.test(l),\n );\n if (!hasCombine) {\n importLines.unshift(\n \"import { combinePermissions } from '@kb-labs/sdk';\",\n );\n }\n const importSet = new Set<string>(importLines);\n\n const permLines = snippets.permissions ?? [];\n const permExpr =\n permLines.length > 0\n ? `combinePermissions()\\n ${permLines.map((l) => `.${l}`).join('\\n ')}\\n .build()`\n : 'combinePermissions().build()';\n\n const body = JSON.stringify(manifest, null, 2);\n\n return `/**\n * V3 plugin manifest. Scaffolded by @kb-labs/scaffold.\n *\n * Edit freely — this is your plugin's public surface. Add commands by\n * appending to \\`cli.commands[]\\`, REST routes under \\`rest.routes[]\\`,\n * Studio pages under \\`studio\\`. Consult neighbouring plugins\n * (\\`plugins/commit\\`, \\`plugins/review\\`) for reference shapes.\n */\n${[...importSet].join('\\n')}\n\nconst permissions = ${permExpr};\n\nconst manifest = ${body} as const;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst withPermissions: typeof manifest & { permissions: any } = { ...manifest, permissions };\n\nexport default withPermissions;\n`;\n}\n","import { join } from 'node:path';\nimport type {\n BlockDefinition,\n EntityDefinition,\n ManifestPatch,\n ManifestSnippets,\n RenderContext,\n RenderedFile,\n} from '@kb-labs/scaffold-contracts';\nimport { resolveBlocks } from './resolver/resolve-blocks.js';\nimport {\n renderFilesDir,\n renderString,\n} from './render/eta-renderer.js';\nimport {\n deepMerge,\n loadPatch,\n loadSnippets,\n mergeSnippets,\n} from './patch/apply-patch.js';\nimport { emitManifest } from './emit/emit-manifest.js';\n\nexport interface BuildInputs {\n entity: EntityDefinition;\n selectedBlockIds: string[];\n context: RenderContext;\n}\n\nexport interface BuildResult {\n blocks: BlockDefinition[];\n files: RenderedFile[];\n manifest: ManifestPatch;\n snippets: ManifestSnippets;\n outRoot: string;\n}\n\n/**\n * Compose the full render result from a resolved entity + user selections.\n *\n * Steps:\n * 1. Resolve & topo-sort blocks (expanding requires, checking conflicts).\n * 2. Render every block's `files/` directory into in-memory RenderedFile[].\n * 3. Fold manifest patches and snippets in topological order.\n * 4. Compute `outRoot` from `entity.output` (also eta-rendered).\n *\n * No disk writes happen here — call `writeFiles()` afterward.\n */\nexport async function build(inputs: BuildInputs): Promise<BuildResult> {\n const { entity, selectedBlockIds, context } = inputs;\n\n const resolved = resolveBlocks(entity.blocks, selectedBlockIds);\n\n const files: RenderedFile[] = [];\n let manifest: ManifestPatch = {};\n let snippets: ManifestSnippets = {};\n\n for (const block of resolved.blocks) {\n const blockFiles = await renderFilesDir(block.filesDir, context);\n files.push(...blockFiles);\n\n if (block.manifestPatch) {\n const patch = await loadPatch(block.manifestPatch, context);\n manifest = deepMerge(manifest, patch);\n }\n if (block.snippetsPath) {\n const s = await loadSnippets(block.snippetsPath, context);\n snippets = mergeSnippets(snippets, s);\n }\n }\n\n const outTemplate = entity.output ?? join('.kb', 'plugins', '<%= it.name %>');\n const outRoot = renderString(outTemplate, context);\n\n if (entity.manifestTarget) {\n const manifestTarget = renderString(entity.manifestTarget, context);\n files.push({\n path: manifestTarget,\n contents: emitManifest(manifest, snippets),\n });\n }\n\n return { blocks: resolved.blocks, files, manifest, snippets, outRoot };\n}\n","import { readFile, readdir, stat } from 'node:fs/promises';\nimport { join, relative, resolve as resolvePath } from 'node:path';\n\nexport type Severity = 'info' | 'warn' | 'error';\n\nexport interface Finding {\n severity: Severity;\n package: string;\n message: string;\n}\n\nconst INTERNAL_IMPORT_RE =\n /from\\s+['\"](@kb-labs\\/(?:core-[a-z0-9-]+|platform-[a-z0-9-]+|core-platform(?:\\/[^'\"]+)?))['\"]/g;\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await stat(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readJson(p: string): Promise<Record<string, unknown>> {\n const raw = await readFile(p, 'utf8');\n return JSON.parse(raw) as Record<string, unknown>;\n}\n\nasync function walkSources(dir: string): Promise<string[]> {\n const out: string[] = [];\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name === 'node_modules' || entry.name === 'dist') continue;\n const p = join(dir, entry.name);\n if (entry.isDirectory()) {\n out.push(...(await walkSources(p)));\n } else if (\n entry.isFile() &&\n (entry.name.endsWith('.ts') || entry.name.endsWith('.tsx'))\n ) {\n out.push(p);\n }\n }\n return out;\n}\n\n/**\n * Scan a single package directory (one that contains `package.json`).\n */\nexport async function scanPackage(pkgDir: string): Promise<Finding[]> {\n const findings: Finding[] = [];\n const pkgJsonPath = join(pkgDir, 'package.json');\n if (!(await exists(pkgJsonPath))) {\n return [\n {\n severity: 'error',\n package: pkgDir,\n message: 'missing package.json',\n },\n ];\n }\n const pkg = await readJson(pkgJsonPath);\n const pkgName = typeof pkg.name === 'string' ? pkg.name : pkgDir;\n\n const kb = pkg.kb as Record<string, unknown> | undefined;\n const isEntry = kb && typeof kb.manifest === 'string';\n\n if (isEntry) {\n const manifestPath = join(pkgDir, kb.manifest as string);\n if (!(await exists(manifestPath))) {\n findings.push({\n severity: 'warn',\n package: pkgName,\n message: `manifest not built: ${kb.manifest} missing (run pnpm build)`,\n });\n }\n }\n\n const deps = (pkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (pkg.devDependencies ?? {}) as Record<string, string>;\n\n if (isEntry && !deps['@kb-labs/sdk'] && !devDeps['@kb-labs/sdk']) {\n findings.push({\n severity: 'error',\n package: pkgName,\n message: '@kb-labs/sdk not listed as a dependency',\n });\n }\n\n const srcDir = join(pkgDir, 'src');\n if (await exists(srcDir)) {\n const sources = await walkSources(srcDir);\n const offenders = new Set<string>();\n for (const file of sources) {\n const raw = await readFile(file, 'utf8');\n for (const match of raw.matchAll(INTERNAL_IMPORT_RE)) {\n if (match[1]) offenders.add(match[1]);\n }\n }\n if (offenders.size > 0) {\n findings.push({\n severity: 'warn',\n package: pkgName,\n message: `imports internal KB Labs packages: ${[...offenders].join(', ')} — use @kb-labs/sdk instead`,\n });\n }\n }\n\n const tsconfigPath = join(pkgDir, 'tsconfig.json');\n if (await exists(tsconfigPath)) {\n const tsconfig = await readJson(tsconfigPath);\n const extendsField = tsconfig.extends;\n if (\n typeof extendsField !== 'string' ||\n !extendsField.includes('@kb-labs/devkit')\n ) {\n findings.push({\n severity: 'info',\n package: pkgName,\n message:\n 'tsconfig does not extend @kb-labs/devkit — custom configs may drift',\n });\n }\n }\n\n return findings;\n}\n\nexport interface ScanResult {\n findings: Finding[];\n packagesScanned: number;\n}\n\ninterface LockEntry {\n resolvedPath?: string;\n enabled?: boolean;\n}\n\ninterface MarketplaceLockShape {\n installed?: Record<string, LockEntry>;\n}\n\nasync function readLock(\n workspaceRoot: string,\n): Promise<MarketplaceLockShape | null> {\n const lockPath = join(workspaceRoot, '.kb', 'marketplace.lock');\n if (!(await exists(lockPath))) return null;\n try {\n const raw = await readFile(lockPath, 'utf8');\n return JSON.parse(raw) as MarketplaceLockShape;\n } catch {\n return null;\n }\n}\n\nasync function findEntryPackageDir(pkgDir: string): Promise<string | null> {\n // If pkgDir itself has a kb-manifest entry, it's already the entry package.\n const pkgJsonPath = join(pkgDir, 'package.json');\n if (await exists(pkgJsonPath)) {\n const pkg = (await readJson(pkgJsonPath)) as { kb?: { manifest?: string } };\n if (pkg.kb?.manifest) return pkgDir;\n }\n // Otherwise look in packages/*-entry.\n const packagesDir = join(pkgDir, 'packages');\n if (!(await exists(packagesDir))) return null;\n const entries = await readdir(packagesDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (!entry.name.endsWith('-entry')) continue;\n const candidate = join(packagesDir, entry.name);\n if (await exists(join(candidate, 'package.json'))) return candidate;\n }\n return null;\n}\n\nexport interface ScanOptions {\n /**\n * Workspace root containing `.kb/marketplace.lock`. When provided, each\n * scaffolded plugin found is cross-checked against the lock — missing\n * entries surface as warnings so the user knows to `kb marketplace\n * plugins link` or rerun `kb scaffold`.\n */\n workspaceRoot?: string;\n}\n\n/**\n * Scan a root directory containing one or more plugin packages. A plugin\n * package has either:\n * - its own `package.json` at the root, or\n * - a `packages/` directory with child packages.\n *\n * When `opts.workspaceRoot` is given, also cross-checks every discovered\n * scaffolded plugin against `.kb/marketplace.lock`.\n */\nexport async function scanRoot(\n root: string,\n opts: ScanOptions = {},\n): Promise<ScanResult> {\n const findings: Finding[] = [];\n let packagesScanned = 0;\n\n async function visit(dir: string): Promise<void> {\n const pkgJson = join(dir, 'package.json');\n const packagesDir = join(dir, 'packages');\n if (await exists(pkgJson)) {\n findings.push(...(await scanPackage(dir)));\n packagesScanned += 1;\n }\n if (await exists(packagesDir)) {\n const entries = await readdir(packagesDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory()) await visit(join(packagesDir, entry.name));\n }\n }\n }\n\n if (!(await exists(root))) {\n return {\n findings: [\n {\n severity: 'warn',\n package: root,\n message: 'scan root does not exist',\n },\n ],\n packagesScanned: 0,\n };\n }\n\n const entries = await readdir(root, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory()) await visit(join(root, entry.name));\n }\n\n if (opts.workspaceRoot) {\n findings.push(...(await checkLockSync(root, opts.workspaceRoot)));\n }\n\n return { findings, packagesScanned };\n}\n\n/**\n * For each scaffolded plugin root under `scaffoldRoot`, verify that the\n * plugin's entry package is registered in `.kb/marketplace.lock`.\n *\n * Produces:\n * - warn \"plugin not registered in marketplace.lock (run `kb marketplace plugins link ...`)\"\n * - warn \"lock entry points elsewhere\"\n * - info \"plugin disabled in lock\"\n */\nasync function checkLockSync(\n scaffoldRoot: string,\n workspaceRoot: string,\n): Promise<Finding[]> {\n const out: Finding[] = [];\n const lock = await readLock(workspaceRoot);\n\n const entries = await readdir(scaffoldRoot, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const pluginDir = join(scaffoldRoot, entry.name);\n const entryPkgDir = await findEntryPackageDir(pluginDir);\n if (!entryPkgDir) continue;\n\n const pkg = (await readJson(join(entryPkgDir, 'package.json'))) as {\n name?: string;\n };\n const id = typeof pkg.name === 'string' ? pkg.name : entry.name;\n\n if (!lock || !lock.installed) {\n out.push({\n severity: 'warn',\n package: id,\n message:\n 'no .kb/marketplace.lock — scaffolded plugins will not be discovered until registered',\n });\n return out;\n }\n\n const lockEntry = lock.installed[id];\n if (!lockEntry) {\n const hint = relative(workspaceRoot, entryPkgDir);\n out.push({\n severity: 'warn',\n package: id,\n message: `not registered in marketplace.lock — run: kb marketplace plugins link ${hint}`,\n });\n continue;\n }\n\n if (lockEntry.enabled === false) {\n out.push({\n severity: 'info',\n package: id,\n message: 'registered but disabled in marketplace.lock',\n });\n }\n\n if (typeof lockEntry.resolvedPath === 'string') {\n const lockAbs = resolvePath(workspaceRoot, lockEntry.resolvedPath);\n if (lockAbs !== entryPkgDir) {\n out.push({\n severity: 'warn',\n package: id,\n message: `lock points at ${lockEntry.resolvedPath} but scaffolded package is at ${relative(workspaceRoot, entryPkgDir)}`,\n });\n }\n }\n }\n\n return out;\n}\n","const NAME_RE = /^[a-z][a-z0-9-]*$/;\nconst SCOPE_RE = /^@[a-z][a-z0-9-]*$/;\nconst SEMVER_RE = /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/;\nconst IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\nconst RESERVED_NAMES = new Set([\n 'kb',\n 'core',\n 'sdk',\n 'test',\n 'tests',\n 'node_modules',\n 'dist',\n 'src',\n 'con',\n 'prn',\n 'nul',\n]);\n\nexport function validatePackageName(name: string): string | null {\n if (!name) return 'name is required';\n if (name.length > 214) return 'name must be <= 214 chars';\n if (!NAME_RE.test(name)) {\n return 'name must be lowercase, start with a letter, and contain only a-z 0-9 -';\n }\n if (RESERVED_NAMES.has(name)) return `name \"${name}\" is reserved`;\n return null;\n}\n\nexport function validateScope(scope: string): string | null {\n if (!scope) return null;\n if (!SCOPE_RE.test(scope)) {\n return 'scope must look like \"@acme\" (lowercase, starts with @, a-z 0-9 -)';\n }\n return null;\n}\n\nexport function validateSemver(v: string): string | null {\n return SEMVER_RE.test(v) ? null : 'expected semver (e.g. 1.2.3)';\n}\n\nexport function validateIdentifier(v: string): string | null {\n return IDENTIFIER_RE.test(v) ? null : 'expected a JS identifier';\n}\n\nexport function runValidator(\n kind: string,\n value: unknown,\n): string | null {\n if (typeof value !== 'string') return 'expected a string';\n switch (kind) {\n case 'npmName':\n return validatePackageName(value);\n case 'npmScope':\n return validateScope(value);\n case 'semver':\n return validateSemver(value);\n case 'identifier':\n return validateIdentifier(value);\n default:\n return null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/loader/load-entity.ts","../src/resolver/resolve-blocks.ts","../src/render/eta-renderer.ts","../src/patch/apply-patch.ts","../src/writer/write-files.ts","../src/emit/emit-manifest.ts","../src/engine.ts","../src/doctor/scan.ts","../src/validators.ts"],"names":["parseYaml","readdir","join","readFile","stat","resolve","entries","relative","resolvePath"],"mappings":"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","file":"index.js","sourcesContent":["import { readFile, readdir, stat } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type {\n BlockDefinition,\n EntityDefinition,\n Variable,\n} from '@kb-labs/scaffold-contracts';\n\ninterface RawBlockYaml {\n id?: string;\n describe?: string;\n requires?: string[];\n conflicts?: string[];\n variables?: Variable[];\n manifestPatch?: string;\n snippets?: string;\n}\n\ninterface RawEntityYaml {\n id?: string;\n displayName?: string;\n description?: string;\n variables?: Variable[];\n defaults?: { blocks?: string[] };\n output?: string;\n manifestTarget?: string;\n}\n\nasync function pathExists(p: string): Promise<boolean> {\n try {\n await stat(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function loadBlock(blockDir: string): Promise<BlockDefinition> {\n const blockYamlPath = join(blockDir, 'block.yaml');\n const raw = await readFile(blockYamlPath, 'utf8');\n const parsed = parseYaml(raw) as RawBlockYaml;\n\n if (!parsed.id) {\n throw new Error(`block.yaml at ${blockYamlPath} is missing \"id\"`);\n }\n\n const filesDir = join(blockDir, 'files');\n const manifestPatchFile =\n parsed.manifestPatch ?? 'manifest.patch.yaml';\n const snippetsFile = parsed.snippets ?? 'manifest.snippets.yaml';\n\n const manifestPatchPath = join(blockDir, manifestPatchFile);\n const snippetsPath = join(blockDir, snippetsFile);\n\n const [hasFiles, hasPatch, hasSnippets] = await Promise.all([\n pathExists(filesDir),\n pathExists(manifestPatchPath),\n pathExists(snippetsPath),\n ]);\n\n return {\n id: parsed.id,\n describe: parsed.describe ?? parsed.id,\n requires: parsed.requires,\n conflicts: parsed.conflicts,\n variables: parsed.variables,\n filesDir: hasFiles ? filesDir : blockDir,\n manifestPatch: hasPatch ? manifestPatchPath : undefined,\n snippetsPath: hasSnippets ? snippetsPath : undefined,\n };\n}\n\n/**\n * Load an entity definition from a templates directory.\n *\n * @param templatesRoot directory containing `<entity>/entity.yaml` and `<entity>/blocks/*`\n * @param entityId e.g. 'plugin', 'adapter'\n */\nexport async function loadEntity(\n templatesRoot: string,\n entityId: string,\n): Promise<EntityDefinition> {\n const entityDir = resolve(templatesRoot, entityId);\n const entityYamlPath = join(entityDir, 'entity.yaml');\n\n if (!(await pathExists(entityYamlPath))) {\n throw new Error(\n `Entity \"${entityId}\" not found: ${entityYamlPath} does not exist`,\n );\n }\n\n const raw = await readFile(entityYamlPath, 'utf8');\n const parsed = (parseYaml(raw) ?? {}) as RawEntityYaml;\n\n const id = parsed.id ?? entityId;\n const blocksDir = join(entityDir, 'blocks');\n const blocks: BlockDefinition[] = [];\n\n if (await pathExists(blocksDir)) {\n const entries = await readdir(blocksDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) {continue;}\n const blockDir = join(blocksDir, entry.name);\n if (!(await pathExists(join(blockDir, 'block.yaml')))) {continue;}\n blocks.push(await loadBlock(blockDir));\n }\n }\n\n return {\n id,\n displayName: parsed.displayName ?? id,\n description: parsed.description,\n variables: parsed.variables ?? [],\n blocks,\n defaults: parsed.defaults,\n output: parsed.output,\n manifestTarget: parsed.manifestTarget,\n };\n}\n\n/**\n * List entity ids available in the templates root (directories with `entity.yaml`).\n */\nexport async function listEntities(templatesRoot: string): Promise<string[]> {\n if (!(await pathExists(templatesRoot))) {return [];}\n const entries = await readdir(templatesRoot, { withFileTypes: true });\n const result: string[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) {continue;}\n if (await pathExists(join(templatesRoot, entry.name, 'entity.yaml'))) {\n result.push(entry.name);\n }\n }\n return result.sort();\n}\n","import type { BlockDefinition } from '@kb-labs/scaffold-contracts';\n\nexport interface ResolveResult {\n /** Block ids in topological order (dependencies first). */\n ordered: string[];\n /** Full block definitions in the same order. */\n blocks: BlockDefinition[];\n}\n\n/**\n * Resolve a user-selected set of block ids into a topologically sorted list,\n * expanding `requires` and rejecting cycles or `conflicts` violations.\n */\nexport function resolveBlocks(\n all: BlockDefinition[],\n selected: string[],\n): ResolveResult {\n const byId = new Map<string, BlockDefinition>();\n for (const b of all) {byId.set(b.id, b);}\n\n const missing = selected.filter((id) => !byId.has(id));\n if (missing.length > 0) {\n throw new Error(`Unknown block(s): ${missing.join(', ')}`);\n }\n\n // Expand requires (BFS).\n const expanded = new Set<string>();\n const queue = [...selected];\n while (queue.length > 0) {\n const id = queue.shift()!;\n if (expanded.has(id)) {continue;}\n expanded.add(id);\n const block = byId.get(id);\n if (!block) {continue;}\n for (const dep of block.requires ?? []) {\n if (!byId.has(dep)) {\n throw new Error(\n `Block \"${id}\" requires unknown block \"${dep}\"`,\n );\n }\n if (!expanded.has(dep)) {queue.push(dep);}\n }\n }\n\n // Conflict check against the final expanded set.\n for (const id of expanded) {\n const block = byId.get(id)!;\n for (const other of block.conflicts ?? []) {\n if (expanded.has(other)) {\n throw new Error(\n `Block \"${id}\" conflicts with \"${other}\" — both selected`,\n );\n }\n }\n }\n\n // Topological sort (Kahn's algorithm).\n const inDegree = new Map<string, number>();\n const edges = new Map<string, Set<string>>();\n for (const id of expanded) {\n inDegree.set(id, 0);\n edges.set(id, new Set());\n }\n for (const id of expanded) {\n const block = byId.get(id)!;\n for (const dep of block.requires ?? []) {\n if (!expanded.has(dep)) {continue;}\n edges.get(dep)!.add(id);\n inDegree.set(id, (inDegree.get(id) ?? 0) + 1);\n }\n }\n\n const ready: string[] = [];\n for (const [id, deg] of inDegree) {if (deg === 0) {ready.push(id);}}\n ready.sort();\n\n const ordered: string[] = [];\n while (ready.length > 0) {\n const id = ready.shift()!;\n ordered.push(id);\n for (const next of edges.get(id) ?? []) {\n const d = (inDegree.get(next) ?? 0) - 1;\n inDegree.set(next, d);\n if (d === 0) {\n ready.push(next);\n ready.sort();\n }\n }\n }\n\n if (ordered.length !== expanded.size) {\n throw new Error('Cycle detected in block requires graph');\n }\n\n return { ordered, blocks: ordered.map((id) => byId.get(id)!) };\n}\n","import { readFile, readdir, stat } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport { Eta } from 'eta';\nimport type {\n RenderContext,\n RenderedFile,\n} from '@kb-labs/scaffold-contracts';\n\nconst eta = new Eta({\n autoEscape: false,\n useWith: true,\n tags: ['<%', '%>'],\n});\n\nconst ETA_SUFFIX = '.eta';\n\n/**\n * Render a single template string through eta using the given context.\n */\nexport function renderString(template: string, ctx: RenderContext): string {\n return eta.renderString(template, ctx);\n}\n\nasync function walk(dir: string): Promise<string[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n const out: string[] = [];\n for (const entry of entries) {\n const p = join(dir, entry.name);\n if (entry.isDirectory()) {\n out.push(...(await walk(p)));\n } else if (entry.isFile()) {\n out.push(p);\n }\n }\n return out;\n}\n\nfunction renderPath(relPath: string, ctx: RenderContext): string {\n // Use simple __var__ substitution for path segments — eta's `<% %>`\n // tags are illegal on Windows and awkward on Unix.\n const substituted = relPath\n .replace(/__name__/g, ctx.name)\n .replace(/__scope__/g, ctx.scope.replace(/^@/, ''));\n return substituted.endsWith(ETA_SUFFIX)\n ? substituted.slice(0, -ETA_SUFFIX.length)\n : substituted;\n}\n\n/**\n * Render all files under `filesDir`. File bodies AND path segments go through\n * eta. A trailing `.eta` extension on the file name is stripped after render.\n *\n * Returned paths are relative to `filesDir`. The caller decides the output root.\n */\nconst SKIP_MARKER = '<!--@@scaffold:skip@@-->';\n\nexport async function renderFilesDir(\n filesDir: string,\n ctx: RenderContext,\n): Promise<RenderedFile[]> {\n const absolutes = await walk(filesDir);\n const rendered: RenderedFile[] = [];\n for (const abs of absolutes) {\n const rel = relative(filesDir, abs);\n const renderedRel = renderPath(rel, ctx);\n const raw = await readFile(abs, 'utf8');\n const body = abs.endsWith(ETA_SUFFIX)\n ? renderString(raw, ctx)\n : raw;\n\n // Templates can opt out of a given file by emitting a skip marker.\n // Useful for files that should only exist in some modes (e.g.\n // pnpm-workspace.yaml only for standalone mode).\n if (body.trim() === SKIP_MARKER) {continue;}\n\n const st = await stat(abs);\n rendered.push({\n path: renderedRel,\n contents: body,\n executable: (st.mode & 0o111) !== 0,\n });\n }\n return rendered;\n}\n","import { readFile } from 'node:fs/promises';\nimport { parse as parseYaml } from 'yaml';\nimport type {\n ManifestPatch,\n ManifestSnippets,\n RenderContext,\n} from '@kb-labs/scaffold-contracts';\nimport { renderString } from '../render/eta-renderer.js';\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return (\n typeof v === 'object' &&\n v !== null &&\n !Array.isArray(v) &&\n Object.getPrototypeOf(v) === Object.prototype\n );\n}\n\nfunction mergeArrays(a: unknown[], b: unknown[]): unknown[] {\n const allObjects =\n a.every(isPlainObject) && b.every(isPlainObject) && a.length + b.length > 0;\n\n if (allObjects) {\n const keyOf = (x: Record<string, unknown>): string | null => {\n if (typeof x.id === 'string') {return `id:${x.id}`;}\n if (typeof x.name === 'string') {return `name:${x.name}`;}\n return null;\n };\n const allKeyed =\n a.every((x) => keyOf(x as Record<string, unknown>) !== null) &&\n b.every((x) => keyOf(x as Record<string, unknown>) !== null);\n\n if (allKeyed) {\n const byKey = new Map<string, Record<string, unknown>>();\n for (const item of [...a, ...b] as Record<string, unknown>[]) {\n const k = keyOf(item)!;\n const prev = byKey.get(k);\n byKey.set(k, prev ? deepMerge(prev, item) : item);\n }\n return [...byKey.values()];\n }\n }\n\n // Primitive or mixed: Set-dedupe where possible.\n const seen = new Set<string>();\n const out: unknown[] = [];\n for (const item of [...a, ...b]) {\n const key = JSON.stringify(item);\n if (seen.has(key)) {continue;}\n seen.add(key);\n out.push(item);\n }\n return out;\n}\n\nexport function deepMerge(\n target: Record<string, unknown>,\n patch: Record<string, unknown>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = { ...target };\n for (const [key, value] of Object.entries(patch)) {\n const existing = out[key];\n if (isPlainObject(existing) && isPlainObject(value)) {\n out[key] = deepMerge(existing, value);\n } else if (Array.isArray(existing) && Array.isArray(value)) {\n out[key] = mergeArrays(existing, value);\n } else {\n out[key] = value;\n }\n }\n return out;\n}\n\n/**\n * Load a manifest.patch.yaml from disk, render it through eta with the\n * render context, parse as YAML, and return the resulting object.\n */\nexport async function loadPatch(\n path: string,\n ctx: RenderContext,\n): Promise<ManifestPatch> {\n const raw = await readFile(path, 'utf8');\n const rendered = renderString(raw, ctx);\n const parsed = parseYaml(rendered);\n if (parsed == null) {return {};}\n if (!isPlainObject(parsed)) {\n throw new Error(`Patch at ${path} must be a YAML object`);\n }\n return parsed;\n}\n\nexport async function loadSnippets(\n path: string,\n ctx: RenderContext,\n): Promise<ManifestSnippets> {\n const raw = await readFile(path, 'utf8');\n const rendered = renderString(raw, ctx);\n const parsed = parseYaml(rendered);\n if (parsed == null) {return {};}\n if (!isPlainObject(parsed)) {\n throw new Error(`Snippets at ${path} must be a YAML object`);\n }\n return parsed as ManifestSnippets;\n}\n\nexport function mergeSnippets(\n a: ManifestSnippets,\n b: ManifestSnippets,\n): ManifestSnippets {\n const mergedExtras: Record<string, string[]> = { ...(a.extras ?? {}) };\n for (const [k, v] of Object.entries(b.extras ?? {})) {\n mergedExtras[k] = dedupe([...(mergedExtras[k] ?? []), ...v]);\n }\n return {\n imports: dedupe([...(a.imports ?? []), ...(b.imports ?? [])]),\n permissions: dedupe([\n ...(a.permissions ?? []),\n ...(b.permissions ?? []),\n ]),\n extras: Object.keys(mergedExtras).length > 0 ? mergedExtras : undefined,\n };\n}\n\nfunction dedupe(items: string[]): string[] {\n return [...new Set(items)];\n}\n","import { mkdir, writeFile, chmod, stat, readdir, rm } from 'node:fs/promises';\nimport { dirname, join, resolve } from 'node:path';\nimport type { RenderedFile } from '@kb-labs/scaffold-contracts';\n\nexport interface WriteOptions {\n outRoot: string;\n files: RenderedFile[];\n /** If set, wipe the root first. */\n force?: boolean;\n}\n\nexport interface TargetState {\n exists: boolean;\n empty: boolean;\n}\n\nexport async function inspectTarget(outRoot: string): Promise<TargetState> {\n try {\n const st = await stat(outRoot);\n if (!st.isDirectory()) {return { exists: true, empty: false };}\n const entries = await readdir(outRoot);\n return { exists: true, empty: entries.length === 0 };\n } catch {\n return { exists: false, empty: true };\n }\n}\n\n/**\n * Detect intra-batch path collisions. Two blocks writing the same path is a\n * configuration bug, not a merge case.\n */\nexport function detectCollisions(files: RenderedFile[]): string[] {\n const seen = new Map<string, number>();\n for (const f of files) {\n seen.set(f.path, (seen.get(f.path) ?? 0) + 1);\n }\n return [...seen.entries()]\n .filter(([, n]) => n > 1)\n .map(([p]) => p);\n}\n\n/**\n * Write the rendered file set to disk. If `force` is set and the root\n * exists, it is wiped first. Otherwise the caller is responsible for\n * ensuring the root is absent or empty — see `inspectTarget`.\n */\nexport async function writeFiles(opts: WriteOptions): Promise<void> {\n const { outRoot, files, force } = opts;\n const abs = resolve(outRoot);\n\n const collisions = detectCollisions(files);\n if (collisions.length > 0) {\n throw new Error(\n `Block path collisions detected: ${collisions.join(', ')}`,\n );\n }\n\n if (force) {\n await rm(abs, { recursive: true, force: true });\n }\n\n await mkdir(abs, { recursive: true });\n\n for (const file of files) {\n const target = join(abs, file.path);\n await mkdir(dirname(target), { recursive: true });\n await writeFile(target, file.contents, 'utf8');\n if (file.executable) {\n await chmod(target, 0o755);\n }\n }\n}\n\n/**\n * Produce a human-readable tree of the files that would be written.\n */\nexport function formatTree(files: RenderedFile[]): string {\n return files\n .map((f) => f.path)\n .sort()\n .map((p) => ` ${p}`)\n .join('\\n');\n}\n","import type {\n ManifestPatch,\n ManifestSnippets,\n} from '@kb-labs/scaffold-contracts';\n\n/**\n * Emit a TypeScript source file for the plugin V3 manifest.\n *\n * The manifest object is stringified as a JSON literal. A `permissions`\n * expression is assembled from `combinePermissions()` snippets contributed\n * by blocks and spread in alongside. Imports are deduped at the top.\n */\nexport function emitManifest(\n manifest: ManifestPatch,\n snippets: ManifestSnippets,\n): string {\n const importLines = [...(snippets.imports ?? [])];\n const hasCombine = importLines.some((l) =>\n /\\bcombinePermissions\\b/.test(l),\n );\n if (!hasCombine) {\n importLines.unshift(\n \"import { combinePermissions } from '@kb-labs/sdk';\",\n );\n }\n const importSet = new Set<string>(importLines);\n\n const permLines = snippets.permissions ?? [];\n const permExpr =\n permLines.length > 0\n ? `combinePermissions()\\n ${permLines.map((l) => `.${l}`).join('\\n ')}\\n .build()`\n : 'combinePermissions().build()';\n\n const body = JSON.stringify(manifest, null, 2);\n\n return `/**\n * V3 plugin manifest. Scaffolded by @kb-labs/scaffold.\n *\n * Edit freely — this is your plugin's public surface. Add commands by\n * appending to \\`cli.commands[]\\`, REST routes under \\`rest.routes[]\\`,\n * Studio pages under \\`studio\\`. Consult neighbouring plugins\n * (\\`plugins/commit\\`, \\`plugins/review\\`) for reference shapes.\n */\n${[...importSet].join('\\n')}\n\nconst permissions = ${permExpr};\n\nconst manifest = ${body} as const;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst withPermissions: typeof manifest & { permissions: any } = { ...manifest, permissions };\n\nexport default withPermissions;\n`;\n}\n","import { join } from 'node:path';\nimport type {\n BlockDefinition,\n EntityDefinition,\n ManifestPatch,\n ManifestSnippets,\n RenderContext,\n RenderedFile,\n} from '@kb-labs/scaffold-contracts';\nimport { resolveBlocks } from './resolver/resolve-blocks.js';\nimport {\n renderFilesDir,\n renderString,\n} from './render/eta-renderer.js';\nimport {\n deepMerge,\n loadPatch,\n loadSnippets,\n mergeSnippets,\n} from './patch/apply-patch.js';\nimport { emitManifest } from './emit/emit-manifest.js';\n\nexport interface BuildInputs {\n entity: EntityDefinition;\n selectedBlockIds: string[];\n context: RenderContext;\n}\n\nexport interface BuildResult {\n blocks: BlockDefinition[];\n files: RenderedFile[];\n manifest: ManifestPatch;\n snippets: ManifestSnippets;\n outRoot: string;\n}\n\n/**\n * Compose the full render result from a resolved entity + user selections.\n *\n * Steps:\n * 1. Resolve & topo-sort blocks (expanding requires, checking conflicts).\n * 2. Render every block's `files/` directory into in-memory RenderedFile[].\n * 3. Fold manifest patches and snippets in topological order.\n * 4. Compute `outRoot` from `entity.output` (also eta-rendered).\n *\n * No disk writes happen here — call `writeFiles()` afterward.\n */\nexport async function build(inputs: BuildInputs): Promise<BuildResult> {\n const { entity, selectedBlockIds, context } = inputs;\n\n const resolved = resolveBlocks(entity.blocks, selectedBlockIds);\n\n const files: RenderedFile[] = [];\n let manifest: ManifestPatch = {};\n let snippets: ManifestSnippets = {};\n\n for (const block of resolved.blocks) {\n const blockFiles = await renderFilesDir(block.filesDir, context);\n files.push(...blockFiles);\n\n if (block.manifestPatch) {\n const patch = await loadPatch(block.manifestPatch, context);\n manifest = deepMerge(manifest, patch);\n }\n if (block.snippetsPath) {\n const s = await loadSnippets(block.snippetsPath, context);\n snippets = mergeSnippets(snippets, s);\n }\n }\n\n const outTemplate = entity.output ?? join('.kb', 'plugins', '<%= it.name %>');\n const outRoot = renderString(outTemplate, context);\n\n if (entity.manifestTarget) {\n const manifestTarget = renderString(entity.manifestTarget, context);\n files.push({\n path: manifestTarget,\n contents: emitManifest(manifest, snippets),\n });\n }\n\n return { blocks: resolved.blocks, files, manifest, snippets, outRoot };\n}\n","import { readFile, readdir, stat } from 'node:fs/promises';\nimport { join, relative, resolve as resolvePath } from 'node:path';\n\nexport type Severity = 'info' | 'warn' | 'error';\n\nexport interface Finding {\n severity: Severity;\n package: string;\n message: string;\n}\n\nconst INTERNAL_IMPORT_RE =\n /from\\s+['\"](@kb-labs\\/(?:core-[a-z0-9-]+|platform-[a-z0-9-]+|core-platform(?:\\/[^'\"]+)?))['\"]/g;\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await stat(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readJson(p: string): Promise<Record<string, unknown>> {\n const raw = await readFile(p, 'utf8');\n return JSON.parse(raw) as Record<string, unknown>;\n}\n\nasync function walkSources(dir: string): Promise<string[]> {\n const out: string[] = [];\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name === 'node_modules' || entry.name === 'dist') {continue;}\n const p = join(dir, entry.name);\n if (entry.isDirectory()) {\n out.push(...(await walkSources(p)));\n } else if (\n entry.isFile() &&\n (entry.name.endsWith('.ts') || entry.name.endsWith('.tsx'))\n ) {\n out.push(p);\n }\n }\n return out;\n}\n\n/**\n * Scan a single package directory (one that contains `package.json`).\n */\nexport async function scanPackage(pkgDir: string): Promise<Finding[]> {\n const findings: Finding[] = [];\n const pkgJsonPath = join(pkgDir, 'package.json');\n if (!(await exists(pkgJsonPath))) {\n return [\n {\n severity: 'error',\n package: pkgDir,\n message: 'missing package.json',\n },\n ];\n }\n const pkg = await readJson(pkgJsonPath);\n const pkgName = typeof pkg.name === 'string' ? pkg.name : pkgDir;\n\n const kb = pkg.kb as Record<string, unknown> | undefined;\n const isEntry = kb && typeof kb.manifest === 'string';\n\n if (isEntry) {\n const manifestPath = join(pkgDir, kb.manifest as string);\n if (!(await exists(manifestPath))) {\n findings.push({\n severity: 'warn',\n package: pkgName,\n message: `manifest not built: ${kb.manifest} missing (run pnpm build)`,\n });\n }\n }\n\n const deps = (pkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (pkg.devDependencies ?? {}) as Record<string, string>;\n\n if (isEntry && !deps['@kb-labs/sdk'] && !devDeps['@kb-labs/sdk']) {\n findings.push({\n severity: 'error',\n package: pkgName,\n message: '@kb-labs/sdk not listed as a dependency',\n });\n }\n\n const srcDir = join(pkgDir, 'src');\n if (await exists(srcDir)) {\n const sources = await walkSources(srcDir);\n const offenders = new Set<string>();\n for (const file of sources) {\n const raw = await readFile(file, 'utf8');\n for (const match of raw.matchAll(INTERNAL_IMPORT_RE)) {\n if (match[1]) {offenders.add(match[1]);}\n }\n }\n if (offenders.size > 0) {\n findings.push({\n severity: 'warn',\n package: pkgName,\n message: `imports internal KB Labs packages: ${[...offenders].join(', ')} — use @kb-labs/sdk instead`,\n });\n }\n }\n\n const tsconfigPath = join(pkgDir, 'tsconfig.json');\n if (await exists(tsconfigPath)) {\n const tsconfig = await readJson(tsconfigPath);\n const extendsField = tsconfig.extends;\n if (\n typeof extendsField !== 'string' ||\n !extendsField.includes('@kb-labs/devkit')\n ) {\n findings.push({\n severity: 'info',\n package: pkgName,\n message:\n 'tsconfig does not extend @kb-labs/devkit — custom configs may drift',\n });\n }\n }\n\n return findings;\n}\n\nexport interface ScanResult {\n findings: Finding[];\n packagesScanned: number;\n}\n\ninterface LockEntry {\n resolvedPath?: string;\n enabled?: boolean;\n}\n\ninterface MarketplaceLockShape {\n installed?: Record<string, LockEntry>;\n}\n\nasync function readLock(\n workspaceRoot: string,\n): Promise<MarketplaceLockShape | null> {\n const lockPath = join(workspaceRoot, '.kb', 'marketplace.lock');\n if (!(await exists(lockPath))) {return null;}\n try {\n const raw = await readFile(lockPath, 'utf8');\n return JSON.parse(raw) as MarketplaceLockShape;\n } catch {\n return null;\n }\n}\n\nasync function findEntryPackageDir(pkgDir: string): Promise<string | null> {\n // If pkgDir itself has a kb-manifest entry, it's already the entry package.\n const pkgJsonPath = join(pkgDir, 'package.json');\n if (await exists(pkgJsonPath)) {\n const pkg = (await readJson(pkgJsonPath)) as { kb?: { manifest?: string } };\n if (pkg.kb?.manifest) {return pkgDir;}\n }\n // Otherwise look in packages/*-entry.\n const packagesDir = join(pkgDir, 'packages');\n if (!(await exists(packagesDir))) {return null;}\n const entries = await readdir(packagesDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) {continue;}\n if (!entry.name.endsWith('-entry')) {continue;}\n const candidate = join(packagesDir, entry.name);\n if (await exists(join(candidate, 'package.json'))) {return candidate;}\n }\n return null;\n}\n\nexport interface ScanOptions {\n /**\n * Workspace root containing `.kb/marketplace.lock`. When provided, each\n * scaffolded plugin found is cross-checked against the lock — missing\n * entries surface as warnings so the user knows to `kb marketplace\n * plugins link` or rerun `kb scaffold`.\n */\n workspaceRoot?: string;\n}\n\n/**\n * Scan a root directory containing one or more plugin packages. A plugin\n * package has either:\n * - its own `package.json` at the root, or\n * - a `packages/` directory with child packages.\n *\n * When `opts.workspaceRoot` is given, also cross-checks every discovered\n * scaffolded plugin against `.kb/marketplace.lock`.\n */\nexport async function scanRoot(\n root: string,\n opts: ScanOptions = {},\n): Promise<ScanResult> {\n const findings: Finding[] = [];\n let packagesScanned = 0;\n\n async function visit(dir: string): Promise<void> {\n const pkgJson = join(dir, 'package.json');\n const packagesDir = join(dir, 'packages');\n if (await exists(pkgJson)) {\n findings.push(...(await scanPackage(dir)));\n packagesScanned += 1;\n }\n if (await exists(packagesDir)) {\n const entries = await readdir(packagesDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory()) {await visit(join(packagesDir, entry.name));}\n }\n }\n }\n\n if (!(await exists(root))) {\n return {\n findings: [\n {\n severity: 'warn',\n package: root,\n message: 'scan root does not exist',\n },\n ],\n packagesScanned: 0,\n };\n }\n\n const entries = await readdir(root, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory()) {await visit(join(root, entry.name));}\n }\n\n if (opts.workspaceRoot) {\n findings.push(...(await checkLockSync(root, opts.workspaceRoot)));\n }\n\n return { findings, packagesScanned };\n}\n\n/**\n * For each scaffolded plugin root under `scaffoldRoot`, verify that the\n * plugin's entry package is registered in `.kb/marketplace.lock`.\n *\n * Produces:\n * - warn \"plugin not registered in marketplace.lock (run `kb marketplace plugins link ...`)\"\n * - warn \"lock entry points elsewhere\"\n * - info \"plugin disabled in lock\"\n */\nasync function checkLockSync(\n scaffoldRoot: string,\n workspaceRoot: string,\n): Promise<Finding[]> {\n const out: Finding[] = [];\n const lock = await readLock(workspaceRoot);\n\n const entries = await readdir(scaffoldRoot, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) {continue;}\n const pluginDir = join(scaffoldRoot, entry.name);\n const entryPkgDir = await findEntryPackageDir(pluginDir);\n if (!entryPkgDir) {continue;}\n\n const pkg = (await readJson(join(entryPkgDir, 'package.json'))) as {\n name?: string;\n };\n const id = typeof pkg.name === 'string' ? pkg.name : entry.name;\n\n if (!lock || !lock.installed) {\n out.push({\n severity: 'warn',\n package: id,\n message:\n 'no .kb/marketplace.lock — scaffolded plugins will not be discovered until registered',\n });\n return out;\n }\n\n const lockEntry = lock.installed[id];\n if (!lockEntry) {\n const hint = relative(workspaceRoot, entryPkgDir);\n out.push({\n severity: 'warn',\n package: id,\n message: `not registered in marketplace.lock — run: kb marketplace plugins link ${hint}`,\n });\n continue;\n }\n\n if (lockEntry.enabled === false) {\n out.push({\n severity: 'info',\n package: id,\n message: 'registered but disabled in marketplace.lock',\n });\n }\n\n if (typeof lockEntry.resolvedPath === 'string') {\n const lockAbs = resolvePath(workspaceRoot, lockEntry.resolvedPath);\n if (lockAbs !== entryPkgDir) {\n out.push({\n severity: 'warn',\n package: id,\n message: `lock points at ${lockEntry.resolvedPath} but scaffolded package is at ${relative(workspaceRoot, entryPkgDir)}`,\n });\n }\n }\n }\n\n return out;\n}\n","const NAME_RE = /^[a-z][a-z0-9-]*$/;\nconst SCOPE_RE = /^@[a-z][a-z0-9-]*$/;\nconst SEMVER_RE = /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/;\nconst IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\nconst RESERVED_NAMES = new Set([\n 'kb',\n 'core',\n 'sdk',\n 'test',\n 'tests',\n 'node_modules',\n 'dist',\n 'src',\n 'con',\n 'prn',\n 'nul',\n]);\n\nexport function validatePackageName(name: string): string | null {\n if (!name) {return 'name is required';}\n if (name.length > 214) {return 'name must be <= 214 chars';}\n if (!NAME_RE.test(name)) {\n return 'name must be lowercase, start with a letter, and contain only a-z 0-9 -';\n }\n if (RESERVED_NAMES.has(name)) {return `name \"${name}\" is reserved`;}\n return null;\n}\n\nexport function validateScope(scope: string): string | null {\n if (!scope) {return null;}\n if (!SCOPE_RE.test(scope)) {\n return 'scope must look like \"@acme\" (lowercase, starts with @, a-z 0-9 -)';\n }\n return null;\n}\n\nexport function validateSemver(v: string): string | null {\n return SEMVER_RE.test(v) ? null : 'expected semver (e.g. 1.2.3)';\n}\n\nexport function validateIdentifier(v: string): string | null {\n return IDENTIFIER_RE.test(v) ? null : 'expected a JS identifier';\n}\n\nexport function runValidator(\n kind: string,\n value: unknown,\n): string | null {\n if (typeof value !== 'string') {return 'expected a string';}\n switch (kind) {\n case 'npmName':\n return validatePackageName(value);\n case 'npmScope':\n return validateScope(value);\n case 'semver':\n return validateSemver(value);\n case 'identifier':\n return validateIdentifier(value);\n default:\n return null;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kb-labs/scaffold-core",
|
|
3
|
-
"version": "2.34.0",
|
|
4
|
-
"type": "module",
|
|
5
3
|
"description": "Pure engine for the KB Labs scaffolder: loader, resolver, renderer, patch merger, writer.",
|
|
4
|
+
"version": "2.35.0",
|
|
5
|
+
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
-
"
|
|
11
|
-
"
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
12
|
},
|
|
13
13
|
"./dist/*": "./dist/*"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
|
-
"sideEffects": false,
|
|
19
18
|
"dependencies": {
|
|
20
19
|
"eta": "^3.5.0",
|
|
21
20
|
"yaml": "^2.6.1",
|
|
22
|
-
"@kb-labs/scaffold-contracts": "2.
|
|
21
|
+
"@kb-labs/scaffold-contracts": "2.35.0"
|
|
23
22
|
},
|
|
24
23
|
"devDependencies": {
|
|
25
24
|
"@types/node": "^24.3.3",
|
|
@@ -28,20 +27,21 @@
|
|
|
28
27
|
"tsup": "^8.5.0",
|
|
29
28
|
"typescript": "^5.6.3",
|
|
30
29
|
"vitest": "^3.2.4",
|
|
31
|
-
"@kb-labs/devkit": "2.
|
|
30
|
+
"@kb-labs/devkit": "2.35.0"
|
|
32
31
|
},
|
|
33
32
|
"engines": {
|
|
34
33
|
"node": ">=20.0.0",
|
|
35
34
|
"pnpm": ">=9.0.0"
|
|
36
35
|
},
|
|
36
|
+
"sideEffects": false,
|
|
37
37
|
"scripts": {
|
|
38
|
-
"clean": "rimraf dist",
|
|
39
38
|
"build": "tsup --config tsup.config.ts",
|
|
39
|
+
"clean": "rimraf dist",
|
|
40
40
|
"dev": "tsup --config tsup.config.ts --watch",
|
|
41
41
|
"lint": "eslint src --ext .ts",
|
|
42
42
|
"lint:fix": "eslint . --fix",
|
|
43
|
-
"type-check": "tsc --noEmit",
|
|
44
43
|
"test": "vitest run --passWithNoTests",
|
|
45
|
-
"test:watch": "vitest"
|
|
44
|
+
"test:watch": "vitest",
|
|
45
|
+
"type-check": "tsc --noEmit"
|
|
46
46
|
}
|
|
47
47
|
}
|