handoff-app 2.0.0-9 → 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 +813 -406
- 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/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 +26 -2
- package/dist/config/resolve-env.d.ts +2 -1
- package/dist/config/resolve-env.js +28 -12
- package/dist/config/runtime.js +1 -1
- 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/preview/component/builder.d.ts +1 -9
- package/dist/transformers/preview/component/builder.js +17 -17
- package/dist/transformers/preview/component/css.d.ts +2 -1
- package/dist/transformers/preview/component/css.js +8 -5
- 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/utils/build.d.ts +5 -0
- package/dist/transformers/utils/build.js +21 -4
- package/dist/types/config.d.ts +129 -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/Preview.tsx +5 -2
- 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/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 +25 -3
- package/src/config/resolve-env.ts +28 -15
- package/src/config/runtime.ts +1 -1
- 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/preview/component/builder.ts +19 -25
- package/src/transformers/preview/component/css.ts +9 -4
- package/src/transformers/preview/component/html.ts +6 -2
- package/src/transformers/preview/component/javascript.ts +14 -4
- package/src/transformers/utils/build.ts +16 -3
- package/src/types/config.ts +142 -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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import react from '@vitejs/plugin-react';
|
|
2
2
|
import { Types as CoreTypes } from 'handoff-core';
|
|
3
3
|
import { InlineConfig, PluginOption, build as viteBuild } from 'vite';
|
|
4
|
+
import { BuildInputs, withBuildInputs } from '../../../cache/build-inputs';
|
|
4
5
|
import type { RendererKind, SourceFormat } from '../../../catalog/renderers';
|
|
5
6
|
import Handoff from '../../../index';
|
|
6
7
|
import { Logger } from '../../../utils/logger';
|
|
@@ -35,6 +36,7 @@ const RENDERER_PLUGINS: Record<RendererKind, PreviewPlugins> = {
|
|
|
35
36
|
* @param data - The result of transforming component tokens.
|
|
36
37
|
* @param handoff - The Handoff configuration object.
|
|
37
38
|
* @param components - Optional file components object.
|
|
39
|
+
* @param inputs - Collects the files that the build reads, for the build cache.
|
|
38
40
|
* @returns A promise that resolves to the transformed component tokens result.
|
|
39
41
|
* @throws Will throw an error if the Vite build process fails.
|
|
40
42
|
*
|
|
@@ -46,7 +48,8 @@ const RENDERER_PLUGINS: Record<RendererKind, PreviewPlugins> = {
|
|
|
46
48
|
export const buildPreviews = async (
|
|
47
49
|
data: TransformComponentTokensResult,
|
|
48
50
|
handoff: Handoff,
|
|
49
|
-
components?: CoreTypes.IDocumentationObject['components']
|
|
51
|
+
components?: CoreTypes.IDocumentationObject['components'],
|
|
52
|
+
inputs?: BuildInputs
|
|
50
53
|
): Promise<TransformComponentTokensResult> => {
|
|
51
54
|
if (!data.entries?.template) return data;
|
|
52
55
|
|
|
@@ -87,8 +90,9 @@ export const buildPreviews = async (
|
|
|
87
90
|
viteConfig = handoff.config.hooks.htmlBuildConfig(viteConfig);
|
|
88
91
|
}
|
|
89
92
|
|
|
90
|
-
await viteBuild(viteConfig);
|
|
93
|
+
await viteBuild(withBuildInputs(viteConfig, inputs));
|
|
91
94
|
} catch (error) {
|
|
95
|
+
if (inputs) inputs.failed = true;
|
|
92
96
|
Logger.error(`Error building component previews: ${data.entries.template}`, error);
|
|
93
97
|
} finally {
|
|
94
98
|
// Restore the original NODE_ENV value after vite build completes
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { InlineConfig, build as viteBuild } from 'vite';
|
|
4
|
+
import { BuildInputs, withBuildInputs } from '../../../cache/build-inputs';
|
|
4
5
|
import Handoff from '../../../index';
|
|
5
6
|
import { formatDurationMs } from '../../../utils/duration';
|
|
6
7
|
import { Logger } from '../../../utils/logger';
|
|
@@ -17,6 +18,7 @@ export const MAIN_COMPONENT_JS_FILE = 'main.js';
|
|
|
17
18
|
* @param options.entry - The entry file path for the bundle
|
|
18
19
|
* @param options.outputPath - The directory where the bundle will be output
|
|
19
20
|
* @param options.outputFilename - The name of the output file
|
|
21
|
+
* @param inputs - Collects the files that the build reads, for the build cache
|
|
20
22
|
*/
|
|
21
23
|
const buildJsBundle = async (
|
|
22
24
|
{
|
|
@@ -25,7 +27,8 @@ const buildJsBundle = async (
|
|
|
25
27
|
outputFilename,
|
|
26
28
|
format = 'cjs',
|
|
27
29
|
}: { entry: string; outputPath: string; outputFilename: string; format?: 'cjs' | 'iife' },
|
|
28
|
-
handoff: Handoff
|
|
30
|
+
handoff: Handoff,
|
|
31
|
+
inputs?: BuildInputs
|
|
29
32
|
) => {
|
|
30
33
|
const absEntryPath = path.resolve(entry);
|
|
31
34
|
|
|
@@ -62,7 +65,7 @@ const buildJsBundle = async (
|
|
|
62
65
|
viteConfig = handoff.config.hooks.jsBuildConfig(viteConfig);
|
|
63
66
|
}
|
|
64
67
|
|
|
65
|
-
await viteBuild(viteConfig);
|
|
68
|
+
await viteBuild(withBuildInputs(viteConfig, inputs));
|
|
66
69
|
} finally {
|
|
67
70
|
// Restore the original NODE_ENV value after vite build completes
|
|
68
71
|
// This prevents interference with Next.js app building/running processes
|
|
@@ -84,7 +87,11 @@ const buildJsBundle = async (
|
|
|
84
87
|
* @param handoff - The Handoff configuration object
|
|
85
88
|
* @returns The updated component transformation result with JavaScript data
|
|
86
89
|
*/
|
|
87
|
-
export const buildComponentJs = async (
|
|
90
|
+
export const buildComponentJs = async (
|
|
91
|
+
data: TransformComponentTokensResult,
|
|
92
|
+
handoff: Handoff,
|
|
93
|
+
inputs?: BuildInputs
|
|
94
|
+
): Promise<TransformComponentTokensResult> => {
|
|
88
95
|
const id = data.id;
|
|
89
96
|
const outputPath = getComponentOutputPath(handoff);
|
|
90
97
|
const builtJsPath = path.resolve(outputPath, `${id}.js`);
|
|
@@ -111,9 +118,11 @@ export const buildComponentJs = async (data: TransformComponentTokensResult, han
|
|
|
111
118
|
outputPath,
|
|
112
119
|
outputFilename: `${id}.js`,
|
|
113
120
|
},
|
|
114
|
-
handoff
|
|
121
|
+
handoff,
|
|
122
|
+
inputs
|
|
115
123
|
);
|
|
116
124
|
} catch (e) {
|
|
125
|
+
if (inputs) inputs.failed = true;
|
|
117
126
|
Logger.error(`Failed to bundle JS for component "${id}" (${id}.js):`, e);
|
|
118
127
|
return data;
|
|
119
128
|
}
|
|
@@ -126,6 +135,7 @@ export const buildComponentJs = async (data: TransformComponentTokensResult, han
|
|
|
126
135
|
delete data['jsCompiled'];
|
|
127
136
|
}
|
|
128
137
|
} catch (e) {
|
|
138
|
+
if (inputs) inputs.failed = true;
|
|
129
139
|
Logger.error(`JS build failed for component "${id}":`, e);
|
|
130
140
|
}
|
|
131
141
|
|
|
@@ -88,6 +88,20 @@ function orderStyleImports(metafile: esbuild.Metafile, entryPath: string): strin
|
|
|
88
88
|
* declared entry.
|
|
89
89
|
*/
|
|
90
90
|
export async function collectStyleImports(entryPath: string, handoff: any): Promise<string[]> {
|
|
91
|
+
const metafile = await buildModuleGraph(entryPath, handoff);
|
|
92
|
+
return metafile ? orderStyleImports(metafile, entryPath) : [];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Every file in the module graph of an entry, stylesheets included, or `null` when the graph does
|
|
97
|
+
* not build.
|
|
98
|
+
*/
|
|
99
|
+
export async function collectModuleInputs(entryPath: string, handoff: any): Promise<string[] | null> {
|
|
100
|
+
const metafile = await buildModuleGraph(entryPath, handoff);
|
|
101
|
+
return metafile ? Object.keys(metafile.inputs).map((input) => path.resolve(input)) : null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function buildModuleGraph(entryPath: string, handoff: any): Promise<esbuild.Metafile | null> {
|
|
91
105
|
const baseConfig: esbuild.BuildOptions = {
|
|
92
106
|
...DEFAULT_SSR_BUILD_CONFIG,
|
|
93
107
|
entryPoints: [entryPath],
|
|
@@ -99,10 +113,9 @@ export async function collectStyleImports(entryPath: string, handoff: any): Prom
|
|
|
99
113
|
// The `empty` loader keeps stylesheets out of the JavaScript, and the metafile still records
|
|
100
114
|
// them as inputs, so the graph carries the order.
|
|
101
115
|
const result = await esbuild.build({ ...withStyleLoaders(hookedConfig), metafile: true });
|
|
102
|
-
|
|
103
|
-
return result.metafile ? orderStyleImports(result.metafile, entryPath) : [];
|
|
116
|
+
return result.metafile ?? null;
|
|
104
117
|
} catch {
|
|
105
|
-
return
|
|
118
|
+
return null;
|
|
106
119
|
}
|
|
107
120
|
}
|
|
108
121
|
|
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>;
|
|
@@ -402,13 +520,14 @@ export interface ClientRuntimeConfig {
|
|
|
402
520
|
/** Values available after config loading. Deferred references retain their names. */
|
|
403
521
|
export type ResolvedConfig = Omit<
|
|
404
522
|
Config,
|
|
405
|
-
|
|
406
|
-
|
|
523
|
+
| 'integrations'
|
|
524
|
+
| 'exportsOutputDirectory'
|
|
525
|
+
| 'sitesOutputDirectory'
|
|
526
|
+
| 'useVariables'
|
|
527
|
+
| 'app'
|
|
528
|
+
| 'runtime'
|
|
407
529
|
> & {
|
|
408
|
-
|
|
409
|
-
devAccessToken?: string | null;
|
|
410
|
-
figma_project_id?: string | null;
|
|
411
|
-
figmaProjectId?: string | null;
|
|
530
|
+
integrations?: { figma?: { projectId?: string | null; accessToken?: string | null } };
|
|
412
531
|
exportsOutputDirectory?: string;
|
|
413
532
|
sitesOutputDirectory?: string;
|
|
414
533
|
useVariables?: boolean;
|
|
@@ -418,7 +537,10 @@ export type ResolvedConfig = Omit<
|
|
|
418
537
|
};
|
|
419
538
|
};
|
|
420
539
|
|
|
421
|
-
export type ClientConfig = Pick<
|
|
540
|
+
export type ClientConfig = Pick<
|
|
541
|
+
ResolvedConfig,
|
|
542
|
+
'app' | 'exportsOutputDirectory' | 'sitesOutputDirectory' | 'assets_zip_links' | 'useVariables'
|
|
543
|
+
> & {
|
|
422
544
|
runtime: ClientRuntimeConfig;
|
|
423
545
|
};
|
|
424
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;
|