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
|
@@ -8,11 +8,32 @@ const isPlainObject_1 = __importDefault(require("lodash/isPlainObject"));
|
|
|
8
8
|
const logger_1 = require("../utils/logger");
|
|
9
9
|
const from_env_1 = require("./from-env");
|
|
10
10
|
const errors_1 = require("./errors");
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
11
|
+
/**
|
|
12
|
+
* Match a dot path against a pattern. A `*` segment matches exactly one segment, so one pattern
|
|
13
|
+
* covers every element of a list. With `prefix`, the pattern also matches anything nested under it.
|
|
14
|
+
*/
|
|
15
|
+
const pathMatches = (pattern, path, prefix = false) => {
|
|
16
|
+
const expected = pattern.split('.');
|
|
17
|
+
const actual = path.split('.');
|
|
18
|
+
if (prefix ? expected.length > actual.length : expected.length !== actual.length)
|
|
19
|
+
return false;
|
|
20
|
+
return expected.every((segment, index) => segment === '*' || segment === actual[index]);
|
|
21
|
+
};
|
|
22
|
+
/** Paths whose value the deployed app reads at request time, so only the variable name is stored. */
|
|
23
|
+
exports.DEFERRED_PATHS = [
|
|
24
|
+
'runtime.registry.database.url',
|
|
25
|
+
'runtime.registry.email.options.apiKey',
|
|
26
|
+
'runtime.registry.email.options.password',
|
|
27
|
+
'runtime.ai.connections.*.apiKey',
|
|
28
|
+
];
|
|
29
|
+
/**
|
|
30
|
+
* Path prefixes whose nested references the deployed app reads at request time. Literals below them
|
|
31
|
+
* are baked. `DEFERRED_PATHS` entries below them still reject literals.
|
|
32
|
+
*/
|
|
33
|
+
const DEFERRED_PREFIXES = ['runtime.registry.email.options', 'runtime.registry.assetStorage.options', 'runtime.ai.connections.*.options'];
|
|
34
|
+
const SECRET_PATHS = new Set(['integrations.figma.accessToken', 'runtime.registryConnection.accessToken']);
|
|
35
|
+
const isDeferred = (path) => exports.DEFERRED_PATHS.some((deferred) => pathMatches(deferred, path));
|
|
36
|
+
const isUnderDeferredPrefix = (path) => DEFERRED_PREFIXES.some((prefix) => pathMatches(`${prefix}.*`, path, true));
|
|
16
37
|
const ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
17
38
|
const ALIASES = {
|
|
18
39
|
HANDOFF_REGISTRY_URL: 'HANDOFF_CLOUD_URL',
|
|
@@ -44,17 +65,12 @@ const resolveConfigEnv = (config, profile, defaults) => {
|
|
|
44
65
|
};
|
|
45
66
|
const walk = (value, path, seed) => {
|
|
46
67
|
var _a;
|
|
47
|
-
const deferred =
|
|
68
|
+
const deferred = isDeferred(path);
|
|
48
69
|
const secret = SECRET_PATHS.has(path);
|
|
49
70
|
if ((secret || deferred) && value !== undefined && !(0, from_env_1.isEnvReference)(value)) {
|
|
50
71
|
fail(path, 'Expected an environment reference, such as { $env: "VARIABLE_NAME" }. Literal values are not allowed.');
|
|
51
72
|
}
|
|
52
73
|
if ((0, from_env_1.isEnvReference)(value)) {
|
|
53
|
-
// Checked before the name, so the message names the supported pattern instead of the reference shape.
|
|
54
|
-
if (isBaked(path)) {
|
|
55
|
-
fail(path, 'Environment references are not allowed here because the resolved value is baked into the build. ' +
|
|
56
|
-
"Put the variable name in options and read it through the adapter factory's `env` argument.");
|
|
57
|
-
}
|
|
58
74
|
if (typeof value.$env !== 'string' || !ENV_NAME.test(value.$env)) {
|
|
59
75
|
fail(path, 'Invalid environment variable name. Use letters, digits, and underscores, starting with a letter or underscore.');
|
|
60
76
|
}
|
|
@@ -63,7 +79,7 @@ const resolveConfigEnv = (config, profile, defaults) => {
|
|
|
63
79
|
if (Object.keys(value).some((key) => key !== '$env' && key !== 'default')) {
|
|
64
80
|
fail(path, `Environment variable "${name}" has an invalid reference shape.`);
|
|
65
81
|
}
|
|
66
|
-
if (deferred) {
|
|
82
|
+
if (deferred || isUnderDeferredPrefix(path)) {
|
|
67
83
|
if ('default' in value)
|
|
68
84
|
fail(path, `Environment variable "${name}" cannot have a default because it is read by the deployed app.`);
|
|
69
85
|
return { $env: name };
|
package/dist/config/runtime.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -83,7 +83,7 @@ declare class Handoff {
|
|
|
83
83
|
private profilesWithoutConfig;
|
|
84
84
|
init(configOverride?: Partial<Config>): Handoff;
|
|
85
85
|
reload(): Handoff;
|
|
86
|
-
preRunner(
|
|
86
|
+
preRunner(): Handoff;
|
|
87
87
|
fetch(): Promise<Handoff>;
|
|
88
88
|
component(name: string | null): Promise<Handoff>;
|
|
89
89
|
pattern(): Promise<Handoff>;
|
|
@@ -186,10 +186,7 @@ declare class Handoff {
|
|
|
186
186
|
*/
|
|
187
187
|
getDocumentationObject(): Promise<CoreTypes.IDocumentationObject | undefined>;
|
|
188
188
|
getRunner(): Promise<ReturnType<typeof HandoffRunner>>;
|
|
189
|
-
/**
|
|
190
|
-
* Gets the project ID, falling back to filesystem-safe working path if figma_project_id is missing
|
|
191
|
-
* @returns {string} The project ID to use for path construction
|
|
192
|
-
*/
|
|
189
|
+
/** Keys `.handoff/<projectId>`, so workspaces that share one installed package stage apart. */
|
|
193
190
|
getProjectId(): string;
|
|
194
191
|
/**
|
|
195
192
|
* Gets the output path for the current project
|
|
@@ -236,6 +233,10 @@ declare class Handoff {
|
|
|
236
233
|
* Gets the selected main config file path if one exists.
|
|
237
234
|
*/
|
|
238
235
|
getMainConfigFilePath(): string | undefined;
|
|
236
|
+
/**
|
|
237
|
+
* Gets the selected profile config file path if one exists.
|
|
238
|
+
*/
|
|
239
|
+
getProfileConfigFilePath(): string | undefined;
|
|
239
240
|
getProfile(): string | undefined;
|
|
240
241
|
/**
|
|
241
242
|
* True for the base config file and for the profile file merged onto it. Both carry project-wide
|
|
@@ -260,7 +261,11 @@ export { defineConfig } from './config';
|
|
|
260
261
|
export { fromEnv } from './config/from-env';
|
|
261
262
|
export type { EnvValue, EnvSecret, RuntimeEnvReference } from './config/from-env';
|
|
262
263
|
export type { CatalogItem, CatalogItemEntries, CatalogItemInput, CatalogItemMeta, CatalogPreview, CompositionRef, Preview, SourceDescriptor, SourceFormat, RendererKind, } from './catalog';
|
|
263
|
-
export {
|
|
264
|
-
export type {
|
|
264
|
+
export { defineStorageProvider } from './registry/asset-storage/define';
|
|
265
|
+
export type { StorageProvider, StorageProviderContext, StorageProviderFactory, StorageInput, StorageReadResult, AssetUpload, AssetUploadInput, } from './registry/asset-storage/types';
|
|
266
|
+
export { defineEmailProvider } from './registry/email/define';
|
|
267
|
+
export type { EmailMessage, EmailProvider, EmailProviderContext, EmailProviderFactory } from './registry/email/types';
|
|
268
|
+
export { defineAiProvider } from './ai/define';
|
|
269
|
+
export type { AiProvider, AiProviderContext, AiProviderFactory } from './ai/types';
|
|
265
270
|
export { Transformers as CoreTransformers, TransformerUtils as CoreTransformerUtils, Types as CoreTypes } from 'handoff-core';
|
|
266
271
|
export default Handoff;
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.CoreTypes = exports.CoreTransformerUtils = exports.CoreTransformers = exports.
|
|
38
|
+
exports.CoreTypes = exports.CoreTransformerUtils = exports.CoreTransformers = exports.defineAiProvider = exports.defineEmailProvider = exports.defineStorageProvider = exports.fromEnv = exports.defineConfig = void 0;
|
|
39
39
|
require("./config/env");
|
|
40
40
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
41
41
|
const handoff_core_1 = require("handoff-core");
|
|
@@ -46,6 +46,7 @@ const make_1 = require("./cli/make");
|
|
|
46
46
|
const store_1 = require("./cli/auth/store");
|
|
47
47
|
const config_1 = require("./config");
|
|
48
48
|
const pipeline_1 = __importStar(require("./pipeline"));
|
|
49
|
+
const figma_1 = require("./pipeline/figma");
|
|
49
50
|
const content_kinds_1 = require("./registry/content-kinds");
|
|
50
51
|
const store_2 = require("./store");
|
|
51
52
|
const builder_1 = __importStar(require("./transformers/preview/component/builder"));
|
|
@@ -193,13 +194,10 @@ class Handoff {
|
|
|
193
194
|
this.construct(this._options);
|
|
194
195
|
return this;
|
|
195
196
|
}
|
|
196
|
-
preRunner(
|
|
197
|
+
preRunner() {
|
|
197
198
|
if (!this.config) {
|
|
198
199
|
throw Error('Handoff not initialized');
|
|
199
200
|
}
|
|
200
|
-
if (validate) {
|
|
201
|
-
this.config = (0, config_1.validateConfig)(this.config);
|
|
202
|
-
}
|
|
203
201
|
return this;
|
|
204
202
|
}
|
|
205
203
|
fetch() {
|
|
@@ -504,12 +502,8 @@ class Handoff {
|
|
|
504
502
|
if (!!this._handoffRunner) {
|
|
505
503
|
return this._handoffRunner;
|
|
506
504
|
}
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
accessToken: this.config.dev_access_token,
|
|
510
|
-
};
|
|
511
|
-
// Initialize the provider
|
|
512
|
-
const provider = handoff_core_1.Providers.RestApiProvider(apiCredentials);
|
|
505
|
+
const { projectId, accessToken } = (0, figma_1.resolveFigmaConnection)(this.config);
|
|
506
|
+
const provider = handoff_core_1.Providers.RestApiProvider({ projectId, accessToken });
|
|
513
507
|
this._handoffRunner = (0, handoff_core_1.Handoff)(provider, {
|
|
514
508
|
options: {
|
|
515
509
|
transformer: this.runtimeConfig.options,
|
|
@@ -531,16 +525,8 @@ class Handoff {
|
|
|
531
525
|
return this._handoffRunner;
|
|
532
526
|
});
|
|
533
527
|
}
|
|
534
|
-
/**
|
|
535
|
-
* Gets the project ID, falling back to filesystem-safe working path if figma_project_id is missing
|
|
536
|
-
* @returns {string} The project ID to use for path construction
|
|
537
|
-
*/
|
|
528
|
+
/** Keys `.handoff/<projectId>`, so workspaces that share one installed package stage apart. */
|
|
538
529
|
getProjectId() {
|
|
539
|
-
var _a;
|
|
540
|
-
if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.figma_project_id) {
|
|
541
|
-
return this.config.figma_project_id;
|
|
542
|
-
}
|
|
543
|
-
// Fallback to filesystem-safe transformation of working path
|
|
544
530
|
return (0, path_3.generateFilesystemSafeId)(this.workingPath);
|
|
545
531
|
}
|
|
546
532
|
/**
|
|
@@ -548,7 +534,7 @@ class Handoff {
|
|
|
548
534
|
* @returns {string} The absolute path to the output directory
|
|
549
535
|
*/
|
|
550
536
|
getOutputPath() {
|
|
551
|
-
return path_1.default.resolve(this.workingPath, this.exportsDirectory
|
|
537
|
+
return path_1.default.resolve(this.workingPath, this.exportsDirectory);
|
|
552
538
|
}
|
|
553
539
|
/**
|
|
554
540
|
* Gets the path to the tokens.json file
|
|
@@ -607,6 +593,12 @@ class Handoff {
|
|
|
607
593
|
getMainConfigFilePath() {
|
|
608
594
|
return this._mainConfigFilePath;
|
|
609
595
|
}
|
|
596
|
+
/**
|
|
597
|
+
* Gets the selected profile config file path if one exists.
|
|
598
|
+
*/
|
|
599
|
+
getProfileConfigFilePath() {
|
|
600
|
+
return this._profileConfigFilePath;
|
|
601
|
+
}
|
|
610
602
|
getProfile() {
|
|
611
603
|
return this._profile;
|
|
612
604
|
}
|
|
@@ -651,7 +643,11 @@ Object.defineProperty(exports, "defineConfig", { enumerable: true, get: function
|
|
|
651
643
|
var from_env_1 = require("./config/from-env");
|
|
652
644
|
Object.defineProperty(exports, "fromEnv", { enumerable: true, get: function () { return from_env_1.fromEnv; } });
|
|
653
645
|
var define_1 = require("./registry/asset-storage/define");
|
|
654
|
-
Object.defineProperty(exports, "
|
|
646
|
+
Object.defineProperty(exports, "defineStorageProvider", { enumerable: true, get: function () { return define_1.defineStorageProvider; } });
|
|
647
|
+
var define_2 = require("./registry/email/define");
|
|
648
|
+
Object.defineProperty(exports, "defineEmailProvider", { enumerable: true, get: function () { return define_2.defineEmailProvider; } });
|
|
649
|
+
var define_3 = require("./ai/define");
|
|
650
|
+
Object.defineProperty(exports, "defineAiProvider", { enumerable: true, get: function () { return define_3.defineAiProvider; } });
|
|
655
651
|
// Export transformers and types from handoff-core
|
|
656
652
|
var handoff_core_2 = require("handoff-core");
|
|
657
653
|
Object.defineProperty(exports, "CoreTransformers", { enumerable: true, get: function () { return handoff_core_2.Transformers; } });
|
package/dist/nav/index.d.ts
CHANGED
|
@@ -78,6 +78,6 @@ export interface NavData {
|
|
|
78
78
|
export { getNavData } from './resolver';
|
|
79
79
|
export type { GetNavDataInput } from './resolver';
|
|
80
80
|
export { getWorkspaceNavData } from './workspace';
|
|
81
|
-
export type {
|
|
81
|
+
export type { WorkspaceNavOptions, WorkspaceNavLoaders } from './workspace';
|
|
82
82
|
export { getRegistryNavData } from './registry';
|
|
83
|
-
export type {
|
|
83
|
+
export type { RegistryNavOptions, RegistryNavRecords } from './registry';
|
package/dist/nav/registry.d.ts
CHANGED
|
@@ -5,11 +5,11 @@ export interface RegistryNavRecords {
|
|
|
5
5
|
pages: NavPageRecord[];
|
|
6
6
|
tokenSets: NavTokenSet[];
|
|
7
7
|
}
|
|
8
|
-
export interface
|
|
8
|
+
export interface RegistryNavOptions {
|
|
9
9
|
shell: SectionLink[];
|
|
10
10
|
load: NavLoad;
|
|
11
11
|
basePath?: string;
|
|
12
12
|
fetchRecords: () => Promise<RegistryNavRecords>;
|
|
13
13
|
}
|
|
14
|
-
/** Registry
|
|
15
|
-
export declare const getRegistryNavData: (options:
|
|
14
|
+
/** Registry nav data: shell-only initial load, or one best-effort runtime-record fetch on refresh. */
|
|
15
|
+
export declare const getRegistryNavData: (options: RegistryNavOptions) => Promise<NavData>;
|
package/dist/nav/registry.js
CHANGED
|
@@ -13,7 +13,7 @@ exports.getRegistryNavData = void 0;
|
|
|
13
13
|
const menu_shell_1 = require("../utils/menu-shell");
|
|
14
14
|
const resolver_1 = require("./resolver");
|
|
15
15
|
const emptyRecords = () => ({ components: [], patterns: [], pages: [], tokenSets: [] });
|
|
16
|
-
/** Registry
|
|
16
|
+
/** Registry nav data: shell-only initial load, or one best-effort runtime-record fetch on refresh. */
|
|
17
17
|
const getRegistryNavData = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
18
18
|
var _a;
|
|
19
19
|
let records = emptyRecords();
|
package/dist/nav/workspace.d.ts
CHANGED
|
@@ -6,13 +6,13 @@ export interface WorkspaceNavLoaders {
|
|
|
6
6
|
pages: () => Awaitable<NavPageRecord[]>;
|
|
7
7
|
tokenSets: () => Awaitable<NavTokenSet[]>;
|
|
8
8
|
}
|
|
9
|
-
export interface
|
|
9
|
+
export interface WorkspaceNavOptions {
|
|
10
10
|
docRoot: string;
|
|
11
11
|
workingPagesDir?: string;
|
|
12
12
|
basePath?: string;
|
|
13
13
|
load?: NavLoad;
|
|
14
14
|
loaders: WorkspaceNavLoaders;
|
|
15
15
|
}
|
|
16
|
-
/** Workspace/static
|
|
17
|
-
export declare const getWorkspaceNavData: (options:
|
|
16
|
+
/** Workspace/static nav data: live filesystem shell plus best-effort local snapshot loaders. */
|
|
17
|
+
export declare const getWorkspaceNavData: (options: WorkspaceNavOptions) => Promise<NavData>;
|
|
18
18
|
export {};
|
package/dist/nav/workspace.js
CHANGED
|
@@ -64,7 +64,7 @@ const markdownTitle = (id, docRoot, workingPagesDir) => {
|
|
|
64
64
|
}
|
|
65
65
|
return undefined;
|
|
66
66
|
};
|
|
67
|
-
/** Workspace/static
|
|
67
|
+
/** Workspace/static nav data: live filesystem shell plus best-effort local snapshot loaders. */
|
|
68
68
|
const getWorkspaceNavData = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
69
69
|
var _a;
|
|
70
70
|
const [loadedComponents, patterns, pages, loadedTokenSets] = yield Promise.all([
|
package/dist/pipeline/figma.d.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import { Types as HandoffTypes } from 'handoff-core';
|
|
2
2
|
import Handoff from '..';
|
|
3
|
+
import type { ResolvedConfig } from '../types/config';
|
|
4
|
+
/** Figma values resolved at config load, with the variable names they come from. */
|
|
5
|
+
export type FigmaConnection = {
|
|
6
|
+
projectId: string;
|
|
7
|
+
accessToken: string;
|
|
8
|
+
/** Unset when the config gives a literal file ID. */
|
|
9
|
+
projectIdEnv?: string;
|
|
10
|
+
accessTokenEnv?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare const resolveFigmaConnection: (config: ResolvedConfig | null | undefined) => FigmaConnection;
|
|
3
13
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
14
|
+
* Makes sure that `fetch` has a Figma file ID and access token. In a terminal, it asks for an empty
|
|
15
|
+
* value and can save it to the env file of the selected profile. Without a terminal, it throws
|
|
16
|
+
* `HandoffConfigError`.
|
|
6
17
|
*/
|
|
7
18
|
export declare const validateFigmaAuth: (handoff: Handoff) => Promise<void>;
|
|
8
19
|
/**
|
package/dist/pipeline/figma.js
CHANGED
|
@@ -35,29 +35,66 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.figmaExtract = exports.validateFigmaAuth = void 0;
|
|
38
|
+
exports.figmaExtract = exports.validateFigmaAuth = exports.resolveFigmaConnection = void 0;
|
|
39
39
|
const p = __importStar(require("@clack/prompts"));
|
|
40
40
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
41
41
|
const stream = __importStar(require("node:stream"));
|
|
42
42
|
const path_1 = __importDefault(require("path"));
|
|
43
|
+
const errors_1 = require("../config/errors");
|
|
44
|
+
const resolve_env_1 = require("../config/resolve-env");
|
|
43
45
|
const logger_1 = require("../utils/logger");
|
|
44
46
|
const archive_1 = require("./archive");
|
|
45
47
|
const documentation_1 = require("./documentation");
|
|
48
|
+
const resolveFigmaConnection = (config) => {
|
|
49
|
+
var _a, _b, _c;
|
|
50
|
+
const figma = (_a = config === null || config === void 0 ? void 0 : config.integrations) === null || _a === void 0 ? void 0 : _a.figma;
|
|
51
|
+
return {
|
|
52
|
+
projectId: ((_b = figma === null || figma === void 0 ? void 0 : figma.projectId) === null || _b === void 0 ? void 0 : _b.trim()) || '',
|
|
53
|
+
accessToken: ((_c = figma === null || figma === void 0 ? void 0 : figma.accessToken) === null || _c === void 0 ? void 0 : _c.trim()) || '',
|
|
54
|
+
projectIdEnv: (0, resolve_env_1.configEnvName)(config, 'integrations.figma.projectId'),
|
|
55
|
+
accessTokenEnv: (0, resolve_env_1.configEnvName)(config, 'integrations.figma.accessToken'),
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
exports.resolveFigmaConnection = resolveFigmaConnection;
|
|
59
|
+
const describeSource = (envName, configPath) => envName ? `${envName} (${configPath})` : configPath;
|
|
60
|
+
/** Replaces each variable that the file already sets and appends the others. */
|
|
61
|
+
const saveEnvValues = (filePath, values) => __awaiter(void 0, void 0, void 0, function* () {
|
|
62
|
+
const lines = fs_extra_1.default.existsSync(filePath) ? (yield fs_extra_1.default.readFile(filePath, 'utf8')).split(/\r?\n/) : [];
|
|
63
|
+
while (lines.length && !lines[lines.length - 1].trim())
|
|
64
|
+
lines.pop();
|
|
65
|
+
for (const [name, value] of Object.entries(values)) {
|
|
66
|
+
const line = `${name}="${value}"`;
|
|
67
|
+
const index = lines.findIndex((existing) => new RegExp(`^\\s*(export\\s+)?${name}\\s*=`).test(existing));
|
|
68
|
+
if (index === -1)
|
|
69
|
+
lines.push(line);
|
|
70
|
+
else
|
|
71
|
+
lines[index] = line;
|
|
72
|
+
}
|
|
73
|
+
yield fs_extra_1.default.writeFile(filePath, `${lines.join('\n')}\n`);
|
|
74
|
+
});
|
|
46
75
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
76
|
+
* Makes sure that `fetch` has a Figma file ID and access token. In a terminal, it asks for an empty
|
|
77
|
+
* value and can save it to the env file of the selected profile. Without a terminal, it throws
|
|
78
|
+
* `HandoffConfigError`.
|
|
49
79
|
*/
|
|
50
80
|
const validateFigmaAuth = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
81
|
+
var _a;
|
|
82
|
+
const connection = (0, exports.resolveFigmaConnection)(handoff.config);
|
|
83
|
+
let { projectId, accessToken } = connection;
|
|
84
|
+
if (projectId && accessToken) {
|
|
54
85
|
return;
|
|
55
86
|
}
|
|
56
|
-
|
|
57
|
-
if (!
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
87
|
+
const profile = handoff.getProfile();
|
|
88
|
+
if (!process.stdin.isTTY) {
|
|
89
|
+
const missing = [
|
|
90
|
+
!accessToken && describeSource(connection.accessTokenEnv, 'integrations.figma.accessToken'),
|
|
91
|
+
!projectId && describeSource(connection.projectIdEnv, 'integrations.figma.projectId'),
|
|
92
|
+
].filter(Boolean);
|
|
93
|
+
throw new errors_1.HandoffConfigError(`Figma is not configured (profile "${profile !== null && profile !== void 0 ? profile : 'default'}"). Set ${missing.join(' and ')}.`);
|
|
94
|
+
}
|
|
95
|
+
if (!accessToken) {
|
|
96
|
+
p.log.warn(`Figma access token not found. Set ${describeSource(connection.accessTokenEnv, 'integrations.figma.accessToken')}.\n` +
|
|
97
|
+
`Use these instructions to generate one: https://help.figma.com/hc/en-us/articles/8085703771159-Manage-personal-access-tokens`);
|
|
61
98
|
const token = yield p.password({
|
|
62
99
|
message: 'Figma Developer Key:',
|
|
63
100
|
});
|
|
@@ -65,61 +102,50 @@ const validateFigmaAuth = (handoff) => __awaiter(void 0, void 0, void 0, functio
|
|
|
65
102
|
p.cancel('Authentication cancelled.');
|
|
66
103
|
process.exit(0);
|
|
67
104
|
}
|
|
68
|
-
|
|
105
|
+
accessToken = token.trim();
|
|
69
106
|
}
|
|
70
|
-
if (!
|
|
71
|
-
|
|
72
|
-
p.log.warn(`Figma project ID not found. Provide HANDOFF_FIGMA_PROJECT_ID via environment variable or .env file.\n` +
|
|
107
|
+
if (!projectId) {
|
|
108
|
+
p.log.warn(`Figma project ID not found. Set ${describeSource(connection.projectIdEnv, 'integrations.figma.projectId')}.\n` +
|
|
73
109
|
`Find it in your Figma file URL (e.g., figma.com/file/{PROJECT_ID}/...).`);
|
|
74
|
-
const
|
|
110
|
+
const value = yield p.text({
|
|
75
111
|
message: 'Figma Project Id:',
|
|
76
112
|
validate: (value) => {
|
|
77
113
|
if (!value.trim())
|
|
78
114
|
return 'Project ID is required';
|
|
79
115
|
},
|
|
80
116
|
});
|
|
81
|
-
if (p.isCancel(
|
|
117
|
+
if (p.isCancel(value)) {
|
|
82
118
|
p.cancel('Authentication cancelled.');
|
|
83
119
|
process.exit(0);
|
|
84
120
|
}
|
|
85
|
-
|
|
121
|
+
projectId = value.trim();
|
|
86
122
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
123
|
+
const values = {};
|
|
124
|
+
if (!connection.accessToken && connection.accessTokenEnv)
|
|
125
|
+
values[connection.accessTokenEnv] = accessToken;
|
|
126
|
+
if (!connection.projectId && connection.projectIdEnv)
|
|
127
|
+
values[connection.projectIdEnv] = projectId;
|
|
128
|
+
const envFileName = profile ? `.env.${profile}` : '.env';
|
|
129
|
+
if (Object.keys(values).length) {
|
|
130
|
+
const save = yield p.confirm({
|
|
131
|
+
message: `Save ${Object.keys(values).join(' and ')} to ${envFileName} for future runs?`,
|
|
91
132
|
initialValue: true,
|
|
92
133
|
});
|
|
93
|
-
if (p.isCancel(
|
|
94
|
-
p.log.info(`Skipped .
|
|
134
|
+
if (p.isCancel(save) || save === false) {
|
|
135
|
+
p.log.info(`Skipped saving. Set these variables before the next run.`);
|
|
95
136
|
}
|
|
96
137
|
else {
|
|
97
|
-
const envFilePath = path_1.default.resolve(handoff.workingPath, '.env');
|
|
98
|
-
const envFileContent = `
|
|
99
|
-
HANDOFF_DEV_ACCESS_TOKEN="${DEV_ACCESS_TOKEN}"
|
|
100
|
-
HANDOFF_FIGMA_PROJECT_ID="${FIGMA_PROJECT_ID}"
|
|
101
|
-
`;
|
|
102
138
|
try {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
.catch(() => false);
|
|
107
|
-
if (fileExists) {
|
|
108
|
-
yield fs_extra_1.default.appendFile(envFilePath, envFileContent);
|
|
109
|
-
p.log.success(`The .env file was found and updated with new content. Since these are sensitive variables, please do not commit this file.`);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
yield fs_extra_1.default.writeFile(envFilePath, envFileContent.replace(/^\s*[\r\n]/gm, ''));
|
|
113
|
-
p.log.success(`Created .env file. Do not commit sensitive variables.`);
|
|
114
|
-
}
|
|
139
|
+
yield saveEnvValues(path_1.default.resolve(handoff.workingPath, envFileName), values);
|
|
140
|
+
const secretNote = connection.accessTokenEnv && values[connection.accessTokenEnv] ? ' It contains a secret, so do not commit it.' : '';
|
|
141
|
+
p.log.success(`Saved to ${envFileName}.${secretNote}`);
|
|
115
142
|
}
|
|
116
143
|
catch (error) {
|
|
117
|
-
logger_1.Logger.error(
|
|
144
|
+
logger_1.Logger.error(`Could not save ${envFileName}:`, error);
|
|
118
145
|
}
|
|
119
146
|
}
|
|
120
147
|
}
|
|
121
|
-
handoff.config.
|
|
122
|
-
handoff.config.figma_project_id = FIGMA_PROJECT_ID;
|
|
148
|
+
handoff.config.integrations = Object.assign(Object.assign({}, handoff.config.integrations), { figma: Object.assign(Object.assign({}, (_a = handoff.config.integrations) === null || _a === void 0 ? void 0 : _a.figma), { projectId, accessToken }) });
|
|
123
149
|
});
|
|
124
150
|
exports.validateFigmaAuth = validateFigmaAuth;
|
|
125
151
|
/**
|
|
@@ -127,17 +153,31 @@ exports.validateFigmaAuth = validateFigmaAuth;
|
|
|
127
153
|
*/
|
|
128
154
|
const figmaExtract = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
|
|
129
155
|
logger_1.Logger.success(`Starting Figma data extraction.`);
|
|
130
|
-
|
|
156
|
+
// The export directory can hold other files, so remove only what fetch writes.
|
|
157
|
+
const outputPath = handoff.getOutputPath();
|
|
158
|
+
yield Promise.all([
|
|
159
|
+
handoff.getTokensFilePath(),
|
|
160
|
+
handoff.getVariablesFilePath(),
|
|
161
|
+
handoff.getIconsZipFilePath(),
|
|
162
|
+
handoff.getLogosZipFilePath(),
|
|
163
|
+
path_1.default.join(outputPath, 'tokens-map.json'),
|
|
164
|
+
path_1.default.join(outputPath, 'fonts'),
|
|
165
|
+
].map((entry) => fs_extra_1.default.remove(entry)));
|
|
166
|
+
yield fs_extra_1.default.ensureDir(outputPath);
|
|
131
167
|
const documentationObject = yield (0, documentation_1.createDocumentationObject)(handoff);
|
|
168
|
+
const createZipFiles = process.env.HANDOFF_CREATE_ASSETS_ZIP_FILES !== 'false';
|
|
132
169
|
yield Promise.all([
|
|
133
170
|
fs_extra_1.default.writeJSON(handoff.getTokensFilePath(), documentationObject, { spaces: 2 }),
|
|
134
|
-
...(
|
|
171
|
+
...(createZipFiles
|
|
135
172
|
? [
|
|
136
173
|
(0, archive_1.zipAssets)(documentationObject.assets.icons, fs_extra_1.default.createWriteStream(handoff.getIconsZipFilePath())).then((writeStream) => stream.promises.finished(writeStream)),
|
|
137
174
|
(0, archive_1.zipAssets)(documentationObject.assets.logos, fs_extra_1.default.createWriteStream(handoff.getLogosZipFilePath())).then((writeStream) => stream.promises.finished(writeStream)),
|
|
138
175
|
]
|
|
139
176
|
: []),
|
|
140
177
|
]);
|
|
178
|
+
if (!createZipFiles) {
|
|
179
|
+
return documentationObject;
|
|
180
|
+
}
|
|
141
181
|
// define the output folder
|
|
142
182
|
const outputFolder = path_1.default.resolve(handoff.modulePath, '.handoff', `${handoff.getProjectId()}`, 'public');
|
|
143
183
|
// ensure output folder exists
|
package/dist/pipeline/styles.js
CHANGED
|
@@ -37,7 +37,7 @@ const buildCustomFonts = (handoff, documentationObject) => __awaiter(void 0, voi
|
|
|
37
37
|
if (fs_extra_1.default.existsSync(fontDirName)) {
|
|
38
38
|
const stream = fs_extra_1.default.createWriteStream(path_1.default.join(fontLocation, `${name}.zip`));
|
|
39
39
|
yield (0, archive_1.zip)(fontDirName, stream);
|
|
40
|
-
const fontsFolder = path_1.default.
|
|
40
|
+
const fontsFolder = path_1.default.join(handoff.getOutputPath(), 'fonts');
|
|
41
41
|
if (!fs_extra_1.default.existsSync(fontsFolder)) {
|
|
42
42
|
fs_extra_1.default.mkdirSync(fontsFolder);
|
|
43
43
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Validates that the Node.js runtime meets the minimum version requirements.
|
|
3
3
|
*
|
|
4
|
-
* @throws {Error} If Node.js version is below
|
|
4
|
+
* @throws {Error} If Node.js version is below 22.
|
|
5
5
|
*/
|
|
6
6
|
export declare const validateHandoffRequirements: () => Promise<void>;
|
|
@@ -14,13 +14,13 @@ const logger_1 = require("../utils/logger");
|
|
|
14
14
|
/**
|
|
15
15
|
* Validates that the Node.js runtime meets the minimum version requirements.
|
|
16
16
|
*
|
|
17
|
-
* @throws {Error} If Node.js version is below
|
|
17
|
+
* @throws {Error} If Node.js version is below 22.
|
|
18
18
|
*/
|
|
19
19
|
const validateHandoffRequirements = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
20
|
let requirements = false;
|
|
21
21
|
const result = process.versions;
|
|
22
22
|
if (result && result.node) {
|
|
23
|
-
if (parseInt(result.node) >=
|
|
23
|
+
if (parseInt(result.node) >= 22) {
|
|
24
24
|
requirements = true;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -29,7 +29,7 @@ const validateHandoffRequirements = () => __awaiter(void 0, void 0, void 0, func
|
|
|
29
29
|
}
|
|
30
30
|
if (!requirements) {
|
|
31
31
|
logger_1.Logger.error('Handoff installation failed.');
|
|
32
|
-
logger_1.Logger.warn('- Please update node to at least Node
|
|
32
|
+
logger_1.Logger.warn('- Please update node to at least Node 22 https://nodejs.org/en/download. \n- You can read more about installing handoff at https://www.handoff.com/docs/');
|
|
33
33
|
throw new Error('Could not run handoff');
|
|
34
34
|
}
|
|
35
35
|
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Define helpers for custom server modules: storage, email and AI providers. This entry point has no
|
|
3
|
+
* runtime dependencies, so a module that imports it does not pull the CLI into the registry bundle.
|
|
4
|
+
*/
|
|
5
|
+
export { defineAiProvider } from './ai/define';
|
|
6
|
+
export type { AiProvider, AiProviderContext, AiProviderFactory } from './ai/types';
|
|
7
|
+
export { defineStorageProvider } from './registry/asset-storage/define';
|
|
8
|
+
export type { StorageProvider, StorageProviderContext, StorageProviderFactory, StorageInput, StorageReadResult, AssetUpload, AssetUploadInput, } from './registry/asset-storage/types';
|
|
9
|
+
export { defineEmailProvider } from './registry/email/define';
|
|
10
|
+
export type { EmailMessage, EmailProvider, EmailProviderContext, EmailProviderFactory } from './registry/email/types';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defineEmailProvider = exports.defineStorageProvider = exports.defineAiProvider = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Define helpers for custom server modules: storage, email and AI providers. This entry point has no
|
|
6
|
+
* runtime dependencies, so a module that imports it does not pull the CLI into the registry bundle.
|
|
7
|
+
*/
|
|
8
|
+
var define_1 = require("./ai/define");
|
|
9
|
+
Object.defineProperty(exports, "defineAiProvider", { enumerable: true, get: function () { return define_1.defineAiProvider; } });
|
|
10
|
+
var define_2 = require("./registry/asset-storage/define");
|
|
11
|
+
Object.defineProperty(exports, "defineStorageProvider", { enumerable: true, get: function () { return define_2.defineStorageProvider; } });
|
|
12
|
+
var define_3 = require("./registry/email/define");
|
|
13
|
+
Object.defineProperty(exports, "defineEmailProvider", { enumerable: true, get: function () { return define_3.defineEmailProvider; } });
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Typed identity helper for custom asset storage
|
|
2
|
+
* Typed identity helper for custom asset storage providers (mirrors `defineCatalogItem`): a consumer
|
|
3
3
|
* default-exports its result from a **server-only** module and points
|
|
4
4
|
* `runtime.registry.assetStorage.module` at it. It must be its own module (not an inline
|
|
5
5
|
* `defineConfig` function) so the build can trace it into the deployed registry. The default export
|
|
6
|
-
* may be the
|
|
6
|
+
* may be the provider object, or a factory `(context) => StorageProvider` when it needs its options/env.
|
|
7
7
|
*/
|
|
8
|
-
import type {
|
|
9
|
-
export declare function
|
|
10
|
-
export declare function
|
|
8
|
+
import type { StorageProvider, StorageProviderFactory } from './types';
|
|
9
|
+
export declare function defineStorageProvider(provider: StorageProvider): StorageProvider;
|
|
10
|
+
export declare function defineStorageProvider(factory: StorageProviderFactory): StorageProviderFactory;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Typed identity helper for custom asset storage
|
|
3
|
+
* Typed identity helper for custom asset storage providers (mirrors `defineCatalogItem`): a consumer
|
|
4
4
|
* default-exports its result from a **server-only** module and points
|
|
5
5
|
* `runtime.registry.assetStorage.module` at it. It must be its own module (not an inline
|
|
6
6
|
* `defineConfig` function) so the build can trace it into the deployed registry. The default export
|
|
7
|
-
* may be the
|
|
7
|
+
* may be the provider object, or a factory `(context) => StorageProvider` when it needs its options/env.
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.
|
|
11
|
-
function
|
|
10
|
+
exports.defineStorageProvider = defineStorageProvider;
|
|
11
|
+
function defineStorageProvider(input) {
|
|
12
12
|
return input;
|
|
13
13
|
}
|