@widgetic/creator 0.3.49
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/README.md +116 -0
- package/dist/CreatorApp.svelte +11821 -0
- package/dist/CreatorApp.svelte.d.ts +41 -0
- package/dist/components/EditableName.svelte +94 -0
- package/dist/components/EditableName.svelte.d.ts +27 -0
- package/dist/components/SelectorDropdown.svelte +238 -0
- package/dist/components/SelectorDropdown.svelte.d.ts +41 -0
- package/dist/components/WidgetDetails.svelte +3127 -0
- package/dist/components/WidgetDetails.svelte.d.ts +235 -0
- package/dist/components/index.d.ts +0 -0
- package/dist/components/index.js +4 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/creator-types.d.ts +64 -0
- package/dist/creator-types.js +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- package/dist/localCacheGate.d.ts +7 -0
- package/dist/localCacheGate.js +29 -0
- package/dist/pageHelpers.d.ts +15 -0
- package/dist/pageHelpers.js +194 -0
- package/dist/stores/userSession.d.ts +7 -0
- package/dist/stores/userSession.js +32 -0
- package/dist/stores/websocketStore.d.ts +53 -0
- package/dist/stores/websocketStore.js +289 -0
- package/dist/syncSiteAuth.d.ts +9 -0
- package/dist/syncSiteAuth.js +53 -0
- package/dist/utils/creatorDraftStorage.d.ts +17 -0
- package/dist/utils/creatorDraftStorage.js +87 -0
- package/dist/utils/embedCode.d.ts +51 -0
- package/dist/utils/embedCode.js +69 -0
- package/dist/utils/models.d.ts +4 -0
- package/dist/utils/models.js +94 -0
- package/dist/utils/operationStream.d.ts +29 -0
- package/dist/utils/operationStream.js +116 -0
- package/dist/utils/prototypes.d.ts +0 -0
- package/dist/utils/prototypes.js +20 -0
- package/dist/utils/widgeticChatUpload.d.ts +26 -0
- package/dist/utils/widgeticChatUpload.js +148 -0
- package/dist/utils.d.ts +11 -0
- package/dist/utils.js +38 -0
- package/package.json +124 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { AgentApi } from '@widgetic/api-sdk';
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: Props & {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
declare const WidgetDetails: $$__sveltets_2_IsomorphicComponent<{
|
|
16
|
+
userSession?: {
|
|
17
|
+
jwt?: string;
|
|
18
|
+
user?: {
|
|
19
|
+
id?: string;
|
|
20
|
+
};
|
|
21
|
+
} | null;
|
|
22
|
+
hasValidToken?: boolean;
|
|
23
|
+
selectedWidgetId?: string | null;
|
|
24
|
+
selectedWidget?: {
|
|
25
|
+
[extra: string]: unknown;
|
|
26
|
+
id?: string;
|
|
27
|
+
created_at?: string | Date;
|
|
28
|
+
createdAt?: string | Date;
|
|
29
|
+
updated_at?: string | Date;
|
|
30
|
+
updatedAt?: string | Date;
|
|
31
|
+
repositoryId?: string | null;
|
|
32
|
+
repository_id?: string | null;
|
|
33
|
+
repoId?: string | null;
|
|
34
|
+
name?: string;
|
|
35
|
+
lastCpgCommitSha?: string | null;
|
|
36
|
+
} | null;
|
|
37
|
+
isGeneratingCode?: boolean;
|
|
38
|
+
skipBasePreview?: boolean;
|
|
39
|
+
/** 'pending' = repo being created (show loader); 'failed' = show Create Repository; 'ready' = normal. */ repositorySetupStatus?: "pending" | "ready" | "failed";
|
|
40
|
+
generateCodeStatus?: string | null;
|
|
41
|
+
isCheckingActiveGeneration?: boolean;
|
|
42
|
+
lastCommitId?: string | null;
|
|
43
|
+
debugMode?: boolean;
|
|
44
|
+
forceMockReady?: boolean;
|
|
45
|
+
debugModeAvailable?: boolean;
|
|
46
|
+
lastGenerationFailed?: boolean;
|
|
47
|
+
lastGenerationError?: string | null;
|
|
48
|
+
saveStatus?: "idle" | "saving" | "saved" | "error";
|
|
49
|
+
hasChangesToSave?: boolean;
|
|
50
|
+
isSaveDisabled?: boolean;
|
|
51
|
+
isGenerateDisabled?: boolean;
|
|
52
|
+
isPublishDisabled?: boolean;
|
|
53
|
+
isPublishing?: boolean;
|
|
54
|
+
publishWidgetStatus?: string | null;
|
|
55
|
+
publishNeedsSaveFirst?: boolean;
|
|
56
|
+
lastPublishedVersion?: number | null;
|
|
57
|
+
widgetJsPath?: string | null;
|
|
58
|
+
isGeneratingInOtherTab?: boolean;
|
|
59
|
+
isPublishingInOtherTab?: boolean;
|
|
60
|
+
isSettingLiveVersion?: number | null;
|
|
61
|
+
isHistoryOpen?: boolean;
|
|
62
|
+
isLoadingHistory?: boolean;
|
|
63
|
+
publishHistory?: any[];
|
|
64
|
+
agentClient: AgentApi;
|
|
65
|
+
codeGenerationPrompt?: string;
|
|
66
|
+
promptImages?: string[];
|
|
67
|
+
imageInputRef?: HTMLInputElement | null;
|
|
68
|
+
isDraggingImage?: boolean;
|
|
69
|
+
MAX_PROMPT_IMAGES?: number;
|
|
70
|
+
selectedModel?: {
|
|
71
|
+
id: string;
|
|
72
|
+
name: string;
|
|
73
|
+
provider: string;
|
|
74
|
+
description: string;
|
|
75
|
+
} | null;
|
|
76
|
+
availableModels?: {
|
|
77
|
+
id: string;
|
|
78
|
+
name: string;
|
|
79
|
+
provider: string;
|
|
80
|
+
description: string;
|
|
81
|
+
}[];
|
|
82
|
+
userSelectedModelId?: string;
|
|
83
|
+
modelsLoading?: boolean;
|
|
84
|
+
/** Published widget URL for Embed step (may include compositionId). Set by parent. */ embedPreviewUrl?: string | null;
|
|
85
|
+
/** Published widget base URL for Edit step when live matches latest commit. Null → Worker preview. */ editPreviewUrl?: string | null;
|
|
86
|
+
/** True when generated code is ahead of the live published artifact. */ hasUnpublishedChanges?: boolean;
|
|
87
|
+
/** Host API root (embedded site passes PUBLIC_API_URL). Used for published artifact proxy URLs. */ apiUrl?: string | null;
|
|
88
|
+
/** Host Widget Builder origin (site PUBLIC_WIDGET_BUILDER_URL). */ widgetBuilderUrl?: string | null;
|
|
89
|
+
/**
|
|
90
|
+
* Viewport top inset for centering/clamping the floating panel (site header / creator top bar).
|
|
91
|
+
* Parent should pass the embedded-aware value; null keeps the legacy auth-panel estimate.
|
|
92
|
+
*/ panelTopOffset?: number | null;
|
|
93
|
+
/** Viewport bottom inset when sizing the default panel height. */ panelBottomMargin?: number | null;
|
|
94
|
+
/**
|
|
95
|
+
* When true (site embed), open the panel nearly full-viewport so Create/Edit
|
|
96
|
+
* chat + preview have room — not a narrow floating card over the canvas.
|
|
97
|
+
*/ fillViewport?: boolean;
|
|
98
|
+
/** Stacking order when multiple Widget Details panels are open. */ panelZIndex?: number;
|
|
99
|
+
/** Cascade offset index (0 = centered, 1+ = shifted down-right). */ panelCascadeIndex?: number;
|
|
100
|
+
/** False when another panel has keyboard/chat focus. */ isFocusedPanel?: boolean;
|
|
101
|
+
currentStep?: "create" | "edit" | "embed";
|
|
102
|
+
beginCompositionHydration?: () => void;
|
|
103
|
+
finishCompositionHydration?: () => void;
|
|
104
|
+
markCodegenPreviewFresh?: () => void;
|
|
105
|
+
hasLiveWorkerPreview?: () => boolean;
|
|
106
|
+
getLatestRuntimeLogs?: (maxLines?: number) => string[];
|
|
107
|
+
resumeDeferredPreviewLoad?: () => Promise<void>;
|
|
108
|
+
loadWidget?: (widgetId: string | null) => Promise<void>;
|
|
109
|
+
invalidatePublishedArtifactCache?: () => void;
|
|
110
|
+
refreshPreview?: (opts?: {
|
|
111
|
+
withRetry?: boolean;
|
|
112
|
+
skipIfAlreadyShowing?: boolean;
|
|
113
|
+
}) => Promise<void>;
|
|
114
|
+
triggerBuildFromRepo?: (options?: {
|
|
115
|
+
force?: boolean;
|
|
116
|
+
}) => Promise<void>;
|
|
117
|
+
enqueueAction?: (action: {
|
|
118
|
+
type: "generate";
|
|
119
|
+
prompt: string;
|
|
120
|
+
} | {
|
|
121
|
+
type: "save";
|
|
122
|
+
}) => void;
|
|
123
|
+
getShowWidgetDetails?: () => boolean;
|
|
124
|
+
getInlinePanelView?: () => "preview" | "console" | null;
|
|
125
|
+
setInlinePanelView?: (view: "preview" | "console" | null) => void;
|
|
126
|
+
hasValidPreview?: () => boolean;
|
|
127
|
+
getPreviewIframe?: () => HTMLIFrameElement | null;
|
|
128
|
+
getCurrentRepositoryId?: () => string | null;
|
|
129
|
+
setCurrentRepositoryId?: (repoId: string | null) => void;
|
|
130
|
+
setDirectPreviewUrl?: (url: string | null) => void;
|
|
131
|
+
setIframeSrc?: (src: string | null) => void;
|
|
132
|
+
setPreviewHasRuntimeError?: (val: boolean) => void;
|
|
133
|
+
setPreviewRuntimeErrorStatus?: (val: number | null) => void;
|
|
134
|
+
setHasAutoOpenedPreview?: (val: boolean) => void;
|
|
135
|
+
setPreviewLoadingState?: (val: boolean) => void;
|
|
136
|
+
getPreviewError?: () => string | null;
|
|
137
|
+
setPreviewBuildError?: (message: string | null) => void;
|
|
138
|
+
showNoCodeYetState?: () => void;
|
|
139
|
+
startPreviewLoadingPublic?: () => void;
|
|
140
|
+
sendMessageToPreview?: (message: Record<string, unknown>) => void;
|
|
141
|
+
setPreviewDimensions?: (width: number, height: number) => void;
|
|
142
|
+
getPreviewDimensions?: () => {
|
|
143
|
+
width: number;
|
|
144
|
+
height: number;
|
|
145
|
+
};
|
|
146
|
+
setupPreviewFallbackTimeoutPublic?: () => void;
|
|
147
|
+
startTokenAutoRefreshPublic?: () => void;
|
|
148
|
+
fetchDirectPreviewUrlPublic?: () => Promise<string | null>;
|
|
149
|
+
centerDetailsPanel?: () => void;
|
|
150
|
+
openWidgetDetails?: () => void;
|
|
151
|
+
closeWidgetDetails?: (options?: {
|
|
152
|
+
silent?: boolean;
|
|
153
|
+
}) => void;
|
|
154
|
+
}, {
|
|
155
|
+
widgetRename: CustomEvent<any>;
|
|
156
|
+
fixErrors: CustomEvent<any>;
|
|
157
|
+
retryRepository: CustomEvent<any>;
|
|
158
|
+
generateNow: CustomEvent<any>;
|
|
159
|
+
fixCompileError: CustomEvent<any>;
|
|
160
|
+
stepChange: CustomEvent<any>;
|
|
161
|
+
previewLoaded: CustomEvent<any>;
|
|
162
|
+
buildFromRepoSuccess: CustomEvent<any>;
|
|
163
|
+
widgetReady: CustomEvent<any>;
|
|
164
|
+
widgetDataChanged: CustomEvent<any>;
|
|
165
|
+
buildFromRepoFailed: CustomEvent<any>;
|
|
166
|
+
previewCompileErrorChanged: CustomEvent<any>;
|
|
167
|
+
previewReady: CustomEvent<any>;
|
|
168
|
+
generateCode: CustomEvent<any>;
|
|
169
|
+
saveWidget: CustomEvent<any>;
|
|
170
|
+
widgetDetailsToggle: CustomEvent<any>;
|
|
171
|
+
focusPanel: CustomEvent<any>;
|
|
172
|
+
stateSync: CustomEvent<any>;
|
|
173
|
+
} & {
|
|
174
|
+
[evt: string]: CustomEvent<any>;
|
|
175
|
+
}, {
|
|
176
|
+
'code-generation': {};
|
|
177
|
+
'publish-widget': {};
|
|
178
|
+
'composition-editor': {};
|
|
179
|
+
'embed-section': {};
|
|
180
|
+
}, {
|
|
181
|
+
beginCompositionHydration: () => void;
|
|
182
|
+
finishCompositionHydration: () => void;
|
|
183
|
+
markCodegenPreviewFresh: () => void;
|
|
184
|
+
hasLiveWorkerPreview: () => boolean;
|
|
185
|
+
getLatestRuntimeLogs: (maxLines?: number) => string[];
|
|
186
|
+
resumeDeferredPreviewLoad: () => Promise<void>;
|
|
187
|
+
loadWidget: (widgetId: string | null) => Promise<void>;
|
|
188
|
+
invalidatePublishedArtifactCache: () => void;
|
|
189
|
+
refreshPreview: (opts?: {
|
|
190
|
+
withRetry?: boolean;
|
|
191
|
+
skipIfAlreadyShowing?: boolean;
|
|
192
|
+
}) => Promise<void>;
|
|
193
|
+
triggerBuildFromRepo: (options?: {
|
|
194
|
+
force?: boolean;
|
|
195
|
+
}) => Promise<void>;
|
|
196
|
+
enqueueAction: (action: {
|
|
197
|
+
type: "generate";
|
|
198
|
+
prompt: string;
|
|
199
|
+
} | {
|
|
200
|
+
type: "save";
|
|
201
|
+
}) => void;
|
|
202
|
+
getShowWidgetDetails: () => boolean;
|
|
203
|
+
getInlinePanelView: () => "preview" | "console" | null;
|
|
204
|
+
setInlinePanelView: (view: "preview" | "console" | null) => void;
|
|
205
|
+
hasValidPreview: () => boolean;
|
|
206
|
+
getPreviewIframe: () => HTMLIFrameElement | null;
|
|
207
|
+
getCurrentRepositoryId: () => string | null;
|
|
208
|
+
setCurrentRepositoryId: (repoId: string | null) => void;
|
|
209
|
+
setDirectPreviewUrl: (url: string | null) => void;
|
|
210
|
+
setIframeSrc: (src: string | null) => void;
|
|
211
|
+
setPreviewHasRuntimeError: (val: boolean) => void;
|
|
212
|
+
setPreviewRuntimeErrorStatus: (val: number | null) => void;
|
|
213
|
+
setHasAutoOpenedPreview: (val: boolean) => void;
|
|
214
|
+
setPreviewLoadingState: (val: boolean) => void;
|
|
215
|
+
getPreviewError: () => string | null;
|
|
216
|
+
setPreviewBuildError: (message: string | null) => void;
|
|
217
|
+
showNoCodeYetState: () => void;
|
|
218
|
+
startPreviewLoadingPublic: () => void;
|
|
219
|
+
sendMessageToPreview: (message: Record<string, unknown>) => void;
|
|
220
|
+
setPreviewDimensions: (width: number, height: number) => void;
|
|
221
|
+
getPreviewDimensions: () => {
|
|
222
|
+
width: number;
|
|
223
|
+
height: number;
|
|
224
|
+
};
|
|
225
|
+
setupPreviewFallbackTimeoutPublic: () => void;
|
|
226
|
+
startTokenAutoRefreshPublic: () => void;
|
|
227
|
+
fetchDirectPreviewUrlPublic: () => Promise<string | null>;
|
|
228
|
+
centerDetailsPanel: () => void;
|
|
229
|
+
openWidgetDetails: () => void;
|
|
230
|
+
closeWidgetDetails: (options?: {
|
|
231
|
+
silent?: boolean;
|
|
232
|
+
}) => void;
|
|
233
|
+
}, string>;
|
|
234
|
+
type WidgetDetails = InstanceType<typeof WidgetDetails>;
|
|
235
|
+
export default WidgetDetails;
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const maxCharsFromId = 12;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const maxCharsFromId = 12;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export interface CreatorAppProps {
|
|
2
|
+
canvasId?: string | null;
|
|
3
|
+
projectId?: string | null;
|
|
4
|
+
workspaceType?: 'personal' | 'organization';
|
|
5
|
+
organizationId?: string | null;
|
|
6
|
+
initialWidgetId?: string | null;
|
|
7
|
+
/** Select this composition when opening Edit step from site. */
|
|
8
|
+
initialCompositionId?: string | null;
|
|
9
|
+
/** Open Widget Details on this step when embedded from site (overrides auto step once). */
|
|
10
|
+
initialStep?: 'create' | 'edit' | 'embed';
|
|
11
|
+
/**
|
|
12
|
+
* Site "+ New widget": create an empty canvas + Untitled widget instead of
|
|
13
|
+
* restoring the last project canvas / selected widget.
|
|
14
|
+
*/
|
|
15
|
+
forceCreateNewWidget?: boolean;
|
|
16
|
+
/** When true, hides auth screen + top bar; syncs session from site localStorage */
|
|
17
|
+
embedded?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* API gateway origin for embedded hosts (e.g. site `PUBLIC_API_URL`).
|
|
20
|
+
* Without this, production creator dist falls back to SDK default `dev-api.widgetic.com`.
|
|
21
|
+
*/
|
|
22
|
+
apiUrl?: string | null;
|
|
23
|
+
/**
|
|
24
|
+
* Widget Builder Worker origin (e.g. site `PUBLIC_WIDGET_BUILDER_URL`).
|
|
25
|
+
* Used for preview probes / iframe when not going through the Vite same-origin proxy.
|
|
26
|
+
*/
|
|
27
|
+
widgetBuilderUrl?: string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Host-controlled debug UI (Planner/Coder dropdowns + toggle).
|
|
30
|
+
* When set, this prop is the source of truth — do not bake debug into creator-app.js.
|
|
31
|
+
* `true` = show debug UI and start ON. `false` = hide debug UI.
|
|
32
|
+
* Omit for standalone widget-creator (falls back to VITE_DEBUG_MODE / dev).
|
|
33
|
+
*/
|
|
34
|
+
initialDebugMode?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Host-controlled default coder model id (e.g. `deepseek-v4-flash`).
|
|
37
|
+
* Site reads its own env and passes this — no creator-app.js rebuild, no API-gateway default for the UI.
|
|
38
|
+
*/
|
|
39
|
+
defaultCoderModelId?: string | null;
|
|
40
|
+
/** Host-controlled default planner model id (e.g. `openai-gpt-5.5`). */
|
|
41
|
+
defaultPlannerModelId?: string | null;
|
|
42
|
+
/**
|
|
43
|
+
* Floating Widgets List panel (debug UI). Default true so standalone Creator
|
|
44
|
+
* still shows it when Debug is ON. Site passes false — My widgets lives in the host.
|
|
45
|
+
*/
|
|
46
|
+
showWidgetsList?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Opt-in Dexie L1 (`@widgetic/cache-layer`). Default false.
|
|
49
|
+
* Site `/canvas` and the standalone creator host pass true so drafts / canvas
|
|
50
|
+
* fallbacks persist per user. When false, setCacheOwner is never called.
|
|
51
|
+
*/
|
|
52
|
+
enableLocalCache?: boolean;
|
|
53
|
+
class?: string;
|
|
54
|
+
style?: string;
|
|
55
|
+
onPublishComplete?: (detail: {
|
|
56
|
+
widgetId: string;
|
|
57
|
+
version?: number;
|
|
58
|
+
}) => void;
|
|
59
|
+
onBack?: () => void;
|
|
60
|
+
onWidgetRenamed?: (detail: {
|
|
61
|
+
widgetId: string;
|
|
62
|
+
name: string;
|
|
63
|
+
}) => void;
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as CreatorApp } from './CreatorApp.svelte';
|
|
2
|
+
export { syncSessionFromSiteAuth } from './syncSiteAuth.js';
|
|
3
|
+
// Re-export so site hosts can mount the self-contained embed with the same
|
|
4
|
+
// Svelte runtime that compiled CreatorApp (avoid dual-runtime crashes).
|
|
5
|
+
export { mount, unmount } from 'svelte';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function setEnableLocalCache(enabled: boolean): void;
|
|
2
|
+
export declare function isLocalCacheEnabled(): boolean;
|
|
3
|
+
/** Scope L1 to user when enabled; otherwise clear owner (creator-owned bundle only). */
|
|
4
|
+
export declare function syncLocalCacheOwner(user: {
|
|
5
|
+
id?: string;
|
|
6
|
+
user_id?: string;
|
|
7
|
+
} | null | undefined): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { clearCacheOwner, setCacheOwner } from '@widgetic/cache-layer';
|
|
2
|
+
/**
|
|
3
|
+
* Gates Dexie L1 for the creator JS graph.
|
|
4
|
+
* Default off — host passes enableLocalCache={true} (site /canvas, standalone page).
|
|
5
|
+
*/
|
|
6
|
+
let enableLocalCache = false;
|
|
7
|
+
export function setEnableLocalCache(enabled) {
|
|
8
|
+
enableLocalCache = !!enabled;
|
|
9
|
+
if (!enableLocalCache) {
|
|
10
|
+
clearCacheOwner();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function isLocalCacheEnabled() {
|
|
14
|
+
return enableLocalCache;
|
|
15
|
+
}
|
|
16
|
+
/** Scope L1 to user when enabled; otherwise clear owner (creator-owned bundle only). */
|
|
17
|
+
export function syncLocalCacheOwner(user) {
|
|
18
|
+
if (!enableLocalCache) {
|
|
19
|
+
clearCacheOwner();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const ownerId = user?.id || user?.user_id || null;
|
|
23
|
+
if (ownerId) {
|
|
24
|
+
setCacheOwner(String(ownerId));
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
clearCacheOwner();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helper functions extracted from +page.svelte to reduce file size
|
|
3
|
+
* and prevent rollup AST recursion overflow during production builds.
|
|
4
|
+
*/
|
|
5
|
+
export declare function looksLikeHtmlErrorPage(raw: string | null | undefined): boolean;
|
|
6
|
+
/** Cloudflare Worker / gateway HTML dumps must never appear in chat, preview, or Edit. */
|
|
7
|
+
export declare function sanitizePreviewBuildError(raw: string | null | undefined): string;
|
|
8
|
+
export declare function isInfrastructurePreviewError(raw: string | null | undefined): boolean;
|
|
9
|
+
export declare function normalizeErrorMessage(rawError: string | Error | unknown): string;
|
|
10
|
+
export declare function toErrorMessage(error: unknown, fallback: string): string;
|
|
11
|
+
export declare function extractDetailsMessage(payload: unknown): string | null;
|
|
12
|
+
export declare function deriveApiErrorMessage(error: unknown, defaultMessage: string): Promise<string>;
|
|
13
|
+
export declare function decodeJWT(token: string): Record<string, unknown> | null;
|
|
14
|
+
export declare function isTokenExpired(token: string): boolean;
|
|
15
|
+
export declare function fileToBase64(file: File): Promise<string>;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helper functions extracted from +page.svelte to reduce file size
|
|
3
|
+
* and prevent rollup AST recursion overflow during production builds.
|
|
4
|
+
*/
|
|
5
|
+
import { ResponseError } from '@widgetic/api-sdk';
|
|
6
|
+
// ===================== Error Handling Helpers =====================
|
|
7
|
+
const HTML_ERROR_PAGE_RE = /^\s*(<!DOCTYPE\s+html|<html[\s>]|<!--\[if\s+lt\s+IE)/i;
|
|
8
|
+
const CLOUDFLARE_ERROR_PAGE_RE = /<title>\s*Page not found\s*<\/title>|workers\.cloudflare|error code:\s*1042/i;
|
|
9
|
+
export function looksLikeHtmlErrorPage(raw) {
|
|
10
|
+
if (!raw)
|
|
11
|
+
return false;
|
|
12
|
+
const text = raw.trim();
|
|
13
|
+
return text.length >= 12 && (HTML_ERROR_PAGE_RE.test(text) || CLOUDFLARE_ERROR_PAGE_RE.test(text));
|
|
14
|
+
}
|
|
15
|
+
/** Cloudflare Worker / gateway HTML dumps must never appear in chat, preview, or Edit. */
|
|
16
|
+
export function sanitizePreviewBuildError(raw) {
|
|
17
|
+
const text = typeof raw === 'string' ? raw.trim() : '';
|
|
18
|
+
if (!text)
|
|
19
|
+
return 'Preview build failed.';
|
|
20
|
+
if (/failed to fetch|fetch failed/i.test(text)) {
|
|
21
|
+
return 'Could not reach the preview builder. Try Rebuild.';
|
|
22
|
+
}
|
|
23
|
+
if (looksLikeHtmlErrorPage(text) || /error code:\s*1042/i.test(text)) {
|
|
24
|
+
return 'Preview builder is unavailable. The widget code was saved — use Rebuild to compile it.';
|
|
25
|
+
}
|
|
26
|
+
if (text.length > 240 && /<\/?[a-z][\s\S]*>/i.test(text)) {
|
|
27
|
+
return 'Preview builder returned an unexpected error page. Try Rebuild.';
|
|
28
|
+
}
|
|
29
|
+
return text.length > 400 ? `${text.slice(0, 400)}…` : text;
|
|
30
|
+
}
|
|
31
|
+
export function isInfrastructurePreviewError(raw) {
|
|
32
|
+
if (!raw)
|
|
33
|
+
return false;
|
|
34
|
+
if (looksLikeHtmlErrorPage(raw))
|
|
35
|
+
return true;
|
|
36
|
+
return /preview builder is unavailable|could not reach the preview builder|unexpected error page/i.test(sanitizePreviewBuildError(raw));
|
|
37
|
+
}
|
|
38
|
+
export function normalizeErrorMessage(rawError) {
|
|
39
|
+
let extracted = '';
|
|
40
|
+
if (typeof rawError === 'string') {
|
|
41
|
+
extracted = rawError;
|
|
42
|
+
}
|
|
43
|
+
else if (!rawError) {
|
|
44
|
+
extracted = 'An unknown error occurred.';
|
|
45
|
+
}
|
|
46
|
+
else if (rawError instanceof Error && rawError.message) {
|
|
47
|
+
extracted = rawError.message;
|
|
48
|
+
}
|
|
49
|
+
else if (typeof rawError === 'object') {
|
|
50
|
+
const maybeMessage = rawError.message ||
|
|
51
|
+
rawError.details;
|
|
52
|
+
if (maybeMessage && maybeMessage.trim().length > 0) {
|
|
53
|
+
extracted = maybeMessage;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
try {
|
|
57
|
+
extracted = JSON.stringify(rawError);
|
|
58
|
+
}
|
|
59
|
+
catch (jsonError) {
|
|
60
|
+
console.warn('Failed to stringify error payload for toast.', {
|
|
61
|
+
rawError,
|
|
62
|
+
err: jsonError
|
|
63
|
+
});
|
|
64
|
+
extracted = 'An unknown error occurred.';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
extracted = String(rawError);
|
|
70
|
+
}
|
|
71
|
+
if (looksLikeHtmlErrorPage(extracted) || /error code:\s*1042/i.test(extracted)) {
|
|
72
|
+
return sanitizePreviewBuildError(extracted);
|
|
73
|
+
}
|
|
74
|
+
if (/failed to fetch|fetch failed/i.test(extracted)) {
|
|
75
|
+
return 'Could not reach the server. Try again.';
|
|
76
|
+
}
|
|
77
|
+
if (extracted.length > 240 && /<\/?[a-z][\s\S]*>/i.test(extracted)) {
|
|
78
|
+
return sanitizePreviewBuildError(extracted);
|
|
79
|
+
}
|
|
80
|
+
return extracted.length > 400 ? `${extracted.slice(0, 400)}…` : extracted;
|
|
81
|
+
}
|
|
82
|
+
export function toErrorMessage(error, fallback) {
|
|
83
|
+
if (error instanceof Error && error.message) {
|
|
84
|
+
return looksLikeHtmlErrorPage(error.message)
|
|
85
|
+
? sanitizePreviewBuildError(error.message)
|
|
86
|
+
: error.message;
|
|
87
|
+
}
|
|
88
|
+
if (typeof error === 'string' && error.trim().length > 0) {
|
|
89
|
+
return looksLikeHtmlErrorPage(error) ? sanitizePreviewBuildError(error) : error;
|
|
90
|
+
}
|
|
91
|
+
return fallback;
|
|
92
|
+
}
|
|
93
|
+
export function extractDetailsMessage(payload) {
|
|
94
|
+
if (!payload) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
if (typeof payload === 'string') {
|
|
98
|
+
try {
|
|
99
|
+
const parsed = JSON.parse(payload);
|
|
100
|
+
return extractDetailsMessage(parsed);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return payload;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (Array.isArray(payload)) {
|
|
107
|
+
for (const item of payload) {
|
|
108
|
+
const message = extractDetailsMessage(item);
|
|
109
|
+
if (message) {
|
|
110
|
+
return message;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
if (typeof payload === 'object') {
|
|
116
|
+
const candidate = payload;
|
|
117
|
+
if (candidate.message && typeof candidate.message === 'string') {
|
|
118
|
+
return candidate.message;
|
|
119
|
+
}
|
|
120
|
+
if (candidate.error) {
|
|
121
|
+
return extractDetailsMessage(candidate.error);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
export async function deriveApiErrorMessage(error, defaultMessage) {
|
|
127
|
+
const response = error instanceof ResponseError
|
|
128
|
+
? error.response
|
|
129
|
+
: error?.response;
|
|
130
|
+
if (response) {
|
|
131
|
+
try {
|
|
132
|
+
const cloned = response.clone();
|
|
133
|
+
const payload = await cloned.json();
|
|
134
|
+
const derived = extractDetailsMessage(payload?.error ?? payload);
|
|
135
|
+
if (derived) {
|
|
136
|
+
return derived;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// ignore JSON parsing issues
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return toErrorMessage(error, defaultMessage);
|
|
144
|
+
}
|
|
145
|
+
// ===================== JWT Helpers =====================
|
|
146
|
+
export function decodeJWT(token) {
|
|
147
|
+
try {
|
|
148
|
+
const parts = token.split('.');
|
|
149
|
+
if (parts.length !== 3) {
|
|
150
|
+
throw new Error(`Invalid JWT format: expected 3 parts, got ${parts.length}`);
|
|
151
|
+
}
|
|
152
|
+
// Verify header parses
|
|
153
|
+
const header = parts[0];
|
|
154
|
+
const paddedHeader = header + '='.repeat((4 - (header.length % 4)) % 4);
|
|
155
|
+
JSON.parse(atob(paddedHeader));
|
|
156
|
+
// Decode payload
|
|
157
|
+
const payload = parts[1];
|
|
158
|
+
const paddedPayload = payload + '='.repeat((4 - (payload.length % 4)) % 4);
|
|
159
|
+
const decodedPayloadString = atob(paddedPayload);
|
|
160
|
+
if (!decodedPayloadString || decodedPayloadString.trim() === '') {
|
|
161
|
+
throw new Error('Empty payload in JWT');
|
|
162
|
+
}
|
|
163
|
+
return JSON.parse(decodedPayloadString);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
console.error('Failed to decode JWT:', error);
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
export function isTokenExpired(token) {
|
|
171
|
+
try {
|
|
172
|
+
const decoded = decodeJWT(token);
|
|
173
|
+
if (!decoded || !decoded.exp) {
|
|
174
|
+
console.warn('Token has no expiration field, considering it expired');
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
const currentTime = Math.floor(Date.now() / 1000);
|
|
178
|
+
return decoded.exp < currentTime;
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
console.error('Error checking token expiration:', error);
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// ===================== File/Image Helpers =====================
|
|
186
|
+
export async function fileToBase64(file) {
|
|
187
|
+
return new Promise((resolve, reject) => {
|
|
188
|
+
const reader = new FileReader();
|
|
189
|
+
reader.onload = () => resolve(reader.result);
|
|
190
|
+
reader.onerror = reject;
|
|
191
|
+
reader.readAsDataURL(file);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
// VM Session Helpers removed — VM infrastructure decommissioned
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { writable } from 'svelte/store';
|
|
2
|
+
import { syncLocalCacheOwner } from '../localCacheGate.js';
|
|
3
|
+
export const userSession = writable({
|
|
4
|
+
user: null,
|
|
5
|
+
jwt: null
|
|
6
|
+
});
|
|
7
|
+
export function setSession(user, jwt) {
|
|
8
|
+
userSession.set({ user, jwt });
|
|
9
|
+
if (jwt)
|
|
10
|
+
localStorage.setItem('jwt', jwt);
|
|
11
|
+
if (user)
|
|
12
|
+
localStorage.setItem('user', JSON.stringify(user));
|
|
13
|
+
syncLocalCacheOwner(user);
|
|
14
|
+
}
|
|
15
|
+
export function clearSession() {
|
|
16
|
+
userSession.set({ user: null, jwt: null });
|
|
17
|
+
localStorage.removeItem('jwt');
|
|
18
|
+
localStorage.removeItem('user');
|
|
19
|
+
syncLocalCacheOwner(null);
|
|
20
|
+
}
|
|
21
|
+
export function restoreSession() {
|
|
22
|
+
const jwt = localStorage.getItem('jwt');
|
|
23
|
+
const userStr = localStorage.getItem('user');
|
|
24
|
+
let user = null;
|
|
25
|
+
try {
|
|
26
|
+
if (userStr)
|
|
27
|
+
user = JSON.parse(userStr);
|
|
28
|
+
}
|
|
29
|
+
catch { }
|
|
30
|
+
userSession.set({ user, jwt });
|
|
31
|
+
syncLocalCacheOwner(user);
|
|
32
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export interface DynamicWorkerPreviewStatus {
|
|
2
|
+
widgetId: string | null;
|
|
3
|
+
previewUrl: string | null;
|
|
4
|
+
buildTimeMs: number | null;
|
|
5
|
+
timestamp: string | null;
|
|
6
|
+
}
|
|
7
|
+
export interface WidgetPublishStatus {
|
|
8
|
+
widgetId: string | null;
|
|
9
|
+
status: 'success' | 'failure' | 'building' | null;
|
|
10
|
+
version?: number;
|
|
11
|
+
artifactUrl?: string;
|
|
12
|
+
message?: string;
|
|
13
|
+
error?: {
|
|
14
|
+
code?: string;
|
|
15
|
+
details?: string;
|
|
16
|
+
};
|
|
17
|
+
timestamp: string | null;
|
|
18
|
+
}
|
|
19
|
+
export interface CodeGenerationStatus {
|
|
20
|
+
operationId: string | null;
|
|
21
|
+
status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | null;
|
|
22
|
+
previousStatus: string | null;
|
|
23
|
+
progress: number;
|
|
24
|
+
error: string | null;
|
|
25
|
+
timestamp: string | null;
|
|
26
|
+
}
|
|
27
|
+
/** Agent harness repair lines pushed during codegen (vmConsole:aiderOutput). */
|
|
28
|
+
export interface AgentHarnessOutput {
|
|
29
|
+
output: string;
|
|
30
|
+
timestamp: string;
|
|
31
|
+
}
|
|
32
|
+
interface ConnectionState {
|
|
33
|
+
connected: boolean;
|
|
34
|
+
joinedRooms: string[];
|
|
35
|
+
error: string | null;
|
|
36
|
+
}
|
|
37
|
+
export declare const connectionState: import("svelte/store").Writable<ConnectionState>;
|
|
38
|
+
export declare const dynamicWorkerPreviewStatus: import("svelte/store").Writable<DynamicWorkerPreviewStatus>;
|
|
39
|
+
export declare const widgetPublishStatus: import("svelte/store").Writable<WidgetPublishStatus>;
|
|
40
|
+
export declare const codeGenerationStatus: import("svelte/store").Writable<CodeGenerationStatus>;
|
|
41
|
+
export declare const agentHarnessOutput: import("svelte/store").Writable<AgentHarnessOutput>;
|
|
42
|
+
export declare function setAuthToken(token: string | null): void;
|
|
43
|
+
/** Prefer host-provided API URL so embedded creator does not socket.io to localhost:3000. */
|
|
44
|
+
export declare function setWebsocketApiUrl(apiUrl: string | null | undefined): void;
|
|
45
|
+
/**
|
|
46
|
+
* Connect to WebSocket and join user room for receiving events.
|
|
47
|
+
*/
|
|
48
|
+
export declare function connectWebSocket(userId?: string): Promise<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* Disconnect from WebSocket.
|
|
51
|
+
*/
|
|
52
|
+
export declare function disconnectWebSocket(): Promise<void>;
|
|
53
|
+
export {};
|