syncorejs 0.2.3 → 0.2.5
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/dist/_dashboard/assets/ConfirmActionDialog-Db4VzVp6.js +1 -0
- package/dist/_dashboard/assets/circle-x-VsB4Z8W4.js +1 -0
- package/dist/_dashboard/assets/data.lazy-DjdU9CzX.js +18 -0
- package/dist/_dashboard/assets/file-code-BrOKjG4n.js +1 -0
- package/dist/_dashboard/assets/functions.lazy-DvDwAGHq.js +1 -0
- package/dist/_dashboard/assets/funnel-BH8EMMJI.js +1 -0
- package/dist/_dashboard/assets/index-DT9ZEELb.css +1 -0
- package/dist/_dashboard/assets/index-DrSG4qZZ.js +54 -0
- package/dist/_dashboard/assets/loader-circle-CmJFSYga.js +1 -0
- package/dist/_dashboard/assets/logs.lazy-50KTk5yd.js +1 -0
- package/dist/_dashboard/assets/play-DS52VsLN.js +1 -0
- package/dist/_dashboard/assets/queries.lazy-CfysRWkz.js +1 -0
- package/dist/_dashboard/assets/scheduler.lazy-BB88mZk-.js +1 -0
- package/dist/_dashboard/assets/select-THYcR8Wt.js +1 -0
- package/dist/_dashboard/assets/separator-BU7xg615.js +1 -0
- package/dist/_dashboard/assets/shared-Bh0wwC2k.js +1 -0
- package/dist/_dashboard/assets/sql.lazy-CHtU9Qnt.js +13 -0
- package/dist/_dashboard/assets/storage.lazy-CneN7wVU.js +1 -0
- package/dist/_dashboard/assets/table-2-CH8JoMXf.js +1 -0
- package/dist/_dashboard/index.html +18 -0
- package/dist/_vendor/cli/app.d.mts.map +1 -1
- package/dist/_vendor/cli/app.mjs +16 -5
- package/dist/_vendor/cli/app.mjs.map +1 -1
- package/dist/_vendor/core/cli.d.mts.map +1 -1
- package/dist/_vendor/core/cli.mjs +358 -16
- package/dist/_vendor/core/cli.mjs.map +1 -1
- package/dist/_vendor/core/index.d.mts +3 -3
- package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/devtools.mjs +131 -0
- package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
- package/dist/_vendor/core/runtime/functions.d.mts +3 -3
- package/dist/_vendor/core/runtime/functions.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs +1 -1
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs +4 -1
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs +6 -3
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs +5 -1
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs +99 -13
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs +38 -4
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs.map +1 -1
- package/dist/_vendor/core/runtime/runtime.d.mts +65 -8
- package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
- package/dist/_vendor/core/transport.d.mts.map +1 -1
- package/dist/_vendor/core/transport.mjs +30 -5
- package/dist/_vendor/core/transport.mjs.map +1 -1
- package/dist/_vendor/devtools-protocol/index.d.ts +75 -1
- package/dist/_vendor/devtools-protocol/index.d.ts.map +1 -1
- package/dist/_vendor/devtools-protocol/index.js.map +1 -1
- package/dist/_vendor/next/index.js +9 -1
- package/dist/_vendor/next/index.js.map +1 -1
- package/dist/_vendor/platform-expo/index.d.ts +1 -1
- package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
- package/dist/_vendor/platform-expo/index.js +6 -1
- package/dist/_vendor/platform-expo/index.js.map +1 -1
- package/dist/_vendor/platform-node/index.d.mts +2 -1
- package/dist/_vendor/platform-node/index.d.mts.map +1 -1
- package/dist/_vendor/platform-node/index.mjs +27 -2
- package/dist/_vendor/platform-node/index.mjs.map +1 -1
- package/dist/_vendor/platform-node/ipc-react.mjs +4 -0
- package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -1
- package/dist/_vendor/platform-web/external-change.d.ts +2 -2
- package/dist/_vendor/platform-web/external-change.js +2 -2
- package/dist/_vendor/platform-web/external-change.js.map +1 -1
- package/dist/_vendor/platform-web/index.d.ts +13 -10
- package/dist/_vendor/platform-web/index.d.ts.map +1 -1
- package/dist/_vendor/platform-web/index.js +66 -10
- package/dist/_vendor/platform-web/index.js.map +1 -1
- package/dist/_vendor/platform-web/indexeddb.d.ts +3 -3
- package/dist/_vendor/platform-web/indexeddb.js +3 -3
- package/dist/_vendor/platform-web/indexeddb.js.map +1 -1
- package/dist/_vendor/platform-web/opfs.d.ts +3 -1
- package/dist/_vendor/platform-web/opfs.d.ts.map +1 -1
- package/dist/_vendor/platform-web/opfs.js +29 -3
- package/dist/_vendor/platform-web/opfs.js.map +1 -1
- package/dist/_vendor/platform-web/persistence.d.ts +31 -1
- package/dist/_vendor/platform-web/persistence.d.ts.map +1 -1
- package/dist/_vendor/platform-web/persistence.js.map +1 -1
- package/dist/_vendor/platform-web/react.d.ts.map +1 -1
- package/dist/_vendor/platform-web/react.js +9 -1
- package/dist/_vendor/platform-web/react.js.map +1 -1
- package/dist/_vendor/react/index.d.ts +6 -5
- package/dist/_vendor/react/index.d.ts.map +1 -1
- package/dist/_vendor/react/index.js +6 -5
- package/dist/_vendor/react/index.js.map +1 -1
- package/dist/_vendor/svelte/index.d.ts +8 -6
- package/dist/_vendor/svelte/index.d.ts.map +1 -1
- package/dist/_vendor/svelte/index.js +7 -5
- package/dist/_vendor/svelte/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.mjs","names":[],"sources":["../../../../src/runtime/internal/engines/shared.ts"],"sourcesContent":["import { fromZonedTime, toZonedTime } from \"date-fns-tz\";\nimport type {\n DevtoolsPreview,\n DocumentChangePreview,\n SyncoreDevtoolsEvent,\n SyncoreDevtoolsEventOrigin\n} from \"@syncore/devtools-protocol\";\nimport {\n searchIndexTableName,\n type TableDefinition,\n type Validator\n} from \"@syncore/schema\";\nimport type {\n MisfirePolicy,\n RecurringSchedule,\n SyncoreFunctionKind\n} from \"../../functions.js\";\nimport type { SyncoreComponentFunctionMetadata } from \"../../components.js\";\nimport type {\n DevtoolsLiveQueryScope,\n JsonObject,\n QueryCondition,\n QueryExpression,\n SearchQuery,\n SyncoreDataModel,\n SyncoreExternalChangeReason\n} from \"../../runtime.js\";\n\nexport type DatabaseRow = {\n _id: string;\n _creationTime: number;\n _json: string;\n};\n\nexport type DependencyKey = string;\n\nexport type ActiveQueryRecord = {\n id: string;\n functionName: string;\n args: JsonObject;\n listeners: Set<() => void>;\n consumers: number;\n dependencyKeys: Set<DependencyKey>;\n lastResult: unknown;\n lastError: Error | undefined;\n lastRunAt: number;\n};\n\nexport type DevtoolsEventMeta = {\n origin?: SyncoreDevtoolsEventOrigin;\n executionId?: string;\n parentExecutionId?: string;\n schedulerJobId?: string;\n schedulerRun?: boolean;\n};\n\nexport type ScheduledJobRow = {\n id: string;\n function_name: string;\n function_kind: SyncoreFunctionKind;\n args_json: string;\n status: \"scheduled\" | \"completed\" | \"failed\" | \"cancelled\" | \"skipped\";\n run_at: number;\n created_at: number;\n updated_at: number;\n recurring_name: string | null;\n schedule_json: string | null;\n timezone: string | null;\n misfire_policy: string;\n last_run_at: number | null;\n window_ms: number | null;\n};\n\nexport type StorageMetadataRow = {\n _id: string;\n _creationTime: number;\n file_name: string | null;\n content_type: string | null;\n size: number;\n path: string;\n};\n\nexport type StoragePendingRow = {\n _id: string;\n _creationTime: number;\n file_name: string | null;\n content_type: string | null;\n};\n\nexport type QuerySource =\n | { type: \"table\" }\n | { type: \"index\"; name: string; range: QueryCondition[] }\n | { type: \"search\"; name: string; query: SearchQuery };\n\nexport type ExecuteQueryBuilderOptions = {\n tableName: string;\n source: QuerySource;\n filterExpression: QueryExpression | undefined;\n orderDirection: \"asc\" | \"desc\";\n dependencyCollector?: Set<DependencyKey>;\n limit?: number;\n offset?: number;\n};\n\nexport type RuntimeExecutionState = {\n executionId?: string;\n mutationDepth: number;\n changedTables: Set<string>;\n documentChanges: DocumentChangePreview[];\n storageChanges: Array<{\n storageId: string;\n reason: Extract<\n SyncoreExternalChangeReason,\n \"storage-put\" | \"storage-delete\"\n >;\n }>;\n dependencyCollector?: Set<DependencyKey>;\n componentMetadata?: SyncoreComponentFunctionMetadata | undefined;\n};\n\nconst PREVIEW_MAX_DEPTH = 5;\nconst PREVIEW_MAX_ARRAY_ITEMS = 50;\nconst PREVIEW_MAX_OBJECT_KEYS = 80;\nconst PREVIEW_MAX_STRING_LENGTH = 4000;\n\nexport function createDevtoolsPreview(value: unknown): DevtoolsPreview {\n const seen = new WeakSet<object>();\n let truncated = false;\n\n const preview = (input: unknown, depth: number): unknown => {\n if (typeof input === \"string\") {\n if (input.length > PREVIEW_MAX_STRING_LENGTH) {\n truncated = true;\n return `${input.slice(0, PREVIEW_MAX_STRING_LENGTH)}...`;\n }\n return input;\n }\n if (\n input === null ||\n typeof input === \"number\" ||\n typeof input === \"boolean\"\n ) {\n return input;\n }\n if (typeof input === \"bigint\") {\n return `${input.toString()}n`;\n }\n if (input === undefined) {\n return \"[undefined]\";\n }\n if (typeof input === \"function\") {\n truncated = true;\n return \"[function]\";\n }\n if (typeof input === \"symbol\") {\n truncated = true;\n return input.toString();\n }\n if (input instanceof Error) {\n return {\n name: input.name,\n message: input.message,\n ...(input.stack ? { stack: input.stack } : {})\n };\n }\n if (input instanceof Date) {\n return input.toISOString();\n }\n if (typeof input !== \"object\") {\n return String(input);\n }\n if (seen.has(input)) {\n truncated = true;\n return \"[circular]\";\n }\n if (depth >= PREVIEW_MAX_DEPTH) {\n truncated = true;\n return Array.isArray(input) ? \"[array]\" : \"[object]\";\n }\n\n seen.add(input);\n if (Array.isArray(input)) {\n const items = input\n .slice(0, PREVIEW_MAX_ARRAY_ITEMS)\n .map((item) => preview(item, depth + 1));\n if (input.length > PREVIEW_MAX_ARRAY_ITEMS) {\n truncated = true;\n items.push(`[${input.length - PREVIEW_MAX_ARRAY_ITEMS} more items]`);\n }\n seen.delete(input);\n return items;\n }\n\n const entries = Object.entries(input as Record<string, unknown>);\n const result: Record<string, unknown> = {};\n for (const [key, nested] of entries.slice(0, PREVIEW_MAX_OBJECT_KEYS)) {\n result[key] = preview(nested, depth + 1);\n }\n if (entries.length > PREVIEW_MAX_OBJECT_KEYS) {\n truncated = true;\n result.__truncatedKeys = entries.length - PREVIEW_MAX_OBJECT_KEYS;\n }\n seen.delete(input);\n return result;\n };\n\n try {\n return {\n kind: \"value\",\n value: preview(value, 0),\n ...(truncated ? { truncated: true } : {})\n };\n } catch (error) {\n return {\n kind: \"error\",\n message: error instanceof Error ? error.message : String(error),\n truncated: true\n };\n }\n}\n\nexport function fieldExpression(tableAlias: string, field: string): string {\n const prefix = tableAlias ? `${tableAlias}.` : \"\";\n return `json_extract(${prefix}_json, '$.${field}')`;\n}\n\nexport function quoteIdentifier(identifier: string): string {\n return `\"${identifier.replaceAll('\"', '\"\"')}\"`;\n}\n\nexport function stableStringify(value: unknown): string {\n return JSON.stringify(sortValue(value));\n}\n\nexport function sortValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(sortValue);\n }\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, nested]) => [key, sortValue(nested)])\n );\n }\n return value;\n}\n\nexport function omitSystemFields<TDocument extends object>(\n document: TDocument\n): JsonObject {\n const clone = { ...(document as Record<string, unknown>) };\n delete clone._id;\n delete clone._creationTime;\n return clone;\n}\n\nexport function toSearchValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n if (value === null || value === undefined) {\n return \"\";\n }\n if (\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n typeof value === \"bigint\"\n ) {\n return String(value);\n }\n return stableStringify(value);\n}\n\nexport function parseMisfirePolicy(\n type: string,\n windowMs: number | null\n): MisfirePolicy {\n if (type === \"windowed\") {\n return { type, windowMs: windowMs ?? 0 };\n }\n if (type === \"skip\" || type === \"run_once_if_missed\") {\n return { type };\n }\n return { type: \"catch_up\" };\n}\n\nexport function shouldRunMissedJob(\n scheduledAt: number,\n now: number,\n policy: MisfirePolicy\n): boolean {\n if (scheduledAt >= now) {\n return true;\n }\n switch (policy.type) {\n case \"catch_up\":\n return true;\n case \"run_once_if_missed\":\n return true;\n case \"skip\":\n return false;\n case \"windowed\":\n return now - scheduledAt <= policy.windowMs;\n }\n}\n\nexport function computeNextRun(\n schedule: RecurringSchedule,\n fromTimestamp: number\n): number {\n switch (schedule.type) {\n case \"interval\":\n return fromTimestamp + intervalToMs(schedule);\n case \"daily\":\n return nextDailyOccurrence(fromTimestamp, schedule);\n case \"weekly\":\n return nextWeeklyOccurrence(fromTimestamp, schedule);\n }\n}\n\nexport function safeReadRecurringSchedule(\n scheduleJson: string | null\n): RecurringSchedule | undefined {\n if (!scheduleJson) {\n return undefined;\n }\n try {\n const parsed = JSON.parse(scheduleJson) as unknown;\n return isRecurringSchedule(parsed) ? parsed : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function normalizeOptionalArgs<TArgs>(\n args: [] | [TArgs] | readonly unknown[]\n): TArgs {\n return (args[0] ?? {}) as TArgs;\n}\n\nexport function splitSchedulerArgs(\n args: readonly unknown[]\n): [JsonObject, MisfirePolicy | undefined] {\n if (args.length === 0) {\n return [{}, undefined];\n }\n if (args.length === 1) {\n const [first] = args;\n if (isMisfirePolicy(first)) {\n return [{}, first];\n }\n return [(first ?? {}) as JsonObject, undefined];\n }\n return [(args[0] ?? {}) as JsonObject, args[1] as MisfirePolicy | undefined];\n}\n\nexport function inferDriverDatabasePath(driver: {\n filename?: string;\n databasePath?: string;\n}): string | undefined {\n return driver.databasePath ?? driver.filename;\n}\n\nexport function parseCanonicalComponentFunctionName(functionName: string):\n | {\n componentPath: string;\n visibility: \"public\" | \"internal\";\n localName: string;\n }\n | undefined {\n const match = /^components\\/(.+)\\/(public|internal)\\/(.+)$/.exec(functionName);\n if (!match) {\n return undefined;\n }\n return {\n componentPath: match[1] ?? \"\",\n visibility: (match[2] as \"public\" | \"internal\") ?? \"public\",\n localName: match[3] ?? \"\"\n };\n}\n\nexport function parseComponentScopedIdentifier(\n value: string\n): { componentPath: string; localId: string } | undefined {\n const match = /^component:([^:]+):(.+)$/.exec(value);\n if (!match) {\n return undefined;\n }\n return {\n componentPath: match[1] ?? \"\",\n localId: match[2] ?? \"\"\n };\n}\n\nexport function devtoolsScopesForEvent(\n event: SyncoreDevtoolsEvent\n): Set<DevtoolsLiveQueryScope> {\n switch (event.type) {\n case \"runtime.connected\":\n case \"runtime.disconnected\":\n return new Set([\"runtime.summary\", \"runtime.activeQueries\"]);\n case \"query.executed\":\n case \"query.invalidated\":\n return new Set([\"runtime.summary\", \"runtime.activeQueries\"]);\n case \"mutation.committed\":\n return new Set([\n \"runtime.summary\",\n ...event.changedTables.map((table: string) => `table:${table}` as const)\n ]);\n case \"scheduler.tick\":\n return new Set([\"scheduler.jobs\", \"runtime.summary\"]);\n case \"storage.updated\":\n return new Set([\"runtime.summary\"]);\n case \"action.completed\":\n case \"log\":\n return new Set([\"runtime.summary\"]);\n default:\n return new Set([\"runtime.summary\"]);\n }\n}\n\nexport function getTableDefinition<\n TSchema extends SyncoreDataModel\n>(\n schema: TSchema,\n tableName: string\n): TableDefinition<\n Validator<Record<string, unknown>, Record<string, unknown>, string>\n> {\n return schema.getTable(tableName as never) as TableDefinition<\n Validator<Record<string, unknown>, Record<string, unknown>, string>\n >;\n}\n\nexport function searchIndexKey(tableName: string, indexName: string): string {\n return `${tableName}:${indexName}`;\n}\n\nexport function resolveSearchIndexTableName(\n tableName: string,\n indexName: string\n): string {\n return searchIndexTableName(tableName, indexName);\n}\n\nfunction intervalToMs(schedule: {\n seconds?: number;\n minutes?: number;\n hours?: number;\n}): number {\n if (schedule.seconds) {\n return schedule.seconds * 1000;\n }\n if (schedule.minutes) {\n return schedule.minutes * 60 * 1000;\n }\n return (schedule.hours ?? 1) * 60 * 60 * 1000;\n}\n\nfunction nextDailyOccurrence(\n fromTimestamp: number,\n schedule: Extract<RecurringSchedule, { type: \"daily\" }>\n): number {\n const timezone = schedule.timezone ?? \"UTC\";\n const now = new Date(fromTimestamp);\n const zonedNow = toZonedTime(now, timezone);\n const zoned = new Date(zonedNow.getTime());\n zoned.setHours(schedule.hour, schedule.minute, 0, 0);\n if (zoned.getTime() <= zonedNow.getTime()) {\n zoned.setDate(zoned.getDate() + 1);\n }\n return fromZonedTime(zoned, timezone).getTime();\n}\n\nfunction nextWeeklyOccurrence(\n fromTimestamp: number,\n schedule: Extract<RecurringSchedule, { type: \"weekly\" }>\n): number {\n const timezone = schedule.timezone ?? \"UTC\";\n const now = new Date(fromTimestamp);\n const zonedNow = toZonedTime(now, timezone);\n const targetDay = [\n \"sunday\",\n \"monday\",\n \"tuesday\",\n \"wednesday\",\n \"thursday\",\n \"friday\",\n \"saturday\"\n ].indexOf(schedule.dayOfWeek);\n const zoned = new Date(zonedNow.getTime());\n const delta = (targetDay - zonedNow.getDay() + 7) % 7;\n zoned.setDate(zoned.getDate() + delta);\n zoned.setHours(schedule.hour, schedule.minute, 0, 0);\n if (zoned.getTime() <= zonedNow.getTime()) {\n zoned.setDate(zoned.getDate() + 7);\n }\n return fromZonedTime(zoned, timezone).getTime();\n}\n\nfunction isRecurringSchedule(value: unknown): value is RecurringSchedule {\n if (!isRecord(value) || typeof value.type !== \"string\") {\n return false;\n }\n switch (value.type) {\n case \"interval\":\n return (\n isOptionalNumber(value.seconds) &&\n isOptionalNumber(value.minutes) &&\n isOptionalNumber(value.hours)\n );\n case \"daily\":\n return (\n typeof value.hour === \"number\" &&\n typeof value.minute === \"number\" &&\n isOptionalString(value.timezone)\n );\n case \"weekly\":\n return (\n isDayOfWeek(value.dayOfWeek) &&\n typeof value.hour === \"number\" &&\n typeof value.minute === \"number\" &&\n isOptionalString(value.timezone)\n );\n default:\n return false;\n }\n}\n\nfunction isMisfirePolicy(value: unknown): value is MisfirePolicy {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"type\" in value &&\n typeof (value as { type?: unknown }).type === \"string\"\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isOptionalNumber(value: unknown): value is number | undefined {\n return value === undefined || typeof value === \"number\";\n}\n\nfunction isOptionalString(value: unknown): value is string | undefined {\n return value === undefined || typeof value === \"string\";\n}\n\nfunction isDayOfWeek(\n value: unknown\n): value is Extract<RecurringSchedule, { type: \"weekly\" }>[\"dayOfWeek\"] {\n return (\n value === \"sunday\" ||\n value === \"monday\" ||\n value === \"tuesday\" ||\n value === \"wednesday\" ||\n value === \"thursday\" ||\n value === \"friday\" ||\n value === \"saturday\"\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shared.mjs","names":[],"sources":["../../../../src/runtime/internal/engines/shared.ts"],"sourcesContent":["import { fromZonedTime, toZonedTime } from \"date-fns-tz\";\nimport type {\n DevtoolsPreview,\n DocumentChangePreview,\n SyncoreDevtoolsEvent,\n SyncoreDevtoolsEventOrigin\n} from \"@syncore/devtools-protocol\";\nimport {\n searchIndexTableName,\n type TableDefinition,\n type Validator\n} from \"@syncore/schema\";\nimport type {\n MisfirePolicy,\n RecurringSchedule,\n SyncoreFunctionKind\n} from \"../../functions.js\";\nimport type { SyncoreComponentFunctionMetadata } from \"../../components.js\";\nimport type {\n DevtoolsLiveQueryScope,\n JsonObject,\n QueryCondition,\n QueryExpression,\n SearchQuery,\n SyncoreDataModel,\n SyncoreExternalChangeReason\n} from \"../../runtime.js\";\n\nexport type DatabaseRow = {\n _id: string;\n _creationTime: number;\n _json: string;\n};\n\nexport type DependencyKey = string;\n\nexport type ActiveQueryRecord = {\n id: string;\n functionName: string;\n args: JsonObject;\n listeners: Set<() => void>;\n consumers: number;\n dependencyKeys: Set<DependencyKey>;\n lastResult: unknown;\n lastError: Error | undefined;\n lastRunAt: number;\n};\n\nexport type DevtoolsEventMeta = {\n origin?: SyncoreDevtoolsEventOrigin;\n executionId?: string;\n parentExecutionId?: string;\n schedulerJobId?: string;\n schedulerRun?: boolean;\n};\n\nexport type ScheduledJobRow = {\n id: string;\n function_name: string;\n function_kind: SyncoreFunctionKind;\n args_json: string;\n status: \"scheduled\" | \"completed\" | \"failed\" | \"cancelled\" | \"skipped\";\n run_at: number;\n created_at: number;\n updated_at: number;\n recurring_name: string | null;\n schedule_json: string | null;\n timezone: string | null;\n misfire_policy: string;\n last_run_at: number | null;\n window_ms: number | null;\n};\n\nexport type StorageMetadataRow = {\n _id: string;\n _creationTime: number;\n file_name: string | null;\n content_type: string | null;\n size: number;\n path: string;\n};\n\nexport type StoragePendingRow = {\n _id: string;\n _creationTime: number;\n file_name: string | null;\n content_type: string | null;\n};\n\nexport type QuerySource =\n | { type: \"table\" }\n | { type: \"index\"; name: string; range: QueryCondition[] }\n | { type: \"search\"; name: string; query: SearchQuery };\n\nexport type ExecuteQueryBuilderOptions = {\n tableName: string;\n source: QuerySource;\n filterExpression: QueryExpression | undefined;\n orderDirection: \"asc\" | \"desc\";\n dependencyCollector?: Set<DependencyKey>;\n limit?: number;\n offset?: number;\n};\n\nexport type RuntimeExecutionState = {\n executionId?: string;\n mutationDepth: number;\n changedTables: Set<string>;\n documentChanges: DocumentChangePreview[];\n storageChanges: Array<{\n storageId: string;\n reason: Extract<\n SyncoreExternalChangeReason,\n \"storage-put\" | \"storage-delete\"\n >;\n }>;\n dependencyCollector?: Set<DependencyKey>;\n componentMetadata?: SyncoreComponentFunctionMetadata | undefined;\n};\n\nconst PREVIEW_MAX_DEPTH = 5;\nconst PREVIEW_MAX_ARRAY_ITEMS = 50;\nconst PREVIEW_MAX_OBJECT_KEYS = 80;\nconst PREVIEW_MAX_STRING_LENGTH = 4000;\n\nexport function createDevtoolsPreview(value: unknown): DevtoolsPreview {\n const seen = new WeakSet<object>();\n let truncated = false;\n\n const preview = (input: unknown, depth: number): unknown => {\n if (typeof input === \"string\") {\n if (input.length > PREVIEW_MAX_STRING_LENGTH) {\n truncated = true;\n return `${input.slice(0, PREVIEW_MAX_STRING_LENGTH)}...`;\n }\n return input;\n }\n if (\n input === null ||\n typeof input === \"number\" ||\n typeof input === \"boolean\"\n ) {\n return input;\n }\n if (typeof input === \"bigint\") {\n return `${input.toString()}n`;\n }\n if (input === undefined) {\n return \"[undefined]\";\n }\n if (typeof input === \"function\") {\n truncated = true;\n return \"[function]\";\n }\n if (typeof input === \"symbol\") {\n truncated = true;\n return input.toString();\n }\n if (input instanceof Error) {\n return {\n name: input.name,\n message: input.message,\n ...(input.stack ? { stack: input.stack } : {})\n };\n }\n if (input instanceof Date) {\n return input.toISOString();\n }\n if (typeof input !== \"object\") {\n return String(input);\n }\n if (seen.has(input)) {\n truncated = true;\n return \"[circular]\";\n }\n if (depth >= PREVIEW_MAX_DEPTH) {\n truncated = true;\n return Array.isArray(input) ? \"[array]\" : \"[object]\";\n }\n\n seen.add(input);\n if (Array.isArray(input)) {\n const items = input\n .slice(0, PREVIEW_MAX_ARRAY_ITEMS)\n .map((item) => preview(item, depth + 1));\n if (input.length > PREVIEW_MAX_ARRAY_ITEMS) {\n truncated = true;\n items.push(`[${input.length - PREVIEW_MAX_ARRAY_ITEMS} more items]`);\n }\n seen.delete(input);\n return items;\n }\n\n const entries = Object.entries(input as Record<string, unknown>);\n const result: Record<string, unknown> = {};\n for (const [key, nested] of entries.slice(0, PREVIEW_MAX_OBJECT_KEYS)) {\n result[key] = preview(nested, depth + 1);\n }\n if (entries.length > PREVIEW_MAX_OBJECT_KEYS) {\n truncated = true;\n result.__truncatedKeys = entries.length - PREVIEW_MAX_OBJECT_KEYS;\n }\n seen.delete(input);\n return result;\n };\n\n try {\n return {\n kind: \"value\",\n value: preview(value, 0),\n ...(truncated ? { truncated: true } : {})\n };\n } catch (error) {\n return {\n kind: \"error\",\n message: error instanceof Error ? error.message : String(error),\n truncated: true\n };\n }\n}\n\nexport function fieldExpression(tableAlias: string, field: string): string {\n const prefix = tableAlias ? `${tableAlias}.` : \"\";\n return `json_extract(${prefix}_json, '$.${field}')`;\n}\n\nexport function quoteIdentifier(identifier: string): string {\n return `\"${identifier.replaceAll('\"', '\"\"')}\"`;\n}\n\nexport function stableStringify(value: unknown): string {\n return JSON.stringify(sortValue(value));\n}\n\nexport function sortValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(sortValue);\n }\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, nested]) => [key, sortValue(nested)])\n );\n }\n return value;\n}\n\nexport function omitSystemFields<TDocument extends object>(\n document: TDocument\n): JsonObject {\n const clone = { ...(document as Record<string, unknown>) };\n delete clone._id;\n delete clone._creationTime;\n return clone;\n}\n\nexport function toSearchValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n if (value === null || value === undefined) {\n return \"\";\n }\n if (\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n typeof value === \"bigint\"\n ) {\n return String(value);\n }\n return stableStringify(value);\n}\n\nexport function parseMisfirePolicy(\n type: string,\n windowMs: number | null\n): MisfirePolicy {\n if (type === \"windowed\") {\n return { type, windowMs: windowMs ?? 0 };\n }\n if (type === \"skip\" || type === \"run_once_if_missed\") {\n return { type };\n }\n return { type: \"catch_up\" };\n}\n\nexport function shouldRunMissedJob(\n scheduledAt: number,\n now: number,\n policy: MisfirePolicy\n): boolean {\n if (scheduledAt >= now) {\n return true;\n }\n switch (policy.type) {\n case \"catch_up\":\n return true;\n case \"run_once_if_missed\":\n return true;\n case \"skip\":\n return false;\n case \"windowed\":\n return now - scheduledAt <= policy.windowMs;\n }\n}\n\nexport function computeNextRun(\n schedule: RecurringSchedule,\n fromTimestamp: number\n): number {\n switch (schedule.type) {\n case \"interval\":\n return fromTimestamp + intervalToMs(schedule);\n case \"daily\":\n return nextDailyOccurrence(fromTimestamp, schedule);\n case \"weekly\":\n return nextWeeklyOccurrence(fromTimestamp, schedule);\n }\n}\n\nexport function safeReadRecurringSchedule(\n scheduleJson: string | null\n): RecurringSchedule | undefined {\n if (!scheduleJson) {\n return undefined;\n }\n try {\n const parsed = JSON.parse(scheduleJson) as unknown;\n return isRecurringSchedule(parsed) ? parsed : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function normalizeOptionalArgs<TArgs>(\n args: [] | [TArgs] | readonly unknown[]\n): TArgs {\n return (args[0] ?? {}) as TArgs;\n}\n\nexport function splitSchedulerArgs(\n args: readonly unknown[]\n): [JsonObject, MisfirePolicy | undefined] {\n if (args.length === 0) {\n return [{}, undefined];\n }\n if (args.length === 1) {\n const [first] = args;\n if (isMisfirePolicy(first)) {\n return [{}, first];\n }\n return [(first ?? {}) as JsonObject, undefined];\n }\n return [(args[0] ?? {}) as JsonObject, args[1] as MisfirePolicy | undefined];\n}\n\nexport function inferDriverDatabasePath(driver: {\n filename?: string;\n databasePath?: string;\n}): string | undefined {\n return driver.databasePath ?? driver.filename;\n}\n\nexport function parseCanonicalComponentFunctionName(functionName: string):\n | {\n componentPath: string;\n visibility: \"public\" | \"internal\";\n localName: string;\n }\n | undefined {\n const match = /^components\\/(.+)\\/(public|internal)\\/(.+)$/.exec(functionName);\n if (!match) {\n return undefined;\n }\n return {\n componentPath: match[1] ?? \"\",\n visibility: (match[2] as \"public\" | \"internal\") ?? \"public\",\n localName: match[3] ?? \"\"\n };\n}\n\nexport function parseComponentScopedIdentifier(\n value: string\n): { componentPath: string; localId: string } | undefined {\n const match = /^component:([^:]+):(.+)$/.exec(value);\n if (!match) {\n return undefined;\n }\n return {\n componentPath: match[1] ?? \"\",\n localId: match[2] ?? \"\"\n };\n}\n\nexport function devtoolsScopesForEvent(\n event: SyncoreDevtoolsEvent\n): Set<DevtoolsLiveQueryScope> {\n switch (event.type) {\n case \"runtime.connected\":\n case \"runtime.disconnected\":\n return new Set([\"runtime.summary\", \"runtime.activeQueries\"]);\n case \"query.executed\":\n case \"query.invalidated\":\n return new Set([\"runtime.summary\", \"runtime.activeQueries\"]);\n case \"mutation.committed\":\n return new Set([\n \"runtime.summary\",\n ...event.changedTables.map((table: string) => `table:${table}` as const)\n ]);\n case \"scheduler.tick\":\n return new Set([\"scheduler.jobs\", \"runtime.summary\"]);\n case \"storage.updated\":\n return new Set<DevtoolsLiveQueryScope>([\n \"runtime.summary\",\n \"storage.objects\",\n `storage:${event.storageId}` as const\n ]);\n case \"action.completed\":\n case \"log\":\n return new Set([\"runtime.summary\"]);\n default:\n return new Set([\"runtime.summary\"]);\n }\n}\n\nexport function getTableDefinition<\n TSchema extends SyncoreDataModel\n>(\n schema: TSchema,\n tableName: string\n): TableDefinition<\n Validator<Record<string, unknown>, Record<string, unknown>, string>\n> {\n return schema.getTable(tableName as never) as TableDefinition<\n Validator<Record<string, unknown>, Record<string, unknown>, string>\n >;\n}\n\nexport function searchIndexKey(tableName: string, indexName: string): string {\n return `${tableName}:${indexName}`;\n}\n\nexport function resolveSearchIndexTableName(\n tableName: string,\n indexName: string\n): string {\n return searchIndexTableName(tableName, indexName);\n}\n\nfunction intervalToMs(schedule: {\n seconds?: number;\n minutes?: number;\n hours?: number;\n}): number {\n if (schedule.seconds) {\n return schedule.seconds * 1000;\n }\n if (schedule.minutes) {\n return schedule.minutes * 60 * 1000;\n }\n return (schedule.hours ?? 1) * 60 * 60 * 1000;\n}\n\nfunction nextDailyOccurrence(\n fromTimestamp: number,\n schedule: Extract<RecurringSchedule, { type: \"daily\" }>\n): number {\n const timezone = schedule.timezone ?? \"UTC\";\n const now = new Date(fromTimestamp);\n const zonedNow = toZonedTime(now, timezone);\n const zoned = new Date(zonedNow.getTime());\n zoned.setHours(schedule.hour, schedule.minute, 0, 0);\n if (zoned.getTime() <= zonedNow.getTime()) {\n zoned.setDate(zoned.getDate() + 1);\n }\n return fromZonedTime(zoned, timezone).getTime();\n}\n\nfunction nextWeeklyOccurrence(\n fromTimestamp: number,\n schedule: Extract<RecurringSchedule, { type: \"weekly\" }>\n): number {\n const timezone = schedule.timezone ?? \"UTC\";\n const now = new Date(fromTimestamp);\n const zonedNow = toZonedTime(now, timezone);\n const targetDay = [\n \"sunday\",\n \"monday\",\n \"tuesday\",\n \"wednesday\",\n \"thursday\",\n \"friday\",\n \"saturday\"\n ].indexOf(schedule.dayOfWeek);\n const zoned = new Date(zonedNow.getTime());\n const delta = (targetDay - zonedNow.getDay() + 7) % 7;\n zoned.setDate(zoned.getDate() + delta);\n zoned.setHours(schedule.hour, schedule.minute, 0, 0);\n if (zoned.getTime() <= zonedNow.getTime()) {\n zoned.setDate(zoned.getDate() + 7);\n }\n return fromZonedTime(zoned, timezone).getTime();\n}\n\nfunction isRecurringSchedule(value: unknown): value is RecurringSchedule {\n if (!isRecord(value) || typeof value.type !== \"string\") {\n return false;\n }\n switch (value.type) {\n case \"interval\":\n return (\n isOptionalNumber(value.seconds) &&\n isOptionalNumber(value.minutes) &&\n isOptionalNumber(value.hours)\n );\n case \"daily\":\n return (\n typeof value.hour === \"number\" &&\n typeof value.minute === \"number\" &&\n isOptionalString(value.timezone)\n );\n case \"weekly\":\n return (\n isDayOfWeek(value.dayOfWeek) &&\n typeof value.hour === \"number\" &&\n typeof value.minute === \"number\" &&\n isOptionalString(value.timezone)\n );\n default:\n return false;\n }\n}\n\nfunction isMisfirePolicy(value: unknown): value is MisfirePolicy {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"type\" in value &&\n typeof (value as { type?: unknown }).type === \"string\"\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isOptionalNumber(value: unknown): value is number | undefined {\n return value === undefined || typeof value === \"number\";\n}\n\nfunction isOptionalString(value: unknown): value is string | undefined {\n return value === undefined || typeof value === \"string\";\n}\n\nfunction isDayOfWeek(\n value: unknown\n): value is Extract<RecurringSchedule, { type: \"weekly\" }>[\"dayOfWeek\"] {\n return (\n value === \"sunday\" ||\n value === \"monday\" ||\n value === \"tuesday\" ||\n value === \"wednesday\" ||\n value === \"thursday\" ||\n value === \"friday\" ||\n value === \"saturday\"\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { generateId } from "../../id.mjs";
|
|
2
2
|
//#region src/runtime/internal/engines/storageEngine.ts
|
|
3
|
+
const STORAGE_RANGE_FALLBACK_LIMIT_BYTES = 8 * 1024 * 1024;
|
|
3
4
|
var StorageEngine = class {
|
|
4
5
|
deps;
|
|
5
6
|
constructor(deps) {
|
|
@@ -54,6 +55,74 @@ var StorageEngine = class {
|
|
|
54
55
|
});
|
|
55
56
|
}
|
|
56
57
|
}
|
|
58
|
+
async listObjects(options = {}) {
|
|
59
|
+
const limit = Math.min(Math.max(options.limit ?? 100, 1), 500);
|
|
60
|
+
const offset = Math.max(options.offset ?? 0, 0);
|
|
61
|
+
const search = options.search?.trim();
|
|
62
|
+
const params = [];
|
|
63
|
+
const whereClauses = [];
|
|
64
|
+
if (search) {
|
|
65
|
+
const pattern = `%${search}%`;
|
|
66
|
+
whereClauses.push(`(_id LIKE ? OR file_name LIKE ? OR content_type LIKE ?)`);
|
|
67
|
+
params.push(pattern, pattern, pattern);
|
|
68
|
+
}
|
|
69
|
+
const whereSql = whereClauses.length > 0 ? ` WHERE ${whereClauses.join(" AND ")}` : "";
|
|
70
|
+
const rows = await this.deps.driver.all(`SELECT _id, _creationTime, file_name, content_type, size, path FROM "_storage"${whereSql} ORDER BY _creationTime DESC LIMIT ? OFFSET ?`, [
|
|
71
|
+
...params,
|
|
72
|
+
limit,
|
|
73
|
+
offset
|
|
74
|
+
]);
|
|
75
|
+
const countRow = await this.deps.driver.get(`SELECT COUNT(*) as count FROM "_storage"${whereSql}`, params);
|
|
76
|
+
return {
|
|
77
|
+
entries: rows.map(storageEntryFromRow),
|
|
78
|
+
totalCount: countRow?.count ?? 0
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
async getObjectAccessInfo(id) {
|
|
82
|
+
const row = await this.deps.driver.get(`SELECT _id, _creationTime, file_name, content_type, size, path FROM "_storage" WHERE _id = ?`, [id]);
|
|
83
|
+
if (!row) return null;
|
|
84
|
+
return {
|
|
85
|
+
entry: storageEntryFromRow(row),
|
|
86
|
+
supportsRange: storageSupportsRange(this.deps.storage)
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
async readObjectRange(id, offset, length) {
|
|
90
|
+
const row = await this.deps.driver.get(`SELECT _id, _creationTime, file_name, content_type, size, path FROM "_storage" WHERE _id = ?`, [id]);
|
|
91
|
+
if (!row) return null;
|
|
92
|
+
const normalizedOffset = Math.max(Math.floor(offset), 0);
|
|
93
|
+
const normalizedLength = Math.max(Math.floor(length), 0);
|
|
94
|
+
const entry = storageEntryFromRow(row);
|
|
95
|
+
const supportsRange = storageSupportsRange(this.deps.storage);
|
|
96
|
+
if (normalizedLength === 0) return {
|
|
97
|
+
entry,
|
|
98
|
+
bytes: new Uint8Array(),
|
|
99
|
+
offset: normalizedOffset,
|
|
100
|
+
bytesRead: 0,
|
|
101
|
+
done: normalizedOffset >= row.size,
|
|
102
|
+
supportsRange
|
|
103
|
+
};
|
|
104
|
+
let bytes;
|
|
105
|
+
if (supportsRange && this.deps.storage.readRange) bytes = await this.deps.storage.readRange(id, normalizedOffset, normalizedLength);
|
|
106
|
+
else {
|
|
107
|
+
if (row.size > STORAGE_RANGE_FALLBACK_LIMIT_BYTES) throw new Error("This storage backend does not support ranged reads for large files.");
|
|
108
|
+
const fullBytes = await this.deps.storage.read(id);
|
|
109
|
+
bytes = fullBytes ? fullBytes.slice(normalizedOffset, normalizedOffset + normalizedLength) : null;
|
|
110
|
+
}
|
|
111
|
+
if (!bytes) return null;
|
|
112
|
+
return {
|
|
113
|
+
entry,
|
|
114
|
+
bytes,
|
|
115
|
+
offset: normalizedOffset,
|
|
116
|
+
bytesRead: bytes.byteLength,
|
|
117
|
+
done: normalizedOffset + bytes.byteLength >= row.size,
|
|
118
|
+
supportsRange
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
async deleteObject(id, meta = {}) {
|
|
122
|
+
if (!await this.deps.driver.get(`SELECT _id FROM "_storage" WHERE _id = ?`, [id])) return false;
|
|
123
|
+
await this.deleteCommittedObject(id, void 0, meta);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
57
126
|
createStorageApi(state) {
|
|
58
127
|
const componentMetadata = state.componentMetadata;
|
|
59
128
|
const namespacePrefix = componentMetadata ? `component:${componentMetadata.componentPath}:` : "";
|
|
@@ -118,19 +187,7 @@ var StorageEngine = class {
|
|
|
118
187
|
},
|
|
119
188
|
delete: async (id) => {
|
|
120
189
|
ensureStorageCapability();
|
|
121
|
-
await this.
|
|
122
|
-
await this.deps.driver.withTransaction(async () => {
|
|
123
|
-
await this.deps.driver.run(`DELETE FROM "_storage" WHERE _id = ?`, [id]);
|
|
124
|
-
await this.deps.driver.run(`DELETE FROM "_storage_pending" WHERE _id = ?`, [id]);
|
|
125
|
-
});
|
|
126
|
-
this.deps.devtools.emit({
|
|
127
|
-
type: "storage.updated",
|
|
128
|
-
runtimeId: this.deps.runtimeId,
|
|
129
|
-
storageId: id,
|
|
130
|
-
...componentMetadata ? { componentPath: componentMetadata.componentPath } : {},
|
|
131
|
-
operation: "delete",
|
|
132
|
-
timestamp: Date.now()
|
|
133
|
-
});
|
|
190
|
+
await this.deleteCommittedObject(id, componentMetadata?.componentPath);
|
|
134
191
|
state.storageChanges.push({
|
|
135
192
|
storageId: id,
|
|
136
193
|
reason: "storage-delete"
|
|
@@ -138,7 +195,36 @@ var StorageEngine = class {
|
|
|
138
195
|
}
|
|
139
196
|
};
|
|
140
197
|
}
|
|
198
|
+
async deleteCommittedObject(id, componentPath, meta = {}) {
|
|
199
|
+
await this.deps.storage.delete(id);
|
|
200
|
+
await this.deps.driver.withTransaction(async () => {
|
|
201
|
+
await this.deps.driver.run(`DELETE FROM "_storage" WHERE _id = ?`, [id]);
|
|
202
|
+
await this.deps.driver.run(`DELETE FROM "_storage_pending" WHERE _id = ?`, [id]);
|
|
203
|
+
});
|
|
204
|
+
this.deps.devtools.emit({
|
|
205
|
+
type: "storage.updated",
|
|
206
|
+
runtimeId: this.deps.runtimeId,
|
|
207
|
+
storageId: id,
|
|
208
|
+
...componentPath ? { componentPath } : {},
|
|
209
|
+
operation: "delete",
|
|
210
|
+
timestamp: Date.now(),
|
|
211
|
+
...meta.origin ? { origin: meta.origin } : {}
|
|
212
|
+
});
|
|
213
|
+
}
|
|
141
214
|
};
|
|
215
|
+
function storageEntryFromRow(row) {
|
|
216
|
+
return {
|
|
217
|
+
id: row._id,
|
|
218
|
+
createdAt: row._creationTime,
|
|
219
|
+
...row.file_name ? { fileName: row.file_name } : {},
|
|
220
|
+
...row.content_type ? { contentType: row.content_type } : {},
|
|
221
|
+
size: row.size,
|
|
222
|
+
path: row.path
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function storageSupportsRange(storage) {
|
|
226
|
+
return Boolean(storage.readRange) && storage.supportsRange?.() !== false;
|
|
227
|
+
}
|
|
142
228
|
//#endregion
|
|
143
229
|
export { StorageEngine };
|
|
144
230
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storageEngine.mjs","names":[],"sources":["../../../../src/runtime/internal/engines/storageEngine.ts"],"sourcesContent":["import type {\n StorageObject,\n SyncoreSqlDriver,\n SyncoreStorageAdapter,\n SyncoreStorageApi,\n StorageWriteInput\n} from \"../../runtime.js\";\nimport {\n type RuntimeExecutionState,\n type StorageMetadataRow,\n type StoragePendingRow\n} from \"./shared.js\";\nimport { DevtoolsEngine } from \"./devtoolsEngine.js\";\nimport { generateId } from \"../../id.js\";\n\ntype StorageEngineDeps = {\n driver: SyncoreSqlDriver;\n storage: SyncoreStorageAdapter;\n runtimeId: string;\n devtools: DevtoolsEngine;\n};\n\nexport class StorageEngine {\n constructor(private readonly deps: StorageEngineDeps) {}\n\n async prepare(): Promise<void> {\n await this.deps.driver.exec(`\n CREATE TABLE IF NOT EXISTS \"_storage\" (\n _id TEXT PRIMARY KEY,\n _creationTime INTEGER NOT NULL,\n file_name TEXT,\n content_type TEXT,\n size INTEGER NOT NULL,\n path TEXT NOT NULL\n );\n CREATE TABLE IF NOT EXISTS \"_storage_pending\" (\n _id TEXT PRIMARY KEY,\n _creationTime INTEGER NOT NULL,\n file_name TEXT,\n content_type TEXT\n );\n `);\n }\n\n async reconcile(): Promise<void> {\n const pendingRows = await this.deps.driver.all<StoragePendingRow>(\n `SELECT _id, _creationTime, file_name, content_type FROM \"_storage_pending\"`\n );\n\n for (const pendingRow of pendingRows) {\n const committed = await this.deps.driver.get<\n Pick<StorageMetadataRow, \"_id\">\n >(`SELECT _id FROM \"_storage\" WHERE _id = ?`, [pendingRow._id]);\n if (!committed) {\n await this.deps.storage.delete(pendingRow._id);\n this.deps.devtools.emit({\n type: \"log\",\n runtimeId: this.deps.runtimeId,\n level: \"warn\",\n message: `Recovered interrupted storage write ${pendingRow._id}.`,\n timestamp: Date.now()\n });\n }\n await this.deps.driver.run(\n `DELETE FROM \"_storage_pending\" WHERE _id = ?`,\n [pendingRow._id]\n );\n }\n\n if (!this.deps.storage.list) {\n return;\n }\n\n const storedRows = await this.deps.driver.all<Pick<StorageMetadataRow, \"_id\">>(\n `SELECT _id FROM \"_storage\"`\n );\n const knownIds = new Set(storedRows.map((row) => row._id));\n const physicalObjects = await this.deps.storage.list();\n for (const object of physicalObjects) {\n if (knownIds.has(object.id)) {\n continue;\n }\n await this.deps.storage.delete(object.id);\n this.deps.devtools.emit({\n type: \"log\",\n runtimeId: this.deps.runtimeId,\n level: \"warn\",\n message: `Removed orphaned storage object ${object.id}.`,\n timestamp: Date.now()\n });\n }\n }\n\n createStorageApi(state: RuntimeExecutionState): SyncoreStorageApi {\n const componentMetadata = state.componentMetadata;\n const namespacePrefix = componentMetadata\n ? `component:${componentMetadata.componentPath}:`\n : \"\";\n const ensureStorageCapability = () => {\n if (\n componentMetadata &&\n !componentMetadata.grantedCapabilities.includes(\"storage\")\n ) {\n throw new Error(\n `Component ${JSON.stringify(componentMetadata.componentPath)} is not allowed to use storage.`\n );\n }\n };\n const scopedId = (id: string) => `${namespacePrefix}${id}`;\n\n return {\n put: async (input: StorageWriteInput) => {\n ensureStorageCapability();\n const id = scopedId(generateId());\n const createdAt = Date.now();\n await this.deps.driver.run(\n `INSERT OR REPLACE INTO \"_storage_pending\" (_id, _creationTime, file_name, content_type) VALUES (?, ?, ?, ?)`,\n [id, createdAt, input.fileName ?? null, input.contentType ?? null]\n );\n const object = await this.deps.storage.put(id, input);\n await this.deps.driver.withTransaction(async () => {\n await this.deps.driver.run(\n `INSERT OR REPLACE INTO \"_storage\" (_id, _creationTime, file_name, content_type, size, path) VALUES (?, ?, ?, ?, ?, ?)`,\n [\n id,\n createdAt,\n input.fileName ?? null,\n object.contentType,\n object.size,\n object.path\n ]\n );\n await this.deps.driver.run(\n `DELETE FROM \"_storage_pending\" WHERE _id = ?`,\n [id]\n );\n });\n this.deps.devtools.emit({\n type: \"storage.updated\",\n runtimeId: this.deps.runtimeId,\n storageId: id,\n ...(componentMetadata\n ? { componentPath: componentMetadata.componentPath }\n : {}),\n operation: \"put\",\n timestamp: Date.now()\n });\n state.storageChanges.push({\n storageId: id,\n reason: \"storage-put\"\n });\n return id;\n },\n get: async (id: string): Promise<StorageObject | null> => {\n ensureStorageCapability();\n state.dependencyCollector?.add(`storage:${id}`);\n const row = await this.deps.driver.get<StorageMetadataRow>(\n `SELECT _id, _creationTime, file_name, content_type, size, path FROM \"_storage\" WHERE _id = ?`,\n [id]\n );\n if (!row) {\n return null;\n }\n return {\n id: row._id,\n path: row.path,\n size: row.size,\n contentType: row.content_type\n };\n },\n read: async (id: string) => {\n ensureStorageCapability();\n state.dependencyCollector?.add(`storage:${id}`);\n const row = await this.deps.driver.get<Pick<StorageMetadataRow, \"_id\">>(\n `SELECT _id FROM \"_storage\" WHERE _id = ?`,\n [id]\n );\n if (!row) {\n return null;\n }\n return this.deps.storage.read(id);\n },\n delete: async (id: string) => {\n ensureStorageCapability();\n await this.deps.storage.delete(id);\n await this.deps.driver.withTransaction(async () => {\n await this.deps.driver.run(\n `DELETE FROM \"_storage\" WHERE _id = ?`,\n [id]\n );\n await this.deps.driver.run(\n `DELETE FROM \"_storage_pending\" WHERE _id = ?`,\n [id]\n );\n });\n this.deps.devtools.emit({\n type: \"storage.updated\",\n runtimeId: this.deps.runtimeId,\n storageId: id,\n ...(componentMetadata\n ? { componentPath: componentMetadata.componentPath }\n : {}),\n operation: \"delete\",\n timestamp: Date.now()\n });\n state.storageChanges.push({\n storageId: id,\n reason: \"storage-delete\"\n });\n }\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"storageEngine.mjs","names":[],"sources":["../../../../src/runtime/internal/engines/storageEngine.ts"],"sourcesContent":["import type {\n StorageObject,\n SyncoreSqlDriver,\n SyncoreStorageAdapter,\n SyncoreStorageApi,\n StorageWriteInput\n} from \"../../runtime.js\";\nimport type { StorageEntry } from \"@syncore/devtools-protocol\";\nimport {\n type DevtoolsEventMeta,\n type RuntimeExecutionState,\n type StorageMetadataRow,\n type StoragePendingRow\n} from \"./shared.js\";\nimport { DevtoolsEngine } from \"./devtoolsEngine.js\";\nimport { generateId } from \"../../id.js\";\n\ntype StorageEngineDeps = {\n driver: SyncoreSqlDriver;\n storage: SyncoreStorageAdapter;\n runtimeId: string;\n devtools: DevtoolsEngine;\n};\n\nconst STORAGE_RANGE_FALLBACK_LIMIT_BYTES = 8 * 1024 * 1024;\n\nexport class StorageEngine {\n constructor(private readonly deps: StorageEngineDeps) {}\n\n async prepare(): Promise<void> {\n await this.deps.driver.exec(`\n CREATE TABLE IF NOT EXISTS \"_storage\" (\n _id TEXT PRIMARY KEY,\n _creationTime INTEGER NOT NULL,\n file_name TEXT,\n content_type TEXT,\n size INTEGER NOT NULL,\n path TEXT NOT NULL\n );\n CREATE TABLE IF NOT EXISTS \"_storage_pending\" (\n _id TEXT PRIMARY KEY,\n _creationTime INTEGER NOT NULL,\n file_name TEXT,\n content_type TEXT\n );\n `);\n }\n\n async reconcile(): Promise<void> {\n const pendingRows = await this.deps.driver.all<StoragePendingRow>(\n `SELECT _id, _creationTime, file_name, content_type FROM \"_storage_pending\"`\n );\n\n for (const pendingRow of pendingRows) {\n const committed = await this.deps.driver.get<\n Pick<StorageMetadataRow, \"_id\">\n >(`SELECT _id FROM \"_storage\" WHERE _id = ?`, [pendingRow._id]);\n if (!committed) {\n await this.deps.storage.delete(pendingRow._id);\n this.deps.devtools.emit({\n type: \"log\",\n runtimeId: this.deps.runtimeId,\n level: \"warn\",\n message: `Recovered interrupted storage write ${pendingRow._id}.`,\n timestamp: Date.now()\n });\n }\n await this.deps.driver.run(\n `DELETE FROM \"_storage_pending\" WHERE _id = ?`,\n [pendingRow._id]\n );\n }\n\n if (!this.deps.storage.list) {\n return;\n }\n\n const storedRows = await this.deps.driver.all<\n Pick<StorageMetadataRow, \"_id\">\n >(`SELECT _id FROM \"_storage\"`);\n const knownIds = new Set(storedRows.map((row) => row._id));\n const physicalObjects = await this.deps.storage.list();\n for (const object of physicalObjects) {\n if (knownIds.has(object.id)) {\n continue;\n }\n await this.deps.storage.delete(object.id);\n this.deps.devtools.emit({\n type: \"log\",\n runtimeId: this.deps.runtimeId,\n level: \"warn\",\n message: `Removed orphaned storage object ${object.id}.`,\n timestamp: Date.now()\n });\n }\n }\n\n async listObjects(\n options: {\n limit?: number;\n offset?: number;\n search?: string;\n } = {}\n ): Promise<{ entries: StorageEntry[]; totalCount: number }> {\n const limit = Math.min(Math.max(options.limit ?? 100, 1), 500);\n const offset = Math.max(options.offset ?? 0, 0);\n const search = options.search?.trim();\n const params: unknown[] = [];\n const whereClauses: string[] = [];\n\n if (search) {\n const pattern = `%${search}%`;\n whereClauses.push(\n `(_id LIKE ? OR file_name LIKE ? OR content_type LIKE ?)`\n );\n params.push(pattern, pattern, pattern);\n }\n\n const whereSql =\n whereClauses.length > 0 ? ` WHERE ${whereClauses.join(\" AND \")}` : \"\";\n const rows = await this.deps.driver.all<StorageMetadataRow>(\n `SELECT _id, _creationTime, file_name, content_type, size, path FROM \"_storage\"${whereSql} ORDER BY _creationTime DESC LIMIT ? OFFSET ?`,\n [...params, limit, offset]\n );\n const countRow = await this.deps.driver.get<{ count: number }>(\n `SELECT COUNT(*) as count FROM \"_storage\"${whereSql}`,\n params\n );\n\n return {\n entries: rows.map(storageEntryFromRow),\n totalCount: countRow?.count ?? 0\n };\n }\n\n async getObjectAccessInfo(\n id: string\n ): Promise<{ entry: StorageEntry; supportsRange: boolean } | null> {\n const row = await this.deps.driver.get<StorageMetadataRow>(\n `SELECT _id, _creationTime, file_name, content_type, size, path FROM \"_storage\" WHERE _id = ?`,\n [id]\n );\n if (!row) {\n return null;\n }\n return {\n entry: storageEntryFromRow(row),\n supportsRange: storageSupportsRange(this.deps.storage)\n };\n }\n\n async readObjectRange(\n id: string,\n offset: number,\n length: number\n ): Promise<{\n entry: StorageEntry;\n bytes: Uint8Array;\n offset: number;\n bytesRead: number;\n done: boolean;\n supportsRange: boolean;\n } | null> {\n const row = await this.deps.driver.get<StorageMetadataRow>(\n `SELECT _id, _creationTime, file_name, content_type, size, path FROM \"_storage\" WHERE _id = ?`,\n [id]\n );\n if (!row) {\n return null;\n }\n\n const normalizedOffset = Math.max(Math.floor(offset), 0);\n const normalizedLength = Math.max(Math.floor(length), 0);\n const entry = storageEntryFromRow(row);\n const supportsRange = storageSupportsRange(this.deps.storage);\n if (normalizedLength === 0) {\n return {\n entry,\n bytes: new Uint8Array(),\n offset: normalizedOffset,\n bytesRead: 0,\n done: normalizedOffset >= row.size,\n supportsRange\n };\n }\n\n let bytes: Uint8Array | null;\n if (supportsRange && this.deps.storage.readRange) {\n bytes = await this.deps.storage.readRange(\n id,\n normalizedOffset,\n normalizedLength\n );\n } else {\n if (row.size > STORAGE_RANGE_FALLBACK_LIMIT_BYTES) {\n throw new Error(\n \"This storage backend does not support ranged reads for large files.\"\n );\n }\n const fullBytes = await this.deps.storage.read(id);\n bytes = fullBytes\n ? fullBytes.slice(normalizedOffset, normalizedOffset + normalizedLength)\n : null;\n }\n if (!bytes) {\n return null;\n }\n return {\n entry,\n bytes,\n offset: normalizedOffset,\n bytesRead: bytes.byteLength,\n done: normalizedOffset + bytes.byteLength >= row.size,\n supportsRange\n };\n }\n\n async deleteObject(\n id: string,\n meta: DevtoolsEventMeta = {}\n ): Promise<boolean> {\n const row = await this.deps.driver.get<Pick<StorageMetadataRow, \"_id\">>(\n `SELECT _id FROM \"_storage\" WHERE _id = ?`,\n [id]\n );\n if (!row) {\n return false;\n }\n await this.deleteCommittedObject(id, undefined, meta);\n return true;\n }\n\n createStorageApi(state: RuntimeExecutionState): SyncoreStorageApi {\n const componentMetadata = state.componentMetadata;\n const namespacePrefix = componentMetadata\n ? `component:${componentMetadata.componentPath}:`\n : \"\";\n const ensureStorageCapability = () => {\n if (\n componentMetadata &&\n !componentMetadata.grantedCapabilities.includes(\"storage\")\n ) {\n throw new Error(\n `Component ${JSON.stringify(componentMetadata.componentPath)} is not allowed to use storage.`\n );\n }\n };\n const scopedId = (id: string) => `${namespacePrefix}${id}`;\n\n return {\n put: async (input: StorageWriteInput) => {\n ensureStorageCapability();\n const id = scopedId(generateId());\n const createdAt = Date.now();\n await this.deps.driver.run(\n `INSERT OR REPLACE INTO \"_storage_pending\" (_id, _creationTime, file_name, content_type) VALUES (?, ?, ?, ?)`,\n [id, createdAt, input.fileName ?? null, input.contentType ?? null]\n );\n const object = await this.deps.storage.put(id, input);\n await this.deps.driver.withTransaction(async () => {\n await this.deps.driver.run(\n `INSERT OR REPLACE INTO \"_storage\" (_id, _creationTime, file_name, content_type, size, path) VALUES (?, ?, ?, ?, ?, ?)`,\n [\n id,\n createdAt,\n input.fileName ?? null,\n object.contentType,\n object.size,\n object.path\n ]\n );\n await this.deps.driver.run(\n `DELETE FROM \"_storage_pending\" WHERE _id = ?`,\n [id]\n );\n });\n this.deps.devtools.emit({\n type: \"storage.updated\",\n runtimeId: this.deps.runtimeId,\n storageId: id,\n ...(componentMetadata\n ? { componentPath: componentMetadata.componentPath }\n : {}),\n operation: \"put\",\n timestamp: Date.now()\n });\n state.storageChanges.push({\n storageId: id,\n reason: \"storage-put\"\n });\n return id;\n },\n get: async (id: string): Promise<StorageObject | null> => {\n ensureStorageCapability();\n state.dependencyCollector?.add(`storage:${id}`);\n const row = await this.deps.driver.get<StorageMetadataRow>(\n `SELECT _id, _creationTime, file_name, content_type, size, path FROM \"_storage\" WHERE _id = ?`,\n [id]\n );\n if (!row) {\n return null;\n }\n return {\n id: row._id,\n path: row.path,\n size: row.size,\n contentType: row.content_type\n };\n },\n read: async (id: string) => {\n ensureStorageCapability();\n state.dependencyCollector?.add(`storage:${id}`);\n const row = await this.deps.driver.get<Pick<StorageMetadataRow, \"_id\">>(\n `SELECT _id FROM \"_storage\" WHERE _id = ?`,\n [id]\n );\n if (!row) {\n return null;\n }\n return this.deps.storage.read(id);\n },\n delete: async (id: string) => {\n ensureStorageCapability();\n await this.deleteCommittedObject(id, componentMetadata?.componentPath);\n state.storageChanges.push({\n storageId: id,\n reason: \"storage-delete\"\n });\n }\n };\n }\n\n private async deleteCommittedObject(\n id: string,\n componentPath?: string,\n meta: DevtoolsEventMeta = {}\n ): Promise<void> {\n await this.deps.storage.delete(id);\n await this.deps.driver.withTransaction(async () => {\n await this.deps.driver.run(`DELETE FROM \"_storage\" WHERE _id = ?`, [id]);\n await this.deps.driver.run(\n `DELETE FROM \"_storage_pending\" WHERE _id = ?`,\n [id]\n );\n });\n this.deps.devtools.emit({\n type: \"storage.updated\",\n runtimeId: this.deps.runtimeId,\n storageId: id,\n ...(componentPath ? { componentPath } : {}),\n operation: \"delete\",\n timestamp: Date.now(),\n ...(meta.origin ? { origin: meta.origin } : {})\n });\n }\n}\n\nfunction storageEntryFromRow(row: StorageMetadataRow): StorageEntry {\n return {\n id: row._id,\n createdAt: row._creationTime,\n ...(row.file_name ? { fileName: row.file_name } : {}),\n ...(row.content_type ? { contentType: row.content_type } : {}),\n size: row.size,\n path: row.path\n };\n}\n\nfunction storageSupportsRange(storage: SyncoreStorageAdapter): boolean {\n return Boolean(storage.readRange) && storage.supportsRange?.() !== false;\n}\n"],"mappings":"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"}
|
|
@@ -17,6 +17,7 @@ var RuntimeKernel = class {
|
|
|
17
17
|
externalChangeSourceId = generateId();
|
|
18
18
|
driverDatabasePath;
|
|
19
19
|
capabilities;
|
|
20
|
+
runtimeCapabilities;
|
|
20
21
|
capabilityDescriptors;
|
|
21
22
|
devtoolsEngine;
|
|
22
23
|
schemaEngine;
|
|
@@ -34,6 +35,10 @@ var RuntimeKernel = class {
|
|
|
34
35
|
this.platform = options.platform ?? "node";
|
|
35
36
|
this.capabilityDescriptors = Object.freeze([...options.capabilityDescriptors ?? []]);
|
|
36
37
|
this.capabilities = Object.freeze({ ...options.capabilities ?? {} });
|
|
38
|
+
this.runtimeCapabilities = Object.freeze(options.runtimeCapabilities ?? { storage: {
|
|
39
|
+
available: true,
|
|
40
|
+
...options.storage.supportsRange ? { supportsRange: options.storage.supportsRange() !== false } : {}
|
|
41
|
+
} });
|
|
37
42
|
this.driverDatabasePath = inferDriverDatabasePath(options.driver);
|
|
38
43
|
this.devtoolsEngine = new DevtoolsEngine({
|
|
39
44
|
runtimeId: this.runtimeId,
|
|
@@ -57,7 +62,8 @@ var RuntimeKernel = class {
|
|
|
57
62
|
this.transactionCoordinator = new TransactionCoordinator(options.driver);
|
|
58
63
|
this.runtimeStatus = new RuntimeStatusController({
|
|
59
64
|
kind: "starting",
|
|
60
|
-
reason: "booting"
|
|
65
|
+
reason: "booting",
|
|
66
|
+
capabilities: this.runtimeCapabilities
|
|
61
67
|
});
|
|
62
68
|
this.schedulerEngine = new SchedulerEngine({
|
|
63
69
|
driver: options.driver,
|
|
@@ -113,6 +119,28 @@ var RuntimeKernel = class {
|
|
|
113
119
|
if (resolvedScopes.size > 0) await this.reactivityEngine.refreshQueriesForScopes(resolvedScopes, reason);
|
|
114
120
|
await this.devtoolsEngine.forceRefresh(reason, { refreshQueriesForScopes: (requestedScopes, refreshReason) => this.reactivityEngine.refreshQueriesForScopes(requestedScopes, refreshReason) }, meta, resolvedScopes);
|
|
115
121
|
},
|
|
122
|
+
listStorageObjects: async (options) => {
|
|
123
|
+
await this.prepareForDirectAccess();
|
|
124
|
+
return this.storageEngine.listObjects(options);
|
|
125
|
+
},
|
|
126
|
+
getStorageObjectAccessInfo: async (id) => {
|
|
127
|
+
await this.prepareForDirectAccess();
|
|
128
|
+
return this.storageEngine.getObjectAccessInfo(id);
|
|
129
|
+
},
|
|
130
|
+
readStorageObjectRange: async (id, offset, length) => {
|
|
131
|
+
await this.prepareForDirectAccess();
|
|
132
|
+
return this.storageEngine.readObjectRange(id, offset, length);
|
|
133
|
+
},
|
|
134
|
+
deleteStorageObject: async (id, meta) => {
|
|
135
|
+
await this.prepareForDirectAccess();
|
|
136
|
+
const deleted = await this.storageEngine.deleteObject(id, meta);
|
|
137
|
+
if (deleted) this.devtoolsEngine.notifyScopes([
|
|
138
|
+
"runtime.summary",
|
|
139
|
+
"storage.objects",
|
|
140
|
+
`storage:${id}`
|
|
141
|
+
]);
|
|
142
|
+
return deleted;
|
|
143
|
+
},
|
|
116
144
|
cancelScheduledJob: async (id) => {
|
|
117
145
|
await this.prepareForDirectAccess();
|
|
118
146
|
return this.schedulerEngine.cancelScheduledJob(id);
|
|
@@ -128,7 +156,8 @@ var RuntimeKernel = class {
|
|
|
128
156
|
if (this.started) return;
|
|
129
157
|
this.runtimeStatus.setStatus({
|
|
130
158
|
kind: "starting",
|
|
131
|
-
reason: "booting"
|
|
159
|
+
reason: "booting",
|
|
160
|
+
capabilities: this.runtimeCapabilities
|
|
132
161
|
});
|
|
133
162
|
await this.prepareForDirectAccess();
|
|
134
163
|
try {
|
|
@@ -136,7 +165,10 @@ var RuntimeKernel = class {
|
|
|
136
165
|
this.reactivityEngine.start();
|
|
137
166
|
this.schedulerEngine.startPolling();
|
|
138
167
|
this.started = true;
|
|
139
|
-
this.runtimeStatus.setStatus({
|
|
168
|
+
this.runtimeStatus.setStatus({
|
|
169
|
+
kind: "ready",
|
|
170
|
+
capabilities: this.runtimeCapabilities
|
|
171
|
+
});
|
|
140
172
|
this.devtoolsEngine.emit({
|
|
141
173
|
type: "runtime.connected",
|
|
142
174
|
runtimeId: this.runtimeId,
|
|
@@ -151,6 +183,7 @@ var RuntimeKernel = class {
|
|
|
151
183
|
this.runtimeStatus.setStatus({
|
|
152
184
|
kind: "error",
|
|
153
185
|
reason: "runtime-unavailable",
|
|
186
|
+
capabilities: this.runtimeCapabilities,
|
|
154
187
|
...error instanceof Error ? { error } : {}
|
|
155
188
|
});
|
|
156
189
|
throw error;
|
|
@@ -185,7 +218,8 @@ var RuntimeKernel = class {
|
|
|
185
218
|
this.started = false;
|
|
186
219
|
this.runtimeStatus.setStatus({
|
|
187
220
|
kind: "unavailable",
|
|
188
|
-
reason: "disposed"
|
|
221
|
+
reason: "disposed",
|
|
222
|
+
capabilities: this.runtimeCapabilities
|
|
189
223
|
});
|
|
190
224
|
if (stopError) throw stopError;
|
|
191
225
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtimeKernel.mjs","names":[],"sources":["../../../src/runtime/internal/runtimeKernel.ts"],"sourcesContent":["import type {\n CapabilityDescriptor,\n DevtoolsLiveQueryScope,\n QueryCtx,\n SyncoreDataModel,\n SyncoreResolvedComponents,\n SyncoreCapabilities,\n SyncoreClient,\n SyncoreRuntime,\n SyncoreRuntimeAdmin,\n SyncoreRuntimeOptions,\n SyncoreWatch,\n UpdateScheduledJobOptions\n} from \"../runtime.js\";\nimport type { FunctionReference } from \"../functions.js\";\nimport type {\n SyncoreDevtoolsEvent,\n SyncoreDevtoolsEventOrigin\n} from \"@syncore/devtools-protocol\";\nimport { generateId } from \"../id.js\";\nimport { DevtoolsEngine } from \"./engines/devtoolsEngine.js\";\nimport { ExecutionEngine } from \"./engines/executionEngine.js\";\nimport { ReactivityEngine } from \"./engines/reactivityEngine.js\";\nimport { SchedulerEngine } from \"./engines/schedulerEngine.js\";\nimport { SchemaEngine } from \"./engines/schemaEngine.js\";\nimport { StorageEngine } from \"./engines/storageEngine.js\";\nimport { inferDriverDatabasePath } from \"./engines/shared.js\";\nimport { TransactionCoordinator } from \"./transactionCoordinator.js\";\nimport { ensureSupportedSystemFormats } from \"./systemMeta.js\";\nimport { RuntimeStatusController } from \"./runtimeStatus.js\";\n\ntype DevtoolsEventMeta = {\n origin?: SyncoreDevtoolsEventOrigin;\n executionId?: string;\n parentExecutionId?: string;\n schedulerJobId?: string;\n schedulerRun?: boolean;\n};\n\nexport class RuntimeKernel<\n TSchema extends SyncoreDataModel\n> {\n readonly runtimeId = generateId();\n readonly platform: string;\n readonly externalChangeSourceId = generateId();\n readonly driverDatabasePath: string | undefined;\n readonly capabilities: Readonly<SyncoreCapabilities>;\n readonly capabilityDescriptors: ReadonlyArray<CapabilityDescriptor>;\n readonly devtoolsEngine: DevtoolsEngine;\n readonly schemaEngine: SchemaEngine<TSchema>;\n readonly storageEngine: StorageEngine;\n readonly schedulerEngine: SchedulerEngine;\n readonly reactivityEngine: ReactivityEngine;\n readonly executionEngine: ExecutionEngine<TSchema>;\n readonly transactionCoordinator: TransactionCoordinator;\n readonly runtimeStatus: RuntimeStatusController;\n readonly admin: SyncoreRuntimeAdmin<TSchema>;\n private prepared = false;\n private started = false;\n\n constructor(\n private readonly options: SyncoreRuntimeOptions<TSchema>,\n runtime: SyncoreRuntime<TSchema>\n ) {\n this.platform = options.platform ?? \"node\";\n this.capabilityDescriptors = Object.freeze([\n ...(options.capabilityDescriptors ?? [])\n ]);\n this.capabilities = Object.freeze({\n ...(options.capabilities ?? {})\n });\n this.driverDatabasePath = inferDriverDatabasePath(\n options.driver as { filename?: string; databasePath?: string }\n );\n this.devtoolsEngine = new DevtoolsEngine({\n runtimeId: this.runtimeId,\n platform: this.platform,\n ...(options.devtools ? { sink: options.devtools } : {}),\n getActiveQueryInfos: () => this.reactivityEngine.getActiveQueryInfos(),\n getSchemaTables: () => this.schemaEngine.getSchemaTablesForDevtools()\n });\n this.schemaEngine = new SchemaEngine({\n schema: options.schema,\n driver: options.driver,\n runtimeId: this.runtimeId,\n devtools: this.devtoolsEngine\n });\n this.storageEngine = new StorageEngine({\n driver: options.driver,\n storage: options.storage,\n runtimeId: this.runtimeId,\n devtools: this.devtoolsEngine\n });\n this.transactionCoordinator = new TransactionCoordinator(options.driver);\n this.runtimeStatus = new RuntimeStatusController({\n kind: \"starting\",\n reason: \"booting\"\n });\n this.schedulerEngine = new SchedulerEngine({\n driver: options.driver,\n runtimeId: this.runtimeId,\n devtools: this.devtoolsEngine,\n recurringJobs: options.scheduler?.recurringJobs ?? [],\n pollIntervalMs: options.scheduler?.pollIntervalMs ?? 1000,\n runMutation: (reference, args, meta) =>\n this.executionEngine.runMutation(reference, args, meta),\n runAction: (reference, args, meta) =>\n this.executionEngine.runAction(reference, args, meta)\n });\n this.reactivityEngine = new ReactivityEngine({\n runtimeId: this.runtimeId,\n externalChangeSourceId: this.externalChangeSourceId,\n ...(options.externalChangeSignal\n ? { externalChangeSignal: options.externalChangeSignal }\n : {}),\n ...(options.externalChangeApplier\n ? { externalChangeApplier: options.externalChangeApplier }\n : {}),\n devtools: this.devtoolsEngine,\n runQuery: (reference, args, meta) =>\n this.executionEngine.runQuery(reference, args, meta),\n collectQueryDependencies: (functionName, args) =>\n this.executionEngine.collectQueryDependencies(functionName, args)\n });\n this.executionEngine = new ExecutionEngine({\n runtimeId: this.runtimeId,\n functions: options.functions,\n driver: options.driver,\n capabilities: this.capabilities,\n capabilityDescriptors: this.capabilityDescriptors,\n schema: this.schemaEngine,\n storage: this.storageEngine,\n scheduler: this.schedulerEngine,\n reactivity: this.reactivityEngine,\n devtools: this.devtoolsEngine,\n transactionCoordinator: this.transactionCoordinator,\n runtimeStatus: this.runtimeStatus\n });\n this.admin = {\n prepareForDirectAccess: () => this.prepareForDirectAccess(),\n createClient: () => this.createClient(),\n runQuery: (reference, args, meta) =>\n this.executionEngine.runQuery(reference, args, meta),\n runMutation: (reference, args, meta) =>\n this.executionEngine.runMutation(reference, args, meta),\n runAction: (reference, args, meta) =>\n this.executionEngine.runAction(reference, args, meta),\n runDevtoolsMutation: async (callback, meta) => {\n await this.prepareForDirectAccess();\n return this.executionEngine.runDevtoolsMutation(callback, meta);\n },\n getRuntimeSummary: () => this.devtoolsEngine.getRuntimeSummary(),\n getActiveQueryInfos: () => this.reactivityEngine.getActiveQueryInfos(),\n getRuntimeId: () => this.runtimeId,\n getDriverDatabasePath: () => this.driverDatabasePath,\n subscribeToDevtoolsEvents: (listener) =>\n this.devtoolsEngine.subscribeEvents(listener),\n subscribeToDevtoolsInvalidations: (listener) =>\n this.devtoolsEngine.subscribeInvalidations(listener),\n notifyDevtoolsScopes: (scopes) => this.devtoolsEngine.notifyScopes(scopes),\n forceRefreshDevtools: async (reason, scopes, meta) => {\n const resolvedScopes = new Set(scopes ?? []);\n if (resolvedScopes.size > 0) {\n await this.reactivityEngine.refreshQueriesForScopes(\n resolvedScopes,\n reason\n );\n }\n await this.devtoolsEngine.forceRefresh(\n reason,\n {\n refreshQueriesForScopes: (requestedScopes, refreshReason) =>\n this.reactivityEngine.refreshQueriesForScopes(\n requestedScopes,\n refreshReason\n )\n },\n meta,\n resolvedScopes\n );\n },\n cancelScheduledJob: async (id) => {\n await this.prepareForDirectAccess();\n return this.schedulerEngine.cancelScheduledJob(id);\n },\n updateScheduledJob: async (update: UpdateScheduledJobOptions) => {\n await this.prepareForDirectAccess();\n return this.schedulerEngine.updateScheduledJob(update);\n }\n };\n options.devtools?.attachRuntime?.(runtime);\n }\n\n async start(): Promise<void> {\n if (this.started) {\n return;\n }\n this.runtimeStatus.setStatus({\n kind: \"starting\",\n reason: \"booting\"\n });\n await this.prepareForDirectAccess();\n try {\n await this.runComponentHooks(\"onStart\");\n this.reactivityEngine.start();\n this.schedulerEngine.startPolling();\n this.started = true;\n this.runtimeStatus.setStatus({\n kind: \"ready\"\n });\n this.devtoolsEngine.emit({\n type: \"runtime.connected\",\n runtimeId: this.runtimeId,\n platform: this.platform,\n timestamp: Date.now()\n });\n } catch (error) {\n this.schedulerEngine.stopPolling();\n this.reactivityEngine.stop();\n await this.options.driver.close?.().catch(() => undefined);\n this.started = false;\n this.runtimeStatus.setStatus({\n kind: \"error\",\n reason: \"runtime-unavailable\",\n ...(error instanceof Error ? { error } : {})\n });\n throw error;\n }\n }\n\n async prepareForDirectAccess(): Promise<void> {\n if (this.prepared) {\n return;\n }\n await ensureSupportedSystemFormats(this.options.driver);\n await this.schemaEngine.prepare();\n await this.storageEngine.prepare();\n await this.schedulerEngine.prepare();\n await this.storageEngine.reconcile();\n await this.schemaEngine.applySchema();\n await this.schedulerEngine.syncRecurringJobs();\n this.prepared = true;\n }\n\n async stop(): Promise<void> {\n this.schedulerEngine.stopPolling();\n let stopError: unknown;\n if (this.started) {\n try {\n await this.runComponentHooks(\"onStop\");\n } catch (error) {\n stopError = error;\n }\n }\n this.reactivityEngine.stop();\n await this.options.driver.close?.();\n if (this.started) {\n this.devtoolsEngine.emit({\n type: \"runtime.disconnected\",\n runtimeId: this.runtimeId,\n timestamp: Date.now()\n });\n }\n this.started = false;\n this.runtimeStatus.setStatus({\n kind: \"unavailable\",\n reason: \"disposed\"\n });\n if (stopError) {\n throw stopError;\n }\n }\n\n createClient(): SyncoreClient {\n return this.executionEngine.createClient();\n }\n\n watchQuery<TArgs, TResult>(\n reference: FunctionReference<\"query\", TArgs, TResult>,\n args: Record<string, unknown> = {}\n ): SyncoreWatch<TResult> {\n return this.executionEngine.watchQuery(reference, args);\n }\n\n private async runComponentHooks(\n hook: \"onStart\" | \"onStop\"\n ): Promise<void> {\n for (const component of this.options.components ?? []) {\n await this.runComponentHookTree(component, hook);\n }\n }\n\n private async runComponentHookTree(\n component: SyncoreResolvedComponents[number],\n hook: \"onStart\" | \"onStop\"\n ): Promise<void> {\n const handler = component[hook];\n if (handler) {\n await handler({\n runtimeId: this.runtimeId,\n platform: this.platform,\n componentPath: component.path,\n componentName: component.name,\n version: component.version,\n config: component.config,\n capabilities: component.grantedCapabilities,\n emitDevtools: (event: SyncoreDevtoolsEvent) => {\n this.devtoolsEngine.emit(event);\n }\n });\n }\n for (const child of component.children) {\n await this.runComponentHookTree(child, hook);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtimeKernel.mjs","names":[],"sources":["../../../src/runtime/internal/runtimeKernel.ts"],"sourcesContent":["import type {\n CapabilityDescriptor,\n DevtoolsLiveQueryScope,\n QueryCtx,\n SyncoreDataModel,\n SyncoreResolvedComponents,\n SyncoreCapabilities,\n SyncoreClient,\n SyncoreRuntimeCapabilities,\n SyncoreRuntime,\n SyncoreRuntimeAdmin,\n SyncoreRuntimeOptions,\n SyncoreWatch,\n UpdateScheduledJobOptions\n} from \"../runtime.js\";\nimport type { FunctionReference } from \"../functions.js\";\nimport type {\n SyncoreDevtoolsEvent,\n SyncoreDevtoolsEventOrigin\n} from \"@syncore/devtools-protocol\";\nimport { generateId } from \"../id.js\";\nimport { DevtoolsEngine } from \"./engines/devtoolsEngine.js\";\nimport { ExecutionEngine } from \"./engines/executionEngine.js\";\nimport { ReactivityEngine } from \"./engines/reactivityEngine.js\";\nimport { SchedulerEngine } from \"./engines/schedulerEngine.js\";\nimport { SchemaEngine } from \"./engines/schemaEngine.js\";\nimport { StorageEngine } from \"./engines/storageEngine.js\";\nimport { inferDriverDatabasePath } from \"./engines/shared.js\";\nimport { TransactionCoordinator } from \"./transactionCoordinator.js\";\nimport { ensureSupportedSystemFormats } from \"./systemMeta.js\";\nimport { RuntimeStatusController } from \"./runtimeStatus.js\";\n\ntype DevtoolsEventMeta = {\n origin?: SyncoreDevtoolsEventOrigin;\n executionId?: string;\n parentExecutionId?: string;\n schedulerJobId?: string;\n schedulerRun?: boolean;\n};\n\nexport class RuntimeKernel<TSchema extends SyncoreDataModel> {\n readonly runtimeId = generateId();\n readonly platform: string;\n readonly externalChangeSourceId = generateId();\n readonly driverDatabasePath: string | undefined;\n readonly capabilities: Readonly<SyncoreCapabilities>;\n readonly runtimeCapabilities: Readonly<SyncoreRuntimeCapabilities>;\n readonly capabilityDescriptors: ReadonlyArray<CapabilityDescriptor>;\n readonly devtoolsEngine: DevtoolsEngine;\n readonly schemaEngine: SchemaEngine<TSchema>;\n readonly storageEngine: StorageEngine;\n readonly schedulerEngine: SchedulerEngine;\n readonly reactivityEngine: ReactivityEngine;\n readonly executionEngine: ExecutionEngine<TSchema>;\n readonly transactionCoordinator: TransactionCoordinator;\n readonly runtimeStatus: RuntimeStatusController;\n readonly admin: SyncoreRuntimeAdmin<TSchema>;\n private prepared = false;\n private started = false;\n\n constructor(\n private readonly options: SyncoreRuntimeOptions<TSchema>,\n runtime: SyncoreRuntime<TSchema>\n ) {\n this.platform = options.platform ?? \"node\";\n this.capabilityDescriptors = Object.freeze([\n ...(options.capabilityDescriptors ?? [])\n ]);\n this.capabilities = Object.freeze({\n ...(options.capabilities ?? {})\n });\n this.runtimeCapabilities = Object.freeze(\n options.runtimeCapabilities ?? {\n storage: {\n available: true,\n ...(options.storage.supportsRange\n ? { supportsRange: options.storage.supportsRange() !== false }\n : {})\n }\n }\n );\n this.driverDatabasePath = inferDriverDatabasePath(\n options.driver as { filename?: string; databasePath?: string }\n );\n this.devtoolsEngine = new DevtoolsEngine({\n runtimeId: this.runtimeId,\n platform: this.platform,\n ...(options.devtools ? { sink: options.devtools } : {}),\n getActiveQueryInfos: () => this.reactivityEngine.getActiveQueryInfos(),\n getSchemaTables: () => this.schemaEngine.getSchemaTablesForDevtools()\n });\n this.schemaEngine = new SchemaEngine({\n schema: options.schema,\n driver: options.driver,\n runtimeId: this.runtimeId,\n devtools: this.devtoolsEngine\n });\n this.storageEngine = new StorageEngine({\n driver: options.driver,\n storage: options.storage,\n runtimeId: this.runtimeId,\n devtools: this.devtoolsEngine\n });\n this.transactionCoordinator = new TransactionCoordinator(options.driver);\n this.runtimeStatus = new RuntimeStatusController({\n kind: \"starting\",\n reason: \"booting\",\n capabilities: this.runtimeCapabilities\n });\n this.schedulerEngine = new SchedulerEngine({\n driver: options.driver,\n runtimeId: this.runtimeId,\n devtools: this.devtoolsEngine,\n recurringJobs: options.scheduler?.recurringJobs ?? [],\n pollIntervalMs: options.scheduler?.pollIntervalMs ?? 1000,\n runMutation: (reference, args, meta) =>\n this.executionEngine.runMutation(reference, args, meta),\n runAction: (reference, args, meta) =>\n this.executionEngine.runAction(reference, args, meta)\n });\n this.reactivityEngine = new ReactivityEngine({\n runtimeId: this.runtimeId,\n externalChangeSourceId: this.externalChangeSourceId,\n ...(options.externalChangeSignal\n ? { externalChangeSignal: options.externalChangeSignal }\n : {}),\n ...(options.externalChangeApplier\n ? { externalChangeApplier: options.externalChangeApplier }\n : {}),\n devtools: this.devtoolsEngine,\n runQuery: (reference, args, meta) =>\n this.executionEngine.runQuery(reference, args, meta),\n collectQueryDependencies: (functionName, args) =>\n this.executionEngine.collectQueryDependencies(functionName, args)\n });\n this.executionEngine = new ExecutionEngine({\n runtimeId: this.runtimeId,\n functions: options.functions,\n driver: options.driver,\n capabilities: this.capabilities,\n capabilityDescriptors: this.capabilityDescriptors,\n schema: this.schemaEngine,\n storage: this.storageEngine,\n scheduler: this.schedulerEngine,\n reactivity: this.reactivityEngine,\n devtools: this.devtoolsEngine,\n transactionCoordinator: this.transactionCoordinator,\n runtimeStatus: this.runtimeStatus\n });\n this.admin = {\n prepareForDirectAccess: () => this.prepareForDirectAccess(),\n createClient: () => this.createClient(),\n runQuery: (reference, args, meta) =>\n this.executionEngine.runQuery(reference, args, meta),\n runMutation: (reference, args, meta) =>\n this.executionEngine.runMutation(reference, args, meta),\n runAction: (reference, args, meta) =>\n this.executionEngine.runAction(reference, args, meta),\n runDevtoolsMutation: async (callback, meta) => {\n await this.prepareForDirectAccess();\n return this.executionEngine.runDevtoolsMutation(callback, meta);\n },\n getRuntimeSummary: () => this.devtoolsEngine.getRuntimeSummary(),\n getActiveQueryInfos: () => this.reactivityEngine.getActiveQueryInfos(),\n getRuntimeId: () => this.runtimeId,\n getDriverDatabasePath: () => this.driverDatabasePath,\n subscribeToDevtoolsEvents: (listener) =>\n this.devtoolsEngine.subscribeEvents(listener),\n subscribeToDevtoolsInvalidations: (listener) =>\n this.devtoolsEngine.subscribeInvalidations(listener),\n notifyDevtoolsScopes: (scopes) =>\n this.devtoolsEngine.notifyScopes(scopes),\n forceRefreshDevtools: async (reason, scopes, meta) => {\n const resolvedScopes = new Set(scopes ?? []);\n if (resolvedScopes.size > 0) {\n await this.reactivityEngine.refreshQueriesForScopes(\n resolvedScopes,\n reason\n );\n }\n await this.devtoolsEngine.forceRefresh(\n reason,\n {\n refreshQueriesForScopes: (requestedScopes, refreshReason) =>\n this.reactivityEngine.refreshQueriesForScopes(\n requestedScopes,\n refreshReason\n )\n },\n meta,\n resolvedScopes\n );\n },\n listStorageObjects: async (options) => {\n await this.prepareForDirectAccess();\n return this.storageEngine.listObjects(options);\n },\n getStorageObjectAccessInfo: async (id) => {\n await this.prepareForDirectAccess();\n return this.storageEngine.getObjectAccessInfo(id);\n },\n readStorageObjectRange: async (id, offset, length) => {\n await this.prepareForDirectAccess();\n return this.storageEngine.readObjectRange(id, offset, length);\n },\n deleteStorageObject: async (id, meta) => {\n await this.prepareForDirectAccess();\n const deleted = await this.storageEngine.deleteObject(id, meta);\n if (deleted) {\n this.devtoolsEngine.notifyScopes([\n \"runtime.summary\",\n \"storage.objects\",\n `storage:${id}`\n ]);\n }\n return deleted;\n },\n cancelScheduledJob: async (id) => {\n await this.prepareForDirectAccess();\n return this.schedulerEngine.cancelScheduledJob(id);\n },\n updateScheduledJob: async (update: UpdateScheduledJobOptions) => {\n await this.prepareForDirectAccess();\n return this.schedulerEngine.updateScheduledJob(update);\n }\n };\n options.devtools?.attachRuntime?.(runtime);\n }\n\n async start(): Promise<void> {\n if (this.started) {\n return;\n }\n this.runtimeStatus.setStatus({\n kind: \"starting\",\n reason: \"booting\",\n capabilities: this.runtimeCapabilities\n });\n await this.prepareForDirectAccess();\n try {\n await this.runComponentHooks(\"onStart\");\n this.reactivityEngine.start();\n this.schedulerEngine.startPolling();\n this.started = true;\n this.runtimeStatus.setStatus({\n kind: \"ready\",\n capabilities: this.runtimeCapabilities\n });\n this.devtoolsEngine.emit({\n type: \"runtime.connected\",\n runtimeId: this.runtimeId,\n platform: this.platform,\n timestamp: Date.now()\n });\n } catch (error) {\n this.schedulerEngine.stopPolling();\n this.reactivityEngine.stop();\n await this.options.driver.close?.().catch(() => undefined);\n this.started = false;\n this.runtimeStatus.setStatus({\n kind: \"error\",\n reason: \"runtime-unavailable\",\n capabilities: this.runtimeCapabilities,\n ...(error instanceof Error ? { error } : {})\n });\n throw error;\n }\n }\n\n async prepareForDirectAccess(): Promise<void> {\n if (this.prepared) {\n return;\n }\n await ensureSupportedSystemFormats(this.options.driver);\n await this.schemaEngine.prepare();\n await this.storageEngine.prepare();\n await this.schedulerEngine.prepare();\n await this.storageEngine.reconcile();\n await this.schemaEngine.applySchema();\n await this.schedulerEngine.syncRecurringJobs();\n this.prepared = true;\n }\n\n async stop(): Promise<void> {\n this.schedulerEngine.stopPolling();\n let stopError: unknown;\n if (this.started) {\n try {\n await this.runComponentHooks(\"onStop\");\n } catch (error) {\n stopError = error;\n }\n }\n this.reactivityEngine.stop();\n await this.options.driver.close?.();\n if (this.started) {\n this.devtoolsEngine.emit({\n type: \"runtime.disconnected\",\n runtimeId: this.runtimeId,\n timestamp: Date.now()\n });\n }\n this.started = false;\n this.runtimeStatus.setStatus({\n kind: \"unavailable\",\n reason: \"disposed\",\n capabilities: this.runtimeCapabilities\n });\n if (stopError) {\n throw stopError;\n }\n }\n\n createClient(): SyncoreClient {\n return this.executionEngine.createClient();\n }\n\n watchQuery<TArgs, TResult>(\n reference: FunctionReference<\"query\", TArgs, TResult>,\n args: Record<string, unknown> = {}\n ): SyncoreWatch<TResult> {\n return this.executionEngine.watchQuery(reference, args);\n }\n\n private async runComponentHooks(hook: \"onStart\" | \"onStop\"): Promise<void> {\n for (const component of this.options.components ?? []) {\n await this.runComponentHookTree(component, hook);\n }\n }\n\n private async runComponentHookTree(\n component: SyncoreResolvedComponents[number],\n hook: \"onStart\" | \"onStop\"\n ): Promise<void> {\n const handler = component[hook];\n if (handler) {\n await handler({\n runtimeId: this.runtimeId,\n platform: this.platform,\n componentPath: component.path,\n componentName: component.name,\n version: component.version,\n config: component.config,\n capabilities: component.grantedCapabilities,\n emitDevtools: (event: SyncoreDevtoolsEvent) => {\n this.devtoolsEngine.emit(event);\n }\n });\n }\n for (const child of component.children) {\n await this.runComponentHookTree(child, hook);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;AAwCA,IAAa,gBAAb,MAA6D;CAqBxC;CApBnB,YAAqB,WAAW;CAChC;CACA,yBAAkC,WAAW;CAC7C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,WAAmB;CACnB,UAAkB;CAElB,YACE,SACA,SACA;EAFiB,KAAA,UAAA;EAGjB,KAAK,WAAW,QAAQ,YAAY;EACpC,KAAK,wBAAwB,OAAO,OAAO,CACzC,GAAI,QAAQ,yBAAyB,CAAC,CACxC,CAAC;EACD,KAAK,eAAe,OAAO,OAAO,EAChC,GAAI,QAAQ,gBAAgB,CAAC,EAC/B,CAAC;EACD,KAAK,sBAAsB,OAAO,OAChC,QAAQ,uBAAuB,EAC7B,SAAS;GACP,WAAW;GACX,GAAI,QAAQ,QAAQ,gBAChB,EAAE,eAAe,QAAQ,QAAQ,cAAc,MAAM,MAAM,IAC3D,CAAC;EACP,EACF,CACF;EACA,KAAK,qBAAqB,wBACxB,QAAQ,MACV;EACA,KAAK,iBAAiB,IAAI,eAAe;GACvC,WAAW,KAAK;GAChB,UAAU,KAAK;GACf,GAAI,QAAQ,WAAW,EAAE,MAAM,QAAQ,SAAS,IAAI,CAAC;GACrD,2BAA2B,KAAK,iBAAiB,oBAAoB;GACrE,uBAAuB,KAAK,aAAa,2BAA2B;EACtE,CAAC;EACD,KAAK,eAAe,IAAI,aAAa;GACnC,QAAQ,QAAQ;GAChB,QAAQ,QAAQ;GAChB,WAAW,KAAK;GAChB,UAAU,KAAK;EACjB,CAAC;EACD,KAAK,gBAAgB,IAAI,cAAc;GACrC,QAAQ,QAAQ;GAChB,SAAS,QAAQ;GACjB,WAAW,KAAK;GAChB,UAAU,KAAK;EACjB,CAAC;EACD,KAAK,yBAAyB,IAAI,uBAAuB,QAAQ,MAAM;EACvE,KAAK,gBAAgB,IAAI,wBAAwB;GAC/C,MAAM;GACN,QAAQ;GACR,cAAc,KAAK;EACrB,CAAC;EACD,KAAK,kBAAkB,IAAI,gBAAgB;GACzC,QAAQ,QAAQ;GAChB,WAAW,KAAK;GAChB,UAAU,KAAK;GACf,eAAe,QAAQ,WAAW,iBAAiB,CAAC;GACpD,gBAAgB,QAAQ,WAAW,kBAAkB;GACrD,cAAc,WAAW,MAAM,SAC7B,KAAK,gBAAgB,YAAY,WAAW,MAAM,IAAI;GACxD,YAAY,WAAW,MAAM,SAC3B,KAAK,gBAAgB,UAAU,WAAW,MAAM,IAAI;EACxD,CAAC;EACD,KAAK,mBAAmB,IAAI,iBAAiB;GAC3C,WAAW,KAAK;GAChB,wBAAwB,KAAK;GAC7B,GAAI,QAAQ,uBACR,EAAE,sBAAsB,QAAQ,qBAAqB,IACrD,CAAC;GACL,GAAI,QAAQ,wBACR,EAAE,uBAAuB,QAAQ,sBAAsB,IACvD,CAAC;GACL,UAAU,KAAK;GACf,WAAW,WAAW,MAAM,SAC1B,KAAK,gBAAgB,SAAS,WAAW,MAAM,IAAI;GACrD,2BAA2B,cAAc,SACvC,KAAK,gBAAgB,yBAAyB,cAAc,IAAI;EACpE,CAAC;EACD,KAAK,kBAAkB,IAAI,gBAAgB;GACzC,WAAW,KAAK;GAChB,WAAW,QAAQ;GACnB,QAAQ,QAAQ;GAChB,cAAc,KAAK;GACnB,uBAAuB,KAAK;GAC5B,QAAQ,KAAK;GACb,SAAS,KAAK;GACd,WAAW,KAAK;GAChB,YAAY,KAAK;GACjB,UAAU,KAAK;GACf,wBAAwB,KAAK;GAC7B,eAAe,KAAK;EACtB,CAAC;EACD,KAAK,QAAQ;GACX,8BAA8B,KAAK,uBAAuB;GAC1D,oBAAoB,KAAK,aAAa;GACtC,WAAW,WAAW,MAAM,SAC1B,KAAK,gBAAgB,SAAS,WAAW,MAAM,IAAI;GACrD,cAAc,WAAW,MAAM,SAC7B,KAAK,gBAAgB,YAAY,WAAW,MAAM,IAAI;GACxD,YAAY,WAAW,MAAM,SAC3B,KAAK,gBAAgB,UAAU,WAAW,MAAM,IAAI;GACtD,qBAAqB,OAAO,UAAU,SAAS;IAC7C,MAAM,KAAK,uBAAuB;IAClC,OAAO,KAAK,gBAAgB,oBAAoB,UAAU,IAAI;GAChE;GACA,yBAAyB,KAAK,eAAe,kBAAkB;GAC/D,2BAA2B,KAAK,iBAAiB,oBAAoB;GACrE,oBAAoB,KAAK;GACzB,6BAA6B,KAAK;GAClC,4BAA4B,aAC1B,KAAK,eAAe,gBAAgB,QAAQ;GAC9C,mCAAmC,aACjC,KAAK,eAAe,uBAAuB,QAAQ;GACrD,uBAAuB,WACrB,KAAK,eAAe,aAAa,MAAM;GACzC,sBAAsB,OAAO,QAAQ,QAAQ,SAAS;IACpD,MAAM,iBAAiB,IAAI,IAAI,UAAU,CAAC,CAAC;IAC3C,IAAI,eAAe,OAAO,GACxB,MAAM,KAAK,iBAAiB,wBAC1B,gBACA,MACF;IAEF,MAAM,KAAK,eAAe,aACxB,QACA,EACE,0BAA0B,iBAAiB,kBACzC,KAAK,iBAAiB,wBACpB,iBACA,aACF,EACJ,GACA,MACA,cACF;GACF;GACA,oBAAoB,OAAO,YAAY;IACrC,MAAM,KAAK,uBAAuB;IAClC,OAAO,KAAK,cAAc,YAAY,OAAO;GAC/C;GACA,4BAA4B,OAAO,OAAO;IACxC,MAAM,KAAK,uBAAuB;IAClC,OAAO,KAAK,cAAc,oBAAoB,EAAE;GAClD;GACA,wBAAwB,OAAO,IAAI,QAAQ,WAAW;IACpD,MAAM,KAAK,uBAAuB;IAClC,OAAO,KAAK,cAAc,gBAAgB,IAAI,QAAQ,MAAM;GAC9D;GACA,qBAAqB,OAAO,IAAI,SAAS;IACvC,MAAM,KAAK,uBAAuB;IAClC,MAAM,UAAU,MAAM,KAAK,cAAc,aAAa,IAAI,IAAI;IAC9D,IAAI,SACF,KAAK,eAAe,aAAa;KAC/B;KACA;KACA,WAAW;IACb,CAAC;IAEH,OAAO;GACT;GACA,oBAAoB,OAAO,OAAO;IAChC,MAAM,KAAK,uBAAuB;IAClC,OAAO,KAAK,gBAAgB,mBAAmB,EAAE;GACnD;GACA,oBAAoB,OAAO,WAAsC;IAC/D,MAAM,KAAK,uBAAuB;IAClC,OAAO,KAAK,gBAAgB,mBAAmB,MAAM;GACvD;EACF;EACA,QAAQ,UAAU,gBAAgB,OAAO;CAC3C;CAEA,MAAM,QAAuB;EAC3B,IAAI,KAAK,SACP;EAEF,KAAK,cAAc,UAAU;GAC3B,MAAM;GACN,QAAQ;GACR,cAAc,KAAK;EACrB,CAAC;EACD,MAAM,KAAK,uBAAuB;EAClC,IAAI;GACF,MAAM,KAAK,kBAAkB,SAAS;GACtC,KAAK,iBAAiB,MAAM;GAC5B,KAAK,gBAAgB,aAAa;GAClC,KAAK,UAAU;GACf,KAAK,cAAc,UAAU;IAC3B,MAAM;IACN,cAAc,KAAK;GACrB,CAAC;GACD,KAAK,eAAe,KAAK;IACvB,MAAM;IACN,WAAW,KAAK;IAChB,UAAU,KAAK;IACf,WAAW,KAAK,IAAI;GACtB,CAAC;EACH,SAAS,OAAO;GACd,KAAK,gBAAgB,YAAY;GACjC,KAAK,iBAAiB,KAAK;GAC3B,MAAM,KAAK,QAAQ,OAAO,QAAQ,EAAE,YAAY,KAAA,CAAS;GACzD,KAAK,UAAU;GACf,KAAK,cAAc,UAAU;IAC3B,MAAM;IACN,QAAQ;IACR,cAAc,KAAK;IACnB,GAAI,iBAAiB,QAAQ,EAAE,MAAM,IAAI,CAAC;GAC5C,CAAC;GACD,MAAM;EACR;CACF;CAEA,MAAM,yBAAwC;EAC5C,IAAI,KAAK,UACP;EAEF,MAAM,6BAA6B,KAAK,QAAQ,MAAM;EACtD,MAAM,KAAK,aAAa,QAAQ;EAChC,MAAM,KAAK,cAAc,QAAQ;EACjC,MAAM,KAAK,gBAAgB,QAAQ;EACnC,MAAM,KAAK,cAAc,UAAU;EACnC,MAAM,KAAK,aAAa,YAAY;EACpC,MAAM,KAAK,gBAAgB,kBAAkB;EAC7C,KAAK,WAAW;CAClB;CAEA,MAAM,OAAsB;EAC1B,KAAK,gBAAgB,YAAY;EACjC,IAAI;EACJ,IAAI,KAAK,SACP,IAAI;GACF,MAAM,KAAK,kBAAkB,QAAQ;EACvC,SAAS,OAAO;GACd,YAAY;EACd;EAEF,KAAK,iBAAiB,KAAK;EAC3B,MAAM,KAAK,QAAQ,OAAO,QAAQ;EAClC,IAAI,KAAK,SACP,KAAK,eAAe,KAAK;GACvB,MAAM;GACN,WAAW,KAAK;GAChB,WAAW,KAAK,IAAI;EACtB,CAAC;EAEH,KAAK,UAAU;EACf,KAAK,cAAc,UAAU;GAC3B,MAAM;GACN,QAAQ;GACR,cAAc,KAAK;EACrB,CAAC;EACD,IAAI,WACF,MAAM;CAEV;CAEA,eAA8B;EAC5B,OAAO,KAAK,gBAAgB,aAAa;CAC3C;CAEA,WACE,WACA,OAAgC,CAAC,GACV;EACvB,OAAO,KAAK,gBAAgB,WAAW,WAAW,IAAI;CACxD;CAEA,MAAc,kBAAkB,MAA2C;EACzE,KAAK,MAAM,aAAa,KAAK,QAAQ,cAAc,CAAC,GAClD,MAAM,KAAK,qBAAqB,WAAW,IAAI;CAEnD;CAEA,MAAc,qBACZ,WACA,MACe;EACf,MAAM,UAAU,UAAU;EAC1B,IAAI,SACF,MAAM,QAAQ;GACZ,WAAW,KAAK;GAChB,UAAU,KAAK;GACf,eAAe,UAAU;GACzB,eAAe,UAAU;GACzB,SAAS,UAAU;GACnB,QAAQ,UAAU;GAClB,cAAc,UAAU;GACxB,eAAe,UAAgC;IAC7C,KAAK,eAAe,KAAK,KAAK;GAChC;EACF,CAAC;EAEH,KAAK,MAAM,SAAS,UAAU,UAC5B,MAAM,KAAK,qBAAqB,OAAO,IAAI;CAE/C;AACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FunctionArgs, FunctionArgsFromDefinition, FunctionKindFromDefinition, FunctionReference, FunctionResultFromDefinition, MisfirePolicy, RecurringJobDefinition, RecurringSchedule, SyncoreFunctionKind } from "./functions.mjs";
|
|
2
2
|
import { ResolvedSyncoreComponent, SyncoreComponentFunctionMetadata } from "./components.mjs";
|
|
3
3
|
import { AnyTableDefinition, InferDocument, InferTableInput, SyncoreSchemaDefinition, TableIndexFields, TableIndexNames, TableSearchIndexConfig, TableSearchIndexNames, Validator } from "../../schema/index.d.ts";
|
|
4
|
-
import { DocumentChangePreview, SyncoreActiveQueryInfo, SyncoreDevtoolsEvent, SyncoreDevtoolsEventOrigin, SyncoreRuntimeSummary } from "../../devtools-protocol/index.d.ts";
|
|
4
|
+
import { DocumentChangePreview, StorageEntry, SyncoreActiveQueryInfo, SyncoreDevtoolsEvent, SyncoreDevtoolsEventOrigin, SyncoreRuntimeSummary } from "../../devtools-protocol/index.d.ts";
|
|
5
5
|
|
|
6
6
|
//#region src/runtime/runtime.d.ts
|
|
7
7
|
/**
|
|
@@ -120,12 +120,12 @@ interface CapabilityDescriptor {
|
|
|
120
120
|
* mutation that writes to the `tasks` table.
|
|
121
121
|
*
|
|
122
122
|
* - `"runtime.summary"` / `"runtime.activeQueries"` / `"schema.tables"` /
|
|
123
|
-
* `"scheduler.jobs"`
|
|
124
|
-
* -
|
|
125
|
-
* -
|
|
126
|
-
* -
|
|
123
|
+
* `"scheduler.jobs"` / `"storage.objects"` - runtime-level state consumed by devtools.
|
|
124
|
+
* - `table:${string}` - every document in a specific table.
|
|
125
|
+
* - `row:${string}:${string}` - a single document (table + id).
|
|
126
|
+
* - `storage:${string}` - a specific storage object.
|
|
127
127
|
*/
|
|
128
|
-
type ImpactScope = "runtime.summary" | "runtime.activeQueries" | "schema.tables" | "scheduler.jobs" | `table:${string}` | `row:${string}:${string}` | `storage:${string}`;
|
|
128
|
+
type ImpactScope = "runtime.summary" | "runtime.activeQueries" | "schema.tables" | "scheduler.jobs" | "storage.objects" | `table:${string}` | `row:${string}:${string}` | `storage:${string}`;
|
|
129
129
|
/** A frozen set of {@link ImpactScope} values. */
|
|
130
130
|
type ImpactSet = ReadonlySet<ImpactScope>;
|
|
131
131
|
interface ExecutionResult<TResult = unknown> {
|
|
@@ -358,6 +358,18 @@ interface SyncoreStorageAdapter {
|
|
|
358
358
|
* Return the raw bytes of a stored object, or `null` if it does not exist.
|
|
359
359
|
*/
|
|
360
360
|
read(id: string): Promise<Uint8Array | null>;
|
|
361
|
+
/**
|
|
362
|
+
* Return a byte range for a stored object, or `null` if it does not exist.
|
|
363
|
+
*
|
|
364
|
+
* Adapters that can seek without loading the whole object should implement
|
|
365
|
+
* this so devtools preview and download endpoints can stream large files.
|
|
366
|
+
*/
|
|
367
|
+
readRange?(id: string, offset: number, length: number): Promise<Uint8Array | null>;
|
|
368
|
+
/**
|
|
369
|
+
* Return `false` when `readRange` is intentionally unavailable for this
|
|
370
|
+
* adapter instance.
|
|
371
|
+
*/
|
|
372
|
+
supportsRange?(): boolean;
|
|
361
373
|
/**
|
|
362
374
|
* Permanently remove a stored object. A no-op if the object does not exist.
|
|
363
375
|
*/
|
|
@@ -415,7 +427,7 @@ interface DevtoolsLiveQuerySnapshot {
|
|
|
415
427
|
documentCount: number;
|
|
416
428
|
}>;
|
|
417
429
|
}
|
|
418
|
-
type DevtoolsLiveQueryScope = "all" | "runtime.summary" | "runtime.activeQueries" | "schema.tables" | "scheduler.jobs" | `table:${string}` | `storage:${string}`;
|
|
430
|
+
type DevtoolsLiveQueryScope = "all" | "runtime.summary" | "runtime.activeQueries" | "schema.tables" | "scheduler.jobs" | "storage.objects" | `table:${string}` | `storage:${string}`;
|
|
419
431
|
/**
|
|
420
432
|
* Configuration for the Syncore built-in scheduler.
|
|
421
433
|
*
|
|
@@ -567,6 +579,13 @@ interface SyncoreRuntimeOptions<TSchema extends SyncoreDataModel> {
|
|
|
567
579
|
* every function handler. See {@link SyncoreCapabilities}.
|
|
568
580
|
*/
|
|
569
581
|
capabilities?: SyncoreCapabilities;
|
|
582
|
+
/**
|
|
583
|
+
* Capabilities exposed to clients through `watchRuntimeStatus()`.
|
|
584
|
+
*
|
|
585
|
+
* Platform adapters fill this with feature availability that app UIs should
|
|
586
|
+
* honor, such as whether `ctx.storage` is usable in the current environment.
|
|
587
|
+
*/
|
|
588
|
+
runtimeCapabilities?: SyncoreRuntimeCapabilities;
|
|
570
589
|
/** Structured capability descriptors validated at start-up. */
|
|
571
590
|
capabilityDescriptors?: CapabilityDescriptor[];
|
|
572
591
|
/**
|
|
@@ -648,6 +667,21 @@ type SyncoreRuntimeStatusKind = "starting" | "ready" | "recovering" | "unavailab
|
|
|
648
667
|
* Useful for rendering descriptive loading or error messages in the UI.
|
|
649
668
|
*/
|
|
650
669
|
type SyncoreRuntimeStatusReason = "booting" | "rehydrating" | "worker-restarting" | "worker-unavailable" | "ipc-unavailable" | "runtime-unavailable" | "disposed";
|
|
670
|
+
/** Runtime-visible storage capability for app UIs and adapters. */
|
|
671
|
+
interface SyncoreRuntimeStorageCapability {
|
|
672
|
+
/** Whether `ctx.storage` can read/write objects in this runtime. */
|
|
673
|
+
available: boolean;
|
|
674
|
+
/** Short reason to show when storage is unavailable. */
|
|
675
|
+
reason?: string;
|
|
676
|
+
/** Storage protocol used by the adapter, such as `"file"` or `"opfs"`. */
|
|
677
|
+
protocol?: string;
|
|
678
|
+
/** Whether the adapter can read byte ranges without loading the full object. */
|
|
679
|
+
supportsRange?: boolean;
|
|
680
|
+
}
|
|
681
|
+
/** Runtime capabilities exposed through `watchRuntimeStatus()`. */
|
|
682
|
+
interface SyncoreRuntimeCapabilities {
|
|
683
|
+
storage: SyncoreRuntimeStorageCapability;
|
|
684
|
+
}
|
|
651
685
|
/**
|
|
652
686
|
* Snapshot of the runtime’s current lifecycle state.
|
|
653
687
|
*
|
|
@@ -667,6 +701,8 @@ interface SyncoreRuntimeStatus {
|
|
|
667
701
|
reason?: SyncoreRuntimeStatusReason;
|
|
668
702
|
/** The underlying error when `kind` is `"error"`. */
|
|
669
703
|
error?: Error;
|
|
704
|
+
/** Runtime capabilities that app UIs can use to enable or hide affordances. */
|
|
705
|
+
capabilities?: SyncoreRuntimeCapabilities;
|
|
670
706
|
}
|
|
671
707
|
/**
|
|
672
708
|
* Lifecycle status of an individual reactive query subscription.
|
|
@@ -1238,6 +1274,27 @@ interface SyncoreRuntimeAdmin<TSchema extends SyncoreDataModel = SyncoreDataMode
|
|
|
1238
1274
|
subscribeToDevtoolsInvalidations(listener: (scopes: Set<DevtoolsLiveQueryScope>) => void): () => void;
|
|
1239
1275
|
notifyDevtoolsScopes(scopes: Iterable<DevtoolsLiveQueryScope>): void;
|
|
1240
1276
|
forceRefreshDevtools(reason: string, scopes?: Iterable<ImpactScope>, meta?: DevtoolsEventMeta): Promise<void>;
|
|
1277
|
+
listStorageObjects(options?: {
|
|
1278
|
+
limit?: number;
|
|
1279
|
+
offset?: number;
|
|
1280
|
+
search?: string;
|
|
1281
|
+
}): Promise<{
|
|
1282
|
+
entries: StorageEntry[];
|
|
1283
|
+
totalCount: number;
|
|
1284
|
+
}>;
|
|
1285
|
+
getStorageObjectAccessInfo(id: string): Promise<{
|
|
1286
|
+
entry: StorageEntry;
|
|
1287
|
+
supportsRange: boolean;
|
|
1288
|
+
} | null>;
|
|
1289
|
+
readStorageObjectRange(id: string, offset: number, length: number): Promise<{
|
|
1290
|
+
entry: StorageEntry;
|
|
1291
|
+
bytes: Uint8Array;
|
|
1292
|
+
offset: number;
|
|
1293
|
+
bytesRead: number;
|
|
1294
|
+
done: boolean;
|
|
1295
|
+
supportsRange: boolean;
|
|
1296
|
+
} | null>;
|
|
1297
|
+
deleteStorageObject(id: string, meta?: DevtoolsEventMeta): Promise<boolean>;
|
|
1241
1298
|
cancelScheduledJob(id: string): Promise<boolean>;
|
|
1242
1299
|
updateScheduledJob(options: UpdateScheduledJobOptions): Promise<boolean>;
|
|
1243
1300
|
}
|
|
@@ -1433,5 +1490,5 @@ declare function createFunctionReferenceFor<TDefinition extends {
|
|
|
1433
1490
|
returnsValidator?: Validator<unknown, unknown, string>;
|
|
1434
1491
|
}>(kind: FunctionKindFromDefinition<TDefinition>, name: string): FunctionReference<FunctionKindFromDefinition<TDefinition>, FunctionArgsFromDefinition<TDefinition>, FunctionResultFromDefinition<TDefinition>>;
|
|
1435
1492
|
//#endregion
|
|
1436
|
-
export { ActionCtx, CapabilityDescriptor, ComparisonOperator, DevtoolsLiveQueryScope, DevtoolsLiveQuerySnapshot, DevtoolsSink, DocumentForTable, ExecutionResult, FilterBuilder, ImpactScope, ImpactSet, IndexRangeBuilder, InsertValueForTable, JsonObject, MutationCtx, PaginationOptions, PaginationResult, PatchValueForTable, QueryBuilder, QueryCondition, QueryCtx, QueryExpression, RegisteredSyncoreFunction, RegisteredSyncoreHandler, RunResult, SchedulerApi, SchedulerOptions, SearchIndexBuilder, SearchQuery, StorageObject, StorageWriteInput, SyncoreCapabilities, SyncoreClient, SyncoreDataModel, SyncoreDatabaseReader, SyncoreDatabaseWriter, SyncoreExternalChangeApplier, SyncoreExternalChangeEvent, SyncoreExternalChangeReason, SyncoreExternalChangeScope, SyncoreExternalChangeSignal, SyncoreFunctionRegistry, SyncorePaginatedQueryStatus, SyncoreQueriesRequest, SyncoreQueryRequest, SyncoreQueryState, SyncoreQueryStatus, SyncoreResolvedComponents, SyncoreRuntime, SyncoreRuntimeAdmin, SyncoreRuntimeOptions, SyncoreRuntimeStatus, SyncoreRuntimeStatusKind, SyncoreRuntimeStatusReason, SyncoreSqlDriver, SyncoreStorageAdapter, SyncoreStorageApi, SyncoreWatch, TableNames, UpdateScheduledJobOptions, UsePaginatedQueryResult, createFunctionReference, createFunctionReferenceFor };
|
|
1493
|
+
export { ActionCtx, CapabilityDescriptor, ComparisonOperator, DevtoolsLiveQueryScope, DevtoolsLiveQuerySnapshot, DevtoolsSink, DocumentForTable, ExecutionResult, FilterBuilder, ImpactScope, ImpactSet, IndexRangeBuilder, InsertValueForTable, JsonObject, MutationCtx, PaginationOptions, PaginationResult, PatchValueForTable, QueryBuilder, QueryCondition, QueryCtx, QueryExpression, RegisteredSyncoreFunction, RegisteredSyncoreHandler, RunResult, SchedulerApi, SchedulerOptions, SearchIndexBuilder, SearchQuery, StorageObject, StorageWriteInput, SyncoreCapabilities, SyncoreClient, SyncoreDataModel, SyncoreDatabaseReader, SyncoreDatabaseWriter, SyncoreExternalChangeApplier, SyncoreExternalChangeEvent, SyncoreExternalChangeReason, SyncoreExternalChangeScope, SyncoreExternalChangeSignal, SyncoreFunctionRegistry, SyncorePaginatedQueryStatus, SyncoreQueriesRequest, SyncoreQueryRequest, SyncoreQueryState, SyncoreQueryStatus, SyncoreResolvedComponents, SyncoreRuntime, SyncoreRuntimeAdmin, SyncoreRuntimeCapabilities, SyncoreRuntimeOptions, SyncoreRuntimeStatus, SyncoreRuntimeStatusKind, SyncoreRuntimeStatusReason, SyncoreRuntimeStorageCapability, SyncoreSqlDriver, SyncoreStorageAdapter, SyncoreStorageApi, SyncoreWatch, TableNames, UpdateScheduledJobOptions, UsePaginatedQueryResult, createFunctionReference, createFunctionReferenceFor };
|
|
1437
1494
|
//# sourceMappingURL=runtime.d.mts.map
|