@aprovan/patchwork-compiler 0.1.0 → 0.1.2-dev.03aaf5b

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.
@@ -0,0 +1,828 @@
1
+ import { z } from 'zod';
2
+ import { Plugin } from 'esbuild-wasm';
3
+
4
+ interface VirtualFile {
5
+ path: string;
6
+ content: string;
7
+ language?: string;
8
+ note?: string;
9
+ encoding?: "utf8" | "base64";
10
+ }
11
+ interface VirtualProject {
12
+ id: string;
13
+ entry: string;
14
+ files: Map<string, VirtualFile>;
15
+ }
16
+
17
+ /**
18
+ * Core types for the Patchwork compiler
19
+ */
20
+ type Platform = 'browser' | 'cli';
21
+ interface Manifest$1 {
22
+ name: string;
23
+ version: string;
24
+ description?: string;
25
+ platform: Platform;
26
+ image: string;
27
+ inputs?: Record<string, InputSpec>;
28
+ services?: string[];
29
+ packages?: Record<string, string>;
30
+ }
31
+ interface InputSpec {
32
+ type: 'string' | 'number' | 'boolean' | 'object' | 'array';
33
+ default?: unknown;
34
+ required?: boolean;
35
+ description?: string;
36
+ }
37
+ interface CompileOptions {
38
+ }
39
+ interface CompiledWidget {
40
+ /** Compiled ESM code */
41
+ code: string;
42
+ /** Content hash for caching */
43
+ hash: string;
44
+ /** Original manifest */
45
+ manifest: Manifest$1;
46
+ /** Source map (if generated) */
47
+ sourceMap?: string;
48
+ }
49
+ type MountMode = 'embedded' | 'iframe';
50
+ interface MountOptions {
51
+ /** Target DOM element to mount into */
52
+ target: HTMLElement;
53
+ /** Mount mode: embedded (trusted) or iframe (sandboxed) */
54
+ mode: MountMode;
55
+ /** CSP sandbox attributes for iframe mode */
56
+ sandbox?: string[];
57
+ /** Initial props/inputs to pass to widget */
58
+ inputs?: Record<string, unknown>;
59
+ }
60
+ interface MountedWidget {
61
+ /** Unique mount ID */
62
+ id: string;
63
+ /** The compiled widget */
64
+ widget: CompiledWidget;
65
+ /** Mount mode used */
66
+ mode: MountMode;
67
+ /** Target element */
68
+ target: HTMLElement;
69
+ /** Iframe element (if mode is 'iframe') */
70
+ iframe?: HTMLIFrameElement;
71
+ /** Inputs used for the mount (if provided) */
72
+ inputs?: Record<string, unknown>;
73
+ /** Sandbox attributes used for iframe mode (if provided) */
74
+ sandbox?: string[];
75
+ /** Unmount function */
76
+ unmount: () => void;
77
+ }
78
+ interface ImageConfig$1 {
79
+ platform: Platform;
80
+ esbuild?: {
81
+ target?: string;
82
+ format?: 'esm' | 'cjs' | 'iife';
83
+ jsx?: 'automatic' | 'transform' | 'preserve';
84
+ jsxFactory?: string;
85
+ jsxFragment?: string;
86
+ };
87
+ framework?: {
88
+ /** Map of package names to window global names (e.g., { react: 'React' }) */
89
+ globals?: Record<string, string>;
90
+ /** CDN URLs to preload before widget execution */
91
+ preload?: string[];
92
+ /** Dependency version overrides for CDN packages (e.g., { react: '18' }) */
93
+ deps?: Record<string, string>;
94
+ };
95
+ /** Import path aliases (e.g., { '@/components/ui/*': '@packagedcn/react' }) */
96
+ aliases?: Record<string, string>;
97
+ }
98
+ /**
99
+ * Mount function signature provided by images to handle widget mounting.
100
+ * Takes the widget module exports and mounts it to the container.
101
+ *
102
+ * @param module - The widget module with its exports (default, mount, render, game, etc.)
103
+ * @param container - The DOM element to mount into
104
+ * @param inputs - Props/inputs to pass to the widget
105
+ * @returns A cleanup function to unmount, or void
106
+ */
107
+ type ImageMountFn = (module: Record<string, unknown>, container: HTMLElement, inputs: Record<string, unknown>) => void | (() => void) | Promise<void | (() => void)>;
108
+ interface LoadedImage {
109
+ /** Package name */
110
+ name: string;
111
+ /** Resolved version */
112
+ version: string;
113
+ /** Browser-importable module URL for this image (when loaded from CDN/local HTTP) */
114
+ moduleUrl?: string;
115
+ /** Package configuration */
116
+ config: ImageConfig$1;
117
+ /** Package dependencies */
118
+ dependencies: Record<string, string>;
119
+ /** Setup function (if available) */
120
+ setup?: (root: HTMLElement) => void | Promise<void>;
121
+ /** CSS content (if available) */
122
+ css?: string;
123
+ /**
124
+ * Mount function to handle widget mounting.
125
+ * Each image defines how it expects widgets to export their entry points.
126
+ * Falls back to default mounting behavior if not provided.
127
+ */
128
+ mount?: ImageMountFn;
129
+ }
130
+ interface CompilerOptions {
131
+ /** Image package to use (e.g., '@aprovan/patchwork-image-shadcnshadcn') */
132
+ image: string;
133
+ /** Backend proxy URL for service calls */
134
+ proxyUrl: string;
135
+ /** Base URL for CDN (default: 'https://esm.sh'). Used for loading image packages. */
136
+ cdnBaseUrl?: string;
137
+ /** Base URL for widget imports (default: same as cdnBaseUrl). Used for transforming imports in widget code. */
138
+ widgetCdnBaseUrl?: string;
139
+ }
140
+ interface Compiler {
141
+ /** Pre-load an image package */
142
+ preloadImage(spec: string): Promise<void>;
143
+ /** Check if an image is loaded */
144
+ isImageLoaded(spec: string): boolean;
145
+ /** Compile widget source to ESM */
146
+ compile(source: string | VirtualProject, manifest: Manifest$1, options?: CompileOptions): Promise<CompiledWidget>;
147
+ /** Mount a compiled widget to the DOM */
148
+ mount(widget: CompiledWidget, options: MountOptions): Promise<MountedWidget>;
149
+ /** Unmount a mounted widget */
150
+ unmount(mounted: MountedWidget): void;
151
+ /** Hot reload a mounted widget */
152
+ reload(mounted: MountedWidget, source: string | VirtualProject, manifest: Manifest$1): Promise<void>;
153
+ }
154
+ /**
155
+ * Service proxy interface - abstracts service calls to backend
156
+ *
157
+ * The compiler provides the interface; actual implementation (e.g., UTCP, MCP)
158
+ * is handled by the runtime/backend.
159
+ */
160
+ interface ServiceProxy {
161
+ call(namespace: string, procedure: string, args: unknown[]): Promise<unknown>;
162
+ }
163
+ /**
164
+ * Service call handler - function that handles calls for a specific namespace
165
+ */
166
+ type ServiceCallHandler = (procedure: string, args: unknown[]) => Promise<unknown>;
167
+ /**
168
+ * Global interface definition for code generation
169
+ *
170
+ * Describes available global namespaces and their methods that widgets can call.
171
+ * Used during compilation to generate proper TypeScript declarations.
172
+ */
173
+ interface GlobalInterfaceDefinition {
174
+ /** Namespace name (e.g., 'git', 'github') */
175
+ name: string;
176
+ /** Methods available on this namespace (supports nested paths like 'repos.list') */
177
+ methods: string[];
178
+ /** Optional TypeScript type definitions for methods */
179
+ types?: string;
180
+ }
181
+ type BridgeMessageType = 'service-call' | 'service-result' | 'error';
182
+ interface BridgeMessage {
183
+ type: BridgeMessageType;
184
+ id: string;
185
+ payload: unknown;
186
+ }
187
+ interface ServiceCallPayload {
188
+ namespace: string;
189
+ procedure: string;
190
+ args: unknown[];
191
+ }
192
+ interface ServiceResultPayload {
193
+ result?: unknown;
194
+ error?: string;
195
+ }
196
+
197
+ /**
198
+ * Create a compiler instance
199
+ */
200
+ declare function createCompiler(options: CompilerOptions): Promise<Compiler>;
201
+
202
+ /**
203
+ * Zod schemas for Patchwork compiler types
204
+ *
205
+ * These schemas validate:
206
+ * - ImageConfig from package.json patchwork field
207
+ * - Widget manifests
208
+ * - Input specifications
209
+ */
210
+
211
+ declare const PlatformSchema: z.ZodEnum<["browser", "cli"]>;
212
+ declare const EsbuildConfigSchema: z.ZodOptional<z.ZodObject<{
213
+ target: z.ZodOptional<z.ZodString>;
214
+ format: z.ZodOptional<z.ZodEnum<["esm", "cjs", "iife"]>>;
215
+ jsx: z.ZodOptional<z.ZodEnum<["automatic", "transform", "preserve"]>>;
216
+ jsxFactory: z.ZodOptional<z.ZodString>;
217
+ jsxFragment: z.ZodOptional<z.ZodString>;
218
+ }, "strict", z.ZodTypeAny, {
219
+ jsx?: "automatic" | "transform" | "preserve" | undefined;
220
+ target?: string | undefined;
221
+ format?: "esm" | "cjs" | "iife" | undefined;
222
+ jsxFactory?: string | undefined;
223
+ jsxFragment?: string | undefined;
224
+ }, {
225
+ jsx?: "automatic" | "transform" | "preserve" | undefined;
226
+ target?: string | undefined;
227
+ format?: "esm" | "cjs" | "iife" | undefined;
228
+ jsxFactory?: string | undefined;
229
+ jsxFragment?: string | undefined;
230
+ }>>;
231
+ declare const ImageConfigSchema: z.ZodObject<{
232
+ platform: z.ZodEnum<["browser", "cli"]>;
233
+ dependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
234
+ esbuild: z.ZodOptional<z.ZodObject<{
235
+ target: z.ZodOptional<z.ZodString>;
236
+ format: z.ZodOptional<z.ZodEnum<["esm", "cjs", "iife"]>>;
237
+ jsx: z.ZodOptional<z.ZodEnum<["automatic", "transform", "preserve"]>>;
238
+ jsxFactory: z.ZodOptional<z.ZodString>;
239
+ jsxFragment: z.ZodOptional<z.ZodString>;
240
+ }, "strict", z.ZodTypeAny, {
241
+ jsx?: "automatic" | "transform" | "preserve" | undefined;
242
+ target?: string | undefined;
243
+ format?: "esm" | "cjs" | "iife" | undefined;
244
+ jsxFactory?: string | undefined;
245
+ jsxFragment?: string | undefined;
246
+ }, {
247
+ jsx?: "automatic" | "transform" | "preserve" | undefined;
248
+ target?: string | undefined;
249
+ format?: "esm" | "cjs" | "iife" | undefined;
250
+ jsxFactory?: string | undefined;
251
+ jsxFragment?: string | undefined;
252
+ }>>;
253
+ framework: z.ZodOptional<z.ZodObject<{
254
+ globals: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
255
+ preload: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
256
+ deps: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
257
+ }, "strict", z.ZodTypeAny, {
258
+ globals?: Record<string, string> | undefined;
259
+ preload?: string[] | undefined;
260
+ deps?: Record<string, string> | undefined;
261
+ }, {
262
+ globals?: Record<string, string> | undefined;
263
+ preload?: string[] | undefined;
264
+ deps?: Record<string, string> | undefined;
265
+ }>>;
266
+ aliases: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
267
+ }, "strict", z.ZodTypeAny, {
268
+ platform: "browser" | "cli";
269
+ dependencies?: Record<string, string> | undefined;
270
+ esbuild?: {
271
+ jsx?: "automatic" | "transform" | "preserve" | undefined;
272
+ target?: string | undefined;
273
+ format?: "esm" | "cjs" | "iife" | undefined;
274
+ jsxFactory?: string | undefined;
275
+ jsxFragment?: string | undefined;
276
+ } | undefined;
277
+ framework?: {
278
+ globals?: Record<string, string> | undefined;
279
+ preload?: string[] | undefined;
280
+ deps?: Record<string, string> | undefined;
281
+ } | undefined;
282
+ aliases?: Record<string, string> | undefined;
283
+ }, {
284
+ platform: "browser" | "cli";
285
+ dependencies?: Record<string, string> | undefined;
286
+ esbuild?: {
287
+ jsx?: "automatic" | "transform" | "preserve" | undefined;
288
+ target?: string | undefined;
289
+ format?: "esm" | "cjs" | "iife" | undefined;
290
+ jsxFactory?: string | undefined;
291
+ jsxFragment?: string | undefined;
292
+ } | undefined;
293
+ framework?: {
294
+ globals?: Record<string, string> | undefined;
295
+ preload?: string[] | undefined;
296
+ deps?: Record<string, string> | undefined;
297
+ } | undefined;
298
+ aliases?: Record<string, string> | undefined;
299
+ }>;
300
+ type ImageConfig = z.infer<typeof ImageConfigSchema>;
301
+ declare const InputSpecSchema: z.ZodObject<{
302
+ type: z.ZodEnum<["string", "number", "boolean", "object", "array"]>;
303
+ default: z.ZodOptional<z.ZodUnknown>;
304
+ required: z.ZodOptional<z.ZodBoolean>;
305
+ description: z.ZodOptional<z.ZodString>;
306
+ }, "strip", z.ZodTypeAny, {
307
+ type: "string" | "number" | "boolean" | "object" | "array";
308
+ default?: unknown;
309
+ required?: boolean | undefined;
310
+ description?: string | undefined;
311
+ }, {
312
+ type: "string" | "number" | "boolean" | "object" | "array";
313
+ default?: unknown;
314
+ required?: boolean | undefined;
315
+ description?: string | undefined;
316
+ }>;
317
+ declare const ManifestSchema: z.ZodObject<{
318
+ name: z.ZodString;
319
+ version: z.ZodString;
320
+ description: z.ZodOptional<z.ZodString>;
321
+ platform: z.ZodEnum<["browser", "cli"]>;
322
+ image: z.ZodString;
323
+ inputs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
324
+ type: z.ZodEnum<["string", "number", "boolean", "object", "array"]>;
325
+ default: z.ZodOptional<z.ZodUnknown>;
326
+ required: z.ZodOptional<z.ZodBoolean>;
327
+ description: z.ZodOptional<z.ZodString>;
328
+ }, "strip", z.ZodTypeAny, {
329
+ type: "string" | "number" | "boolean" | "object" | "array";
330
+ default?: unknown;
331
+ required?: boolean | undefined;
332
+ description?: string | undefined;
333
+ }, {
334
+ type: "string" | "number" | "boolean" | "object" | "array";
335
+ default?: unknown;
336
+ required?: boolean | undefined;
337
+ description?: string | undefined;
338
+ }>>>;
339
+ services: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
340
+ packages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
341
+ }, "strip", z.ZodTypeAny, {
342
+ platform: "browser" | "cli";
343
+ name: string;
344
+ version: string;
345
+ image: string;
346
+ description?: string | undefined;
347
+ inputs?: Record<string, {
348
+ type: "string" | "number" | "boolean" | "object" | "array";
349
+ default?: unknown;
350
+ required?: boolean | undefined;
351
+ description?: string | undefined;
352
+ }> | undefined;
353
+ services?: string[] | undefined;
354
+ packages?: Record<string, string> | undefined;
355
+ }, {
356
+ platform: "browser" | "cli";
357
+ name: string;
358
+ version: string;
359
+ image: string;
360
+ description?: string | undefined;
361
+ inputs?: Record<string, {
362
+ type: "string" | "number" | "boolean" | "object" | "array";
363
+ default?: unknown;
364
+ required?: boolean | undefined;
365
+ description?: string | undefined;
366
+ }> | undefined;
367
+ services?: string[] | undefined;
368
+ packages?: Record<string, string> | undefined;
369
+ }>;
370
+ type Manifest = z.infer<typeof ManifestSchema>;
371
+ declare const CompileOptionsSchema: z.ZodOptional<z.ZodObject<{
372
+ typescript: z.ZodOptional<z.ZodBoolean>;
373
+ }, "strict", z.ZodTypeAny, {
374
+ typescript?: boolean | undefined;
375
+ }, {
376
+ typescript?: boolean | undefined;
377
+ }>>;
378
+ declare const MountModeSchema: z.ZodEnum<["embedded", "iframe"]>;
379
+ declare const MountOptionsSchema: z.ZodObject<{
380
+ target: z.ZodType<HTMLElement, z.ZodTypeDef, HTMLElement>;
381
+ mode: z.ZodEnum<["embedded", "iframe"]>;
382
+ sandbox: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
383
+ inputs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
384
+ }, "strip", z.ZodTypeAny, {
385
+ target: HTMLElement;
386
+ mode: "embedded" | "iframe";
387
+ inputs?: Record<string, unknown> | undefined;
388
+ sandbox?: string[] | undefined;
389
+ }, {
390
+ target: HTMLElement;
391
+ mode: "embedded" | "iframe";
392
+ inputs?: Record<string, unknown> | undefined;
393
+ sandbox?: string[] | undefined;
394
+ }>;
395
+ /**
396
+ * Parse and validate ImageConfig from package.json patchwork field
397
+ *
398
+ * @param data - Raw data from package.json patchwork field
399
+ * @returns Validated ImageConfig
400
+ * @throws z.ZodError if validation fails
401
+ */
402
+ declare function parseImageConfig(data: unknown): ImageConfig;
403
+ /**
404
+ * Safely parse ImageConfig, returning null on failure
405
+ */
406
+ declare function safeParseImageConfig(data: unknown): ImageConfig | null;
407
+ /**
408
+ * Parse and validate widget manifest
409
+ */
410
+ declare function parseManifest(data: unknown): Manifest;
411
+ /**
412
+ * Safely parse manifest, returning null on failure
413
+ */
414
+ declare function safeParseManifest(data: unknown): Manifest | null;
415
+ declare const DEFAULT_IMAGE_CONFIG: ImageConfig;
416
+ declare const DEFAULT_CLI_IMAGE_CONFIG: ImageConfig;
417
+
418
+ /**
419
+ * Image loader - fetches and loads image packages from CDN or local
420
+ *
421
+ * Images must be installed as npm packages or available on CDN.
422
+ */
423
+
424
+ /**
425
+ * Set the CDN base URL for image loading
426
+ */
427
+ declare function setCdnBaseUrl(url: string): void;
428
+ /**
429
+ * Get the current CDN base URL
430
+ */
431
+ declare function getCdnBaseUrl(): string;
432
+ interface ImagePackageJson {
433
+ name: string;
434
+ version: string;
435
+ main?: string;
436
+ dependencies?: Record<string, string>;
437
+ patchwork?: unknown;
438
+ }
439
+ /**
440
+ * Parse image specifier into name and version
441
+ */
442
+ declare function parseImageSpec(spec: string): {
443
+ name: string;
444
+ version?: string;
445
+ };
446
+ /**
447
+ * Fetch package.json from CDN
448
+ */
449
+ declare function fetchPackageJson(packageName: string, version?: string): Promise<ImagePackageJson>;
450
+ /**
451
+ * Load an image package
452
+ *
453
+ * Priority:
454
+ * 1. Try to resolve locally (require.resolve for installed packages)
455
+ * 2. Fetch from CDN
456
+ *
457
+ * Images must be explicitly installed or available on CDN.
458
+ */
459
+ declare function loadImage(spec: string): Promise<LoadedImage>;
460
+
461
+ /**
462
+ * Image registry - manages loaded images
463
+ */
464
+
465
+ /**
466
+ * Registry of loaded images
467
+ */
468
+ declare class ImageRegistry {
469
+ private images;
470
+ private loading;
471
+ /**
472
+ * Get a loaded image by spec
473
+ */
474
+ get(spec: string): LoadedImage | undefined;
475
+ /**
476
+ * Check if an image is loaded
477
+ */
478
+ has(spec: string): boolean;
479
+ /**
480
+ * Load an image (or return cached)
481
+ */
482
+ load(spec: string): Promise<LoadedImage>;
483
+ /**
484
+ * Preload an image
485
+ */
486
+ preload(spec: string): Promise<void>;
487
+ /**
488
+ * Clear a specific image from cache
489
+ */
490
+ clear(spec: string): void;
491
+ /**
492
+ * Clear all cached images
493
+ */
494
+ clearAll(): void;
495
+ /**
496
+ * Get all loaded image names
497
+ */
498
+ getLoadedNames(): string[];
499
+ }
500
+ /**
501
+ * Get the global image registry
502
+ */
503
+ declare function getImageRegistry(): ImageRegistry;
504
+ /**
505
+ * Create a new isolated image registry
506
+ */
507
+ declare function createImageRegistry(): ImageRegistry;
508
+
509
+ /**
510
+ * CDN transform - converts bare imports to CDN URLs (esm.sh)
511
+ */
512
+
513
+ interface CdnTransformOptions {
514
+ /** Map of package names to versions */
515
+ packages?: Record<string, string>;
516
+ /** Additional external packages */
517
+ external?: string[];
518
+ /** Use bundled versions from esm.sh (adds ?bundle) */
519
+ bundle?: boolean;
520
+ /** Packages to inject from window globals instead of CDN */
521
+ globals?: Record<string, string>;
522
+ /** Dependency version overrides for CDN URLs (e.g., { react: '18' }) */
523
+ deps?: Record<string, string>;
524
+ /** Import path aliases (e.g., { '@/components/ui/*': '@packagedcn/react' }) */
525
+ aliases?: Record<string, string>;
526
+ }
527
+ /**
528
+ * Create an esbuild plugin that transforms bare imports to CDN URLs
529
+ * and injects globals for specified packages (like React)
530
+ */
531
+ declare function cdnTransformPlugin(options?: CdnTransformOptions): Plugin;
532
+ /**
533
+ * Generate import map for CDN dependencies
534
+ */
535
+ declare function generateImportMap(packages: Record<string, string>): Record<string, string>;
536
+
537
+ interface VFSPluginOptions {
538
+ aliases?: Record<string, string>;
539
+ }
540
+ declare function vfsPlugin(project: VirtualProject, options?: VFSPluginOptions): Plugin;
541
+
542
+ /**
543
+ * File statistics matching Node.js fs.Stats subset
544
+ */
545
+ interface FileStats {
546
+ size: number;
547
+ mtime: Date;
548
+ isFile(): boolean;
549
+ isDirectory(): boolean;
550
+ }
551
+ /**
552
+ * Directory entry matching Node.js fs.Dirent
553
+ */
554
+ interface DirEntry {
555
+ name: string;
556
+ isFile(): boolean;
557
+ isDirectory(): boolean;
558
+ }
559
+ type WatchEventType = "create" | "update" | "delete";
560
+ type WatchCallback = (event: WatchEventType, path: string) => void;
561
+ /**
562
+ * FSProvider - Node.js fs/promises compatible interface
563
+ * All paths are relative to provider root
564
+ */
565
+ interface FSProvider {
566
+ readFile(path: string, encoding?: "utf8" | "base64"): Promise<string>;
567
+ writeFile(path: string, content: string): Promise<void>;
568
+ unlink(path: string): Promise<void>;
569
+ stat(path: string): Promise<FileStats>;
570
+ mkdir(path: string, options?: {
571
+ recursive?: boolean;
572
+ }): Promise<void>;
573
+ readdir(path: string): Promise<DirEntry[]>;
574
+ rmdir(path: string, options?: {
575
+ recursive?: boolean;
576
+ }): Promise<void>;
577
+ exists(path: string): Promise<boolean>;
578
+ watch?(path: string, callback: WatchCallback): () => void;
579
+ }
580
+ /**
581
+ * Change record for sync operations
582
+ */
583
+ interface ChangeRecord {
584
+ path: string;
585
+ type: WatchEventType;
586
+ mtime: Date;
587
+ checksum?: string;
588
+ }
589
+ type ConflictStrategy = "local-wins" | "remote-wins" | "newest-wins" | "manual";
590
+ interface SyncResult {
591
+ pushed: number;
592
+ pulled: number;
593
+ conflicts: ConflictRecord[];
594
+ }
595
+ interface ConflictRecord {
596
+ path: string;
597
+ localMtime: Date;
598
+ remoteMtime: Date;
599
+ resolved?: "local" | "remote";
600
+ }
601
+ type SyncStatus = "idle" | "syncing" | "error";
602
+ type SyncEventType = "change" | "conflict" | "error" | "status";
603
+ type SyncEventCallback<T = unknown> = (data: T) => void;
604
+
605
+ declare class IndexedDBBackend implements FSProvider {
606
+ private prefix;
607
+ constructor(prefix?: string);
608
+ private key;
609
+ readFile(path: string): Promise<string>;
610
+ writeFile(path: string, content: string): Promise<void>;
611
+ unlink(path: string): Promise<void>;
612
+ stat(path: string): Promise<FileStats>;
613
+ mkdir(path: string, options?: {
614
+ recursive?: boolean;
615
+ }): Promise<void>;
616
+ readdir(path: string): Promise<DirEntry[]>;
617
+ rmdir(path: string, options?: {
618
+ recursive?: boolean;
619
+ }): Promise<void>;
620
+ exists(path: string): Promise<boolean>;
621
+ private dirExists;
622
+ }
623
+
624
+ interface HttpBackendConfig {
625
+ baseUrl: string;
626
+ }
627
+ /**
628
+ * HTTP-based FSProvider for connecting to remote servers (e.g., stitchery)
629
+ */
630
+ declare class HttpBackend implements FSProvider {
631
+ private config;
632
+ constructor(config: HttpBackendConfig);
633
+ readFile(path: string): Promise<string>;
634
+ writeFile(path: string, content: string): Promise<void>;
635
+ unlink(path: string): Promise<void>;
636
+ stat(path: string): Promise<FileStats>;
637
+ mkdir(path: string, options?: {
638
+ recursive?: boolean;
639
+ }): Promise<void>;
640
+ readdir(path: string): Promise<DirEntry[]>;
641
+ rmdir(path: string, options?: {
642
+ recursive?: boolean;
643
+ }): Promise<void>;
644
+ exists(path: string): Promise<boolean>;
645
+ watch(path: string, callback: WatchCallback): () => void;
646
+ private startWatch;
647
+ private url;
648
+ }
649
+
650
+ declare function createProjectFromFiles(files: VirtualFile[], id?: string): VirtualProject;
651
+ declare function resolveEntry(files: Map<string, VirtualFile>): string;
652
+ declare function detectMainFile(language?: string): string;
653
+ declare function createSingleFileProject(content: string, entry?: string, id?: string): VirtualProject;
654
+
655
+ interface VFSStoreOptions {
656
+ root?: string;
657
+ sync?: boolean;
658
+ conflictStrategy?: ConflictStrategy;
659
+ autoSyncIntervalMs?: number;
660
+ }
661
+ declare class VFSStore {
662
+ private provider;
663
+ private local?;
664
+ private syncEngine?;
665
+ private root;
666
+ constructor(provider: FSProvider, options?: VFSStoreOptions);
667
+ readFile(path: string, encoding?: "utf8" | "base64"): Promise<string>;
668
+ writeFile(path: string, content: string): Promise<void>;
669
+ unlink(path: string): Promise<void>;
670
+ stat(path: string): Promise<FileStats>;
671
+ mkdir(path: string, options?: {
672
+ recursive?: boolean;
673
+ }): Promise<void>;
674
+ readdir(path: string): Promise<DirEntry[]>;
675
+ rmdir(path: string, options?: {
676
+ recursive?: boolean;
677
+ }): Promise<void>;
678
+ exists(path: string): Promise<boolean>;
679
+ listFiles(prefix?: string): Promise<string[]>;
680
+ loadProject(id: string): Promise<VirtualProject | null>;
681
+ saveProject(project: VirtualProject): Promise<void>;
682
+ sync(): Promise<SyncResult>;
683
+ on<T extends SyncEventType>(event: T, callback: SyncEventCallback<T extends "change" ? ChangeRecord : T extends "conflict" ? ConflictRecord : T extends "error" ? Error : SyncStatus>): () => void;
684
+ private remotePath;
685
+ private walkFiles;
686
+ }
687
+
688
+ /**
689
+ * Embedded mount mode - mounts widgets directly in the DOM
690
+ *
691
+ * For trusted widgets that need full window access.
692
+ */
693
+
694
+ /**
695
+ * Mount a widget in embedded mode (direct DOM injection)
696
+ */
697
+ declare function mountEmbedded(widget: CompiledWidget, options: MountOptions, image: LoadedImage | null, proxy: ServiceProxy): Promise<MountedWidget>;
698
+ /**
699
+ * Hot reload an embedded widget
700
+ */
701
+ declare function reloadEmbedded(mounted: MountedWidget, widget: CompiledWidget, image: LoadedImage | null, proxy: ServiceProxy): Promise<MountedWidget>;
702
+
703
+ /**
704
+ * Iframe mount mode - mounts widgets in sandboxed iframes
705
+ *
706
+ * For untrusted widgets that need isolation.
707
+ */
708
+
709
+ /**
710
+ * Development sandbox attributes - includes allow-same-origin
711
+ *
712
+ * allow-same-origin is required when:
713
+ * - Fetching modules from the parent origin (e.g., /_local-packages/ in dev)
714
+ * - Using import maps that reference parent-relative URLs
715
+ * - Accessing the parent's CDN proxy
716
+ *
717
+ * Note: This does NOT allow the iframe to access parent's DOM or cookies,
718
+ * but it does allow same-origin network requests.
719
+ *
720
+ * WARNING: Combining allow-scripts + allow-same-origin allows the iframe to
721
+ * escape its sandbox. Only use in development or when hosting on a separate subdomain.
722
+ */
723
+ declare const DEV_SANDBOX: string[];
724
+ /**
725
+ * Mount a widget in iframe mode (sandboxed)
726
+ */
727
+ declare function mountIframe(widget: CompiledWidget, options: MountOptions, image: LoadedImage | null, proxy: ServiceProxy): Promise<MountedWidget>;
728
+ /**
729
+ * Hot reload an iframe widget
730
+ */
731
+ declare function reloadIframe(mounted: MountedWidget, widget: CompiledWidget, image: LoadedImage | null, proxy: ServiceProxy): Promise<MountedWidget>;
732
+ /**
733
+ * Dispose the shared bridge (call on app shutdown)
734
+ */
735
+ declare function disposeIframeBridge(): void;
736
+
737
+ /**
738
+ * Service bridge - handles communication between widgets and service proxy
739
+ */
740
+
741
+ /**
742
+ * Create a service proxy that calls the backend via HTTP
743
+ */
744
+ declare function createHttpServiceProxy(proxyUrl: string): ServiceProxy;
745
+ /**
746
+ * Creates a proxy that enables fluent method chaining for dynamic field access.
747
+ *
748
+ * This allows arbitrary nested property access that resolves to a callable function,
749
+ * supporting patterns like `proxy.foo()`, `proxy.foo.bar()`, `proxy.bar.baz.qux()`.
750
+ *
751
+ * Used to create global namespace objects that proxy calls to a service backend.
752
+ */
753
+ declare function createFieldAccessProxy<T = unknown>(namespace: string, handler: (namespace: string, methodPath: string, ...args: T[]) => Promise<unknown>): Record<string, (...args: T[]) => Promise<unknown>>;
754
+ /**
755
+ * Create namespace globals that proxy calls to a service proxy
756
+ *
757
+ * Creates dynamic proxy objects for each namespace that support arbitrary
758
+ * nested method calls. This replaces the old static method registration.
759
+ *
760
+ * @param services - Array of service names (e.g., ['git', 'github'])
761
+ * @param proxy - The service proxy to forward calls to
762
+ * @returns Record of namespace names to proxy objects
763
+ *
764
+ * @example
765
+ * ```typescript
766
+ * const namespaces = generateNamespaceGlobals(['git', 'github'], proxy);
767
+ * // namespaces.git.status() calls proxy.call('git', 'status', [])
768
+ * // namespaces.github.repos.list_for_user({ username: 'x' })
769
+ * // calls proxy.call('github', 'repos.list_for_user', [{ username: 'x' }])
770
+ * ```
771
+ */
772
+ declare function generateNamespaceGlobals(services: string[], proxy: ServiceProxy): Record<string, unknown>;
773
+ /**
774
+ * Inject namespace globals into a window object
775
+ */
776
+ declare function injectNamespaceGlobals(target: Window | typeof globalThis, namespaces: Record<string, unknown>): void;
777
+ /**
778
+ * Remove namespace globals from a window object
779
+ */
780
+ declare function removeNamespaceGlobals(target: Window | typeof globalThis, namespaceNames: string[]): void;
781
+ /**
782
+ * Extract unique namespace names from services array
783
+ */
784
+ declare function extractNamespaces(services: string[]): string[];
785
+ /**
786
+ * Parent-side bridge for iframe communication
787
+ *
788
+ * Listens for postMessage events from iframes and proxies service calls.
789
+ */
790
+ declare class ParentBridge {
791
+ private proxy;
792
+ private pendingCalls;
793
+ private iframes;
794
+ private messageHandler;
795
+ constructor(proxy: ServiceProxy);
796
+ /**
797
+ * Register an iframe to receive messages from
798
+ */
799
+ registerIframe(iframe: HTMLIFrameElement): void;
800
+ /**
801
+ * Unregister an iframe
802
+ */
803
+ unregisterIframe(iframe: HTMLIFrameElement): void;
804
+ /**
805
+ * Handle incoming messages from iframes
806
+ */
807
+ private handleMessage;
808
+ /**
809
+ * Dispose the bridge
810
+ */
811
+ dispose(): void;
812
+ }
813
+ /**
814
+ * Child-side bridge for iframe communication
815
+ *
816
+ * Creates a service proxy that sends postMessage to parent.
817
+ */
818
+ declare function createIframeServiceProxy(): ServiceProxy;
819
+ /**
820
+ * Generate the bridge script to inject into iframes
821
+ *
822
+ * Creates a self-contained script that sets up:
823
+ * 1. Message handling for service results from parent
824
+ * 2. Dynamic proxy objects for each namespace that support arbitrary nested calls
825
+ */
826
+ declare function generateIframeBridgeScript(services: string[]): string;
827
+
828
+ export { type BridgeMessage, type BridgeMessageType, type CdnTransformOptions, type ChangeRecord, type CompileOptions, CompileOptionsSchema, type CompiledWidget, type Compiler, type CompilerOptions, DEFAULT_CLI_IMAGE_CONFIG, DEFAULT_IMAGE_CONFIG, DEV_SANDBOX, EsbuildConfigSchema, type GlobalInterfaceDefinition, HttpBackend, type HttpBackendConfig, type ImageConfig$1 as ImageConfig, ImageConfigSchema, type ImageMountFn, ImageRegistry, IndexedDBBackend, type InputSpec, InputSpecSchema, type LoadedImage, type Manifest$1 as Manifest, ManifestSchema, type MountMode, MountModeSchema, type MountOptions, MountOptionsSchema, type MountedWidget, ParentBridge, type Platform, PlatformSchema, type ServiceCallHandler, type ServiceCallPayload, type ServiceProxy, type ServiceResultPayload, type VFSPluginOptions, VFSStore, type VFSStoreOptions, type VirtualFile, type VirtualProject, cdnTransformPlugin, createCompiler, createFieldAccessProxy, createHttpServiceProxy, createIframeServiceProxy, createImageRegistry, createProjectFromFiles, createSingleFileProject, detectMainFile, disposeIframeBridge, extractNamespaces, fetchPackageJson, generateIframeBridgeScript, generateImportMap, generateNamespaceGlobals, getCdnBaseUrl, getImageRegistry, injectNamespaceGlobals, loadImage, mountEmbedded, mountIframe, parseImageConfig, parseImageSpec, parseManifest, reloadEmbedded, reloadIframe, removeNamespaceGlobals, resolveEntry, safeParseImageConfig, safeParseManifest, setCdnBaseUrl, vfsPlugin };