@exponential_app/engine 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +54 -0
  3. package/README.md +35 -2
  4. package/dist/capabilities.js +29 -0
  5. package/dist/capabilities.js.map +9 -0
  6. package/dist/chunks/index-4ntgtkmb.js +6783 -0
  7. package/dist/chunks/index-4ntgtkmb.js.map +13 -0
  8. package/dist/chunks/index-ans80t68.js +382 -0
  9. package/dist/chunks/index-ans80t68.js.map +9 -0
  10. package/dist/chunks/index-ax4aay30.js +315 -0
  11. package/dist/chunks/index-ax4aay30.js.map +10 -0
  12. package/dist/chunks/index-e49v2qpf.js +2177 -0
  13. package/dist/chunks/index-e49v2qpf.js.map +9 -0
  14. package/dist/chunks/index-m2845dn6.js +72 -0
  15. package/dist/chunks/index-m2845dn6.js.map +10 -0
  16. package/dist/chunks/index-md3hz6r2.js +3015 -0
  17. package/dist/chunks/index-md3hz6r2.js.map +19 -0
  18. package/dist/chunks/index-n0acffvs.js +366 -0
  19. package/dist/chunks/index-n0acffvs.js.map +10 -0
  20. package/dist/chunks/index-nrr8x2kq.js +259 -0
  21. package/dist/chunks/index-nrr8x2kq.js.map +10 -0
  22. package/dist/chunks/index-s3xjr701.js +170 -0
  23. package/dist/chunks/index-s3xjr701.js.map +10 -0
  24. package/dist/chunks/index-t89cvabm.js +2301 -0
  25. package/dist/chunks/index-t89cvabm.js.map +10 -0
  26. package/dist/chunks/index-zw0575tv.js +126 -0
  27. package/dist/chunks/index-zw0575tv.js.map +10 -0
  28. package/dist/consent.js +24 -0
  29. package/dist/consent.js.map +9 -0
  30. package/dist/index.js +526 -0
  31. package/dist/index.js.map +11 -0
  32. package/dist/lifecycle.js +11 -0
  33. package/dist/lifecycle.js.map +9 -0
  34. package/dist/outbox.js +27 -0
  35. package/dist/outbox.js.map +9 -0
  36. package/dist/pdf.js +15 -0
  37. package/dist/pdf.js.map +9 -0
  38. package/dist/providers.js +26 -0
  39. package/dist/providers.js.map +9 -0
  40. package/dist/runner.js +24 -0
  41. package/dist/runner.js.map +9 -0
  42. package/dist/tools.js +38 -0
  43. package/dist/tools.js.map +9 -0
  44. package/dist/types/domain-contract/src/app-records.d.ts +3148 -0
  45. package/dist/types/domain-contract/src/app-share.d.ts +222 -0
  46. package/dist/types/domain-contract/src/apps.d.ts +594 -0
  47. package/dist/types/eengine/fixtures/providers.json +55 -0
  48. package/dist/types/eengine/src/broker.d.ts +80 -0
  49. package/dist/types/eengine/src/capabilities.d.ts +86 -0
  50. package/dist/types/eengine/src/consent.d.ts +50 -0
  51. package/dist/types/eengine/src/index.d.ts +11 -0
  52. package/dist/types/eengine/src/instance.d.ts +122 -0
  53. package/dist/types/eengine/src/lifecycle.d.ts +64 -0
  54. package/dist/types/eengine/src/outbox.d.ts +3 -0
  55. package/dist/types/eengine/src/pdf.d.ts +36 -0
  56. package/dist/types/eengine/src/providers.d.ts +38 -0
  57. package/dist/types/eengine/src/runner.d.ts +82 -0
  58. package/dist/types/eengine/src/stores.d.ts +125 -0
  59. package/dist/types/eengine/src/tools.d.ts +79 -0
  60. package/dist/types/eengine/src/web/index.d.ts +20 -0
  61. package/dist/types/eengine/src/web/mcp.d.ts +27 -0
  62. package/dist/types/eengine/src/web/platform.d.ts +91 -0
  63. package/dist/types/eengine/src/web/stores.d.ts +125 -0
  64. package/dist/types/emcp/fixtures/automations.json +521 -0
  65. package/dist/types/emcp/fixtures/hub.json +498 -0
  66. package/dist/types/emcp/src/access.d.ts +55 -0
  67. package/dist/types/emcp/src/audit.d.ts +22 -0
  68. package/dist/types/emcp/src/automations.d.ts +111 -0
  69. package/dist/types/emcp/src/exposes.d.ts +242 -0
  70. package/dist/types/emcp/src/hub.d.ts +63 -0
  71. package/dist/types/emcp/src/index.d.ts +7 -0
  72. package/dist/types/emcp/src/pure.d.ts +11 -0
  73. package/dist/types/emcp/src/upstream.d.ts +288 -0
  74. package/dist/types/emcp/src/vault.d.ts +34 -0
  75. package/dist/web/index.js +791 -0
  76. package/dist/web/index.js.map +13 -0
  77. package/fixtures/bundle.json +1165 -0
  78. package/fixtures/capabilities.json +373 -0
  79. package/fixtures/consent.json +146 -0
  80. package/fixtures/lifecycle.json +125 -0
  81. package/fixtures/outbox.json +8 -0
  82. package/fixtures/providers.json +55 -0
  83. package/fixtures/runner.json +2167 -0
  84. package/package.json +92 -4
