@wendoo/bridge-app 0.2.2

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.
Files changed (77) hide show
  1. package/README.md +44 -0
  2. package/dist/app-bridge.d.ts +77 -0
  3. package/dist/app-bridge.d.ts.map +1 -0
  4. package/dist/app-bridge.js +205 -0
  5. package/dist/app-environment-host.d.ts +524 -0
  6. package/dist/app-environment-host.d.ts.map +1 -0
  7. package/dist/app-environment-host.js +1560 -0
  8. package/dist/brain-diagnostics.d.ts +47 -0
  9. package/dist/brain-diagnostics.d.ts.map +1 -0
  10. package/dist/brain-diagnostics.js +100 -0
  11. package/dist/bridge-project.d.ts +32 -0
  12. package/dist/bridge-project.d.ts.map +1 -0
  13. package/dist/bridge-project.js +69 -0
  14. package/dist/compilation.d.ts +145 -0
  15. package/dist/compilation.d.ts.map +1 -0
  16. package/dist/compilation.js +404 -0
  17. package/dist/core-extension.d.ts +10 -0
  18. package/dist/core-extension.d.ts.map +1 -0
  19. package/dist/core-extension.js +9 -0
  20. package/dist/embedded-extension-id-gate.d.ts +38 -0
  21. package/dist/embedded-extension-id-gate.d.ts.map +1 -0
  22. package/dist/embedded-extension-id-gate.js +55 -0
  23. package/dist/embedded-extension-loader.d.ts +33 -0
  24. package/dist/embedded-extension-loader.d.ts.map +1 -0
  25. package/dist/embedded-extension-loader.js +90 -0
  26. package/dist/embedded-extension-vite-plugin.d.ts +34 -0
  27. package/dist/embedded-extension-vite-plugin.d.ts.map +1 -0
  28. package/dist/embedded-extension-vite-plugin.js +39 -0
  29. package/dist/embedded-extensions.d.ts +293 -0
  30. package/dist/embedded-extensions.d.ts.map +1 -0
  31. package/dist/embedded-extensions.js +526 -0
  32. package/dist/extension-catalog.d.ts +243 -0
  33. package/dist/extension-catalog.d.ts.map +1 -0
  34. package/dist/extension-catalog.js +408 -0
  35. package/dist/extension-install-log.d.ts +54 -0
  36. package/dist/extension-install-log.d.ts.map +1 -0
  37. package/dist/extension-install-log.js +22 -0
  38. package/dist/extension-install.d.ts +162 -0
  39. package/dist/extension-install.d.ts.map +1 -0
  40. package/dist/extension-install.js +412 -0
  41. package/dist/extension-report-presenter.d.ts +40 -0
  42. package/dist/extension-report-presenter.d.ts.map +1 -0
  43. package/dist/extension-report-presenter.js +36 -0
  44. package/dist/fetched-extension-snapshots.d.ts +66 -0
  45. package/dist/fetched-extension-snapshots.d.ts.map +1 -0
  46. package/dist/fetched-extension-snapshots.js +137 -0
  47. package/dist/folder-host-session.d.ts +85 -0
  48. package/dist/folder-host-session.d.ts.map +1 -0
  49. package/dist/folder-host-session.js +210 -0
  50. package/dist/index.d.ts +38 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +19 -0
  53. package/dist/library-offer.d.ts +60 -0
  54. package/dist/library-offer.d.ts.map +1 -0
  55. package/dist/library-offer.js +47 -0
  56. package/dist/library-uninstall-guard.d.ts +66 -0
  57. package/dist/library-uninstall-guard.d.ts.map +1 -0
  58. package/dist/library-uninstall-guard.js +103 -0
  59. package/dist/manifest-files.d.ts +53 -0
  60. package/dist/manifest-files.d.ts.map +1 -0
  61. package/dist/manifest-files.js +242 -0
  62. package/dist/node.d.ts +4 -0
  63. package/dist/node.d.ts.map +1 -0
  64. package/dist/node.js +2 -0
  65. package/dist/project-file-bridge.d.ts +10 -0
  66. package/dist/project-file-bridge.d.ts.map +1 -0
  67. package/dist/project-file-bridge.js +87 -0
  68. package/dist/user-tile-registration.d.ts +89 -0
  69. package/dist/user-tile-registration.d.ts.map +1 -0
  70. package/dist/user-tile-registration.js +100 -0
  71. package/dist/vfs-asset-url-provider.d.ts +22 -0
  72. package/dist/vfs-asset-url-provider.d.ts.map +1 -0
  73. package/dist/vfs-asset-url-provider.js +52 -0
  74. package/dist/workspace-folder-project-store.d.ts +125 -0
  75. package/dist/workspace-folder-project-store.d.ts.map +1 -0
  76. package/dist/workspace-folder-project-store.js +400 -0
  77. package/package.json +103 -0
