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
|
@@ -193,6 +193,23 @@ export declare const components: import("drizzle-orm/pg-core").PgTableWithColumn
|
|
|
193
193
|
identity: undefined;
|
|
194
194
|
generated: undefined;
|
|
195
195
|
}, {}, {}>;
|
|
196
|
+
sourceFormat: import("drizzle-orm/pg-core").PgColumn<{
|
|
197
|
+
name: "source_format";
|
|
198
|
+
tableName: "components";
|
|
199
|
+
dataType: "string";
|
|
200
|
+
columnType: "PgText";
|
|
201
|
+
data: string;
|
|
202
|
+
driverParam: string;
|
|
203
|
+
notNull: false;
|
|
204
|
+
hasDefault: false;
|
|
205
|
+
isPrimaryKey: false;
|
|
206
|
+
isAutoincrement: false;
|
|
207
|
+
hasRuntimeDefault: false;
|
|
208
|
+
enumValues: [string, ...string[]];
|
|
209
|
+
baseColumn: never;
|
|
210
|
+
identity: undefined;
|
|
211
|
+
generated: undefined;
|
|
212
|
+
}, {}, {}>;
|
|
196
213
|
tags: import("drizzle-orm/pg-core").PgColumn<{
|
|
197
214
|
name: "tags";
|
|
198
215
|
tableName: "components";
|
|
@@ -3533,6 +3550,23 @@ export declare const registrySchema: {
|
|
|
3533
3550
|
identity: undefined;
|
|
3534
3551
|
generated: undefined;
|
|
3535
3552
|
}, {}, {}>;
|
|
3553
|
+
sourceFormat: import("drizzle-orm/pg-core").PgColumn<{
|
|
3554
|
+
name: "source_format";
|
|
3555
|
+
tableName: "components";
|
|
3556
|
+
dataType: "string";
|
|
3557
|
+
columnType: "PgText";
|
|
3558
|
+
data: string;
|
|
3559
|
+
driverParam: string;
|
|
3560
|
+
notNull: false;
|
|
3561
|
+
hasDefault: false;
|
|
3562
|
+
isPrimaryKey: false;
|
|
3563
|
+
isAutoincrement: false;
|
|
3564
|
+
hasRuntimeDefault: false;
|
|
3565
|
+
enumValues: [string, ...string[]];
|
|
3566
|
+
baseColumn: never;
|
|
3567
|
+
identity: undefined;
|
|
3568
|
+
generated: undefined;
|
|
3569
|
+
}, {}, {}>;
|
|
3536
3570
|
tags: import("drizzle-orm/pg-core").PgColumn<{
|
|
3537
3571
|
name: "tags";
|
|
3538
3572
|
tableName: "components";
|
|
@@ -51,6 +51,8 @@ exports.components = (0, pg_core_1.pgTable)('components', {
|
|
|
51
51
|
group: (0, pg_core_1.text)('group'),
|
|
52
52
|
type: (0, pg_core_1.text)('type'),
|
|
53
53
|
renderer: (0, pg_core_1.text)('renderer'),
|
|
54
|
+
/** How the implementation file is written (`csf`), when the renderer alone does not say. */
|
|
55
|
+
sourceFormat: (0, pg_core_1.text)('source_format'),
|
|
54
56
|
tags: (0, pg_core_1.jsonb)('tags').$type(),
|
|
55
57
|
categories: (0, pg_core_1.jsonb)('categories').$type(),
|
|
56
58
|
/** Full normalized component record. */
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Connected-workspace publish orchestration.
|
|
3
3
|
*
|
|
4
|
-
* `publish <
|
|
5
|
-
*
|
|
4
|
+
* `publish <catalog|pages> <id>` prepares one entity and uploads its record, source files, applicable
|
|
5
|
+
* rendered artifacts, and build metadata through the shared registry client. A catalog item's lane
|
|
6
|
+
* comes from its declaration, so the caller names items and this module resolves the lane.
|
|
6
7
|
*
|
|
7
8
|
* The build is targeted: a component builds the global artifacts + that component; a pattern builds
|
|
8
9
|
* the global artifacts + the components it composes + the pattern itself. This is the smallest build
|
|
@@ -56,3 +57,13 @@ export declare const publishEntity: (handoff: Handoff, kind: TransferEntityKind,
|
|
|
56
57
|
* run throws at the end if any entity failed.
|
|
57
58
|
*/
|
|
58
59
|
export declare const publishEntities: (handoff: Handoff, kind: TransferEntityKind, ids?: string[]) => Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Publish the catalog items declared in this connected workspace: every one, or only `ids` when
|
|
62
|
+
* given. An item takes the component lane or the pattern lane depending on whether it declares an
|
|
63
|
+
* implementation or a composition, so the caller names items and never names a lane.
|
|
64
|
+
*
|
|
65
|
+
* One build covers both lanes, because building the patterns already builds every component they
|
|
66
|
+
* compose. A failing lane is reported and never aborts the other. The run throws at the end if any
|
|
67
|
+
* item failed.
|
|
68
|
+
*/
|
|
69
|
+
export declare const publishCatalog: (handoff: Handoff, ids?: string[]) => Promise<void>;
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Connected-workspace publish orchestration.
|
|
4
4
|
*
|
|
5
|
-
* `publish <
|
|
6
|
-
*
|
|
5
|
+
* `publish <catalog|pages> <id>` prepares one entity and uploads its record, source files, applicable
|
|
6
|
+
* rendered artifacts, and build metadata through the shared registry client. A catalog item's lane
|
|
7
|
+
* comes from its declaration, so the caller names items and this module resolves the lane.
|
|
7
8
|
*
|
|
8
9
|
* The build is targeted: a component builds the global artifacts + that component; a pattern builds
|
|
9
10
|
* the global artifacts + the components it composes + the pattern itself. This is the smallest build
|
|
@@ -22,7 +23,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
22
23
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
24
|
};
|
|
24
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.publishEntities = exports.publishEntity = exports.publishedLabel = exports.resolveTransport = exports.resolveConnectionOrThrow = exports.assertPublishableWorkspace = exports.PublishError = void 0;
|
|
26
|
+
exports.publishCatalog = exports.publishEntities = exports.publishEntity = exports.publishedLabel = exports.resolveTransport = exports.resolveConnectionOrThrow = exports.assertPublishableWorkspace = exports.PublishError = void 0;
|
|
26
27
|
const css_1 = require("../../transformers/preview/component/css");
|
|
27
28
|
const javascript_1 = require("../../transformers/preview/component/javascript");
|
|
28
29
|
const builder_1 = __importDefault(require("../../transformers/preview/component/builder"));
|
|
@@ -55,6 +56,22 @@ const assertPublishableWorkspace = (handoff) => {
|
|
|
55
56
|
}
|
|
56
57
|
};
|
|
57
58
|
exports.assertPublishableWorkspace = assertPublishableWorkspace;
|
|
59
|
+
/** The entity lanes a catalog run visits, in dependency order: a pattern composes components. */
|
|
60
|
+
const CATALOG_LANES = ['component', 'pattern'];
|
|
61
|
+
const isCatalogLane = (kind) => CATALOG_LANES.some((lane) => lane === kind);
|
|
62
|
+
/**
|
|
63
|
+
* Refuse a catalog run while the workspace declares one id twice. Discovery keeps the first
|
|
64
|
+
* declaration and skips the rest, so a publish uploads a catalog that silently omits an item.
|
|
65
|
+
*/
|
|
66
|
+
const assertUniqueCatalogIds = (handoff) => {
|
|
67
|
+
var _a, _b;
|
|
68
|
+
const duplicates = (_b = (_a = handoff.runtimeConfig) === null || _a === void 0 ? void 0 : _a.duplicateCatalogIds) !== null && _b !== void 0 ? _b : [];
|
|
69
|
+
if (duplicates.length === 0)
|
|
70
|
+
return;
|
|
71
|
+
throw new PublishError(`Catalog id${duplicates.length > 1 ? 's' : ''} declared twice: ` +
|
|
72
|
+
duplicates.map(({ id, kept, skipped }) => `"${id}" (${kept} and ${skipped})`).join('; ') +
|
|
73
|
+
'. Give each catalog item a unique id.');
|
|
74
|
+
};
|
|
58
75
|
/**
|
|
59
76
|
* Ensure the workspace is a connected workspace able to publish: workspace runtime mode (registry
|
|
60
77
|
* hosts do not publish) and a resolved registry URL + access token. Throws an actionable
|
|
@@ -95,11 +112,11 @@ const publishedLabel = (handoff) => (handoff.dryRun ? 'Would publish' : 'Publish
|
|
|
95
112
|
exports.publishedLabel = publishedLabel;
|
|
96
113
|
/** Run the smallest build that guarantees the selected entity's artifacts are current. */
|
|
97
114
|
const runTargetedBuild = (handoff, kind, id) => __awaiter(void 0, void 0, void 0, function* () {
|
|
98
|
-
var _a, _b, _c, _d
|
|
115
|
+
var _a, _b, _c, _d;
|
|
99
116
|
// Pages carry no rendered artifacts (raw markdown is rendered at runtime), so there is nothing to
|
|
100
117
|
// build — the package is assembled directly from the discovered page record + its `.md`.
|
|
101
118
|
if (kind === 'page') {
|
|
102
|
-
if (!((
|
|
119
|
+
if (!((_a = handoff.runtimeConfig) === null || _a === void 0 ? void 0 : _a.entities.pages[id])) {
|
|
103
120
|
throw new package_1.PublishPackageError(`Page "${id}" is not declared in this workspace.`);
|
|
104
121
|
}
|
|
105
122
|
return;
|
|
@@ -109,13 +126,13 @@ const runTargetedBuild = (handoff, kind, id) => __awaiter(void 0, void 0, void 0
|
|
|
109
126
|
yield (0, javascript_1.buildMainJS)(handoff);
|
|
110
127
|
yield (0, css_1.buildMainCss)(handoff);
|
|
111
128
|
if (kind === 'component') {
|
|
112
|
-
if (!((
|
|
129
|
+
if (!((_b = handoff.runtimeConfig) === null || _b === void 0 ? void 0 : _b.entities.components[id])) {
|
|
113
130
|
throw new package_1.PublishPackageError(`Component "${id}" is not declared in this workspace.`);
|
|
114
131
|
}
|
|
115
132
|
yield (0, builder_1.default)(handoff, id);
|
|
116
133
|
return;
|
|
117
134
|
}
|
|
118
|
-
const pattern = (
|
|
135
|
+
const pattern = (_c = handoff.runtimeConfig) === null || _c === void 0 ? void 0 : _c.entities.patterns[id];
|
|
119
136
|
if (!pattern) {
|
|
120
137
|
throw new package_1.PublishPackageError(`Pattern "${id}" is not declared in this workspace.`);
|
|
121
138
|
}
|
|
@@ -123,7 +140,7 @@ const runTargetedBuild = (handoff, kind, id) => __awaiter(void 0, void 0, void 0
|
|
|
123
140
|
// then compose just this pattern.
|
|
124
141
|
const referencedComponentIds = new Set(pattern.components.map((ref) => ref.id));
|
|
125
142
|
for (const componentId of Array.from(referencedComponentIds)) {
|
|
126
|
-
if ((
|
|
143
|
+
if ((_d = handoff.runtimeConfig) === null || _d === void 0 ? void 0 : _d.entities.components[componentId]) {
|
|
127
144
|
yield (0, builder_1.default)(handoff, componentId);
|
|
128
145
|
}
|
|
129
146
|
}
|
|
@@ -134,6 +151,8 @@ const runTargetedBuild = (handoff, kind, id) => __awaiter(void 0, void 0, void 0
|
|
|
134
151
|
* receive a targeted build, while pages are packaged directly from their source.
|
|
135
152
|
*/
|
|
136
153
|
const publishEntity = (handoff, kind, id) => __awaiter(void 0, void 0, void 0, function* () {
|
|
154
|
+
if (isCatalogLane(kind))
|
|
155
|
+
assertUniqueCatalogIds(handoff);
|
|
137
156
|
const { client, url } = yield (0, exports.resolveTransport)(handoff);
|
|
138
157
|
if (!handoff.skipBuild) {
|
|
139
158
|
logger_1.Logger.info(kind === 'page' ? `Preparing page "${id}" for publish…` : `Building ${kind} "${id}" for publish…`);
|
|
@@ -200,22 +219,18 @@ const selectEntityIds = (available, requested, kind) => {
|
|
|
200
219
|
return selected;
|
|
201
220
|
};
|
|
202
221
|
/**
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
222
|
+
* Assemble and upload the selected entities of one kind. The caller runs the build, because a catalog
|
|
223
|
+
* run covers both entity lanes from one build.
|
|
224
|
+
*
|
|
225
|
+
* A per-entity failure is collected and never aborts the rest. Failures are reported here, and the
|
|
226
|
+
* count is returned so the caller raises one error for the whole run.
|
|
208
227
|
*/
|
|
209
|
-
const
|
|
210
|
-
const { client, url } =
|
|
211
|
-
if (!handoff.skipBuild) {
|
|
212
|
-
logger_1.Logger.info(`Building ${kind}s for publish…`);
|
|
213
|
-
yield runBulkBuild(handoff, kind);
|
|
214
|
-
}
|
|
228
|
+
const uploadEntities = (handoff, transport, kind, ids) => __awaiter(void 0, void 0, void 0, function* () {
|
|
229
|
+
const { client, url } = transport;
|
|
215
230
|
const targets = selectEntityIds(yield listWorkspaceEntityIds(handoff, kind), ids, kind);
|
|
216
231
|
if (targets.length === 0) {
|
|
217
232
|
logger_1.Logger.success(`No ${kind}s are declared in this workspace; nothing to publish.`);
|
|
218
|
-
return;
|
|
233
|
+
return 0;
|
|
219
234
|
}
|
|
220
235
|
// Without a registry there is nothing to compare against, so a dry run reports every target.
|
|
221
236
|
let remote = [];
|
|
@@ -255,11 +270,80 @@ const publishEntities = (handoff, kind, ids) => __awaiter(void 0, void 0, void 0
|
|
|
255
270
|
}
|
|
256
271
|
logger_1.Logger.success(`${kind[0].toUpperCase()}${kind.slice(1)}s publish complete — ${published} ${handoff.dryRun ? 'would be published' : 'published'}, ` +
|
|
257
272
|
`${unchanged} unchanged${failed.length ? `, ${failed.length} failed` : ''}.`);
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
273
|
+
for (const failure of failed) {
|
|
274
|
+
logger_1.Logger.error(` - ${failure.id}: ${failure.message}`);
|
|
275
|
+
}
|
|
276
|
+
return failed.length;
|
|
277
|
+
});
|
|
278
|
+
/**
|
|
279
|
+
* Publish the components, patterns or pages declared in this connected workspace: every one of the
|
|
280
|
+
* kind, or only `ids` when given. Builds the kind once, assembles each entity's package, skips
|
|
281
|
+
* entities whose content hash already matches the registry (unless `--force`), and reports
|
|
282
|
+
* published/unchanged/failed counts. A per-entity failure is collected and never aborts the rest; the
|
|
283
|
+
* run throws at the end if any entity failed.
|
|
284
|
+
*/
|
|
285
|
+
const publishEntities = (handoff, kind, ids) => __awaiter(void 0, void 0, void 0, function* () {
|
|
286
|
+
if (isCatalogLane(kind))
|
|
287
|
+
assertUniqueCatalogIds(handoff);
|
|
288
|
+
const transport = yield (0, exports.resolveTransport)(handoff);
|
|
289
|
+
if (!handoff.skipBuild) {
|
|
290
|
+
logger_1.Logger.info(`Building ${kind}s for publish…`);
|
|
291
|
+
yield runBulkBuild(handoff, kind);
|
|
292
|
+
}
|
|
293
|
+
const failed = yield uploadEntities(handoff, transport, kind, ids);
|
|
294
|
+
if (failed > 0) {
|
|
295
|
+
throw new PublishError(`${failed} ${kind}(s) failed to publish.`);
|
|
263
296
|
}
|
|
264
297
|
});
|
|
265
298
|
exports.publishEntities = publishEntities;
|
|
299
|
+
/**
|
|
300
|
+
* Resolve which lane each requested catalog id belongs to. Without ids every lane runs in full. An
|
|
301
|
+
* unknown id is reported against the whole catalog, because the caller never chose a lane to report
|
|
302
|
+
* it against.
|
|
303
|
+
*/
|
|
304
|
+
const resolveCatalogLanes = (handoff, ids) => __awaiter(void 0, void 0, void 0, function* () {
|
|
305
|
+
if (!ids) {
|
|
306
|
+
return CATALOG_LANES.map((kind) => ({ kind }));
|
|
307
|
+
}
|
|
308
|
+
const available = {
|
|
309
|
+
component: yield listWorkspaceEntityIds(handoff, 'component'),
|
|
310
|
+
pattern: yield listWorkspaceEntityIds(handoff, 'pattern'),
|
|
311
|
+
};
|
|
312
|
+
const { lanes, unknown, ambiguous } = (0, selection_1.splitCatalogIds)(ids, available);
|
|
313
|
+
if (ambiguous.length > 0) {
|
|
314
|
+
throw new PublishError(`${(0, selection_1.quoteIds)(ambiguous)} names both a component and a pattern in this workspace. Give each catalog item a unique id.`);
|
|
315
|
+
}
|
|
316
|
+
if (unknown.length > 0) {
|
|
317
|
+
const declared = [...available.component, ...available.pattern];
|
|
318
|
+
throw new PublishError(`No catalog item named ${(0, selection_1.quoteIds)(unknown)} is declared in this workspace. ` +
|
|
319
|
+
`Declared catalog items: ${declared.join(', ') || '(none)'}.`);
|
|
320
|
+
}
|
|
321
|
+
return CATALOG_LANES.map((kind) => ({ kind, ids: lanes[kind] })).filter((lane) => lane.ids.length > 0);
|
|
322
|
+
});
|
|
323
|
+
/**
|
|
324
|
+
* Publish the catalog items declared in this connected workspace: every one, or only `ids` when
|
|
325
|
+
* given. An item takes the component lane or the pattern lane depending on whether it declares an
|
|
326
|
+
* implementation or a composition, so the caller names items and never names a lane.
|
|
327
|
+
*
|
|
328
|
+
* One build covers both lanes, because building the patterns already builds every component they
|
|
329
|
+
* compose. A failing lane is reported and never aborts the other. The run throws at the end if any
|
|
330
|
+
* item failed.
|
|
331
|
+
*/
|
|
332
|
+
const publishCatalog = (handoff, ids) => __awaiter(void 0, void 0, void 0, function* () {
|
|
333
|
+
assertUniqueCatalogIds(handoff);
|
|
334
|
+
const transport = yield (0, exports.resolveTransport)(handoff);
|
|
335
|
+
const lanes = yield resolveCatalogLanes(handoff, ids);
|
|
336
|
+
if (!handoff.skipBuild) {
|
|
337
|
+
logger_1.Logger.info('Building catalog items for publish…');
|
|
338
|
+
// The pattern build runs the component build first, so one call covers both lanes.
|
|
339
|
+
yield runBulkBuild(handoff, 'pattern');
|
|
340
|
+
}
|
|
341
|
+
let failed = 0;
|
|
342
|
+
for (const lane of lanes) {
|
|
343
|
+
failed += yield uploadEntities(handoff, transport, lane.kind, lane.ids);
|
|
344
|
+
}
|
|
345
|
+
if (failed > 0) {
|
|
346
|
+
throw new PublishError(`${failed} catalog item(s) failed to publish.`);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
exports.publishCatalog = publishCatalog;
|
|
@@ -52,12 +52,14 @@ class PublishPackageError extends Error {
|
|
|
52
52
|
}
|
|
53
53
|
exports.PublishPackageError = PublishPackageError;
|
|
54
54
|
/**
|
|
55
|
-
* Build a registry-safe `item` record: the built summary enriched with the renderer
|
|
55
|
+
* Build a registry-safe `item` record: the built summary enriched with the renderer, its source
|
|
56
|
+
* format, and the entry
|
|
56
57
|
* source-file paths **remapped** from absolute workspace locations to the registry-safe relative
|
|
57
58
|
* paths the uploaded source files use. Workspace-absolute paths never cross to the registry, and a
|
|
58
59
|
* later checkout can reconstruct the entity from the relative entries + uploaded files.
|
|
59
60
|
*/
|
|
60
61
|
const enrichItem = (handoff, kind, id, summary) => __awaiter(void 0, void 0, void 0, function* () {
|
|
62
|
+
var _a;
|
|
61
63
|
const runtime = kind === 'component' ? yield handoff.store.components.get(id) : yield handoff.store.patterns.get(id);
|
|
62
64
|
if (!runtime) {
|
|
63
65
|
return summary;
|
|
@@ -69,6 +71,17 @@ const enrichItem = (handoff, kind, id, summary) => __awaiter(void 0, void 0, voi
|
|
|
69
71
|
if (renderer) {
|
|
70
72
|
item.renderer = renderer;
|
|
71
73
|
}
|
|
74
|
+
const sourceFormat = runtime.sourceFormat;
|
|
75
|
+
if (sourceFormat) {
|
|
76
|
+
item.sourceFormat = sourceFormat;
|
|
77
|
+
}
|
|
78
|
+
const componentExport = runtime.componentExport;
|
|
79
|
+
if (componentExport)
|
|
80
|
+
item.componentExport = componentExport;
|
|
81
|
+
if (kind === 'component') {
|
|
82
|
+
// PostgreSQL jsonb does not preserve object key order.
|
|
83
|
+
item.previewOrder = Object.keys((_a = runtime.previews) !== null && _a !== void 0 ? _a : {});
|
|
84
|
+
}
|
|
72
85
|
if (rawEntries && sourceDir) {
|
|
73
86
|
const remapped = {};
|
|
74
87
|
for (const [key, value] of Object.entries(rawEntries)) {
|
|
@@ -4,9 +4,29 @@
|
|
|
4
4
|
* Every bulk operation discovers what is available (declared locally or published remotely) and may
|
|
5
5
|
* be asked for only part of it. Splitting the request into what exists and what does not lets each
|
|
6
6
|
* caller build its own actionable error while the matching lives in one place.
|
|
7
|
+
*
|
|
8
|
+
* A catalog request needs one more step. A catalog item normalizes into a component or a pattern
|
|
9
|
+
* from its declaration, so the CLI names the item and the lane is looked up here.
|
|
7
10
|
*/
|
|
8
11
|
/** Narrow an available list to the requested subset, separating out ids that do not exist. */
|
|
9
12
|
export declare const selectIds: (available: string[], requested?: string[]) => {
|
|
10
13
|
selected: string[];
|
|
11
14
|
unknown: string[];
|
|
12
15
|
};
|
|
16
|
+
/** Catalog item ids grouped by lane. */
|
|
17
|
+
export interface CatalogLanes {
|
|
18
|
+
component: string[];
|
|
19
|
+
pattern: string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Route each requested catalog id to its lane. The two lanes are keyed separately, so nothing stops a
|
|
23
|
+
* workspace from declaring one id twice. Such an id is reported rather than guessed, because picking
|
|
24
|
+
* a lane silently would act on the wrong entity.
|
|
25
|
+
*/
|
|
26
|
+
export declare const splitCatalogIds: (requested: string[], available: CatalogLanes) => {
|
|
27
|
+
lanes: CatalogLanes;
|
|
28
|
+
unknown: string[];
|
|
29
|
+
ambiguous: string[];
|
|
30
|
+
};
|
|
31
|
+
/** Quote ids for an error message: `"button", "card"`. */
|
|
32
|
+
export declare const quoteIds: (ids: string[]) => string;
|
|
@@ -5,9 +5,12 @@
|
|
|
5
5
|
* Every bulk operation discovers what is available (declared locally or published remotely) and may
|
|
6
6
|
* be asked for only part of it. Splitting the request into what exists and what does not lets each
|
|
7
7
|
* caller build its own actionable error while the matching lives in one place.
|
|
8
|
+
*
|
|
9
|
+
* A catalog request needs one more step. A catalog item normalizes into a component or a pattern
|
|
10
|
+
* from its declaration, so the CLI names the item and the lane is looked up here.
|
|
8
11
|
*/
|
|
9
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.selectIds = void 0;
|
|
13
|
+
exports.quoteIds = exports.splitCatalogIds = exports.selectIds = void 0;
|
|
11
14
|
/** Narrow an available list to the requested subset, separating out ids that do not exist. */
|
|
12
15
|
const selectIds = (available, requested) => {
|
|
13
16
|
if (!requested) {
|
|
@@ -20,3 +23,36 @@ const selectIds = (available, requested) => {
|
|
|
20
23
|
};
|
|
21
24
|
};
|
|
22
25
|
exports.selectIds = selectIds;
|
|
26
|
+
/**
|
|
27
|
+
* Route each requested catalog id to its lane. The two lanes are keyed separately, so nothing stops a
|
|
28
|
+
* workspace from declaring one id twice. Such an id is reported rather than guessed, because picking
|
|
29
|
+
* a lane silently would act on the wrong entity.
|
|
30
|
+
*/
|
|
31
|
+
const splitCatalogIds = (requested, available) => {
|
|
32
|
+
const components = new Set(available.component);
|
|
33
|
+
const patterns = new Set(available.pattern);
|
|
34
|
+
const lanes = { component: [], pattern: [] };
|
|
35
|
+
const unknown = [];
|
|
36
|
+
const ambiguous = [];
|
|
37
|
+
for (const id of requested) {
|
|
38
|
+
const isComponent = components.has(id);
|
|
39
|
+
const isPattern = patterns.has(id);
|
|
40
|
+
if (isComponent && isPattern) {
|
|
41
|
+
ambiguous.push(id);
|
|
42
|
+
}
|
|
43
|
+
else if (isComponent) {
|
|
44
|
+
lanes.component.push(id);
|
|
45
|
+
}
|
|
46
|
+
else if (isPattern) {
|
|
47
|
+
lanes.pattern.push(id);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
unknown.push(id);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { lanes, unknown, ambiguous };
|
|
54
|
+
};
|
|
55
|
+
exports.splitCatalogIds = splitCatalogIds;
|
|
56
|
+
/** Quote ids for an error message: `"button", "card"`. */
|
|
57
|
+
const quoteIds = (ids) => ids.map((id) => `"${id}"`).join(', ');
|
|
58
|
+
exports.quoteIds = quoteIds;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Filesystem-backed implementation of the normalized store abstraction.
|
|
3
3
|
*
|
|
4
|
-
* It is a thin read view over the already-resolved `runtimeConfig.
|
|
4
|
+
* It is a thin read view over the already-resolved `runtimeConfig.entities`, so the records it
|
|
5
5
|
* returns are the same normalized component/pattern records the build consumes today — discovery
|
|
6
6
|
* and normalization (modern `*.handoff.*` + legacy `{dirname}.*`, react/handlebars/csf/plain-object
|
|
7
7
|
* declarations, CSF story discovery, `entries` resolution) all happen upstream in
|
package/dist/store/filesystem.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Filesystem-backed implementation of the normalized store abstraction.
|
|
4
4
|
*
|
|
5
|
-
* It is a thin read view over the already-resolved `runtimeConfig.
|
|
5
|
+
* It is a thin read view over the already-resolved `runtimeConfig.entities`, so the records it
|
|
6
6
|
* returns are the same normalized component/pattern records the build consumes today — discovery
|
|
7
7
|
* and normalization (modern `*.handoff.*` + legacy `{dirname}.*`, react/handlebars/csf/plain-object
|
|
8
8
|
* declarations, CSF story discovery, `entries` resolution) all happen upstream in
|
|
@@ -42,8 +42,8 @@ class FilesystemComponentStore {
|
|
|
42
42
|
this.context = context;
|
|
43
43
|
}
|
|
44
44
|
get records() {
|
|
45
|
-
var _a, _b
|
|
46
|
-
return (
|
|
45
|
+
var _a, _b;
|
|
46
|
+
return (_b = (_a = this.context.runtimeConfig) === null || _a === void 0 ? void 0 : _a.entities.components) !== null && _b !== void 0 ? _b : {};
|
|
47
47
|
}
|
|
48
48
|
list() {
|
|
49
49
|
return Object.values(this.records);
|
|
@@ -68,8 +68,8 @@ class FilesystemPatternStore {
|
|
|
68
68
|
this.context = context;
|
|
69
69
|
}
|
|
70
70
|
get records() {
|
|
71
|
-
var _a, _b
|
|
72
|
-
return (
|
|
71
|
+
var _a, _b;
|
|
72
|
+
return (_b = (_a = this.context.runtimeConfig) === null || _a === void 0 ? void 0 : _a.entities.patterns) !== null && _b !== void 0 ? _b : {};
|
|
73
73
|
}
|
|
74
74
|
list() {
|
|
75
75
|
return Object.values(this.records);
|
|
@@ -116,8 +116,8 @@ class FilesystemPageStore {
|
|
|
116
116
|
this.context = context;
|
|
117
117
|
}
|
|
118
118
|
get records() {
|
|
119
|
-
var _a, _b
|
|
120
|
-
return (
|
|
119
|
+
var _a, _b;
|
|
120
|
+
return (_b = (_a = this.context.runtimeConfig) === null || _a === void 0 ? void 0 : _a.entities.pages) !== null && _b !== void 0 ? _b : {};
|
|
121
121
|
}
|
|
122
122
|
list() {
|
|
123
123
|
return Object.values(this.records);
|
package/dist/store/registry.js
CHANGED
|
@@ -23,6 +23,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
23
23
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
24
24
|
});
|
|
25
25
|
};
|
|
26
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
27
|
+
var t = {};
|
|
28
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
29
|
+
t[p] = s[p];
|
|
30
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
31
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
32
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
33
|
+
t[p[i]] = s[p[i]];
|
|
34
|
+
}
|
|
35
|
+
return t;
|
|
36
|
+
};
|
|
26
37
|
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
27
38
|
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
28
39
|
var m = o[Symbol.asyncIterator], i;
|
|
@@ -32,6 +43,7 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
|
32
43
|
};
|
|
33
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
45
|
exports.createRegistryStore = exports.RegistryAssetStore = exports.RegistryTokenStore = exports.filterPublishedPageIds = exports.searchPageCandidates = exports.RegistryPageStore = exports.RegistryPatternStore = exports.RegistryComponentStore = void 0;
|
|
46
|
+
const previews_1 = require("../catalog/previews");
|
|
35
47
|
const drizzle_orm_1 = require("drizzle-orm");
|
|
36
48
|
const schema_1 = require("../registry/db/schema");
|
|
37
49
|
/**
|
|
@@ -52,6 +64,16 @@ const toTextFileResource = (row) => {
|
|
|
52
64
|
contentType: row.contentType,
|
|
53
65
|
};
|
|
54
66
|
};
|
|
67
|
+
/**
|
|
68
|
+
* Restore source order after jsonb storage without exposing transfer-only metadata. `entries` and
|
|
69
|
+
* `componentExport` describe the publisher's source layout and exist for checkout. The workspace
|
|
70
|
+
* has no equivalent, so the docs API must not serve them.
|
|
71
|
+
*/
|
|
72
|
+
const readComponentRecord = (record) => {
|
|
73
|
+
var _a;
|
|
74
|
+
const { previewOrder, entries, componentExport } = record, item = __rest(record, ["previewOrder", "entries", "componentExport"]);
|
|
75
|
+
return Object.assign(Object.assign({}, item), { previews: (0, previews_1.orderPreviews)((_a = item.previews) !== null && _a !== void 0 ? _a : {}, previewOrder !== null && previewOrder !== void 0 ? previewOrder : []) });
|
|
76
|
+
};
|
|
55
77
|
class RegistryComponentStore {
|
|
56
78
|
constructor(context) {
|
|
57
79
|
this.context = context;
|
|
@@ -59,14 +81,13 @@ class RegistryComponentStore {
|
|
|
59
81
|
list() {
|
|
60
82
|
return __awaiter(this, void 0, void 0, function* () {
|
|
61
83
|
const rows = yield this.context.db.select({ record: schema_1.components.record }).from(schema_1.components);
|
|
62
|
-
return rows.map((row) => row.record);
|
|
84
|
+
return rows.map((row) => readComponentRecord(row.record));
|
|
63
85
|
});
|
|
64
86
|
}
|
|
65
87
|
get(id) {
|
|
66
88
|
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
-
var _a, _b;
|
|
68
89
|
const rows = yield this.context.db.select({ record: schema_1.components.record }).from(schema_1.components).where((0, drizzle_orm_1.eq)(schema_1.components.id, id)).limit(1);
|
|
69
|
-
return
|
|
90
|
+
return rows[0] ? readComponentRecord(rows[0].record) : null;
|
|
70
91
|
});
|
|
71
92
|
}
|
|
72
93
|
/**
|
|
@@ -19,6 +19,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
19
19
|
const react_1 = __importDefault(require("react"));
|
|
20
20
|
const server_1 = __importDefault(require("react-dom/server"));
|
|
21
21
|
const react_element_to_jsx_string_1 = __importDefault(require("react-element-to-jsx-string"));
|
|
22
|
+
const catalog_1 = require("../../catalog");
|
|
22
23
|
const logger_1 = require("../../utils/logger");
|
|
23
24
|
const docgen_1 = require("../docgen");
|
|
24
25
|
const component_1 = require("../preview/component");
|
|
@@ -304,8 +305,9 @@ function csfRenderPlugin(componentData, _documentationComponents, handoff) {
|
|
|
304
305
|
const generatedProperties = Object.assign({}, explicitProperties);
|
|
305
306
|
const incomingPreviews = Object.assign({}, (componentData.previews || {}));
|
|
306
307
|
const patternPreviews = Object.fromEntries(Object.entries(incomingPreviews).filter(([key]) => key.startsWith('__pattern_')));
|
|
307
|
-
// Include all named stories as previews and preserve injected pattern previews.
|
|
308
|
-
|
|
308
|
+
// Include all named stories as previews and preserve injected pattern previews. Story order
|
|
309
|
+
// comes from the source text: esbuild emits its export map alphabetically.
|
|
310
|
+
componentData.previews = Object.assign(Object.assign({}, (0, catalog_1.orderPreviews)((0, csf_1.createCsfStoryPreviews)(moduleExports), (0, catalog_1.readExportOrderFromSource)(sourceCode))), patternPreviews);
|
|
309
311
|
for (const [storyKey, storyValue] of stories) {
|
|
310
312
|
const storyObj = (typeof storyValue === 'function' ? {} : storyValue);
|
|
311
313
|
const mergedArgs = Object.assign(Object.assign({}, (meta.args || {})), (storyObj.args || {}));
|
|
@@ -49,6 +49,13 @@ const PLUGIN_CONSTANTS = {
|
|
|
49
49
|
const CLIENT_ARTIFACT_SUFFIX = 'client.js';
|
|
50
50
|
/** Logical artifact path of a component's client/hydration bundle. */
|
|
51
51
|
const clientArtifactPath = (componentId) => `component/${componentId}.${CLIENT_ARTIFACT_SUFFIX}`;
|
|
52
|
+
function selectComponentExport(moduleExports, exportName) {
|
|
53
|
+
var _a;
|
|
54
|
+
if (exportName && exportName !== 'default' && (moduleExports === null || moduleExports === void 0 ? void 0 : moduleExports[exportName])) {
|
|
55
|
+
return moduleExports[exportName];
|
|
56
|
+
}
|
|
57
|
+
return (_a = moduleExports === null || moduleExports === void 0 ? void 0 : moduleExports.default) !== null && _a !== void 0 ? _a : null;
|
|
58
|
+
}
|
|
52
59
|
/**
|
|
53
60
|
* Loads and processes component schema using hierarchical approach
|
|
54
61
|
* @param componentData - Component transformation data
|
|
@@ -70,7 +77,7 @@ function loadComponentSchemaAndModule(componentData, componentPath, handoff) {
|
|
|
70
77
|
if (!((_b = componentData.entries) === null || _b === void 0 ? void 0 : _b.schema)) {
|
|
71
78
|
try {
|
|
72
79
|
const moduleExports = yield (0, module_1.buildAndEvaluateModule)(componentPath, handoff);
|
|
73
|
-
component = moduleExports.exports.
|
|
80
|
+
component = selectComponentExport(moduleExports.exports, componentData.componentExport);
|
|
74
81
|
// Try to load schema from component exports
|
|
75
82
|
properties = yield (0, schema_loader_1.loadSchemaFromComponent)(moduleExports.exports, handoff);
|
|
76
83
|
// If no schema found, use shared docgen fallback
|
|
@@ -86,7 +93,7 @@ function loadComponentSchemaAndModule(componentData, componentPath, handoff) {
|
|
|
86
93
|
if (!component) {
|
|
87
94
|
try {
|
|
88
95
|
const moduleExports = yield (0, module_1.buildAndEvaluateModule)(componentPath, handoff);
|
|
89
|
-
component = moduleExports.exports.
|
|
96
|
+
component = selectComponentExport(moduleExports.exports, componentData.componentExport);
|
|
90
97
|
}
|
|
91
98
|
catch (error) {
|
|
92
99
|
logger_1.Logger.error(`Failed to load component for rendering "${componentPath}":`, error);
|
|
@@ -111,13 +118,15 @@ function loadComponentSchemaAndModule(componentData, componentPath, handoff) {
|
|
|
111
118
|
*
|
|
112
119
|
* @param componentId - Component identifier used to match pattern mount points to this bundle
|
|
113
120
|
* @param componentPath - Path to the component file
|
|
121
|
+
* @param componentExport - Export holding the implementation; the default export when absent
|
|
114
122
|
* @returns Client-side hydration source code
|
|
115
123
|
*/
|
|
116
|
-
function generateClientHydrationSource(componentId, componentPath) {
|
|
124
|
+
function generateClientHydrationSource(componentId, componentPath, componentExport) {
|
|
125
|
+
const importClause = componentExport && componentExport !== 'default' ? `{ ${componentExport} as Component }` : 'Component';
|
|
117
126
|
return `
|
|
118
127
|
import React from 'react';
|
|
119
128
|
import { hydrateRoot } from 'react-dom/client';
|
|
120
|
-
import
|
|
129
|
+
import ${importClause} from '${(0, vite_1.normalizePath)(componentPath)}';
|
|
121
130
|
|
|
122
131
|
const parseProps = (propsId) => {
|
|
123
132
|
const raw = propsId ? document.getElementById(propsId)?.textContent : '{}';
|
|
@@ -266,7 +275,7 @@ function ssrRenderPlugin(componentData, documentationComponents, handoff) {
|
|
|
266
275
|
// `component/<id>.client.js` artifact. The hydration source only imports the component and
|
|
267
276
|
// reads props from the in-document `__APP_PROPS__` element, so it is identical across every
|
|
268
277
|
// preview of this component.
|
|
269
|
-
const clientHydrationSource = generateClientHydrationSource(componentId, componentPath);
|
|
278
|
+
const clientHydrationSource = generateClientHydrationSource(componentId, componentPath, componentData.componentExport);
|
|
270
279
|
const clientBuildConfig = Object.assign(Object.assign({}, build_1.DEFAULT_CLIENT_BUILD_CONFIG), { logLevel: 'silent', stdin: {
|
|
271
280
|
contents: clientHydrationSource,
|
|
272
281
|
resolveDir: process.cwd(),
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import Handoff from '../../../index';
|
|
2
2
|
import { ComponentListObject, TransformComponentTokensResult } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Strip the fields that must not reach the written artifact.
|
|
5
|
+
*
|
|
6
|
+
* The docs API serves this artifact publicly, and publish uploads it verbatim. An absolute path in
|
|
7
|
+
* the artifact exposes the filesystem layout of the build machine, so this drops the workspace
|
|
8
|
+
* locations `path` and `entries`. The build takes those locations from the runtime config, and
|
|
9
|
+
* publish remaps `entries` onto the registry record.
|
|
10
|
+
*/
|
|
3
11
|
export declare const sanitizeComponentApiData: (component: TransformComponentTokensResult) => TransformComponentTokensResult;
|
|
4
12
|
export declare const getAPIPath: (handoff: Handoff) => string;
|
|
5
13
|
export declare const writeComponentApi: (id: string, component: TransformComponentTokensResult, handoff: Handoff, preserveKeys?: string[]) => Promise<void>;
|