@fragno-dev/lofi 0.0.1 → 0.0.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/adapters/in-memory/adapter.d.ts.map +1 -1
- package/dist/adapters/in-memory/adapter.js.map +1 -1
- package/dist/adapters/in-memory/query.js +1 -2
- package/dist/adapters/in-memory/query.js.map +1 -1
- package/dist/adapters/in-memory/store.d.ts.map +1 -1
- package/dist/adapters/in-memory/store.js +1 -1
- package/dist/adapters/in-memory/store.js.map +1 -1
- package/dist/adapters/stacked/adapter.d.ts.map +1 -1
- package/dist/adapters/stacked/adapter.js.map +1 -1
- package/dist/adapters/stacked/merge.js.map +1 -1
- package/dist/cli/client.js +1 -1
- package/dist/cli/client.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/scenario.js +1 -1
- package/dist/cli/scenario.js.map +1 -1
- package/dist/cli/server.js +1 -1
- package/dist/cli/server.js.map +1 -1
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js.map +1 -1
- package/dist/indexeddb/adapter.d.ts.map +1 -1
- package/dist/indexeddb/adapter.js +1 -1
- package/dist/indexeddb/adapter.js.map +1 -1
- package/dist/optimistic/overlay-manager.d.ts.map +1 -1
- package/dist/optimistic/overlay-manager.js +0 -1
- package/dist/optimistic/overlay-manager.js.map +1 -1
- package/dist/outbox/decode.d.ts.map +1 -1
- package/dist/outbox/decode.js.map +1 -1
- package/dist/outbox/uow.d.ts.map +1 -1
- package/dist/outbox/uow.js.map +1 -1
- package/dist/query/conditions.d.ts +2 -1
- package/dist/query/conditions.d.ts.map +1 -1
- package/dist/query/conditions.js +2 -1
- package/dist/query/conditions.js.map +1 -1
- package/dist/query/engine.d.ts.map +1 -1
- package/dist/query/engine.js +1 -1
- package/dist/query/engine.js.map +1 -1
- package/dist/scenario.d.ts.map +1 -1
- package/dist/scenario.js.map +1 -1
- package/dist/submit/client.d.ts.map +1 -1
- package/dist/submit/client.js.map +1 -1
- package/dist/submit/local-handler-tx.d.ts.map +1 -1
- package/dist/submit/local-handler-tx.js.map +1 -1
- package/dist/submit/queue.js.map +1 -1
- package/dist/submit/rebase.d.ts.map +1 -1
- package/dist/submit/rebase.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +23 -26
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-handler-tx.js","names":["current: Record<string, unknown>","created: (bigint | null)[]","queryExecutor: LocalHandlerQueryExecutor<TContext>","compiler: UOWCompiler<LocalCompiledOperation>","executor: UOWExecutor<LocalCompiledOperation, unknown>","results: unknown[]","mutations: LofiMutation[]","decoder: UOWDecoder<unknown>"],"sources":["../../src/submit/local-handler-tx.ts"],"sourcesContent":["import { createHandlerTxBuilder, UnitOfWork, type HandlerTxBuilder } from \"@fragno-dev/db\";\nimport type {\n CompiledMutation,\n FindBuilder,\n IndexedJoinBuilder,\n JoinFindBuilder,\n MutationOperation,\n RetrievalOperation,\n UOWCompiler,\n UOWDecoder,\n UOWExecutor,\n} from \"@fragno-dev/db/unit-of-work\";\nimport type { Cursor } from \"@fragno-dev/db/cursor\";\nimport { FragnoId } from \"@fragno-dev/db/schema\";\nimport type { AnyColumn, AnySchema, AnyTable } from \"@fragno-dev/db/schema\";\nimport type { IndexedDbQueryContext } from \"../query/engine\";\nimport { executeIndexedDbRetrievalOperation } from \"../query/engine\";\nimport type { Condition, ConditionBuilder } from \"../query/conditions\";\nimport type { LofiMutation, LofiQueryInterface, LofiQueryableAdapter } from \"../types\";\n\ntype HandlerTxOptions = Parameters<typeof createHandlerTxBuilder>[0];\n\nexport type LocalHandlerTxFactory = (\n options?: Omit<HandlerTxOptions, \"createUnitOfWork\">,\n) => HandlerTxBuilder<readonly [], [], [], unknown, unknown, false, false, false, false, {}>;\n\nexport type LocalHandlerCommandDefinition<TInput = unknown, TContext = unknown> = {\n name: string;\n handler: (args: { input: TInput; tx: LocalHandlerTxFactory; ctx: TContext }) => Promise<unknown>;\n};\n\ntype LocalHandlerTxAdapter = {\n applyMutations?(mutations: LofiMutation[]): Promise<void>;\n createQueryContext?: (schemaName: string) => IndexedDbQueryContext;\n createQueryEngine?: LofiQueryableAdapter[\"createQueryEngine\"];\n};\n\ntype LocalRetrievalOperation =\n | {\n type: \"find\";\n table: AnyTable;\n indexName: string;\n options: {\n useIndex: string;\n select?: unknown;\n where?:\n | ((builder: ConditionBuilder<Record<string, AnyColumn>>) => Condition | boolean)\n | Condition;\n orderByIndex?: {\n indexName: string;\n direction: \"asc\" | \"desc\";\n };\n after?: Cursor | string;\n before?: Cursor | string;\n pageSize?: number;\n joins?: CompiledJoin[];\n };\n withCursor: boolean;\n }\n | {\n type: \"count\";\n table: AnyTable;\n indexName: string;\n options: {\n where?:\n | ((builder: ConditionBuilder<Record<string, AnyColumn>>) => Condition | boolean)\n | Condition;\n };\n };\n\ntype CompiledJoin = {\n relation: { name: string; table: AnyTable; on: [string, string][] };\n options:\n | {\n select: unknown;\n where?: Condition;\n orderBy?: [AnyColumn, \"asc\" | \"desc\"][];\n join?: CompiledJoin[];\n limit?: number;\n }\n | false;\n};\n\nexport type LocalHandlerQueryExecutor<TContext> = {\n createQueryContext: (schemaName: string) => TContext;\n executeRetrievalOperation: (options: {\n operation: LocalRetrievalOperation;\n context: TContext;\n }) => Promise<unknown>;\n};\n\nexport type LocalHandlerTxOptions<TContext = IndexedDbQueryContext> = {\n adapter: LocalHandlerTxAdapter;\n schemas: AnySchema[];\n queryExecutor?: LocalHandlerQueryExecutor<TContext>;\n};\n\ntype LocalCompiledOperation = RetrievalOperation<AnySchema> | MutationOperation<AnySchema>;\n\nconst createLocalVersionstamp = (): string =>\n `local-${Date.now()}-${Math.random().toString(16).slice(2)}`;\n\nconst getExternalId = (id: FragnoId | string): string =>\n typeof id === \"string\" ? id : id.externalId;\n\nconst buildLocalMutation = (\n operation: MutationOperation<AnySchema>,\n versionstamp: string,\n): LofiMutation | null => {\n if (operation.type === \"create\") {\n return {\n op: \"create\",\n schema: operation.schema.name,\n table: operation.table,\n externalId: operation.generatedExternalId,\n values: operation.values as Record<string, unknown>,\n versionstamp,\n };\n }\n\n if (operation.type === \"update\") {\n return {\n op: \"update\",\n schema: operation.schema.name,\n table: operation.table,\n externalId: getExternalId(operation.id),\n set: operation.set as Record<string, unknown>,\n versionstamp,\n };\n }\n\n if (operation.type === \"delete\") {\n return {\n op: \"delete\",\n schema: operation.schema.name,\n table: operation.table,\n externalId: getExternalId(operation.id),\n versionstamp,\n };\n }\n\n return null;\n};\n\nconst isFindOrCount = (\n operation: LocalCompiledOperation,\n): operation is RetrievalOperation<AnySchema> =>\n operation.type === \"find\" || operation.type === \"count\";\n\nconst isMutationOperation = (\n operation: LocalCompiledOperation,\n): operation is MutationOperation<AnySchema> =>\n operation.type === \"create\" ||\n operation.type === \"update\" ||\n operation.type === \"delete\" ||\n operation.type === \"check\";\n\nconst buildFindKeyCondition = (\n table: AnyTable,\n externalId: string,\n): ((builder: ConditionBuilder<Record<string, AnyColumn>>) => Condition | boolean) => {\n const idColumn = table.getIdColumn();\n return (eb) => eb(idColumn.name, \"=\", externalId);\n};\n\nconst resolveQueryContext = <TContext>(\n executor: LocalHandlerQueryExecutor<TContext>,\n schema: AnySchema,\n): TContext => executor.createQueryContext(schema.name);\n\nconst normalizeIndexName = (indexName: string): string =>\n indexName === \"_primary\" ? \"primary\" : indexName;\n\nconst resolveIndexNameFromOrderBy = (\n table: AnyTable,\n orderBy: [AnyColumn, \"asc\" | \"desc\"][],\n): string | null => {\n if (orderBy.length === 0) {\n return null;\n }\n\n const direction = orderBy[0]?.[1];\n if (!direction || orderBy.some(([, dir]) => dir !== direction)) {\n return null;\n }\n\n const orderColumns = orderBy.map(([column]) => column.name);\n const idColumn = table.getIdColumn();\n if (orderColumns.length === 1 && orderColumns[0] === idColumn.name) {\n return \"primary\";\n }\n\n for (const [indexName, index] of Object.entries(table.indexes)) {\n const indexColumns = index.columns.map((column) => column.name);\n if (\n indexColumns.length === orderColumns.length &&\n indexColumns.every((name, idx) => name === orderColumns[idx])\n ) {\n return indexName;\n }\n }\n\n return null;\n};\n\nconst applyCompiledJoins = (\n builder: IndexedJoinBuilder<AnyTable, {}>,\n joins: CompiledJoin[] | undefined,\n): IndexedJoinBuilder<AnyTable, {}> => {\n if (!joins || joins.length === 0) {\n return builder;\n }\n\n let current: Record<string, unknown> = builder as Record<string, unknown>;\n\n for (const join of joins) {\n if (join.options === false) {\n continue;\n }\n const joinOptions = join.options;\n\n const relationName = join.relation.name;\n const relationBuilder = current[relationName];\n if (typeof relationBuilder !== \"function\") {\n continue;\n }\n\n current = relationBuilder((joinBuilder: JoinFindBuilder<AnyTable>) => {\n if (joinOptions.select && joinOptions.select !== true) {\n joinBuilder.select(joinOptions.select as unknown as true | string[]);\n }\n\n if (joinOptions.where) {\n joinBuilder.whereIndex(\"primary\", () => joinOptions.where as Condition);\n }\n\n if (joinOptions.orderBy && joinOptions.orderBy.length > 0) {\n const indexName = resolveIndexNameFromOrderBy(join.relation.table, joinOptions.orderBy);\n const direction = joinOptions.orderBy[0][1];\n if (indexName) {\n joinBuilder.orderByIndex(indexName as \"primary\" | string, direction);\n }\n }\n\n if (joinOptions.limit !== undefined) {\n joinBuilder.pageSize(joinOptions.limit);\n }\n\n if (joinOptions.join && joinOptions.join.length > 0) {\n joinBuilder.join((nestedBuilder) => applyCompiledJoins(nestedBuilder, joinOptions.join));\n }\n\n return joinBuilder;\n }) as Record<string, unknown>;\n }\n\n return current as IndexedJoinBuilder<AnyTable, {}>;\n};\n\nconst applyFindOptionsToBuilder = (\n builder: Omit<FindBuilder<AnyTable>, \"build\">,\n operation: LocalRetrievalOperation,\n): void => {\n const useIndex = normalizeIndexName(\n operation.type === \"count\" ? operation.indexName : operation.options.useIndex,\n ) as \"primary\" | string;\n if (operation.options.where) {\n if (typeof operation.options.where === \"function\") {\n builder.whereIndex(useIndex, operation.options.where as () => Condition);\n } else {\n builder.whereIndex(useIndex, () => operation.options.where as Condition);\n }\n } else {\n builder.whereIndex(useIndex);\n }\n\n if (operation.type === \"count\") {\n builder.selectCount();\n return;\n }\n\n if (operation.options.select && operation.options.select !== true) {\n builder.select(operation.options.select as unknown as true | string[]);\n }\n\n if (operation.options.orderByIndex) {\n builder.orderByIndex(\n normalizeIndexName(operation.options.orderByIndex.indexName) as \"primary\" | string,\n operation.options.orderByIndex.direction,\n );\n }\n\n if (operation.options.after) {\n builder.after(operation.options.after);\n }\n\n if (operation.options.before) {\n builder.before(operation.options.before);\n }\n\n if (operation.options.pageSize !== undefined) {\n builder.pageSize(operation.options.pageSize);\n }\n\n if (operation.options.joins && operation.options.joins.length > 0) {\n builder.join((joinBuilder) => applyCompiledJoins(joinBuilder, operation.options.joins));\n }\n};\n\nconst executeQueryEngineRetrievalOperation = async (\n operation: LocalRetrievalOperation,\n query: LofiQueryInterface<AnySchema>,\n): Promise<unknown> => {\n const tableName = operation.table.name;\n const builderFn = (builder: Omit<FindBuilder<AnyTable>, \"build\">) => {\n applyFindOptionsToBuilder(builder, operation);\n return builder;\n };\n\n if (operation.type === \"count\") {\n return (query.find as unknown as typeof query.find)(tableName, builderFn);\n }\n\n if (operation.withCursor) {\n return (query.findWithCursor as unknown as typeof query.findWithCursor)(tableName, builderFn);\n }\n\n return (query.find as unknown as typeof query.find)(tableName, builderFn);\n};\n\nconst getRowVersion = async <TContext>(\n executor: LocalHandlerQueryExecutor<TContext>,\n schema: AnySchema,\n table: AnyTable,\n externalId: string,\n): Promise<number | null> => {\n const context = resolveQueryContext(executor, schema);\n const result = await executor.executeRetrievalOperation({\n operation: {\n type: \"find\",\n table,\n indexName: \"_primary\",\n options: {\n useIndex: \"_primary\",\n where: buildFindKeyCondition(table, externalId),\n pageSize: 1,\n },\n withCursor: false,\n },\n context,\n });\n\n if (!Array.isArray(result) || result.length === 0) {\n return null;\n }\n\n const idColumn = table.getIdColumn();\n const row = result[0] as Record<string, unknown>;\n const idValue = row[idColumn.name];\n if (idValue && typeof idValue === \"object\" && \"version\" in idValue) {\n return (idValue as FragnoId).version;\n }\n\n return null;\n};\n\nconst validateMutationChecks = async <TContext>(\n executor: LocalHandlerQueryExecutor<TContext>,\n mutationBatch: CompiledMutation<LocalCompiledOperation>[],\n): Promise<boolean> => {\n for (const mutation of mutationBatch) {\n const operation = mutation.operation;\n if (!operation || !isMutationOperation(operation)) {\n continue;\n }\n\n if (operation.type === \"check\") {\n const externalId = getExternalId(operation.id);\n const version = operation.id instanceof FragnoId ? operation.id.version : undefined;\n if (version === undefined) {\n return false;\n }\n const currentVersion = await getRowVersion(\n executor,\n operation.schema,\n operation.schema.tables[operation.table],\n externalId,\n );\n if (currentVersion === null || currentVersion !== version) {\n return false;\n }\n continue;\n }\n\n if ((operation.type === \"update\" || operation.type === \"delete\") && operation.checkVersion) {\n const externalId = getExternalId(operation.id);\n const version = operation.id instanceof FragnoId ? operation.id.version : undefined;\n if (version === undefined) {\n return false;\n }\n const currentVersion = await getRowVersion(\n executor,\n operation.schema,\n operation.schema.tables[operation.table],\n externalId,\n );\n if (currentVersion === null || currentVersion !== version) {\n return false;\n }\n }\n }\n\n return true;\n};\n\nconst collectCreatedInternalIds = async <TContext>(\n executor: LocalHandlerQueryExecutor<TContext>,\n mutationBatch: CompiledMutation<LocalCompiledOperation>[],\n): Promise<(bigint | null)[]> => {\n const created: (bigint | null)[] = [];\n\n for (const mutation of mutationBatch) {\n const operation = mutation.operation;\n if (!operation || operation.type !== \"create\") {\n continue;\n }\n\n const table = operation.schema.tables[operation.table];\n const context = resolveQueryContext(executor, operation.schema);\n const result = await executor.executeRetrievalOperation({\n operation: {\n type: \"find\",\n table,\n indexName: \"_primary\",\n options: {\n useIndex: \"_primary\",\n where: buildFindKeyCondition(table, operation.generatedExternalId),\n pageSize: 1,\n },\n withCursor: false,\n },\n context,\n });\n\n const row = Array.isArray(result) ? result[0] : undefined;\n if (!row) {\n created.push(null);\n continue;\n }\n\n const idColumn = table.getIdColumn();\n const idValue = (row as Record<string, unknown>)[idColumn.name];\n if (idValue && typeof idValue === \"object\" && \"internalId\" in idValue) {\n const internalId = (idValue as FragnoId).internalId;\n created.push(internalId ?? null);\n } else {\n created.push(null);\n }\n }\n\n return created;\n};\n\nexport const createLocalHandlerTx = <TContext>(\n options: LocalHandlerTxOptions<TContext>,\n): LocalHandlerTxFactory => {\n const schemaMap = new Map<string, AnySchema>();\n const schemaNamespaceMap = new WeakMap<AnySchema, string | null>();\n for (const schema of options.schemas) {\n schemaMap.set(schema.name, schema);\n schemaNamespaceMap.set(schema, schema.name);\n }\n\n const queryExecutor: LocalHandlerQueryExecutor<TContext> =\n options.queryExecutor ??\n (() => {\n const createQueryEngine = options.adapter.createQueryEngine?.bind(options.adapter);\n if (createQueryEngine) {\n const cache = new Map<string, LofiQueryInterface<AnySchema>>();\n return {\n createQueryContext: (schemaName: string) => {\n const cached = cache.get(schemaName);\n if (cached) {\n return cached as unknown as TContext;\n }\n const schema = schemaMap.get(schemaName);\n if (!schema) {\n throw new Error(`Local handler tx missing schema: ${schemaName}`);\n }\n const engine = createQueryEngine(schema, { schemaName });\n cache.set(schemaName, engine);\n return engine as unknown as TContext;\n },\n executeRetrievalOperation: async ({\n operation,\n context,\n }: {\n operation: LocalRetrievalOperation;\n context: LofiQueryInterface<AnySchema>;\n }) => await executeQueryEngineRetrievalOperation(operation, context),\n } as unknown as LocalHandlerQueryExecutor<TContext>;\n }\n if (!options.adapter.createQueryContext) {\n throw new Error(\n \"Local handler tx requires a queryExecutor, adapter.createQueryEngine(), or adapter.createQueryContext().\",\n );\n }\n return {\n createQueryContext: options.adapter.createQueryContext.bind(options.adapter),\n executeRetrievalOperation: executeIndexedDbRetrievalOperation,\n } as unknown as LocalHandlerQueryExecutor<TContext>;\n })();\n\n const compiler: UOWCompiler<LocalCompiledOperation> = {\n compileRetrievalOperation(op: RetrievalOperation<AnySchema>): LocalCompiledOperation | null {\n return op;\n },\n compileMutationOperation(\n op: MutationOperation<AnySchema>,\n ): CompiledMutation<LocalCompiledOperation> | null {\n return {\n query: op,\n operation: op,\n op: op.type,\n expectedAffectedRows: null,\n expectedReturnedRows: null,\n };\n },\n };\n\n const executor: UOWExecutor<LocalCompiledOperation, unknown> = {\n async executeRetrievalPhase(retrievalBatch: LocalCompiledOperation[]): Promise<unknown[]> {\n const results: unknown[] = [];\n\n for (const compiled of retrievalBatch) {\n if (!isFindOrCount(compiled)) {\n throw new Error(`Unsupported local retrieval operation: ${compiled.type}`);\n }\n\n const context = resolveQueryContext(queryExecutor, compiled.schema);\n const result = await queryExecutor.executeRetrievalOperation({\n operation:\n compiled.type === \"count\"\n ? {\n type: \"count\",\n table: compiled.table,\n indexName: compiled.indexName,\n options: { where: compiled.options.where },\n }\n : {\n type: \"find\",\n table: compiled.table,\n indexName: compiled.indexName,\n options: compiled.options,\n withCursor: compiled.withCursor ?? false,\n },\n context,\n });\n\n results.push(result);\n }\n\n return results;\n },\n\n async executeMutationPhase(mutationBatch: CompiledMutation<LocalCompiledOperation>[]) {\n if (mutationBatch.length === 0) {\n return { success: true, createdInternalIds: [] };\n }\n\n const checksOk = await validateMutationChecks(queryExecutor, mutationBatch);\n if (!checksOk) {\n return { success: false };\n }\n\n if (!options.adapter.applyMutations) {\n throw new Error(\"Lofi adapter does not support applyMutations.\");\n }\n\n const txVersionstamp = createLocalVersionstamp();\n const mutations: LofiMutation[] = [];\n for (const compiled of mutationBatch) {\n const operation = compiled.operation;\n if (!operation || !isMutationOperation(operation)) {\n continue;\n }\n\n const mutation = buildLocalMutation(operation, txVersionstamp);\n if (mutation) {\n mutations.push(mutation);\n }\n }\n\n if (mutations.length > 0) {\n await options.adapter.applyMutations(mutations);\n }\n\n const createdInternalIds = await collectCreatedInternalIds(queryExecutor, mutationBatch);\n return { success: true, createdInternalIds };\n },\n };\n\n const decoder: UOWDecoder<unknown> = {\n decode(rawResults) {\n return rawResults;\n },\n };\n\n return (execOptions?: Omit<HandlerTxOptions, \"createUnitOfWork\">) =>\n createHandlerTxBuilder({\n ...execOptions,\n createUnitOfWork: () => {\n const uow = new UnitOfWork(\n compiler,\n executor,\n decoder,\n undefined,\n undefined,\n schemaNamespaceMap,\n );\n return uow;\n },\n });\n};\n\nexport const runLocalHandlerCommand = async <TInput, TContext>(options: {\n command: LocalHandlerCommandDefinition<TInput, TContext>;\n input: TInput;\n ctx: TContext;\n tx: LocalHandlerTxFactory;\n}): Promise<void> => {\n await options.command.handler({\n input: options.input,\n ctx: options.ctx,\n tx: options.tx,\n });\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"local-handler-tx.js","names":["current: Record<string, unknown>","created: (bigint | null)[]","queryExecutor: LocalHandlerQueryExecutor<TContext>","compiler: UOWCompiler<LocalCompiledOperation>","executor: UOWExecutor<LocalCompiledOperation, unknown>","results: unknown[]","mutations: LofiMutation[]","decoder: UOWDecoder<unknown>"],"sources":["../../src/submit/local-handler-tx.ts"],"sourcesContent":["import type { Cursor } from \"@fragno-dev/db/cursor\";\nimport { FragnoId } from \"@fragno-dev/db/schema\";\nimport type { AnyColumn, AnySchema, AnyTable } from \"@fragno-dev/db/schema\";\nimport type {\n CompiledMutation,\n FindBuilder,\n IndexedJoinBuilder,\n JoinFindBuilder,\n MutationOperation,\n RetrievalOperation,\n UOWCompiler,\n UOWDecoder,\n UOWExecutor,\n} from \"@fragno-dev/db/unit-of-work\";\n\nimport { createHandlerTxBuilder, UnitOfWork, type HandlerTxBuilder } from \"@fragno-dev/db\";\n\nimport type { Condition, ConditionBuilder } from \"../query/conditions\";\nimport type { IndexedDbQueryContext } from \"../query/engine\";\nimport { executeIndexedDbRetrievalOperation } from \"../query/engine\";\nimport type { LofiMutation, LofiQueryInterface, LofiQueryableAdapter } from \"../types\";\n\ntype HandlerTxOptions = Parameters<typeof createHandlerTxBuilder>[0];\n\nexport type LocalHandlerTxFactory = (\n options?: Omit<HandlerTxOptions, \"createUnitOfWork\">,\n) => HandlerTxBuilder<readonly [], [], [], unknown, unknown, false, false, false, false, {}>;\n\nexport type LocalHandlerCommandDefinition<TInput = unknown, TContext = unknown> = {\n name: string;\n handler: (args: { input: TInput; tx: LocalHandlerTxFactory; ctx: TContext }) => Promise<unknown>;\n};\n\ntype LocalHandlerTxAdapter = {\n applyMutations?(mutations: LofiMutation[]): Promise<void>;\n createQueryContext?: (schemaName: string) => IndexedDbQueryContext;\n createQueryEngine?: LofiQueryableAdapter[\"createQueryEngine\"];\n};\n\ntype LocalRetrievalOperation =\n | {\n type: \"find\";\n table: AnyTable;\n indexName: string;\n options: {\n useIndex: string;\n select?: unknown;\n where?:\n | ((builder: ConditionBuilder<Record<string, AnyColumn>>) => Condition | boolean)\n | Condition;\n orderByIndex?: {\n indexName: string;\n direction: \"asc\" | \"desc\";\n };\n after?: Cursor | string;\n before?: Cursor | string;\n pageSize?: number;\n joins?: CompiledJoin[];\n };\n withCursor: boolean;\n }\n | {\n type: \"count\";\n table: AnyTable;\n indexName: string;\n options: {\n where?:\n | ((builder: ConditionBuilder<Record<string, AnyColumn>>) => Condition | boolean)\n | Condition;\n };\n };\n\ntype CompiledJoin = {\n relation: { name: string; table: AnyTable; on: [string, string][] };\n options:\n | {\n select: unknown;\n where?: Condition;\n orderBy?: [AnyColumn, \"asc\" | \"desc\"][];\n join?: CompiledJoin[];\n limit?: number;\n }\n | false;\n};\n\nexport type LocalHandlerQueryExecutor<TContext> = {\n createQueryContext: (schemaName: string) => TContext;\n executeRetrievalOperation: (options: {\n operation: LocalRetrievalOperation;\n context: TContext;\n }) => Promise<unknown>;\n};\n\nexport type LocalHandlerTxOptions<TContext = IndexedDbQueryContext> = {\n adapter: LocalHandlerTxAdapter;\n schemas: AnySchema[];\n queryExecutor?: LocalHandlerQueryExecutor<TContext>;\n};\n\ntype LocalCompiledOperation = RetrievalOperation<AnySchema> | MutationOperation<AnySchema>;\n\nconst createLocalVersionstamp = (): string =>\n `local-${Date.now()}-${Math.random().toString(16).slice(2)}`;\n\nconst getExternalId = (id: FragnoId | string): string =>\n typeof id === \"string\" ? id : id.externalId;\n\nconst buildLocalMutation = (\n operation: MutationOperation<AnySchema>,\n versionstamp: string,\n): LofiMutation | null => {\n if (operation.type === \"create\") {\n return {\n op: \"create\",\n schema: operation.schema.name,\n table: operation.table,\n externalId: operation.generatedExternalId,\n values: operation.values as Record<string, unknown>,\n versionstamp,\n };\n }\n\n if (operation.type === \"update\") {\n return {\n op: \"update\",\n schema: operation.schema.name,\n table: operation.table,\n externalId: getExternalId(operation.id),\n set: operation.set as Record<string, unknown>,\n versionstamp,\n };\n }\n\n if (operation.type === \"delete\") {\n return {\n op: \"delete\",\n schema: operation.schema.name,\n table: operation.table,\n externalId: getExternalId(operation.id),\n versionstamp,\n };\n }\n\n return null;\n};\n\nconst isFindOrCount = (\n operation: LocalCompiledOperation,\n): operation is RetrievalOperation<AnySchema> =>\n operation.type === \"find\" || operation.type === \"count\";\n\nconst isMutationOperation = (\n operation: LocalCompiledOperation,\n): operation is MutationOperation<AnySchema> =>\n operation.type === \"create\" ||\n operation.type === \"update\" ||\n operation.type === \"delete\" ||\n operation.type === \"check\";\n\nconst buildFindKeyCondition = (\n table: AnyTable,\n externalId: string,\n): ((builder: ConditionBuilder<Record<string, AnyColumn>>) => Condition | boolean) => {\n const idColumn = table.getIdColumn();\n return (eb) => eb(idColumn.name, \"=\", externalId);\n};\n\nconst resolveQueryContext = <TContext>(\n executor: LocalHandlerQueryExecutor<TContext>,\n schema: AnySchema,\n): TContext => executor.createQueryContext(schema.name);\n\nconst normalizeIndexName = (indexName: string): string =>\n indexName === \"_primary\" ? \"primary\" : indexName;\n\nconst resolveIndexNameFromOrderBy = (\n table: AnyTable,\n orderBy: [AnyColumn, \"asc\" | \"desc\"][],\n): string | null => {\n if (orderBy.length === 0) {\n return null;\n }\n\n const direction = orderBy[0]?.[1];\n if (!direction || orderBy.some(([, dir]) => dir !== direction)) {\n return null;\n }\n\n const orderColumns = orderBy.map(([column]) => column.name);\n const idColumn = table.getIdColumn();\n if (orderColumns.length === 1 && orderColumns[0] === idColumn.name) {\n return \"primary\";\n }\n\n for (const [indexName, index] of Object.entries(table.indexes)) {\n const indexColumns = index.columns.map((column) => column.name);\n if (\n indexColumns.length === orderColumns.length &&\n indexColumns.every((name, idx) => name === orderColumns[idx])\n ) {\n return indexName;\n }\n }\n\n return null;\n};\n\nconst applyCompiledJoins = (\n builder: IndexedJoinBuilder<AnyTable, {}>,\n joins: CompiledJoin[] | undefined,\n): IndexedJoinBuilder<AnyTable, {}> => {\n if (!joins || joins.length === 0) {\n return builder;\n }\n\n let current: Record<string, unknown> = builder as Record<string, unknown>;\n\n for (const join of joins) {\n if (join.options === false) {\n continue;\n }\n const joinOptions = join.options;\n\n const relationName = join.relation.name;\n const relationBuilder = current[relationName];\n if (typeof relationBuilder !== \"function\") {\n continue;\n }\n\n current = relationBuilder((joinBuilder: JoinFindBuilder<AnyTable>) => {\n if (joinOptions.select && joinOptions.select !== true) {\n joinBuilder.select(joinOptions.select as unknown as true | string[]);\n }\n\n if (joinOptions.where) {\n joinBuilder.whereIndex(\"primary\", () => joinOptions.where as Condition);\n }\n\n if (joinOptions.orderBy && joinOptions.orderBy.length > 0) {\n const indexName = resolveIndexNameFromOrderBy(join.relation.table, joinOptions.orderBy);\n const direction = joinOptions.orderBy[0][1];\n if (indexName) {\n joinBuilder.orderByIndex(indexName as \"primary\" | string, direction);\n }\n }\n\n if (joinOptions.limit !== undefined) {\n joinBuilder.pageSize(joinOptions.limit);\n }\n\n if (joinOptions.join && joinOptions.join.length > 0) {\n joinBuilder.join((nestedBuilder) => applyCompiledJoins(nestedBuilder, joinOptions.join));\n }\n\n return joinBuilder;\n }) as Record<string, unknown>;\n }\n\n return current as IndexedJoinBuilder<AnyTable, {}>;\n};\n\nconst applyFindOptionsToBuilder = (\n builder: Omit<FindBuilder<AnyTable>, \"build\">,\n operation: LocalRetrievalOperation,\n): void => {\n const useIndex = normalizeIndexName(\n operation.type === \"count\" ? operation.indexName : operation.options.useIndex,\n ) as \"primary\" | string;\n if (operation.options.where) {\n if (typeof operation.options.where === \"function\") {\n builder.whereIndex(useIndex, operation.options.where as () => Condition);\n } else {\n builder.whereIndex(useIndex, () => operation.options.where as Condition);\n }\n } else {\n builder.whereIndex(useIndex);\n }\n\n if (operation.type === \"count\") {\n builder.selectCount();\n return;\n }\n\n if (operation.options.select && operation.options.select !== true) {\n builder.select(operation.options.select as unknown as true | string[]);\n }\n\n if (operation.options.orderByIndex) {\n builder.orderByIndex(\n normalizeIndexName(operation.options.orderByIndex.indexName) as \"primary\" | string,\n operation.options.orderByIndex.direction,\n );\n }\n\n if (operation.options.after) {\n builder.after(operation.options.after);\n }\n\n if (operation.options.before) {\n builder.before(operation.options.before);\n }\n\n if (operation.options.pageSize !== undefined) {\n builder.pageSize(operation.options.pageSize);\n }\n\n if (operation.options.joins && operation.options.joins.length > 0) {\n builder.join((joinBuilder) => applyCompiledJoins(joinBuilder, operation.options.joins));\n }\n};\n\nconst executeQueryEngineRetrievalOperation = async (\n operation: LocalRetrievalOperation,\n query: LofiQueryInterface<AnySchema>,\n): Promise<unknown> => {\n const tableName = operation.table.name;\n const builderFn = (builder: Omit<FindBuilder<AnyTable>, \"build\">) => {\n applyFindOptionsToBuilder(builder, operation);\n return builder;\n };\n\n if (operation.type === \"count\") {\n return (query.find as unknown as typeof query.find)(tableName, builderFn);\n }\n\n if (operation.withCursor) {\n return (query.findWithCursor as unknown as typeof query.findWithCursor)(tableName, builderFn);\n }\n\n return (query.find as unknown as typeof query.find)(tableName, builderFn);\n};\n\nconst getRowVersion = async <TContext>(\n executor: LocalHandlerQueryExecutor<TContext>,\n schema: AnySchema,\n table: AnyTable,\n externalId: string,\n): Promise<number | null> => {\n const context = resolveQueryContext(executor, schema);\n const result = await executor.executeRetrievalOperation({\n operation: {\n type: \"find\",\n table,\n indexName: \"_primary\",\n options: {\n useIndex: \"_primary\",\n where: buildFindKeyCondition(table, externalId),\n pageSize: 1,\n },\n withCursor: false,\n },\n context,\n });\n\n if (!Array.isArray(result) || result.length === 0) {\n return null;\n }\n\n const idColumn = table.getIdColumn();\n const row = result[0] as Record<string, unknown>;\n const idValue = row[idColumn.name];\n if (idValue && typeof idValue === \"object\" && \"version\" in idValue) {\n return (idValue as FragnoId).version;\n }\n\n return null;\n};\n\nconst validateMutationChecks = async <TContext>(\n executor: LocalHandlerQueryExecutor<TContext>,\n mutationBatch: CompiledMutation<LocalCompiledOperation>[],\n): Promise<boolean> => {\n for (const mutation of mutationBatch) {\n const operation = mutation.operation;\n if (!operation || !isMutationOperation(operation)) {\n continue;\n }\n\n if (operation.type === \"check\") {\n const externalId = getExternalId(operation.id);\n const version = operation.id instanceof FragnoId ? operation.id.version : undefined;\n if (version === undefined) {\n return false;\n }\n const currentVersion = await getRowVersion(\n executor,\n operation.schema,\n operation.schema.tables[operation.table],\n externalId,\n );\n if (currentVersion === null || currentVersion !== version) {\n return false;\n }\n continue;\n }\n\n if ((operation.type === \"update\" || operation.type === \"delete\") && operation.checkVersion) {\n const externalId = getExternalId(operation.id);\n const version = operation.id instanceof FragnoId ? operation.id.version : undefined;\n if (version === undefined) {\n return false;\n }\n const currentVersion = await getRowVersion(\n executor,\n operation.schema,\n operation.schema.tables[operation.table],\n externalId,\n );\n if (currentVersion === null || currentVersion !== version) {\n return false;\n }\n }\n }\n\n return true;\n};\n\nconst collectCreatedInternalIds = async <TContext>(\n executor: LocalHandlerQueryExecutor<TContext>,\n mutationBatch: CompiledMutation<LocalCompiledOperation>[],\n): Promise<(bigint | null)[]> => {\n const created: (bigint | null)[] = [];\n\n for (const mutation of mutationBatch) {\n const operation = mutation.operation;\n if (!operation || operation.type !== \"create\") {\n continue;\n }\n\n const table = operation.schema.tables[operation.table];\n const context = resolveQueryContext(executor, operation.schema);\n const result = await executor.executeRetrievalOperation({\n operation: {\n type: \"find\",\n table,\n indexName: \"_primary\",\n options: {\n useIndex: \"_primary\",\n where: buildFindKeyCondition(table, operation.generatedExternalId),\n pageSize: 1,\n },\n withCursor: false,\n },\n context,\n });\n\n const row = Array.isArray(result) ? result[0] : undefined;\n if (!row) {\n created.push(null);\n continue;\n }\n\n const idColumn = table.getIdColumn();\n const idValue = (row as Record<string, unknown>)[idColumn.name];\n if (idValue && typeof idValue === \"object\" && \"internalId\" in idValue) {\n const internalId = (idValue as FragnoId).internalId;\n created.push(internalId ?? null);\n } else {\n created.push(null);\n }\n }\n\n return created;\n};\n\nexport const createLocalHandlerTx = <TContext>(\n options: LocalHandlerTxOptions<TContext>,\n): LocalHandlerTxFactory => {\n const schemaMap = new Map<string, AnySchema>();\n const schemaNamespaceMap = new WeakMap<AnySchema, string | null>();\n for (const schema of options.schemas) {\n schemaMap.set(schema.name, schema);\n schemaNamespaceMap.set(schema, schema.name);\n }\n\n const queryExecutor: LocalHandlerQueryExecutor<TContext> =\n options.queryExecutor ??\n (() => {\n const createQueryEngine = options.adapter.createQueryEngine?.bind(options.adapter);\n if (createQueryEngine) {\n const cache = new Map<string, LofiQueryInterface<AnySchema>>();\n return {\n createQueryContext: (schemaName: string) => {\n const cached = cache.get(schemaName);\n if (cached) {\n return cached as unknown as TContext;\n }\n const schema = schemaMap.get(schemaName);\n if (!schema) {\n throw new Error(`Local handler tx missing schema: ${schemaName}`);\n }\n const engine = createQueryEngine(schema, { schemaName });\n cache.set(schemaName, engine);\n return engine as unknown as TContext;\n },\n executeRetrievalOperation: async ({\n operation,\n context,\n }: {\n operation: LocalRetrievalOperation;\n context: LofiQueryInterface<AnySchema>;\n }) => await executeQueryEngineRetrievalOperation(operation, context),\n } as unknown as LocalHandlerQueryExecutor<TContext>;\n }\n if (!options.adapter.createQueryContext) {\n throw new Error(\n \"Local handler tx requires a queryExecutor, adapter.createQueryEngine(), or adapter.createQueryContext().\",\n );\n }\n return {\n createQueryContext: options.adapter.createQueryContext.bind(options.adapter),\n executeRetrievalOperation: executeIndexedDbRetrievalOperation,\n } as unknown as LocalHandlerQueryExecutor<TContext>;\n })();\n\n const compiler: UOWCompiler<LocalCompiledOperation> = {\n compileRetrievalOperation(op: RetrievalOperation<AnySchema>): LocalCompiledOperation | null {\n return op;\n },\n compileMutationOperation(\n op: MutationOperation<AnySchema>,\n ): CompiledMutation<LocalCompiledOperation> | null {\n return {\n query: op,\n operation: op,\n op: op.type,\n expectedAffectedRows: null,\n expectedReturnedRows: null,\n };\n },\n };\n\n const executor: UOWExecutor<LocalCompiledOperation, unknown> = {\n async executeRetrievalPhase(retrievalBatch: LocalCompiledOperation[]): Promise<unknown[]> {\n const results: unknown[] = [];\n\n for (const compiled of retrievalBatch) {\n if (!isFindOrCount(compiled)) {\n throw new Error(`Unsupported local retrieval operation: ${compiled.type}`);\n }\n\n const context = resolveQueryContext(queryExecutor, compiled.schema);\n const result = await queryExecutor.executeRetrievalOperation({\n operation:\n compiled.type === \"count\"\n ? {\n type: \"count\",\n table: compiled.table,\n indexName: compiled.indexName,\n options: { where: compiled.options.where },\n }\n : {\n type: \"find\",\n table: compiled.table,\n indexName: compiled.indexName,\n options: compiled.options,\n withCursor: compiled.withCursor ?? false,\n },\n context,\n });\n\n results.push(result);\n }\n\n return results;\n },\n\n async executeMutationPhase(mutationBatch: CompiledMutation<LocalCompiledOperation>[]) {\n if (mutationBatch.length === 0) {\n return { success: true, createdInternalIds: [] };\n }\n\n const checksOk = await validateMutationChecks(queryExecutor, mutationBatch);\n if (!checksOk) {\n return { success: false };\n }\n\n if (!options.adapter.applyMutations) {\n throw new Error(\"Lofi adapter does not support applyMutations.\");\n }\n\n const txVersionstamp = createLocalVersionstamp();\n const mutations: LofiMutation[] = [];\n for (const compiled of mutationBatch) {\n const operation = compiled.operation;\n if (!operation || !isMutationOperation(operation)) {\n continue;\n }\n\n const mutation = buildLocalMutation(operation, txVersionstamp);\n if (mutation) {\n mutations.push(mutation);\n }\n }\n\n if (mutations.length > 0) {\n await options.adapter.applyMutations(mutations);\n }\n\n const createdInternalIds = await collectCreatedInternalIds(queryExecutor, mutationBatch);\n return { success: true, createdInternalIds };\n },\n };\n\n const decoder: UOWDecoder<unknown> = {\n decode(rawResults) {\n return rawResults;\n },\n };\n\n return (execOptions?: Omit<HandlerTxOptions, \"createUnitOfWork\">) =>\n createHandlerTxBuilder({\n ...execOptions,\n createUnitOfWork: () => {\n const uow = new UnitOfWork(\n compiler,\n executor,\n decoder,\n undefined,\n undefined,\n schemaNamespaceMap,\n );\n return uow;\n },\n });\n};\n\nexport const runLocalHandlerCommand = async <TInput, TContext>(options: {\n command: LocalHandlerCommandDefinition<TInput, TContext>;\n input: TInput;\n ctx: TContext;\n tx: LocalHandlerTxFactory;\n}): Promise<void> => {\n await options.command.handler({\n input: options.input,\n ctx: options.ctx,\n tx: options.tx,\n });\n};\n"],"mappings":"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"}
|
package/dist/submit/queue.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.js","names":[],"sources":["../../src/submit/queue.ts"],"sourcesContent":["import superjson from \"superjson\";\nimport type { LofiAdapter, LofiSubmitCommand } from \"../types\";\n\nexport type SubmitQueue = LofiSubmitCommand[];\n\nexport const defaultQueueKey = (endpointName: string) => `${endpointName}::submit-queue`;\n\nexport const buildCommandKey = (command: {\n target: { fragment: string; schema: string };\n name: string;\n}): string => `${command.target.fragment}::${command.target.schema}::${command.name}`;\n\nexport const loadSubmitQueue = async (\n adapter: Pick<LofiAdapter, \"getMeta\">,\n key: string,\n): Promise<SubmitQueue> => {\n const raw = await adapter.getMeta(key);\n if (!raw) {\n return [];\n }\n\n try {\n const parsed = superjson.deserialize(JSON.parse(raw));\n return Array.isArray(parsed) ? (parsed as SubmitQueue) : [];\n } catch {\n return [];\n }\n};\n\nexport const storeSubmitQueue = async (\n adapter: Pick<LofiAdapter, \"setMeta\">,\n key: string,\n queue: SubmitQueue,\n): Promise<void> => {\n const serialized = superjson.serialize(queue);\n await adapter.setMeta(key, JSON.stringify(serialized));\n};\n"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"queue.js","names":[],"sources":["../../src/submit/queue.ts"],"sourcesContent":["import superjson from \"superjson\";\n\nimport type { LofiAdapter, LofiSubmitCommand } from \"../types\";\n\nexport type SubmitQueue = LofiSubmitCommand[];\n\nexport const defaultQueueKey = (endpointName: string) => `${endpointName}::submit-queue`;\n\nexport const buildCommandKey = (command: {\n target: { fragment: string; schema: string };\n name: string;\n}): string => `${command.target.fragment}::${command.target.schema}::${command.name}`;\n\nexport const loadSubmitQueue = async (\n adapter: Pick<LofiAdapter, \"getMeta\">,\n key: string,\n): Promise<SubmitQueue> => {\n const raw = await adapter.getMeta(key);\n if (!raw) {\n return [];\n }\n\n try {\n const parsed = superjson.deserialize(JSON.parse(raw));\n return Array.isArray(parsed) ? (parsed as SubmitQueue) : [];\n } catch {\n return [];\n }\n};\n\nexport const storeSubmitQueue = async (\n adapter: Pick<LofiAdapter, \"setMeta\">,\n key: string,\n queue: SubmitQueue,\n): Promise<void> => {\n const serialized = superjson.serialize(queue);\n await adapter.setMeta(key, JSON.stringify(serialized));\n};\n"],"mappings":";;;AAMA,MAAa,mBAAmB,iBAAyB,GAAG,aAAa;AAEzE,MAAa,mBAAmB,YAGlB,GAAG,QAAQ,OAAO,SAAS,IAAI,QAAQ,OAAO,OAAO,IAAI,QAAQ;AAE/E,MAAa,kBAAkB,OAC7B,SACA,QACyB;CACzB,MAAM,MAAM,MAAM,QAAQ,QAAQ,IAAI;AACtC,KAAI,CAAC,IACH,QAAO,EAAE;AAGX,KAAI;EACF,MAAM,SAAS,UAAU,YAAY,KAAK,MAAM,IAAI,CAAC;AACrD,SAAO,MAAM,QAAQ,OAAO,GAAI,SAAyB,EAAE;SACrD;AACN,SAAO,EAAE;;;AAIb,MAAa,mBAAmB,OAC9B,SACA,KACA,UACkB;CAClB,MAAM,aAAa,UAAU,UAAU,MAAM;AAC7C,OAAM,QAAQ,QAAQ,KAAK,KAAK,UAAU,WAAW,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rebase.d.ts","names":[],"sources":["../../src/submit/rebase.ts"],"sourcesContent":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"rebase.d.ts","names":[],"sources":["../../src/submit/rebase.ts"],"sourcesContent":[],"mappings":";;;;KAKY,YAAA;;EAAA,gBAAY,CAAA,EAAA,MAAA;EAyCX,KAAA,EAtCJ,iBAwER,EAAA;CAjCU;AACA,cAFE,kBAEF,EAAA,CAAA,OAAA,EAAA;EAGP,OAAA,EAJO,WAIP;EAAO,OAAA,EAHA,WAGA,EAAA;EA+BE,SAAA,EAAA,MAAA;EACF,SAAA,CAAA,EAAA,MAAA;CACA,EAAA,GAjCP,OAiCO,CAAA;EAGF,cAAA,EAAA,MAAA;EAEyB,gBAAA,CAAA,EAAA,MAAA;CAAkD,CAAA;AAExE,cATC,iBASD,EAAA,CAAA,OAAA,EAAA;EAAR,OAAA,EARO,WAQP;EAAO,OAAA,EAPA,WAOA,EAAA;;;SAJF;;;cAEyB;;UAAkD;;MAEhF,QAAQ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rebase.js","names":["lastVersionstamp: string | undefined","remaining: LofiSubmitCommand[]"],"sources":["../../src/submit/rebase.ts"],"sourcesContent":["import type { OutboxEntry } from \"@fragno-dev/db\";\nimport { decodeOutboxPayload, resolveOutboxRefs } from \"../outbox\";\nimport type { LofiAdapter, LofiMutation, LofiSubmitCommand } from \"../types\";\n\nexport type RebaseResult = {\n appliedEntries: number;\n lastVersionstamp?: string;\n queue: LofiSubmitCommand[];\n};\n\nconst decodeEntryMutations = (entry: OutboxEntry): LofiMutation[] => {\n const payload = decodeOutboxPayload(entry.payload);\n return payload.mutations.map((mutation) => {\n if (mutation.op === \"create\") {\n return {\n op: \"create\",\n schema: mutation.schema,\n table: mutation.table,\n externalId: mutation.externalId,\n values: mutation.values,\n versionstamp: mutation.versionstamp,\n };\n }\n\n if (mutation.op === \"update\") {\n return {\n op: \"update\",\n schema: mutation.schema,\n table: mutation.table,\n externalId: mutation.externalId,\n set: mutation.set,\n versionstamp: mutation.versionstamp,\n };\n }\n\n return {\n op: \"delete\",\n schema: mutation.schema,\n table: mutation.table,\n externalId: mutation.externalId,\n versionstamp: mutation.versionstamp,\n };\n });\n};\n\nexport const applyOutboxEntries = async (options: {\n adapter: LofiAdapter;\n entries: OutboxEntry[];\n cursorKey: string;\n sourceKey?: string;\n}): Promise<{ appliedEntries: number; lastVersionstamp?: string }> => {\n const { adapter, entries, cursorKey } = options;\n const sourceKey = options.sourceKey ?? cursorKey;\n\n let appliedEntries = 0;\n let lastVersionstamp: string | undefined;\n\n for (const entry of entries) {\n const mutations = decodeEntryMutations(entry);\n const resolvedMutations = entry.refMap\n ? mutations.map((mutation) => resolveOutboxRefs(mutation, entry.refMap ?? {}))\n : mutations;\n\n const result = await adapter.applyOutboxEntry({\n sourceKey,\n versionstamp: entry.versionstamp,\n uowId: entry.uowId,\n mutations: resolvedMutations,\n });\n\n lastVersionstamp = entry.versionstamp;\n await adapter.setMeta(cursorKey, entry.versionstamp);\n\n if (result.applied) {\n appliedEntries += 1;\n }\n }\n\n return { appliedEntries, lastVersionstamp };\n};\n\nexport const rebaseSubmitQueue = async (options: {\n adapter: LofiAdapter;\n entries: OutboxEntry[];\n cursorKey: string;\n confirmedCommandIds: string[];\n queue: LofiSubmitCommand[];\n overlay?: {\n rebuild: (options?: { queue?: LofiSubmitCommand[]; schemaNames?: string[] }) => Promise<void>;\n };\n}): Promise<RebaseResult> => {\n const { adapter, entries, cursorKey, confirmedCommandIds, queue, overlay } = options;\n\n const { appliedEntries, lastVersionstamp } = await applyOutboxEntries({\n adapter,\n entries,\n cursorKey,\n });\n\n const confirmedSet = new Set(confirmedCommandIds);\n const remaining: LofiSubmitCommand[] = [];\n\n for (const command of queue) {\n if (confirmedSet.has(command.id)) {\n continue;\n }\n remaining.push(command);\n }\n\n if (overlay) {\n await overlay.rebuild({ queue: remaining });\n }\n\n return { appliedEntries, lastVersionstamp, queue: remaining };\n};\n"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"rebase.js","names":["lastVersionstamp: string | undefined","remaining: LofiSubmitCommand[]"],"sources":["../../src/submit/rebase.ts"],"sourcesContent":["import type { OutboxEntry } from \"@fragno-dev/db\";\n\nimport { decodeOutboxPayload, resolveOutboxRefs } from \"../outbox\";\nimport type { LofiAdapter, LofiMutation, LofiSubmitCommand } from \"../types\";\n\nexport type RebaseResult = {\n appliedEntries: number;\n lastVersionstamp?: string;\n queue: LofiSubmitCommand[];\n};\n\nconst decodeEntryMutations = (entry: OutboxEntry): LofiMutation[] => {\n const payload = decodeOutboxPayload(entry.payload);\n return payload.mutations.map((mutation) => {\n if (mutation.op === \"create\") {\n return {\n op: \"create\",\n schema: mutation.schema,\n table: mutation.table,\n externalId: mutation.externalId,\n values: mutation.values,\n versionstamp: mutation.versionstamp,\n };\n }\n\n if (mutation.op === \"update\") {\n return {\n op: \"update\",\n schema: mutation.schema,\n table: mutation.table,\n externalId: mutation.externalId,\n set: mutation.set,\n versionstamp: mutation.versionstamp,\n };\n }\n\n return {\n op: \"delete\",\n schema: mutation.schema,\n table: mutation.table,\n externalId: mutation.externalId,\n versionstamp: mutation.versionstamp,\n };\n });\n};\n\nexport const applyOutboxEntries = async (options: {\n adapter: LofiAdapter;\n entries: OutboxEntry[];\n cursorKey: string;\n sourceKey?: string;\n}): Promise<{ appliedEntries: number; lastVersionstamp?: string }> => {\n const { adapter, entries, cursorKey } = options;\n const sourceKey = options.sourceKey ?? cursorKey;\n\n let appliedEntries = 0;\n let lastVersionstamp: string | undefined;\n\n for (const entry of entries) {\n const mutations = decodeEntryMutations(entry);\n const resolvedMutations = entry.refMap\n ? mutations.map((mutation) => resolveOutboxRefs(mutation, entry.refMap ?? {}))\n : mutations;\n\n const result = await adapter.applyOutboxEntry({\n sourceKey,\n versionstamp: entry.versionstamp,\n uowId: entry.uowId,\n mutations: resolvedMutations,\n });\n\n lastVersionstamp = entry.versionstamp;\n await adapter.setMeta(cursorKey, entry.versionstamp);\n\n if (result.applied) {\n appliedEntries += 1;\n }\n }\n\n return { appliedEntries, lastVersionstamp };\n};\n\nexport const rebaseSubmitQueue = async (options: {\n adapter: LofiAdapter;\n entries: OutboxEntry[];\n cursorKey: string;\n confirmedCommandIds: string[];\n queue: LofiSubmitCommand[];\n overlay?: {\n rebuild: (options?: { queue?: LofiSubmitCommand[]; schemaNames?: string[] }) => Promise<void>;\n };\n}): Promise<RebaseResult> => {\n const { adapter, entries, cursorKey, confirmedCommandIds, queue, overlay } = options;\n\n const { appliedEntries, lastVersionstamp } = await applyOutboxEntries({\n adapter,\n entries,\n cursorKey,\n });\n\n const confirmedSet = new Set(confirmedCommandIds);\n const remaining: LofiSubmitCommand[] = [];\n\n for (const command of queue) {\n if (confirmedSet.has(command.id)) {\n continue;\n }\n remaining.push(command);\n }\n\n if (overlay) {\n await overlay.rebuild({ queue: remaining });\n }\n\n return { appliedEntries, lastVersionstamp, queue: remaining };\n};\n"],"mappings":";;;;;AAWA,MAAM,wBAAwB,UAAuC;AAEnE,QADgB,oBAAoB,MAAM,QAAQ,CACnC,UAAU,KAAK,aAAa;AACzC,MAAI,SAAS,OAAO,SAClB,QAAO;GACL,IAAI;GACJ,QAAQ,SAAS;GACjB,OAAO,SAAS;GAChB,YAAY,SAAS;GACrB,QAAQ,SAAS;GACjB,cAAc,SAAS;GACxB;AAGH,MAAI,SAAS,OAAO,SAClB,QAAO;GACL,IAAI;GACJ,QAAQ,SAAS;GACjB,OAAO,SAAS;GAChB,YAAY,SAAS;GACrB,KAAK,SAAS;GACd,cAAc,SAAS;GACxB;AAGH,SAAO;GACL,IAAI;GACJ,QAAQ,SAAS;GACjB,OAAO,SAAS;GAChB,YAAY,SAAS;GACrB,cAAc,SAAS;GACxB;GACD;;AAGJ,MAAa,qBAAqB,OAAO,YAK6B;CACpE,MAAM,EAAE,SAAS,SAAS,cAAc;CACxC,MAAM,YAAY,QAAQ,aAAa;CAEvC,IAAI,iBAAiB;CACrB,IAAIA;AAEJ,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,YAAY,qBAAqB,MAAM;EAC7C,MAAM,oBAAoB,MAAM,SAC5B,UAAU,KAAK,aAAa,kBAAkB,UAAU,MAAM,UAAU,EAAE,CAAC,CAAC,GAC5E;EAEJ,MAAM,SAAS,MAAM,QAAQ,iBAAiB;GAC5C;GACA,cAAc,MAAM;GACpB,OAAO,MAAM;GACb,WAAW;GACZ,CAAC;AAEF,qBAAmB,MAAM;AACzB,QAAM,QAAQ,QAAQ,WAAW,MAAM,aAAa;AAEpD,MAAI,OAAO,QACT,mBAAkB;;AAItB,QAAO;EAAE;EAAgB;EAAkB;;AAG7C,MAAa,oBAAoB,OAAO,YASX;CAC3B,MAAM,EAAE,SAAS,SAAS,WAAW,qBAAqB,OAAO,YAAY;CAE7E,MAAM,EAAE,gBAAgB,qBAAqB,MAAM,mBAAmB;EACpE;EACA;EACA;EACD,CAAC;CAEF,MAAM,eAAe,IAAI,IAAI,oBAAoB;CACjD,MAAMC,YAAiC,EAAE;AAEzC,MAAK,MAAM,WAAW,OAAO;AAC3B,MAAI,aAAa,IAAI,QAAQ,GAAG,CAC9B;AAEF,YAAU,KAAK,QAAQ;;AAGzB,KAAI,QACF,OAAM,QAAQ,QAAQ,EAAE,OAAO,WAAW,CAAC;AAG7C,QAAO;EAAE;EAAgB;EAAkB,OAAO;EAAW"}
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;;;;;KAQY,iBAAA;EAAA,SAAA,EAAA,MAAA;EAGD,YAAA,EAAA,MAAA;EACM,OAAA,EADN,WACM;EAIU,KAAA,CAAA,EAAA,OAJV,KAIU;EAA0B,cAAA,CAAA,EAAA,MAAA;EAE1C,KAAA,CAAA,EAAA,MAAA;EAAW,SAAA,CAAA,EAAA,MAAA;EAGV,aAAA,CAAA,EAAA,CAAc,MAAA,EALC,cAKD,EAAA,GAAA,IAAA,GAL2B,OAK3B,CAAA,IAAA,CAAA;EAKd,OAAA,CAAA,EAAA,CAAA,KAAA,EAAA,OAAsB,EAAA,GAAA,IAAA;EAEtB,MAAA,CAAA,EAVD,WAUY;CAKR;AACT,KAbM,cAAA,GAaN;EACuB,cAAA,EAAA,MAAA;EAAiB,gBAAA,CAAA,EAAA,MAAA;CACtB;AACe,KAX3B,sBAAA,GAW2B;EAAO,MAAA,EAXC,SAWD;AAG9C,CAAA;AAOY,KAnBA,WAAA,GAmBA;EAOA,gBAAA,CAAA,OAAkB,EAAA;IAAiB,SAAA,EAAA,MAAA;IAClB,YAAA,EAAA,MAAA;IAArB,KAAA,EAAA,MAAA;IAC0B,SAAA,EAvBnB,YAuBmB,EAAA;EAArB,CAAA,CAAA,EAtBP,OAsBO,CAAA;IAC0B,OAAA,EAAA,OAAA;EAArB,CAAA,CAAA;EAAoB,cAAA,EAAA,SAAA,EAtBT,YAsBS,EAAA,CAAA,EAtBQ,OAsBR,CAAA,IAAA,CAAA;EAG1B,OAAA,CAAA,GAAA,EAAA,MAAA,CAAA,EAxBY,OAwBU,CAAA,MAAA,GAAA,SAAA,CAAA;EAIjB,OAAA,CAAA,GAAA,EAAA,MAAA,EAAA,KAAoB,EAAA,MAAA,CAAA,EA3BE,OA2BF,CAAA,IAAA,CAAA;CACD;AACxB,KA1BA,uBAAA,GA0BA;EACE,MAAA,CAAA,EAAA,MAAA;EACU,YAAA,EAAA,MAAA;EAAnB,OAAA,EAzBM,sBAyBN,EAAA;EAAkB,oBAAA,CAAA,EAAA,OAAA;AAGvB,CAAA;AAKY,KA7BA,0BAAA,GAgCF;EAIE,YAAA,EAAA,MAAA;EAgBA,OAAA,EAlDD,SAkDC,EAAA;EAQA,oBAAA,CAAA,EAAA,OAA0B;EAU1B,KAAA,CAAA,EAlEF,iBAkEoB;AAA0D,CAAA;AAI5E,KAnEA,kBAmEA,CAAwB,gBAnEW,SAmEX,CAAA,GAAA;EACnB,IAAA,EAnET,oBAmES,CAnEY,OAmEZ,CAAA,CAAA,MAAA,CAAA;EAAL,SAAA,EAlEC,oBAkED,CAlEsB,OAkEtB,CAAA,CAAA,WAAA,CAAA;EACP,cAAA,EAlEa,oBAkEb,CAlEkC,OAkElC,CAAA,CAAA,gBAAA,CAAA;CAAgB;AAET,KAjEA,sBAAA,GAiE2B;EAE7B,UAAA,CAAA,EAAA,MAAA;CAEC;AACH,UAlES,oBAAA,CAkET;EACC,iBAAA,CAAA,gBAlE2B,SAkE3B,CAAA,CAAA,MAAA,EAjEG,CAiEH,EAAA,OAAA,CAAA,EAhEK,sBAgEL,CAAA,EA/DJ,kBA+DI,CA/De,CA+Df,CAAA;;AACM,KA7DH,uBAAA,GA6DG;EAGH,QAAA,EAAA,MAAY;;;KA3DZ,iBAAA;;;UAGF;;;KAIE,wBAAA;KAgBA,yBAAA;;;;;WAKD;;KAGC,0BAAA;;;;;;WAMD;UACD;;KAGE,kBAAA,GAAqB,4BAA4B;KAExD,gBAAA,GAAmB,kBAAkB;KAE9B,wBAAA,cACA,KAAK,0CACZ;KAEO;;UAEF;;WAEC;QACH;SACC;QACD;;KAGI,YAAA;;;;;UAME;;;;;;;OAQH"}
|
package/package.json
CHANGED
|
@@ -1,64 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fragno-dev/lofi",
|
|
3
|
+
"version": "0.0.3",
|
|
3
4
|
"description": "Fragno local-first client",
|
|
4
|
-
"
|
|
5
|
+
"homepage": "https://fragno.dev",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/rejot-dev/fragno.git",
|
|
10
|
+
"directory": "packages/lofi"
|
|
11
|
+
},
|
|
12
|
+
"bin": {
|
|
13
|
+
"fragno-lofi": "./bin/run.js"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"bin"
|
|
18
|
+
],
|
|
5
19
|
"type": "module",
|
|
6
20
|
"main": "./dist/mod.js",
|
|
7
21
|
"module": "./dist/mod.js",
|
|
8
22
|
"types": "./dist/mod.d.ts",
|
|
9
23
|
"exports": {
|
|
10
24
|
".": {
|
|
11
|
-
"development": "./src/mod.ts",
|
|
12
25
|
"types": "./dist/mod.d.ts",
|
|
13
26
|
"default": "./dist/mod.js"
|
|
14
27
|
},
|
|
15
28
|
"./cli": {
|
|
16
|
-
"development": "./src/cli/index.ts",
|
|
17
29
|
"types": "./dist/cli/index.d.ts",
|
|
18
30
|
"default": "./dist/cli/index.js"
|
|
19
31
|
},
|
|
20
32
|
"./scenario": {
|
|
21
|
-
"development": "./src/scenario.ts",
|
|
22
33
|
"types": "./dist/scenario.d.ts",
|
|
23
34
|
"default": "./dist/scenario.js"
|
|
24
35
|
}
|
|
25
36
|
},
|
|
26
|
-
"files": [
|
|
27
|
-
"dist",
|
|
28
|
-
"bin"
|
|
29
|
-
],
|
|
30
|
-
"bin": {
|
|
31
|
-
"fragno-lofi": "./bin/run.js"
|
|
32
|
-
},
|
|
33
37
|
"dependencies": {
|
|
34
38
|
"fake-indexeddb": "^6.1.0",
|
|
35
39
|
"gunshi": "^0.26.3",
|
|
36
40
|
"idb": "^8.0.3",
|
|
37
41
|
"superjson": "^2.2.1",
|
|
38
|
-
"@fragno-dev/
|
|
39
|
-
"@fragno-dev/
|
|
40
|
-
"@fragno-dev/
|
|
42
|
+
"@fragno-dev/core": "0.2.2",
|
|
43
|
+
"@fragno-dev/db": "0.4.1",
|
|
44
|
+
"@fragno-dev/node": "0.0.9"
|
|
41
45
|
},
|
|
42
46
|
"devDependencies": {
|
|
43
47
|
"@types/node": "^22.19.7",
|
|
44
|
-
"@vitest/coverage-istanbul": "^
|
|
48
|
+
"@vitest/coverage-istanbul": "^4.1.0",
|
|
45
49
|
"tsdown": "^0.15.12",
|
|
46
|
-
"vitest": "^
|
|
47
|
-
"@fragno-private/
|
|
48
|
-
"@fragno-private/
|
|
50
|
+
"vitest": "^4.1.4",
|
|
51
|
+
"@fragno-private/typescript-config": "0.0.1",
|
|
52
|
+
"@fragno-private/vitest-config": "0.0.0"
|
|
49
53
|
},
|
|
50
|
-
"repository": {
|
|
51
|
-
"type": "git",
|
|
52
|
-
"url": "https://github.com/rejot-dev/fragno.git",
|
|
53
|
-
"directory": "packages/lofi"
|
|
54
|
-
},
|
|
55
|
-
"homepage": "https://fragno.dev",
|
|
56
|
-
"license": "MIT",
|
|
57
54
|
"scripts": {
|
|
58
55
|
"build": "tsdown",
|
|
59
56
|
"build:watch": "tsdown --watch",
|
|
60
57
|
"lint": "oxlint .",
|
|
61
|
-
"types:check": "
|
|
58
|
+
"types:check": "tsgo --noEmit",
|
|
62
59
|
"test": "vitest run",
|
|
63
60
|
"test:watch": "vitest --watch"
|
|
64
61
|
}
|