@kb-labs/scaffold 2.30.0 → 2.32.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.
|
@@ -34,7 +34,8 @@ async function readVersion(pkgPath) {
|
|
|
34
34
|
}
|
|
35
35
|
var FALLBACK_VERSIONS = {
|
|
36
36
|
sdk: "2.18.0",
|
|
37
|
-
devkit: "2.28.0"
|
|
37
|
+
devkit: "2.28.0",
|
|
38
|
+
commandKit: "2.30.0"
|
|
38
39
|
};
|
|
39
40
|
async function detectVersions() {
|
|
40
41
|
const req = createRequire(import.meta.url);
|
|
@@ -47,11 +48,12 @@ async function detectVersions() {
|
|
|
47
48
|
return fallback;
|
|
48
49
|
}
|
|
49
50
|
};
|
|
50
|
-
const [sdk, devkit] = await Promise.all([
|
|
51
|
+
const [sdk, devkit, commandKit] = await Promise.all([
|
|
51
52
|
readPkg("@kb-labs/sdk/package.json", FALLBACK_VERSIONS.sdk),
|
|
52
|
-
readPkg("@kb-labs/devkit/package.json", FALLBACK_VERSIONS.devkit)
|
|
53
|
+
readPkg("@kb-labs/devkit/package.json", FALLBACK_VERSIONS.devkit),
|
|
54
|
+
readPkg("@kb-labs/shared-command-kit/package.json", FALLBACK_VERSIONS.commandKit)
|
|
53
55
|
]);
|
|
54
|
-
return { sdk, devkit };
|
|
56
|
+
return { sdk, devkit, commandKit };
|
|
55
57
|
}
|
|
56
58
|
function parsePositional(argv) {
|
|
57
59
|
if (!argv || argv.length === 0) return {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/ui/prompt.ts","../../src/commands/scaffold.ts"],"names":["clackOutro","runValidator"],"mappings":"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","file":"scaffold.js","sourcesContent":["import {\n intro as clackIntro,\n outro as clackOutro,\n text,\n confirm,\n select,\n multiselect,\n isCancel,\n cancel,\n log,\n} from '@clack/prompts';\nimport type { Variable } from '@kb-labs/scaffold-contracts';\nimport { runValidator } from '@kb-labs/scaffold-core';\n\nexport function intro(msg: string): void {\n clackIntro(msg);\n}\nexport function outro(msg: string): void {\n clackOutro(msg);\n}\n\nexport function info(msg: string): void {\n log.info(msg);\n}\nexport function warn(msg: string): void {\n log.warn(msg);\n}\nexport function error(msg: string): void {\n log.error(msg);\n}\n\nfunction abortOnCancel<T>(value: T | symbol): T {\n if (isCancel(value)) {\n cancel('Aborted.');\n process.exit(130);\n }\n return value as T;\n}\n\nexport async function askVariable(\n variable: Variable,\n defaults: Record<string, unknown>,\n): Promise<unknown> {\n const preset = defaults[variable.name] ?? variable.default;\n\n switch (variable.type) {\n case 'boolean': {\n const result = await confirm({\n message: variable.describe,\n initialValue: typeof preset === 'boolean' ? preset : false,\n });\n return abortOnCancel(result);\n }\n case 'select': {\n if (!variable.choices || variable.choices.length === 0) {\n throw new Error(`Variable \"${variable.name}\" is select but has no choices`);\n }\n const result = await select({\n message: variable.describe,\n options: variable.choices.map((c) => ({ value: c.value, label: c.label })),\n initialValue: (preset as string) ?? variable.choices[0]?.value,\n });\n return abortOnCancel(result);\n }\n case 'multiselect': {\n if (!variable.choices || variable.choices.length === 0) {\n throw new Error(`Variable \"${variable.name}\" is multiselect but has no choices`);\n }\n const result = await multiselect({\n message: variable.describe,\n options: variable.choices.map((c) => ({ value: c.value, label: c.label })),\n initialValues: Array.isArray(preset) ? (preset as string[]) : [],\n required: false,\n });\n return abortOnCancel(result);\n }\n case 'string':\n default: {\n const result = await text({\n message: variable.describe,\n initialValue: typeof preset === 'string' ? preset : '',\n validate: variable.validate\n ? (value: string) => runValidator(variable.validate!, value) ?? undefined\n : undefined,\n });\n return abortOnCancel(result);\n }\n }\n}\n\nexport async function askBlocks(\n options: { value: string; label: string; hint?: string }[],\n initialValues: string[],\n): Promise<string[]> {\n const result = await multiselect({\n message: 'Pick blocks to include',\n options,\n initialValues,\n required: true,\n });\n return abortOnCancel(result) as string[];\n}\n\nexport async function confirmOverwrite(path: string): Promise<boolean> {\n const result = await confirm({\n message: `Target \"${path}\" is not empty. Overwrite?`,\n initialValue: false,\n });\n return abortOnCancel(result);\n}\n","import { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createRequire } from 'node:module';\nimport { readFile } from 'node:fs/promises';\nimport {\n defineCommand,\n type PluginContextV3,\n type CLIInput,\n} from '@kb-labs/sdk';\nimport {\n build,\n inspectTarget,\n formatTree,\n listEntities,\n loadEntity,\n resolveBlocks,\n runValidator,\n writeFiles,\n} from '@kb-labs/scaffold-core';\nimport type {\n RenderContext,\n} from '@kb-labs/scaffold-contracts';\nimport {\n error,\n info,\n outro,\n warn,\n} from '../ui/prompt.js';\n\nconst here = dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_ROOT = resolve(here, '..', '..', 'templates');\n\ninterface ScaffoldFlags {\n blocks?: string;\n yes?: boolean;\n force?: boolean;\n 'dry-run'?: boolean;\n out?: string;\n scope?: string;\n mode?: string;\n}\n\ntype ScaffoldResult = {\n exitCode: number;\n result?: { outRoot: string; files: number };\n};\n\nasync function readVersion(pkgPath: string): Promise<string> {\n try {\n const raw = await readFile(pkgPath, 'utf8');\n const parsed = JSON.parse(raw) as { version?: string };\n return parsed.version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\n// Conservative fallbacks — bumped when we cut a new scaffold release.\nconst FALLBACK_VERSIONS = {\n sdk: '2.18.0',\n devkit: '2.28.0',\n} as const;\n\nasync function detectVersions(): Promise<Record<string, string>> {\n // Use require.resolve from this module as the anchor. Works under pnpm's\n // virtual store because createRequire follows node's resolution rules.\n const req = createRequire(import.meta.url);\n const readPkg = async (\n spec: string,\n fallback: string,\n ): Promise<string> => {\n try {\n const resolved = req.resolve(spec);\n const v = await readVersion(resolved);\n return v === '0.0.0' ? fallback : v;\n } catch {\n return fallback;\n }\n };\n const [sdk, devkit] = await Promise.all([\n readPkg('@kb-labs/sdk/package.json', FALLBACK_VERSIONS.sdk),\n readPkg('@kb-labs/devkit/package.json', FALLBACK_VERSIONS.devkit),\n ]);\n return { sdk, devkit };\n}\n\nfunction parsePositional(argv: string[] | undefined): {\n entity?: string;\n name?: string;\n} {\n if (!argv || argv.length === 0) return {};\n const positional = argv.filter((a) => !a.startsWith('-'));\n return { entity: positional[0], name: positional[1] };\n}\n\nasync function runDefault(\n ctx: PluginContextV3,\n rawInput: CLIInput<ScaffoldFlags>,\n): Promise<ScaffoldResult> {\n const input = { ...rawInput.flags, argv: rawInput.argv };\n\n const { entity: entityArg, name: nameArg } = parsePositional(input.argv);\n\n const available = await listEntities(TEMPLATES_ROOT);\n if (available.length === 0) {\n error(`No entities found in templates root: ${TEMPLATES_ROOT}`);\n return { exitCode: 1 };\n }\n\n // Resolve entity.\n const entityId = entityArg ?? available[0]!;\n if (!available.includes(entityId)) {\n error(`Unknown entity: ${entityId}. Available: ${available.join(', ')}`);\n return { exitCode: 1 };\n }\n\n const entity = await loadEntity(TEMPLATES_ROOT, entityId);\n\n // Resolve name — required positional.\n if (!nameArg) {\n error('Usage: kb scaffold run <entity> <name> [flags]');\n return { exitCode: 1 };\n }\n const problem = runValidator('npmName', nameArg);\n if (problem) {\n error(`Invalid name \"${nameArg}\": ${problem}`);\n return { exitCode: 1 };\n }\n const name = nameArg;\n\n // Collect entity-level variables — flags override, then entity defaults.\n const vars: Record<string, unknown> = {};\n for (const v of entity.variables) {\n if (v.name === 'scope' && input.scope !== undefined) {\n vars[v.name] = input.scope;\n } else if (v.name === 'mode' && input.mode !== undefined) {\n vars[v.name] = input.mode;\n } else {\n vars[v.name] = v.default ?? '';\n }\n }\n\n // Select blocks — flag overrides, then entity defaults.\n let selectedBlocks: string[];\n if (input.blocks) {\n selectedBlocks = input.blocks\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n } else {\n selectedBlocks = entity.defaults?.blocks ?? entity.blocks.map((b) => b.id);\n }\n\n // Collect block-specific variables — use defaults.\n try {\n resolveBlocks(entity.blocks, selectedBlocks);\n } catch (e) {\n error((e as Error).message);\n return { exitCode: 1 };\n }\n for (const blockId of selectedBlocks) {\n const block = entity.blocks.find((b) => b.id === blockId);\n for (const v of block?.variables ?? []) {\n vars[v.name] = v.default ?? '';\n }\n }\n\n const scope = (vars.scope as string) ?? input.scope ?? '';\n const mode = (input.mode ?? (vars.mode as string) ?? 'in-workspace') as\n | 'in-workspace'\n | 'standalone';\n\n const versions = await detectVersions();\n\n const context: RenderContext = {\n name,\n scope,\n vars,\n blocks: selectedBlocks,\n mode,\n versions,\n };\n\n const result = await build({\n entity,\n selectedBlockIds: selectedBlocks,\n context,\n });\n\n const outRoot = input.out ?? result.outRoot;\n const state = await inspectTarget(outRoot);\n\n if (input['dry-run']) {\n info(`Would write to: ${outRoot}`);\n info('Tree:');\n info(formatTree(result.files));\n outro('Dry run complete.');\n return { exitCode: 0, result: { outRoot, files: result.files.length } };\n }\n\n if (state.exists && !state.empty) {\n if (input.force) {\n warn(`--force: overwriting ${outRoot}`);\n } else {\n error(`Target \"${outRoot}\" is not empty. Use --force to overwrite.`);\n return { exitCode: 1 };\n }\n }\n\n await writeFiles({ outRoot, files: result.files, force: input.force });\n\n ctx.ui?.success?.(`Scaffolded ${entityId} \"${name}\"`);\n info(`Output: ${outRoot}`);\n\n // The package that carries `\"kb\": { \"manifest\": \"...\" }` is the target\n // marketplace.link needs. For plugin entity → <outRoot>/packages/<name>-entry.\n // For adapter entity → <outRoot> itself.\n const entryPkgDir =\n entityId === 'plugin'\n ? `${outRoot}/packages/${name}-entry`\n : outRoot;\n\n const linked = await linkWithMarketplace(ctx, entryPkgDir);\n if (linked === 'ok') {\n info('Registered in .kb/marketplace.lock');\n } else if (linked === 'no-shell') {\n warn('Could not auto-register (no shell). Run manually:');\n info(` kb marketplace plugins link ${entryPkgDir}`);\n } else {\n warn('Auto-register failed — register manually:');\n info(` kb marketplace plugins link ${entryPkgDir}`);\n }\n\n info('Next steps:');\n info(' pnpm install');\n info(' pnpm -w build');\n info(` pnpm kb ${name} hello # try it`);\n info(` pnpm kb scaffold doctor --path ${dirname(outRoot)}`);\n outro('Done.');\n\n return {\n exitCode: 0,\n result: { outRoot, files: result.files.length },\n };\n}\n\ntype LinkOutcome = 'ok' | 'no-shell' | 'failed';\n\nasync function linkWithMarketplace(\n ctx: PluginContextV3,\n entryPkgDir: string,\n): Promise<LinkOutcome> {\n const shell = ctx.api?.shell;\n if (!shell?.exec) {\n return 'no-shell';\n }\n try {\n const res = await shell.exec(\n 'kb',\n ['marketplace', 'plugins', 'link', entryPkgDir],\n { timeout: 60_000 },\n );\n return res.ok ? 'ok' : 'failed';\n } catch {\n return 'failed';\n }\n}\n\nexport default defineCommand({\n id: 'scaffold:run',\n description: 'Scaffold <entity> <name> from blocks',\n\n handler: {\n execute: runDefault,\n },\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/ui/prompt.ts","../../src/commands/scaffold.ts"],"names":["clackOutro","runValidator"],"mappings":"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","file":"scaffold.js","sourcesContent":["import {\n intro as clackIntro,\n outro as clackOutro,\n text,\n confirm,\n select,\n multiselect,\n isCancel,\n cancel,\n log,\n} from '@clack/prompts';\nimport type { Variable } from '@kb-labs/scaffold-contracts';\nimport { runValidator } from '@kb-labs/scaffold-core';\n\nexport function intro(msg: string): void {\n clackIntro(msg);\n}\nexport function outro(msg: string): void {\n clackOutro(msg);\n}\n\nexport function info(msg: string): void {\n log.info(msg);\n}\nexport function warn(msg: string): void {\n log.warn(msg);\n}\nexport function error(msg: string): void {\n log.error(msg);\n}\n\nfunction abortOnCancel<T>(value: T | symbol): T {\n if (isCancel(value)) {\n cancel('Aborted.');\n process.exit(130);\n }\n return value as T;\n}\n\nexport async function askVariable(\n variable: Variable,\n defaults: Record<string, unknown>,\n): Promise<unknown> {\n const preset = defaults[variable.name] ?? variable.default;\n\n switch (variable.type) {\n case 'boolean': {\n const result = await confirm({\n message: variable.describe,\n initialValue: typeof preset === 'boolean' ? preset : false,\n });\n return abortOnCancel(result);\n }\n case 'select': {\n if (!variable.choices || variable.choices.length === 0) {\n throw new Error(`Variable \"${variable.name}\" is select but has no choices`);\n }\n const result = await select({\n message: variable.describe,\n options: variable.choices.map((c) => ({ value: c.value, label: c.label })),\n initialValue: (preset as string) ?? variable.choices[0]?.value,\n });\n return abortOnCancel(result);\n }\n case 'multiselect': {\n if (!variable.choices || variable.choices.length === 0) {\n throw new Error(`Variable \"${variable.name}\" is multiselect but has no choices`);\n }\n const result = await multiselect({\n message: variable.describe,\n options: variable.choices.map((c) => ({ value: c.value, label: c.label })),\n initialValues: Array.isArray(preset) ? (preset as string[]) : [],\n required: false,\n });\n return abortOnCancel(result);\n }\n case 'string':\n default: {\n const result = await text({\n message: variable.describe,\n initialValue: typeof preset === 'string' ? preset : '',\n validate: variable.validate\n ? (value: string) => runValidator(variable.validate!, value) ?? undefined\n : undefined,\n });\n return abortOnCancel(result);\n }\n }\n}\n\nexport async function askBlocks(\n options: { value: string; label: string; hint?: string }[],\n initialValues: string[],\n): Promise<string[]> {\n const result = await multiselect({\n message: 'Pick blocks to include',\n options,\n initialValues,\n required: true,\n });\n return abortOnCancel(result) as string[];\n}\n\nexport async function confirmOverwrite(path: string): Promise<boolean> {\n const result = await confirm({\n message: `Target \"${path}\" is not empty. Overwrite?`,\n initialValue: false,\n });\n return abortOnCancel(result);\n}\n","import { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createRequire } from 'node:module';\nimport { readFile } from 'node:fs/promises';\nimport {\n defineCommand,\n type PluginContextV3,\n type CLIInput,\n} from '@kb-labs/sdk';\nimport {\n build,\n inspectTarget,\n formatTree,\n listEntities,\n loadEntity,\n resolveBlocks,\n runValidator,\n writeFiles,\n} from '@kb-labs/scaffold-core';\nimport type {\n RenderContext,\n} from '@kb-labs/scaffold-contracts';\nimport {\n error,\n info,\n outro,\n warn,\n} from '../ui/prompt.js';\n\nconst here = dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_ROOT = resolve(here, '..', '..', 'templates');\n\ninterface ScaffoldFlags {\n blocks?: string;\n yes?: boolean;\n force?: boolean;\n 'dry-run'?: boolean;\n out?: string;\n scope?: string;\n mode?: string;\n}\n\ntype ScaffoldResult = {\n exitCode: number;\n result?: { outRoot: string; files: number };\n};\n\nasync function readVersion(pkgPath: string): Promise<string> {\n try {\n const raw = await readFile(pkgPath, 'utf8');\n const parsed = JSON.parse(raw) as { version?: string };\n return parsed.version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\n// Conservative fallbacks — bumped when we cut a new scaffold release.\nconst FALLBACK_VERSIONS = {\n sdk: '2.18.0',\n devkit: '2.28.0',\n commandKit: '2.30.0',\n} as const;\n\nasync function detectVersions(): Promise<Record<string, string>> {\n // Use require.resolve from this module as the anchor. Works under pnpm's\n // virtual store because createRequire follows node's resolution rules.\n const req = createRequire(import.meta.url);\n const readPkg = async (\n spec: string,\n fallback: string,\n ): Promise<string> => {\n try {\n const resolved = req.resolve(spec);\n const v = await readVersion(resolved);\n return v === '0.0.0' ? fallback : v;\n } catch {\n return fallback;\n }\n };\n const [sdk, devkit, commandKit] = await Promise.all([\n readPkg('@kb-labs/sdk/package.json', FALLBACK_VERSIONS.sdk),\n readPkg('@kb-labs/devkit/package.json', FALLBACK_VERSIONS.devkit),\n readPkg('@kb-labs/shared-command-kit/package.json', FALLBACK_VERSIONS.commandKit),\n ]);\n return { sdk, devkit, commandKit };\n}\n\nfunction parsePositional(argv: string[] | undefined): {\n entity?: string;\n name?: string;\n} {\n if (!argv || argv.length === 0) return {};\n const positional = argv.filter((a) => !a.startsWith('-'));\n return { entity: positional[0], name: positional[1] };\n}\n\nasync function runDefault(\n ctx: PluginContextV3,\n rawInput: CLIInput<ScaffoldFlags>,\n): Promise<ScaffoldResult> {\n const input = { ...rawInput.flags, argv: rawInput.argv };\n\n const { entity: entityArg, name: nameArg } = parsePositional(input.argv);\n\n const available = await listEntities(TEMPLATES_ROOT);\n if (available.length === 0) {\n error(`No entities found in templates root: ${TEMPLATES_ROOT}`);\n return { exitCode: 1 };\n }\n\n // Resolve entity.\n const entityId = entityArg ?? available[0]!;\n if (!available.includes(entityId)) {\n error(`Unknown entity: ${entityId}. Available: ${available.join(', ')}`);\n return { exitCode: 1 };\n }\n\n const entity = await loadEntity(TEMPLATES_ROOT, entityId);\n\n // Resolve name — required positional.\n if (!nameArg) {\n error('Usage: kb scaffold run <entity> <name> [flags]');\n return { exitCode: 1 };\n }\n const problem = runValidator('npmName', nameArg);\n if (problem) {\n error(`Invalid name \"${nameArg}\": ${problem}`);\n return { exitCode: 1 };\n }\n const name = nameArg;\n\n // Collect entity-level variables — flags override, then entity defaults.\n const vars: Record<string, unknown> = {};\n for (const v of entity.variables) {\n if (v.name === 'scope' && input.scope !== undefined) {\n vars[v.name] = input.scope;\n } else if (v.name === 'mode' && input.mode !== undefined) {\n vars[v.name] = input.mode;\n } else {\n vars[v.name] = v.default ?? '';\n }\n }\n\n // Select blocks — flag overrides, then entity defaults.\n let selectedBlocks: string[];\n if (input.blocks) {\n selectedBlocks = input.blocks\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n } else {\n selectedBlocks = entity.defaults?.blocks ?? entity.blocks.map((b) => b.id);\n }\n\n // Collect block-specific variables — use defaults.\n try {\n resolveBlocks(entity.blocks, selectedBlocks);\n } catch (e) {\n error((e as Error).message);\n return { exitCode: 1 };\n }\n for (const blockId of selectedBlocks) {\n const block = entity.blocks.find((b) => b.id === blockId);\n for (const v of block?.variables ?? []) {\n vars[v.name] = v.default ?? '';\n }\n }\n\n const scope = (vars.scope as string) ?? input.scope ?? '';\n const mode = (input.mode ?? (vars.mode as string) ?? 'in-workspace') as\n | 'in-workspace'\n | 'standalone';\n\n const versions = await detectVersions();\n\n const context: RenderContext = {\n name,\n scope,\n vars,\n blocks: selectedBlocks,\n mode,\n versions,\n };\n\n const result = await build({\n entity,\n selectedBlockIds: selectedBlocks,\n context,\n });\n\n const outRoot = input.out ?? result.outRoot;\n const state = await inspectTarget(outRoot);\n\n if (input['dry-run']) {\n info(`Would write to: ${outRoot}`);\n info('Tree:');\n info(formatTree(result.files));\n outro('Dry run complete.');\n return { exitCode: 0, result: { outRoot, files: result.files.length } };\n }\n\n if (state.exists && !state.empty) {\n if (input.force) {\n warn(`--force: overwriting ${outRoot}`);\n } else {\n error(`Target \"${outRoot}\" is not empty. Use --force to overwrite.`);\n return { exitCode: 1 };\n }\n }\n\n await writeFiles({ outRoot, files: result.files, force: input.force });\n\n ctx.ui?.success?.(`Scaffolded ${entityId} \"${name}\"`);\n info(`Output: ${outRoot}`);\n\n // The package that carries `\"kb\": { \"manifest\": \"...\" }` is the target\n // marketplace.link needs. For plugin entity → <outRoot>/packages/<name>-entry.\n // For adapter entity → <outRoot> itself.\n const entryPkgDir =\n entityId === 'plugin'\n ? `${outRoot}/packages/${name}-entry`\n : outRoot;\n\n const linked = await linkWithMarketplace(ctx, entryPkgDir);\n if (linked === 'ok') {\n info('Registered in .kb/marketplace.lock');\n } else if (linked === 'no-shell') {\n warn('Could not auto-register (no shell). Run manually:');\n info(` kb marketplace plugins link ${entryPkgDir}`);\n } else {\n warn('Auto-register failed — register manually:');\n info(` kb marketplace plugins link ${entryPkgDir}`);\n }\n\n info('Next steps:');\n info(' pnpm install');\n info(' pnpm -w build');\n info(` pnpm kb ${name} hello # try it`);\n info(` pnpm kb scaffold doctor --path ${dirname(outRoot)}`);\n outro('Done.');\n\n return {\n exitCode: 0,\n result: { outRoot, files: result.files.length },\n };\n}\n\ntype LinkOutcome = 'ok' | 'no-shell' | 'failed';\n\nasync function linkWithMarketplace(\n ctx: PluginContextV3,\n entryPkgDir: string,\n): Promise<LinkOutcome> {\n const shell = ctx.api?.shell;\n if (!shell?.exec) {\n return 'no-shell';\n }\n try {\n const res = await shell.exec(\n 'kb',\n ['marketplace', 'plugins', 'link', entryPkgDir],\n { timeout: 60_000 },\n );\n return res.ok ? 'ok' : 'failed';\n } catch {\n return 'failed';\n }\n}\n\nexport default defineCommand({\n id: 'scaffold:run',\n description: 'Scaffold <entity> <name> from blocks',\n\n handler: {\n execute: runDefault,\n },\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kb-labs/scaffold",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.32.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Generic entity scaffolder for KB Labs plugins, adapters, and friends.",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"sideEffects": false,
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@clack/prompts": "^0.11.0",
|
|
28
|
-
"@kb-labs/scaffold-contracts": "2.
|
|
29
|
-
"@kb-labs/
|
|
30
|
-
"@kb-labs/
|
|
28
|
+
"@kb-labs/scaffold-contracts": "2.32.0",
|
|
29
|
+
"@kb-labs/sdk": "2.18.2",
|
|
30
|
+
"@kb-labs/scaffold-core": "2.32.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/node": "^24.3.3",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"tsup": "^8.5.0",
|
|
37
37
|
"typescript": "^5.6.3",
|
|
38
38
|
"vitest": "^3.2.4",
|
|
39
|
-
"@kb-labs/devkit": "2.
|
|
40
|
-
"@kb-labs/plugin-contracts": "2.
|
|
39
|
+
"@kb-labs/devkit": "2.32.0",
|
|
40
|
+
"@kb-labs/plugin-contracts": "2.32.0"
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
43
43
|
"node": ">=20.0.0",
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"<%= it.scope ? it.scope + '/' : '' %><%= it.name %>-core": "workspace:*",
|
|
31
31
|
"<%= it.scope ? it.scope + '/' : '' %><%= it.name %>-contracts": "workspace:*",
|
|
32
|
-
"@kb-labs/sdk": "<%= it.mode === 'in-workspace' ? 'workspace:*' : '^' + it.versions.sdk %>"
|
|
32
|
+
"@kb-labs/sdk": "<%= it.mode === 'in-workspace' ? 'workspace:*' : '^' + it.versions.sdk %>"<% if (it.mode === 'standalone') { %>,
|
|
33
|
+
"@kb-labs/shared-command-kit": "^<%= it.versions.commandKit %>"<% } %>
|
|
33
34
|
},
|
|
34
35
|
"devDependencies": {
|
|
35
36
|
"@kb-labs/devkit": "<%= it.mode === 'in-workspace' ? 'workspace:*' : '^' + it.versions.devkit %>",
|