syncorejs 0.2.2 → 0.2.3
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/_vendor/cli/app.d.mts.map +1 -1
- package/dist/_vendor/cli/app.mjs +8 -5
- package/dist/_vendor/cli/app.mjs.map +1 -1
- package/dist/_vendor/cli/context.mjs.map +1 -1
- package/dist/_vendor/cli/dev-session.mjs.map +1 -1
- package/dist/_vendor/cli/doctor.mjs.map +1 -1
- package/dist/_vendor/cli/errors.mjs.map +1 -1
- package/dist/_vendor/cli/help.mjs.map +1 -1
- package/dist/_vendor/cli/index.mjs +9 -2
- package/dist/_vendor/cli/index.mjs.map +1 -1
- package/dist/_vendor/cli/messages.mjs.map +1 -1
- package/dist/_vendor/cli/preflight.mjs.map +1 -1
- package/dist/_vendor/cli/project.mjs +20 -20
- package/dist/_vendor/cli/project.mjs.map +1 -1
- package/dist/_vendor/cli/render.mjs.map +1 -1
- package/dist/_vendor/cli/targets.mjs.map +1 -1
- package/dist/_vendor/core/cli.d.mts +8 -2
- package/dist/_vendor/core/cli.d.mts.map +1 -1
- package/dist/_vendor/core/cli.mjs +238 -64
- package/dist/_vendor/core/cli.mjs.map +1 -1
- package/dist/_vendor/core/devtools-auth.mjs.map +1 -1
- package/dist/_vendor/core/runtime/components.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/components.mjs.map +1 -1
- package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/devtools.mjs +130 -23
- package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
- package/dist/_vendor/core/runtime/functions.d.mts +388 -6
- package/dist/_vendor/core/runtime/functions.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/functions.mjs +72 -1
- package/dist/_vendor/core/runtime/functions.mjs.map +1 -1
- package/dist/_vendor/core/runtime/id.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/id.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs +11 -5
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs +123 -20
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs +56 -8
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs +49 -14
- package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs +4 -7
- package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs +76 -1
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs +1 -0
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs +4 -3
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/systemMeta.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs +4 -0
- package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs.map +1 -1
- package/dist/_vendor/core/runtime/runtime.d.mts +1040 -9
- package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/runtime.mjs +63 -0
- package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
- package/dist/_vendor/core/transport.d.mts +2 -0
- package/dist/_vendor/core/transport.d.mts.map +1 -1
- package/dist/_vendor/core/transport.mjs +33 -24
- package/dist/_vendor/core/transport.mjs.map +1 -1
- package/dist/_vendor/devtools-protocol/index.d.ts +149 -4
- 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/config.d.ts +3 -4
- package/dist/_vendor/next/config.d.ts.map +1 -1
- package/dist/_vendor/next/config.js +37 -19
- package/dist/_vendor/next/config.js.map +1 -1
- package/dist/_vendor/next/index.d.ts +109 -29
- package/dist/_vendor/next/index.d.ts.map +1 -1
- package/dist/_vendor/next/index.js +77 -17
- package/dist/_vendor/next/index.js.map +1 -1
- package/dist/_vendor/platform-expo/index.d.ts +146 -27
- package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
- package/dist/_vendor/platform-expo/index.js +76 -10
- package/dist/_vendor/platform-expo/index.js.map +1 -1
- package/dist/_vendor/platform-expo/react.js.map +1 -1
- package/dist/_vendor/platform-expo/web-sqljs-wasm.js +16 -0
- package/dist/_vendor/platform-expo/web-sqljs-wasm.js.map +1 -0
- package/dist/_vendor/platform-node/index.d.mts +173 -9
- package/dist/_vendor/platform-node/index.d.mts.map +1 -1
- package/dist/_vendor/platform-node/index.mjs +225 -94
- package/dist/_vendor/platform-node/index.mjs.map +1 -1
- package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -1
- package/dist/_vendor/platform-node/ipc.d.mts.map +1 -1
- package/dist/_vendor/platform-node/ipc.mjs.map +1 -1
- package/dist/_vendor/platform-web/external-change.d.ts +41 -0
- package/dist/_vendor/platform-web/external-change.d.ts.map +1 -1
- package/dist/_vendor/platform-web/external-change.js +30 -0
- package/dist/_vendor/platform-web/external-change.js.map +1 -1
- package/dist/_vendor/platform-web/index.d.ts +307 -35
- package/dist/_vendor/platform-web/index.d.ts.map +1 -1
- package/dist/_vendor/platform-web/index.js +189 -23
- package/dist/_vendor/platform-web/index.js.map +1 -1
- package/dist/_vendor/platform-web/indexeddb.d.ts +12 -0
- package/dist/_vendor/platform-web/indexeddb.d.ts.map +1 -1
- package/dist/_vendor/platform-web/indexeddb.js +10 -0
- package/dist/_vendor/platform-web/indexeddb.js.map +1 -1
- package/dist/_vendor/platform-web/opfs.d.ts +13 -0
- package/dist/_vendor/platform-web/opfs.d.ts.map +1 -1
- package/dist/_vendor/platform-web/opfs.js +12 -0
- package/dist/_vendor/platform-web/opfs.js.map +1 -1
- package/dist/_vendor/platform-web/persistence.d.ts +54 -0
- package/dist/_vendor/platform-web/persistence.d.ts.map +1 -1
- package/dist/_vendor/platform-web/persistence.js +15 -0
- package/dist/_vendor/platform-web/persistence.js.map +1 -1
- package/dist/_vendor/platform-web/react.d.ts +1 -2
- package/dist/_vendor/platform-web/react.d.ts.map +1 -1
- package/dist/_vendor/platform-web/react.js +2 -4
- package/dist/_vendor/platform-web/react.js.map +1 -1
- package/dist/_vendor/platform-web/sqljs.js +10 -1
- package/dist/_vendor/platform-web/sqljs.js.map +1 -1
- package/dist/_vendor/platform-web/web-sqljs-wasm.js +8 -0
- package/dist/_vendor/platform-web/web-sqljs-wasm.js.map +1 -0
- package/dist/_vendor/platform-web/worker.d.ts +60 -9
- package/dist/_vendor/platform-web/worker.d.ts.map +1 -1
- package/dist/_vendor/platform-web/worker.js +37 -4
- package/dist/_vendor/platform-web/worker.js.map +1 -1
- package/dist/_vendor/react/index.d.ts +196 -13
- package/dist/_vendor/react/index.d.ts.map +1 -1
- package/dist/_vendor/react/index.js +208 -17
- package/dist/_vendor/react/index.js.map +1 -1
- package/dist/_vendor/schema/definition.d.ts +129 -0
- package/dist/_vendor/schema/definition.d.ts.map +1 -1
- package/dist/_vendor/schema/definition.js +99 -0
- package/dist/_vendor/schema/definition.js.map +1 -1
- package/dist/_vendor/schema/planner.d.ts.map +1 -1
- package/dist/_vendor/schema/planner.js.map +1 -1
- package/dist/_vendor/schema/validators.d.ts +180 -4
- package/dist/_vendor/schema/validators.d.ts.map +1 -1
- package/dist/_vendor/schema/validators.js +35 -1
- package/dist/_vendor/schema/validators.js.map +1 -1
- package/dist/_vendor/svelte/index.d.ts +205 -7
- package/dist/_vendor/svelte/index.d.ts.map +1 -1
- package/dist/_vendor/svelte/index.js +199 -6
- package/dist/_vendor/svelte/index.js.map +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/package.json +24 -21
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devtools-auth.mjs","names":[],"sources":["../src/devtools-auth.ts"],"sourcesContent":["import { randomBytes, timingSafeEqual } from \"node:crypto\";\n\nconst TOKEN_ALPHABET = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\nexport function sanitizeDevtoolsToken(value: string | undefined): string | null {\n if (!value) {\n return null;\n }\n const sanitized = value.replace(/[^A-Za-z0-9]/g, \"\");\n return sanitized.length > 0 ? sanitized : null;\n}\n\nexport function generateDevtoolsToken(length = 20): string {\n let token = \"\";\n while (token.length < length) {\n const bytes = randomBytes(length);\n for (const byte of bytes) {\n if (byte >= 248) {\n continue;\n }\n token += TOKEN_ALPHABET[byte % TOKEN_ALPHABET.length];\n if (token.length === length) {\n break;\n }\n }\n }\n return token;\n}\n\nexport function readDevtoolsTokenFromUrl(requestUrl: string | undefined): string | null {\n if (!requestUrl) {\n return null;\n }\n try {\n const url = new URL(requestUrl, \"ws://localhost\");\n return url.searchParams.get(\"token\") ?? url.searchParams.get(\"hubToken\");\n } catch {\n return null;\n }\n}\n\nexport function isAllowedDashboardOrigin(\n originHeader: string | undefined,\n dashboardPort: number\n): boolean {\n if (!originHeader) {\n return false;\n }\n try {\n const origin = new URL(originHeader);\n if (!isLoopbackHostname(origin.hostname)) {\n return false;\n }\n const expectedPort = String(dashboardPort);\n const originPort =\n origin.port ||\n (origin.protocol === \"https:\" ? \"443\" : origin.protocol === \"http:\" ? \"80\" : \"\");\n return originPort === expectedPort;\n } catch {\n return false;\n }\n}\n\nexport function isAuthorizedDashboardRequest(input: {\n requestUrl: string | undefined;\n originHeader: string | undefined;\n dashboardPort: number;\n expectedToken: string;\n}): boolean {\n if (!isAllowedDashboardOrigin(input.originHeader, input.dashboardPort)) {\n return false;\n }\n const providedToken = readDevtoolsTokenFromUrl(input.requestUrl);\n if (!providedToken) {\n return false;\n }\n return tokensMatch(providedToken, input.expectedToken);\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n const normalized = hostname.toLowerCase();\n return (\n normalized === \"localhost\" ||\n normalized === \"127.0.0.1\" ||\n normalized === \"::1\" ||\n normalized === \"[::1]\"\n );\n}\n\nfunction tokensMatch(left: string, right: string): boolean {\n const leftBuffer = Buffer.from(left, \"utf8\");\n const rightBuffer = Buffer.from(right, \"utf8\");\n if (leftBuffer.length !== rightBuffer.length) {\n return false;\n }\n return timingSafeEqual(leftBuffer, rightBuffer);\n}\n"],"mappings":";;AAEA,MAAM,iBAAiB;AAEvB,SAAgB,sBAAsB,OAA0C;
|
|
1
|
+
{"version":3,"file":"devtools-auth.mjs","names":[],"sources":["../src/devtools-auth.ts"],"sourcesContent":["import { randomBytes, timingSafeEqual } from \"node:crypto\";\n\nconst TOKEN_ALPHABET = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\nexport function sanitizeDevtoolsToken(value: string | undefined): string | null {\n if (!value) {\n return null;\n }\n const sanitized = value.replace(/[^A-Za-z0-9]/g, \"\");\n return sanitized.length > 0 ? sanitized : null;\n}\n\nexport function generateDevtoolsToken(length = 20): string {\n let token = \"\";\n while (token.length < length) {\n const bytes = randomBytes(length);\n for (const byte of bytes) {\n if (byte >= 248) {\n continue;\n }\n token += TOKEN_ALPHABET[byte % TOKEN_ALPHABET.length];\n if (token.length === length) {\n break;\n }\n }\n }\n return token;\n}\n\nexport function readDevtoolsTokenFromUrl(requestUrl: string | undefined): string | null {\n if (!requestUrl) {\n return null;\n }\n try {\n const url = new URL(requestUrl, \"ws://localhost\");\n return url.searchParams.get(\"token\") ?? url.searchParams.get(\"hubToken\");\n } catch {\n return null;\n }\n}\n\nexport function isAllowedDashboardOrigin(\n originHeader: string | undefined,\n dashboardPort: number\n): boolean {\n if (!originHeader) {\n return false;\n }\n try {\n const origin = new URL(originHeader);\n if (!isLoopbackHostname(origin.hostname)) {\n return false;\n }\n const expectedPort = String(dashboardPort);\n const originPort =\n origin.port ||\n (origin.protocol === \"https:\" ? \"443\" : origin.protocol === \"http:\" ? \"80\" : \"\");\n return originPort === expectedPort;\n } catch {\n return false;\n }\n}\n\nexport function isAuthorizedDashboardRequest(input: {\n requestUrl: string | undefined;\n originHeader: string | undefined;\n dashboardPort: number;\n expectedToken: string;\n}): boolean {\n if (!isAllowedDashboardOrigin(input.originHeader, input.dashboardPort)) {\n return false;\n }\n const providedToken = readDevtoolsTokenFromUrl(input.requestUrl);\n if (!providedToken) {\n return false;\n }\n return tokensMatch(providedToken, input.expectedToken);\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n const normalized = hostname.toLowerCase();\n return (\n normalized === \"localhost\" ||\n normalized === \"127.0.0.1\" ||\n normalized === \"::1\" ||\n normalized === \"[::1]\"\n );\n}\n\nfunction tokensMatch(left: string, right: string): boolean {\n const leftBuffer = Buffer.from(left, \"utf8\");\n const rightBuffer = Buffer.from(right, \"utf8\");\n if (leftBuffer.length !== rightBuffer.length) {\n return false;\n }\n return timingSafeEqual(leftBuffer, rightBuffer);\n}\n"],"mappings":";;AAEA,MAAM,iBAAiB;AAEvB,SAAgB,sBAAsB,OAA0C;CAC9E,IAAI,CAAC,OACH,OAAO;CAET,MAAM,YAAY,MAAM,QAAQ,iBAAiB,EAAE;CACnD,OAAO,UAAU,SAAS,IAAI,YAAY;AAC5C;AAEA,SAAgB,sBAAsB,SAAS,IAAY;CACzD,IAAI,QAAQ;CACZ,OAAO,MAAM,SAAS,QAAQ;EAC5B,MAAM,QAAQ,YAAY,MAAM;EAChC,KAAK,MAAM,QAAQ,OAAO;GACxB,IAAI,QAAQ,KACV;GAEF,SAAS,eAAe,OAAO;GAC/B,IAAI,MAAM,WAAW,QACnB;EAEJ;CACF;CACA,OAAO;AACT;AAEA,SAAgB,yBAAyB,YAA+C;CACtF,IAAI,CAAC,YACH,OAAO;CAET,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,YAAY,gBAAgB;EAChD,OAAO,IAAI,aAAa,IAAI,OAAO,KAAK,IAAI,aAAa,IAAI,UAAU;CACzE,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,yBACd,cACA,eACS;CACT,IAAI,CAAC,cACH,OAAO;CAET,IAAI;EACF,MAAM,SAAS,IAAI,IAAI,YAAY;EACnC,IAAI,CAAC,mBAAmB,OAAO,QAAQ,GACrC,OAAO;EAET,MAAM,eAAe,OAAO,aAAa;EAIzC,QAFE,OAAO,SACN,OAAO,aAAa,WAAW,QAAQ,OAAO,aAAa,UAAU,OAAO,SACzD;CACxB,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,6BAA6B,OAKjC;CACV,IAAI,CAAC,yBAAyB,MAAM,cAAc,MAAM,aAAa,GACnE,OAAO;CAET,MAAM,gBAAgB,yBAAyB,MAAM,UAAU;CAC/D,IAAI,CAAC,eACH,OAAO;CAET,OAAO,YAAY,eAAe,MAAM,aAAa;AACvD;AAEA,SAAS,mBAAmB,UAA2B;CACrD,MAAM,aAAa,SAAS,YAAY;CACxC,OACE,eAAe,eACf,eAAe,eACf,eAAe,SACf,eAAe;AAEnB;AAEA,SAAS,YAAY,MAAc,OAAwB;CACzD,MAAM,aAAa,OAAO,KAAK,MAAM,MAAM;CAC3C,MAAM,cAAc,OAAO,KAAK,OAAO,MAAM;CAC7C,IAAI,WAAW,WAAW,YAAY,QACpC,OAAO;CAET,OAAO,gBAAgB,YAAY,WAAW;AAChD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.d.mts","names":[],"sources":["../../src/runtime/components.ts"],"mappings":";;;;;;KAqBY,aAAA;AAAA,KAEA,qBAAA;AAAA,KAQA,sBAAA;AAAA,KAQA,0BAAA,GACR,qBAAA,WACQ,
|
|
1
|
+
{"version":3,"file":"components.d.mts","names":[],"sources":["../../src/runtime/components.ts"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.mjs","names":[],"sources":["../../src/runtime/components.ts"],"sourcesContent":["import {\n SyncoreSchema,\n TableDefinition,\n defineSchema,\n type AnyTableDefinition,\n type Validator\n} from \"@syncore/schema\";\nimport type { SyncoreDevtoolsEvent } from \"@syncore/devtools-protocol\";\nimport {\n type FunctionReference,\n type FunctionReferenceFor,\n type SyncoreFunctionDefinition,\n type SyncoreFunctionKind\n} from \"./functions.js\";\nimport type {\n JsonObject,\n RegisteredSyncoreFunction,\n SyncoreDataModel,\n SyncoreFunctionRegistry\n} from \"./runtime.js\";\n\nexport type ComponentPath = string;\n\nexport type SyncoreCoreCapability =\n | \"storage\"\n | \"scheduler\"\n | \"devtools\"\n | \"ownTables\"\n | \"publicExports\"\n | \"internalActions\";\n\nexport type SyncoreHostServiceName =\n | \"http\"\n | \"notifications\"\n | \"secureStore\"\n | \"filesystem\"\n | \"backgroundTasks\"\n | \"crypto\";\n\nexport type SyncoreRequestedCapability =\n | SyncoreCoreCapability\n | `host:${SyncoreHostServiceName}`;\n\nexport type AnySyncoreFunctionDefinition = SyncoreFunctionDefinition<\n SyncoreFunctionKind,\n any,\n any,\n unknown\n>;\n\nexport type SyncoreFunctionTree = {\n readonly [key: string]:\n | AnySyncoreFunctionDefinition\n | SyncoreFunctionTree\n | undefined;\n};\n\nexport interface SyncoreComponentHookContext {\n runtimeId: string;\n platform: string;\n componentPath: ComponentPath;\n componentName: string;\n version: string;\n config: unknown;\n capabilities: readonly SyncoreRequestedCapability[];\n emitDevtools(event: SyncoreDevtoolsEvent): void;\n}\n\nexport interface SyncoreComponent<\n TConfig = unknown,\n TSchema extends SyncoreDataModel | undefined =\n | SyncoreDataModel\n | undefined,\n TPublic extends SyncoreFunctionTree | undefined =\n | SyncoreFunctionTree\n | undefined,\n TInternal extends SyncoreFunctionTree | undefined =\n | SyncoreFunctionTree\n | undefined\n> {\n readonly kind: \"syncore.component\";\n readonly name: string;\n readonly version: string;\n readonly config?: Validator<TConfig>;\n readonly requestedCapabilities?: readonly SyncoreRequestedCapability[];\n readonly schema?: TSchema;\n readonly public?: TPublic;\n readonly internal?: TInternal;\n readonly dependencies?: readonly string[];\n onStart?(context: SyncoreComponentHookContext): Promise<void> | void;\n onStop?(context: SyncoreComponentHookContext): Promise<void> | void;\n}\n\nexport interface SyncoreComponentInstall<\n TComponent extends SyncoreComponent = SyncoreComponent,\n TChildren extends SyncoreComponentsManifest = SyncoreComponentsManifest\n> {\n readonly kind: \"syncore.component.install\";\n readonly component: TComponent;\n readonly source: string;\n readonly config?: TComponent extends SyncoreComponent<infer TConfig, any, any, any>\n ? TConfig\n : unknown;\n readonly capabilities?: readonly SyncoreRequestedCapability[];\n readonly bindings?: Record<string, string>;\n readonly children?: TChildren;\n}\n\nexport type SyncoreComponentsManifest = Record<string, SyncoreComponentInstall>;\n\nexport interface SyncoreComponentFunctionMetadata {\n componentPath: ComponentPath;\n componentName: string;\n version: string;\n visibility: \"public\" | \"internal\";\n localName: string;\n localTables: Record<string, string>;\n grantedCapabilities: readonly SyncoreRequestedCapability[];\n bindings: Record<string, string>;\n}\n\nexport interface ResolvedSyncoreComponent {\n alias: string;\n path: ComponentPath;\n source: string;\n name: string;\n version: string;\n config: unknown;\n grantedCapabilities: readonly SyncoreRequestedCapability[];\n requestedCapabilities: readonly SyncoreRequestedCapability[];\n bindings: Record<string, string>;\n schema: SyncoreDataModel | undefined;\n public: SyncoreFunctionTree | undefined;\n internal: SyncoreFunctionTree | undefined;\n publicEntries: Array<{\n localName: string;\n canonicalName: string;\n definition: RegisteredSyncoreFunction;\n }>;\n internalEntries: Array<{\n localName: string;\n canonicalName: string;\n definition: RegisteredSyncoreFunction;\n }>;\n localTables: Record<string, string>;\n onStart: SyncoreComponent[\"onStart\"] | undefined;\n onStop: SyncoreComponent[\"onStop\"] | undefined;\n children: ResolvedSyncoreComponent[];\n}\n\ntype Simplify<T> = { [K in keyof T]: T[K] } & {};\n\ntype PublicFunctionTreeOf<TComponent> = TComponent extends SyncoreComponent<\n any,\n any,\n infer TPublic,\n any\n>\n ? NonNullable<TPublic>\n : never;\n\nexport type FunctionReferencesForTree<TTree extends SyncoreFunctionTree> = Simplify<{\n [TKey in keyof TTree]: TTree[TKey] extends AnySyncoreFunctionDefinition\n ? FunctionReferenceFor<TTree[TKey]>\n : Record<string, unknown>;\n}>;\n\nexport type InstalledComponentApi<\n TInstall extends SyncoreComponentInstall\n> = Simplify<\n FunctionReferencesForTree<PublicFunctionTreeOf<TInstall[\"component\"]>> &\n Record<string, unknown>\n>;\n\nexport type InstalledComponentsApi<\n TManifest extends SyncoreComponentsManifest\n> = Simplify<{\n [TAlias in keyof TManifest]: InstalledComponentApi<TManifest[TAlias]>;\n}>;\n\ntype TablesOfSchema<TSchema extends SyncoreDataModel> = TSchema[\"tables\"];\n\nexport function defineComponent<\n TConfig = unknown,\n TSchema extends SyncoreDataModel | undefined =\n | SyncoreDataModel\n | undefined,\n TPublic extends SyncoreFunctionTree | undefined =\n | SyncoreFunctionTree\n | undefined,\n TInternal extends SyncoreFunctionTree | undefined =\n | SyncoreFunctionTree\n | undefined\n>(\n component: Omit<\n SyncoreComponent<TConfig, TSchema, TPublic, TInternal>,\n \"kind\"\n >\n): SyncoreComponent<TConfig, TSchema, TPublic, TInternal> {\n return {\n kind: \"syncore.component\",\n ...component\n };\n}\n\nexport function installComponent<\n TComponent extends SyncoreComponent,\n TChildren extends SyncoreComponentsManifest = {}\n>(install: {\n component: TComponent;\n source: string;\n config?: TComponent extends SyncoreComponent<infer TConfig, any, any, any>\n ? TConfig\n : unknown;\n capabilities?: readonly SyncoreRequestedCapability[];\n bindings?: Record<string, string>;\n children?: TChildren;\n}): SyncoreComponentInstall<TComponent, TChildren> {\n return {\n kind: \"syncore.component.install\",\n ...install\n };\n}\n\nexport function defineComponents<TManifest extends SyncoreComponentsManifest>(\n components: TManifest\n): TManifest {\n return components;\n}\n\nexport function createBindingFunctionReference<\n TKind extends SyncoreFunctionKind,\n TArgs = JsonObject,\n TResult = unknown\n>(\n kind: TKind,\n bindingName: string,\n functionName: string\n): FunctionReference<TKind, TArgs, TResult> {\n return {\n kind,\n name: `binding:${bindingName}/${functionName}`\n };\n}\n\nexport function composeProjectSchema<\n TRootSchema extends SyncoreDataModel\n>(\n rootSchema: TRootSchema,\n manifest?: SyncoreComponentsManifest\n): SyncoreSchema<TablesOfSchema<TRootSchema> & Record<string, AnyTableDefinition>> {\n const tables: Record<string, AnyTableDefinition> = {\n ...rootSchema.tables\n };\n\n for (const component of resolveComponentsManifest(manifest)) {\n for (const [physicalTableName, tableDefinition] of composeComponentTables(\n component\n )) {\n if (tables[physicalTableName]) {\n throw new Error(\n `Component table collision detected for ${JSON.stringify(physicalTableName)}.`\n );\n }\n tables[physicalTableName] = tableDefinition;\n }\n }\n\n return defineSchema(tables) as unknown as SyncoreSchema<\n TablesOfSchema<TRootSchema> & Record<string, AnyTableDefinition>\n >;\n}\n\nexport function composeProjectFunctionRegistry(\n rootFunctions: SyncoreFunctionRegistry,\n manifest?: SyncoreComponentsManifest\n): SyncoreFunctionRegistry {\n const registry: Record<string, RegisteredSyncoreFunction> = {};\n for (const [name, definition] of Object.entries(rootFunctions)) {\n if (definition) {\n registry[name] = definition;\n }\n }\n\n for (const component of resolveComponentsManifest(manifest)) {\n appendResolvedComponentFunctions(registry, component);\n }\n\n return registry;\n}\n\nexport function createInstalledComponentsApi<\n TManifest extends SyncoreComponentsManifest\n>(manifest: TManifest): InstalledComponentsApi<TManifest> {\n return createInstalledComponentsApiObject(resolveComponentsManifest(manifest)) as InstalledComponentsApi<TManifest>;\n}\n\nexport function resolveComponentsManifest(\n manifest?: SyncoreComponentsManifest\n): ResolvedSyncoreComponent[] {\n if (!manifest) {\n return [];\n }\n\n return Object.entries(manifest)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([alias, install]) => resolveInstalledComponent(alias, install, []));\n}\n\nexport function toCanonicalComponentFunctionName(\n componentPath: ComponentPath,\n visibility: \"public\" | \"internal\",\n localName: string\n): string {\n return [\"components\", componentPath, visibility, localName]\n .filter(Boolean)\n .join(\"/\");\n}\n\nexport function createComponentPhysicalTableName(\n componentPath: ComponentPath,\n tableName: string\n): string {\n const pathPart = sanitizeComponentPath(componentPath);\n return `__syncore_component__${pathPart}__${tableName}`;\n}\n\nfunction resolveInstalledComponent(\n alias: string,\n install: SyncoreComponentInstall,\n parentPath: string[]\n): ResolvedSyncoreComponent {\n const pathSegments = [...parentPath, alias];\n const componentPath = pathSegments.join(\"/\");\n const component = install.component;\n const requestedCapabilities = [\n ...(component.requestedCapabilities ?? [])\n ];\n const localTables = createLocalTableMap(componentPath, component.schema);\n const defaultCapabilities = new Set<SyncoreRequestedCapability>(\n component.schema ? [\"ownTables\"] : []\n );\n if (component.public) {\n defaultCapabilities.add(\"publicExports\");\n }\n if (component.internal) {\n defaultCapabilities.add(\"internalActions\");\n }\n const grantedCapabilities = Array.from(\n new Set([\n ...defaultCapabilities,\n ...(install.capabilities ?? requestedCapabilities)\n ])\n );\n\n for (const capability of requestedCapabilities) {\n if (!grantedCapabilities.includes(capability)) {\n throw new Error(\n `Component ${JSON.stringify(component.name)} at ${JSON.stringify(componentPath)} requested capability ${JSON.stringify(capability)} but it was not granted.`\n );\n }\n }\n\n if (component.config) {\n component.config.parse(install.config);\n }\n\n const bindings = { ...(install.bindings ?? {}) };\n for (const dependency of component.dependencies ?? []) {\n if (!bindings[dependency]) {\n throw new Error(\n `Component ${JSON.stringify(component.name)} at ${JSON.stringify(componentPath)} requires binding ${JSON.stringify(dependency)}.`\n );\n }\n }\n\n const children = Object.entries(install.children ?? {})\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([childAlias, childInstall]) =>\n resolveInstalledComponent(childAlias, childInstall, pathSegments)\n );\n\n return {\n alias,\n path: componentPath,\n source: install.source,\n name: component.name,\n version: component.version,\n config: install.config,\n grantedCapabilities,\n requestedCapabilities,\n bindings,\n schema: component.schema,\n public: component.public,\n internal: component.internal,\n publicEntries: flattenComponentFunctionTree(\n component.public,\n componentPath,\n component.name,\n component.version,\n \"public\",\n localTables,\n grantedCapabilities,\n bindings\n ),\n internalEntries: flattenComponentFunctionTree(\n component.internal,\n componentPath,\n component.name,\n component.version,\n \"internal\",\n localTables,\n grantedCapabilities,\n bindings\n ),\n localTables,\n onStart: component.onStart,\n onStop: component.onStop,\n children\n };\n}\n\nfunction createLocalTableMap(\n componentPath: string,\n schema?: SyncoreDataModel\n): Record<string, string> {\n if (!schema) {\n return {};\n }\n return Object.fromEntries(\n schema.tableNames().map((tableName) => [\n tableName,\n createComponentPhysicalTableName(componentPath, tableName)\n ])\n );\n}\n\nfunction composeComponentTables(\n component: ResolvedSyncoreComponent\n): Array<[string, AnyTableDefinition]> {\n const entries: Array<[string, AnyTableDefinition]> = [];\n if (component.schema) {\n for (const localTableName of component.schema.tableNames()) {\n const original = component.schema.getTable(localTableName);\n const cloned = new TableDefinition(original.validator, {\n ...original.options,\n tableName: localTableName,\n componentPath: component.path,\n componentName: component.name\n });\n for (const index of original.indexes) {\n if (index.fields.length > 0) {\n cloned.index(index.name, [...index.fields] as [string, ...string[]]);\n }\n }\n for (const index of original.searchIndexes) {\n cloned.searchIndex(index.name, {\n searchField: index.searchField,\n filterFields: [...index.filterFields]\n });\n }\n entries.push([component.localTables[localTableName]!, cloned]);\n }\n }\n for (const child of component.children) {\n entries.push(...composeComponentTables(child));\n }\n return entries;\n}\n\nfunction appendResolvedComponentFunctions(\n registry: Record<string, RegisteredSyncoreFunction>,\n component: ResolvedSyncoreComponent\n): void {\n for (const entry of component.publicEntries) {\n registry[entry.canonicalName] = entry.definition;\n }\n for (const entry of component.internalEntries) {\n registry[entry.canonicalName] = entry.definition;\n }\n for (const child of component.children) {\n appendResolvedComponentFunctions(registry, child);\n }\n}\n\nfunction flattenComponentFunctionTree(\n tree: SyncoreFunctionTree | undefined,\n componentPath: string,\n componentName: string,\n version: string,\n visibility: \"public\" | \"internal\",\n localTables: Record<string, string>,\n grantedCapabilities: readonly SyncoreRequestedCapability[],\n bindings: Record<string, string>,\n prefix: string[] = []\n): Array<{\n localName: string;\n canonicalName: string;\n definition: RegisteredSyncoreFunction;\n}> {\n if (!tree) {\n return [];\n }\n\n const entries: Array<{\n localName: string;\n canonicalName: string;\n definition: RegisteredSyncoreFunction;\n }> = [];\n\n for (const [key, value] of Object.entries(tree).sort(([left], [right]) =>\n left.localeCompare(right)\n )) {\n if (!value) {\n continue;\n }\n if (isFunctionDefinition(value)) {\n const localName = [...prefix, key].join(\"/\");\n entries.push({\n localName,\n canonicalName: toCanonicalComponentFunctionName(\n componentPath,\n visibility,\n localName\n ),\n definition: decorateComponentFunctionDefinition(value, {\n componentPath,\n componentName,\n version,\n visibility,\n localName,\n localTables,\n grantedCapabilities,\n bindings\n })\n });\n continue;\n }\n entries.push(\n ...flattenComponentFunctionTree(\n value,\n componentPath,\n componentName,\n version,\n visibility,\n localTables,\n grantedCapabilities,\n bindings,\n [...prefix, key]\n )\n );\n }\n\n return entries;\n}\n\nfunction decorateComponentFunctionDefinition(\n definition: AnySyncoreFunctionDefinition,\n metadata: SyncoreComponentFunctionMetadata\n): RegisteredSyncoreFunction {\n return {\n ...definition,\n __syncoreComponent: metadata\n } as RegisteredSyncoreFunction;\n}\n\nfunction createInstalledComponentsApiObject(\n components: ResolvedSyncoreComponent[]\n): Record<string, unknown> {\n return Object.fromEntries(\n components.map((component) => [\n component.alias,\n createInstalledComponentApiNode(component)\n ])\n );\n}\n\nfunction createInstalledComponentApiNode(\n component: ResolvedSyncoreComponent\n): Record<string, unknown> {\n const node: Record<string, unknown> = {};\n for (const entry of component.publicEntries) {\n assignFunctionReference(\n node,\n entry.localName.split(\"/\"),\n {\n kind: entry.definition.kind,\n name: entry.canonicalName\n }\n );\n }\n for (const child of component.children) {\n node[child.alias] = createInstalledComponentApiNode(child);\n }\n return node;\n}\n\nfunction assignFunctionReference(\n node: Record<string, unknown>,\n pathParts: string[],\n reference: FunctionReference\n): void {\n const [head, ...tail] = pathParts;\n if (!head) {\n return;\n }\n if (tail.length === 0) {\n node[head] = reference;\n return;\n }\n const child =\n node[head] && typeof node[head] === \"object\"\n ? (node[head] as Record<string, unknown>)\n : {};\n node[head] = child;\n assignFunctionReference(child, tail, reference);\n}\n\nfunction isFunctionDefinition(value: unknown): value is AnySyncoreFunctionDefinition {\n return (\n Boolean(value) &&\n typeof value === \"object\" &&\n \"kind\" in (value as Record<string, unknown>) &&\n \"argsValidator\" in (value as Record<string, unknown>) &&\n \"handler\" in (value as Record<string, unknown>)\n );\n}\n\nfunction sanitizeComponentPath(componentPath: string): string {\n return componentPath.replace(/[^a-zA-Z0-9_]+/g, \"_\");\n}\n"],"mappings":";;AAsLA,SAAgB,gBAYd,WAIwD;AACxD,QAAO;EACL,MAAM;EACN,GAAG;EACJ;;AAGH,SAAgB,iBAGd,SASiD;AACjD,QAAO;EACL,MAAM;EACN,GAAG;EACJ;;AAGH,SAAgB,iBACd,YACW;AACX,QAAO;;AAGT,SAAgB,+BAKd,MACA,aACA,cAC0C;AAC1C,QAAO;EACL;EACA,MAAM,WAAW,YAAY,GAAG;EACjC;;AAGH,SAAgB,qBAGd,YACA,UACiF;CACjF,MAAM,SAA6C,EACjD,GAAG,WAAW,QACf;AAED,MAAK,MAAM,aAAa,0BAA0B,SAAS,CACzD,MAAK,MAAM,CAAC,mBAAmB,oBAAoB,uBACjD,UACD,EAAE;AACD,MAAI,OAAO,mBACT,OAAM,IAAI,MACR,0CAA0C,KAAK,UAAU,kBAAkB,CAAC,GAC7E;AAEH,SAAO,qBAAqB;;AAIhC,QAAO,aAAa,OAAO;;AAK7B,SAAgB,+BACd,eACA,UACyB;CACzB,MAAM,WAAsD,EAAE;AAC9D,MAAK,MAAM,CAAC,MAAM,eAAe,OAAO,QAAQ,cAAc,CAC5D,KAAI,WACF,UAAS,QAAQ;AAIrB,MAAK,MAAM,aAAa,0BAA0B,SAAS,CACzD,kCAAiC,UAAU,UAAU;AAGvD,QAAO;;AAGT,SAAgB,6BAEd,UAAwD;AACxD,QAAO,mCAAmC,0BAA0B,SAAS,CAAC;;AAGhF,SAAgB,0BACd,UAC4B;AAC5B,KAAI,CAAC,SACH,QAAO,EAAE;AAGX,QAAO,OAAO,QAAQ,SAAS,CAC5B,MAAM,CAAC,OAAO,CAAC,WAAW,KAAK,cAAc,MAAM,CAAC,CACpD,KAAK,CAAC,OAAO,aAAa,0BAA0B,OAAO,SAAS,EAAE,CAAC,CAAC;;AAG7E,SAAgB,iCACd,eACA,YACA,WACQ;AACR,QAAO;EAAC;EAAc;EAAe;EAAY;EAAU,CACxD,OAAO,QAAQ,CACf,KAAK,IAAI;;AAGd,SAAgB,iCACd,eACA,WACQ;AAER,QAAO,wBADU,sBAAsB,cAAc,CACb,IAAI;;AAG9C,SAAS,0BACP,OACA,SACA,YAC0B;CAC1B,MAAM,eAAe,CAAC,GAAG,YAAY,MAAM;CAC3C,MAAM,gBAAgB,aAAa,KAAK,IAAI;CAC5C,MAAM,YAAY,QAAQ;CAC1B,MAAM,wBAAwB,CAC5B,GAAI,UAAU,yBAAyB,EAAE,CAC1C;CACD,MAAM,cAAc,oBAAoB,eAAe,UAAU,OAAO;CACxE,MAAM,sBAAsB,IAAI,IAC9B,UAAU,SAAS,CAAC,YAAY,GAAG,EAAE,CACtC;AACD,KAAI,UAAU,OACZ,qBAAoB,IAAI,gBAAgB;AAE1C,KAAI,UAAU,SACZ,qBAAoB,IAAI,kBAAkB;CAE5C,MAAM,sBAAsB,MAAM,KAChC,IAAI,IAAI,CACN,GAAG,qBACH,GAAI,QAAQ,gBAAgB,sBAC7B,CAAC,CACH;AAED,MAAK,MAAM,cAAc,sBACvB,KAAI,CAAC,oBAAoB,SAAS,WAAW,CAC3C,OAAM,IAAI,MACR,aAAa,KAAK,UAAU,UAAU,KAAK,CAAC,MAAM,KAAK,UAAU,cAAc,CAAC,wBAAwB,KAAK,UAAU,WAAW,CAAC,0BACpI;AAIL,KAAI,UAAU,OACZ,WAAU,OAAO,MAAM,QAAQ,OAAO;CAGxC,MAAM,WAAW,EAAE,GAAI,QAAQ,YAAY,EAAE,EAAG;AAChD,MAAK,MAAM,cAAc,UAAU,gBAAgB,EAAE,CACnD,KAAI,CAAC,SAAS,YACZ,OAAM,IAAI,MACR,aAAa,KAAK,UAAU,UAAU,KAAK,CAAC,MAAM,KAAK,UAAU,cAAc,CAAC,oBAAoB,KAAK,UAAU,WAAW,CAAC,GAChI;CAIL,MAAM,WAAW,OAAO,QAAQ,QAAQ,YAAY,EAAE,CAAC,CACpD,MAAM,CAAC,OAAO,CAAC,WAAW,KAAK,cAAc,MAAM,CAAC,CACpD,KAAK,CAAC,YAAY,kBACjB,0BAA0B,YAAY,cAAc,aAAa,CAClE;AAEH,QAAO;EACL;EACA,MAAM;EACN,QAAQ,QAAQ;EAChB,MAAM,UAAU;EAChB,SAAS,UAAU;EACnB,QAAQ,QAAQ;EAChB;EACA;EACA;EACA,QAAQ,UAAU;EAClB,QAAQ,UAAU;EAClB,UAAU,UAAU;EACpB,eAAe,6BACb,UAAU,QACV,eACA,UAAU,MACV,UAAU,SACV,UACA,aACA,qBACA,SACD;EACD,iBAAiB,6BACf,UAAU,UACV,eACA,UAAU,MACV,UAAU,SACV,YACA,aACA,qBACA,SACD;EACD;EACA,SAAS,UAAU;EACnB,QAAQ,UAAU;EAClB;EACD;;AAGH,SAAS,oBACP,eACA,QACwB;AACxB,KAAI,CAAC,OACH,QAAO,EAAE;AAEX,QAAO,OAAO,YACZ,OAAO,YAAY,CAAC,KAAK,cAAc,CACrC,WACA,iCAAiC,eAAe,UAAU,CAC3D,CAAC,CACH;;AAGH,SAAS,uBACP,WACqC;CACrC,MAAM,UAA+C,EAAE;AACvD,KAAI,UAAU,OACZ,MAAK,MAAM,kBAAkB,UAAU,OAAO,YAAY,EAAE;EAC1D,MAAM,WAAW,UAAU,OAAO,SAAS,eAAe;EAC1D,MAAM,SAAS,IAAI,gBAAgB,SAAS,WAAW;GACrD,GAAG,SAAS;GACZ,WAAW;GACX,eAAe,UAAU;GACzB,eAAe,UAAU;GAC1B,CAAC;AACF,OAAK,MAAM,SAAS,SAAS,QAC3B,KAAI,MAAM,OAAO,SAAS,EACxB,QAAO,MAAM,MAAM,MAAM,CAAC,GAAG,MAAM,OAAO,CAA0B;AAGxE,OAAK,MAAM,SAAS,SAAS,cAC3B,QAAO,YAAY,MAAM,MAAM;GAC7B,aAAa,MAAM;GACnB,cAAc,CAAC,GAAG,MAAM,aAAa;GACtC,CAAC;AAEJ,UAAQ,KAAK,CAAC,UAAU,YAAY,iBAAkB,OAAO,CAAC;;AAGlE,MAAK,MAAM,SAAS,UAAU,SAC5B,SAAQ,KAAK,GAAG,uBAAuB,MAAM,CAAC;AAEhD,QAAO;;AAGT,SAAS,iCACP,UACA,WACM;AACN,MAAK,MAAM,SAAS,UAAU,cAC5B,UAAS,MAAM,iBAAiB,MAAM;AAExC,MAAK,MAAM,SAAS,UAAU,gBAC5B,UAAS,MAAM,iBAAiB,MAAM;AAExC,MAAK,MAAM,SAAS,UAAU,SAC5B,kCAAiC,UAAU,MAAM;;AAIrD,SAAS,6BACP,MACA,eACA,eACA,SACA,YACA,aACA,qBACA,UACA,SAAmB,EAAE,EAKpB;AACD,KAAI,CAAC,KACH,QAAO,EAAE;CAGX,MAAM,UAID,EAAE;AAEP,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,WAC7D,KAAK,cAAc,MAAM,CAC1B,EAAE;AACD,MAAI,CAAC,MACH;AAEF,MAAI,qBAAqB,MAAM,EAAE;GAC/B,MAAM,YAAY,CAAC,GAAG,QAAQ,IAAI,CAAC,KAAK,IAAI;AAC5C,WAAQ,KAAK;IACX;IACA,eAAe,iCACb,eACA,YACA,UACD;IACD,YAAY,oCAAoC,OAAO;KACrD;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACD,CAAC;IACH,CAAC;AACF;;AAEF,UAAQ,KACN,GAAG,6BACD,OACA,eACA,eACA,SACA,YACA,aACA,qBACA,UACA,CAAC,GAAG,QAAQ,IAAI,CACjB,CACF;;AAGH,QAAO;;AAGT,SAAS,oCACP,YACA,UAC2B;AAC3B,QAAO;EACL,GAAG;EACH,oBAAoB;EACrB;;AAGH,SAAS,mCACP,YACyB;AACzB,QAAO,OAAO,YACZ,WAAW,KAAK,cAAc,CAC5B,UAAU,OACV,gCAAgC,UAAU,CAC3C,CAAC,CACH;;AAGH,SAAS,gCACP,WACyB;CACzB,MAAM,OAAgC,EAAE;AACxC,MAAK,MAAM,SAAS,UAAU,cAC5B,yBACE,MACA,MAAM,UAAU,MAAM,IAAI,EAC1B;EACE,MAAM,MAAM,WAAW;EACvB,MAAM,MAAM;EACb,CACF;AAEH,MAAK,MAAM,SAAS,UAAU,SAC5B,MAAK,MAAM,SAAS,gCAAgC,MAAM;AAE5D,QAAO;;AAGT,SAAS,wBACP,MACA,WACA,WACM;CACN,MAAM,CAAC,MAAM,GAAG,QAAQ;AACxB,KAAI,CAAC,KACH;AAEF,KAAI,KAAK,WAAW,GAAG;AACrB,OAAK,QAAQ;AACb;;CAEF,MAAM,QACJ,KAAK,SAAS,OAAO,KAAK,UAAU,WAC/B,KAAK,QACN,EAAE;AACR,MAAK,QAAQ;AACb,yBAAwB,OAAO,MAAM,UAAU;;AAGjD,SAAS,qBAAqB,OAAuD;AACnF,QACE,QAAQ,MAAM,IACd,OAAO,UAAU,YACjB,UAAW,SACX,mBAAoB,SACpB,aAAc;;AAIlB,SAAS,sBAAsB,eAA+B;AAC5D,QAAO,cAAc,QAAQ,mBAAmB,IAAI"}
|
|
1
|
+
{"version":3,"file":"components.mjs","names":[],"sources":["../../src/runtime/components.ts"],"sourcesContent":["import {\n SyncoreSchema,\n TableDefinition,\n defineSchema,\n type AnyTableDefinition,\n type Validator\n} from \"@syncore/schema\";\nimport type { SyncoreDevtoolsEvent } from \"@syncore/devtools-protocol\";\nimport {\n type FunctionReference,\n type FunctionReferenceFor,\n type SyncoreFunctionDefinition,\n type SyncoreFunctionKind\n} from \"./functions.js\";\nimport type {\n JsonObject,\n RegisteredSyncoreFunction,\n SyncoreDataModel,\n SyncoreFunctionRegistry\n} from \"./runtime.js\";\n\nexport type ComponentPath = string;\n\nexport type SyncoreCoreCapability =\n | \"storage\"\n | \"scheduler\"\n | \"devtools\"\n | \"ownTables\"\n | \"publicExports\"\n | \"internalActions\";\n\nexport type SyncoreHostServiceName =\n | \"http\"\n | \"notifications\"\n | \"secureStore\"\n | \"filesystem\"\n | \"backgroundTasks\"\n | \"crypto\";\n\nexport type SyncoreRequestedCapability =\n | SyncoreCoreCapability\n | `host:${SyncoreHostServiceName}`;\n\nexport type AnySyncoreFunctionDefinition = SyncoreFunctionDefinition<\n SyncoreFunctionKind,\n any,\n any,\n unknown\n>;\n\nexport type SyncoreFunctionTree = {\n readonly [key: string]:\n | AnySyncoreFunctionDefinition\n | SyncoreFunctionTree\n | undefined;\n};\n\nexport interface SyncoreComponentHookContext {\n runtimeId: string;\n platform: string;\n componentPath: ComponentPath;\n componentName: string;\n version: string;\n config: unknown;\n capabilities: readonly SyncoreRequestedCapability[];\n emitDevtools(event: SyncoreDevtoolsEvent): void;\n}\n\nexport interface SyncoreComponent<\n TConfig = unknown,\n TSchema extends SyncoreDataModel | undefined =\n | SyncoreDataModel\n | undefined,\n TPublic extends SyncoreFunctionTree | undefined =\n | SyncoreFunctionTree\n | undefined,\n TInternal extends SyncoreFunctionTree | undefined =\n | SyncoreFunctionTree\n | undefined\n> {\n readonly kind: \"syncore.component\";\n readonly name: string;\n readonly version: string;\n readonly config?: Validator<TConfig>;\n readonly requestedCapabilities?: readonly SyncoreRequestedCapability[];\n readonly schema?: TSchema;\n readonly public?: TPublic;\n readonly internal?: TInternal;\n readonly dependencies?: readonly string[];\n onStart?(context: SyncoreComponentHookContext): Promise<void> | void;\n onStop?(context: SyncoreComponentHookContext): Promise<void> | void;\n}\n\nexport interface SyncoreComponentInstall<\n TComponent extends SyncoreComponent = SyncoreComponent,\n TChildren extends SyncoreComponentsManifest = SyncoreComponentsManifest\n> {\n readonly kind: \"syncore.component.install\";\n readonly component: TComponent;\n readonly source: string;\n readonly config?: TComponent extends SyncoreComponent<infer TConfig, any, any, any>\n ? TConfig\n : unknown;\n readonly capabilities?: readonly SyncoreRequestedCapability[];\n readonly bindings?: Record<string, string>;\n readonly children?: TChildren;\n}\n\nexport type SyncoreComponentsManifest = Record<string, SyncoreComponentInstall>;\n\nexport interface SyncoreComponentFunctionMetadata {\n componentPath: ComponentPath;\n componentName: string;\n version: string;\n visibility: \"public\" | \"internal\";\n localName: string;\n localTables: Record<string, string>;\n grantedCapabilities: readonly SyncoreRequestedCapability[];\n bindings: Record<string, string>;\n}\n\nexport interface ResolvedSyncoreComponent {\n alias: string;\n path: ComponentPath;\n source: string;\n name: string;\n version: string;\n config: unknown;\n grantedCapabilities: readonly SyncoreRequestedCapability[];\n requestedCapabilities: readonly SyncoreRequestedCapability[];\n bindings: Record<string, string>;\n schema: SyncoreDataModel | undefined;\n public: SyncoreFunctionTree | undefined;\n internal: SyncoreFunctionTree | undefined;\n publicEntries: Array<{\n localName: string;\n canonicalName: string;\n definition: RegisteredSyncoreFunction;\n }>;\n internalEntries: Array<{\n localName: string;\n canonicalName: string;\n definition: RegisteredSyncoreFunction;\n }>;\n localTables: Record<string, string>;\n onStart: SyncoreComponent[\"onStart\"] | undefined;\n onStop: SyncoreComponent[\"onStop\"] | undefined;\n children: ResolvedSyncoreComponent[];\n}\n\ntype Simplify<T> = { [K in keyof T]: T[K] } & {};\n\ntype PublicFunctionTreeOf<TComponent> = TComponent extends SyncoreComponent<\n any,\n any,\n infer TPublic,\n any\n>\n ? NonNullable<TPublic>\n : never;\n\nexport type FunctionReferencesForTree<TTree extends SyncoreFunctionTree> = Simplify<{\n [TKey in keyof TTree]: TTree[TKey] extends AnySyncoreFunctionDefinition\n ? FunctionReferenceFor<TTree[TKey]>\n : Record<string, unknown>;\n}>;\n\nexport type InstalledComponentApi<\n TInstall extends SyncoreComponentInstall\n> = Simplify<\n FunctionReferencesForTree<PublicFunctionTreeOf<TInstall[\"component\"]>> &\n Record<string, unknown>\n>;\n\nexport type InstalledComponentsApi<\n TManifest extends SyncoreComponentsManifest\n> = Simplify<{\n [TAlias in keyof TManifest]: InstalledComponentApi<TManifest[TAlias]>;\n}>;\n\ntype TablesOfSchema<TSchema extends SyncoreDataModel> = TSchema[\"tables\"];\n\nexport function defineComponent<\n TConfig = unknown,\n TSchema extends SyncoreDataModel | undefined =\n | SyncoreDataModel\n | undefined,\n TPublic extends SyncoreFunctionTree | undefined =\n | SyncoreFunctionTree\n | undefined,\n TInternal extends SyncoreFunctionTree | undefined =\n | SyncoreFunctionTree\n | undefined\n>(\n component: Omit<\n SyncoreComponent<TConfig, TSchema, TPublic, TInternal>,\n \"kind\"\n >\n): SyncoreComponent<TConfig, TSchema, TPublic, TInternal> {\n return {\n kind: \"syncore.component\",\n ...component\n };\n}\n\nexport function installComponent<\n TComponent extends SyncoreComponent,\n TChildren extends SyncoreComponentsManifest = {}\n>(install: {\n component: TComponent;\n source: string;\n config?: TComponent extends SyncoreComponent<infer TConfig, any, any, any>\n ? TConfig\n : unknown;\n capabilities?: readonly SyncoreRequestedCapability[];\n bindings?: Record<string, string>;\n children?: TChildren;\n}): SyncoreComponentInstall<TComponent, TChildren> {\n return {\n kind: \"syncore.component.install\",\n ...install\n };\n}\n\nexport function defineComponents<TManifest extends SyncoreComponentsManifest>(\n components: TManifest\n): TManifest {\n return components;\n}\n\nexport function createBindingFunctionReference<\n TKind extends SyncoreFunctionKind,\n TArgs = JsonObject,\n TResult = unknown\n>(\n kind: TKind,\n bindingName: string,\n functionName: string\n): FunctionReference<TKind, TArgs, TResult> {\n return {\n kind,\n name: `binding:${bindingName}/${functionName}`\n };\n}\n\nexport function composeProjectSchema<\n TRootSchema extends SyncoreDataModel\n>(\n rootSchema: TRootSchema,\n manifest?: SyncoreComponentsManifest\n): SyncoreSchema<TablesOfSchema<TRootSchema> & Record<string, AnyTableDefinition>> {\n const tables: Record<string, AnyTableDefinition> = {\n ...rootSchema.tables\n };\n\n for (const component of resolveComponentsManifest(manifest)) {\n for (const [physicalTableName, tableDefinition] of composeComponentTables(\n component\n )) {\n if (tables[physicalTableName]) {\n throw new Error(\n `Component table collision detected for ${JSON.stringify(physicalTableName)}.`\n );\n }\n tables[physicalTableName] = tableDefinition;\n }\n }\n\n return defineSchema(tables) as unknown as SyncoreSchema<\n TablesOfSchema<TRootSchema> & Record<string, AnyTableDefinition>\n >;\n}\n\nexport function composeProjectFunctionRegistry(\n rootFunctions: SyncoreFunctionRegistry,\n manifest?: SyncoreComponentsManifest\n): SyncoreFunctionRegistry {\n const registry: Record<string, RegisteredSyncoreFunction> = {};\n for (const [name, definition] of Object.entries(rootFunctions)) {\n if (definition) {\n registry[name] = definition;\n }\n }\n\n for (const component of resolveComponentsManifest(manifest)) {\n appendResolvedComponentFunctions(registry, component);\n }\n\n return registry;\n}\n\nexport function createInstalledComponentsApi<\n TManifest extends SyncoreComponentsManifest\n>(manifest: TManifest): InstalledComponentsApi<TManifest> {\n return createInstalledComponentsApiObject(resolveComponentsManifest(manifest)) as InstalledComponentsApi<TManifest>;\n}\n\nexport function resolveComponentsManifest(\n manifest?: SyncoreComponentsManifest\n): ResolvedSyncoreComponent[] {\n if (!manifest) {\n return [];\n }\n\n return Object.entries(manifest)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([alias, install]) => resolveInstalledComponent(alias, install, []));\n}\n\nexport function toCanonicalComponentFunctionName(\n componentPath: ComponentPath,\n visibility: \"public\" | \"internal\",\n localName: string\n): string {\n return [\"components\", componentPath, visibility, localName]\n .filter(Boolean)\n .join(\"/\");\n}\n\nexport function createComponentPhysicalTableName(\n componentPath: ComponentPath,\n tableName: string\n): string {\n const pathPart = sanitizeComponentPath(componentPath);\n return `__syncore_component__${pathPart}__${tableName}`;\n}\n\nfunction resolveInstalledComponent(\n alias: string,\n install: SyncoreComponentInstall,\n parentPath: string[]\n): ResolvedSyncoreComponent {\n const pathSegments = [...parentPath, alias];\n const componentPath = pathSegments.join(\"/\");\n const component = install.component;\n const requestedCapabilities = [\n ...(component.requestedCapabilities ?? [])\n ];\n const localTables = createLocalTableMap(componentPath, component.schema);\n const defaultCapabilities = new Set<SyncoreRequestedCapability>(\n component.schema ? [\"ownTables\"] : []\n );\n if (component.public) {\n defaultCapabilities.add(\"publicExports\");\n }\n if (component.internal) {\n defaultCapabilities.add(\"internalActions\");\n }\n const grantedCapabilities = Array.from(\n new Set([\n ...defaultCapabilities,\n ...(install.capabilities ?? requestedCapabilities)\n ])\n );\n\n for (const capability of requestedCapabilities) {\n if (!grantedCapabilities.includes(capability)) {\n throw new Error(\n `Component ${JSON.stringify(component.name)} at ${JSON.stringify(componentPath)} requested capability ${JSON.stringify(capability)} but it was not granted.`\n );\n }\n }\n\n if (component.config) {\n component.config.parse(install.config);\n }\n\n const bindings = { ...(install.bindings ?? {}) };\n for (const dependency of component.dependencies ?? []) {\n if (!bindings[dependency]) {\n throw new Error(\n `Component ${JSON.stringify(component.name)} at ${JSON.stringify(componentPath)} requires binding ${JSON.stringify(dependency)}.`\n );\n }\n }\n\n const children = Object.entries(install.children ?? {})\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([childAlias, childInstall]) =>\n resolveInstalledComponent(childAlias, childInstall, pathSegments)\n );\n\n return {\n alias,\n path: componentPath,\n source: install.source,\n name: component.name,\n version: component.version,\n config: install.config,\n grantedCapabilities,\n requestedCapabilities,\n bindings,\n schema: component.schema,\n public: component.public,\n internal: component.internal,\n publicEntries: flattenComponentFunctionTree(\n component.public,\n componentPath,\n component.name,\n component.version,\n \"public\",\n localTables,\n grantedCapabilities,\n bindings\n ),\n internalEntries: flattenComponentFunctionTree(\n component.internal,\n componentPath,\n component.name,\n component.version,\n \"internal\",\n localTables,\n grantedCapabilities,\n bindings\n ),\n localTables,\n onStart: component.onStart,\n onStop: component.onStop,\n children\n };\n}\n\nfunction createLocalTableMap(\n componentPath: string,\n schema?: SyncoreDataModel\n): Record<string, string> {\n if (!schema) {\n return {};\n }\n return Object.fromEntries(\n schema.tableNames().map((tableName) => [\n tableName,\n createComponentPhysicalTableName(componentPath, tableName)\n ])\n );\n}\n\nfunction composeComponentTables(\n component: ResolvedSyncoreComponent\n): Array<[string, AnyTableDefinition]> {\n const entries: Array<[string, AnyTableDefinition]> = [];\n if (component.schema) {\n for (const localTableName of component.schema.tableNames()) {\n const original = component.schema.getTable(localTableName);\n const cloned = new TableDefinition(original.validator, {\n ...original.options,\n tableName: localTableName,\n componentPath: component.path,\n componentName: component.name\n });\n for (const index of original.indexes) {\n if (index.fields.length > 0) {\n cloned.index(index.name, [...index.fields] as [string, ...string[]]);\n }\n }\n for (const index of original.searchIndexes) {\n cloned.searchIndex(index.name, {\n searchField: index.searchField,\n filterFields: [...index.filterFields]\n });\n }\n entries.push([component.localTables[localTableName]!, cloned]);\n }\n }\n for (const child of component.children) {\n entries.push(...composeComponentTables(child));\n }\n return entries;\n}\n\nfunction appendResolvedComponentFunctions(\n registry: Record<string, RegisteredSyncoreFunction>,\n component: ResolvedSyncoreComponent\n): void {\n for (const entry of component.publicEntries) {\n registry[entry.canonicalName] = entry.definition;\n }\n for (const entry of component.internalEntries) {\n registry[entry.canonicalName] = entry.definition;\n }\n for (const child of component.children) {\n appendResolvedComponentFunctions(registry, child);\n }\n}\n\nfunction flattenComponentFunctionTree(\n tree: SyncoreFunctionTree | undefined,\n componentPath: string,\n componentName: string,\n version: string,\n visibility: \"public\" | \"internal\",\n localTables: Record<string, string>,\n grantedCapabilities: readonly SyncoreRequestedCapability[],\n bindings: Record<string, string>,\n prefix: string[] = []\n): Array<{\n localName: string;\n canonicalName: string;\n definition: RegisteredSyncoreFunction;\n}> {\n if (!tree) {\n return [];\n }\n\n const entries: Array<{\n localName: string;\n canonicalName: string;\n definition: RegisteredSyncoreFunction;\n }> = [];\n\n for (const [key, value] of Object.entries(tree).sort(([left], [right]) =>\n left.localeCompare(right)\n )) {\n if (!value) {\n continue;\n }\n if (isFunctionDefinition(value)) {\n const localName = [...prefix, key].join(\"/\");\n entries.push({\n localName,\n canonicalName: toCanonicalComponentFunctionName(\n componentPath,\n visibility,\n localName\n ),\n definition: decorateComponentFunctionDefinition(value, {\n componentPath,\n componentName,\n version,\n visibility,\n localName,\n localTables,\n grantedCapabilities,\n bindings\n })\n });\n continue;\n }\n entries.push(\n ...flattenComponentFunctionTree(\n value,\n componentPath,\n componentName,\n version,\n visibility,\n localTables,\n grantedCapabilities,\n bindings,\n [...prefix, key]\n )\n );\n }\n\n return entries;\n}\n\nfunction decorateComponentFunctionDefinition(\n definition: AnySyncoreFunctionDefinition,\n metadata: SyncoreComponentFunctionMetadata\n): RegisteredSyncoreFunction {\n return {\n ...definition,\n __syncoreComponent: metadata\n } as RegisteredSyncoreFunction;\n}\n\nfunction createInstalledComponentsApiObject(\n components: ResolvedSyncoreComponent[]\n): Record<string, unknown> {\n return Object.fromEntries(\n components.map((component) => [\n component.alias,\n createInstalledComponentApiNode(component)\n ])\n );\n}\n\nfunction createInstalledComponentApiNode(\n component: ResolvedSyncoreComponent\n): Record<string, unknown> {\n const node: Record<string, unknown> = {};\n for (const entry of component.publicEntries) {\n assignFunctionReference(\n node,\n entry.localName.split(\"/\"),\n {\n kind: entry.definition.kind,\n name: entry.canonicalName\n }\n );\n }\n for (const child of component.children) {\n node[child.alias] = createInstalledComponentApiNode(child);\n }\n return node;\n}\n\nfunction assignFunctionReference(\n node: Record<string, unknown>,\n pathParts: string[],\n reference: FunctionReference\n): void {\n const [head, ...tail] = pathParts;\n if (!head) {\n return;\n }\n if (tail.length === 0) {\n node[head] = reference;\n return;\n }\n const child =\n node[head] && typeof node[head] === \"object\"\n ? (node[head] as Record<string, unknown>)\n : {};\n node[head] = child;\n assignFunctionReference(child, tail, reference);\n}\n\nfunction isFunctionDefinition(value: unknown): value is AnySyncoreFunctionDefinition {\n return (\n Boolean(value) &&\n typeof value === \"object\" &&\n \"kind\" in (value as Record<string, unknown>) &&\n \"argsValidator\" in (value as Record<string, unknown>) &&\n \"handler\" in (value as Record<string, unknown>)\n );\n}\n\nfunction sanitizeComponentPath(componentPath: string): string {\n return componentPath.replace(/[^a-zA-Z0-9_]+/g, \"_\");\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devtools.d.mts","names":[],"sources":["../../src/runtime/devtools.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"devtools.d.mts","names":[],"sources":["../../src/runtime/devtools.ts"],"mappings":";;;;UA+BiB,0BAAA;EACf,MAAA,EAAQ,gBAAA;EACR,MAAA,EAAQ,gBAAA;EACR,SAAA,EAAW,qBAAA,CAAsB,gBAAA;EACjC,KAAA,EAAO,mBAAA,CAAoB,gBAAA;EAC3B,GAAA,GAAM,kBAAA;AAAA;AAAA,KAGI,eAAA;AAAA,UAEK,mBAAA;EACf,IAAA,EAAM,eAAA;EACN,UAAA;EACA,WAAA;EACA,aAAA;EACA,cAAA,EAAgB,sBAAsB;AAAA;AAAA,UAGvB,qBAAA;EACf,OAAA;EACA,IAAA;EACA,cAAA;AAAA;AAAA,UAGe,kBAAA;EACf,mBAAA,CAAoB,KAAA,WAAgB,mBAAA;EACpC,aAAA,CACE,QAAA,EAAU,mBAAA,EACV,QAAA,EAAU,eAAA;EAEZ,gBAAA,CAAiB,YAAA,UAAsB,KAAA,WAAgB,qBAAA;AAAA;AAAA,KAG7C,sBAAA,IACV,OAAA,EAAS,6BAAA,KACN,OAAA,CAAQ,mCAAA;AAAA,KAED,4BAAA,IACV,OAAiD,EAAxC,wCAAwC;AAAA,UAGlC,wBAAA;EACf,SAAA,CACE,cAAA,UACA,OAAA,EAAS,kCAAA,EACT,QAAA,EAAU,4BAAA,GACT,OAAA;EACH,WAAA,CAAY,cAAA;EACZ,OAAA;AAAA;AAAA,iBAYc,4BAAA,CACd,IAAA,EAAM,0BAAA,GACL,sBAAsB;AAAA,iBAyRT,8BAAA,CACd,IAAA,EAAM,0BAAA,GACL,wBAAwB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseCanonicalComponentFunctionName, parseComponentScopedIdentifier, safeReadRecurringSchedule } from "./internal/engines/shared.mjs";
|
|
1
|
+
import { parseCanonicalComponentFunctionName, parseComponentScopedIdentifier, quoteIdentifier, safeReadRecurringSchedule } from "./internal/engines/shared.mjs";
|
|
2
2
|
import { createFunctionReference } from "./runtime.mjs";
|
|
3
3
|
import { describeValidator } from "../../schema/index.js";
|
|
4
4
|
//#region src/runtime/devtools.ts
|
|
@@ -36,10 +36,12 @@ function createDevtoolsCommandHandler(deps) {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
case "data.insert": try {
|
|
39
|
+
const id = await runDevtoolsMutation(admin, async (ctx) => ctx.db.insert(payload.table, payload.document), { origin: "dashboard" });
|
|
40
|
+
notifyDataMutationScopes(admin, payload.table);
|
|
39
41
|
return {
|
|
40
42
|
kind: "data.mutate.result",
|
|
41
43
|
success: true,
|
|
42
|
-
id
|
|
44
|
+
id
|
|
43
45
|
};
|
|
44
46
|
} catch (error) {
|
|
45
47
|
return {
|
|
@@ -53,6 +55,7 @@ function createDevtoolsCommandHandler(deps) {
|
|
|
53
55
|
await ctx.db.patch(payload.table, payload.id, payload.fields);
|
|
54
56
|
return null;
|
|
55
57
|
}, { origin: "dashboard" });
|
|
58
|
+
notifyDataMutationScopes(admin, payload.table);
|
|
56
59
|
return {
|
|
57
60
|
kind: "data.mutate.result",
|
|
58
61
|
success: true,
|
|
@@ -70,6 +73,7 @@ function createDevtoolsCommandHandler(deps) {
|
|
|
70
73
|
await ctx.db.delete(payload.table, payload.id);
|
|
71
74
|
return null;
|
|
72
75
|
}, { origin: "dashboard" });
|
|
76
|
+
notifyDataMutationScopes(admin, payload.table);
|
|
73
77
|
return {
|
|
74
78
|
kind: "data.mutate.result",
|
|
75
79
|
success: true
|
|
@@ -81,6 +85,51 @@ function createDevtoolsCommandHandler(deps) {
|
|
|
81
85
|
error: error instanceof Error ? error.message : String(error)
|
|
82
86
|
};
|
|
83
87
|
}
|
|
88
|
+
case "data.export": try {
|
|
89
|
+
const requestedTables = payload.tables && payload.tables.length > 0 ? payload.tables : deps.schema.tableNames();
|
|
90
|
+
return {
|
|
91
|
+
kind: "data.export.result",
|
|
92
|
+
tables: await Promise.all(requestedTables.map(async (name) => {
|
|
93
|
+
const result = await queryTable(driver, name);
|
|
94
|
+
return {
|
|
95
|
+
name,
|
|
96
|
+
rows: result.rows,
|
|
97
|
+
totalCount: result.totalCount
|
|
98
|
+
};
|
|
99
|
+
}))
|
|
100
|
+
};
|
|
101
|
+
} catch (error) {
|
|
102
|
+
return {
|
|
103
|
+
kind: "data.export.result",
|
|
104
|
+
tables: [],
|
|
105
|
+
error: error instanceof Error ? error.message : String(error)
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
case "data.referenceOptions": {
|
|
109
|
+
const limit = Math.min(Math.max(payload.limit ?? 100, 1), 200);
|
|
110
|
+
const offset = Math.max(payload.offset ?? 0, 0);
|
|
111
|
+
try {
|
|
112
|
+
const result = await queryReferenceOptions(driver, payload.table, payload.search, limit, offset);
|
|
113
|
+
return {
|
|
114
|
+
kind: "data.referenceOptions.result",
|
|
115
|
+
table: payload.table,
|
|
116
|
+
rows: result.rows,
|
|
117
|
+
totalCount: result.totalCount,
|
|
118
|
+
offset,
|
|
119
|
+
hasMore: offset + result.rows.length < result.totalCount
|
|
120
|
+
};
|
|
121
|
+
} catch (error) {
|
|
122
|
+
return {
|
|
123
|
+
kind: "data.referenceOptions.result",
|
|
124
|
+
table: payload.table,
|
|
125
|
+
rows: [],
|
|
126
|
+
totalCount: 0,
|
|
127
|
+
offset,
|
|
128
|
+
hasMore: false,
|
|
129
|
+
error: error instanceof Error ? error.message : String(error)
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
84
133
|
case "sql.read": try {
|
|
85
134
|
const sqlSupport = requireDevtoolsSqlSupport(sql);
|
|
86
135
|
const databasePath = admin.getDriverDatabasePath();
|
|
@@ -135,9 +184,9 @@ function createDevtoolsCommandHandler(deps) {
|
|
|
135
184
|
case "scheduler.update": try {
|
|
136
185
|
const updated = await admin.updateScheduledJob({
|
|
137
186
|
id: payload.jobId,
|
|
138
|
-
schedule: payload.schedule,
|
|
139
187
|
args: payload.args,
|
|
140
|
-
|
|
188
|
+
...payload.schedule ? { schedule: payload.schedule } : {},
|
|
189
|
+
...payload.misfirePolicy ? { misfirePolicy: payload.misfirePolicy } : {},
|
|
141
190
|
...payload.runAt !== void 0 ? { runAt: payload.runAt } : {}
|
|
142
191
|
});
|
|
143
192
|
const updatedJob = (updated ? await listSchedulerJobs(driver) : []).find((job) => job.id === payload.jobId);
|
|
@@ -311,12 +360,16 @@ async function resolveSubscriptionPayload(payload, deps) {
|
|
|
311
360
|
}
|
|
312
361
|
}
|
|
313
362
|
async function queryTable(driver, table, filters, limit) {
|
|
314
|
-
let sql = `SELECT _id, _creationTime, _json FROM
|
|
363
|
+
let sql = `SELECT _id, _creationTime, _json FROM ${quoteIdentifier(table)}`;
|
|
315
364
|
const params = [];
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
365
|
+
const whereClauses = [];
|
|
366
|
+
if (filters && filters.length > 0) {
|
|
367
|
+
for (const filter of filters) {
|
|
368
|
+
whereClauses.push(filterToSql(filter));
|
|
369
|
+
params.push(normalizeFilterValue(filter));
|
|
370
|
+
}
|
|
371
|
+
sql += ` WHERE ${whereClauses.join(" AND ")}`;
|
|
372
|
+
}
|
|
320
373
|
sql += " ORDER BY _creationTime DESC";
|
|
321
374
|
if (limit) sql += ` LIMIT ${limit}`;
|
|
322
375
|
return {
|
|
@@ -325,7 +378,30 @@ async function queryTable(driver, table, filters, limit) {
|
|
|
325
378
|
_creationTime: row._creationTime,
|
|
326
379
|
...JSON.parse(row._json)
|
|
327
380
|
})),
|
|
328
|
-
totalCount: (await driver.get(`SELECT COUNT(*) as count FROM
|
|
381
|
+
totalCount: (await driver.get(`SELECT COUNT(*) as count FROM ${quoteIdentifier(table)}${whereClauses.length > 0 ? ` WHERE ${whereClauses.join(" AND ")}` : ""}`, params))?.count ?? 0
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
async function queryReferenceOptions(driver, table, search, limit, offset) {
|
|
385
|
+
let sql = `SELECT _id, _creationTime, _json FROM ${quoteIdentifier(table)}`;
|
|
386
|
+
const params = [];
|
|
387
|
+
const trimmedSearch = search?.trim();
|
|
388
|
+
const whereClause = trimmedSearch ? " WHERE _id LIKE ? OR _json LIKE ?" : "";
|
|
389
|
+
if (trimmedSearch) {
|
|
390
|
+
const like = `%${trimmedSearch}%`;
|
|
391
|
+
params.push(like, like);
|
|
392
|
+
}
|
|
393
|
+
sql += `${whereClause} ORDER BY _creationTime DESC LIMIT ? OFFSET ?`;
|
|
394
|
+
return {
|
|
395
|
+
rows: (await driver.all(sql, [
|
|
396
|
+
...params,
|
|
397
|
+
limit,
|
|
398
|
+
offset
|
|
399
|
+
])).map((row) => ({
|
|
400
|
+
_id: row._id,
|
|
401
|
+
_creationTime: row._creationTime,
|
|
402
|
+
...JSON.parse(row._json)
|
|
403
|
+
})),
|
|
404
|
+
totalCount: (await driver.get(`SELECT COUNT(*) as count FROM ${quoteIdentifier(table)}${whereClause}`, params))?.count ?? 0
|
|
329
405
|
};
|
|
330
406
|
}
|
|
331
407
|
async function getSchemaTables(driver, schema) {
|
|
@@ -337,7 +413,8 @@ async function getSchemaTables(driver, schema) {
|
|
|
337
413
|
return {
|
|
338
414
|
name: fieldName,
|
|
339
415
|
type: field.validator.kind,
|
|
340
|
-
optional: field.optional
|
|
416
|
+
optional: field.optional,
|
|
417
|
+
...field.validator.kind === "id" && field.validator.tableName ? { referenceTable: field.validator.tableName } : {}
|
|
341
418
|
};
|
|
342
419
|
}) : [];
|
|
343
420
|
fields.unshift({
|
|
@@ -349,12 +426,7 @@ async function getSchemaTables(driver, schema) {
|
|
|
349
426
|
type: "number",
|
|
350
427
|
optional: false
|
|
351
428
|
});
|
|
352
|
-
|
|
353
|
-
try {
|
|
354
|
-
documentCount = (await driver.get(`SELECT COUNT(*) as count FROM "${name}"`))?.count ?? 0;
|
|
355
|
-
} catch {
|
|
356
|
-
documentCount = 0;
|
|
357
|
-
}
|
|
429
|
+
const documentCount = await driver.get(`SELECT COUNT(*) as count FROM "${name}"`).then((countRow) => countRow?.count ?? 0).catch(() => 0);
|
|
358
430
|
return {
|
|
359
431
|
name,
|
|
360
432
|
...table.options.tableName ? { displayName: table.options.tableName } : {},
|
|
@@ -410,12 +482,18 @@ function listFunctions(functions) {
|
|
|
410
482
|
const descriptor = {
|
|
411
483
|
name,
|
|
412
484
|
type: fn.kind,
|
|
413
|
-
file: inferFileFromFunctionName(name),
|
|
414
485
|
owner: componentFunction ? "component" : "root",
|
|
486
|
+
namespace: inferFunctionNamespace(name),
|
|
487
|
+
metadataAvailable: componentFunction !== null || name.includes(":"),
|
|
415
488
|
...componentFunction ? {
|
|
489
|
+
file: `components/${componentFunction.componentPath}`,
|
|
490
|
+
modulePath: componentFunction.componentPath,
|
|
416
491
|
componentPath: componentFunction.componentPath,
|
|
417
492
|
visibility: componentFunction.visibility,
|
|
418
493
|
localName: componentFunction.localName
|
|
494
|
+
} : inferFileFromFunctionName(name) ? {
|
|
495
|
+
file: inferFileFromFunctionName(name),
|
|
496
|
+
modulePath: inferFunctionNamespace(name)
|
|
419
497
|
} : {}
|
|
420
498
|
};
|
|
421
499
|
const argsDesc = describeValidator(fn.argsValidator);
|
|
@@ -428,15 +506,41 @@ function inferFileFromFunctionName(name) {
|
|
|
428
506
|
if (componentFunction) return `components/${componentFunction.componentPath}`;
|
|
429
507
|
const parts = name.split(":");
|
|
430
508
|
if (parts.length > 1) return `${parts[0]}.ts`;
|
|
431
|
-
return "
|
|
509
|
+
return "";
|
|
510
|
+
}
|
|
511
|
+
function inferFunctionNamespace(name) {
|
|
512
|
+
const componentFunction = parseCanonicalComponentFunctionName(name);
|
|
513
|
+
if (componentFunction) return componentFunction.componentPath;
|
|
514
|
+
if (name.includes(":")) return name.split(":")[0] ?? "root";
|
|
515
|
+
if (name.includes("/")) return name.split("/")[0] ?? "root";
|
|
516
|
+
return "root";
|
|
432
517
|
}
|
|
433
518
|
function normalizeFilterValue(filter) {
|
|
519
|
+
const value = coerceFilterValue(filter.value);
|
|
434
520
|
switch (filter.operator) {
|
|
435
|
-
case "contains": return `%${String(
|
|
436
|
-
case "startsWith": return `${String(
|
|
437
|
-
default: return
|
|
521
|
+
case "contains": return `%${String(value)}%`;
|
|
522
|
+
case "startsWith": return `${String(value)}%`;
|
|
523
|
+
default: return value;
|
|
438
524
|
}
|
|
439
525
|
}
|
|
526
|
+
function filterToSql(filter) {
|
|
527
|
+
const operator = filterOperatorToSql(filter.operator);
|
|
528
|
+
if (filter.field === "_id") return `_id ${operator} ?`;
|
|
529
|
+
if (filter.field === "_creationTime") return `_creationTime ${operator} ?`;
|
|
530
|
+
return `json_extract(_json, ${JSON.stringify(`$.${filter.field}`)}) ${operator} ?`;
|
|
531
|
+
}
|
|
532
|
+
function coerceFilterValue(value) {
|
|
533
|
+
if (typeof value !== "string") return value;
|
|
534
|
+
const trimmed = value.trim();
|
|
535
|
+
if (trimmed === "true") return true;
|
|
536
|
+
if (trimmed === "false") return false;
|
|
537
|
+
if (trimmed === "null") return null;
|
|
538
|
+
if (/^-?\d+(?:\.\d+)?$/.test(trimmed)) {
|
|
539
|
+
const numberValue = Number(trimmed);
|
|
540
|
+
if (Number.isFinite(numberValue)) return numberValue;
|
|
541
|
+
}
|
|
542
|
+
return value;
|
|
543
|
+
}
|
|
440
544
|
function filterOperatorToSql(operator) {
|
|
441
545
|
switch (operator) {
|
|
442
546
|
case "eq": return "=";
|
|
@@ -491,6 +595,9 @@ function capitalize(value) {
|
|
|
491
595
|
async function runDevtoolsMutation(admin, callback, meta) {
|
|
492
596
|
return admin.runDevtoolsMutation(callback, meta);
|
|
493
597
|
}
|
|
598
|
+
function notifyDataMutationScopes(admin, tableName) {
|
|
599
|
+
admin.notifyDevtoolsScopes(["schema.tables", `table:${tableName}`]);
|
|
600
|
+
}
|
|
494
601
|
function scopesForSubscription(payload, sql) {
|
|
495
602
|
switch (payload.kind) {
|
|
496
603
|
case "runtime.summary": return new Set(["runtime.summary"]);
|
|
@@ -517,7 +624,7 @@ function intersects(a, b) {
|
|
|
517
624
|
return false;
|
|
518
625
|
}
|
|
519
626
|
function requireDevtoolsSqlSupport(sql) {
|
|
520
|
-
if (!sql) throw new Error("SQL
|
|
627
|
+
if (!sql) throw new Error("SQL Console is not available for this runtime.");
|
|
521
628
|
return sql;
|
|
522
629
|
}
|
|
523
630
|
//#endregion
|