handoff-app 2.0.0-5 → 2.0.0-7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +174 -41
- package/UPGRADE.md +198 -0
- package/config/config.template.js +1 -4
- package/config/config.template.ts +1 -2
- package/dist/app-builder/build.js +11 -6
- package/dist/app-builder/client-config.js +1 -0
- package/dist/app-builder/config-diff/strategies/pattern.js +3 -3
- package/dist/app-builder/watchers/component.js +5 -5
- package/dist/app-builder/watchers/utils.d.ts +2 -3
- package/dist/app-builder/watchers.d.ts +8 -15
- package/dist/app-builder/watchers.js +53 -54
- package/dist/cache/build-cache.js +18 -22
- package/dist/catalog/define.d.ts +6 -0
- package/dist/catalog/define.js +72 -0
- package/dist/catalog/implementation.d.ts +27 -0
- package/dist/catalog/implementation.js +133 -0
- package/dist/catalog/index.d.ts +6 -0
- package/dist/catalog/index.js +22 -0
- package/dist/catalog/normalize.d.ts +16 -0
- package/dist/catalog/normalize.js +115 -0
- package/dist/catalog/previews.d.ts +18 -0
- package/dist/catalog/previews.js +106 -0
- package/dist/catalog/renderers.d.ts +43 -0
- package/dist/catalog/renderers.js +62 -0
- package/dist/catalog/types.d.ts +63 -0
- package/dist/cli/make.d.ts +0 -5
- package/dist/cli/make.js +22 -67
- package/dist/cli/scaffold.js +25 -33
- package/dist/commands/checkout/index.d.ts +7 -4
- package/dist/commands/checkout/index.js +9 -6
- package/dist/commands/compat/push-args.d.ts +2 -2
- package/dist/commands/index.js +0 -2
- package/dist/commands/publish/index.d.ts +9 -6
- package/dist/commands/publish/index.js +11 -8
- package/dist/commands/pull/index.js +1 -1
- package/dist/commands/push/index.js +1 -1
- package/dist/commands/utils.d.ts +15 -4
- package/dist/commands/utils.js +19 -6
- package/dist/config/catalog-include.d.ts +43 -0
- package/dist/config/catalog-include.js +203 -0
- package/dist/config/defaults.d.ts +2 -0
- package/dist/config/defaults.js +4 -1
- package/dist/config/index.d.ts +3 -3
- package/dist/config/index.js +6 -5
- package/dist/config/loader.js +9 -1
- package/dist/config/runtime.d.ts +5 -6
- package/dist/config/runtime.js +154 -154
- package/dist/handlebars.d.ts +9 -0
- package/dist/handlebars.js +16 -0
- package/dist/index.d.ts +15 -4
- package/dist/index.js +29 -15
- package/dist/pattern.d.ts +7 -0
- package/dist/pattern.js +13 -0
- package/dist/react.d.ts +43 -0
- package/dist/react.js +11 -0
- package/dist/registry/asset-storage/define.d.ts +1 -1
- package/dist/registry/asset-storage/define.js +1 -1
- package/dist/registry/checkout/index.d.ts +9 -0
- package/dist/registry/checkout/index.js +335 -149
- package/dist/registry/db/schema.d.ts +34 -0
- package/dist/registry/db/schema.js +2 -0
- package/dist/registry/publish/index.d.ts +13 -2
- package/dist/registry/publish/index.js +109 -25
- package/dist/registry/publish/package.js +14 -1
- package/dist/registry/selection.d.ts +20 -0
- package/dist/registry/selection.js +37 -1
- package/dist/store/filesystem.d.ts +1 -1
- package/dist/store/filesystem.js +7 -7
- package/dist/store/registry.js +24 -3
- package/dist/transformers/plugins/csf-render.js +4 -2
- package/dist/transformers/plugins/ssr-render.js +14 -5
- package/dist/transformers/preview/component/api.d.ts +8 -0
- package/dist/transformers/preview/component/api.js +11 -15
- package/dist/transformers/preview/component/artifacts.d.ts +1 -1
- package/dist/transformers/preview/component/artifacts.js +11 -7
- package/dist/transformers/preview/component/builder.js +15 -18
- package/dist/transformers/preview/component/css.d.ts +2 -0
- package/dist/transformers/preview/component/css.js +8 -11
- package/dist/transformers/preview/component/html.js +18 -16
- package/dist/transformers/preview/component/javascript.js +2 -4
- package/dist/transformers/preview/pattern/builder.js +31 -18
- package/dist/transformers/preview/types.d.ts +15 -1
- package/dist/types/config.d.ts +36 -11
- package/docs/api.md +3 -0
- package/docs/cli.md +1 -1
- package/drizzle/0006_add_component_source_format.sql +3 -0
- package/drizzle/meta/0006_snapshot.json +1941 -0
- package/drizzle/meta/_journal.json +8 -1
- package/package.json +37 -2
- package/src/app/components/Component/Preview.tsx +36 -50
- package/src/app/components/CopyToClipboard.tsx +27 -26
- package/src/app/components/Layout/Header.tsx +4 -12
- package/src/app/components/Layout/RuntimeModeBadge.tsx +18 -0
- package/src/app/components/Markdown/CodeHighlight.tsx +73 -70
- package/src/app/components/McpIntegration/McpConfigDialog.tsx +349 -0
- package/src/app/components/McpIntegration/McpIcon.tsx +10 -0
- package/src/app/components/Navigation/MobileNav.tsx +3 -1
- package/src/app/components/context/PreviewContext.tsx +5 -5
- package/src/app/components/ui/dialog.tsx +73 -0
- package/src/app/components/util/index.ts +7 -15
- package/src/app/lib/docs-api/backend.ts +5 -1
- package/src/app/lib/docs-api/page-discovery.ts +1 -6
- package/src/app/lib/docs-api/page-rendering.ts +21 -1
- package/src/app/lib/docs-api/records.ts +25 -10
- package/src/app/lib/docs-api/registry.ts +4 -2
- package/src/app/lib/docs-api/runtime-config.ts +5 -0
- package/src/app/lib/docs-api/search.ts +7 -2
- package/src/app/lib/mcp/auth.ts +64 -0
- package/src/app/lib/mcp/index.ts +2 -0
- package/src/app/lib/mcp/server.ts +343 -0
- package/src/app/lib/mcp/shape.ts +596 -0
- package/src/app/lib/registry-api/transfer.ts +7 -5
- package/src/app/next.config.mjs +3 -0
- package/src/app/pages/[...slug]/index.tsx +16 -30
- package/src/app/pages/api/mcp.ts +56 -0
- package/src/app/pages/index.tsx +10 -9
- package/src/app-builder/build.ts +12 -8
- package/src/app-builder/client-config.ts +2 -1
- package/src/app-builder/config-diff/strategies/pattern.ts +1 -1
- package/src/app-builder/watchers/component.ts +3 -3
- package/src/app-builder/watchers/utils.ts +2 -3
- package/src/app-builder/watchers.ts +46 -50
- package/src/cache/build-cache.ts +11 -14
- package/src/catalog/README.md +92 -0
- package/src/catalog/define.ts +79 -0
- package/src/catalog/implementation.ts +145 -0
- package/src/catalog/index.ts +31 -0
- package/src/catalog/normalize.ts +143 -0
- package/src/catalog/previews.ts +111 -0
- package/src/catalog/renderers.ts +94 -0
- package/src/catalog/types.ts +74 -0
- package/src/cli/README.md +1 -1
- package/src/cli/make.ts +20 -72
- package/src/cli/scaffold.ts +25 -31
- package/src/commands/README.md +1 -1
- package/src/commands/checkout/index.ts +17 -7
- package/src/commands/compat/push-args.ts +2 -2
- package/src/commands/index.ts +0 -2
- package/src/commands/publish/index.ts +19 -9
- package/src/commands/pull/index.ts +2 -2
- package/src/commands/push/index.ts +2 -2
- package/src/commands/utils.ts +22 -7
- package/src/config/README.md +2 -1
- package/src/config/catalog-include.ts +227 -0
- package/src/config/defaults.ts +3 -0
- package/src/config/index.ts +4 -4
- package/src/config/loader.ts +12 -0
- package/src/config/runtime.ts +186 -191
- package/src/handlebars.ts +18 -0
- package/src/index.ts +39 -26
- package/src/pattern.ts +14 -0
- package/src/react.ts +52 -0
- package/src/registry/asset-storage/define.ts +1 -1
- package/src/registry/checkout/index.ts +416 -152
- package/src/registry/db/schema.ts +2 -0
- package/src/registry/publish/index.ts +123 -26
- package/src/registry/publish/package.ts +14 -1
- package/src/registry/selection.ts +44 -0
- package/src/store/filesystem.ts +4 -4
- package/src/store/registry.ts +13 -2
- package/src/transformers/plugins/csf-render.ts +4 -2
- package/src/transformers/plugins/ssr-render.ts +15 -5
- package/src/transformers/preview/component/api.ts +13 -1
- package/src/transformers/preview/component/artifacts.ts +8 -4
- package/src/transformers/preview/component/builder.ts +17 -4
- package/src/transformers/preview/component/css.ts +6 -10
- package/src/transformers/preview/component/html.ts +30 -19
- package/src/transformers/preview/component/javascript.ts +1 -3
- package/src/transformers/preview/pattern/builder.ts +33 -20
- package/src/transformers/preview/types.ts +15 -1
- package/src/types/config.ts +38 -11
- package/templates/default/README.md.tpl +10 -0
- package/templates/default/components/button/button.react.handoff.js.tpl +19 -23
- package/templates/default/components/button/button.react.handoff.ts.tpl +22 -22
- package/templates/default/handoff.config.js.tpl +11 -18
- package/templates/default/handoff.config.ts.tpl +11 -18
- package/templates/default/handoff.config.with-examples.js.tpl +12 -16
- package/templates/default/handoff.config.with-examples.ts.tpl +12 -16
- package/config/templates/component/template.json +0 -49
- package/config/templates/template.html +0 -7
- package/dist/commands/make/template.d.ts +0 -8
- package/dist/commands/make/template.js +0 -43
- package/dist/config/entries.d.ts +0 -47
- package/dist/config/entries.js +0 -162
- package/dist/config/normalizers/declaration.d.ts +0 -11
- package/dist/config/normalizers/declaration.js +0 -122
- package/dist/config/normalizers/pattern.d.ts +0 -8
- package/dist/config/normalizers/pattern.js +0 -41
- package/dist/declarations/helpers.d.ts +0 -6
- package/dist/declarations/helpers.js +0 -19
- package/dist/declarations/index.d.ts +0 -2
- package/dist/declarations/index.js +0 -9
- package/dist/declarations/types.d.ts +0 -60
- package/src/commands/make/template.ts +0 -46
- package/src/config/entries.ts +0 -175
- package/src/config/normalizers/declaration.ts +0 -179
- package/src/config/normalizers/pattern.ts +0 -59
- package/src/declarations/helpers.ts +0 -36
- package/src/declarations/index.ts +0 -19
- package/src/declarations/types.ts +0 -70
- /package/dist/{declarations → catalog}/types.js +0 -0
package/dist/cli/scaffold.js
CHANGED
|
@@ -40,7 +40,7 @@ const p = __importStar(require("@clack/prompts"));
|
|
|
40
40
|
const chalk_1 = __importDefault(require("chalk"));
|
|
41
41
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
42
42
|
const path_1 = __importDefault(require("path"));
|
|
43
|
-
const
|
|
43
|
+
const catalog_include_1 = require("../config/catalog-include");
|
|
44
44
|
// Constants
|
|
45
45
|
const COMPONENTS_DIR = 'components';
|
|
46
46
|
const DEFAULT_GROUPS = [
|
|
@@ -63,49 +63,41 @@ const toTitleCase = (str) => {
|
|
|
63
63
|
* Generate the component JS stub content
|
|
64
64
|
*/
|
|
65
65
|
const generateComponentStub = (config) => {
|
|
66
|
+
// `implementation` names the source, so `entries` carries only supporting files.
|
|
66
67
|
const entriesLines = [];
|
|
67
|
-
if (config.generateTsx) {
|
|
68
|
-
entriesLines.push(` component: './${config.name}.tsx',`);
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
entriesLines.push(` template: './${config.name}.hbs',`);
|
|
72
|
-
}
|
|
73
68
|
if (config.generateScss) {
|
|
74
69
|
entriesLines.push(` scss: './${config.name}.scss',`);
|
|
75
70
|
}
|
|
71
|
+
const entriesBlock = entriesLines.length ? `\n entries: {\n${entriesLines.join('\n')}\n },` : '';
|
|
76
72
|
const commonMetadata = ` id: "${config.name}",
|
|
77
73
|
name: "${config.title}",
|
|
78
74
|
description: "${config.description}",
|
|
79
75
|
group: "${config.group}",
|
|
80
76
|
type: "element",
|
|
81
77
|
figmaComponentId: "${config.name}",`;
|
|
78
|
+
const previewExport = `
|
|
79
|
+
exports.Default = {
|
|
80
|
+
args: {},
|
|
81
|
+
};
|
|
82
|
+
`;
|
|
82
83
|
if (config.generateTsx) {
|
|
83
|
-
|
|
84
|
-
const
|
|
84
|
+
const identifier = toTitleCase(config.name).replace(/\s/g, '');
|
|
85
|
+
return `const { defineCatalogItem } = require('handoff-app/react');
|
|
86
|
+
const ${identifier} = require('./${config.name}').default;
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
exports.default = defineCatalogItem({
|
|
87
89
|
${commonMetadata}
|
|
88
|
-
|
|
89
|
-
${entriesLines.join('\n')}
|
|
90
|
-
},
|
|
91
|
-
previews: {
|
|
92
|
-
default: { title: "Default", args: {} }
|
|
93
|
-
}
|
|
90
|
+
implementation: ${identifier},${entriesBlock}
|
|
94
91
|
});
|
|
95
|
-
`;
|
|
92
|
+
${previewExport}`;
|
|
96
93
|
}
|
|
97
|
-
return `const {
|
|
94
|
+
return `const { defineCatalogItem } = require('handoff-app/handlebars');
|
|
98
95
|
|
|
99
|
-
|
|
96
|
+
exports.default = defineCatalogItem({
|
|
100
97
|
${commonMetadata}
|
|
101
|
-
|
|
102
|
-
${entriesLines.join('\n')}
|
|
103
|
-
},
|
|
104
|
-
previews: {
|
|
105
|
-
default: { title: "Default", args: {} }
|
|
106
|
-
}
|
|
98
|
+
implementation: './${config.name}.hbs',${entriesBlock}
|
|
107
99
|
});
|
|
108
|
-
`;
|
|
100
|
+
${previewExport}`;
|
|
109
101
|
};
|
|
110
102
|
/**
|
|
111
103
|
* Generate a basic React component stub with variant props
|
|
@@ -179,8 +171,8 @@ const getFigmaComponents = (handoff) => __awaiter(void 0, void 0, void 0, functi
|
|
|
179
171
|
* Get list of registered component IDs from runtime config
|
|
180
172
|
*/
|
|
181
173
|
const getRegisteredComponentIds = (handoff) => {
|
|
182
|
-
var _a
|
|
183
|
-
const components = ((
|
|
174
|
+
var _a;
|
|
175
|
+
const components = ((_a = handoff.runtimeConfig) === null || _a === void 0 ? void 0 : _a.entities.components) || {};
|
|
184
176
|
return Object.keys(components);
|
|
185
177
|
};
|
|
186
178
|
/**
|
|
@@ -385,22 +377,22 @@ const runScaffold = (handoff) => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
385
377
|
console.log(chalk_1.default.dim(` ${relativePath}`));
|
|
386
378
|
}
|
|
387
379
|
// Update config if requested. Components already covered by a collection directory auto-load,
|
|
388
|
-
// so we only write the
|
|
380
|
+
// so we only write the unlisted ones into catalog.include.
|
|
389
381
|
if (updateConfig) {
|
|
390
382
|
const componentDirs = componentNames.map((name) => path_1.default.resolve(handoff.workingPath, COMPONENTS_DIR, name));
|
|
391
|
-
const
|
|
392
|
-
if (
|
|
383
|
+
const unlisted = componentDirs.filter((dir) => !(0, catalog_include_1.isIncluded)(handoff, dir));
|
|
384
|
+
if (unlisted.length === 0) {
|
|
393
385
|
p.log.info(`Config already covers these components - they'll auto-load`);
|
|
394
386
|
}
|
|
395
387
|
else {
|
|
396
|
-
const result = yield (0,
|
|
388
|
+
const result = yield (0, catalog_include_1.addToCatalog)(handoff, unlisted);
|
|
397
389
|
if (result.status === 'added') {
|
|
398
390
|
const configFileName = result.configPath ? path_1.default.basename(result.configPath) : 'handoff.config.json';
|
|
399
391
|
p.log.success(`Updated ${configFileName} with component paths`);
|
|
400
392
|
}
|
|
401
393
|
else {
|
|
402
394
|
const where = result.configPath ? path_1.default.relative(handoff.workingPath, result.configPath) : 'handoff.config';
|
|
403
|
-
p.log.warn(`Could not automatically update ${where}. Please manually add these paths to
|
|
395
|
+
p.log.warn(`Could not automatically update ${where}. Please manually add these paths to catalog.include:`);
|
|
404
396
|
for (const rel of result.pending) {
|
|
405
397
|
console.log(chalk_1.default.yellow(` '${rel}'`));
|
|
406
398
|
}
|
|
@@ -6,10 +6,13 @@ export interface CheckoutArgs extends SharedArgs {
|
|
|
6
6
|
id?: string[];
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
* `handoff-app checkout <
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* `handoff-app checkout <catalog|pages> [id...]` pulls entities from the connected registry into this
|
|
10
|
+
* workspace, writing their source files in standard authoring form and synthesizing local
|
|
11
|
+
* declarations. Pass ids to pull only those entities, or omit them for every published entity of that
|
|
12
|
+
* kind.
|
|
13
|
+
*
|
|
14
|
+
* `catalog` covers every published catalog item. The lane an item was published into is looked up in
|
|
15
|
+
* the registry, so an id is enough and no lane is named here.
|
|
13
16
|
*
|
|
14
17
|
* `handoff-app checkout tokens [setId...]` pulls every published token set, or only the named ones,
|
|
15
18
|
* reconstructing `tokens.json` and restoring the generated token files.
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const utils_1 = require("../utils");
|
|
4
4
|
/**
|
|
5
|
-
* `handoff-app checkout <
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* `handoff-app checkout <catalog|pages> [id...]` pulls entities from the connected registry into this
|
|
6
|
+
* workspace, writing their source files in standard authoring form and synthesizing local
|
|
7
|
+
* declarations. Pass ids to pull only those entities, or omit them for every published entity of that
|
|
8
|
+
* kind.
|
|
9
|
+
*
|
|
10
|
+
* `catalog` covers every published catalog item. The lane an item was published into is looked up in
|
|
11
|
+
* the registry, so an id is enough and no lane is named here.
|
|
9
12
|
*
|
|
10
13
|
* `handoff-app checkout tokens [setId...]` pulls every published token set, or only the named ones,
|
|
11
14
|
* reconstructing `tokens.json` and restoring the generated token files.
|
|
@@ -21,8 +24,8 @@ const utils_1 = require("../utils");
|
|
|
21
24
|
*/
|
|
22
25
|
const command = {
|
|
23
26
|
command: 'checkout <type> [id..]',
|
|
24
|
-
describe: 'Pull
|
|
25
|
-
builder: (yargs) => (0, utils_1.withTargetPositionals)((0, utils_1.getCheckoutOptions)(yargs), 'checkout'),
|
|
27
|
+
describe: 'Pull catalog items, pages, design tokens, or assets from the connected registry into this workspace',
|
|
28
|
+
builder: (yargs) => (0, utils_1.withTargetPositionals)((0, utils_1.getCheckoutOptions)(yargs), 'checkout', utils_1.REGISTRY_TARGET_KINDS),
|
|
26
29
|
handler: (args) => (0, utils_1.runRegistryCommand)(args, (handoff) => (0, utils_1.runTarget)(handoff, args.type, args.id, 'checkout')),
|
|
27
30
|
};
|
|
28
31
|
exports.default = command;
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
* {@link Handoff.publishAll}, so no orchestration lives here.
|
|
8
8
|
*/
|
|
9
9
|
import { type RegistryEntityKind } from '../../registry/content-kinds';
|
|
10
|
-
import type {
|
|
10
|
+
import type { CompatTargetKind } from '../utils';
|
|
11
11
|
import type { ContentTarget } from '../../index';
|
|
12
12
|
/** The documented `push` / `pull` arguments read here. */
|
|
13
13
|
export interface CompatTargetArgs {
|
|
14
|
-
type?:
|
|
14
|
+
type?: CompatTargetKind;
|
|
15
15
|
id?: string[];
|
|
16
16
|
components?: string[];
|
|
17
17
|
patterns?: string[];
|
package/dist/commands/index.js
CHANGED
|
@@ -19,7 +19,6 @@ const login_1 = __importDefault(require("./login"));
|
|
|
19
19
|
const logout_1 = __importDefault(require("./logout"));
|
|
20
20
|
const component_1 = __importDefault(require("./make/component"));
|
|
21
21
|
const page_1 = __importDefault(require("./make/page"));
|
|
22
|
-
const template_1 = __importDefault(require("./make/template"));
|
|
23
22
|
const pull_1 = __importDefault(require("./pull"));
|
|
24
23
|
const publish_1 = __importDefault(require("./publish"));
|
|
25
24
|
const push_1 = require("./push");
|
|
@@ -42,7 +41,6 @@ exports.commands = [
|
|
|
42
41
|
logout_1.default,
|
|
43
42
|
page_1.default,
|
|
44
43
|
component_1.default,
|
|
45
|
-
template_1.default,
|
|
46
44
|
publish_1.default,
|
|
47
45
|
pull_1.default,
|
|
48
46
|
...push_1.pushCommands,
|
|
@@ -6,10 +6,13 @@ export interface PublishArgs extends SharedArgs {
|
|
|
6
6
|
id?: string[];
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
* `handoff-app publish <
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* `handoff-app publish <catalog|pages> [id...]` runs a fresh local build and uploads to the connected
|
|
10
|
+
* registry. Pass ids to build and upload only those entities, or omit them to build the kind once and
|
|
11
|
+
* upload every declared entity, skipping any whose content already matches the registry (`--force`
|
|
12
|
+
* re-uploads everything).
|
|
13
|
+
*
|
|
14
|
+
* `catalog` covers every declared catalog item. Whether an item is stored as a component or as a
|
|
15
|
+
* pattern follows from its declaration, so an id is enough and no lane is named here.
|
|
13
16
|
*
|
|
14
17
|
* `handoff-app publish tokens [setId...]` does a fresh token build and uploads every logical token
|
|
15
18
|
* set, or only the named ones (`foundation/colors`, `component/button`).
|
|
@@ -17,8 +20,8 @@ export interface PublishArgs extends SharedArgs {
|
|
|
17
20
|
* `handoff-app publish assets [collection...]` runs a fresh build and uploads every asset collection,
|
|
18
21
|
* or only the named ones (`icons`, `logos`, `fonts`).
|
|
19
22
|
*
|
|
20
|
-
* `handoff-app publish all` runs every kind in dependency order: tokens, assets,
|
|
21
|
-
*
|
|
23
|
+
* `handoff-app publish all` runs every kind in dependency order: tokens, assets, catalog items, then
|
|
24
|
+
* pages.
|
|
22
25
|
*
|
|
23
26
|
* Available only from a connected workspace (`runtime.mode: workspace` + a configured
|
|
24
27
|
* `registryConnection`), except under `--dry-run`, which reports what would be uploaded and needs no
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const utils_1 = require("../utils");
|
|
4
4
|
/**
|
|
5
|
-
* `handoff-app publish <
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* `handoff-app publish <catalog|pages> [id...]` runs a fresh local build and uploads to the connected
|
|
6
|
+
* registry. Pass ids to build and upload only those entities, or omit them to build the kind once and
|
|
7
|
+
* upload every declared entity, skipping any whose content already matches the registry (`--force`
|
|
8
|
+
* re-uploads everything).
|
|
9
|
+
*
|
|
10
|
+
* `catalog` covers every declared catalog item. Whether an item is stored as a component or as a
|
|
11
|
+
* pattern follows from its declaration, so an id is enough and no lane is named here.
|
|
9
12
|
*
|
|
10
13
|
* `handoff-app publish tokens [setId...]` does a fresh token build and uploads every logical token
|
|
11
14
|
* set, or only the named ones (`foundation/colors`, `component/button`).
|
|
@@ -13,8 +16,8 @@ const utils_1 = require("../utils");
|
|
|
13
16
|
* `handoff-app publish assets [collection...]` runs a fresh build and uploads every asset collection,
|
|
14
17
|
* or only the named ones (`icons`, `logos`, `fonts`).
|
|
15
18
|
*
|
|
16
|
-
* `handoff-app publish all` runs every kind in dependency order: tokens, assets,
|
|
17
|
-
*
|
|
19
|
+
* `handoff-app publish all` runs every kind in dependency order: tokens, assets, catalog items, then
|
|
20
|
+
* pages.
|
|
18
21
|
*
|
|
19
22
|
* Available only from a connected workspace (`runtime.mode: workspace` + a configured
|
|
20
23
|
* `registryConnection`), except under `--dry-run`, which reports what would be uploaded and needs no
|
|
@@ -22,8 +25,8 @@ const utils_1 = require("../utils");
|
|
|
22
25
|
*/
|
|
23
26
|
const command = {
|
|
24
27
|
command: 'publish <type> [id..]',
|
|
25
|
-
describe: 'Build and publish
|
|
26
|
-
builder: (yargs) => (0, utils_1.withTargetPositionals)((0, utils_1.getPublishOptions)(yargs), 'publish'),
|
|
28
|
+
describe: 'Build and publish catalog items, pages, design tokens, or assets to the connected registry',
|
|
29
|
+
builder: (yargs) => (0, utils_1.withTargetPositionals)((0, utils_1.getPublishOptions)(yargs), 'publish', utils_1.REGISTRY_TARGET_KINDS),
|
|
27
30
|
handler: (args) => (0, utils_1.runRegistryCommand)(args, (handoff) => (0, utils_1.runTarget)(handoff, args.type, args.id, 'publish')),
|
|
28
31
|
};
|
|
29
32
|
exports.default = command;
|
|
@@ -7,7 +7,7 @@ const pull = {
|
|
|
7
7
|
command: 'pull [type] [id..]',
|
|
8
8
|
describe: 'Deprecated alias for checkout',
|
|
9
9
|
deprecated: true,
|
|
10
|
-
builder: (yargs) => (0, utils_1.withTargetPositionals)((0, utils_1.getCheckoutOptions)(yargs), 'checkout').options({
|
|
10
|
+
builder: (yargs) => (0, utils_1.withTargetPositionals)((0, utils_1.getCheckoutOptions)(yargs), 'checkout', utils_1.COMPAT_TARGET_KINDS).options({
|
|
11
11
|
components: { type: 'array', string: true, description: 'Checkout only these component ids' },
|
|
12
12
|
patterns: { type: 'array', string: true, description: 'Checkout only these pattern ids' },
|
|
13
13
|
pages: { type: 'array', string: true, description: 'Checkout only these page slugs' },
|
|
@@ -9,7 +9,7 @@ const push = {
|
|
|
9
9
|
command: 'push [type] [id..]',
|
|
10
10
|
describe: 'Deprecated alias for publish',
|
|
11
11
|
deprecated: true,
|
|
12
|
-
builder: (yargs) => (0, utils_1.withTargetPositionals)((0, utils_1.getPublishOptions)(yargs), 'publish').options(Object.assign({ components: { type: 'array', string: true, description: 'Publish only these component ids' }, patterns: { type: 'array', string: true, description: 'Publish only these pattern ids' }, pages: { type: 'array', string: true, description: 'Publish only these page slugs' } }, (0, deprecations_1.hiddenOptions)(deprecations_1.UNSUPPORTED_PUSH_OPTIONS))),
|
|
12
|
+
builder: (yargs) => (0, utils_1.withTargetPositionals)((0, utils_1.getPublishOptions)(yargs), 'publish', utils_1.COMPAT_TARGET_KINDS).options(Object.assign({ components: { type: 'array', string: true, description: 'Publish only these component ids' }, patterns: { type: 'array', string: true, description: 'Publish only these pattern ids' }, pages: { type: 'array', string: true, description: 'Publish only these page slugs' } }, (0, deprecations_1.hiddenOptions)(deprecations_1.UNSUPPORTED_PUSH_OPTIONS))),
|
|
13
13
|
handler: (args) => (0, utils_1.runRegistryCommand)(args, (handoff) => {
|
|
14
14
|
(0, deprecations_1.warnDeprecatedCommand)('push', 'publish');
|
|
15
15
|
(0, deprecations_1.warnUnsupportedOptions)(args, deprecations_1.UNSUPPORTED_PUSH_OPTIONS);
|
package/dist/commands/utils.d.ts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import { Argv } from 'yargs';
|
|
2
2
|
import Handoff from '../';
|
|
3
3
|
import { SharedArgs } from './types';
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* The `type` argument accepted by publish and checkout, or `all` for every kind. `catalog` covers
|
|
6
|
+
* every catalog item. An item's lane comes from its declaration, so the command line names items and
|
|
7
|
+
* never a lane.
|
|
8
|
+
*/
|
|
9
|
+
export declare const REGISTRY_TARGET_KINDS: readonly ["catalog", "pages", "tokens", "assets", "all"];
|
|
6
10
|
export type RegistryTargetKind = (typeof REGISTRY_TARGET_KINDS)[number];
|
|
11
|
+
/**
|
|
12
|
+
* The `type` argument accepted by the deprecated `push` / `pull` aliases: the plural content kinds the
|
|
13
|
+
* published docs name. This list keeps `components` and `patterns`, which the canonical commands do
|
|
14
|
+
* not take, and omits `catalog`, which the docs do not describe.
|
|
15
|
+
*/
|
|
16
|
+
export declare const COMPAT_TARGET_KINDS: readonly ["components", "patterns", "pages", "tokens", "assets", "all"];
|
|
17
|
+
export type CompatTargetKind = (typeof COMPAT_TARGET_KINDS)[number];
|
|
7
18
|
export declare const createHandoff: (args: SharedArgs) => Handoff;
|
|
8
19
|
/**
|
|
9
20
|
* Run a registry command against a fresh Handoff. Registry failures are the user's to act on, so they
|
|
@@ -83,8 +94,8 @@ export declare const getCheckoutOptions: (yargs: Argv) => Argv<import("yargs").O
|
|
|
83
94
|
* `choices` is always declared: yargs allows an omitted optional positional while still rejecting an
|
|
84
95
|
* unrecognized one, so the deprecated commands get the same guard as the canonical ones.
|
|
85
96
|
*/
|
|
86
|
-
export declare const withTargetPositionals: (yargs: Argv, verb: "publish" | "checkout") => Argv<{
|
|
87
|
-
type:
|
|
97
|
+
export declare const withTargetPositionals: <TKind extends string>(yargs: Argv, verb: "publish" | "checkout", choices: readonly TKind[]) => Argv<{
|
|
98
|
+
type: (unknown extends TKind ? true : false) extends false ? TKind : unknown;
|
|
88
99
|
} & {
|
|
89
100
|
id: string[];
|
|
90
101
|
}>;
|
package/dist/commands/utils.js
CHANGED
|
@@ -12,12 +12,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.runTarget = exports.withTargetPositionals = exports.getCheckoutOptions = exports.getPublishOptions = exports.getSharedOptions = exports.runRegistryCommand = exports.createHandoff = exports.REGISTRY_TARGET_KINDS = void 0;
|
|
15
|
+
exports.runTarget = exports.withTargetPositionals = exports.getCheckoutOptions = exports.getPublishOptions = exports.getSharedOptions = exports.runRegistryCommand = exports.createHandoff = exports.COMPAT_TARGET_KINDS = exports.REGISTRY_TARGET_KINDS = void 0;
|
|
16
16
|
const __1 = __importDefault(require("../"));
|
|
17
17
|
const content_kinds_1 = require("../registry/content-kinds");
|
|
18
18
|
const logger_1 = require("../utils/logger");
|
|
19
|
-
/**
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* The `type` argument accepted by publish and checkout, or `all` for every kind. `catalog` covers
|
|
21
|
+
* every catalog item. An item's lane comes from its declaration, so the command line names items and
|
|
22
|
+
* never a lane.
|
|
23
|
+
*/
|
|
24
|
+
exports.REGISTRY_TARGET_KINDS = ['catalog', 'pages', 'tokens', 'assets', 'all'];
|
|
25
|
+
/**
|
|
26
|
+
* The `type` argument accepted by the deprecated `push` / `pull` aliases: the plural content kinds the
|
|
27
|
+
* published docs name. This list keeps `components` and `patterns`, which the canonical commands do
|
|
28
|
+
* not take, and omits `catalog`, which the docs do not describe.
|
|
29
|
+
*/
|
|
30
|
+
exports.COMPAT_TARGET_KINDS = [...content_kinds_1.REGISTRY_ENTITY_KINDS, 'all'];
|
|
21
31
|
const createHandoff = (args) => new __1.default({
|
|
22
32
|
debug: args.debug,
|
|
23
33
|
force: args.force,
|
|
@@ -88,14 +98,14 @@ exports.getCheckoutOptions = getCheckoutOptions;
|
|
|
88
98
|
* `choices` is always declared: yargs allows an omitted optional positional while still rejecting an
|
|
89
99
|
* unrecognized one, so the deprecated commands get the same guard as the canonical ones.
|
|
90
100
|
*/
|
|
91
|
-
const withTargetPositionals = (yargs, verb) => yargs
|
|
101
|
+
const withTargetPositionals = (yargs, verb, choices) => yargs
|
|
92
102
|
.positional('type', {
|
|
93
103
|
describe: `The kind of content to ${verb}, or "all" for every kind`,
|
|
94
|
-
choices
|
|
104
|
+
choices,
|
|
95
105
|
type: 'string',
|
|
96
106
|
})
|
|
97
107
|
.positional('id', {
|
|
98
|
-
describe: `The stable id (
|
|
108
|
+
describe: `The stable id (catalog item id, page id, token set id, or asset collection); omit to ${verb} all of that kind`,
|
|
99
109
|
type: 'string',
|
|
100
110
|
array: true,
|
|
101
111
|
});
|
|
@@ -105,6 +115,9 @@ const runTarget = (handoff, type, ids, verb) => {
|
|
|
105
115
|
if (type === 'all') {
|
|
106
116
|
return verb === 'publish' ? handoff.publishAll() : handoff.checkoutAll();
|
|
107
117
|
}
|
|
118
|
+
if (type === 'catalog') {
|
|
119
|
+
return verb === 'publish' ? handoff.publishCatalog(ids) : handoff.checkoutCatalog(ids);
|
|
120
|
+
}
|
|
108
121
|
return verb === 'publish' ? handoff.publishKind(type, ids) : handoff.checkoutKind(type, ids);
|
|
109
122
|
};
|
|
110
123
|
exports.runTarget = runTarget;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registering catalog directories in the handoff config. Both scaffolding new item stubs and
|
|
3
|
+
* checking entities out of a registry need a freshly-written entity to be discoverable by the
|
|
4
|
+
* workspace build, so both have to handle every way a path can be declared:
|
|
5
|
+
*
|
|
6
|
+
* - a collection directory (e.g. `"components"`) whose subdirectories are entities: a new sibling
|
|
7
|
+
* is auto-discovered at runtime, so nothing needs writing to the config;
|
|
8
|
+
* - an individual entity directory (e.g. `"components/button"`): the entity stays invisible until
|
|
9
|
+
* its own path is added to the list.
|
|
10
|
+
*
|
|
11
|
+
* A workspace registers items under `catalog.include`. Discovery expands collection directories;
|
|
12
|
+
* the writer appends unlisted paths in JSON, TypeScript, JavaScript, and CommonJS project configs.
|
|
13
|
+
*/
|
|
14
|
+
import { Config } from '../types/config';
|
|
15
|
+
/** Minimal handoff shape needed here; avoids importing the full Handoff class (circular dep). */
|
|
16
|
+
interface ConfigContext {
|
|
17
|
+
config?: Config;
|
|
18
|
+
workingPath: string;
|
|
19
|
+
}
|
|
20
|
+
/** Outcome of {@link addToCatalog}: `added` on success, `unsupported` when the config couldn't be edited. */
|
|
21
|
+
export interface AddToCatalogResult {
|
|
22
|
+
status: 'added' | 'unsupported';
|
|
23
|
+
/** The config file written (or that would need editing); null only when none exists and creation failed. */
|
|
24
|
+
configPath: string | null;
|
|
25
|
+
/** Workspace-relative POSIX paths written into the config. */
|
|
26
|
+
added: string[];
|
|
27
|
+
/** Workspace-relative POSIX paths the caller must add manually (`status: 'unsupported'`). */
|
|
28
|
+
pending: string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* True when `targetDir` already loads through an existing declaration: listed directly, or sitting
|
|
32
|
+
* under a declared collection directory that runtime discovery expands. Reuses the same expansion
|
|
33
|
+
* the runtime uses, so every declaration style is covered.
|
|
34
|
+
*/
|
|
35
|
+
export declare const isIncluded: (handoff: ConfigContext, targetDir: string) => boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Add `targetDirs` to the config so the build discovers them. Callers should first drop
|
|
38
|
+
* already-loading dirs via {@link isIncluded}. Paths are stored workspace-relative; a `.json`
|
|
39
|
+
* config is edited losslessly, a code config best-effort. When no config file exists a minimal
|
|
40
|
+
* `handoff.config.json` is created.
|
|
41
|
+
*/
|
|
42
|
+
export declare const addToCatalog: (handoff: ConfigContext, targetDirs: string[]) => Promise<AddToCatalogResult>;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Registering catalog directories in the handoff config. Both scaffolding new item stubs and
|
|
4
|
+
* checking entities out of a registry need a freshly-written entity to be discoverable by the
|
|
5
|
+
* workspace build, so both have to handle every way a path can be declared:
|
|
6
|
+
*
|
|
7
|
+
* - a collection directory (e.g. `"components"`) whose subdirectories are entities: a new sibling
|
|
8
|
+
* is auto-discovered at runtime, so nothing needs writing to the config;
|
|
9
|
+
* - an individual entity directory (e.g. `"components/button"`): the entity stays invisible until
|
|
10
|
+
* its own path is added to the list.
|
|
11
|
+
*
|
|
12
|
+
* A workspace registers items under `catalog.include`. Discovery expands collection directories;
|
|
13
|
+
* the writer appends unlisted paths in JSON, TypeScript, JavaScript, and CommonJS project configs.
|
|
14
|
+
*/
|
|
15
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
16
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
17
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
18
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
19
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
20
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
21
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
25
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.addToCatalog = exports.isIncluded = void 0;
|
|
29
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
30
|
+
const path_1 = __importDefault(require("path"));
|
|
31
|
+
const path_2 = require("../utils/path");
|
|
32
|
+
const runtime_1 = require("./runtime");
|
|
33
|
+
/** Config files in precedence order; the first that exists is the one we mutate. */
|
|
34
|
+
const CONFIG_FILES = ['handoff.config.ts', 'handoff.config.js', 'handoff.config.cjs', 'handoff.config.json'];
|
|
35
|
+
/** Workspace-relative, POSIX-separated path, as stored in `catalog.include`. */
|
|
36
|
+
const toIncludePath = (handoff, targetDir) => path_1.default.relative(handoff.workingPath, targetDir).split(path_1.default.sep).join('/');
|
|
37
|
+
const includedPaths = (handoff) => { var _a, _b, _c; return (_c = (_b = (_a = handoff.config) === null || _a === void 0 ? void 0 : _a.catalog) === null || _b === void 0 ? void 0 : _b.include) !== null && _c !== void 0 ? _c : []; };
|
|
38
|
+
/**
|
|
39
|
+
* True when `targetDir` already loads through an existing declaration: listed directly, or sitting
|
|
40
|
+
* under a declared collection directory that runtime discovery expands. Reuses the same expansion
|
|
41
|
+
* the runtime uses, so every declaration style is covered.
|
|
42
|
+
*/
|
|
43
|
+
const isIncluded = (handoff, targetDir) => {
|
|
44
|
+
const configured = includedPaths(handoff);
|
|
45
|
+
if (!configured.length) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return configured
|
|
49
|
+
.flatMap((included) => (0, runtime_1.getComponentsForPath)(path_1.default.resolve(handoff.workingPath, included)))
|
|
50
|
+
.some((dir) => (0, path_2.arePathsEqual)(dir, targetDir));
|
|
51
|
+
};
|
|
52
|
+
exports.isIncluded = isIncluded;
|
|
53
|
+
/** Format the path list as source, matching the surrounding indentation of a code config. */
|
|
54
|
+
const formatPathArray = (paths, indent) => {
|
|
55
|
+
if (paths.length === 0)
|
|
56
|
+
return '[]';
|
|
57
|
+
if (paths.length === 1)
|
|
58
|
+
return `['${paths[0]}']`;
|
|
59
|
+
return `[\n${paths.map((relPath) => `${indent}'${relPath}',`).join('\n')}\n${indent.slice(2)}]`;
|
|
60
|
+
};
|
|
61
|
+
/** Append paths to a structured `.json` config (lossless read/modify/write). */
|
|
62
|
+
const addToJsonConfig = (configPath, relPaths) => __awaiter(void 0, void 0, void 0, function* () {
|
|
63
|
+
var _a;
|
|
64
|
+
try {
|
|
65
|
+
const config = yield fs_extra_1.default.readJSON(configPath);
|
|
66
|
+
config.catalog = (_a = config.catalog) !== null && _a !== void 0 ? _a : {};
|
|
67
|
+
const parent = config.catalog;
|
|
68
|
+
const existing = Array.isArray(parent.include) ? parent.include : [];
|
|
69
|
+
const existingSet = new Set(existing);
|
|
70
|
+
for (const relPath of relPaths) {
|
|
71
|
+
if (!existingSet.has(relPath))
|
|
72
|
+
existing.push(relPath);
|
|
73
|
+
}
|
|
74
|
+
parent.include = existing;
|
|
75
|
+
yield fs_extra_1.default.writeJSON(configPath, config, { spaces: 2 });
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
catch (_b) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
/**
|
|
83
|
+
* Blanks out comment regions while keeping every index in place, so a match found here points at
|
|
84
|
+
* the same offset in the original source. A project config often carries a commented-out `catalog`
|
|
85
|
+
* example, and a plain search would rewrite that comment instead of the live code.
|
|
86
|
+
*/
|
|
87
|
+
const maskComments = (content) => content
|
|
88
|
+
.replace(/\/\*[\s\S]*?\*\//g, (comment) => ' '.repeat(comment.length))
|
|
89
|
+
.replace(/(^|[^:])\/\/[^\n]*/g, (comment, prefix) => prefix + ' '.repeat(comment.length - prefix.length));
|
|
90
|
+
/** Index of the brace closing the one at `openIndex`, or -1. */
|
|
91
|
+
const findMatchingBrace = (source, openIndex) => {
|
|
92
|
+
let depth = 0;
|
|
93
|
+
for (let i = openIndex; i < source.length; i += 1) {
|
|
94
|
+
if (source[i] === '{')
|
|
95
|
+
depth += 1;
|
|
96
|
+
if (source[i] === '}') {
|
|
97
|
+
depth -= 1;
|
|
98
|
+
if (depth === 0)
|
|
99
|
+
return i;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return -1;
|
|
103
|
+
};
|
|
104
|
+
/** Locates `parent: { key: [ ... ] }` in a code config, ignoring commented-out examples. */
|
|
105
|
+
const locateList = (masked) => {
|
|
106
|
+
const parentMatch = new RegExp(`(^|[\\s{,;])catalog\\s*:\\s*\\{`, 'm').exec(masked);
|
|
107
|
+
if (!parentMatch)
|
|
108
|
+
return undefined;
|
|
109
|
+
const parentBrace = masked.indexOf('{', parentMatch.index + parentMatch[0].length - 1);
|
|
110
|
+
const parentClose = findMatchingBrace(masked, parentBrace);
|
|
111
|
+
if (parentClose < 0)
|
|
112
|
+
return { parentBrace };
|
|
113
|
+
const block = masked.slice(parentBrace, parentClose + 1);
|
|
114
|
+
const keyMatch = new RegExp(`(^|[\\s{,])include\\s*:\\s*\\[`).exec(block);
|
|
115
|
+
if (!keyMatch)
|
|
116
|
+
return { parentBrace };
|
|
117
|
+
const listStart = parentBrace + block.indexOf('[', keyMatch.index);
|
|
118
|
+
const listEnd = masked.indexOf(']', listStart);
|
|
119
|
+
if (listEnd < 0)
|
|
120
|
+
return { parentBrace };
|
|
121
|
+
return { parentBrace, listStart, listEnd };
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Best-effort splice of paths into an executable `.ts` / `.js` / `.cjs` config. These are
|
|
125
|
+
* modules, not data, so there's no lossless structured write; if a computed or spread list can't be
|
|
126
|
+
* edited textually, the caller falls back to printing the paths for the user to add.
|
|
127
|
+
*/
|
|
128
|
+
const addToCodeConfig = (configPath, relPaths) => __awaiter(void 0, void 0, void 0, function* () {
|
|
129
|
+
try {
|
|
130
|
+
const content = yield fs_extra_1.default.readFile(configPath, 'utf8');
|
|
131
|
+
const masked = maskComments(content);
|
|
132
|
+
const arrayBlock = formatPathArray(relPaths, ' ');
|
|
133
|
+
const location = locateList(masked);
|
|
134
|
+
// 1) The list already exists, so merge into it.
|
|
135
|
+
if ((location === null || location === void 0 ? void 0 : location.listStart) !== undefined && location.listEnd !== undefined) {
|
|
136
|
+
const existing = content
|
|
137
|
+
.slice(location.listStart + 1, location.listEnd)
|
|
138
|
+
.split(',')
|
|
139
|
+
.map((listed) => listed.trim().replace(/['"]/g, ''))
|
|
140
|
+
.filter(Boolean);
|
|
141
|
+
const existingSet = new Set(existing);
|
|
142
|
+
const toAdd = relPaths.filter((relPath) => !existingSet.has(relPath));
|
|
143
|
+
if (toAdd.length > 0) {
|
|
144
|
+
const indentMatch = /\[\s*\n(\s*)/.exec(content.slice(location.listStart));
|
|
145
|
+
const indent = indentMatch ? indentMatch[1] : ' ';
|
|
146
|
+
const merged = formatPathArray([...existing, ...toAdd], indent);
|
|
147
|
+
yield fs_extra_1.default.writeFile(configPath, content.slice(0, location.listStart) + merged + content.slice(location.listEnd + 1), 'utf8');
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
// 2) The parent object exists but not this key, so add the key.
|
|
152
|
+
if (location) {
|
|
153
|
+
const insertAt = location.parentBrace + 1;
|
|
154
|
+
yield fs_extra_1.default.writeFile(configPath, `${content.slice(0, insertAt)}\n include: ${arrayBlock},${content.slice(insertAt)}`, 'utf8');
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
// 3) No parent object, so insert one into the exported config object.
|
|
158
|
+
const parentBlock = ` catalog: {\n include: ${arrayBlock},\n },\n`;
|
|
159
|
+
for (const anchor of [/module\.exports\s*=\s*\{/, /export\s+default\s+\{/, /defineConfig\s*\(\s*\{/]) {
|
|
160
|
+
const anchorMatch = anchor.exec(masked);
|
|
161
|
+
if (anchorMatch) {
|
|
162
|
+
const insertAt = anchorMatch.index + anchorMatch[0].length;
|
|
163
|
+
yield fs_extra_1.default.writeFile(configPath, `${content.slice(0, insertAt)}\n${parentBlock}${content.slice(insertAt)}`, 'utf8');
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
catch (_a) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
/**
|
|
174
|
+
* Add `targetDirs` to the config so the build discovers them. Callers should first drop
|
|
175
|
+
* already-loading dirs via {@link isIncluded}. Paths are stored workspace-relative; a `.json`
|
|
176
|
+
* config is edited losslessly, a code config best-effort. When no config file exists a minimal
|
|
177
|
+
* `handoff.config.json` is created.
|
|
178
|
+
*/
|
|
179
|
+
const addToCatalog = (handoff, targetDirs) => __awaiter(void 0, void 0, void 0, function* () {
|
|
180
|
+
const relPaths = [...new Set(targetDirs.map((dir) => toIncludePath(handoff, dir)))];
|
|
181
|
+
const configFile = CONFIG_FILES.find((file) => fs_extra_1.default.existsSync(path_1.default.resolve(handoff.workingPath, file)));
|
|
182
|
+
const configPath = configFile ? path_1.default.resolve(handoff.workingPath, configFile) : null;
|
|
183
|
+
if (relPaths.length === 0) {
|
|
184
|
+
return { status: 'added', configPath, added: [], pending: [] };
|
|
185
|
+
}
|
|
186
|
+
if (!configPath) {
|
|
187
|
+
const newConfigPath = path_1.default.resolve(handoff.workingPath, 'handoff.config.json');
|
|
188
|
+
try {
|
|
189
|
+
yield fs_extra_1.default.writeJSON(newConfigPath, { catalog: { include: relPaths } }, { spaces: 2 });
|
|
190
|
+
return { status: 'added', configPath: newConfigPath, added: relPaths, pending: [] };
|
|
191
|
+
}
|
|
192
|
+
catch (_a) {
|
|
193
|
+
return { status: 'unsupported', configPath: null, added: [], pending: relPaths };
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const ok = configPath.endsWith('.json')
|
|
197
|
+
? yield addToJsonConfig(configPath, relPaths)
|
|
198
|
+
: yield addToCodeConfig(configPath, relPaths);
|
|
199
|
+
return ok
|
|
200
|
+
? { status: 'added', configPath, added: relPaths, pending: [] }
|
|
201
|
+
: { status: 'unsupported', configPath, added: [], pending: relPaths };
|
|
202
|
+
});
|
|
203
|
+
exports.addToCatalog = addToCatalog;
|
|
@@ -6,6 +6,8 @@ export interface ImageStyle {
|
|
|
6
6
|
width: number;
|
|
7
7
|
description: string;
|
|
8
8
|
}
|
|
9
|
+
/** Whether the MCP endpoint is served. On unless `runtime.mcp` is explicitly `false`. */
|
|
10
|
+
export declare const isMcpEnabled: (config: Config | null | undefined) => boolean;
|
|
9
11
|
export declare const defaultConfig: () => Config;
|
|
10
12
|
/**
|
|
11
13
|
* Retrieves the client configuration from the provided handoff configuration.
|