@@ -0,0 +1,125 @@
1
+ import type { RecordRow } from "@exponential_app/eui/host";
2
+ import type { Failure, Vault } from "./broker.js";
3
+ import type { BlobStore } from "./tools.js";
4
+ /** One write of a batch (the store's spelling of the outbox writes). */
5
+ export type RecordWrite = {
6
+ op: `upsert`;
7
+ id: string;
8
+ kind: string;
9
+ data: Record<string, unknown>;
10
+ create: boolean;
11
+ } | {
12
+ op: `delete`;
13
+ id: string;
14
+ };
15
+ /** One call's writes, all or nothing, with its idempotency key. */
16
+ export interface WriteBatch {
17
+ writeId: string;
18
+ writes: RecordWrite[];
19
+ /** ISO time of the write (createdAt / updatedAt of what it touches). */
20
+ at: string;
21
+ }
22
+ /** The ids in write order; `replayed` = the writeId was applied before. */
23
+ export interface WriteAck {
24
+ ids: string[];
25
+ replayed: boolean;
26
+ }
27
+ /** One history event of a record. */
28
+ export interface RecordEvent {
29
+ recordId: string;
30
+ op: `create` | `update` | `delete`;
31
+ actor: string | null;
32
+ writeId: string;
33
+ patch: unknown;
34
+ before: unknown;
35
+ at: string;
36
+ }
37
+ export interface RecordsDelta {
38
+ upserts: RecordRow[];
39
+ deletes: string[];
40
+ }
41
+ /** Where an app's records live. Rejects with a `StoreError`. */
42
+ export interface EngineRecordStore {
43
+ rows(app: string): Promise<RecordRow[]>;
44
+ write(app: string, batch: WriteBatch, by: string | null): Promise<WriteAck>;
45
+ history(app: string, id: string): Promise<RecordEvent[]>;
46
+ /** Called with every change to `app`'s rows; returns the cancel. */
47
+ subscribe(app: string, on: (delta: RecordsDelta) => void): () => void;
48
+ }
49
+ /** A store's refusal as an Error carrying the Failure. */
50
+ export declare class StoreError extends Error implements Failure {
51
+ readonly code: string;
52
+ constructor(code: string, message: string);
53
+ }
54
+ /** Apply one batch to `rows` (all or nothing: throws with nothing changed).
55
+ * Answers the next rows, the ack, the delta and the events. */
56
+ export declare function applyBatch(rows: readonly RecordRow[], batch: WriteBatch, by: string | null): {
57
+ rows: RecordRow[];
58
+ ack: WriteAck;
59
+ delta: RecordsDelta;
60
+ events: RecordEvent[];
61
+ };
62
+ /** One committed batch, what a persistence stores in one transaction. */
63
+ export interface RecordCommit {
64
+ writeId: string;
65
+ ids: string[];
66
+ upserts: RecordRow[];
67
+ deletes: string[];
68
+ events: RecordEvent[];
69
+ }
70
+ /** Where a `LocalRecordStore` keeps its rows. */
71
+ export interface RecordPersistence {
72
+ load(app: string): Promise<RecordRow[]>;
73
+ /** The ids of an applied writeId, or null. */
74
+ ack(app: string, writeId: string): Promise<string[] | null>;
75
+ /** One batch, all or nothing. */
76
+ commit(app: string, commit: RecordCommit): Promise<void>;
77
+ history(app: string, id: string): Promise<RecordEvent[]>;
78
+ }
79
+ /** Every app's rows in memory over a persistence; writes run one at a time. */
80
+ export declare class LocalRecordStore implements EngineRecordStore {
81
+ readonly persistence: RecordPersistence;
82
+ private cache;
83
+ private listeners;
84
+ private queue;
85
+ constructor(persistence: RecordPersistence);
86
+ private loaded;
87
+ rows(app: string): Promise<RecordRow[]>;
88
+ write(app: string, batch: WriteBatch, by: string | null): Promise<WriteAck>;
89
+ history(app: string, id: string): Promise<RecordEvent[]>;
90
+ subscribe(app: string, on: (delta: RecordsDelta) => void): () => void;
91
+ }
92
+ /** The persistence of tests and previews. */
93
+ export declare class MemoryPersistence implements RecordPersistence {
94
+ private rows;
95
+ private acks;
96
+ private events;
97
+ load(app: string): Promise<RecordRow[]>;
98
+ ack(app: string, writeId: string): Promise<string[] | null>;
99
+ commit(app: string, commit: RecordCommit): Promise<void>;
100
+ history(app: string, id: string): Promise<RecordEvent[]>;
101
+ }
102
+ /** Every app's rows in memory (tests, previews). */
103
+ export declare class MemoryRecordStore extends LocalRecordStore {
104
+ constructor();
105
+ }
106
+ /** A process-local vault (tests, previews). */
107
+ export declare class MemoryVault implements Vault {
108
+ readonly values: Map<string, string>;
109
+ read(key: string): Promise<string | null>;
110
+ write(key: string, value: string): Promise<void>;
111
+ delete(key: string): Promise<void>;
112
+ }
113
+ /** Record files in memory (tests, previews). */
114
+ export declare class MemoryBlobStore implements BlobStore {
115
+ readonly files: Map<string, {
116
+ name: string;
117
+ mimeType: string;
118
+ bytes: Uint8Array;
119
+ }>;
120
+ put(app: string, name: string, mimeType: string, bytes: Uint8Array): Promise<string>;
121
+ get(app: string, id: string): Promise<Uint8Array | null>;
122
+ delete(app: string, id: string): Promise<void>;
123
+ }
124
+ /** The `local` identity's device uuid under `key` in the Vault, created once. */
125
+ export declare function localDeviceId(vault: Vault, key: string): Promise<string>;
@@ -0,0 +1,79 @@
1
+ import type { HubOutcome } from "../../emcp/src/index.js";
2
+ export type JsonSchema = Record<string, unknown>;
3
+ export interface CapabilityTool {
4
+ name: string;
5
+ runs: `native` | `engine`;
6
+ description: string;
7
+ inputSchema: JsonSchema;
8
+ nativeOutputSchema: JsonSchema | null;
9
+ outputSchema: JsonSchema;
10
+ }
11
+ export declare const CAPABILITY_TOOLS: readonly CapabilityTool[];
12
+ export declare const MIME_BY_EXTENSION: Readonly<Record<string, string>>;
13
+ export declare const toolDef: (name: string) => CapabilityTool | null;
14
+ /** A host's native provider of one capability (`name`, like the crate's
15
+ * `Capability`); `call` gets the bare tool (`pick`) and the mapped native
16
+ * arguments, and answers an MCP call result (`structuredContent` per
17
+ * `nativeOutputSchema`, or `isError`). */
18
+ export interface NativeCapability {
19
+ name: string;
20
+ call(tool: string, args: Record<string, unknown>): Promise<unknown>;
21
+ }
22
+ /** `bridgeCall`'s `native` over a host's capabilities: `photos_pick` → the
23
+ * `photos` provider's `pick`; a capability the host lacks answers `unavailable`. */
24
+ export declare const nativeCaller: (capabilities: readonly NativeCapability[]) => (tool: string, args: Record<string, unknown>) => Promise<unknown>;
25
+ /** The first violation of `value` against `schema` as `<pointer> <keyword>`, or null. */
26
+ export declare function schemaViolation(schema: JsonSchema, value: unknown, path?: readonly string[]): string | null;
27
+ export type ValidateResult = {
28
+ arguments: Record<string, unknown>;
29
+ } | {
30
+ error: string;
31
+ };
32
+ /** A call's arguments against the tool's `inputSchema`; a missing top-level
33
+ * property with a `default` gets it. */
34
+ export declare function validateToolArguments(tool: string, args: unknown): ValidateResult;
35
+ export declare function base64Encode(bytes: Uint8Array): string;
36
+ /** Strict: the standard alphabet, padded, no whitespace, zero trailing bits; null otherwise. */
37
+ export declare function base64Decode(s: string): Uint8Array | null;
38
+ /** The type the bytes tell (PDF, JPEG, PNG, GIF), or null. */
39
+ export declare function sniffMime(bytes: Uint8Array): string | null;
40
+ /** A file's MIME type: the given one, else its name's extension, else its bytes,
41
+ * else text/plain for a text and application/octet-stream. */
42
+ export declare function mimeFor(name: string, bytes: Uint8Array, given: string | null | undefined, isText: boolean): string;
43
+ /** A notification id the app did not name: `n-` + 32 lowercase hex. */
44
+ export declare function newNotificationId(): string;
45
+ export interface BlobStore {
46
+ get(app: string, id: string): Promise<Uint8Array | null>;
47
+ /** Stores the bytes as an app file; answers its id. */
48
+ put(app: string, name: string, mimeType: string, bytes: Uint8Array): Promise<string>;
49
+ }
50
+ export interface BridgeContext {
51
+ app: string;
52
+ screens: readonly string[];
53
+ }
54
+ export interface McpCallResult {
55
+ content: {
56
+ type: `text`;
57
+ text: string;
58
+ }[];
59
+ structuredContent?: unknown;
60
+ isError?: true;
61
+ }
62
+ export interface BridgeInput {
63
+ tool: string;
64
+ arguments: unknown;
65
+ context: BridgeContext;
66
+ blobs: BlobStore;
67
+ native: (tool: string, args: Record<string, unknown>) => Promise<unknown>;
68
+ newId?: () => string;
69
+ }
70
+ export interface BridgeOutput {
71
+ result: McpCallResult;
72
+ outcome: HubOutcome;
73
+ }
74
+ export declare const toolResult: (structuredContent: unknown) => McpCallResult;
75
+ export declare const toolError: (text: string) => McpCallResult;
76
+ /** One capability call from the broker's `call` verdict to its answer. */
77
+ export declare function bridgeCall(input: BridgeInput): Promise<BridgeOutput>;
78
+ /** print.pdf's default file name: the title with `/\:*?"<>|` and controls as `-`, + `.pdf`. */
79
+ export declare const pdfFileName: (title: string) => string;
@@ -0,0 +1,20 @@
1
+ import type { OpenPickerOptions, WebPlatform } from "./platform.js";
2
+ export * from "./mcp.js";
3
+ export * from "./platform.js";
4
+ export * from "./stores.js";
5
+ import type { NativeCapability } from "../tools.js";
6
+ export type { NativeCapability };
7
+ export interface WebCapabilityOptions {
8
+ /** A notification was tapped: `tap` = the lifecycle event posted with it, verbatim. */
9
+ onTap?(tap: unknown): void;
10
+ }
11
+ /** The OPFS directory that is the app's photo library. */
12
+ export declare const PHOTOS_DIR = "photos";
13
+ /** `accept` (MIME types or `.ext`) as `showOpenFilePicker` types. */
14
+ export declare const pickerTypes: (accept: string[]) => OpenPickerOptions[`types`];
15
+ /**
16
+ * The web's native capabilities, leaving out what this browser lacks
17
+ * (no `navigator.share` = no share, no Notification = no notifications).
18
+ * photos, files and print are always there (photos without OPFS = an empty library).
19
+ */
20
+ export declare const webCapabilities: (platform?: WebPlatform, opts?: WebCapabilityOptions) => NativeCapability[];
@@ -0,0 +1,27 @@
1
+ /** An MCP call result as a native capability answers it. */
2
+ export type McpResult = {
3
+ content: [{
4
+ type: `text`;
5
+ text: string;
6
+ }];
7
+ structuredContent: Record<string, unknown>;
8
+ } | {
9
+ content: [{
10
+ type: `text`;
11
+ text: string;
12
+ }];
13
+ isError: true;
14
+ };
15
+ export declare const ok: (structuredContent: Record<string, unknown>) => McpResult;
16
+ export declare const fail: (reason: string) => McpResult;
17
+ export declare const notFound: () => McpResult;
18
+ export declare const unavailable: () => McpResult;
19
+ export declare const failed: (message: string) => McpResult;
20
+ /** The message of anything thrown, short and on one line. */
21
+ export declare const errorMessage: (error: unknown) => string;
22
+ /** A DOMException-style abort (a cancelled picker or share sheet). */
23
+ export declare const isAbort: (error: unknown) => boolean;
24
+ /** Standard padded base64. */
25
+ export declare const encodeBase64: (bytes: Uint8Array) => string;
26
+ /** Strict standard padded base64 (no whitespace, no URL alphabet, zero pad bits); null when malformed. */
27
+ export declare const decodeBase64: (text: string) => Uint8Array | null;
@@ -0,0 +1,91 @@
1
+ /** The parts of a `File` the capabilities read. */
2
+ export interface FileLike {
3
+ readonly name: string;
4
+ readonly type: string;
5
+ readonly lastModified: number;
6
+ arrayBuffer(): Promise<ArrayBuffer>;
7
+ }
8
+ /** File System Access / OPFS file handle (the parts used). */
9
+ export interface FileHandleLike {
10
+ readonly kind: `file`;
11
+ readonly name: string;
12
+ getFile(): Promise<FileLike>;
13
+ createWritable(): Promise<WritableLike>;
14
+ }
15
+ export interface WritableLike {
16
+ write(data: Blob | Uint8Array): Promise<void>;
17
+ close(): Promise<void>;
18
+ }
19
+ /** An OPFS directory handle (the parts used). */
20
+ export interface DirectoryHandleLike {
21
+ readonly kind: `directory`;
22
+ readonly name: string;
23
+ getDirectoryHandle(name: string, options?: {
24
+ create?: boolean;
25
+ }): Promise<DirectoryHandleLike>;
26
+ getFileHandle(name: string, options?: {
27
+ create?: boolean;
28
+ }): Promise<FileHandleLike>;
29
+ values(): AsyncIterable<FileHandleLike | DirectoryHandleLike>;
30
+ }
31
+ /** `showOpenFilePicker` options (File System Access). */
32
+ export interface OpenPickerOptions {
33
+ multiple: boolean;
34
+ types?: {
35
+ description?: string;
36
+ accept: Record<string, string[]>;
37
+ }[];
38
+ excludeAcceptAllOption?: boolean;
39
+ }
40
+ export interface ShareDataLike {
41
+ title?: string;
42
+ text?: string;
43
+ url?: string;
44
+ files?: File[];
45
+ }
46
+ /** A shown notification (the parts used). */
47
+ export interface NotificationLike {
48
+ onclick: ((event: unknown) => void) | null;
49
+ onclose: ((event: unknown) => void) | null;
50
+ close(): void;
51
+ }
52
+ export interface NotificationsLike {
53
+ permission(): `default` | `granted` | `denied`;
54
+ requestPermission(): Promise<`default` | `granted` | `denied`>;
55
+ show(title: string, options: {
56
+ body?: string;
57
+ tag: string;
58
+ }): NotificationLike;
59
+ }
60
+ export type TimerHandle = unknown;
61
+ export interface WebPlatform {
62
+ /** File System Access open picker; throws AbortError on cancel. */
63
+ showOpenFilePicker?(options: OpenPickerOptions): Promise<FileHandleLike[]>;
64
+ /** File System Access save picker; throws AbortError on cancel. */
65
+ showSaveFilePicker?(options: {
66
+ suggestedName: string;
67
+ }): Promise<FileHandleLike>;
68
+ /** A hidden `<input type=file>`; resolves [] when the person cancels. */
69
+ pickWithInput(options: {
70
+ accept: string;
71
+ multiple: boolean;
72
+ }): Promise<FileLike[]>;
73
+ /** A download through an `<a download>` blob URL. */
74
+ download(name: string, blob: Blob): void;
75
+ /** `navigator.share` and `navigator.canShare`. */
76
+ share?(data: ShareDataLike): Promise<void>;
77
+ canShare?(data: ShareDataLike): boolean;
78
+ /** A hidden iframe on a blob URL, `contentWindow.print()` once loaded, then removed. */
79
+ print(blob: Blob): Promise<void>;
80
+ /** `navigator.storage.getDirectory()` (OPFS). */
81
+ storageDirectory?(): Promise<DirectoryHandleLike>;
82
+ /** The Notification API. */
83
+ notifications?: NotificationsLike;
84
+ now(): number;
85
+ setTimeout(fn: () => void, ms: number): TimerHandle;
86
+ clearTimeout(handle: TimerHandle): void;
87
+ /** window.focus(). */
88
+ focus(): void;
89
+ }
90
+ /** The real browser. Call it in a page (it reads `window`, `document` and `navigator`). */
91
+ export declare const browserPlatform: () => WebPlatform;
@@ -0,0 +1,125 @@
1
+ import type { RecordRow } from "@exponential_app/eui/host";
2
+ import type { Vault } from "../broker.js";
3
+ import { LocalRecordStore, type RecordCommit, type RecordEvent, type RecordPersistence } from "../stores.js";
4
+ import type { BlobStore } from "../tools.js";
5
+ /** The schema (idempotent): the crate's `sqlite::SCHEMA`, statement for statement. */
6
+ export declare const SQLITE_SCHEMA: string[];
7
+ export type SqlValue = string | number | null;
8
+ export interface SqlStatement {
9
+ sql: string;
10
+ bind?: SqlValue[];
11
+ }
12
+ /** A synchronous SQLite connection (sqlite-wasm's oo1 `DB`, `bun:sqlite` in tests). */
13
+ export interface SyncSqlDatabase {
14
+ /** Rows as objects keyed by column name. */
15
+ query(sql: string, bind: SqlValue[]): Record<string, SqlValue>[];
16
+ run(sql: string, bind: SqlValue[]): void;
17
+ }
18
+ /** The page's handle on the worker's database. */
19
+ export interface SqlDatabase {
20
+ query(sql: string, bind?: SqlValue[]): Promise<Record<string, SqlValue>[]>;
21
+ /** The statements in ONE transaction: all or nothing. */
22
+ transaction(statements: SqlStatement[]): Promise<void>;
23
+ }
24
+ type SqlRequest = {
25
+ id: number;
26
+ op: `query`;
27
+ sql: string;
28
+ bind: SqlValue[];
29
+ } | {
30
+ id: number;
31
+ op: `transaction`;
32
+ statements: SqlStatement[];
33
+ };
34
+ type SqlResponse = {
35
+ id: number;
36
+ rows?: Record<string, SqlValue>[];
37
+ error?: string;
38
+ };
39
+ /** The smallest MessagePort a worker and a page share. */
40
+ export interface PortLike {
41
+ postMessage(message: unknown): void;
42
+ addEventListener(type: `message`, listener: (event: {
43
+ data: unknown;
44
+ }) => void): void;
45
+ }
46
+ /** Run one request against `db` (the worker's half, a transaction rolls back on any failure). */
47
+ export declare function answerSql(db: SyncSqlDatabase, request: SqlRequest): SqlResponse;
48
+ /** Serve `db` over `port` (call it inside the worker once the database is open). */
49
+ export declare function serveSql(db: SyncSqlDatabase, port: PortLike): void;
50
+ /** The page's client of a worker's `serveSql`. */
51
+ export declare function sqlClient(port: PortLike): SqlDatabase;
52
+ /** The crate's `SqliteRecordStore` tables over a `SqlDatabase`. */
53
+ export declare class SqlitePersistence implements RecordPersistence {
54
+ private readonly db;
55
+ constructor(db: SqlDatabase);
56
+ load(app: string): Promise<RecordRow[]>;
57
+ ack(app: string, writeId: string): Promise<string[] | null>;
58
+ commit(app: string, c: RecordCommit): Promise<void>;
59
+ history(app: string, id: string): Promise<RecordEvent[]>;
60
+ }
61
+ /** Open (and create) the runner's IndexedDB database: records, writes, events and the vault. */
62
+ export declare function openRunnerIdb(factory: IDBFactory, name: string): Promise<IDBDatabase>;
63
+ /** The records' fallback when OPFS has no sync access handles: one IndexedDB transaction per batch. */
64
+ export declare class IndexedDbPersistence implements RecordPersistence {
65
+ private readonly db;
66
+ constructor(db: IDBDatabase);
67
+ load(app: string): Promise<RecordRow[]>;
68
+ ack(app: string, writeId: string): Promise<string[] | null>;
69
+ commit(app: string, c: RecordCommit): Promise<void>;
70
+ history(app: string, id: string): Promise<RecordEvent[]>;
71
+ }
72
+ /** The Vault in IndexedDB (runner.json `storage`: the web's keystore). */
73
+ export declare class IndexedDbVault implements Vault {
74
+ private readonly db;
75
+ constructor(db: IDBDatabase);
76
+ read(key: string): Promise<string | null>;
77
+ write(key: string, value: string): Promise<void>;
78
+ delete(key: string): Promise<void>;
79
+ }
80
+ /** An OPFS directory (the parts the BlobStore uses). */
81
+ export interface OpfsDirectory {
82
+ getDirectoryHandle(name: string, options?: {
83
+ create?: boolean;
84
+ }): Promise<OpfsDirectory>;
85
+ getFileHandle(name: string, options?: {
86
+ create?: boolean;
87
+ }): Promise<{
88
+ getFile(): Promise<{
89
+ arrayBuffer(): Promise<ArrayBuffer>;
90
+ }>;
91
+ createWritable(): Promise<{
92
+ write(data: Uint8Array | string): Promise<void>;
93
+ close(): Promise<void>;
94
+ }>;
95
+ }>;
96
+ removeEntry(name: string): Promise<void>;
97
+ }
98
+ /** Record files in OPFS: `<root>/<app>/<id>` (+ `<id>.json` with name and mime), the crate's `FsBlobStore` layout. */
99
+ export declare class OpfsBlobStore implements BlobStore {
100
+ private readonly root;
101
+ constructor(root: () => Promise<OpfsDirectory>);
102
+ private dir;
103
+ private writeFile;
104
+ put(app: string, name: string, mimeType: string, bytes: Uint8Array): Promise<string>;
105
+ get(app: string, id: string): Promise<Uint8Array | null>;
106
+ delete(app: string, id: string): Promise<void>;
107
+ }
108
+ export interface WebStorage {
109
+ records: LocalRecordStore;
110
+ /** Which records backend opened: `sqlite` (OPFS) or the `indexeddb` fallback. */
111
+ backend: `sqlite` | `indexeddb`;
112
+ vault: Vault;
113
+ blobs: BlobStore;
114
+ }
115
+ /** The runner's stores: SQLite on OPFS when `openSqlite` opens, else IndexedDB. */
116
+ export declare function openWebStorage(options: {
117
+ indexedDB: IDBFactory;
118
+ /** The IndexedDB database name (per app id). */
119
+ idbName: string;
120
+ /** Opens the worker's SQLite on OPFS; rejects when OPFS's sync access handles are missing. */
121
+ openSqlite?: () => Promise<SqlDatabase>;
122
+ /** The OPFS directory `storage.files` lives in. */
123
+ files: () => Promise<OpfsDirectory>;
124
+ }): Promise<WebStorage>;
125
+ export {};