@agent-native/core 0.141.2 → 0.141.4
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/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +1 -1
- package/corpus/templates/analytics/actions/gong-calls.ts +56 -18
- package/corpus/templates/analytics/changelog/2026-08-05-analytics-queries-keep-every-table-tenant-scoped.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-05-durable-a2a-workers-avoid-startup-migration-contention.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-05-fixed-sign-in-and-dashboard-requests-failing-when-background.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-05-historical-rollups-stay-complete-while-live-events-arrive.md +6 -0
- package/corpus/templates/analytics/server/db/schema.ts +1 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +2 -0
- package/corpus/templates/analytics/server/lib/emails.ts +51 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-health.ts +8 -12
- package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +9 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +262 -13
- package/corpus/templates/analytics/server/lib/gong.ts +132 -33
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/analytics/server/plugins/auth.ts +21 -2
- package/corpus/templates/analytics/server/plugins/db.ts +35 -10
- package/corpus/templates/analytics/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +17 -7
- package/corpus/templates/calendar/server/lib/booking-emails.ts +154 -70
- package/corpus/templates/calendar/server/lib/emails.ts +167 -0
- package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +64 -28
- package/corpus/templates/calendar/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/clips/actions/invite-member.ts +39 -16
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +73 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +3 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +10 -25
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +2 -0
- package/corpus/templates/clips/changelog/2026-08-05-activity-is-now-the-default-clips-recording-tab-and-ai-setup.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-05-clips-can-copy-a-linked-email-preview-for-public-recordings.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-05-preparing-recording-now-uses-a-clean-shadow-free-status-card.md +6 -0
- package/corpus/templates/clips/desktop/src/styles.css +0 -3
- package/corpus/templates/clips/server/lib/emails.ts +256 -0
- package/corpus/templates/clips/server/lib/transactional-email-templates.ts +24 -0
- package/corpus/templates/clips/server/plugins/transactional-email-catalog.ts +5 -0
- package/corpus/templates/clips/server/routes/api/thumbnail/[recordingId].get.ts +4 -1
- package/corpus/templates/clips/shared/email-preview.ts +61 -0
- package/corpus/templates/content/server/lib/comment-notifications.ts +57 -26
- package/corpus/templates/content/server/lib/emails.ts +70 -0
- package/corpus/templates/content/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/design/actions/import-design-tokens.ts +11 -8
- package/corpus/templates/design/actions/index-design-tokens.ts +13 -6
- package/corpus/templates/design/changelog/2026-08-05-design-token-imports-classify-typography-dimensions-correctly.md +6 -0
- package/corpus/templates/dispatch/app/routes/transactional-email.$appId.$id.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/transactional-email.tsx +4 -0
- package/corpus/templates/dispatch/changelog/2026-08-05-transactional-email-catalogs-and-delivery-activity-are-available-again.md +6 -0
- package/corpus/templates/factory/AGENTS.md +18 -17
- package/corpus/templates/factory/actions/get-factory-automation-health.ts +50 -0
- package/corpus/templates/factory/actions/get-triage-config.ts +8 -0
- package/corpus/templates/factory/actions/save-triage-config.ts +26 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +27 -0
- package/corpus/templates/factory/app/routes/factory.tsx +376 -206
- package/corpus/templates/factory/changelog/2026-08-05-factory-now-keeps-production-automations-running-shows-sched.md +6 -0
- package/corpus/templates/factory/server/db/schema.ts +6 -0
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +10 -0
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +141 -2
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +41 -21
- package/corpus/templates/forms/changelog/2026-08-05-form-links-can-now-be-cmd-clicked-to-open-in-a-new-tab.md +6 -0
- package/corpus/templates/forms/server/lib/emails.ts +52 -0
- package/corpus/templates/forms/server/lib/response-email.ts +2 -0
- package/corpus/templates/forms/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/plan/actions/request-plan-access.ts +33 -12
- package/corpus/templates/plan/server/lib/comment-notifications.ts +53 -27
- package/corpus/templates/plan/server/lib/emails.ts +67 -0
- package/corpus/templates/plan/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/slides/actions/import-from-url.ts +1 -0
- package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +492 -381
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +8 -7
- package/corpus/templates/slides/app/components/layout/Layout.tsx +27 -23
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +313 -0
- package/corpus/templates/slides/app/components/ui/command.tsx +1 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +8 -2
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +305 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +12 -12
- package/corpus/templates/slides/app/pages/Index.tsx +127 -137
- package/corpus/templates/slides/app/root.tsx +8 -0
- package/corpus/templates/slides/changelog/2026-08-05-deck-browsing-keeps-all-and-mine-in-the-header-with-a-tighte.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-05-new-deck-creation-now-flows-through-a-clean-full-screen-refe.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-05-website-imports-now-include-linked-stylesheets-for-more-accu.md +6 -0
- package/corpus/templates/slides/server/lib/comment-notifications.ts +44 -21
- package/corpus/templates/slides/server/lib/emails.ts +40 -0
- package/corpus/templates/slides/server/plugins/transactional-emails.ts +5 -0
- package/dist/brand-kit/index.d.ts +1 -0
- package/dist/brand-kit/index.js +1 -0
- package/dist/brand-kit/tokens.d.ts +91 -0
- package/dist/brand-kit/tokens.js +279 -0
- package/dist/brand-kit/types.d.ts +25 -0
- package/dist/client/AssistantChat.js +7 -7
- package/dist/client/onboarding/FirstRunOnboarding.js +26 -2
- package/dist/client/onboarding/first-run-registry.d.ts +25 -0
- package/dist/client/onboarding/first-run-registry.js +18 -0
- package/dist/client/onboarding/index.d.ts +2 -0
- package/dist/client/onboarding/index.js +1 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/migrations.d.ts +13 -3
- package/dist/db/migrations.js +19 -4
- package/dist/deploy/build.d.ts +8 -0
- package/dist/deploy/build.js +92 -3
- package/dist/deploy/workspace-deploy.js +86 -3
- package/dist/email-catalog/actions/list-email-activity.d.ts +5 -0
- package/dist/email-catalog/actions/list-email-activity.js +19 -0
- package/dist/email-catalog/actions/list-email-engagement.d.ts +5 -0
- package/dist/email-catalog/actions/list-email-engagement.js +15 -0
- package/dist/email-catalog/actions/list-email-log.d.ts +7 -0
- package/dist/email-catalog/actions/list-email-log.js +23 -0
- package/dist/email-catalog/actions/list-transactional-emails.d.ts +22 -0
- package/dist/email-catalog/actions/list-transactional-emails.js +67 -0
- package/dist/email-catalog/actions/render-transactional-email-preview.d.ts +9 -0
- package/dist/email-catalog/actions/render-transactional-email-preview.js +25 -0
- package/dist/email-catalog/authorize.d.ts +1 -0
- package/dist/email-catalog/authorize.js +9 -0
- package/dist/email-catalog/log.d.ts +60 -0
- package/dist/email-catalog/log.js +142 -0
- package/dist/email-catalog/provider-metrics.d.ts +34 -0
- package/dist/email-catalog/provider-metrics.js +182 -0
- package/dist/email-catalog/registry.d.ts +78 -0
- package/dist/email-catalog/registry.js +70 -0
- package/dist/email-catalog/schema.d.ts +231 -0
- package/dist/email-catalog/schema.js +53 -0
- package/dist/email-catalog/system-emails.d.ts +13 -0
- package/dist/email-catalog/system-emails.js +67 -0
- package/dist/jobs/index.d.ts +2 -0
- package/dist/jobs/index.js +2 -0
- package/dist/jobs/run-history.js +48 -1
- package/dist/jobs/scheduler-dispatch.d.ts +7 -0
- package/dist/jobs/scheduler-dispatch.js +7 -0
- package/dist/jobs/scheduler-health.d.ts +22 -0
- package/dist/jobs/scheduler-health.js +172 -0
- package/dist/jobs/scheduler.js +67 -2
- package/dist/localization/default-messages.d.ts +45 -0
- package/dist/localization/default-messages.js +45 -0
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/handlers.js +9 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +10 -10
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/server/action-discovery.js +22 -0
- package/dist/server/agent-chat/recurring-jobs-runtime.d.ts +7 -1
- package/dist/server/agent-chat/recurring-jobs-runtime.js +12 -0
- package/dist/server/agent-chat-plugin.d.ts +2 -1
- package/dist/server/agent-chat-plugin.js +69 -22
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/better-auth-instance.js +17 -2
- package/dist/server/design-token-utils.d.ts +6 -1
- package/dist/server/design-token-utils.js +252 -59
- package/dist/server/email.d.ts +11 -0
- package/dist/server/email.js +54 -3
- package/dist/server/index.d.ts +3 -2
- package/dist/server/index.js +3 -2
- package/dist/vite/client.js +20 -14
- package/package.json +2 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@agent-native/core/brand-kit/tokens`
|
|
3
|
+
*
|
|
4
|
+
* Pure helpers for the named-token vocabulary a Brand Kit stores alongside its
|
|
5
|
+
* seven color roles. Kept on its own subpath (no `design-token-utils` re-export)
|
|
6
|
+
* so browser code can import the CSS-safety predicates without pulling the
|
|
7
|
+
* server-side extraction stack into the bundle.
|
|
8
|
+
*/
|
|
9
|
+
import type { BrandKitToken, BrandKitTokenType } from "./types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Upper bound on a single kit's stored vocabulary. Large systems legitimately
|
|
12
|
+
* define hundreds of tokens; this only stops an unbounded scrape landing in SQL.
|
|
13
|
+
*/
|
|
14
|
+
export declare const MAX_BRAND_KIT_TOKENS = 500;
|
|
15
|
+
export declare function isSafeCssVarName(value: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Token values are spliced raw into `:root { … }` declarations, so anything that
|
|
18
|
+
* could terminate a declaration or break out of a `<style>` element is unsafe.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isSafeCssTokenValue(value: string): boolean;
|
|
21
|
+
export declare function isColorTokenValue(value: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Bucket a token, trusting the value's shape over the name's keywords.
|
|
24
|
+
*
|
|
25
|
+
* Name-first classification called Primer's `--text-body-size-medium: 1rem` a
|
|
26
|
+
* color because the name contains "text", which then rendered a swatch with
|
|
27
|
+
* `background: 1rem`. A dimension is never a color however the token is named.
|
|
28
|
+
*/
|
|
29
|
+
export declare function classifyBrandKitToken(name: string, value: string): BrandKitTokenType;
|
|
30
|
+
/** Title-case display name derived from a CSS var, e.g. `--primary-color`. */
|
|
31
|
+
export declare function friendlyTokenName(cssVar: string): string;
|
|
32
|
+
export type BrandKitTokenRejectionReason = "malformed" | "unsafe-css-var" | "unsafe-value" | "over-limit";
|
|
33
|
+
export interface BrandKitTokenRejection {
|
|
34
|
+
reason: BrandKitTokenRejectionReason;
|
|
35
|
+
/** Best-effort identifier for the offending entry, for error messages. */
|
|
36
|
+
label: string;
|
|
37
|
+
}
|
|
38
|
+
export interface NormalizedBrandKitTokens {
|
|
39
|
+
tokens: BrandKitToken[];
|
|
40
|
+
/**
|
|
41
|
+
* Entries that could not be stored. Callers must surface these - a kit that
|
|
42
|
+
* silently kept 4 of 40 tokens reads downstream as a 4-token design system.
|
|
43
|
+
*/
|
|
44
|
+
rejected: BrandKitTokenRejection[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Coerce untrusted token JSON into storable tokens, reporting every entry it
|
|
48
|
+
* could not accept. Later duplicates of a `cssVar` win, matching the overlay
|
|
49
|
+
* order importers use.
|
|
50
|
+
*/
|
|
51
|
+
export declare function normalizeBrandKitTokens(input: unknown): NormalizedBrandKitTokens;
|
|
52
|
+
/** Human-readable summary of why tokens were refused, for thrown errors. */
|
|
53
|
+
export declare function describeBrandKitTokenRejections(rejected: readonly BrandKitTokenRejection[]): string;
|
|
54
|
+
/**
|
|
55
|
+
* The seven colour roles plus radius/spacing, as tokens. Derived from a kit's
|
|
56
|
+
* summary fields rather than named by the source system, so they carry no
|
|
57
|
+
* `group`.
|
|
58
|
+
*/
|
|
59
|
+
export declare function brandKitRoleTokens(data: {
|
|
60
|
+
colors?: object | null;
|
|
61
|
+
borders?: {
|
|
62
|
+
radius?: string;
|
|
63
|
+
} | null;
|
|
64
|
+
spacing?: object | null;
|
|
65
|
+
} | null | undefined, source?: string): BrandKitToken[];
|
|
66
|
+
/**
|
|
67
|
+
* Read a kit's named tokens out of a raw CSS block. A kit's `customCSS` already
|
|
68
|
+
* spells out the source system's real token names. Declaration order wins on
|
|
69
|
+
* duplicates, matching the cascade.
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseBrandKitTokensFromCss(css: string, source?: string): BrandKitToken[];
|
|
72
|
+
/**
|
|
73
|
+
* The kit's named vocabulary: its stored `tokens` when it has them, else the
|
|
74
|
+
* names its `customCSS` declares. Kits predating `tokens` still carry real names
|
|
75
|
+
* in CSS, so reading only `tokens` would report them as having none.
|
|
76
|
+
*/
|
|
77
|
+
export declare function resolveBrandKitTokens(data: {
|
|
78
|
+
tokens?: unknown;
|
|
79
|
+
customCSS?: unknown;
|
|
80
|
+
} | null | undefined, cssSource?: string): BrandKitToken[];
|
|
81
|
+
export interface BrandKitTokenGroup {
|
|
82
|
+
/** The source's own group path when it has one, else the token type. */
|
|
83
|
+
label: string;
|
|
84
|
+
type: BrandKitTokenType;
|
|
85
|
+
tokens: BrandKitToken[];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Group tokens for display, preserving the source's collection paths. Groups sort
|
|
89
|
+
* by token type so colors lead, then alphabetically within a type.
|
|
90
|
+
*/
|
|
91
|
+
export declare function groupBrandKitTokens(tokens: readonly BrandKitToken[]): BrandKitTokenGroup[];
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@agent-native/core/brand-kit/tokens`
|
|
3
|
+
*
|
|
4
|
+
* Pure helpers for the named-token vocabulary a Brand Kit stores alongside its
|
|
5
|
+
* seven color roles. Kept on its own subpath (no `design-token-utils` re-export)
|
|
6
|
+
* so browser code can import the CSS-safety predicates without pulling the
|
|
7
|
+
* server-side extraction stack into the bundle.
|
|
8
|
+
*/
|
|
9
|
+
const BRAND_KIT_TOKEN_TYPES = [
|
|
10
|
+
"color",
|
|
11
|
+
"typography",
|
|
12
|
+
"spacing",
|
|
13
|
+
"radius",
|
|
14
|
+
"shadow",
|
|
15
|
+
"other",
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* Upper bound on a single kit's stored vocabulary. Large systems legitimately
|
|
19
|
+
* define hundreds of tokens; this only stops an unbounded scrape landing in SQL.
|
|
20
|
+
*/
|
|
21
|
+
export const MAX_BRAND_KIT_TOKENS = 500;
|
|
22
|
+
const CSS_CUSTOM_PROPERTY_NAME = /^--[-_a-zA-Z0-9]+$/;
|
|
23
|
+
const COLOR_FUNCTION_OR_HEX = /^(#[0-9a-fA-F]{3,8}|rgba?\(|hsla?\(|oklch\(|color\()/i;
|
|
24
|
+
const NAMED_CSS_COLORS = new Set([
|
|
25
|
+
"red",
|
|
26
|
+
"blue",
|
|
27
|
+
"green",
|
|
28
|
+
"yellow",
|
|
29
|
+
"orange",
|
|
30
|
+
"purple",
|
|
31
|
+
"pink",
|
|
32
|
+
"cyan",
|
|
33
|
+
"magenta",
|
|
34
|
+
"teal",
|
|
35
|
+
"navy",
|
|
36
|
+
"maroon",
|
|
37
|
+
"coral",
|
|
38
|
+
"salmon",
|
|
39
|
+
"gold",
|
|
40
|
+
"silver",
|
|
41
|
+
"gray",
|
|
42
|
+
"grey",
|
|
43
|
+
"indigo",
|
|
44
|
+
"violet",
|
|
45
|
+
"lime",
|
|
46
|
+
"olive",
|
|
47
|
+
"aqua",
|
|
48
|
+
"fuchsia",
|
|
49
|
+
"crimson",
|
|
50
|
+
"turquoise",
|
|
51
|
+
"ivory",
|
|
52
|
+
"beige",
|
|
53
|
+
"lavender",
|
|
54
|
+
"tan",
|
|
55
|
+
"khaki",
|
|
56
|
+
"plum",
|
|
57
|
+
"orchid",
|
|
58
|
+
"sienna",
|
|
59
|
+
]);
|
|
60
|
+
export function isSafeCssVarName(value) {
|
|
61
|
+
return CSS_CUSTOM_PROPERTY_NAME.test(value);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Token values are spliced raw into `:root { … }` declarations, so anything that
|
|
65
|
+
* could terminate a declaration or break out of a `<style>` element is unsafe.
|
|
66
|
+
*/
|
|
67
|
+
export function isSafeCssTokenValue(value) {
|
|
68
|
+
return (value.length > 0 &&
|
|
69
|
+
value.length <= 300 &&
|
|
70
|
+
!/[;{}<>]/.test(value) &&
|
|
71
|
+
!/\/\*/.test(value) &&
|
|
72
|
+
!/[\u0000-\u001f\u007f]/.test(value));
|
|
73
|
+
}
|
|
74
|
+
export function isColorTokenValue(value) {
|
|
75
|
+
const normalized = value.trim().toLowerCase();
|
|
76
|
+
return (COLOR_FUNCTION_OR_HEX.test(normalized) || NAMED_CSS_COLORS.has(normalized));
|
|
77
|
+
}
|
|
78
|
+
const COLOR_NAME_HINT = /color|bg|background|text|border|accent|primary|secondary|surface|muted|foreground|fill|stroke/i;
|
|
79
|
+
const DIMENSION_VALUE = /^-?\d*\.?\d+(px|rem|em|ex|ch|%|vh|vw|vmin|vmax|pt|pc|cm|mm|in|s|ms|deg|fr)?$/i;
|
|
80
|
+
/**
|
|
81
|
+
* Bucket a token, trusting the value's shape over the name's keywords.
|
|
82
|
+
*
|
|
83
|
+
* Name-first classification called Primer's `--text-body-size-medium: 1rem` a
|
|
84
|
+
* color because the name contains "text", which then rendered a swatch with
|
|
85
|
+
* `background: 1rem`. A dimension is never a color however the token is named.
|
|
86
|
+
*/
|
|
87
|
+
export function classifyBrandKitToken(name, value) {
|
|
88
|
+
const n = name.toLowerCase();
|
|
89
|
+
if (isColorTokenValue(value))
|
|
90
|
+
return "color";
|
|
91
|
+
if (/radius|rounded/i.test(n))
|
|
92
|
+
return "radius";
|
|
93
|
+
// `line-?height` and `letter` run before the spacing check so
|
|
94
|
+
// `letter-spacing` is type metrics, not layout spacing.
|
|
95
|
+
if (/font|size|leading|line-?height|letter|tracking|weight|heading|body|type/i.test(n)) {
|
|
96
|
+
return "typography";
|
|
97
|
+
}
|
|
98
|
+
if (/spacing|gap|padding|margin|space/i.test(n))
|
|
99
|
+
return "spacing";
|
|
100
|
+
if (/shadow|blur|drop/i.test(n))
|
|
101
|
+
return "shadow";
|
|
102
|
+
if (COLOR_NAME_HINT.test(n) && !DIMENSION_VALUE.test(value.trim())) {
|
|
103
|
+
return "color";
|
|
104
|
+
}
|
|
105
|
+
return "other";
|
|
106
|
+
}
|
|
107
|
+
/** Title-case display name derived from a CSS var, e.g. `--primary-color`. */
|
|
108
|
+
export function friendlyTokenName(cssVar) {
|
|
109
|
+
return cssVar
|
|
110
|
+
.replace(/^--/, "")
|
|
111
|
+
.replace(/[-_]/g, " ")
|
|
112
|
+
.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
113
|
+
}
|
|
114
|
+
function readString(source, key) {
|
|
115
|
+
const value = source[key];
|
|
116
|
+
return typeof value === "string" ? value.trim() : "";
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Coerce untrusted token JSON into storable tokens, reporting every entry it
|
|
120
|
+
* could not accept. Later duplicates of a `cssVar` win, matching the overlay
|
|
121
|
+
* order importers use.
|
|
122
|
+
*/
|
|
123
|
+
export function normalizeBrandKitTokens(input) {
|
|
124
|
+
if (input === undefined || input === null) {
|
|
125
|
+
return { tokens: [], rejected: [] };
|
|
126
|
+
}
|
|
127
|
+
if (!Array.isArray(input)) {
|
|
128
|
+
return { tokens: [], rejected: [{ reason: "malformed", label: "tokens" }] };
|
|
129
|
+
}
|
|
130
|
+
const byCssVar = new Map();
|
|
131
|
+
const rejected = [];
|
|
132
|
+
for (const entry of input) {
|
|
133
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
134
|
+
rejected.push({ reason: "malformed", label: String(entry) });
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const record = entry;
|
|
138
|
+
const cssVar = readString(record, "cssVar");
|
|
139
|
+
const value = readString(record, "value");
|
|
140
|
+
const name = readString(record, "name") || friendlyTokenName(cssVar);
|
|
141
|
+
if (!cssVar || !isSafeCssVarName(cssVar)) {
|
|
142
|
+
rejected.push({ reason: "unsafe-css-var", label: cssVar || name });
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (!isSafeCssTokenValue(value)) {
|
|
146
|
+
rejected.push({ reason: "unsafe-value", label: cssVar });
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const declaredType = readString(record, "type");
|
|
150
|
+
const group = readString(record, "group");
|
|
151
|
+
const source = readString(record, "source");
|
|
152
|
+
byCssVar.set(cssVar, {
|
|
153
|
+
name,
|
|
154
|
+
cssVar,
|
|
155
|
+
value,
|
|
156
|
+
type: BRAND_KIT_TOKEN_TYPES.includes(declaredType)
|
|
157
|
+
? declaredType
|
|
158
|
+
: classifyBrandKitToken(cssVar, value),
|
|
159
|
+
...(group ? { group } : {}),
|
|
160
|
+
...(source ? { source } : {}),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
const tokens = [...byCssVar.values()];
|
|
164
|
+
if (tokens.length > MAX_BRAND_KIT_TOKENS) {
|
|
165
|
+
for (const token of tokens.slice(MAX_BRAND_KIT_TOKENS)) {
|
|
166
|
+
rejected.push({ reason: "over-limit", label: token.cssVar });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return { tokens: tokens.slice(0, MAX_BRAND_KIT_TOKENS), rejected };
|
|
170
|
+
}
|
|
171
|
+
/** Human-readable summary of why tokens were refused, for thrown errors. */
|
|
172
|
+
export function describeBrandKitTokenRejections(rejected) {
|
|
173
|
+
return rejected
|
|
174
|
+
.slice(0, 10)
|
|
175
|
+
.map((entry) => `${entry.label} (${entry.reason})`)
|
|
176
|
+
.join(", ");
|
|
177
|
+
}
|
|
178
|
+
/** The CSS variable each colour role is published under. */
|
|
179
|
+
const BRAND_KIT_COLOR_ROLE_VARS = {
|
|
180
|
+
primary: "--color-primary",
|
|
181
|
+
secondary: "--color-secondary",
|
|
182
|
+
accent: "--color-accent",
|
|
183
|
+
background: "--color-background",
|
|
184
|
+
surface: "--color-surface",
|
|
185
|
+
text: "--color-text",
|
|
186
|
+
textMuted: "--color-text-muted",
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* The seven colour roles plus radius/spacing, as tokens. Derived from a kit's
|
|
190
|
+
* summary fields rather than named by the source system, so they carry no
|
|
191
|
+
* `group`.
|
|
192
|
+
*/
|
|
193
|
+
export function brandKitRoleTokens(data, source = "Brand Kit") {
|
|
194
|
+
if (!data)
|
|
195
|
+
return [];
|
|
196
|
+
const out = [];
|
|
197
|
+
const push = (cssVar, value) => {
|
|
198
|
+
if (typeof value !== "string" || !value.trim())
|
|
199
|
+
return;
|
|
200
|
+
if (!isSafeCssVarName(cssVar) || !isSafeCssTokenValue(value.trim()))
|
|
201
|
+
return;
|
|
202
|
+
out.push({
|
|
203
|
+
name: friendlyTokenName(cssVar),
|
|
204
|
+
cssVar,
|
|
205
|
+
value: value.trim(),
|
|
206
|
+
type: classifyBrandKitToken(cssVar, value.trim()),
|
|
207
|
+
source,
|
|
208
|
+
});
|
|
209
|
+
};
|
|
210
|
+
const colors = (data.colors ?? {});
|
|
211
|
+
const spacing = (data.spacing ?? {});
|
|
212
|
+
for (const [role, cssVar] of Object.entries(BRAND_KIT_COLOR_ROLE_VARS)) {
|
|
213
|
+
push(cssVar, colors[role]);
|
|
214
|
+
}
|
|
215
|
+
push("--radius", data.borders?.radius);
|
|
216
|
+
push("--spacing-element-gap", spacing.elementGap);
|
|
217
|
+
push("--spacing-page-padding", spacing.pagePadding);
|
|
218
|
+
return out;
|
|
219
|
+
}
|
|
220
|
+
const CSS_CUSTOM_PROPERTY_DECLARATION = /(--[-_a-zA-Z0-9]+)\s*:\s*([^;{}]+)[;}]/g;
|
|
221
|
+
/**
|
|
222
|
+
* Read a kit's named tokens out of a raw CSS block. A kit's `customCSS` already
|
|
223
|
+
* spells out the source system's real token names. Declaration order wins on
|
|
224
|
+
* duplicates, matching the cascade.
|
|
225
|
+
*/
|
|
226
|
+
export function parseBrandKitTokensFromCss(css, source) {
|
|
227
|
+
const byCssVar = new Map();
|
|
228
|
+
for (const match of css.matchAll(CSS_CUSTOM_PROPERTY_DECLARATION)) {
|
|
229
|
+
const cssVar = match[1];
|
|
230
|
+
const value = match[2].trim();
|
|
231
|
+
if (!isSafeCssVarName(cssVar) || !isSafeCssTokenValue(value))
|
|
232
|
+
continue;
|
|
233
|
+
byCssVar.set(cssVar, {
|
|
234
|
+
name: cssVar.replace(/^--/, ""),
|
|
235
|
+
cssVar,
|
|
236
|
+
value,
|
|
237
|
+
type: classifyBrandKitToken(cssVar, value),
|
|
238
|
+
...(source ? { source } : {}),
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
return [...byCssVar.values()].slice(0, MAX_BRAND_KIT_TOKENS);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* The kit's named vocabulary: its stored `tokens` when it has them, else the
|
|
245
|
+
* names its `customCSS` declares. Kits predating `tokens` still carry real names
|
|
246
|
+
* in CSS, so reading only `tokens` would report them as having none.
|
|
247
|
+
*/
|
|
248
|
+
export function resolveBrandKitTokens(data, cssSource) {
|
|
249
|
+
if (!data)
|
|
250
|
+
return [];
|
|
251
|
+
const stored = normalizeBrandKitTokens(data.tokens).tokens;
|
|
252
|
+
if (stored.length > 0)
|
|
253
|
+
return stored;
|
|
254
|
+
return typeof data.customCSS === "string"
|
|
255
|
+
? parseBrandKitTokensFromCss(data.customCSS, cssSource)
|
|
256
|
+
: [];
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Group tokens for display, preserving the source's collection paths. Groups sort
|
|
260
|
+
* by token type so colors lead, then alphabetically within a type.
|
|
261
|
+
*/
|
|
262
|
+
export function groupBrandKitTokens(tokens) {
|
|
263
|
+
const groups = new Map();
|
|
264
|
+
for (const token of tokens) {
|
|
265
|
+
const label = token.group?.trim() || token.type;
|
|
266
|
+
const key = `${token.type}::${label}`;
|
|
267
|
+
const existing = groups.get(key);
|
|
268
|
+
if (existing) {
|
|
269
|
+
existing.tokens.push(token);
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
groups.set(key, { label, type: token.type, tokens: [token] });
|
|
273
|
+
}
|
|
274
|
+
return [...groups.values()].sort((a, b) => {
|
|
275
|
+
const byType = BRAND_KIT_TOKEN_TYPES.indexOf(a.type) -
|
|
276
|
+
BRAND_KIT_TOKEN_TYPES.indexOf(b.type);
|
|
277
|
+
return byType !== 0 ? byType : a.label.localeCompare(b.label);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
@@ -23,6 +23,25 @@ export interface BrandKitColors {
|
|
|
23
23
|
text: string;
|
|
24
24
|
textMuted: string;
|
|
25
25
|
}
|
|
26
|
+
/** Semantic category a {@link BrandKitToken} belongs to. */
|
|
27
|
+
export type BrandKitTokenType = "color" | "typography" | "spacing" | "radius" | "shadow" | "other";
|
|
28
|
+
/**
|
|
29
|
+
* One token under the name its source design system uses. The seven
|
|
30
|
+
* {@link BrandKitColors} roles are a summary view, not a substitute: collapsing
|
|
31
|
+
* `interactive-01` into `secondary` discards the only name the design team has.
|
|
32
|
+
*/
|
|
33
|
+
export interface BrandKitToken {
|
|
34
|
+
name: string;
|
|
35
|
+
/** e.g. `--cds-interactive-01`. */
|
|
36
|
+
cssVar: string;
|
|
37
|
+
/** Resolved value, e.g. a hex color or `0.5rem`. */
|
|
38
|
+
value: string;
|
|
39
|
+
type: BrandKitTokenType;
|
|
40
|
+
/** Collection path as the source organises it, e.g. `Colors/Interactive`. */
|
|
41
|
+
group?: string;
|
|
42
|
+
/** e.g. `Carbon v11` or `globals.css`. */
|
|
43
|
+
source?: string;
|
|
44
|
+
}
|
|
26
45
|
/** Brand typography system. */
|
|
27
46
|
export interface BrandKitTypography {
|
|
28
47
|
headingFont: string;
|
|
@@ -76,6 +95,12 @@ export interface BrandKitData {
|
|
|
76
95
|
spacing: BrandKitSpacing;
|
|
77
96
|
borders: BrandKitBorders;
|
|
78
97
|
logos: BrandKitLogo[];
|
|
98
|
+
/**
|
|
99
|
+
* The source system's full named vocabulary. Optional because kits predating
|
|
100
|
+
* it store only the role summary - absent means "never extracted", not "the
|
|
101
|
+
* system has none".
|
|
102
|
+
*/
|
|
103
|
+
tokens?: BrandKitToken[];
|
|
79
104
|
imageStyle?: BrandKitImageStyle;
|
|
80
105
|
customCSS?: string;
|
|
81
106
|
notes?: string;
|
|
@@ -1440,16 +1440,16 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1440
1440
|
const agentEngineConfigured = useAgentEngineConfigured(providerStatusChecksEnabled, { tabId, threadId });
|
|
1441
1441
|
const modelCatalogMissing = modelCatalogConfirmsMissing(availableModels, modelListLoading);
|
|
1442
1442
|
// The model picker has already resolved the same provider status shown in
|
|
1443
|
-
// its setup choices.
|
|
1444
|
-
//
|
|
1445
|
-
// response always wins over a stale catalog.
|
|
1443
|
+
// its setup choices. Keep the signal available for the authoritative missing
|
|
1444
|
+
// state, but do not surface setup while the readiness request is unresolved.
|
|
1446
1445
|
const missingApiKey = agentEngineConfigured.state !== "configured" &&
|
|
1447
1446
|
(agentEngineConfigured.missing || modelCatalogMissing);
|
|
1448
|
-
// Unknown and unavailable
|
|
1449
|
-
//
|
|
1450
|
-
//
|
|
1447
|
+
// Unknown and unavailable mean we do not know yet. Only an authoritative
|
|
1448
|
+
// missing response may replace the composer with the setup card; otherwise
|
|
1449
|
+
// connected users briefly see a false "Connect AI" state on first mount.
|
|
1451
1450
|
const engineSetupRequired = providerStatusChecksEnabled &&
|
|
1452
|
-
|
|
1451
|
+
agentEngineConfigured.state === "missing" &&
|
|
1452
|
+
missingApiKey;
|
|
1453
1453
|
const isComposerDisabled = composerDisabled;
|
|
1454
1454
|
const [missingKeySetupOpen, setMissingKeySetupOpen] = useState(false);
|
|
1455
1455
|
const requestMissingKeySetup = useCallback(() => {
|
|
@@ -10,6 +10,7 @@ import { formatMcpServerError, useCreateMcpServer, useMcpServers, } from "../res
|
|
|
10
10
|
import { useBuilderConnectFlow } from "../settings/useBuilderStatus.js";
|
|
11
11
|
import { cn } from "../utils.js";
|
|
12
12
|
import { shouldSkipFirstRunIntegrations } from "./first-run-enabled.js";
|
|
13
|
+
import { listFirstRunOnboardingExtensions } from "./first-run-registry.js";
|
|
13
14
|
import { useOnboarding } from "./use-onboarding.js";
|
|
14
15
|
import { useOnboardingPreviewMode } from "./use-preview-mode.js";
|
|
15
16
|
const BUILDER_MORE_SERVICES = [
|
|
@@ -26,10 +27,12 @@ export function FirstRunOnboarding({ skipIntegrations = shouldSkipFirstRunIntegr
|
|
|
26
27
|
const previewMode = useOnboardingPreviewMode();
|
|
27
28
|
const { firstRun, loading, error, profile, completeFirstRun } = useOnboarding({ preview: previewMode });
|
|
28
29
|
const [screen, setScreen] = useState("intro");
|
|
30
|
+
const [extensionIndex, setExtensionIndex] = useState(0);
|
|
29
31
|
const [integrationQuery, setIntegrationQuery] = useState("");
|
|
30
32
|
const [integrationDialogId, setIntegrationDialogId] = useState(null);
|
|
31
33
|
const [connectingIntegrationId, setConnectingIntegrationId] = useState(null);
|
|
32
34
|
const [connectError, setConnectError] = useState(null);
|
|
35
|
+
const extensions = useMemo(() => listFirstRunOnboardingExtensions(), []);
|
|
33
36
|
const mcpCatalog = useMemo(() => getDefaultMcpIntegrations(), []);
|
|
34
37
|
const mcpServersQuery = useMcpServers();
|
|
35
38
|
const createMcpServer = useCreateMcpServer();
|
|
@@ -86,8 +89,13 @@ export function FirstRunOnboarding({ skipIntegrations = shouldSkipFirstRunIntegr
|
|
|
86
89
|
}));
|
|
87
90
|
await completeFirstRun();
|
|
88
91
|
};
|
|
89
|
-
const handleFinish =
|
|
90
|
-
|
|
92
|
+
const handleFinish = () => {
|
|
93
|
+
if (extensions.length === 0) {
|
|
94
|
+
void completeFirstRun();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
setExtensionIndex(0);
|
|
98
|
+
setScreen("extension");
|
|
91
99
|
};
|
|
92
100
|
const returnUrl = typeof window === "undefined"
|
|
93
101
|
? "/"
|
|
@@ -137,6 +145,22 @@ export function FirstRunOnboarding({ skipIntegrations = shouldSkipFirstRunIntegr
|
|
|
137
145
|
}
|
|
138
146
|
setIntegrationDialogId(integration.id);
|
|
139
147
|
};
|
|
148
|
+
if (screen === "extension") {
|
|
149
|
+
const extension = extensions[extensionIndex];
|
|
150
|
+
if (!extension) {
|
|
151
|
+
void completeFirstRun();
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
const Extension = extension.component;
|
|
155
|
+
const advanceExtension = () => {
|
|
156
|
+
if (extensionIndex < extensions.length - 1) {
|
|
157
|
+
setExtensionIndex((current) => current + 1);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
void completeFirstRun();
|
|
161
|
+
};
|
|
162
|
+
return (_jsx(Extension, { onComplete: advanceExtension, onSkip: () => void completeFirstRun() }));
|
|
163
|
+
}
|
|
140
164
|
if (screen === "intro") {
|
|
141
165
|
return (_jsx(OnboardingShell, { profile: profile, screen: "intro", children: _jsxs("div", { className: "mx-auto flex w-full max-w-lg flex-col items-center text-center", children: [_jsxs("h1", { className: "text-3xl font-semibold tracking-[-0.05em] sm:text-4xl", children: ["Free forever.", _jsx("br", {}), _jsx("span", { className: "text-primary", children: "Open source for life." })] }), _jsxs("div", { className: "mt-7 grid w-full gap-2 text-left sm:grid-cols-3", children: [_jsxs("div", { className: "rounded-lg border border-border bg-card px-3 py-3", children: [_jsx("p", { className: "text-xs font-medium", children: "Fully customizable" }), _jsx("p", { className: "mt-1 text-[11px] leading-4 text-muted-foreground", children: "Change the UI, code, and behavior." })] }), _jsxs("div", { className: "rounded-lg border border-border bg-card px-3 py-3", children: [_jsx("p", { className: "text-xs font-medium", children: "Bring your own keys" }), _jsx("p", { className: "mt-1 text-[11px] leading-4 text-muted-foreground", children: "Use your own providers and accounts." })] }), _jsxs("div", { className: "rounded-lg border border-border bg-card px-3 py-3", children: [_jsx("p", { className: "text-xs font-medium", children: "Build your own" }), _jsx("p", { className: "mt-1 text-[11px] leading-4 text-muted-foreground", children: "Mix and match toolkit pieces in your own apps." })] })] }), _jsxs("button", { type: "button", className: cn(primaryButtonClass, "mt-6"), onClick: () => setScreen("choice"), children: ["Continue", _jsx(IconArrowRight, { size: 15 })] }), _jsxs("a", { href: "https://github.com/builderio/agent-native", target: "_blank", rel: "noreferrer", className: "mt-3 inline-flex items-center gap-1.5 text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: [_jsx(IconBrandGithub, { size: 14 }), _jsx("span", { children: "View source" }), _jsx(IconExternalLink, { size: 13 })] })] }) }));
|
|
142
166
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ComponentType } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Props passed to an app-specific first-run onboarding step.
|
|
4
|
+
*
|
|
5
|
+
* Register one component per screen when an app needs a continuous, full-screen
|
|
6
|
+
* flow after the shared connection and agent-introduction screens.
|
|
7
|
+
*/
|
|
8
|
+
export interface FirstRunOnboardingExtensionProps {
|
|
9
|
+
/** Finish this step and open the next registered step, if any. */
|
|
10
|
+
onComplete: () => void;
|
|
11
|
+
/** Abort first-run onboarding without opening another app-specific step. */
|
|
12
|
+
onSkip: () => void;
|
|
13
|
+
}
|
|
14
|
+
/** A full-screen app step that follows the framework's connection setup. */
|
|
15
|
+
export interface FirstRunOnboardingExtension {
|
|
16
|
+
id: string;
|
|
17
|
+
component: ComponentType<FirstRunOnboardingExtensionProps>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Register the app-owned part of first-run onboarding. Registration is
|
|
21
|
+
* replaceable by id so Vite reloads do not stack duplicate screens.
|
|
22
|
+
*/
|
|
23
|
+
export declare function registerFirstRunOnboardingExtension(extension: FirstRunOnboardingExtension): void;
|
|
24
|
+
/** Return app-specific first-run screens in registration order. */
|
|
25
|
+
export declare function listFirstRunOnboardingExtensions(): readonly FirstRunOnboardingExtension[];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
let extensions = [];
|
|
2
|
+
/**
|
|
3
|
+
* Register the app-owned part of first-run onboarding. Registration is
|
|
4
|
+
* replaceable by id so Vite reloads do not stack duplicate screens.
|
|
5
|
+
*/
|
|
6
|
+
export function registerFirstRunOnboardingExtension(extension) {
|
|
7
|
+
if (!extension.id.trim()) {
|
|
8
|
+
throw new Error("registerFirstRunOnboardingExtension: extension.id is required");
|
|
9
|
+
}
|
|
10
|
+
extensions = [
|
|
11
|
+
...extensions.filter((current) => current.id !== extension.id),
|
|
12
|
+
extension,
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
/** Return app-specific first-run screens in registration order. */
|
|
16
|
+
export function listFirstRunOnboardingExtensions() {
|
|
17
|
+
return extensions;
|
|
18
|
+
}
|
|
@@ -9,5 +9,7 @@ export { OnboardingPanel } from "./OnboardingPanel.js";
|
|
|
9
9
|
export { OnboardingBanner } from "./OnboardingBanner.js";
|
|
10
10
|
export { SetupButton } from "./SetupButton.js";
|
|
11
11
|
export { FirstRunOnboarding } from "./FirstRunOnboarding.js";
|
|
12
|
+
export { listFirstRunOnboardingExtensions, registerFirstRunOnboardingExtension, } from "./first-run-registry.js";
|
|
13
|
+
export type { FirstRunOnboardingExtension, FirstRunOnboardingExtensionProps, } from "./first-run-registry.js";
|
|
12
14
|
export type { OnboardingStep, OnboardingMethod, OnboardingMethodBadge, OnboardingFormField, OnboardingStepStatus, OnboardingCapability, OnboardingAppProfile, } from "../../onboarding/types.js";
|
|
13
15
|
export { registerOnboardingStep, listOnboardingSteps, } from "../../onboarding/registry.js";
|
|
@@ -9,4 +9,5 @@ export { OnboardingPanel } from "./OnboardingPanel.js";
|
|
|
9
9
|
export { OnboardingBanner } from "./OnboardingBanner.js";
|
|
10
10
|
export { SetupButton } from "./SetupButton.js";
|
|
11
11
|
export { FirstRunOnboarding } from "./FirstRunOnboarding.js";
|
|
12
|
+
export { listFirstRunOnboardingExtensions, registerFirstRunOnboardingExtension, } from "./first-run-registry.js";
|
|
12
13
|
export { registerOnboardingStep, listOnboardingSteps, } from "../../onboarding/registry.js";
|
|
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
62
62
|
error: string;
|
|
63
63
|
states?: undefined;
|
|
64
64
|
} | {
|
|
65
|
-
error?: undefined;
|
|
66
65
|
states: {
|
|
67
66
|
clientId: number;
|
|
68
67
|
state: string;
|
|
69
68
|
}[];
|
|
69
|
+
error?: undefined;
|
|
70
70
|
}>>;
|
|
71
71
|
/**
|
|
72
72
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
77
77
|
error: string;
|
|
78
78
|
users?: undefined;
|
|
79
79
|
} | {
|
|
80
|
-
error?: undefined;
|
|
81
80
|
users: {
|
|
82
81
|
clientId: number;
|
|
83
82
|
lastSeen: number;
|
|
84
83
|
}[];
|
|
84
|
+
error?: undefined;
|
|
85
85
|
}>>;
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
error: string;
|
|
30
29
|
ok?: undefined;
|
|
30
|
+
error: string;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
error: string;
|
|
17
16
|
ok?: undefined;
|
|
17
|
+
error: string;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
package/dist/db/index.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export declare function createDb(config: DbConfig): Promise<(import("drizzle-orm
|
|
|
21
21
|
})>;
|
|
22
22
|
export type DrizzleDb = Awaited<ReturnType<typeof createDb>>;
|
|
23
23
|
export { createGetDb } from "./create-get-db.js";
|
|
24
|
-
export { runMigrations, type MigrationEntry, type MigrationSql, } from "./migrations.js";
|
|
24
|
+
export { deferMigration, MIGRATION_DEFERRED, runMigrations, type MigrationEntry, type MigrationRunResult, type MigrationSql, } from "./migrations.js";
|
|
25
25
|
export { getDbExec, createDbExec, getDatabaseUrl, getDialect, isLocalDatabase, isPostgres, intType, closeDbExec, type DbExec, type DbExecConfig, type DbExecQuery, type DbExecStatement, type Dialect, } from "./client.js";
|
|
26
26
|
export { table, text, integer, now } from "./schema.js";
|
|
27
27
|
export { ensureAdditiveColumns, type EnsureAdditiveColumnsOptions, type EnsureAdditiveColumnsResult, type EnsureAdditiveColumnsLogger, } from "./ensure-additive-columns.js";
|
package/dist/db/index.js
CHANGED
|
@@ -20,7 +20,7 @@ export async function createDb(config) {
|
|
|
20
20
|
throw new Error(`Unsupported driver: ${config.driver}`);
|
|
21
21
|
}
|
|
22
22
|
export { createGetDb } from "./create-get-db.js";
|
|
23
|
-
export { runMigrations, } from "./migrations.js";
|
|
23
|
+
export { deferMigration, MIGRATION_DEFERRED, runMigrations, } from "./migrations.js";
|
|
24
24
|
export { getDbExec, createDbExec, getDatabaseUrl, getDialect, isLocalDatabase, isPostgres, intType, closeDbExec, } from "./client.js";
|
|
25
25
|
export { table, text, integer, now } from "./schema.js";
|
|
26
26
|
export { ensureAdditiveColumns, } from "./ensure-additive-columns.js";
|
package/dist/db/migrations.d.ts
CHANGED
|
@@ -53,6 +53,14 @@ export type MigrationSql = string | {
|
|
|
53
53
|
postgres?: string;
|
|
54
54
|
sqlite?: string;
|
|
55
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* A run-only migration can defer its work without recording itself as applied.
|
|
58
|
+
* This is for serialized backfills where another instance owns the advisory
|
|
59
|
+
* lock; throwing would turn an expected loser into a startup retry storm.
|
|
60
|
+
*/
|
|
61
|
+
export declare const MIGRATION_DEFERRED: unique symbol;
|
|
62
|
+
export declare function deferMigration(): typeof MIGRATION_DEFERRED;
|
|
63
|
+
export type MigrationRunResult = void | typeof MIGRATION_DEFERRED;
|
|
56
64
|
export interface MigrationEntry {
|
|
57
65
|
version: number;
|
|
58
66
|
sql: MigrationSql;
|
|
@@ -68,11 +76,13 @@ export interface MigrationEntry {
|
|
|
68
76
|
* JS step for a backfill SQL cannot express — e.g. a repair whose value comes
|
|
69
77
|
* from application-level parsing of a stored blob. Runs BEFORE this entry's
|
|
70
78
|
* SQL and before the bookkeeping row is written, so a throw leaves the
|
|
71
|
-
* migration unrecorded and it retries on the next boot.
|
|
72
|
-
*
|
|
79
|
+
* migration unrecorded and it retries on the next boot. Return
|
|
80
|
+
* `deferMigration()` when another instance owns a serialized backfill; the
|
|
81
|
+
* entry stays pending without logging a startup failure. Pass `sql: {}` for
|
|
82
|
+
* a run-only entry. Give run-only entries a `name`: the legacy version gate
|
|
73
83
|
* would otherwise mark them applied via any later migration's MAX advance.
|
|
74
84
|
*/
|
|
75
|
-
run?: () => Promise<
|
|
85
|
+
run?: () => Promise<MigrationRunResult>;
|
|
76
86
|
}
|
|
77
87
|
/**
|
|
78
88
|
* Runs a list of migrations against the configured database, gated by a
|