handoff-app 1.2.2-7 → 2.0.0-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Changelog.md +37 -15
- package/README.md +372 -118
- package/dist/app-builder/build.d.ts +41 -2
- package/dist/app-builder/build.js +455 -18
- package/dist/app-builder/client-config.d.ts +15 -2
- package/dist/app-builder/client-config.js +43 -4
- package/dist/app-builder/config-diff/snapshot.d.ts +1 -6
- package/dist/app-builder/config-diff/snapshot.js +2 -9
- package/dist/app-builder/index.d.ts +1 -1
- package/dist/app-builder/index.js +3 -1
- package/dist/app-builder/nav-shell.d.ts +23 -0
- package/dist/app-builder/nav-shell.js +80 -0
- package/dist/app-builder/static-export.d.ts +17 -0
- package/dist/app-builder/static-export.js +181 -0
- package/dist/app-builder/vercel-output.d.ts +39 -0
- package/dist/app-builder/vercel-output.js +259 -0
- package/dist/app-builder/watchers/utils.d.ts +2 -0
- package/dist/app-builder/watchers.d.ts +14 -4
- package/dist/app-builder/watchers.js +123 -28
- package/dist/app-builder/websocket.js +1 -1
- package/dist/artifacts/index.d.ts +2 -0
- package/dist/artifacts/index.js +13 -0
- package/dist/artifacts/types.d.ts +136 -0
- package/dist/artifacts/types.js +24 -0
- package/dist/artifacts/url.d.ts +49 -0
- package/dist/artifacts/url.js +86 -0
- package/dist/cache/build-cache.js +48 -4
- package/dist/cli.js +0 -0
- package/dist/commands/build/app.js +1 -2
- package/dist/commands/build/index.d.ts +17 -0
- package/dist/commands/build/index.js +66 -0
- package/dist/commands/checkout/index.d.ts +24 -0
- package/dist/commands/checkout/index.js +71 -0
- package/dist/commands/db/migrate.d.ts +11 -0
- package/dist/commands/db/migrate.js +33 -0
- package/dist/commands/index.js +8 -0
- package/dist/commands/publish/index.d.ts +21 -0
- package/dist/commands/publish/index.js +68 -0
- package/dist/config/defaults.js +15 -1
- package/dist/config/loader.js +6 -1
- package/dist/config/normalizers/declaration.js +4 -1
- package/dist/config/normalizers/page.d.ts +18 -0
- package/dist/config/normalizers/page.js +34 -0
- package/dist/config/normalizers/pattern.js +7 -1
- package/dist/config/runtime.d.ts +4 -0
- package/dist/config/runtime.js +53 -5
- package/dist/index.d.ts +65 -1
- package/dist/index.js +123 -3
- package/dist/nav/index.d.ts +83 -0
- package/dist/nav/index.js +9 -0
- package/dist/nav/registry.d.ts +15 -0
- package/dist/nav/registry.js +42 -0
- package/dist/nav/resolver.d.ts +8 -0
- package/dist/nav/resolver.js +192 -0
- package/dist/nav/workspace.d.ts +18 -0
- package/dist/nav/workspace.js +103 -0
- package/dist/pipeline/styles.js +7 -35
- package/dist/pipeline/token-transformers.d.ts +45 -0
- package/dist/pipeline/token-transformers.js +71 -0
- package/dist/registry/asset-storage/adapters/vercel-blob.d.ts +17 -0
- package/dist/registry/asset-storage/adapters/vercel-blob.js +87 -0
- package/dist/registry/asset-storage/define.d.ts +10 -0
- package/dist/registry/asset-storage/define.js +13 -0
- package/dist/registry/asset-storage/resolve.d.ts +45 -0
- package/dist/registry/asset-storage/resolve.js +36 -0
- package/dist/registry/asset-storage/types.d.ts +51 -0
- package/dist/registry/asset-storage/types.js +9 -0
- package/dist/registry/assets/layout.d.ts +22 -0
- package/dist/registry/assets/layout.js +30 -0
- package/dist/registry/assets/sets.d.ts +18 -0
- package/dist/registry/assets/sets.js +44 -0
- package/dist/registry/assets/transfer.d.ts +45 -0
- package/dist/registry/assets/transfer.js +11 -0
- package/dist/registry/checkout/assets.d.ts +16 -0
- package/dist/registry/checkout/assets.js +150 -0
- package/dist/registry/checkout/index.d.ts +33 -0
- package/dist/registry/checkout/index.js +610 -0
- package/dist/registry/checkout/tokens.d.ts +15 -0
- package/dist/registry/checkout/tokens.js +171 -0
- package/dist/registry/client.d.ts +61 -0
- package/dist/registry/client.js +211 -0
- package/dist/registry/connection.d.ts +30 -0
- package/dist/registry/connection.js +36 -0
- package/dist/registry/db/adapter.d.ts +43 -0
- package/dist/registry/db/adapter.js +59 -0
- package/dist/registry/db/client.d.ts +35 -0
- package/dist/registry/db/client.js +94 -0
- package/dist/registry/db/index.d.ts +5 -0
- package/dist/registry/db/index.js +24 -0
- package/dist/registry/db/migrate.d.ts +23 -0
- package/dist/registry/db/migrate.js +64 -0
- package/dist/registry/db/schema.d.ts +4869 -0
- package/dist/registry/db/schema.js +347 -0
- package/dist/registry/path.d.ts +4 -0
- package/dist/registry/path.js +31 -0
- package/dist/registry/publish/artifacts.d.ts +16 -0
- package/dist/registry/publish/artifacts.js +132 -0
- package/dist/registry/publish/assets.d.ts +16 -0
- package/dist/registry/publish/assets.js +129 -0
- package/dist/registry/publish/errors.d.ts +5 -0
- package/dist/registry/publish/errors.js +26 -0
- package/dist/registry/publish/index.d.ts +27 -0
- package/dist/registry/publish/index.js +126 -0
- package/dist/registry/publish/package.d.ts +27 -0
- package/dist/registry/publish/package.js +257 -0
- package/dist/registry/publish/publish-build.d.ts +12 -0
- package/dist/registry/publish/publish-build.js +43 -0
- package/dist/registry/publish/tokens.d.ts +18 -0
- package/dist/registry/publish/tokens.js +112 -0
- package/dist/registry/tokens/sets.d.ts +59 -0
- package/dist/registry/tokens/sets.js +109 -0
- package/dist/registry/tokens/transfer.d.ts +48 -0
- package/dist/registry/tokens/transfer.js +10 -0
- package/dist/registry/transfer.d.ts +75 -0
- package/dist/registry/transfer.js +11 -0
- package/dist/store/filesystem-assets.d.ts +17 -0
- package/dist/store/filesystem-assets.js +147 -0
- package/dist/store/filesystem.d.ts +76 -0
- package/dist/store/filesystem.js +208 -0
- package/dist/store/index.d.ts +20 -0
- package/dist/store/index.js +38 -0
- package/dist/store/registry.d.ts +77 -0
- package/dist/store/registry.js +350 -0
- package/dist/store/source-files.d.ts +24 -0
- package/dist/store/source-files.js +147 -0
- package/dist/store/types.d.ts +185 -0
- package/dist/store/types.js +12 -0
- package/dist/transformers/plugins/csf-render.js +17 -8
- package/dist/transformers/plugins/handlebars-previews.js +10 -3
- package/dist/transformers/plugins/ssr-render.js +116 -49
- package/dist/transformers/preview/component/api.js +3 -1
- package/dist/transformers/preview/component/artifacts.js +8 -1
- package/dist/transformers/preview/component/builder.js +13 -5
- package/dist/transformers/preview/component/css.js +9 -1
- package/dist/transformers/preview/component/javascript.d.ts +9 -3
- package/dist/transformers/preview/component/javascript.js +45 -17
- package/dist/transformers/preview/component/shared-artifacts.d.ts +83 -0
- package/dist/transformers/preview/component/shared-artifacts.js +92 -0
- package/dist/transformers/preview/component.js +5 -2
- package/dist/transformers/preview/pattern/builder.js +28 -9
- package/dist/transformers/preview/pattern/html.d.ts +13 -10
- package/dist/transformers/preview/pattern/html.js +62 -27
- package/dist/transformers/preview/types.d.ts +38 -0
- package/dist/transformers/utils/handlebars.d.ts +3 -0
- package/dist/transformers/utils/handlebars.js +19 -5
- package/dist/types/config.d.ts +118 -25
- package/dist/utils/menu-shell.d.ts +60 -0
- package/dist/utils/menu-shell.js +221 -0
- package/dist/utils/stable-stringify.d.ts +2 -0
- package/dist/utils/stable-stringify.js +8 -0
- package/docs/cli.md +4 -2
- package/drizzle/0000_init_registry_storage.sql +95 -0
- package/drizzle/0001_add_review_metadata.sql +2 -0
- package/drizzle/0002_add_pages.sql +28 -0
- package/drizzle/0003_add_tokens.sql +29 -0
- package/drizzle/0004_add_assets.sql +37 -0
- package/drizzle/meta/0000_snapshot.json +642 -0
- package/drizzle/meta/0001_snapshot.json +654 -0
- package/drizzle/meta/0002_snapshot.json +835 -0
- package/drizzle/meta/0003_snapshot.json +1023 -0
- package/drizzle/meta/0004_snapshot.json +1252 -0
- package/drizzle/meta/_journal.json +41 -0
- package/drizzle.config.ts +16 -0
- package/package.json +10 -1
- package/src/app/components/Component/Preview.tsx +3 -2
- package/src/app/components/Component/RegistryActions.tsx +150 -0
- package/src/app/components/Foundations/DisplayLogo.tsx +5 -3
- package/src/app/components/Layout/Header.tsx +21 -3
- package/src/app/components/Layout/Main.tsx +11 -3
- package/src/app/components/Navigation/MainNav.tsx +4 -2
- package/src/app/components/Navigation/MobileNav.tsx +4 -2
- package/src/app/components/Navigation/SideNav.tsx +46 -11
- package/src/app/components/NotFound.tsx +24 -0
- package/src/app/components/context/NavProvider.tsx +71 -0
- package/src/app/components/old/Header.tsx +3 -3
- package/src/app/components/util/index.ts +203 -380
- package/src/app/components/util/useCollectionAssets.ts +125 -0
- package/src/app/components/util/useFoundationTokens.ts +67 -0
- package/src/app/generated/default-pages.json +1 -0
- package/src/app/generated/nav-shell.json +1 -0
- package/src/app/lib/api/query.ts +6 -0
- package/src/app/lib/api/redact.ts +46 -0
- package/src/app/lib/asset-storage.ts +81 -0
- package/src/app/lib/docs-api/artifacts.ts +116 -0
- package/src/app/lib/docs-api/backend.ts +151 -0
- package/src/app/lib/docs-api/errors.ts +52 -0
- package/src/app/lib/docs-api/handler.ts +34 -0
- package/src/app/lib/docs-api/index.ts +7 -0
- package/src/app/lib/docs-api/records.ts +189 -0
- package/src/app/lib/docs-api/registry.ts +130 -0
- package/src/app/lib/docs-api/runtime-config.ts +173 -0
- package/src/app/lib/docs-api/serve.ts +37 -0
- package/src/app/lib/docs-api/token-detail.ts +19 -0
- package/src/app/lib/registry-api/allowlist.ts +163 -0
- package/src/app/lib/registry-api/asset-transfer.ts +363 -0
- package/src/app/lib/registry-api/auth.ts +68 -0
- package/src/app/lib/registry-api/entity-routes.ts +197 -0
- package/src/app/lib/registry-api/errors.ts +51 -0
- package/src/app/lib/registry-api/files.ts +135 -0
- package/src/app/lib/registry-api/handler.ts +96 -0
- package/src/app/lib/registry-api/index.ts +4 -0
- package/src/app/lib/registry-api/meta.ts +87 -0
- package/src/app/lib/registry-api/revalidate.ts +36 -0
- package/src/app/lib/registry-api/store.ts +348 -0
- package/src/app/lib/registry-api/token-transfer.ts +231 -0
- package/src/app/lib/registry-api/transfer.ts +513 -0
- package/src/app/lib/registry-api/validation.ts +74 -0
- package/src/app/lib/registry-connection.ts +58 -0
- package/src/app/lib/utils.ts +14 -0
- package/src/app/next.config.mjs +72 -13
- package/src/app/pages/[...slug]/index.tsx +74 -20
- package/src/app/pages/_app.tsx +5 -2
- package/src/app/pages/api/docs/artifacts/[...artifactPath].ts +16 -0
- package/src/app/pages/api/docs/assets/[collection]/[...path].ts +50 -0
- package/src/app/pages/api/docs/assets/[collection]/index.ts +22 -0
- package/src/app/pages/api/docs/components/[id]/assets/[asset].ts +33 -0
- package/src/app/pages/api/docs/components/[id]/inspect/[previewId].ts +20 -0
- package/src/app/pages/api/docs/components/[id]/previews/[previewId].ts +21 -0
- package/src/app/pages/api/docs/components/[id].ts +24 -0
- package/src/app/pages/api/docs/components.json.ts +12 -0
- package/src/app/pages/api/docs/nav.json.ts +48 -0
- package/src/app/pages/api/docs/patterns/[id]/preview.ts +19 -0
- package/src/app/pages/api/docs/patterns/[id].ts +24 -0
- package/src/app/pages/api/docs/patterns.json.ts +12 -0
- package/src/app/pages/api/docs/tokens/components/[id].ts +30 -0
- package/src/app/pages/api/docs/tokens/foundations/[type].ts +32 -0
- package/src/app/pages/api/registry/components/[id]/files/[...filePath].ts +19 -0
- package/src/app/pages/api/registry/components/[id]/files/index.ts +19 -0
- package/src/app/pages/api/registry/components/[id].ts +20 -0
- package/src/app/pages/api/registry/components/index.ts +19 -0
- package/src/app/pages/api/registry/health.ts +20 -0
- package/src/app/pages/api/registry/patterns/[id]/files/[...filePath].ts +19 -0
- package/src/app/pages/api/registry/patterns/[id]/files/index.ts +19 -0
- package/src/app/pages/api/registry/patterns/[id].ts +20 -0
- package/src/app/pages/api/registry/patterns/index.ts +19 -0
- package/src/app/pages/api/registry/transfer/[kind]/[id].ts +39 -0
- package/src/app/pages/api/registry/transfer/assets/[collection].ts +24 -0
- package/src/app/pages/api/registry/transfer/assets/blobs/[hash].ts +23 -0
- package/src/app/pages/api/registry/transfer/assets/blobs/have.ts +11 -0
- package/src/app/pages/api/registry/transfer/assets/index.ts +10 -0
- package/src/app/pages/api/registry/transfer/tokens/[...setId].ts +26 -0
- package/src/app/pages/api/registry/transfer/tokens/index.ts +11 -0
- package/src/app/pages/assets/fonts.tsx +41 -17
- package/src/app/pages/assets/index.tsx +2 -2
- package/src/app/pages/assets/logos.tsx +2 -2
- package/src/app/pages/foundations/colors.tsx +18 -8
- package/src/app/pages/foundations/effects.tsx +18 -8
- package/src/app/pages/foundations/icons/[name]/index.tsx +26 -14
- package/src/app/pages/foundations/icons/index.tsx +13 -9
- package/src/app/pages/foundations/index.tsx +1 -1
- package/src/app/pages/foundations/logo.tsx +7 -4
- package/src/app/pages/foundations/typography.tsx +19 -9
- package/src/app/pages/index.tsx +1 -1
- package/src/app/pages/system/component/[component]/index.tsx +87 -17
- package/src/app/pages/system/index.tsx +13 -4
- package/src/app/pages/system/pattern/[pattern]/index.tsx +70 -14
- package/src/app/pages/system/tokens/components/[component]/index.tsx +42 -14
- package/src/app/pages/system/tokens/foundations/colors.tsx +7 -5
- package/src/app/pages/system/tokens/foundations/effects.tsx +7 -5
- package/src/app/pages/system/tokens/foundations/typography.tsx +8 -4
- package/src/app/tsconfig.json +2 -3
- package/src/app-builder/build.ts +555 -11
- package/src/app-builder/client-config.ts +61 -4
- package/src/app-builder/config-diff/snapshot.ts +1 -11
- package/src/app-builder/index.ts +1 -1
- package/src/app-builder/nav-shell.ts +74 -0
- package/src/app-builder/static-export.ts +215 -0
- package/src/app-builder/vercel-output.ts +297 -0
- package/src/app-builder/watchers/utils.ts +2 -0
- package/src/app-builder/watchers.ts +149 -25
- package/src/app-builder/websocket.ts +2 -2
- package/src/artifacts/README.md +14 -0
- package/src/artifacts/index.ts +17 -0
- package/src/artifacts/types.ts +146 -0
- package/src/artifacts/url.ts +90 -0
- package/src/cache/build-cache.ts +47 -2
- package/src/commands/build/app.ts +1 -2
- package/src/commands/build/index.ts +61 -0
- package/src/commands/checkout/index.ts +66 -0
- package/src/commands/db/migrate.ts +25 -0
- package/src/commands/index.ts +8 -0
- package/src/commands/publish/index.ts +63 -0
- package/src/config/defaults.ts +15 -0
- package/src/config/loader.ts +10 -1
- package/src/config/normalizers/declaration.ts +3 -0
- package/src/config/normalizers/page.ts +45 -0
- package/src/config/normalizers/pattern.ts +4 -1
- package/src/config/runtime.ts +48 -2
- package/src/index.ts +126 -3
- package/src/nav/index.ts +94 -0
- package/src/nav/registry.ts +54 -0
- package/src/nav/resolver.ts +217 -0
- package/src/nav/workspace.ts +87 -0
- package/src/pipeline/styles.ts +4 -35
- package/src/pipeline/token-transformers.ts +97 -0
- package/src/registry/asset-storage/adapters/vercel-blob.ts +51 -0
- package/src/registry/asset-storage/define.ts +15 -0
- package/src/registry/asset-storage/resolve.ts +72 -0
- package/src/registry/asset-storage/types.ts +46 -0
- package/src/registry/assets/layout.ts +38 -0
- package/src/registry/assets/sets.ts +48 -0
- package/src/registry/assets/transfer.ts +50 -0
- package/src/registry/checkout/assets.ts +126 -0
- package/src/registry/checkout/index.ts +596 -0
- package/src/registry/checkout/tokens.ts +152 -0
- package/src/registry/client.ts +234 -0
- package/src/registry/connection.ts +50 -0
- package/src/registry/db/adapter.ts +74 -0
- package/src/registry/db/client.ts +88 -0
- package/src/registry/db/index.ts +35 -0
- package/src/registry/db/migrate.ts +56 -0
- package/src/registry/db/schema.ts +444 -0
- package/src/registry/path.ts +26 -0
- package/src/registry/publish/artifacts.ts +147 -0
- package/src/registry/publish/assets.ts +129 -0
- package/src/registry/publish/errors.ts +34 -0
- package/src/registry/publish/index.ts +128 -0
- package/src/registry/publish/package.ts +272 -0
- package/src/registry/publish/publish-build.ts +51 -0
- package/src/registry/publish/tokens.ts +119 -0
- package/src/registry/tokens/sets.ts +132 -0
- package/src/registry/tokens/transfer.ts +53 -0
- package/src/registry/transfer.ts +82 -0
- package/src/store/filesystem-assets.ts +152 -0
- package/src/store/filesystem.ts +237 -0
- package/src/store/index.ts +62 -0
- package/src/store/registry.ts +334 -0
- package/src/store/source-files.ts +155 -0
- package/src/store/types.ts +210 -0
- package/src/transformers/plugins/csf-render.ts +31 -7
- package/src/transformers/plugins/handlebars-previews.ts +22 -3
- package/src/transformers/plugins/ssr-render.ts +145 -57
- package/src/transformers/preview/component/api.ts +2 -1
- package/src/transformers/preview/component/artifacts.ts +10 -1
- package/src/transformers/preview/component/builder.ts +9 -2
- package/src/transformers/preview/component/css.ts +10 -1
- package/src/transformers/preview/component/javascript.ts +55 -20
- package/src/transformers/preview/component/shared-artifacts.ts +146 -0
- package/src/transformers/preview/component.ts +5 -2
- package/src/transformers/preview/pattern/builder.ts +33 -7
- package/src/transformers/preview/pattern/html.ts +71 -27
- package/src/transformers/preview/types.ts +42 -0
- package/src/transformers/utils/handlebars.ts +31 -5
- package/src/types/config.ts +123 -25
- package/src/utils/menu-shell.ts +241 -0
- package/src/utils/stable-stringify.ts +7 -0
- package/templates/default/package.json.tpl +1 -1
- package/handoff.config.js +0 -90
- package/src/app/components/ComponentSearch.tsx +0 -93
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Drizzle ORM schema for registry storage.
|
|
4
|
+
*
|
|
5
|
+
* The registry is database-backed (PostgreSQL, including PG-compatible managed services such as
|
|
6
|
+
* Neon/Vercel). This schema declares the six record groups the registry persists:
|
|
7
|
+
*
|
|
8
|
+
* - `components` / `component_files`
|
|
9
|
+
* - `patterns` / `pattern_files`
|
|
10
|
+
* - `docs_artifacts` (docs read-model artifacts)
|
|
11
|
+
* - `build_metadata` (build/artifact metadata)
|
|
12
|
+
*
|
|
13
|
+
* Schema notes:
|
|
14
|
+
* - Artifact and build-metadata columns mirror the structured artifact model
|
|
15
|
+
* (`ArtifactDescriptor`, `ArtifactBuildMetadata`, `ArtifactReference`) so the database can
|
|
16
|
+
* validate, serve, and debug an artifact without ever parsing HTML.
|
|
17
|
+
* - Metadata-only records are supported: a component/pattern row may exist with no
|
|
18
|
+
* `docs_artifacts` rows and a `build_metadata` row reporting `status: 'missing'`.
|
|
19
|
+
* - Text file records (`component_files` / `pattern_files`) cover checkout/inspection/management
|
|
20
|
+
* only and **exclude declaration files** — a CHECK constraint rejects `kind = 'declaration'`,
|
|
21
|
+
* so declarations have no representation in registry text file records.
|
|
22
|
+
* - `content` and `storage_ref` are both nullable so the model leaves room for future object
|
|
23
|
+
* storage of large/binary assets (a content-reference field) rather than assuming inline content.
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.registrySchema = exports.assetBlobs = exports.assets = exports.assetCollections = exports.tokenArtifacts = exports.tokenSets = exports.buildMetadata = exports.docsArtifacts = exports.pageFiles = exports.pages = exports.patternFiles = exports.patterns = exports.componentFiles = exports.components = void 0;
|
|
27
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
28
|
+
const pg_core_1 = require("drizzle-orm/pg-core");
|
|
29
|
+
/**
|
|
30
|
+
* PostgreSQL `bytea` column. Drizzle pg-core has no built-in binary type, so declare it once here.
|
|
31
|
+
* Reads/writes are Node `Buffer`s. The default asset storage adapter keeps small/ordinary asset
|
|
32
|
+
* bytes inline in this column; larger assets are offloaded to an object-storage `storageRef` instead.
|
|
33
|
+
*/
|
|
34
|
+
const bytea = (0, pg_core_1.customType)({
|
|
35
|
+
dataType() {
|
|
36
|
+
return 'bytea';
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* Components record group. `record` holds the full normalized {@link ComponentListObject} so the
|
|
41
|
+
* registry serves the same record shape as the filesystem store; the promoted columns exist for
|
|
42
|
+
* querying/sorting the catalog.
|
|
43
|
+
*/
|
|
44
|
+
exports.components = (0, pg_core_1.pgTable)('components', {
|
|
45
|
+
/** Stable component id (explicit `id`, else directory basename). Join key across stores. */
|
|
46
|
+
id: (0, pg_core_1.text)('id').primaryKey(),
|
|
47
|
+
/** Logical docs path for the component. */
|
|
48
|
+
path: (0, pg_core_1.text)('path').notNull(),
|
|
49
|
+
title: (0, pg_core_1.text)('title'),
|
|
50
|
+
description: (0, pg_core_1.text)('description'),
|
|
51
|
+
group: (0, pg_core_1.text)('group'),
|
|
52
|
+
type: (0, pg_core_1.text)('type'),
|
|
53
|
+
renderer: (0, pg_core_1.text)('renderer'),
|
|
54
|
+
tags: (0, pg_core_1.jsonb)('tags').$type(),
|
|
55
|
+
categories: (0, pg_core_1.jsonb)('categories').$type(),
|
|
56
|
+
/** Full normalized component record. */
|
|
57
|
+
record: (0, pg_core_1.jsonb)('record').$type().notNull(),
|
|
58
|
+
/** Registry-only review/catalog metadata (management-API allowlist; never a render input). */
|
|
59
|
+
metadata: (0, pg_core_1.jsonb)('metadata').$type(),
|
|
60
|
+
createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
61
|
+
updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
62
|
+
}, (table) => [(0, pg_core_1.index)('components_group_idx').on(table.group)]);
|
|
63
|
+
/**
|
|
64
|
+
* Component source files. Used for checkout/inspection/management only — never to rebuild
|
|
65
|
+
* previews. Declaration files are rejected at the schema level.
|
|
66
|
+
*/
|
|
67
|
+
exports.componentFiles = (0, pg_core_1.pgTable)('component_files', {
|
|
68
|
+
componentId: (0, pg_core_1.text)('component_id')
|
|
69
|
+
.notNull()
|
|
70
|
+
.references(() => exports.components.id, { onDelete: 'cascade' }),
|
|
71
|
+
/** Registry-safe relative path within the entity (e.g. `Badge.tsx`). */
|
|
72
|
+
path: (0, pg_core_1.text)('path').notNull(),
|
|
73
|
+
kind: (0, pg_core_1.text)('kind').$type().notNull(),
|
|
74
|
+
/** Inline content; null when stored externally via `storageRef`. */
|
|
75
|
+
content: (0, pg_core_1.text)('content'),
|
|
76
|
+
/** Reference to externally stored content (future object storage). */
|
|
77
|
+
storageRef: (0, pg_core_1.text)('storage_ref'),
|
|
78
|
+
contentType: (0, pg_core_1.text)('content_type').notNull(),
|
|
79
|
+
createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
80
|
+
updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
81
|
+
}, (table) => [
|
|
82
|
+
(0, pg_core_1.primaryKey)({ columns: [table.componentId, table.path] }),
|
|
83
|
+
(0, pg_core_1.check)('component_files_kind_not_declaration', (0, drizzle_orm_1.sql) `${table.kind} <> 'declaration'`),
|
|
84
|
+
]);
|
|
85
|
+
/**
|
|
86
|
+
* Patterns record group. `record` holds the full normalized {@link PatternListObject};
|
|
87
|
+
* `components` promotes the pattern's component refs for querying.
|
|
88
|
+
*/
|
|
89
|
+
exports.patterns = (0, pg_core_1.pgTable)('patterns', {
|
|
90
|
+
/** Stable pattern id. Join key across stores. */
|
|
91
|
+
id: (0, pg_core_1.text)('id').primaryKey(),
|
|
92
|
+
path: (0, pg_core_1.text)('path').notNull(),
|
|
93
|
+
title: (0, pg_core_1.text)('title'),
|
|
94
|
+
description: (0, pg_core_1.text)('description'),
|
|
95
|
+
group: (0, pg_core_1.text)('group'),
|
|
96
|
+
tags: (0, pg_core_1.jsonb)('tags').$type(),
|
|
97
|
+
/** Pattern component references. */
|
|
98
|
+
components: (0, pg_core_1.jsonb)('components').$type(),
|
|
99
|
+
/** Full normalized pattern record. */
|
|
100
|
+
record: (0, pg_core_1.jsonb)('record').$type().notNull(),
|
|
101
|
+
/** Registry-only review/catalog metadata (management-API allowlist; never a render input). */
|
|
102
|
+
metadata: (0, pg_core_1.jsonb)('metadata').$type(),
|
|
103
|
+
createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
104
|
+
updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
105
|
+
}, (table) => [(0, pg_core_1.index)('patterns_group_idx').on(table.group)]);
|
|
106
|
+
/**
|
|
107
|
+
* Pattern source files. Same checkout/inspection/management role as {@link componentFiles};
|
|
108
|
+
* declaration files are rejected at the schema level.
|
|
109
|
+
*/
|
|
110
|
+
exports.patternFiles = (0, pg_core_1.pgTable)('pattern_files', {
|
|
111
|
+
patternId: (0, pg_core_1.text)('pattern_id')
|
|
112
|
+
.notNull()
|
|
113
|
+
.references(() => exports.patterns.id, { onDelete: 'cascade' }),
|
|
114
|
+
path: (0, pg_core_1.text)('path').notNull(),
|
|
115
|
+
kind: (0, pg_core_1.text)('kind').$type().notNull(),
|
|
116
|
+
content: (0, pg_core_1.text)('content'),
|
|
117
|
+
storageRef: (0, pg_core_1.text)('storage_ref'),
|
|
118
|
+
contentType: (0, pg_core_1.text)('content_type').notNull(),
|
|
119
|
+
createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
120
|
+
updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
121
|
+
}, (table) => [
|
|
122
|
+
(0, pg_core_1.primaryKey)({ columns: [table.patternId, table.path] }),
|
|
123
|
+
(0, pg_core_1.check)('pattern_files_kind_not_declaration', (0, drizzle_orm_1.sql) `${table.kind} <> 'declaration'`),
|
|
124
|
+
]);
|
|
125
|
+
/**
|
|
126
|
+
* Pages record group. `record` holds the full normalized {@link PageListObject} (frontmatter
|
|
127
|
+
* metadata) so the registry serves the same record shape the filesystem store produces; promoted
|
|
128
|
+
* columns exist for catalog querying/sorting. The markdown body travels as a `page_files` row, not in
|
|
129
|
+
* the record — see {@link pageFiles}.
|
|
130
|
+
*/
|
|
131
|
+
exports.pages = (0, pg_core_1.pgTable)('pages', {
|
|
132
|
+
/** Stable page id (slug path, e.g. `guides/setup`). Join key across stores. */
|
|
133
|
+
id: (0, pg_core_1.text)('id').primaryKey(),
|
|
134
|
+
/** Logical route the page is served at (e.g. `/guides/setup`). */
|
|
135
|
+
path: (0, pg_core_1.text)('path').notNull(),
|
|
136
|
+
title: (0, pg_core_1.text)('title'),
|
|
137
|
+
description: (0, pg_core_1.text)('description'),
|
|
138
|
+
group: (0, pg_core_1.text)('group'),
|
|
139
|
+
/** Sort weight within the nav section. */
|
|
140
|
+
weight: (0, pg_core_1.integer)('weight'),
|
|
141
|
+
/** Full normalized page record. */
|
|
142
|
+
record: (0, pg_core_1.jsonb)('record').$type().notNull(),
|
|
143
|
+
/** Registry-only review/catalog metadata (management-API allowlist; never a render input). */
|
|
144
|
+
metadata: (0, pg_core_1.jsonb)('metadata').$type(),
|
|
145
|
+
createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
146
|
+
updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
147
|
+
}, (table) => [(0, pg_core_1.index)('pages_group_idx').on(table.group)]);
|
|
148
|
+
/**
|
|
149
|
+
* Page source files. A page has a single verbatim `.md` (kind `markdown`) stored for byte-exact
|
|
150
|
+
* checkout and for resolving the rendered body at request time. Declaration files are rejected at the
|
|
151
|
+
* schema level (consistent with the other file tables, though pages never carry declarations).
|
|
152
|
+
*/
|
|
153
|
+
exports.pageFiles = (0, pg_core_1.pgTable)('page_files', {
|
|
154
|
+
pageId: (0, pg_core_1.text)('page_id')
|
|
155
|
+
.notNull()
|
|
156
|
+
.references(() => exports.pages.id, { onDelete: 'cascade' }),
|
|
157
|
+
/** Registry-safe relative path within the entity (e.g. `guides/setup.md`). */
|
|
158
|
+
path: (0, pg_core_1.text)('path').notNull(),
|
|
159
|
+
kind: (0, pg_core_1.text)('kind').$type().notNull(),
|
|
160
|
+
content: (0, pg_core_1.text)('content'),
|
|
161
|
+
storageRef: (0, pg_core_1.text)('storage_ref'),
|
|
162
|
+
contentType: (0, pg_core_1.text)('content_type').notNull(),
|
|
163
|
+
createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
164
|
+
updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
165
|
+
}, (table) => [
|
|
166
|
+
(0, pg_core_1.primaryKey)({ columns: [table.pageId, table.path] }),
|
|
167
|
+
(0, pg_core_1.check)('page_files_kind_not_declaration', (0, drizzle_orm_1.sql) `${table.kind} <> 'declaration'`),
|
|
168
|
+
]);
|
|
169
|
+
/**
|
|
170
|
+
* Docs read-model artifacts. Path-keyed so shared/global artifacts (`component/main.css`,
|
|
171
|
+
* `component/main.js`, `component/shared.css`) are upserted by stable logical path. Mirrors the
|
|
172
|
+
* `ArtifactDescriptor` field set.
|
|
173
|
+
*/
|
|
174
|
+
exports.docsArtifacts = (0, pg_core_1.pgTable)('docs_artifacts', {
|
|
175
|
+
/** Logical artifact path (e.g. `component/badge-primary.html`). Stable serving key. */
|
|
176
|
+
path: (0, pg_core_1.text)('path').primaryKey(),
|
|
177
|
+
entityKind: (0, pg_core_1.text)('entity_kind').$type().notNull(),
|
|
178
|
+
entityId: (0, pg_core_1.text)('entity_id'),
|
|
179
|
+
artifactKind: (0, pg_core_1.text)('artifact_kind').$type().notNull(),
|
|
180
|
+
/** Inline content; null when stored externally via `storageRef`. */
|
|
181
|
+
content: (0, pg_core_1.text)('content'),
|
|
182
|
+
/** Reference to externally stored content (future object storage). */
|
|
183
|
+
storageRef: (0, pg_core_1.text)('storage_ref'),
|
|
184
|
+
contentType: (0, pg_core_1.text)('content_type').notNull(),
|
|
185
|
+
ownerKind: (0, pg_core_1.text)('owner_kind').$type(),
|
|
186
|
+
ownerId: (0, pg_core_1.text)('owner_id'),
|
|
187
|
+
/** Structured required/optional references (drives validation/serving/dedup). */
|
|
188
|
+
references: (0, pg_core_1.jsonb)('references').$type(),
|
|
189
|
+
formatVersion: (0, pg_core_1.text)('format_version'),
|
|
190
|
+
buildId: (0, pg_core_1.text)('build_id'),
|
|
191
|
+
hash: (0, pg_core_1.text)('hash'),
|
|
192
|
+
size: (0, pg_core_1.integer)('size'),
|
|
193
|
+
/** Gzipped byte size diagnostic, when measured. */
|
|
194
|
+
gzipSize: (0, pg_core_1.integer)('gzip_size'),
|
|
195
|
+
createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
196
|
+
updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
197
|
+
}, (table) => [
|
|
198
|
+
(0, pg_core_1.index)('docs_artifacts_entity_idx').on(table.entityKind, table.entityId),
|
|
199
|
+
(0, pg_core_1.index)('docs_artifacts_owner_idx').on(table.ownerKind, table.ownerId),
|
|
200
|
+
]);
|
|
201
|
+
/**
|
|
202
|
+
* Build/artifact metadata per entity. Mirrors the `ArtifactBuildMetadata` field set.
|
|
203
|
+
* A successful publish records `status: 'current'` with `builtAt` + `builderVersion` +
|
|
204
|
+
* `artifactHash`; metadata-only records report `status: 'missing'`.
|
|
205
|
+
*/
|
|
206
|
+
exports.buildMetadata = (0, pg_core_1.pgTable)('build_metadata', {
|
|
207
|
+
entityKind: (0, pg_core_1.text)('entity_kind').$type().notNull(),
|
|
208
|
+
entityId: (0, pg_core_1.text)('entity_id').notNull(),
|
|
209
|
+
status: (0, pg_core_1.text)('status').$type().notNull(),
|
|
210
|
+
builtAt: (0, pg_core_1.timestamp)('built_at', { withTimezone: true }),
|
|
211
|
+
builderVersion: (0, pg_core_1.text)('builder_version'),
|
|
212
|
+
artifactHash: (0, pg_core_1.text)('artifact_hash'),
|
|
213
|
+
sourceHash: (0, pg_core_1.text)('source_hash'),
|
|
214
|
+
warnings: (0, pg_core_1.jsonb)('warnings').$type(),
|
|
215
|
+
error: (0, pg_core_1.text)('error'),
|
|
216
|
+
createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
217
|
+
updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
218
|
+
}, (table) => [(0, pg_core_1.primaryKey)({ columns: [table.entityKind, table.entityId] })]);
|
|
219
|
+
/**
|
|
220
|
+
* Token sets record group. One row per logical token set (`foundation/colors`, `component/<id>`).
|
|
221
|
+
* `record` holds the exact extracted token slice as JSONB so no token property is lost and new ones
|
|
222
|
+
* flow through without a migration. Build/publish metadata (status/source_hash/built_at) lives on
|
|
223
|
+
* this row — tokens are self-contained and do not use the shared `build_metadata` table.
|
|
224
|
+
*/
|
|
225
|
+
exports.tokenSets = (0, pg_core_1.pgTable)('token_sets', {
|
|
226
|
+
/** Stable logical set id (`foundation/colors` | `component/button`). Join key across stores. */
|
|
227
|
+
id: (0, pg_core_1.text)('id').primaryKey(),
|
|
228
|
+
/** Set kind (`foundation` | `component`). */
|
|
229
|
+
kind: (0, pg_core_1.text)('kind').$type().notNull(),
|
|
230
|
+
/** Full extracted token slice (`IColorObject[]`/…/`IFileComponentObject`). */
|
|
231
|
+
record: (0, pg_core_1.jsonb)('record').notNull(),
|
|
232
|
+
/** Deterministic content hash over the record + generated artifacts (drives skip-unchanged). */
|
|
233
|
+
sourceHash: (0, pg_core_1.text)('source_hash'),
|
|
234
|
+
/** Build/publish status for the set. */
|
|
235
|
+
status: (0, pg_core_1.text)('status').$type(),
|
|
236
|
+
builtAt: (0, pg_core_1.timestamp)('built_at', { withTimezone: true }),
|
|
237
|
+
builderVersion: (0, pg_core_1.text)('builder_version'),
|
|
238
|
+
/** Registry-only review/catalog metadata (parity with other entities; management-API only). */
|
|
239
|
+
metadata: (0, pg_core_1.jsonb)('metadata').$type(),
|
|
240
|
+
createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
241
|
+
updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
242
|
+
}, (table) => [(0, pg_core_1.index)('token_sets_kind_idx').on(table.kind)]);
|
|
243
|
+
/**
|
|
244
|
+
* Generated token artifacts owned by a token set (CSS/SCSS/Style Dictionary/types/custom transformer
|
|
245
|
+
* output). Served byte-for-byte; the registry never re-runs transformers. Keyed by `(token_set_id,
|
|
246
|
+
* path)` where `path` is the registry-safe output path relative to `getVariablesFilePath()`.
|
|
247
|
+
*/
|
|
248
|
+
exports.tokenArtifacts = (0, pg_core_1.pgTable)('token_artifacts', {
|
|
249
|
+
tokenSetId: (0, pg_core_1.text)('token_set_id')
|
|
250
|
+
.notNull()
|
|
251
|
+
.references(() => exports.tokenSets.id, { onDelete: 'cascade' }),
|
|
252
|
+
/** Registry-safe relative output path (e.g. `css/colors.css`, `sd/button/button.tokens.json`). */
|
|
253
|
+
path: (0, pg_core_1.text)('path').notNull(),
|
|
254
|
+
/** Logical format label (`css`|`scss`|`types`|`styleDictionary`|custom outDir). */
|
|
255
|
+
format: (0, pg_core_1.text)('format').notNull(),
|
|
256
|
+
/** Inline content; null when stored externally via `storageRef`. */
|
|
257
|
+
content: (0, pg_core_1.text)('content'),
|
|
258
|
+
/** Reference to externally stored content (future object storage). */
|
|
259
|
+
storageRef: (0, pg_core_1.text)('storage_ref'),
|
|
260
|
+
contentType: (0, pg_core_1.text)('content_type').notNull(),
|
|
261
|
+
hash: (0, pg_core_1.text)('hash'),
|
|
262
|
+
size: (0, pg_core_1.integer)('size'),
|
|
263
|
+
createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
264
|
+
updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
265
|
+
}, (table) => [(0, pg_core_1.primaryKey)({ columns: [table.tokenSetId, table.path] })]);
|
|
266
|
+
/**
|
|
267
|
+
* Asset collections. Owns a collection (`icons`|`logos`|`fonts`) and its build/publish metadata
|
|
268
|
+
* (mirrors {@link tokenSets}): `sourceHash` drives skip-unchanged, and the set of `assets` rows for a
|
|
269
|
+
* collection is its current manifest. Publish replaces those rows atomically, so readers always see a
|
|
270
|
+
* complete manifest.
|
|
271
|
+
*/
|
|
272
|
+
exports.assetCollections = (0, pg_core_1.pgTable)('asset_collections', {
|
|
273
|
+
/** Stable collection id (`icons`|`logos`|`fonts`). Join key across stores. */
|
|
274
|
+
collection: (0, pg_core_1.text)('collection').primaryKey(),
|
|
275
|
+
/** Deterministic content hash over the collection's `(path, contentHash)` manifest (skip-unchanged). */
|
|
276
|
+
sourceHash: (0, pg_core_1.text)('source_hash'),
|
|
277
|
+
/** Build/publish status for the collection. */
|
|
278
|
+
status: (0, pg_core_1.text)('status').$type(),
|
|
279
|
+
builtAt: (0, pg_core_1.timestamp)('built_at', { withTimezone: true }),
|
|
280
|
+
builderVersion: (0, pg_core_1.text)('builder_version'),
|
|
281
|
+
/** Registry-only review/catalog metadata (parity with other entities; management-API only). */
|
|
282
|
+
metadata: (0, pg_core_1.jsonb)('metadata').$type(),
|
|
283
|
+
createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
284
|
+
updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
285
|
+
});
|
|
286
|
+
/**
|
|
287
|
+
* Logical asset metadata - the collection manifest. One row per asset (icon/logo SVG, sprite,
|
|
288
|
+
* sprite manifest, ZIP archive, font archive), keyed by `(collection, path)`. Binary content is not
|
|
289
|
+
* stored here; `blobHash` references the content-addressed {@link assetBlobs} store, so identical
|
|
290
|
+
* bytes across paths/collections dedupe to one blob.
|
|
291
|
+
*/
|
|
292
|
+
exports.assets = (0, pg_core_1.pgTable)('assets', {
|
|
293
|
+
collection: (0, pg_core_1.text)('collection')
|
|
294
|
+
.notNull()
|
|
295
|
+
.references(() => exports.assetCollections.collection, { onDelete: 'cascade' }),
|
|
296
|
+
/** Registry-safe logical path within the collection (e.g. `assets/icons/add.svg`, `icons.zip`). */
|
|
297
|
+
path: (0, pg_core_1.text)('path').notNull(),
|
|
298
|
+
/** Human-facing asset name. */
|
|
299
|
+
name: (0, pg_core_1.text)('name').notNull(),
|
|
300
|
+
contentType: (0, pg_core_1.text)('content_type').notNull(),
|
|
301
|
+
size: (0, pg_core_1.integer)('size'),
|
|
302
|
+
/** SHA-256 of the asset bytes - the blob identity, and the ETag for content responses. */
|
|
303
|
+
contentHash: (0, pg_core_1.text)('content_hash').notNull(),
|
|
304
|
+
/** Free-form asset metadata carried from extraction (icon index, description, …). */
|
|
305
|
+
metadata: (0, pg_core_1.jsonb)('metadata'),
|
|
306
|
+
/** References {@link assetBlobs.hash}; equals `contentHash`. */
|
|
307
|
+
blobHash: (0, pg_core_1.text)('blob_hash')
|
|
308
|
+
.notNull()
|
|
309
|
+
.references(() => exports.assetBlobs.hash),
|
|
310
|
+
createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
311
|
+
updatedAt: (0, pg_core_1.timestamp)('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
312
|
+
}, (table) => [(0, pg_core_1.primaryKey)({ columns: [table.collection, table.path] })]);
|
|
313
|
+
/**
|
|
314
|
+
* Content-addressed binary blob store, shared across assets/collections (the `hash` is the blob
|
|
315
|
+
* identity, so an unchanged file re-references the same row). Exactly one location is active per row:
|
|
316
|
+
* inline `content` (bytea, default DB adapter) or an external `storageRef` resolved through the
|
|
317
|
+
* recorded `storageProvider`. Both nullable so DB- and object-backed blobs coexist.
|
|
318
|
+
*/
|
|
319
|
+
exports.assetBlobs = (0, pg_core_1.pgTable)('asset_blobs', {
|
|
320
|
+
/** SHA-256 of the blob bytes (hex). */
|
|
321
|
+
hash: (0, pg_core_1.text)('hash').primaryKey(),
|
|
322
|
+
/** Which storage backed this blob when it was written (`database`|`vercel-blob`|custom id). */
|
|
323
|
+
storageProvider: (0, pg_core_1.text)('storage_provider').$type().notNull(),
|
|
324
|
+
/** Inline bytes; null when stored externally via `storageRef`. */
|
|
325
|
+
content: bytea('content'),
|
|
326
|
+
/** External object reference/key; null when stored inline in `content`. */
|
|
327
|
+
storageRef: (0, pg_core_1.text)('storage_ref'),
|
|
328
|
+
contentType: (0, pg_core_1.text)('content_type').notNull(),
|
|
329
|
+
size: (0, pg_core_1.integer)('size').notNull(),
|
|
330
|
+
createdAt: (0, pg_core_1.timestamp)('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
331
|
+
});
|
|
332
|
+
/** All registry tables, for typed Drizzle clients and migration tooling. */
|
|
333
|
+
exports.registrySchema = {
|
|
334
|
+
components: exports.components,
|
|
335
|
+
componentFiles: exports.componentFiles,
|
|
336
|
+
patterns: exports.patterns,
|
|
337
|
+
patternFiles: exports.patternFiles,
|
|
338
|
+
pages: exports.pages,
|
|
339
|
+
pageFiles: exports.pageFiles,
|
|
340
|
+
docsArtifacts: exports.docsArtifacts,
|
|
341
|
+
buildMetadata: exports.buildMetadata,
|
|
342
|
+
tokenSets: exports.tokenSets,
|
|
343
|
+
tokenArtifacts: exports.tokenArtifacts,
|
|
344
|
+
assetCollections: exports.assetCollections,
|
|
345
|
+
assets: exports.assets,
|
|
346
|
+
assetBlobs: exports.assetBlobs,
|
|
347
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const isSafeRelativePath: (value: string) => boolean;
|
|
2
|
+
export declare const normalizeRelativePath: (value: string) => string;
|
|
3
|
+
export declare const isSafePathSegment: (value: string) => boolean;
|
|
4
|
+
export declare const resolvePathWithin: (root: string, value: string) => string | null;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolvePathWithin = exports.isSafePathSegment = exports.normalizeRelativePath = exports.isSafeRelativePath = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const isSafeRelativePath = (value) => {
|
|
9
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
const normalized = (0, exports.normalizeRelativePath)(value);
|
|
13
|
+
if (normalized.startsWith('/') || /^[a-zA-Z]:/.test(normalized)) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
return normalized.split('/').every((segment) => segment !== '' && segment !== '.' && segment !== '..');
|
|
17
|
+
};
|
|
18
|
+
exports.isSafeRelativePath = isSafeRelativePath;
|
|
19
|
+
const normalizeRelativePath = (value) => value.replace(/\\/g, '/');
|
|
20
|
+
exports.normalizeRelativePath = normalizeRelativePath;
|
|
21
|
+
const isSafePathSegment = (value) => typeof value === 'string' && value === value.trim() && (0, exports.isSafeRelativePath)(value) && !(0, exports.normalizeRelativePath)(value).includes('/');
|
|
22
|
+
exports.isSafePathSegment = isSafePathSegment;
|
|
23
|
+
const resolvePathWithin = (root, value) => {
|
|
24
|
+
if (!(0, exports.isSafeRelativePath)(value)) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
const absolutePath = path_1.default.resolve(root, ...(0, exports.normalizeRelativePath)(value).split('/'));
|
|
28
|
+
const relativePath = path_1.default.relative(root, absolutePath);
|
|
29
|
+
return relativePath.startsWith('..') || path_1.default.isAbsolute(relativePath) ? null : absolutePath;
|
|
30
|
+
};
|
|
31
|
+
exports.resolvePathWithin = resolvePathWithin;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Handoff from '../../index';
|
|
2
|
+
import type { TransferArtifact } from '../transfer';
|
|
3
|
+
/** Absolute path of the generated artifact root the build writes to (`<workspace>/public/api`). */
|
|
4
|
+
export declare const getArtifactRoot: (handoff: Handoff) => string;
|
|
5
|
+
export declare const isSharedArtifactPath: (artifactPath: string) => boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the owning component id for a file under `public/api/component`, or `null` when it is a
|
|
8
|
+
* shared artifact or owned by no known component. Exact CSS, JavaScript, JSON, and client bundle
|
|
9
|
+
* filenames map directly. HTML filenames use the longest known component id prefix, which prevents
|
|
10
|
+
* a component such as `button group` from being read as `button`.
|
|
11
|
+
*/
|
|
12
|
+
export declare const resolveComponentArtifactOwner: (fileName: string, componentIds: Set<string>) => string | null;
|
|
13
|
+
/** Read a generated artifact file into a {@link TransferArtifact}, or `null` when it does not exist. */
|
|
14
|
+
export declare const readArtifact: (root: string, artifactPath: string, ownerKind: TransferArtifact["ownerKind"], ownerId: string | null) => TransferArtifact | null;
|
|
15
|
+
/** Add a referenced shared/component artifact to the map when present on disk (deduped by path). */
|
|
16
|
+
export declare const addReferencedArtifact: (root: string, artifactPath: string, byPath: Map<string, TransferArtifact>) => void;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.addReferencedArtifact = exports.readArtifact = exports.resolveComponentArtifactOwner = exports.isSharedArtifactPath = exports.getArtifactRoot = void 0;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const artifacts_1 = require("../../artifacts");
|
|
10
|
+
const SHARED_ARTIFACT_PATHS = new Set([artifacts_1.SHARED_MAIN_CSS_ARTIFACT_PATH, artifacts_1.SHARED_MAIN_JS_ARTIFACT_PATH, artifacts_1.SHARED_STYLES_CSS_ARTIFACT_PATH]);
|
|
11
|
+
const CLIENT_ARTIFACT_SUFFIX = '.client.js';
|
|
12
|
+
const ARTIFACT_KIND_BY_EXT = {
|
|
13
|
+
'.json': 'json',
|
|
14
|
+
'.html': 'html',
|
|
15
|
+
'.css': 'css',
|
|
16
|
+
'.js': 'javascript',
|
|
17
|
+
};
|
|
18
|
+
const CONTENT_TYPE_BY_EXT = {
|
|
19
|
+
'.json': 'application/json',
|
|
20
|
+
'.html': 'text/html; charset=utf-8',
|
|
21
|
+
'.css': 'text/css; charset=utf-8',
|
|
22
|
+
'.js': 'application/javascript; charset=utf-8',
|
|
23
|
+
};
|
|
24
|
+
const artifactKindForPath = (artifactPath) => { var _a; return (_a = ARTIFACT_KIND_BY_EXT[path_1.default.extname(artifactPath).toLowerCase()]) !== null && _a !== void 0 ? _a : 'other'; };
|
|
25
|
+
const contentTypeForPath = (artifactPath) => { var _a; return (_a = CONTENT_TYPE_BY_EXT[path_1.default.extname(artifactPath).toLowerCase()]) !== null && _a !== void 0 ? _a : 'text/plain; charset=utf-8'; };
|
|
26
|
+
/** Absolute path of the generated artifact root the build writes to (`<workspace>/public/api`). */
|
|
27
|
+
const getArtifactRoot = (handoff) => path_1.default.resolve(handoff.workingPath, 'public', 'api');
|
|
28
|
+
exports.getArtifactRoot = getArtifactRoot;
|
|
29
|
+
const isSharedArtifactPath = (artifactPath) => SHARED_ARTIFACT_PATHS.has(artifactPath);
|
|
30
|
+
exports.isSharedArtifactPath = isSharedArtifactPath;
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the owning component id for a file under `public/api/component`, or `null` when it is a
|
|
33
|
+
* shared artifact or owned by no known component. Exact CSS, JavaScript, JSON, and client bundle
|
|
34
|
+
* filenames map directly. HTML filenames use the longest known component id prefix, which prevents
|
|
35
|
+
* a component such as `button group` from being read as `button`.
|
|
36
|
+
*/
|
|
37
|
+
const resolveComponentArtifactOwner = (fileName, componentIds) => {
|
|
38
|
+
if ((0, exports.isSharedArtifactPath)(`component/${fileName}`)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (fileName.endsWith(CLIENT_ARTIFACT_SUFFIX)) {
|
|
42
|
+
const id = fileName.slice(0, -CLIENT_ARTIFACT_SUFFIX.length);
|
|
43
|
+
return componentIds.has(id) ? id : null;
|
|
44
|
+
}
|
|
45
|
+
const ext = path_1.default.extname(fileName).toLowerCase();
|
|
46
|
+
if (ext === '.css' || ext === '.js' || ext === '.json') {
|
|
47
|
+
const id = fileName.slice(0, -ext.length);
|
|
48
|
+
return componentIds.has(id) ? id : null;
|
|
49
|
+
}
|
|
50
|
+
if (ext === '.html') {
|
|
51
|
+
let longest = null;
|
|
52
|
+
for (const id of Array.from(componentIds)) {
|
|
53
|
+
if (fileName.startsWith(`${id}-`) && (!longest || id.length > longest.length)) {
|
|
54
|
+
longest = id;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return longest;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
};
|
|
61
|
+
exports.resolveComponentArtifactOwner = resolveComponentArtifactOwner;
|
|
62
|
+
/** Extract the logical artifact paths an HTML document references through the canonical route. */
|
|
63
|
+
const extractReferencedArtifactPaths = (html) => {
|
|
64
|
+
const pattern = new RegExp(`(?:href|src)=["'][^"']*?${artifacts_1.ARTIFACTS_ROUTE_SEGMENT}/([^"']+)["']`, 'g');
|
|
65
|
+
const paths = new Set();
|
|
66
|
+
let match;
|
|
67
|
+
while ((match = pattern.exec(html)) !== null) {
|
|
68
|
+
const encoded = match[1].split(/[?#]/)[0];
|
|
69
|
+
const segments = encoded.split('/').filter(Boolean);
|
|
70
|
+
try {
|
|
71
|
+
const decoded = segments.map((segment) => decodeURIComponent(segment));
|
|
72
|
+
if (decoded.length > 0) {
|
|
73
|
+
paths.add(decoded.join('/'));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (_a) {
|
|
77
|
+
paths.add(encoded);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return Array.from(paths);
|
|
81
|
+
};
|
|
82
|
+
/** Build a structured reference for a referenced artifact path (only the client bundle is required). */
|
|
83
|
+
const toArtifactReference = (referencedPath) => {
|
|
84
|
+
if (referencedPath.endsWith(CLIENT_ARTIFACT_SUFFIX)) {
|
|
85
|
+
const ownerId = path_1.default.basename(referencedPath).slice(0, -CLIENT_ARTIFACT_SUFFIX.length);
|
|
86
|
+
return { path: referencedPath, kind: 'client', required: true, ownerKind: 'component', ownerId };
|
|
87
|
+
}
|
|
88
|
+
if ((0, exports.isSharedArtifactPath)(referencedPath)) {
|
|
89
|
+
return { path: referencedPath, kind: 'shared', required: false, ownerKind: 'asset', ownerId: null };
|
|
90
|
+
}
|
|
91
|
+
const ext = path_1.default.extname(referencedPath).toLowerCase();
|
|
92
|
+
if (referencedPath.startsWith('component/') && (ext === '.css' || ext === '.js')) {
|
|
93
|
+
const ownerId = path_1.default.basename(referencedPath, ext);
|
|
94
|
+
return { path: referencedPath, kind: ext === '.css' ? 'style' : 'script', required: false, ownerKind: 'component', ownerId };
|
|
95
|
+
}
|
|
96
|
+
return { path: referencedPath, kind: 'other', required: false };
|
|
97
|
+
};
|
|
98
|
+
/** Read a generated artifact file into a {@link TransferArtifact}, or `null` when it does not exist. */
|
|
99
|
+
const readArtifact = (root, artifactPath, ownerKind, ownerId) => {
|
|
100
|
+
const absolutePath = path_1.default.resolve(root, ...artifactPath.split('/'));
|
|
101
|
+
if (!fs_extra_1.default.existsSync(absolutePath) || !fs_extra_1.default.statSync(absolutePath).isFile()) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
const content = fs_extra_1.default.readFileSync(absolutePath, 'utf8');
|
|
105
|
+
const references = artifactPath.endsWith('.html') ? extractReferencedArtifactPaths(content).map(toArtifactReference) : undefined;
|
|
106
|
+
return {
|
|
107
|
+
path: artifactPath,
|
|
108
|
+
artifactKind: artifactKindForPath(artifactPath),
|
|
109
|
+
content,
|
|
110
|
+
contentType: contentTypeForPath(artifactPath),
|
|
111
|
+
ownerKind,
|
|
112
|
+
ownerId,
|
|
113
|
+
references,
|
|
114
|
+
size: Buffer.byteLength(content, 'utf8'),
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
exports.readArtifact = readArtifact;
|
|
118
|
+
/** Add a referenced shared/component artifact to the map when present on disk (deduped by path). */
|
|
119
|
+
const addReferencedArtifact = (root, artifactPath, byPath) => {
|
|
120
|
+
var _a, _b;
|
|
121
|
+
if (byPath.has(artifactPath)) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const reference = toArtifactReference(artifactPath);
|
|
125
|
+
const ownerKind = (_a = reference.ownerKind) !== null && _a !== void 0 ? _a : ((0, exports.isSharedArtifactPath)(artifactPath) ? 'asset' : 'component');
|
|
126
|
+
const ownerId = reference.ownerKind === 'asset' ? null : ((_b = reference.ownerId) !== null && _b !== void 0 ? _b : null);
|
|
127
|
+
const artifact = (0, exports.readArtifact)(root, artifactPath, ownerKind, ownerId);
|
|
128
|
+
if (artifact) {
|
|
129
|
+
byPath.set(artifactPath, artifact);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
exports.addReferencedArtifact = addReferencedArtifact;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connected-workspace asset publish orchestration.
|
|
3
|
+
*
|
|
4
|
+
* `publish assets [collection]` runs a fresh build (`handoff.fetch()`), discovers the collections, and
|
|
5
|
+
* uploads each changed one. A collection is skipped when its deterministic `sourceHash` is unchanged;
|
|
6
|
+
* content transfers blob-by-blob (only hashes the registry lacks, since content-addressed dedup is the
|
|
7
|
+
* per-blob skip-unchanged), and the manifest is finalized atomically only after its blobs exist.
|
|
8
|
+
*/
|
|
9
|
+
import Handoff from '../../index';
|
|
10
|
+
/**
|
|
11
|
+
* Publish all discovered asset collections, or a single collection when `collection` is given. Runs a
|
|
12
|
+
* fresh build, skips collections whose content is unchanged on the registry, uploads only missing
|
|
13
|
+
* blobs, and finalizes each manifest atomically. Reports published/unchanged/uploaded/failed counts;
|
|
14
|
+
* throws at the end if any collection failed.
|
|
15
|
+
*/
|
|
16
|
+
export declare const publishAssets: (handoff: Handoff, collection?: string) => Promise<void>;
|