handoff-app 2.0.0-8 → 2.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 → CHANGELOG.md} +85 -1
- package/{License.md → LICENSE.md} +1 -1
- package/README.md +816 -393
- package/RECIPES.md +975 -0
- package/UPGRADE.md +57 -9
- package/components.json +20 -20
- package/config/docs/foundations/colors/guidelines.md +0 -1
- package/config/docs/foundations/colors.md +0 -1
- package/config/docs/foundations/effects/guidelines.md +0 -1
- package/config/docs/foundations/effects/resources.md +0 -1
- package/config/docs/foundations/effects.md +0 -1
- package/config/docs/foundations/fonts.md +0 -1
- package/config/docs/foundations/grid.md +0 -1
- package/config/docs/foundations/icon.md +0 -1
- package/config/docs/foundations/icons/guidelines.md +0 -1
- package/config/docs/foundations/icons.md +0 -1
- package/config/docs/foundations/images/guidelines.md +0 -1
- package/config/docs/foundations/images/resources.md +0 -1
- package/config/docs/foundations/images.md +0 -1
- package/config/docs/foundations/logo/resources.md +0 -1
- package/config/docs/foundations/logo.md +0 -1
- package/config/docs/foundations/typography/guidelines.md +0 -1
- package/config/docs/foundations/typography/resources.md +0 -1
- package/config/docs/foundations/typography.md +0 -1
- package/config/docs/foundations.md +0 -1
- package/config/docs/guidelines.md +0 -1
- package/config/docs/index.md +0 -1
- package/config/docs/system/tokens/foundations/colors.md +0 -4
- package/config/docs/system/tokens/foundations/effects.md +0 -4
- package/config/docs/system/tokens/foundations/typography.md +0 -2
- package/config/docs/system.md +0 -2
- package/config/templates/page.md +2 -1
- package/config/templates/page.mdx +2 -1
- package/dist/ai/connections.d.ts +66 -0
- package/dist/ai/connections.js +149 -0
- package/dist/ai/define.d.ts +10 -0
- package/dist/ai/define.js +13 -0
- package/dist/ai/types.d.ts +26 -0
- package/dist/ai/types.js +10 -0
- package/dist/app-builder/build.d.ts +14 -7
- package/dist/app-builder/build.js +195 -66
- package/dist/app-builder/client-config.js +3 -2
- package/dist/app-builder/paths.d.ts +0 -12
- package/dist/app-builder/paths.js +3 -20
- package/dist/app-builder/static-export.js +1 -1
- package/dist/app-builder/vercel-output.d.ts +1 -1
- package/dist/app-builder/vercel-output.js +5 -4
- package/dist/cache/build-cache.d.ts +27 -4
- package/dist/cache/build-cache.js +114 -47
- package/dist/cache/build-inputs.d.ts +13 -0
- package/dist/cache/build-inputs.js +19 -0
- package/dist/cache/index.d.ts +2 -1
- package/dist/cache/index.js +5 -1
- package/dist/catalog/normalize.js +3 -0
- package/dist/catalog/previews.js +5 -4
- package/dist/catalog/types.d.ts +8 -0
- package/dist/cli/create.js +1 -2
- package/dist/commands/build/index.d.ts +1 -1
- package/dist/commands/build/index.js +1 -1
- package/dist/commands/utils.d.ts +3 -3
- package/dist/config/defaults.js +7 -4
- package/dist/config/from-env.d.ts +4 -0
- package/dist/config/from-env.js +38 -1
- package/dist/config/helpers.js +2 -2
- package/dist/config/index.d.ts +0 -1
- package/dist/config/index.js +1 -4
- package/dist/config/loader.js +28 -2
- package/dist/config/resolve-env.d.ts +2 -1
- package/dist/config/resolve-env.js +28 -12
- package/dist/config/runtime.js +9 -11
- package/dist/handlebars.d.ts +10 -2
- package/dist/index.d.ts +12 -7
- package/dist/index.js +18 -22
- package/dist/nav/index.d.ts +2 -2
- package/dist/nav/registry.d.ts +3 -3
- package/dist/nav/registry.js +1 -1
- package/dist/nav/workspace.d.ts +3 -3
- package/dist/nav/workspace.js +1 -1
- package/dist/pipeline/figma.d.ts +13 -2
- package/dist/pipeline/figma.js +86 -46
- package/dist/pipeline/styles.js +1 -1
- package/dist/pipeline/validation.d.ts +1 -1
- package/dist/pipeline/validation.js +3 -3
- package/dist/providers.d.ts +10 -0
- package/dist/providers.js +13 -0
- package/dist/registry/asset-storage/define.d.ts +5 -5
- package/dist/registry/asset-storage/define.js +4 -4
- package/dist/registry/asset-storage/resolve.d.ts +9 -19
- package/dist/registry/asset-storage/resolve.js +33 -21
- package/dist/registry/asset-storage/types.d.ts +37 -17
- package/dist/registry/asset-storage/types.js +5 -5
- package/dist/registry/auth/ai-keys.d.ts +32 -0
- package/dist/registry/auth/ai-keys.js +69 -0
- package/dist/registry/auth/crypto.d.ts +17 -0
- package/dist/registry/auth/crypto.js +61 -1
- package/dist/registry/auth/index.d.ts +2 -1
- package/dist/registry/auth/index.js +11 -2
- package/dist/registry/checkout/index.d.ts +2 -1
- package/dist/registry/checkout/index.js +57 -127
- package/dist/registry/client.js +53 -17
- package/dist/registry/db/driver.js +3 -3
- package/dist/registry/db/schema.d.ts +261 -3
- package/dist/registry/db/schema.js +29 -4
- package/dist/registry/email/define.d.ts +10 -0
- package/dist/registry/email/define.js +13 -0
- package/dist/registry/email/providers/smtp.d.ts +10 -0
- package/dist/registry/email/providers/smtp.js +73 -0
- package/dist/registry/email/resolve.d.ts +28 -0
- package/dist/registry/email/resolve.js +74 -0
- package/dist/registry/email/types.d.ts +24 -0
- package/dist/registry/email/types.js +6 -0
- package/dist/registry/path.d.ts +2 -0
- package/dist/registry/path.js +11 -1
- package/dist/registry/publish/package.js +8 -0
- package/dist/registry/transfer.d.ts +4 -0
- package/dist/store/registry.d.ts +3 -3
- package/dist/store/registry.js +4 -4
- package/dist/transformers/plugins/ssr-render.js +40 -15
- package/dist/transformers/preview/component/builder.d.ts +1 -9
- package/dist/transformers/preview/component/builder.js +17 -17
- package/dist/transformers/preview/component/css.d.ts +3 -1
- package/dist/transformers/preview/component/css.js +92 -51
- package/dist/transformers/preview/component/html.d.ts +3 -1
- package/dist/transformers/preview/component/html.js +6 -2
- package/dist/transformers/preview/component/javascript.d.ts +2 -1
- package/dist/transformers/preview/component/javascript.js +10 -4
- package/dist/transformers/preview/pattern/html.js +3 -1
- package/dist/transformers/preview/types.d.ts +13 -0
- package/dist/transformers/utils/build.d.ts +24 -0
- package/dist/transformers/utils/build.js +100 -1
- package/dist/transformers/utils/module.js +2 -1
- package/dist/types/config.d.ts +135 -18
- package/dist/utils/path.d.ts +1 -5
- package/dist/utils/path.js +6 -23
- package/docs/api.md +6 -4
- package/docs/cli.md +275 -54
- package/drizzle/0007_add_ai_keys.sql +11 -0
- package/drizzle/0008_add_source_dir.sql +2 -0
- package/drizzle/meta/0007_snapshot.json +2013 -0
- package/drizzle/meta/0008_snapshot.json +2025 -0
- package/drizzle/meta/_journal.json +14 -0
- package/package.json +19 -8
- package/src/ai/README.md +42 -0
- package/src/ai/connections.ts +189 -0
- package/src/ai/define.ts +15 -0
- package/src/ai/types.ts +30 -0
- package/src/app/components/AiAssistant/AiAssistantPanel.tsx +144 -0
- package/src/app/components/AiAssistant/AiAssistantProvider.tsx +215 -0
- package/src/app/components/AiAssistant/AiConversation.tsx +737 -0
- package/src/app/components/AiAssistant/AiToolResult.tsx +99 -0
- package/src/app/components/AiAssistant/dockState.ts +86 -0
- package/src/app/components/AiAssistant/toolLabel.ts +24 -0
- package/src/app/components/AiAssistant/useAiChat.ts +147 -0
- package/src/app/components/AiAssistant/useAiConnections.ts +86 -0
- package/src/app/components/AiAssistant/usePageContext.ts +63 -0
- package/src/app/components/Auth/AccountLayout.tsx +58 -19
- package/src/app/components/Auth/AuthShell.tsx +27 -33
- package/src/app/components/Auth/RegistryInstallGate.tsx +4 -8
- package/src/app/components/Auth/installStatus.ts +29 -0
- package/src/app/components/Component/PageSliceResolver.tsx +1 -0
- package/src/app/components/Component/Preview.tsx +383 -189
- package/src/app/components/Component/slices/ComponentDisplaySlice.tsx +4 -0
- package/src/app/components/Foundations/ColorGrid.tsx +13 -14
- package/src/app/components/Layout/Header.tsx +21 -15
- package/src/app/components/Layout/Main.tsx +2 -2
- package/src/app/components/Markdown/MarkdownComponents.tsx +30 -32
- package/src/app/components/McpIntegration/McpConfigDialog.tsx +12 -51
- package/src/app/components/Navigation/MobileNav.tsx +2 -2
- package/src/app/components/Navigation/SideNav.tsx +1 -15
- package/src/app/components/context/NavProvider.tsx +7 -3
- package/src/app/components/ui/attachment.tsx +50 -0
- package/src/app/components/ui/bubble.tsx +57 -0
- package/src/app/components/ui/button.tsx +3 -1
- package/src/app/components/ui/confirm-dialog.tsx +87 -0
- package/src/app/components/ui/dialog.tsx +7 -2
- package/src/app/components/ui/marker.tsx +56 -0
- package/src/app/components/ui/sidebar.tsx +3 -1
- package/src/app/components/util/index.ts +3 -12
- package/src/app/css/index.css +64 -0
- package/src/app/lib/ai/auth.ts +33 -0
- package/src/app/lib/ai/context.ts +99 -0
- package/src/app/lib/ai/model.ts +79 -0
- package/src/app/lib/ai/prompt.ts +36 -0
- package/src/app/lib/ai/resolve.ts +97 -0
- package/src/app/lib/ai/tools.ts +120 -0
- package/src/app/lib/api/methods.ts +13 -0
- package/src/app/lib/asset-storage.ts +35 -36
- package/src/app/lib/auth/api.ts +4 -12
- package/src/app/lib/auth/email.ts +96 -23
- package/src/app/lib/docs-api/page-rendering.ts +1 -1
- package/src/app/lib/docs-api/registry.ts +2 -3
- package/src/app/lib/docs-api/runtime-config.ts +47 -21
- package/src/app/lib/mcp/components.ts +523 -0
- package/src/app/lib/mcp/page-url.ts +24 -0
- package/src/app/lib/mcp/pages.ts +84 -0
- package/src/app/lib/mcp/result.ts +33 -0
- package/src/app/lib/mcp/server.ts +39 -318
- package/src/app/lib/mcp/tokens.ts +334 -0
- package/src/app/lib/mcp/tool.ts +19 -0
- package/src/app/lib/registry-api/asset-transfer.ts +119 -11
- package/src/app/lib/registry-api/errors.ts +2 -0
- package/src/app/lib/registry-api/handler.ts +7 -1
- package/src/app/lib/registry-api/transfer.ts +28 -6
- package/src/app/lib/server-module.ts +34 -0
- package/src/app/lib/utils.ts +20 -0
- package/src/app/next.config.mjs +26 -24
- package/src/app/pages/[...slug]/index.tsx +2 -1
- package/src/app/pages/_app.tsx +6 -2
- package/src/app/pages/_document.tsx +6 -0
- package/src/app/pages/account/ai.tsx +183 -0
- package/src/app/pages/account/index.tsx +68 -68
- package/src/app/pages/account/tokens.tsx +37 -7
- package/src/app/pages/account/users.tsx +75 -15
- package/src/app/pages/api/account/ai/keys/[connectionId].ts +60 -0
- package/src/app/pages/api/account/ai/keys/index.ts +20 -0
- package/src/app/pages/api/admin/users/[id]/[action].ts +80 -11
- package/src/app/pages/api/admin/users/index.ts +2 -2
- package/src/app/pages/api/ai/chat.ts +115 -0
- package/src/app/pages/api/ai/connections.ts +23 -0
- package/src/app/pages/api/auth/request-reset.ts +14 -16
- package/src/app/pages/api/docs/nav.json.ts +1 -1
- package/src/app/pages/api/install.ts +3 -3
- package/src/app/pages/api/mcp.ts +6 -0
- package/src/app/pages/api/registry/transfer/assets/blobs/[hash]/complete.ts +11 -0
- package/src/app/pages/api/registry/transfer/assets/blobs/[hash]/upload.ts +12 -0
- package/src/app/pages/api/registry/transfer/assets/blobs/[hash].ts +1 -1
- package/src/app/pages/cli/device.tsx +10 -5
- package/src/app/pages/foundations/colors.tsx +9 -8
- package/src/app/pages/foundations/index.tsx +3 -3
- package/src/app/pages/index.tsx +2 -2
- package/src/app/pages/install.tsx +7 -2
- package/src/app/pages/login.tsx +32 -27
- package/src/app/pages/reset-password.tsx +21 -20
- package/src/app/pages/system/component/[component]/index.tsx +2 -5
- package/src/app/pages/system/index.tsx +11 -11
- package/src/app/pages/system/pattern/[pattern]/index.tsx +2 -2
- package/src/app/pages/system/tokens/components/[component]/index.tsx +0 -4
- package/src/app-builder/README.md +2 -1
- package/src/app-builder/build.ts +218 -73
- package/src/app-builder/client-config.ts +3 -2
- package/src/app-builder/paths.ts +3 -22
- package/src/app-builder/static-export.ts +1 -1
- package/src/app-builder/vercel-output.ts +5 -4
- package/src/cache/README.md +4 -1
- package/src/cache/build-cache.ts +128 -43
- package/src/cache/build-inputs.ts +28 -0
- package/src/cache/index.ts +4 -0
- package/src/catalog/README.md +3 -0
- package/src/catalog/normalize.ts +2 -0
- package/src/catalog/previews.ts +6 -3
- package/src/catalog/types.ts +8 -0
- package/src/cli/create.ts +1 -2
- package/src/commands/build/index.ts +1 -1
- package/src/config/README.md +10 -9
- package/src/config/defaults.ts +7 -4
- package/src/config/from-env.ts +33 -0
- package/src/config/helpers.ts +1 -3
- package/src/config/index.ts +0 -3
- package/src/config/loader.ts +27 -3
- package/src/config/resolve-env.ts +28 -15
- package/src/config/runtime.ts +10 -5
- package/src/handlebars.ts +8 -2
- package/src/index.ts +33 -29
- package/src/nav/index.ts +2 -2
- package/src/nav/registry.ts +3 -3
- package/src/nav/workspace.ts +3 -3
- package/src/pipeline/README.md +1 -1
- package/src/pipeline/figma.ts +98 -49
- package/src/pipeline/styles.ts +1 -1
- package/src/pipeline/validation.ts +3 -3
- package/src/providers.ts +18 -0
- package/src/registry/asset-storage/define.ts +6 -6
- package/src/registry/asset-storage/resolve.ts +38 -37
- package/src/registry/asset-storage/types.ts +39 -17
- package/src/registry/auth/ai-keys.ts +62 -0
- package/src/registry/auth/crypto.ts +63 -1
- package/src/registry/auth/index.ts +11 -1
- package/src/registry/checkout/index.ts +60 -138
- package/src/registry/client.ts +60 -20
- package/src/registry/db/driver.ts +2 -2
- package/src/registry/db/schema.ts +49 -22
- package/src/registry/email/define.ts +15 -0
- package/src/registry/email/providers/smtp.ts +39 -0
- package/src/registry/email/resolve.ts +94 -0
- package/src/registry/email/types.ts +28 -0
- package/src/registry/path.ts +11 -0
- package/src/registry/publish/package.ts +9 -0
- package/src/registry/transfer.ts +4 -0
- package/src/store/registry.ts +7 -7
- package/src/transformers/plugins/ssr-render.ts +53 -16
- package/src/transformers/preview/component/builder.ts +19 -25
- package/src/transformers/preview/component/css.ts +101 -53
- package/src/transformers/preview/component/html.ts +6 -2
- package/src/transformers/preview/component/javascript.ts +14 -4
- package/src/transformers/preview/pattern/html.ts +3 -1
- package/src/transformers/preview/types.ts +14 -0
- package/src/transformers/utils/build.ts +93 -0
- package/src/transformers/utils/module.ts +4 -2
- package/src/types/config.ts +148 -20
- package/src/utils/README.md +1 -1
- package/src/utils/path.ts +6 -29
- package/templates/default/handoff.config.js.tpl +10 -2
- package/templates/default/handoff.config.ts.tpl +10 -2
- package/templates/default/handoff.config.with-examples.js.tpl +10 -2
- package/templates/default/handoff.config.with-examples.ts.tpl +10 -2
- package/templates/default/package.json.tpl +2 -2
- package/.editorconfig +0 -19
- package/.eslintrc.json +0 -4
- package/.prettierignore +0 -0
- package/.prettierrc.json +0 -8
- package/.vscode/settings.json +0 -17
- package/dist/config/validator.d.ts +0 -9
- package/dist/config/validator.js +0 -24
- package/dist/registry/asset-storage/adapters/vercel-blob.d.ts +0 -17
- package/dist/registry/asset-storage/adapters/vercel-blob.js +0 -87
- package/src/app/components/old/Header.tsx +0 -89
- package/src/app/lib/mcp/shape.ts +0 -596
- package/src/app/pages/assets/fonts.tsx +0 -129
- package/src/app/pages/assets/index.tsx +0 -91
- package/src/app/pages/assets/logos.tsx +0 -75
- package/src/config/validator.ts +0 -22
- package/src/registry/asset-storage/adapters/vercel-blob.ts +0 -51
package/src/types/config.ts
CHANGED
|
@@ -115,6 +115,108 @@ export type RuntimeMode = 'workspace' | 'registry';
|
|
|
115
115
|
/** Format used when synthesizing local workspace declarations. */
|
|
116
116
|
export type DeclarationFormat = 'ts' | 'js' | 'cjs';
|
|
117
117
|
|
|
118
|
+
/** How a connection's credential is supplied. Declared, never inferred from a missing key. */
|
|
119
|
+
export type AiCredentialKind = 'service' | 'user' | 'none';
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* An email option: a literal, baked into the build, or an environment reference, read by the deployed
|
|
123
|
+
* app at request time.
|
|
124
|
+
*/
|
|
125
|
+
export type HandoffEmailOption<T> = T | RuntimeEnvReference<T>;
|
|
126
|
+
|
|
127
|
+
interface HandoffEmailBase {
|
|
128
|
+
/** Sender address, such as `Handoff <no-reply@example.com>`. Use a profile for per-environment values. */
|
|
129
|
+
from?: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Send through an SMTP server, such as Amazon SES, SendGrid, Postmark, Mailgun or Microsoft 365. */
|
|
133
|
+
export interface HandoffSmtpEmail extends HandoffEmailBase {
|
|
134
|
+
provider: 'smtp';
|
|
135
|
+
options: {
|
|
136
|
+
host: HandoffEmailOption<string>;
|
|
137
|
+
/** @default 465, or 587 when `secure` is false */
|
|
138
|
+
port?: HandoffEmailOption<number>;
|
|
139
|
+
/**
|
|
140
|
+
* Use TLS from the start of the connection. When false, the connection upgrades with STARTTLS if
|
|
141
|
+
* the server offers it. @default true, or false when `port` is set to a port other than 465
|
|
142
|
+
*/
|
|
143
|
+
secure?: HandoffEmailOption<boolean>;
|
|
144
|
+
user?: HandoffEmailOption<string>;
|
|
145
|
+
/** Environment reference to the SMTP password. */
|
|
146
|
+
password?: RuntimeEnvReference<string>;
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Send through a server-only module that default-exports a `defineEmailProvider()` result. */
|
|
151
|
+
export interface HandoffCustomEmail extends HandoffEmailBase {
|
|
152
|
+
provider: 'custom';
|
|
153
|
+
/** Server-only module path. It must be its own file so the build can trace it into the deployed registry. */
|
|
154
|
+
module: string;
|
|
155
|
+
/**
|
|
156
|
+
* Options passed to the provider factory. Literals are baked. Environment references are resolved
|
|
157
|
+
* at request time. `apiKey` and `password` must be environment references.
|
|
158
|
+
*/
|
|
159
|
+
options?: Record<string, unknown>;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Registry email settings. `provider` selects the shape of `options`. */
|
|
163
|
+
export type HandoffEmailConfig = HandoffSmtpEmail | HandoffCustomEmail;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* One AI connection the deployment declares. Connections are the whole surface: a reader can add a
|
|
167
|
+
* key for a declared connection and nothing else, so the server never calls a URL a reader chose.
|
|
168
|
+
*
|
|
169
|
+
* Every connection speaks the OpenAI-compatible `/chat/completions` API. A provider that fits
|
|
170
|
+
* nothing else names a server-only `module` instead of a `baseUrl`.
|
|
171
|
+
*/
|
|
172
|
+
export interface HandoffAiConnection {
|
|
173
|
+
/** Stable id. A model is addressed as `<id>/<model>`. */
|
|
174
|
+
id: string;
|
|
175
|
+
/** Name shown to a reader in the model picker and on the account page. */
|
|
176
|
+
label: string;
|
|
177
|
+
/** OpenAI-compatible base URL, such as `https://api.openai.com/v1`. Omit only when `module` is set. */
|
|
178
|
+
baseUrl?: string;
|
|
179
|
+
/**
|
|
180
|
+
* Server-only module path default-exporting a `defineAiProvider()` result, for a provider that is
|
|
181
|
+
* not OpenAI-compatible. It must be its own file so the build can trace it into the deployed
|
|
182
|
+
* registry.
|
|
183
|
+
*/
|
|
184
|
+
module?: string;
|
|
185
|
+
/**
|
|
186
|
+
* Environment reference to the deployment's own key. Its presence makes the connection a service
|
|
187
|
+
* key: the deployment pays and every reader can use it. The name is baked; the value is read at
|
|
188
|
+
* request time and never leaves the server.
|
|
189
|
+
*/
|
|
190
|
+
apiKey?: RuntimeEnvReference<string>;
|
|
191
|
+
/**
|
|
192
|
+
* Set to `'user'` when each reader supplies their own key. Without it, a connection that needs a
|
|
193
|
+
* reader's key looks like one that needs none, and the reader gets a raw 401 instead of an
|
|
194
|
+
* instruction.
|
|
195
|
+
*/
|
|
196
|
+
credential?: 'user';
|
|
197
|
+
/** The models this connection offers. A reader cannot use a model that is not listed. */
|
|
198
|
+
models?: string[];
|
|
199
|
+
/**
|
|
200
|
+
* Options passed to a `module` provider factory. Literals are baked. Environment references are
|
|
201
|
+
* resolved at request time, so secrets must be environment references.
|
|
202
|
+
*/
|
|
203
|
+
options?: Record<string, unknown>;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* The AI assistant block. Presence of the block opts the build in, and `enabled: false` turns it
|
|
208
|
+
* off. Like `mcp`, `enabled` is config-only and baked at build time, so a build without it leaves
|
|
209
|
+
* out both the chat route and the header control rather than showing a control that fails.
|
|
210
|
+
*/
|
|
211
|
+
export interface HandoffAiConfig {
|
|
212
|
+
/** @default true when the `ai` block is present */
|
|
213
|
+
enabled?: boolean;
|
|
214
|
+
/** Declared connections. Merged by `id` with any supplied through `HANDOFF_AI_CONNECTIONS`. */
|
|
215
|
+
connections?: HandoffAiConnection[];
|
|
216
|
+
/** The `<connectionId>/<model>` used when a reader has not picked one. */
|
|
217
|
+
defaultModel?: string;
|
|
218
|
+
}
|
|
219
|
+
|
|
118
220
|
/**
|
|
119
221
|
* User-facing `runtime` configuration block. A single optional block that selects the runtime
|
|
120
222
|
* mode and carries mode-specific host/connection settings.
|
|
@@ -135,6 +237,8 @@ export interface HandoffRuntimeConfig {
|
|
|
135
237
|
* @default true
|
|
136
238
|
*/
|
|
137
239
|
mcp?: boolean;
|
|
240
|
+
/** The docs AI assistant. Omit the block to leave it out of the build. See {@link HandoffAiConfig}. */
|
|
241
|
+
ai?: HandoffAiConfig;
|
|
138
242
|
/** Workspace-mode settings. */
|
|
139
243
|
workspace?: {
|
|
140
244
|
entries?: ConfigEntries;
|
|
@@ -142,9 +246,9 @@ export interface HandoffRuntimeConfig {
|
|
|
142
246
|
};
|
|
143
247
|
/** Registry-mode host settings. Env-var values are stored as names, never as secrets. */
|
|
144
248
|
registry?: {
|
|
145
|
-
/** Environment reference to the database URL. @default fromEnv('DATABASE_URL') */
|
|
146
|
-
databaseUrl?: RuntimeEnvReference<string>;
|
|
147
249
|
database?: {
|
|
250
|
+
/** Environment reference to the database URL. @default fromEnv('DATABASE_URL') */
|
|
251
|
+
url?: RuntimeEnvReference<string>;
|
|
148
252
|
/**
|
|
149
253
|
* PostgreSQL is the supported database. `driver` selects the built-in connection driver — how
|
|
150
254
|
* to connect, not which engine — over the same package-owned Postgres schema and migrations.
|
|
@@ -159,20 +263,26 @@ export interface HandoffRuntimeConfig {
|
|
|
159
263
|
*/
|
|
160
264
|
assetStorage?: {
|
|
161
265
|
/**
|
|
162
|
-
* Active storage provider for new uploads. `database` keeps bytes inline in Postgres; use
|
|
163
|
-
*
|
|
266
|
+
* Active storage provider for new uploads. `database` keeps bytes inline in Postgres; use a
|
|
267
|
+
* `custom` module for object storage.
|
|
164
268
|
* @default "database"
|
|
165
269
|
*/
|
|
166
|
-
|
|
167
|
-
/** For `
|
|
270
|
+
provider?: 'database' | 'custom';
|
|
271
|
+
/** For `provider: "custom"` - server-only module path default-exporting a `defineStorageProvider()` result. */
|
|
168
272
|
module?: string;
|
|
169
|
-
/** For `adapter: "vercel-blob"` - environment reference to the Blob read/write token. @default fromEnv('BLOB_READ_WRITE_TOKEN') */
|
|
170
|
-
token?: RuntimeEnvReference<string>;
|
|
171
273
|
/** Max bytes kept inline in the database `bytea` column (larger uploads are rejected). @default 4194304 */
|
|
172
274
|
maxInlineBytes?: number;
|
|
173
|
-
/**
|
|
275
|
+
/**
|
|
276
|
+
* Options passed to the provider factory. Literals are baked. Environment references are resolved
|
|
277
|
+
* at request time, so secrets must be environment references.
|
|
278
|
+
*/
|
|
174
279
|
options?: Record<string, unknown>;
|
|
175
280
|
};
|
|
281
|
+
/**
|
|
282
|
+
* Invitation and password-reset email. Email stays off until `from` is set and the required
|
|
283
|
+
* options of the provider have values. Until then, invitation links are shown to an administrator.
|
|
284
|
+
*/
|
|
285
|
+
email?: HandoffEmailConfig;
|
|
176
286
|
};
|
|
177
287
|
/**
|
|
178
288
|
* Connected-workspace settings pointing at a remote registry. A connected workspace is
|
|
@@ -186,11 +296,19 @@ export interface HandoffRuntimeConfig {
|
|
|
186
296
|
};
|
|
187
297
|
}
|
|
188
298
|
|
|
299
|
+
/** Connections to external services. */
|
|
300
|
+
export interface ConfigIntegrations {
|
|
301
|
+
/** The Figma file that `fetch` reads foundations from. In a terminal, `fetch` asks for an empty value. */
|
|
302
|
+
figma?: {
|
|
303
|
+
/** The Figma file ID. @default fromEnv('HANDOFF_FIGMA_PROJECT_ID', { default: null }) */
|
|
304
|
+
projectId?: EnvValue<string | null>;
|
|
305
|
+
/** A Figma personal access token. Accepts only an environment reference. @default fromEnv('HANDOFF_DEV_ACCESS_TOKEN', { default: null }) */
|
|
306
|
+
accessToken?: EnvSecret<string | null>;
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
189
310
|
export interface Config {
|
|
190
|
-
|
|
191
|
-
devAccessToken?: EnvSecret<string | null>;
|
|
192
|
-
figma_project_id?: EnvValue<string | null>;
|
|
193
|
-
figmaProjectId?: EnvValue<string | null>;
|
|
311
|
+
integrations?: ConfigIntegrations;
|
|
194
312
|
exportsOutputDirectory?: EnvValue<string>;
|
|
195
313
|
sitesOutputDirectory?: EnvValue<string>;
|
|
196
314
|
useVariables?: EnvValue<boolean>;
|
|
@@ -275,6 +393,9 @@ export interface Config {
|
|
|
275
393
|
|
|
276
394
|
/**
|
|
277
395
|
* Optional hook to override the SSR build configuration used in the ssrRenderPlugin
|
|
396
|
+
*
|
|
397
|
+
* Stylesheet loaders are re-applied after this hook, so a `.css`/`.scss`/`.sass` import stays out
|
|
398
|
+
* of the JavaScript graph whatever the hook returns.
|
|
278
399
|
* @param config - The default esbuild configuration
|
|
279
400
|
* @returns Modified esbuild configuration
|
|
280
401
|
* @example
|
|
@@ -289,6 +410,9 @@ export interface Config {
|
|
|
289
410
|
|
|
290
411
|
/**
|
|
291
412
|
* Optional hook to override the client-side build configuration used in the ssrRenderPlugin
|
|
413
|
+
*
|
|
414
|
+
* Stylesheet loaders are re-applied after this hook, so a `.css`/`.scss`/`.sass` import stays out
|
|
415
|
+
* of the JavaScript graph whatever the hook returns.
|
|
292
416
|
* @param config - The default esbuild configuration
|
|
293
417
|
* @returns Modified esbuild configuration
|
|
294
418
|
* @example
|
|
@@ -396,13 +520,14 @@ export interface ClientRuntimeConfig {
|
|
|
396
520
|
/** Values available after config loading. Deferred references retain their names. */
|
|
397
521
|
export type ResolvedConfig = Omit<
|
|
398
522
|
Config,
|
|
399
|
-
|
|
400
|
-
|
|
523
|
+
| 'integrations'
|
|
524
|
+
| 'exportsOutputDirectory'
|
|
525
|
+
| 'sitesOutputDirectory'
|
|
526
|
+
| 'useVariables'
|
|
527
|
+
| 'app'
|
|
528
|
+
| 'runtime'
|
|
401
529
|
> & {
|
|
402
|
-
|
|
403
|
-
devAccessToken?: string | null;
|
|
404
|
-
figma_project_id?: string | null;
|
|
405
|
-
figmaProjectId?: string | null;
|
|
530
|
+
integrations?: { figma?: { projectId?: string | null; accessToken?: string | null } };
|
|
406
531
|
exportsOutputDirectory?: string;
|
|
407
532
|
sitesOutputDirectory?: string;
|
|
408
533
|
useVariables?: boolean;
|
|
@@ -412,7 +537,10 @@ export type ResolvedConfig = Omit<
|
|
|
412
537
|
};
|
|
413
538
|
};
|
|
414
539
|
|
|
415
|
-
export type ClientConfig = Pick<
|
|
540
|
+
export type ClientConfig = Pick<
|
|
541
|
+
ResolvedConfig,
|
|
542
|
+
'app' | 'exportsOutputDirectory' | 'sitesOutputDirectory' | 'assets_zip_links' | 'useVariables'
|
|
543
|
+
> & {
|
|
416
544
|
runtime: ClientRuntimeConfig;
|
|
417
545
|
};
|
|
418
546
|
|
package/src/utils/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Shared utility functions used across the codebase.
|
|
|
8
8
|
|------|---------|
|
|
9
9
|
| `logger.ts` | `Logger` class — timestamped, color-coded console logging |
|
|
10
10
|
| `filter.ts` | `evaluateFilter()`, `filterAndSort()` — generic object filtering with logical operators |
|
|
11
|
-
| `path.ts` | `generateFilesystemSafeId()` — creates safe directory names from paths |
|
|
11
|
+
| `path.ts` | `generateFilesystemSafeId()` — creates short, safe directory names (base name + path hash) from paths |
|
|
12
12
|
| `fs.ts` | `findFilesByExtension()` — recursive file search by extension |
|
|
13
13
|
| `markdown.ts` | `parseMarkdown()` — frontmatter parse without gray-matter's unbounded module cache |
|
|
14
14
|
| `index.ts` | `filterOutNull()` type guard |
|
package/src/utils/path.ts
CHANGED
|
@@ -1,35 +1,12 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
1
2
|
import path from 'path';
|
|
2
3
|
|
|
3
|
-
/**
|
|
4
|
-
* Generates a filesystem-safe directory name from an absolute path
|
|
5
|
-
* @param workingPath - The absolute working path to transform
|
|
6
|
-
* @returns A filesystem-safe string suitable for use as a directory name
|
|
7
|
-
*/
|
|
4
|
+
/** `<base name>-<path hash>`; the hash keeps directories with the same base name apart. */
|
|
8
5
|
export function generateFilesystemSafeId(workingPath: string): string {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
safeId = safeId.replace(/\//g, '-');
|
|
14
|
-
|
|
15
|
-
// Remove or replace invalid filesystem characters
|
|
16
|
-
safeId = safeId.replace(/[<>:"|?*\x00]/g, '-');
|
|
17
|
-
|
|
18
|
-
// Remove leading/trailing dashes and spaces
|
|
19
|
-
safeId = safeId.replace(/^[\s-]+|[\s-]+$/g, '');
|
|
20
|
-
|
|
21
|
-
// Handle Windows reserved names (case-insensitive)
|
|
22
|
-
const reservedNames = /^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\.|$)/i;
|
|
23
|
-
if (reservedNames.test(safeId)) {
|
|
24
|
-
safeId = `project-${safeId}`;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Ensure we have at least one character
|
|
28
|
-
if (!safeId) {
|
|
29
|
-
safeId = 'default-project';
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return safeId;
|
|
6
|
+
const baseName = path.basename(path.resolve(workingPath));
|
|
7
|
+
const name = baseName.replace(/[^A-Za-z0-9._-]/g, '-').replace(/^[.-]+|[.-]+$/g, '') || 'project';
|
|
8
|
+
const hash = createHash('sha256').update(normalizePathForCompare(workingPath)).digest('hex').slice(0, 8);
|
|
9
|
+
return `${name}-${hash}`;
|
|
33
10
|
}
|
|
34
11
|
|
|
35
12
|
/**
|
|
@@ -46,6 +46,15 @@ const config = {
|
|
|
46
46
|
// subdirectories are each an item.
|
|
47
47
|
// catalog: { include: ["components", "patterns"] },
|
|
48
48
|
|
|
49
|
+
// Figma: `fetch` reads the file ID and token from these variables. Defaults shown. If a value is
|
|
50
|
+
// empty, `fetch` asks for it. The token accepts only an environment reference.
|
|
51
|
+
// integrations: {
|
|
52
|
+
// figma: {
|
|
53
|
+
// projectId: fromEnv("HANDOFF_FIGMA_PROJECT_ID", { default: null }),
|
|
54
|
+
// accessToken: fromEnv("HANDOFF_DEV_ACCESS_TOKEN", { default: null }),
|
|
55
|
+
// },
|
|
56
|
+
// },
|
|
57
|
+
|
|
49
58
|
// `mode` selects the runtime: "workspace" (no database) or "registry" (Postgres). The registry
|
|
50
59
|
// block is read only by `build --target registry` and `db:migrate`, and secrets are referenced by
|
|
51
60
|
// env var name. A named profile (`handoff.config.registry.*`, `--profile registry`) is a good home
|
|
@@ -54,8 +63,7 @@ const config = {
|
|
|
54
63
|
mode: "workspace",
|
|
55
64
|
// mcp: false,
|
|
56
65
|
// registry: {
|
|
57
|
-
//
|
|
58
|
-
// database: { driver: "pg" }, // 'pg' | 'neon'
|
|
66
|
+
// database: { url: fromEnv("DATABASE_URL"), driver: "pg" }, // driver: 'pg' | 'neon'
|
|
59
67
|
// },
|
|
60
68
|
},
|
|
61
69
|
|
|
@@ -44,6 +44,15 @@ export default defineConfig({
|
|
|
44
44
|
// subdirectories are each an item.
|
|
45
45
|
// catalog: { include: ["components", "patterns"] },
|
|
46
46
|
|
|
47
|
+
// Figma: `fetch` reads the file ID and token from these variables. Defaults shown. If a value is
|
|
48
|
+
// empty, `fetch` asks for it. The token accepts only an environment reference.
|
|
49
|
+
// integrations: {
|
|
50
|
+
// figma: {
|
|
51
|
+
// projectId: fromEnv("HANDOFF_FIGMA_PROJECT_ID", { default: null }),
|
|
52
|
+
// accessToken: fromEnv("HANDOFF_DEV_ACCESS_TOKEN", { default: null }),
|
|
53
|
+
// },
|
|
54
|
+
// },
|
|
55
|
+
|
|
47
56
|
// `mode` selects the runtime: "workspace" (no database) or "registry" (Postgres). The registry
|
|
48
57
|
// block is read only by `build --target registry` and `db:migrate`, and secrets are referenced by
|
|
49
58
|
// env var name. A named profile (`handoff.config.registry.*`, `--profile registry`) is a good home
|
|
@@ -52,8 +61,7 @@ export default defineConfig({
|
|
|
52
61
|
mode: "workspace",
|
|
53
62
|
// mcp: false,
|
|
54
63
|
// registry: {
|
|
55
|
-
//
|
|
56
|
-
// database: { driver: "pg" }, // 'pg' | 'neon'
|
|
64
|
+
// database: { url: fromEnv("DATABASE_URL"), driver: "pg" }, // driver: 'pg' | 'neon'
|
|
57
65
|
// },
|
|
58
66
|
},
|
|
59
67
|
|
|
@@ -48,6 +48,15 @@ const config = {
|
|
|
48
48
|
include: ["components/button"],
|
|
49
49
|
},
|
|
50
50
|
|
|
51
|
+
// Figma: `fetch` reads the file ID and token from these variables. Defaults shown. If a value is
|
|
52
|
+
// empty, `fetch` asks for it. The token accepts only an environment reference.
|
|
53
|
+
// integrations: {
|
|
54
|
+
// figma: {
|
|
55
|
+
// projectId: fromEnv("HANDOFF_FIGMA_PROJECT_ID", { default: null }),
|
|
56
|
+
// accessToken: fromEnv("HANDOFF_DEV_ACCESS_TOKEN", { default: null }),
|
|
57
|
+
// },
|
|
58
|
+
// },
|
|
59
|
+
|
|
51
60
|
// `mode` selects the runtime: "workspace" (no database) or "registry" (Postgres). The registry
|
|
52
61
|
// block is read only by `build --target registry` and `db:migrate`, and secrets are referenced by
|
|
53
62
|
// env var name. A named profile (`handoff.config.registry.*`, `--profile registry`) is a good home
|
|
@@ -56,8 +65,7 @@ const config = {
|
|
|
56
65
|
mode: "workspace",
|
|
57
66
|
// mcp: false,
|
|
58
67
|
// registry: {
|
|
59
|
-
//
|
|
60
|
-
// database: { driver: "pg" }, // 'pg' | 'neon'
|
|
68
|
+
// database: { url: fromEnv("DATABASE_URL"), driver: "pg" }, // driver: 'pg' | 'neon'
|
|
61
69
|
// },
|
|
62
70
|
},
|
|
63
71
|
|
|
@@ -46,6 +46,15 @@ export default defineConfig({
|
|
|
46
46
|
include: ["components/button"],
|
|
47
47
|
},
|
|
48
48
|
|
|
49
|
+
// Figma: `fetch` reads the file ID and token from these variables. Defaults shown. If a value is
|
|
50
|
+
// empty, `fetch` asks for it. The token accepts only an environment reference.
|
|
51
|
+
// integrations: {
|
|
52
|
+
// figma: {
|
|
53
|
+
// projectId: fromEnv("HANDOFF_FIGMA_PROJECT_ID", { default: null }),
|
|
54
|
+
// accessToken: fromEnv("HANDOFF_DEV_ACCESS_TOKEN", { default: null }),
|
|
55
|
+
// },
|
|
56
|
+
// },
|
|
57
|
+
|
|
49
58
|
// `mode` selects the runtime: "workspace" (no database) or "registry" (Postgres). The registry
|
|
50
59
|
// block is read only by `build --target registry` and `db:migrate`, and secrets are referenced by
|
|
51
60
|
// env var name. A named profile (`handoff.config.registry.*`, `--profile registry`) is a good home
|
|
@@ -54,8 +63,7 @@ export default defineConfig({
|
|
|
54
63
|
mode: "workspace",
|
|
55
64
|
// mcp: false,
|
|
56
65
|
// registry: {
|
|
57
|
-
//
|
|
58
|
-
// database: { driver: "pg" }, // 'pg' | 'neon'
|
|
66
|
+
// database: { url: fromEnv("DATABASE_URL"), driver: "pg" }, // driver: 'pg' | 'neon'
|
|
59
67
|
// },
|
|
60
68
|
},
|
|
61
69
|
|
package/.editorconfig
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# EditorConfig is awesome: https://EditorConfig.org
|
|
2
|
-
|
|
3
|
-
# top-most EditorConfig file
|
|
4
|
-
root = true
|
|
5
|
-
|
|
6
|
-
[*.{css,scss,sass}]
|
|
7
|
-
charset = utf-8
|
|
8
|
-
indent_style = tab
|
|
9
|
-
indent_size = unset
|
|
10
|
-
end_of_line = lf
|
|
11
|
-
trim_trailing_whitespace = true
|
|
12
|
-
insert_final_newline = true
|
|
13
|
-
|
|
14
|
-
[*.{js,ts,jsx,tsx}]
|
|
15
|
-
charset = utf-8
|
|
16
|
-
indent_style = space
|
|
17
|
-
end_of_line = lf
|
|
18
|
-
trim_trailing_whitespace = true
|
|
19
|
-
insert_final_newline = true
|
package/.eslintrc.json
DELETED
package/.prettierignore
DELETED
|
File without changes
|
package/.prettierrc.json
DELETED
package/.vscode/settings.json
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
3
|
-
"[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
|
|
4
|
-
"editor.formatOnSave": true,
|
|
5
|
-
"editor.codeActionsOnSave": {
|
|
6
|
-
"source.organizeImports": "explicit"
|
|
7
|
-
},
|
|
8
|
-
"[xml]": {
|
|
9
|
-
"editor.defaultFormatter": "redhat.vscode-xml"
|
|
10
|
-
},
|
|
11
|
-
"[typescriptreact]": {
|
|
12
|
-
"editor.defaultFormatter": "vscode.typescript-language-features"
|
|
13
|
-
},
|
|
14
|
-
"[markdown]": {
|
|
15
|
-
"editor.defaultFormatter": "unifiedjs.vscode-remark"
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { ResolvedConfig } from '../types/config';
|
|
2
|
-
/**
|
|
3
|
-
* Validates that the configuration has the required Figma credentials.
|
|
4
|
-
*
|
|
5
|
-
* @param config - The config to validate.
|
|
6
|
-
* @returns The validated config (same reference).
|
|
7
|
-
* @throws {Error} If required Figma credentials are missing.
|
|
8
|
-
*/
|
|
9
|
-
export declare const validateConfig: (config: ResolvedConfig) => ResolvedConfig;
|
package/dist/config/validator.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validateConfig = void 0;
|
|
4
|
-
const logger_1 = require("../utils/logger");
|
|
5
|
-
/**
|
|
6
|
-
* Validates that the configuration has the required Figma credentials.
|
|
7
|
-
*
|
|
8
|
-
* @param config - The config to validate.
|
|
9
|
-
* @returns The validated config (same reference).
|
|
10
|
-
* @throws {Error} If required Figma credentials are missing.
|
|
11
|
-
*/
|
|
12
|
-
const validateConfig = (config) => {
|
|
13
|
-
// TODO: Check to see if the exported folder exists before we run start
|
|
14
|
-
if (!config.figma_project_id) {
|
|
15
|
-
logger_1.Logger.error('Figma Project ID missing. Please set HANDOFF_FIGMA_PROJECT_ID or run "handoff-app fetch".');
|
|
16
|
-
throw new Error('Cannot initialize configuration');
|
|
17
|
-
}
|
|
18
|
-
if (!config.dev_access_token) {
|
|
19
|
-
logger_1.Logger.error('Figma Access Token missing. Please set HANDOFF_DEV_ACCESS_TOKEN or run "handoff-app fetch".');
|
|
20
|
-
throw new Error('Cannot initialize configuration');
|
|
21
|
-
}
|
|
22
|
-
return config;
|
|
23
|
-
};
|
|
24
|
-
exports.validateConfig = validateConfig;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pre-packaged Vercel Blob asset storage adapter.
|
|
3
|
-
*
|
|
4
|
-
* Ships with Handoff and is selected via `runtime.registry.assetStorage.adapter: "vercel-blob"`. The
|
|
5
|
-
* read/write token is read from `process.env[tokenEnv]` at request time (never persisted in config).
|
|
6
|
-
* Blobs are stored public and content-addressed by hash, so reads resolve to a direct provider URL
|
|
7
|
-
* (a `redirect` result), keeping large payloads out of the serverless function body/response.
|
|
8
|
-
*
|
|
9
|
-
* The `@vercel/blob` SDK is loaded lazily so it is only pulled into memory (and traced into the
|
|
10
|
-
* registry bundle) when this adapter is actually used.
|
|
11
|
-
*/
|
|
12
|
-
import type { AssetStorage } from '../types';
|
|
13
|
-
/** Build a Vercel Blob storage adapter bound to a token env-var name + non-secret options. */
|
|
14
|
-
export declare const createVercelBlobStorage: (params: {
|
|
15
|
-
tokenEnv: string;
|
|
16
|
-
options: Record<string, unknown>;
|
|
17
|
-
}) => AssetStorage;
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Pre-packaged Vercel Blob asset storage adapter.
|
|
4
|
-
*
|
|
5
|
-
* Ships with Handoff and is selected via `runtime.registry.assetStorage.adapter: "vercel-blob"`. The
|
|
6
|
-
* read/write token is read from `process.env[tokenEnv]` at request time (never persisted in config).
|
|
7
|
-
* Blobs are stored public and content-addressed by hash, so reads resolve to a direct provider URL
|
|
8
|
-
* (a `redirect` result), keeping large payloads out of the serverless function body/response.
|
|
9
|
-
*
|
|
10
|
-
* The `@vercel/blob` SDK is loaded lazily so it is only pulled into memory (and traced into the
|
|
11
|
-
* registry bundle) when this adapter is actually used.
|
|
12
|
-
*/
|
|
13
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
-
if (k2 === undefined) k2 = k;
|
|
15
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
-
}
|
|
19
|
-
Object.defineProperty(o, k2, desc);
|
|
20
|
-
}) : (function(o, m, k, k2) {
|
|
21
|
-
if (k2 === undefined) k2 = k;
|
|
22
|
-
o[k2] = m[k];
|
|
23
|
-
}));
|
|
24
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
-
}) : function(o, v) {
|
|
27
|
-
o["default"] = v;
|
|
28
|
-
});
|
|
29
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
30
|
-
if (mod && mod.__esModule) return mod;
|
|
31
|
-
var result = {};
|
|
32
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
33
|
-
__setModuleDefault(result, mod);
|
|
34
|
-
return result;
|
|
35
|
-
};
|
|
36
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
37
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
38
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
40
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
41
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
42
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
43
|
-
});
|
|
44
|
-
};
|
|
45
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
-
exports.createVercelBlobStorage = void 0;
|
|
47
|
-
/** Build a Vercel Blob storage adapter bound to a token env-var name + non-secret options. */
|
|
48
|
-
const createVercelBlobStorage = (params) => {
|
|
49
|
-
const prefix = typeof params.options.prefix === 'string' && params.options.prefix.trim() ? params.options.prefix.trim() : 'handoff/assets';
|
|
50
|
-
const resolveToken = () => {
|
|
51
|
-
var _a;
|
|
52
|
-
const token = (_a = process.env[params.tokenEnv]) === null || _a === void 0 ? void 0 : _a.trim();
|
|
53
|
-
if (!token) {
|
|
54
|
-
throw new Error(`Vercel Blob storage is configured but the token env var "${params.tokenEnv}" is not set. ` +
|
|
55
|
-
'Set it to a Blob read/write token, or change runtime.registry.assetStorage.token.');
|
|
56
|
-
}
|
|
57
|
-
return token;
|
|
58
|
-
};
|
|
59
|
-
return {
|
|
60
|
-
put(_a) {
|
|
61
|
-
return __awaiter(this, arguments, void 0, function* ({ hash, bytes, contentType }) {
|
|
62
|
-
const { put } = yield Promise.resolve().then(() => __importStar(require('@vercel/blob')));
|
|
63
|
-
// Content-addressed pathname + no random suffix so the same bytes map to a stable, dedupable key.
|
|
64
|
-
const result = yield put(`${prefix}/${hash}`, bytes, {
|
|
65
|
-
access: 'public',
|
|
66
|
-
token: resolveToken(),
|
|
67
|
-
contentType,
|
|
68
|
-
addRandomSuffix: false,
|
|
69
|
-
});
|
|
70
|
-
return { storageRef: result.url };
|
|
71
|
-
});
|
|
72
|
-
},
|
|
73
|
-
get(storageRef) {
|
|
74
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
75
|
-
// Public blob URLs are directly fetchable; redirect the client to avoid proxying bytes.
|
|
76
|
-
return { kind: 'redirect', url: storageRef };
|
|
77
|
-
});
|
|
78
|
-
},
|
|
79
|
-
delete(storageRef) {
|
|
80
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
-
const { del } = yield Promise.resolve().then(() => __importStar(require('@vercel/blob')));
|
|
82
|
-
yield del(storageRef, { token: resolveToken() });
|
|
83
|
-
});
|
|
84
|
-
},
|
|
85
|
-
};
|
|
86
|
-
};
|
|
87
|
-
exports.createVercelBlobStorage = createVercelBlobStorage;
|