@@ -0,0 +1,87 @@
1
+ import { fileContentFromWire, fileContentToWire } from "@wendoo/app-host";
2
+ /** Convert an app-host project file snapshot into a bridge-client snapshot. */
3
+ export function toFileSystemSnapshot(snapshot) {
4
+ return new Map(snapshot);
5
+ }
6
+ /** Convert an app-host project file mutation into a bridge protocol notification. */
7
+ export function toFileSystemNotification(change) {
8
+ switch (change.action) {
9
+ case "write":
10
+ return {
11
+ action: "write",
12
+ path: change.path,
13
+ ...fileContentToWire(change.content),
14
+ newEtag: change.newEtag,
15
+ ...(change.isReadonly !== undefined ? { isReadonly: change.isReadonly } : {}),
16
+ ...(change.expectedEtag !== undefined ? { expectedEtag: change.expectedEtag } : {}),
17
+ };
18
+ case "delete":
19
+ return {
20
+ action: "delete",
21
+ path: change.path,
22
+ ...(change.expectedEtag !== undefined ? { expectedEtag: change.expectedEtag } : {}),
23
+ };
24
+ case "rename":
25
+ return {
26
+ action: "rename",
27
+ oldPath: change.oldPath,
28
+ newPath: change.newPath,
29
+ ...(change.expectedEtag !== undefined ? { expectedEtag: change.expectedEtag } : {}),
30
+ };
31
+ case "mkdir":
32
+ return { action: "mkdir", path: change.path };
33
+ case "rmdir":
34
+ return { action: "rmdir", path: change.path };
35
+ case "import":
36
+ return { action: "import", entries: [...change.entries].map(toWireEntry) };
37
+ }
38
+ }
39
+ /** Convert a bridge protocol notification into an app-host project file mutation. */
40
+ export function toProjectFileChange(notification) {
41
+ switch (notification.action) {
42
+ case "write":
43
+ return {
44
+ action: "write",
45
+ path: notification.path,
46
+ content: fileContentFromWire(notification),
47
+ newEtag: notification.newEtag,
48
+ ...(notification.isReadonly !== undefined ? { isReadonly: notification.isReadonly } : {}),
49
+ ...(notification.expectedEtag !== undefined ? { expectedEtag: notification.expectedEtag } : {}),
50
+ };
51
+ case "delete":
52
+ return {
53
+ action: "delete",
54
+ path: notification.path,
55
+ ...(notification.expectedEtag !== undefined ? { expectedEtag: notification.expectedEtag } : {}),
56
+ };
57
+ case "rename":
58
+ return {
59
+ action: "rename",
60
+ oldPath: notification.oldPath,
61
+ newPath: notification.newPath,
62
+ ...(notification.expectedEtag !== undefined ? { expectedEtag: notification.expectedEtag } : {}),
63
+ };
64
+ case "mkdir":
65
+ return { action: "mkdir", path: notification.path };
66
+ case "rmdir":
67
+ return { action: "rmdir", path: notification.path };
68
+ case "import":
69
+ return { action: "import", entries: [...notification.entries].map(fromWireEntry) };
70
+ }
71
+ }
72
+ /** Encode a project snapshot entry for the wire. */
73
+ function toWireEntry([path, entry]) {
74
+ if (entry.kind === "directory") {
75
+ return [path, entry];
76
+ }
77
+ const { content, ...rest } = entry;
78
+ return [path, { ...rest, ...fileContentToWire(content) }];
79
+ }
80
+ /** Decode a wire entry back into a project snapshot entry. */
81
+ function fromWireEntry([path, entry]) {
82
+ if (entry.kind === "directory") {
83
+ return [path, entry];
84
+ }
85
+ const { encoding, ...rest } = entry;
86
+ return [path, { ...rest, content: fileContentFromWire(entry) }];
87
+ }
@@ -0,0 +1,89 @@
1
+ import type { ActionKind, BrainActionCallSpec, WendooEnvironment } from "@wendoo/core/app";
2
+ import type { ActionKey } from "@wendoo/core/runtime";
3
+ import type { CompileDiagnostic, ExtractedArgSpec, ExtractedOutput, WorkspaceCompileResult } from "@wendoo/ts-compiler";
4
+ /** Metadata describing a user-authored sensor or actuator tile. */
5
+ export interface UserTileMetadata {
6
+ /** Stable key used to identify the tile across compiles. */
7
+ key: string;
8
+ /**
9
+ * Namespace of the project that compiled this tile: a host project's store id
10
+ * or an installed extension's `<owner>/<repo>` coordinate.
11
+ */
12
+ namespace: string;
13
+ /** Opaque stable id from the source declaration. */
14
+ id: string;
15
+ /** The tile-bearing action kind; conversions surface no tile and are excluded. */
16
+ kind: Exclude<ActionKind, "conversion">;
17
+ /** Display name of the user's action. */
18
+ name: string;
19
+ /** Brain-action call signature derived from the source. */
20
+ callSpec: BrainActionCallSpec;
21
+ /** Argument descriptors derived from the source. */
22
+ args: ExtractedArgSpec[];
23
+ /** For sensors, the typeId of the value the tile produces. */
24
+ outputType?: string;
25
+ /** For sensors, the declared named outputs surfaced as inline output value-tiles. */
26
+ outputs?: ExtractedOutput[];
27
+ /** Whether the tile's call returns a `Promise`. */
28
+ isAsync: boolean;
29
+ /** Optional human-readable label for the tile. */
30
+ label?: string;
31
+ /** Optional icon URL for the tile. */
32
+ iconUrl?: string;
33
+ /** Optional Markdown documentation shown in the editor. */
34
+ docsMarkdown?: string;
35
+ /** Optional categorization tags. */
36
+ tags?: string[];
37
+ /** For sensors, when true the tile is placement-inline; the picker offers it in value-slot positions. */
38
+ inline?: boolean;
39
+ /** For sensors, when true the tile carries the PresenceGated capability; a bare WHEN gates on value presence. */
40
+ presenceGated?: boolean;
41
+ }
42
+ /** Result returned by {@link applyCompiledUserTiles}. */
43
+ export interface UserTileApplyResult {
44
+ metadata: readonly UserTileMetadata[];
45
+ /** Action keys whose call definition changed since the previous bundle. */
46
+ changedActionKeys: readonly string[];
47
+ /** Number of brains invalidated by the change. */
48
+ invalidatedBrainCount: number;
49
+ }
50
+ /**
51
+ * Extract user-tile metadata from a compile result, sorted by key. Includes a
52
+ * metadata entry for every contributing file of every compilation root -- the
53
+ * host project and each installed extension, each keyed under its own
54
+ * namespace -- matching the files whose tiles enter the compiled bundle.
55
+ */
56
+ export declare function collectMetadataFromCompile(result: WorkspaceCompileResult): UserTileMetadata[];
57
+ /**
58
+ * A user tile's error compile diagnostics together with the source file path
59
+ * that produced them. `path` is the compilation-root path keyed by the tile's
60
+ * {@link ActionKey}; a consumer composes a source location from `path` and each
61
+ * diagnostic's `line`/`column`.
62
+ */
63
+ export interface TileCompileDiagnostics {
64
+ /** Compilation-root path of the source file that contributed the tile. */
65
+ readonly path: string;
66
+ /** The file's error compile diagnostics, verbatim and in emit order. */
67
+ readonly diagnostics: readonly CompileDiagnostic[];
68
+ }
69
+ /**
70
+ * Map each user tile's {@link ActionKey} to the error compile diagnostics of the
71
+ * source file that contributed it and that source's path, built from a single
72
+ * workspace compile. Iterates every compilation root's per-file results, keying
73
+ * by `(program ?? definition).key` and collecting that file's compile errors:
74
+ * the TypeScript pre-emit diagnostics (`tsErrors` for the file's path) together
75
+ * with the result's own descriptor, lowering, and emit diagnostics, filtered to
76
+ * `severity === "error"`. Conversions surface no tile and are excluded. A file
77
+ * that compiled cleanly, or produced only warnings and infos, is absent from the
78
+ * map.
79
+ *
80
+ * The stored diagnostics are the compiler's verbatim {@link CompileDiagnostic}
81
+ * objects, so a consumer reads `message`, `severity`, and `line`/`column` directly.
82
+ */
83
+ export declare function collectTileSourceCompileErrors(result: WorkspaceCompileResult): Map<ActionKey, TileCompileDiagnostics>;
84
+ /**
85
+ * Apply the user-tile bundle from a project compile result to the environment.
86
+ * Returns `undefined` when the compile produced no bundle.
87
+ */
88
+ export declare function applyCompiledUserTiles(env: WendooEnvironment, result: WorkspaceCompileResult): UserTileApplyResult | undefined;
89
+ //# sourceMappingURL=user-tile-registration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-tile-registration.d.ts","sourceRoot":"","sources":["../src/user-tile-registration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE3F,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EAGf,sBAAsB,EACvB,MAAM,qBAAqB,CAAC;AAE7B,mEAAmE;AACnE,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,EAAE,EAAE,MAAM,CAAC;IACX,kFAAkF;IAClF,IAAI,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IACxC,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,oDAAoD;IACpD,IAAI,EAAE,gBAAgB,EAAE,CAAC;IACzB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,mDAAmD;IACnD,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,yGAAyG;IACzG,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iHAAiH;IACjH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,yDAAyD;AACzD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACtC,2EAA2E;IAC3E,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,kDAAkD;IAClD,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AA0BD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,sBAAsB,GAAG,gBAAgB,EAAE,CAe7F;AAED;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,CAAC,WAAW,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACpD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,sBAAsB,GAAG,GAAG,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAqBrH;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,sBAAsB,GAC7B,mBAAmB,GAAG,SAAS,CAwBjC"}
@@ -0,0 +1,100 @@
1
+ import { logger, mkActionTileId } from "@wendoo/core/app";
2
+ function metadataFromProgram(program) {
3
+ if (program.kind === "conversion") {
4
+ throw new Error(`Conversion "${program.key}" has no tile metadata`);
5
+ }
6
+ return {
7
+ key: program.key,
8
+ namespace: program.projectNamespace,
9
+ id: program.id,
10
+ kind: program.kind,
11
+ name: program.name,
12
+ callSpec: program.callDef.callSpec,
13
+ args: program.args,
14
+ outputType: program.outputType,
15
+ outputs: program.outputs,
16
+ isAsync: program.isAsync,
17
+ label: program.label,
18
+ iconUrl: program.iconUrl,
19
+ docsMarkdown: program.docsMarkdown,
20
+ tags: program.tags,
21
+ inline: program.inline,
22
+ presenceGated: program.presenceGated,
23
+ };
24
+ }
25
+ /**
26
+ * Extract user-tile metadata from a compile result, sorted by key. Includes a
27
+ * metadata entry for every contributing file of every compilation root -- the
28
+ * host project and each installed extension, each keyed under its own
29
+ * namespace -- matching the files whose tiles enter the compiled bundle.
30
+ */
31
+ export function collectMetadataFromCompile(result) {
32
+ const metadata = [];
33
+ for (const rootResult of result.rootResults) {
34
+ for (const compileResult of rootResult.results.values()) {
35
+ const surface = compileResult.program ?? compileResult.definition;
36
+ // Conversions compile to a program but surface no tiles, so they contribute no tile metadata.
37
+ if (surface && surface.kind !== "conversion") {
38
+ metadata.push(metadataFromProgram(surface));
39
+ }
40
+ }
41
+ }
42
+ metadata.sort((left, right) => left.key.localeCompare(right.key));
43
+ return metadata;
44
+ }
45
+ /**
46
+ * Map each user tile's {@link ActionKey} to the error compile diagnostics of the
47
+ * source file that contributed it and that source's path, built from a single
48
+ * workspace compile. Iterates every compilation root's per-file results, keying
49
+ * by `(program ?? definition).key` and collecting that file's compile errors:
50
+ * the TypeScript pre-emit diagnostics (`tsErrors` for the file's path) together
51
+ * with the result's own descriptor, lowering, and emit diagnostics, filtered to
52
+ * `severity === "error"`. Conversions surface no tile and are excluded. A file
53
+ * that compiled cleanly, or produced only warnings and infos, is absent from the
54
+ * map.
55
+ *
56
+ * The stored diagnostics are the compiler's verbatim {@link CompileDiagnostic}
57
+ * objects, so a consumer reads `message`, `severity`, and `line`/`column` directly.
58
+ */
59
+ export function collectTileSourceCompileErrors(result) {
60
+ const byKey = new Map();
61
+ for (const rootResult of result.rootResults) {
62
+ for (const [path, compileResult] of rootResult.results) {
63
+ const surface = compileResult.program ?? compileResult.definition;
64
+ // Conversions compile to a program but surface no tile, so they contribute no tile diagnostics.
65
+ if (!surface || surface.kind === "conversion") {
66
+ continue;
67
+ }
68
+ const tsErrors = rootResult.tsErrors.get(path) ?? [];
69
+ const diagnostics = [...tsErrors, ...compileResult.diagnostics].filter((diagnostic) => diagnostic.severity === "error");
70
+ if (diagnostics.length > 0) {
71
+ byKey.set(surface.key, { path, diagnostics });
72
+ }
73
+ }
74
+ }
75
+ return byKey;
76
+ }
77
+ /**
78
+ * Apply the user-tile bundle from a project compile result to the environment.
79
+ * Returns `undefined` when the compile produced no bundle.
80
+ */
81
+ export function applyCompiledUserTiles(env, result) {
82
+ const bundle = result.bundle;
83
+ if (!bundle) {
84
+ return undefined;
85
+ }
86
+ const metadata = collectMetadataFromCompile(result);
87
+ const update = env.replaceActionBundle(bundle);
88
+ if (metadata.length > 0 || update.changedActionKeys.length > 0) {
89
+ logger.debug(`[user-tile-registration] applied bundle: ${metadata.length} tile(s), ${update.changedActionKeys.length} changed action(s), ${update.invalidatedBrains.length} invalidated brain(s)`);
90
+ for (const entry of metadata) {
91
+ const tileId = mkActionTileId(entry.kind, entry.key);
92
+ logger.debug(`[user-tile-registration] ${tileId}`);
93
+ }
94
+ }
95
+ return {
96
+ metadata,
97
+ changedActionKeys: update.changedActionKeys,
98
+ invalidatedBrainCount: update.invalidatedBrains.length,
99
+ };
100
+ }
@@ -0,0 +1,22 @@
1
+ import type { ProjectFileSystem } from "./app-bridge.js";
2
+ /** Options for {@link createVfsAssetUrlProvider}. */
3
+ export interface VfsAssetUrlProviderOptions {
4
+ /** Returns the project file system whose snapshot carries the served assets. */
5
+ getProjectFileSystem: () => ProjectFileSystem;
6
+ /** Returns the current VFS revision. Advancing it invalidates minted URLs. */
7
+ getVfsRevision: () => number;
8
+ }
9
+ /** Resolves compiler-minted `/vfs/<path>` asset references to loadable URLs. */
10
+ export interface VfsAssetUrlProvider {
11
+ /**
12
+ * Resolve `url` to an object URL for the file at `<path>` in the current
13
+ * snapshot of the project file system. URLs are cached per (path, revision);
14
+ * the first resolution after the revision advances re-reads the snapshot and
15
+ * revokes the superseded generation's URLs. Returns `url` unchanged when it
16
+ * does not start with `/vfs/` or names no file in the snapshot.
17
+ */
18
+ resolveAssetUrl(url: string): string;
19
+ }
20
+ /** Create a {@link VfsAssetUrlProvider} over a project file system and a VFS revision source. */
21
+ export declare function createVfsAssetUrlProvider(options: VfsAssetUrlProviderOptions): VfsAssetUrlProvider;
22
+ //# sourceMappingURL=vfs-asset-url-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vfs-asset-url-provider.d.ts","sourceRoot":"","sources":["../src/vfs-asset-url-provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAuB,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAmB9E,qDAAqD;AACrD,MAAM,WAAW,0BAA0B;IACzC,gFAAgF;IAChF,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;IAC9C,8EAA8E;IAC9E,cAAc,EAAE,MAAM,MAAM,CAAC;CAC9B;AAED,gFAAgF;AAChF,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACtC;AAED,iGAAiG;AACjG,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,0BAA0B,GAAG,mBAAmB,CAuClG"}
@@ -0,0 +1,52 @@
1
+ import { fileContentToBytes } from "@wendoo/app-host";
2
+ const VFS_PREFIX = "/vfs/";
3
+ const MIME_TYPES = {
4
+ ".svg": "image/svg+xml",
5
+ ".png": "image/png",
6
+ ".jpg": "image/jpeg",
7
+ ".jpeg": "image/jpeg",
8
+ ".gif": "image/gif",
9
+ ".webp": "image/webp",
10
+ };
11
+ function mimeForPath(path) {
12
+ const dot = path.lastIndexOf(".");
13
+ if (dot === -1)
14
+ return "application/octet-stream";
15
+ return MIME_TYPES[path.slice(dot)] ?? "application/octet-stream";
16
+ }
17
+ /** Create a {@link VfsAssetUrlProvider} over a project file system and a VFS revision source. */
18
+ export function createVfsAssetUrlProvider(options) {
19
+ let generationRevision;
20
+ let snapshot;
21
+ let urlsByPath = new Map();
22
+ return {
23
+ resolveAssetUrl(url) {
24
+ if (!url.startsWith(VFS_PREFIX)) {
25
+ return url;
26
+ }
27
+ const revision = options.getVfsRevision();
28
+ if (revision !== generationRevision) {
29
+ for (const minted of urlsByPath.values()) {
30
+ URL.revokeObjectURL(minted);
31
+ }
32
+ urlsByPath = new Map();
33
+ snapshot = undefined;
34
+ generationRevision = revision;
35
+ }
36
+ const path = url.slice(VFS_PREFIX.length);
37
+ const cached = urlsByPath.get(path);
38
+ if (cached !== undefined) {
39
+ return cached;
40
+ }
41
+ snapshot ??= options.getProjectFileSystem().exportSnapshot();
42
+ const entry = snapshot.get(path);
43
+ if (!entry || entry.kind !== "file") {
44
+ return url;
45
+ }
46
+ const bytes = new Uint8Array(fileContentToBytes(entry.content));
47
+ const minted = URL.createObjectURL(new Blob([bytes], { type: mimeForPath(path) }));
48
+ urlsByPath.set(path, minted);
49
+ return minted;
50
+ },
51
+ };
52
+ }
@@ -0,0 +1,125 @@
1
+ import type { ProjectCollection, ProjectCollectionTabSession, ProjectFileChange, ProjectFileSnapshot, ProjectManifest, ProjectRef, ProjectStore } from "@wendoo/app-host";
2
+ import type { FileSystemNotification } from "@wendoo/bridge-protocol";
3
+ import type { InstalledExtensionSnapshots } from "./fetched-extension-snapshots.js";
4
+ /** Project collection id of the single collection a workspace-folder store exposes. */
5
+ export declare const WORKSPACE_FOLDER_PROJECT_COLLECTION_ID = "workspace-folder";
6
+ /** Stable identifiers for workspace-folder store errors. */
7
+ export declare const WorkspaceFolderStoreErrorCode: {
8
+ /** The host-provided `wendoo.json` failed content-manifest validation. */
9
+ readonly INVALID_MANIFEST: "WORKSPACE_FOLDER_INVALID_MANIFEST";
10
+ /** A multi-project or collection-management operation was invoked; a workspace folder holds exactly one project. */
11
+ readonly UNSUPPORTED_OPERATION: "WORKSPACE_FOLDER_UNSUPPORTED_OPERATION";
12
+ };
13
+ /** Union of all {@link WorkspaceFolderStoreErrorCode} values. */
14
+ export type WorkspaceFolderStoreErrorCode = (typeof WorkspaceFolderStoreErrorCode)[keyof typeof WorkspaceFolderStoreErrorCode];
15
+ /** Error thrown by {@link WorkspaceFolderProjectStore}. */
16
+ export declare class WorkspaceFolderStoreError extends Error {
17
+ /** Stable machine-readable error code. */
18
+ readonly code: WorkspaceFolderStoreErrorCode;
19
+ constructor(code: WorkspaceFolderStoreErrorCode, message: string);
20
+ }
21
+ /**
22
+ * Translates between per-project app-data entries and the owning app's session
23
+ * chunk stored in the manifest's `app` map.
24
+ */
25
+ export interface FolderAppDataCodec {
26
+ /**
27
+ * Build the app chunk from the current app-data entries. Returns `undefined`
28
+ * when the entries carry no chunk-worthy state; the chunk is then absent
29
+ * from the manifest.
30
+ */
31
+ chunkFromAppData(appData: ReadonlyMap<string, string>): unknown;
32
+ /** Translate an app chunk into app-data entries keyed by app-data key. */
33
+ appDataFromChunk(chunk: unknown): Record<string, string>;
34
+ }
35
+ /** File operations the store issues against the host-owned project folder. */
36
+ export interface WorkspaceFolderRpc {
37
+ /** Apply one file change to the project folder. Resolves when written. */
38
+ sendChange(change: FileSystemNotification): Promise<void>;
39
+ /** Replace the project's `wendoo.json` with `content`. */
40
+ writeManifest(content: string): Promise<void>;
41
+ /** Read the project's file snapshot entries, excluding `wendoo.json`. */
42
+ loadFiles(): Promise<ProjectFileSnapshot>;
43
+ }
44
+ /** Options for {@link WorkspaceFolderProjectStore}. */
45
+ export interface WorkspaceFolderProjectStoreOptions {
46
+ /** Transport performing the actual folder I/O. */
47
+ rpc: WorkspaceFolderRpc;
48
+ /** Stable opaque id of the host-provided project. */
49
+ projectId: string;
50
+ /** JSON text of the project's `wendoo.json` as read from disk. */
51
+ manifestContent: string;
52
+ /** App name keying this app's chunk in the manifest's `app` map. */
53
+ appName: string;
54
+ /** Translator between app-data entries and this app's manifest chunk. */
55
+ appDataCodec?: FolderAppDataCodec;
56
+ /**
57
+ * Installed fetched-extension snapshot records seeding the store's
58
+ * installed-extensions app data, keyed by `<owner>/<repo>` origin. Loading
59
+ * the project then regenerates the installed-extensions tree from these
60
+ * records without reaching the network.
61
+ */
62
+ installedExtensionSnapshots?: InstalledExtensionSnapshots;
63
+ }
64
+ /**
65
+ * A {@link ProjectStore} over a host-owned workspace folder: the folder is the
66
+ * single project of the store's single collection. File writes are
67
+ * change-granular; the project manifest and its app data are stored inside the
68
+ * folder's `wendoo.json` (brains and app chunks in the pass-through
69
+ * section, unknown fields preserved). Multi-project and collection-management
70
+ * operations throw {@link WorkspaceFolderStoreError}.
71
+ */
72
+ export declare class WorkspaceFolderProjectStore implements ProjectStore {
73
+ readonly keyPrefix: string;
74
+ private readonly rpc;
75
+ private readonly projectId;
76
+ private readonly appName;
77
+ private readonly appDataCodec;
78
+ private readonly collection;
79
+ private base;
80
+ private manifest;
81
+ private readonly appData;
82
+ private chunkAppDataKeys;
83
+ private lastManifestContent;
84
+ private mirror;
85
+ constructor(options: WorkspaceFolderProjectStoreOptions);
86
+ /**
87
+ * Absorb a change observed on disk outside the app: a `wendoo.json`
88
+ * write replaces the store's manifest and app-data state; any other change
89
+ * updates the store's view of the folder. Returns the change in project
90
+ * file form for the caller to apply to the live project file system.
91
+ */
92
+ absorbExternalChange(change: FileSystemNotification): ProjectFileChange;
93
+ listProjectCollections(): Promise<ProjectCollection[]>;
94
+ getProjectCollection(projectCollectionId: string): Promise<ProjectCollection | undefined>;
95
+ createProjectCollection(): Promise<ProjectCollection>;
96
+ updateProjectCollection(): Promise<void>;
97
+ deleteProjectCollection(): Promise<void>;
98
+ ensureDefaultProjectCollection(): Promise<ProjectCollection>;
99
+ listProjects(projectCollectionId: string): Promise<ProjectManifest[]>;
100
+ countProjectsByCollection(): Promise<Map<string, number>>;
101
+ getProject(id: string): Promise<ProjectManifest | undefined>;
102
+ createProject(): Promise<ProjectManifest>;
103
+ deleteProject(): Promise<void>;
104
+ updateProject(id: string, updates: Partial<Pick<ProjectManifest, "name" | "version" | "description" | "thumbnailUrl" | "extensions" | "targets">>): Promise<void>;
105
+ duplicateProject(): Promise<ProjectManifest>;
106
+ copyProjectToCollection(): Promise<ProjectManifest>;
107
+ loadProjectFiles(id: string): Promise<ProjectFileSnapshot | undefined>;
108
+ saveProjectFiles(id: string, snapshot: ProjectFileSnapshot): Promise<void>;
109
+ applyProjectFileChanges(id: string, changes: readonly ProjectFileChange[]): Promise<void>;
110
+ loadAppData(id: string, key: string): Promise<string | undefined>;
111
+ saveAppData(id: string, key: string, data: string): Promise<void>;
112
+ deleteAppData(id: string, key: string): Promise<void>;
113
+ getProjectSession(): ProjectCollectionTabSession | undefined;
114
+ setProjectSession(): void;
115
+ getLastOpenedProject(): ProjectRef;
116
+ /** Ignores the write; this store's last opened project is always its folder project. */
117
+ setLastOpenedProject(): void;
118
+ private unsupported;
119
+ private requireProject;
120
+ private seedAppDataFromBase;
121
+ private composeManifestContent;
122
+ private writeManifestIfChanged;
123
+ private writeSnapshotDiff;
124
+ }
125
+ //# sourceMappingURL=workspace-folder-project-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-folder-project-store.d.ts","sourceRoot":"","sources":["../src/workspace-folder-project-store.ts"],"names":[],"mappings":"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"}