@rocicorp/zero 0.25.0-canary.12 → 0.25.0-canary.14
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/out/zero/package.json.js +1 -1
- package/out/zero/src/pg.js +4 -2
- package/out/zero/src/server.js +4 -2
- package/out/zero-cache/src/config/zero-config.d.ts +0 -4
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +5 -15
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +2 -8
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/otel-diag-logger.js +1 -0
- package/out/zero-cache/src/server/otel-diag-logger.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js +62 -42
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/control.d.ts +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current/control.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/control.js +5 -1
- package/out/zero-cache/src/services/change-source/protocol/current/control.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +2 -0
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/json.d.ts +8 -0
- package/out/zero-cache/src/services/change-source/protocol/current/json.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current/json.js +19 -0
- package/out/zero-cache/src/services/change-source/protocol/current/json.js.map +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current.d.ts +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current.js +3 -0
- package/out/zero-cache/src/services/change-source/protocol/current.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +0 -2
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +0 -5
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +8 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +2 -3
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/http-service.d.ts +0 -1
- package/out/zero-cache/src/services/http-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/http-service.js +0 -4
- package/out/zero-cache/src/services/http-service.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.d.ts +2 -0
- package/out/zero-cache/src/services/replicator/replication-status.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.js +14 -1
- package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
- package/out/zero-client/src/client/connection-manager.d.ts +3 -3
- package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/connection-manager.js.map +1 -1
- package/out/zero-client/src/client/connection.d.ts.map +1 -1
- package/out/zero-client/src/client/connection.js +8 -1
- package/out/zero-client/src/client/connection.js.map +1 -1
- package/out/zero-client/src/client/custom.d.ts.map +1 -1
- package/out/zero-client/src/client/custom.js +4 -3
- package/out/zero-client/src/client/custom.js.map +1 -1
- package/out/zero-client/src/client/error.d.ts +6 -1
- package/out/zero-client/src/client/error.d.ts.map +1 -1
- package/out/zero-client/src/client/error.js +2 -2
- package/out/zero-client/src/client/error.js.map +1 -1
- package/out/zero-client/src/client/make-mutate-property.d.ts +6 -9
- package/out/zero-client/src/client/make-mutate-property.d.ts.map +1 -1
- package/out/zero-client/src/client/make-mutate-property.js +3 -8
- package/out/zero-client/src/client/make-mutate-property.js.map +1 -1
- package/out/zero-client/src/client/mutator-proxy.d.ts +3 -2
- package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
- package/out/zero-client/src/client/mutator-proxy.js +15 -3
- package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +8 -8
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-events/src/status.d.ts +1 -1
- package/out/zero-events/src/status.d.ts.map +1 -1
- package/out/zero-schema/src/permissions.d.ts +3 -0
- package/out/zero-schema/src/permissions.d.ts.map +1 -1
- package/out/zero-schema/src/permissions.js.map +1 -1
- package/out/zero-server/src/custom.d.ts +2 -2
- package/out/zero-server/src/custom.d.ts.map +1 -1
- package/out/zero-server/src/custom.js +40 -4
- package/out/zero-server/src/custom.js.map +1 -1
- package/out/zero-server/src/mod.d.ts +1 -1
- package/out/zero-server/src/mod.d.ts.map +1 -1
- package/out/zero-server/src/process-mutations.d.ts +10 -6
- package/out/zero-server/src/process-mutations.d.ts.map +1 -1
- package/out/zero-server/src/process-mutations.js +9 -18
- package/out/zero-server/src/process-mutations.js.map +1 -1
- package/out/zero-server/src/push-processor.d.ts.map +1 -1
- package/out/zero-server/src/push-processor.js +10 -8
- package/out/zero-server/src/push-processor.js.map +1 -1
- package/out/zero-server/src/queries/process-queries.d.ts +14 -2
- package/out/zero-server/src/queries/process-queries.d.ts.map +1 -1
- package/out/zero-server/src/queries/process-queries.js +18 -15
- package/out/zero-server/src/queries/process-queries.js.map +1 -1
- package/out/zero-server/src/zql-database.d.ts.map +1 -1
- package/out/zero-server/src/zql-database.js +1 -5
- package/out/zero-server/src/zql-database.js.map +1 -1
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js +0 -1
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/ivm/data.js +0 -11
- package/out/zql/src/ivm/data.js.map +1 -1
- package/out/zql/src/ivm/exists.d.ts +2 -2
- package/out/zql/src/ivm/exists.d.ts.map +1 -1
- package/out/zql/src/ivm/exists.js +34 -20
- package/out/zql/src/ivm/exists.js.map +1 -1
- package/out/zql/src/ivm/fan-in.d.ts +1 -1
- package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-in.js +4 -2
- package/out/zql/src/ivm/fan-in.js.map +1 -1
- package/out/zql/src/ivm/fan-out.d.ts +1 -1
- package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-out.js +9 -3
- package/out/zql/src/ivm/fan-out.js.map +1 -1
- package/out/zql/src/ivm/filter-operators.d.ts +4 -6
- package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
- package/out/zql/src/ivm/filter-operators.js +14 -27
- package/out/zql/src/ivm/filter-operators.js.map +1 -1
- package/out/zql/src/ivm/filter.d.ts +1 -1
- package/out/zql/src/ivm/filter.d.ts.map +1 -1
- package/out/zql/src/ivm/filter.js +4 -2
- package/out/zql/src/ivm/filter.js.map +1 -1
- package/out/zql/src/ivm/flipped-join.d.ts +0 -1
- package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
- package/out/zql/src/ivm/flipped-join.js +0 -2
- package/out/zql/src/ivm/flipped-join.js.map +1 -1
- package/out/zql/src/ivm/join.d.ts +2 -15
- package/out/zql/src/ivm/join.d.ts.map +1 -1
- package/out/zql/src/ivm/join.js +33 -96
- package/out/zql/src/ivm/join.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts +4 -3
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +24 -23
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/operator.d.ts +0 -12
- package/out/zql/src/ivm/operator.d.ts.map +1 -1
- package/out/zql/src/ivm/operator.js.map +1 -1
- package/out/zql/src/ivm/skip.d.ts +0 -1
- package/out/zql/src/ivm/skip.d.ts.map +1 -1
- package/out/zql/src/ivm/skip.js +3 -11
- package/out/zql/src/ivm/skip.js.map +1 -1
- package/out/zql/src/ivm/take.d.ts +0 -1
- package/out/zql/src/ivm/take.d.ts.map +1 -1
- package/out/zql/src/ivm/take.js +0 -17
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.d.ts +0 -1
- package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +0 -3
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zql/src/ivm/union-fan-out.d.ts +0 -1
- package/out/zql/src/ivm/union-fan-out.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-out.js +0 -3
- package/out/zql/src/ivm/union-fan-out.js.map +1 -1
- package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
- package/out/zql/src/ivm/view-apply-change.js +1 -2
- package/out/zql/src/ivm/view-apply-change.js.map +1 -1
- package/out/zql/src/mutate/mutator.d.ts +2 -2
- package/out/zql/src/mutate/mutator.d.ts.map +1 -1
- package/out/zql/src/mutate/mutator.js.map +1 -1
- package/out/zql/src/query/create-builder.d.ts +2 -2
- package/out/zql/src/query/create-builder.d.ts.map +1 -1
- package/out/zql/src/query/create-builder.js +12 -3
- package/out/zql/src/query/create-builder.js.map +1 -1
- package/out/zql/src/query/measure-push-operator.d.ts +0 -1
- package/out/zql/src/query/measure-push-operator.d.ts.map +1 -1
- package/out/zql/src/query/measure-push-operator.js +0 -3
- package/out/zql/src/query/measure-push-operator.js.map +1 -1
- package/out/zql/src/query/query.d.ts +18 -5
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +6 -10
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../../zero-schema/src/permissions.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../../zero-schema/src/permissions.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,aAAa,EACb,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,8BAA8B,CAAC;AAExD,OAAO,KAAK,EAEV,iBAAiB,IAAI,yBAAyB,EAC/C,MAAM,2BAA2B,CAAC;AAInC,eAAO,MAAM,UAAU,OACjB,OAAO,MAAM,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,iBAClD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB;;qBAN7B,OAAO,MAAM,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC;qBAA7C,OAAO,MAAM,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC;;8BAA7C,OAAO,MAAM,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC;+BAA7C,OAAO,MAAM,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC;;qBAA7C,OAAO,MAAM,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC;;CAgBlD,CAAC;AAEF,eAAO,MAAM,UAAU,SAAK,CAAC;AAE7B,MAAM,MAAM,MAAM,GAAG,UAAU,GAAG,gBAAgB,CAAC;AAEnD,MAAM,MAAM,OAAO,CAAC,OAAO,SAAS,MAAM,IAAI;KAC3C,CAAC,IAAI,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC;CAC3D,CAAC;AAEF,MAAM,MAAM,cAAc,CACxB,cAAc,EACd,OAAO,SAAS,MAAM,EACtB,MAAM,SAAS,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,IAC7C,CACF,QAAQ,EAAE,cAAc,EACxB,EAAE,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,KACnC,SAAS,CAAC;AAEf,MAAM,MAAM,gBAAgB,CAC1B,cAAc,EACd,OAAO,SAAS,MAAM,EACtB,MAAM,SAAS,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,IAC7C;IAEF,MAAM,CAAC,EAAE,cAAc,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC;IACvE;;;OAGG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC;IACvE;;;OAGG;IACH,MAAM,CAAC,EACH;QACE,WAAW,CAAC,EAAE,cAAc,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;QAChE,YAAY,CAAC,EAAE,cAAc,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;KAClE,GACD,SAAS,CAAC;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC;CACxE,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAAC,cAAc,EAAE,OAAO,SAAS,MAAM,IAAI;KACrE,CAAC,IAAI,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;QAC/B,GAAG,CAAC,EAAE,gBAAgB,CAAC,cAAc,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,GAAG,SAAS,CAAC;QACxE,IAAI,CAAC,EACD;aACG,CAAC,IAAI,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,CACjD,gBAAgB,CAAC,cAAc,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,EACrD,MAAM,CACP;SACF,GACD,SAAS,CAAC;KACf;CACF,CAAC;AAEF;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,cAAc,EAAE,OAAO,SAAS,MAAM,EAC5E,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,MACL,OAAO,CAAC,iBAAiB,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,GACnD,iBAAiB,CAAC,cAAc,EAAE,OAAO,CAAC,GAC7C,OAAO,CAAC,yBAAyB,GAAG,SAAS,CAAC,CAgBhD;AAoMD,eAAO,MAAM,WAAW;qBA1BQ,MAAM,SAAS;CA0BG,CAAC;AACnD,eAAO,MAAM,iBAAiB;qBA3BE,MAAM,SAAS;CA2Be,CAAC;AAC/D,wBAAgB,WAAW,CACzB,WAAW,EAAE,UAAU,GAAG,gBAAgB,EAC1C,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GACvB,SAAS,CAOX"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.js","sources":["../../../../zero-schema/src/permissions.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\nimport {\n mapCondition,\n toStaticParam,\n type Condition,\n type Parameter,\n} from '../../zero-protocol/src/ast.ts';\nimport {defaultFormat} from '../../zero-types/src/format.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {ExpressionBuilder} from '../../zql/src/query/expression.ts';\nimport type {Query} from '../../zql/src/query/query.ts';\nimport {StaticQuery} from '../../zql/src/query/static-query.ts';\nimport type {\n AssetPermissions as CompiledAssetPermissions,\n PermissionsConfig as CompiledPermissionsConfig,\n} from './compiled-permissions.ts';\nimport type {NameMapper} from './name-mapper.ts';\nimport {clientToServer} from './name-mapper.ts';\n\nexport const ANYONE_CAN = [\n (_: unknown, eb: ExpressionBuilder<never, Schema>) => eb.and(),\n];\n\n/**\n * @deprecated Use {@link ANYONE_CAN} instead.\n */\nexport const ANYONE_CAN_DO_ANYTHING = {\n row: {\n select: ANYONE_CAN,\n insert: ANYONE_CAN,\n update: {\n preMutation: ANYONE_CAN,\n postMutation: ANYONE_CAN,\n },\n delete: ANYONE_CAN,\n },\n};\n\nexport const NOBODY_CAN = [];\n\nexport type Anchor = 'authData' | 'preMutationRow';\n\nexport type Queries<TSchema extends Schema> = {\n [K in keyof TSchema['tables']]: Query<K & string, TSchema>;\n};\n\nexport type PermissionRule<\n TAuthDataShape,\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n> = (\n authData: TAuthDataShape,\n eb: ExpressionBuilder<TTable, TSchema>,\n) => Condition;\n\nexport type AssetPermissions<\n TAuthDataShape,\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n> = {\n // Why an array of rules?: https://github.com/rocicorp/mono/pull/3184/files#r1869680716\n select?: PermissionRule<TAuthDataShape, TSchema, TTable>[] | undefined;\n /**\n * @deprecated Use Mutators instead.\n * @see {@link https://zero.rocicorp.dev/docs/writing-data}\n */\n insert?: PermissionRule<TAuthDataShape, TSchema, TTable>[] | undefined;\n /**\n * @deprecated Use Mutators instead.\n * @see {@link https://zero.rocicorp.dev/docs/writing-data}\n */\n update?:\n | {\n preMutation?: PermissionRule<TAuthDataShape, TSchema, TTable>[];\n postMutation?: PermissionRule<TAuthDataShape, TSchema, TTable>[];\n }\n | undefined;\n /**\n * @deprecated Use Mutators instead.\n * @see {@link https://zero.rocicorp.dev/docs/writing-data}\n */\n delete?: PermissionRule<TAuthDataShape, TSchema, TTable>[] | undefined;\n};\n\nexport type PermissionsConfig<TAuthDataShape, TSchema extends Schema> = {\n [K in keyof TSchema['tables']]?: {\n row?: AssetPermissions<TAuthDataShape, TSchema, K & string> | undefined;\n cell?:\n | {\n [C in keyof TSchema['tables'][K]['columns']]?: Omit<\n AssetPermissions<TAuthDataShape, TSchema, K & string>,\n 'cell'\n >;\n }\n | undefined;\n };\n};\n\nexport async function definePermissions<TAuthDataShape, TSchema extends Schema>(\n schema: TSchema,\n definer: () =>\n | Promise<PermissionsConfig<TAuthDataShape, TSchema>>\n | PermissionsConfig<TAuthDataShape, TSchema>,\n): Promise<CompiledPermissionsConfig | undefined> {\n const expressionBuilders = {} as Record<\n string,\n ExpressionBuilder<string, Schema>\n >;\n for (const name of Object.keys(schema.tables)) {\n expressionBuilders[name] = new StaticQuery(\n schema,\n name,\n {table: name},\n defaultFormat,\n ).expressionBuilder();\n }\n\n const config = await definer();\n return compilePermissions(schema, config, expressionBuilders);\n}\n\nfunction compilePermissions<TAuthDataShape, TSchema extends Schema>(\n schema: TSchema,\n authz: PermissionsConfig<TAuthDataShape, TSchema> | undefined,\n expressionBuilders: Record<string, ExpressionBuilder<string, Schema>>,\n): CompiledPermissionsConfig | undefined {\n if (!authz) {\n return undefined;\n }\n const nameMapper = clientToServer(schema.tables);\n const ret: CompiledPermissionsConfig = {tables: {}};\n for (const [tableName, tableConfig] of Object.entries(authz)) {\n const serverName = schema.tables[tableName].serverName ?? tableName;\n ret.tables[serverName] = {\n row: compileRowConfig(\n nameMapper,\n tableName,\n tableConfig.row,\n expressionBuilders[tableName],\n ),\n cell: compileCellConfig(\n nameMapper,\n tableName,\n tableConfig.cell,\n expressionBuilders[tableName],\n ),\n };\n }\n\n return ret;\n}\n\nfunction compileRowConfig<\n TAuthDataShape,\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n>(\n clientToServer: NameMapper,\n tableName: TTable,\n rowRules: AssetPermissions<TAuthDataShape, TSchema, TTable> | undefined,\n expressionBuilder: ExpressionBuilder<TTable, TSchema>,\n): CompiledAssetPermissions | undefined {\n if (!rowRules) {\n return undefined;\n }\n return {\n select: compileRules(\n clientToServer,\n tableName,\n rowRules.select,\n expressionBuilder,\n ),\n insert: compileRules(\n clientToServer,\n tableName,\n rowRules.insert,\n expressionBuilder,\n ),\n update: {\n preMutation: compileRules(\n clientToServer,\n tableName,\n rowRules.update?.preMutation,\n expressionBuilder,\n ),\n postMutation: compileRules(\n clientToServer,\n tableName,\n rowRules.update?.postMutation,\n expressionBuilder,\n ),\n },\n delete: compileRules(\n clientToServer,\n tableName,\n rowRules.delete,\n expressionBuilder,\n ),\n };\n}\n\n/**\n * What is this \"allow\" and why are permissions policies an array of rules?\n *\n * Please read: https://github.com/rocicorp/mono/pull/3184/files#r1869680716\n */\nfunction compileRules<\n TAuthDataShape,\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n>(\n clientToServer: NameMapper,\n tableName: TTable,\n rules: PermissionRule<TAuthDataShape, TSchema, TTable>[] | undefined,\n expressionBuilder: ExpressionBuilder<TTable, TSchema>,\n): ['allow', Condition][] | undefined {\n if (!rules) {\n return undefined;\n }\n\n return rules.map(rule => {\n const cond = rule(authDataRef as TAuthDataShape, expressionBuilder);\n return ['allow', mapCondition(cond, tableName, clientToServer)] as const;\n });\n}\n\nfunction compileCellConfig<\n TAuthDataShape,\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n>(\n clientToServer: NameMapper,\n tableName: TTable,\n cellRules:\n | Record<string, AssetPermissions<TAuthDataShape, TSchema, TTable>>\n | undefined,\n expressionBuilder: ExpressionBuilder<TTable, TSchema>,\n): Record<string, CompiledAssetPermissions> | undefined {\n if (!cellRules) {\n return undefined;\n }\n const ret: Record<string, CompiledAssetPermissions> = {};\n for (const [columnName, rules] of Object.entries(cellRules)) {\n ret[columnName] = {\n select: compileRules(\n clientToServer,\n tableName,\n rules.select,\n expressionBuilder,\n ),\n insert: compileRules(\n clientToServer,\n tableName,\n rules.insert,\n expressionBuilder,\n ),\n update: {\n preMutation: compileRules(\n clientToServer,\n tableName,\n rules.update?.preMutation,\n expressionBuilder,\n ),\n postMutation: compileRules(\n clientToServer,\n tableName,\n rules.update?.postMutation,\n expressionBuilder,\n ),\n },\n delete: compileRules(\n clientToServer,\n tableName,\n rules.delete,\n expressionBuilder,\n ),\n };\n }\n return ret;\n}\n\nclass CallTracker {\n readonly #anchor: Anchor;\n readonly #path: string[];\n constructor(anchor: Anchor, path: string[]) {\n this.#anchor = anchor;\n this.#path = path;\n }\n\n get(target: {[toStaticParam]: () => Parameter}, prop: string | symbol) {\n if (prop === toStaticParam) {\n return target[toStaticParam];\n }\n assert(typeof prop === 'string');\n const path = [...this.#path, prop];\n return new Proxy(\n {\n [toStaticParam]: () => staticParam(this.#anchor, path),\n },\n new CallTracker(this.#anchor, path),\n );\n }\n}\n\nfunction baseTracker(anchor: Anchor) {\n return new Proxy(\n {\n [toStaticParam]: () => {\n throw new Error('no JWT field specified');\n },\n },\n new CallTracker(anchor, []),\n );\n}\n\nexport const authDataRef = baseTracker('authData');\nexport const preMutationRowRef = baseTracker('preMutationRow');\nexport function staticParam(\n anchorClass: 'authData' | 'preMutationRow',\n field: string | string[],\n): Parameter {\n return {\n type: 'static',\n anchor: anchorClass,\n // for backwards compatibility\n field: field.length === 1 ? field[0] : field,\n };\n}\n"],"names":["clientToServer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"permissions.js","sources":["../../../../zero-schema/src/permissions.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\nimport {\n mapCondition,\n toStaticParam,\n type Condition,\n type Parameter,\n} from '../../zero-protocol/src/ast.ts';\nimport {defaultFormat} from '../../zero-types/src/format.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {ExpressionBuilder} from '../../zql/src/query/expression.ts';\nimport type {Query} from '../../zql/src/query/query.ts';\nimport {StaticQuery} from '../../zql/src/query/static-query.ts';\nimport type {\n AssetPermissions as CompiledAssetPermissions,\n PermissionsConfig as CompiledPermissionsConfig,\n} from './compiled-permissions.ts';\nimport type {NameMapper} from './name-mapper.ts';\nimport {clientToServer} from './name-mapper.ts';\n\nexport const ANYONE_CAN = [\n (_: unknown, eb: ExpressionBuilder<never, Schema>) => eb.and(),\n];\n\n/**\n * @deprecated Use {@link ANYONE_CAN} instead.\n */\nexport const ANYONE_CAN_DO_ANYTHING = {\n row: {\n select: ANYONE_CAN,\n insert: ANYONE_CAN,\n update: {\n preMutation: ANYONE_CAN,\n postMutation: ANYONE_CAN,\n },\n delete: ANYONE_CAN,\n },\n};\n\nexport const NOBODY_CAN = [];\n\nexport type Anchor = 'authData' | 'preMutationRow';\n\nexport type Queries<TSchema extends Schema> = {\n [K in keyof TSchema['tables']]: Query<K & string, TSchema>;\n};\n\nexport type PermissionRule<\n TAuthDataShape,\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n> = (\n authData: TAuthDataShape,\n eb: ExpressionBuilder<TTable, TSchema>,\n) => Condition;\n\nexport type AssetPermissions<\n TAuthDataShape,\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n> = {\n // Why an array of rules?: https://github.com/rocicorp/mono/pull/3184/files#r1869680716\n select?: PermissionRule<TAuthDataShape, TSchema, TTable>[] | undefined;\n /**\n * @deprecated Use Mutators instead.\n * @see {@link https://zero.rocicorp.dev/docs/writing-data}\n */\n insert?: PermissionRule<TAuthDataShape, TSchema, TTable>[] | undefined;\n /**\n * @deprecated Use Mutators instead.\n * @see {@link https://zero.rocicorp.dev/docs/writing-data}\n */\n update?:\n | {\n preMutation?: PermissionRule<TAuthDataShape, TSchema, TTable>[];\n postMutation?: PermissionRule<TAuthDataShape, TSchema, TTable>[];\n }\n | undefined;\n /**\n * @deprecated Use Mutators instead.\n * @see {@link https://zero.rocicorp.dev/docs/writing-data}\n */\n delete?: PermissionRule<TAuthDataShape, TSchema, TTable>[] | undefined;\n};\n\nexport type PermissionsConfig<TAuthDataShape, TSchema extends Schema> = {\n [K in keyof TSchema['tables']]?: {\n row?: AssetPermissions<TAuthDataShape, TSchema, K & string> | undefined;\n cell?:\n | {\n [C in keyof TSchema['tables'][K]['columns']]?: Omit<\n AssetPermissions<TAuthDataShape, TSchema, K & string>,\n 'cell'\n >;\n }\n | undefined;\n };\n};\n\n/**\n * @deprecated Use {@link defineMutators} and {@link defineQueries} instead.\n */\nexport async function definePermissions<TAuthDataShape, TSchema extends Schema>(\n schema: TSchema,\n definer: () =>\n | Promise<PermissionsConfig<TAuthDataShape, TSchema>>\n | PermissionsConfig<TAuthDataShape, TSchema>,\n): Promise<CompiledPermissionsConfig | undefined> {\n const expressionBuilders = {} as Record<\n string,\n ExpressionBuilder<string, Schema>\n >;\n for (const name of Object.keys(schema.tables)) {\n expressionBuilders[name] = new StaticQuery(\n schema,\n name,\n {table: name},\n defaultFormat,\n ).expressionBuilder();\n }\n\n const config = await definer();\n return compilePermissions(schema, config, expressionBuilders);\n}\n\nfunction compilePermissions<TAuthDataShape, TSchema extends Schema>(\n schema: TSchema,\n authz: PermissionsConfig<TAuthDataShape, TSchema> | undefined,\n expressionBuilders: Record<string, ExpressionBuilder<string, Schema>>,\n): CompiledPermissionsConfig | undefined {\n if (!authz) {\n return undefined;\n }\n const nameMapper = clientToServer(schema.tables);\n const ret: CompiledPermissionsConfig = {tables: {}};\n for (const [tableName, tableConfig] of Object.entries(authz)) {\n const serverName = schema.tables[tableName].serverName ?? tableName;\n ret.tables[serverName] = {\n row: compileRowConfig(\n nameMapper,\n tableName,\n tableConfig.row,\n expressionBuilders[tableName],\n ),\n cell: compileCellConfig(\n nameMapper,\n tableName,\n tableConfig.cell,\n expressionBuilders[tableName],\n ),\n };\n }\n\n return ret;\n}\n\nfunction compileRowConfig<\n TAuthDataShape,\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n>(\n clientToServer: NameMapper,\n tableName: TTable,\n rowRules: AssetPermissions<TAuthDataShape, TSchema, TTable> | undefined,\n expressionBuilder: ExpressionBuilder<TTable, TSchema>,\n): CompiledAssetPermissions | undefined {\n if (!rowRules) {\n return undefined;\n }\n return {\n select: compileRules(\n clientToServer,\n tableName,\n rowRules.select,\n expressionBuilder,\n ),\n insert: compileRules(\n clientToServer,\n tableName,\n rowRules.insert,\n expressionBuilder,\n ),\n update: {\n preMutation: compileRules(\n clientToServer,\n tableName,\n rowRules.update?.preMutation,\n expressionBuilder,\n ),\n postMutation: compileRules(\n clientToServer,\n tableName,\n rowRules.update?.postMutation,\n expressionBuilder,\n ),\n },\n delete: compileRules(\n clientToServer,\n tableName,\n rowRules.delete,\n expressionBuilder,\n ),\n };\n}\n\n/**\n * What is this \"allow\" and why are permissions policies an array of rules?\n *\n * Please read: https://github.com/rocicorp/mono/pull/3184/files#r1869680716\n */\nfunction compileRules<\n TAuthDataShape,\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n>(\n clientToServer: NameMapper,\n tableName: TTable,\n rules: PermissionRule<TAuthDataShape, TSchema, TTable>[] | undefined,\n expressionBuilder: ExpressionBuilder<TTable, TSchema>,\n): ['allow', Condition][] | undefined {\n if (!rules) {\n return undefined;\n }\n\n return rules.map(rule => {\n const cond = rule(authDataRef as TAuthDataShape, expressionBuilder);\n return ['allow', mapCondition(cond, tableName, clientToServer)] as const;\n });\n}\n\nfunction compileCellConfig<\n TAuthDataShape,\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n>(\n clientToServer: NameMapper,\n tableName: TTable,\n cellRules:\n | Record<string, AssetPermissions<TAuthDataShape, TSchema, TTable>>\n | undefined,\n expressionBuilder: ExpressionBuilder<TTable, TSchema>,\n): Record<string, CompiledAssetPermissions> | undefined {\n if (!cellRules) {\n return undefined;\n }\n const ret: Record<string, CompiledAssetPermissions> = {};\n for (const [columnName, rules] of Object.entries(cellRules)) {\n ret[columnName] = {\n select: compileRules(\n clientToServer,\n tableName,\n rules.select,\n expressionBuilder,\n ),\n insert: compileRules(\n clientToServer,\n tableName,\n rules.insert,\n expressionBuilder,\n ),\n update: {\n preMutation: compileRules(\n clientToServer,\n tableName,\n rules.update?.preMutation,\n expressionBuilder,\n ),\n postMutation: compileRules(\n clientToServer,\n tableName,\n rules.update?.postMutation,\n expressionBuilder,\n ),\n },\n delete: compileRules(\n clientToServer,\n tableName,\n rules.delete,\n expressionBuilder,\n ),\n };\n }\n return ret;\n}\n\nclass CallTracker {\n readonly #anchor: Anchor;\n readonly #path: string[];\n constructor(anchor: Anchor, path: string[]) {\n this.#anchor = anchor;\n this.#path = path;\n }\n\n get(target: {[toStaticParam]: () => Parameter}, prop: string | symbol) {\n if (prop === toStaticParam) {\n return target[toStaticParam];\n }\n assert(typeof prop === 'string');\n const path = [...this.#path, prop];\n return new Proxy(\n {\n [toStaticParam]: () => staticParam(this.#anchor, path),\n },\n new CallTracker(this.#anchor, path),\n );\n }\n}\n\nfunction baseTracker(anchor: Anchor) {\n return new Proxy(\n {\n [toStaticParam]: () => {\n throw new Error('no JWT field specified');\n },\n },\n new CallTracker(anchor, []),\n );\n}\n\nexport const authDataRef = baseTracker('authData');\nexport const preMutationRowRef = baseTracker('preMutationRow');\nexport function staticParam(\n anchorClass: 'authData' | 'preMutationRow',\n field: string | string[],\n): Parameter {\n return {\n type: 'static',\n anchor: anchorClass,\n // for backwards compatibility\n field: field.length === 1 ? field[0] : field,\n };\n}\n"],"names":["clientToServer"],"mappings":"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"}
|
|
@@ -16,9 +16,9 @@ export declare class TransactionImpl<TSchema extends Schema, TWrappedTransaction
|
|
|
16
16
|
readonly mutationID: number;
|
|
17
17
|
readonly mutate: SchemaCRUD<TSchema>;
|
|
18
18
|
readonly query: SchemaQuery<TSchema>;
|
|
19
|
-
constructor(dbTransaction: DBTransaction<TWrappedTransaction>, clientID: string, mutationID: number, mutate: SchemaCRUD<TSchema>,
|
|
19
|
+
constructor(dbTransaction: DBTransaction<TWrappedTransaction>, clientID: string, mutationID: number, mutate: SchemaCRUD<TSchema>, schema: TSchema, serverSchema: ServerSchema);
|
|
20
20
|
run<TTable extends keyof TSchema['tables'] & string, TReturn>(query: Query<TTable, TSchema, TReturn>, _options?: RunOptions): Promise<HumanReadable<TReturn>>;
|
|
21
21
|
}
|
|
22
|
-
export declare function makeServerTransaction<TSchema extends Schema, TWrappedTransaction>(dbTransaction: DBTransaction<TWrappedTransaction>, clientID: string, mutationID: number, schema: TSchema, mutate: (dbTransaction: DBTransaction<TWrappedTransaction>, serverSchema: ServerSchema) => SchemaCRUD<TSchema
|
|
22
|
+
export declare function makeServerTransaction<TSchema extends Schema, TWrappedTransaction>(dbTransaction: DBTransaction<TWrappedTransaction>, clientID: string, mutationID: number, schema: TSchema, mutate: (dbTransaction: DBTransaction<TWrappedTransaction>, serverSchema: ServerSchema) => SchemaCRUD<TSchema>): Promise<TransactionImpl<TSchema, TWrappedTransaction>>;
|
|
23
23
|
export declare function makeSchemaCRUD<S extends Schema>(schema: S): (dbTransaction: DBTransaction<unknown>, serverSchema: ServerSchema) => SchemaCRUD<S>;
|
|
24
24
|
//# sourceMappingURL=custom.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/custom.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAEV,YAAY,EAEb,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,iBAAiB,EAElB,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/custom.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAEV,YAAY,EAEb,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,iBAAiB,EAElB,MAAM,gCAAgC,CAAC;AAIxC,OAAO,KAAK,EACV,aAAa,EACb,KAAK,EACL,UAAU,EACX,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,qCAAqC,CAAC;AAGrE,MAAM,MAAM,iBAAiB,CAAC,cAAc,IAAI;IAC9C,CAAC,cAAc,EAAE,MAAM,GACnB,iBAAiB,CAAC,cAAc,CAAC,GACjC,iBAAiB,CAAC,cAAc,CAAC,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAC3B,cAAc,EAEd,KAAK,GAAG,GAAG,EACX,OAAO,GAAG,OAAO,IACf,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAwDrE,qBAAa,eAAe,CAAC,OAAO,SAAS,MAAM,EAAE,mBAAmB,CACtE,YAAW,iBAAiB,CAAC,OAAO,EAAE,mBAAmB,CAAC;;IAE1D,QAAQ,CAAC,QAAQ,YAAY;IAC7B,QAAQ,CAAC,MAAM,mBAAmB;IAClC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;gBAKnC,aAAa,EAAE,aAAa,CAAC,mBAAmB,CAAC,EACjD,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,EAC3B,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,YAAY;IAiB5B,GAAG,CAAC,MAAM,SAAS,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE,OAAO,EAC1D,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,EACtC,QAAQ,CAAC,EAAE,UAAU,GACpB,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;CAWnC;AAWD,wBAAsB,qBAAqB,CACzC,OAAO,SAAS,MAAM,EACtB,mBAAmB,EAEnB,aAAa,EAAE,aAAa,CAAC,mBAAmB,CAAC,EACjD,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,CACN,aAAa,EAAE,aAAa,CAAC,mBAAmB,CAAC,EACjD,YAAY,EAAE,YAAY,KACvB,UAAU,CAAC,OAAO,CAAC,0DAWzB;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAC7C,MAAM,EAAE,CAAC,GACR,CACD,aAAa,EAAE,aAAa,CAAC,OAAO,CAAC,EACrC,YAAY,EAAE,YAAY,KACvB,UAAU,CAAC,CAAC,CAAC,CAgDjB"}
|
|
@@ -1,7 +1,39 @@
|
|
|
1
1
|
import { assert } from "../../shared/src/asserts.js";
|
|
2
2
|
import { formatPgInternalConvert, sql, sqlConvertColumnArg } from "../../z2s/src/sql.js";
|
|
3
|
+
import { createRunnableBuilder } from "../../zql/src/query/create-builder.js";
|
|
4
|
+
import { QueryDelegateBase } from "../../zql/src/query/query-delegate-base.js";
|
|
3
5
|
import { asQueryInternals } from "../../zql/src/query/query-internals.js";
|
|
4
6
|
import { getServerSchema } from "./schema.js";
|
|
7
|
+
class ServerTransactionQueryDelegate extends QueryDelegateBase {
|
|
8
|
+
#dbTransaction;
|
|
9
|
+
#schema;
|
|
10
|
+
#serverSchema;
|
|
11
|
+
defaultQueryComplete = true;
|
|
12
|
+
constructor(dbTransaction, schema, serverSchema) {
|
|
13
|
+
super();
|
|
14
|
+
this.#dbTransaction = dbTransaction;
|
|
15
|
+
this.#schema = schema;
|
|
16
|
+
this.#serverSchema = serverSchema;
|
|
17
|
+
}
|
|
18
|
+
getSource() {
|
|
19
|
+
throw new Error("not implemented");
|
|
20
|
+
}
|
|
21
|
+
run(query, _options) {
|
|
22
|
+
const queryInternals = asQueryInternals(query);
|
|
23
|
+
return this.#dbTransaction.runQuery(
|
|
24
|
+
queryInternals.ast,
|
|
25
|
+
queryInternals.format,
|
|
26
|
+
this.#schema,
|
|
27
|
+
this.#serverSchema
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
preload() {
|
|
31
|
+
throw new Error("preload() is not supported in server transactions");
|
|
32
|
+
}
|
|
33
|
+
materialize() {
|
|
34
|
+
throw new Error("materialize() is not supported in server transactions");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
5
37
|
class TransactionImpl {
|
|
6
38
|
location = "server";
|
|
7
39
|
reason = "authoritative";
|
|
@@ -12,14 +44,19 @@ class TransactionImpl {
|
|
|
12
44
|
query;
|
|
13
45
|
#schema;
|
|
14
46
|
#serverSchema;
|
|
15
|
-
constructor(dbTransaction, clientID, mutationID, mutate,
|
|
47
|
+
constructor(dbTransaction, clientID, mutationID, mutate, schema, serverSchema) {
|
|
16
48
|
this.dbTransaction = dbTransaction;
|
|
17
49
|
this.clientID = clientID;
|
|
18
50
|
this.mutationID = mutationID;
|
|
19
51
|
this.mutate = mutate;
|
|
20
|
-
this.query = query;
|
|
21
52
|
this.#schema = schema;
|
|
22
53
|
this.#serverSchema = serverSchema;
|
|
54
|
+
const delegate = new ServerTransactionQueryDelegate(
|
|
55
|
+
dbTransaction,
|
|
56
|
+
schema,
|
|
57
|
+
serverSchema
|
|
58
|
+
);
|
|
59
|
+
this.query = createRunnableBuilder(delegate, schema);
|
|
23
60
|
}
|
|
24
61
|
run(query, _options) {
|
|
25
62
|
const queryInternals = asQueryInternals(query);
|
|
@@ -33,14 +70,13 @@ class TransactionImpl {
|
|
|
33
70
|
}
|
|
34
71
|
const dbTxSymbol = Symbol();
|
|
35
72
|
const serverSchemaSymbol = Symbol();
|
|
36
|
-
async function makeServerTransaction(dbTransaction, clientID, mutationID, schema, mutate
|
|
73
|
+
async function makeServerTransaction(dbTransaction, clientID, mutationID, schema, mutate) {
|
|
37
74
|
const serverSchema = await getServerSchema(dbTransaction, schema);
|
|
38
75
|
return new TransactionImpl(
|
|
39
76
|
dbTransaction,
|
|
40
77
|
clientID,
|
|
41
78
|
mutationID,
|
|
42
79
|
mutate(dbTransaction, serverSchema),
|
|
43
|
-
query,
|
|
44
80
|
schema,
|
|
45
81
|
serverSchema
|
|
46
82
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom.js","sources":["../../../../zero-server/src/custom.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\nimport {\n formatPgInternalConvert,\n sql,\n sqlConvertColumnArg,\n} from '../../z2s/src/sql.ts';\nimport type {TableSchema} from '../../zero-schema/src/table-schema.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {\n ServerColumnSchema,\n ServerSchema,\n ServerTableSchema,\n} from '../../zero-types/src/server-schema.ts';\nimport type {\n DBTransaction,\n SchemaCRUD,\n ServerTransaction,\n TableCRUD,\n} from '../../zql/src/mutate/custom.ts';\nimport {asQueryInternals} from '../../zql/src/query/query-internals.ts';\nimport type {\n HumanReadable,\n Query,\n RunOptions,\n} from '../../zql/src/query/query.ts';\nimport type {SchemaQuery} from '../../zql/src/query/schema-query.ts';\nimport {getServerSchema} from './schema.ts';\n\nexport type CustomMutatorDefs<TDBTransaction> = {\n [namespaceOrKey: string]:\n | CustomMutatorImpl<TDBTransaction>\n | CustomMutatorDefs<TDBTransaction>;\n};\n\nexport type CustomMutatorImpl<\n TDBTransaction,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n TArgs = any,\n Context = unknown,\n> = (tx: TDBTransaction, args: TArgs, ctx: Context) => Promise<void>;\n\nexport class TransactionImpl<TSchema extends Schema, TWrappedTransaction>\n implements ServerTransaction<TSchema, TWrappedTransaction>\n{\n readonly location = 'server';\n readonly reason = 'authoritative';\n readonly dbTransaction: DBTransaction<TWrappedTransaction>;\n readonly clientID: string;\n readonly mutationID: number;\n readonly mutate: SchemaCRUD<TSchema>;\n readonly query: SchemaQuery<TSchema>;\n readonly #schema: TSchema;\n readonly #serverSchema: ServerSchema;\n\n constructor(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n mutate: SchemaCRUD<TSchema>,\n query: SchemaQuery<TSchema>,\n schema: TSchema,\n serverSchema: ServerSchema,\n ) {\n this.dbTransaction = dbTransaction;\n this.clientID = clientID;\n this.mutationID = mutationID;\n this.mutate = mutate;\n this.query = query;\n this.#schema = schema;\n this.#serverSchema = serverSchema;\n }\n\n run<TTable extends keyof TSchema['tables'] & string, TReturn>(\n query: Query<TTable, TSchema, TReturn>,\n _options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n const queryInternals = asQueryInternals(query);\n\n // Execute the query using the database-specific executor\n return this.dbTransaction.runQuery<TReturn>(\n queryInternals.ast,\n queryInternals.format,\n this.#schema,\n this.#serverSchema,\n );\n }\n}\n\nconst dbTxSymbol = Symbol();\n\nconst serverSchemaSymbol = Symbol();\n\ntype WithHiddenTxAndSchema = {\n [dbTxSymbol]: DBTransaction<unknown>;\n [serverSchemaSymbol]: ServerSchema;\n};\n\nexport async function makeServerTransaction<\n TSchema extends Schema,\n TWrappedTransaction,\n>(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n schema: TSchema,\n mutate: (\n dbTransaction: DBTransaction<TWrappedTransaction>,\n serverSchema: ServerSchema,\n ) => SchemaCRUD<TSchema>,\n query: SchemaQuery<TSchema>,\n) {\n const serverSchema = await getServerSchema(dbTransaction, schema);\n return new TransactionImpl(\n dbTransaction,\n clientID,\n mutationID,\n mutate(dbTransaction, serverSchema),\n query,\n schema,\n serverSchema,\n );\n}\n\nexport function makeSchemaCRUD<S extends Schema>(\n schema: S,\n): (\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n) => SchemaCRUD<S> {\n const schemaCRUDs: Record<string, TableCRUD<TableSchema>> = {};\n for (const tableSchema of Object.values(schema.tables)) {\n schemaCRUDs[tableSchema.name] = makeTableCRUD(tableSchema);\n }\n\n /**\n * For users with very large schemas it is expensive to re-create\n * all the CRUD mutators for each transaction. Instead, we create\n * them all once up-front and then bind them to the transaction\n * as requested.\n */\n class CRUDHandler {\n readonly #dbTransaction: DBTransaction<unknown>;\n readonly #serverSchema: ServerSchema;\n constructor(\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n ) {\n this.#dbTransaction = dbTransaction;\n this.#serverSchema = serverSchema;\n }\n\n get(target: Record<string, TableCRUD<TableSchema>>, prop: string) {\n if (prop in target) {\n return target[prop];\n }\n\n const txHolder: WithHiddenTxAndSchema = {\n [dbTxSymbol]: this.#dbTransaction,\n [serverSchemaSymbol]: this.#serverSchema,\n };\n target[prop] = Object.fromEntries(\n Object.entries(schemaCRUDs[prop]).map(([name, method]) => [\n name,\n method.bind(txHolder),\n ]),\n ) as TableCRUD<TableSchema>;\n\n return target[prop];\n }\n }\n\n return (dbTransaction: DBTransaction<unknown>, serverSchema: ServerSchema) =>\n new Proxy(\n {},\n new CRUDHandler(dbTransaction, serverSchema),\n ) as SchemaCRUD<S>;\n}\n\nfunction removeUndefined<T extends Record<string, unknown>>(value: T): T {\n const valueWithoutUndefined: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (val !== undefined) {\n valueWithoutUndefined[key] = val;\n }\n }\n return valueWithoutUndefined as T;\n}\n\nfunction makeTableCRUD(schema: TableSchema): TableCRUD<TableSchema> {\n return {\n async insert(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const stmt = formatPgInternalConvert(\n sql`INSERT INTO ${sql.ident(serverName(schema))} (${sql.join(\n targetedColumns.map(([, serverName]) => sql.ident(serverName)),\n ',',\n )}) VALUES (${sql.join(\n Object.entries(value).map(([col, v]) =>\n sqlInsertValue(v, serverTableSchema[serverNameFor(col, schema)]),\n ),\n ', ',\n )})`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async upsert(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const primaryKeyColumns = origAndServerNamesFor(\n schema.primaryKey,\n schema,\n );\n const stmt = formatPgInternalConvert(\n sql`INSERT INTO ${sql.ident(serverName(schema))} (${sql.join(\n targetedColumns.map(([, serverName]) => sql.ident(serverName)),\n ',',\n )}) VALUES (${sql.join(\n Object.entries(value).map(([col, val]) =>\n sqlInsertValue(val, serverTableSchema[serverNameFor(col, schema)]),\n ),\n ', ',\n )}) ON CONFLICT (${sql.join(\n primaryKeyColumns.map(([, serverName]) => sql.ident(serverName)),\n ', ',\n )}) DO UPDATE SET ${sql.join(\n Object.entries(value).map(\n ([col, val]) =>\n sql`${sql.ident(\n schema.columns[col].serverName ?? col,\n )} = ${sqlInsertValue(val, serverTableSchema[serverNameFor(col, schema)])}`,\n ),\n ', ',\n )}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async update(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const stmt = formatPgInternalConvert(\n sql`UPDATE ${sql.ident(serverName(schema))} SET ${sql.join(\n targetedColumns.map(\n ([origName, serverName]) =>\n sql`${sql.ident(serverName)} = ${sqlInsertValue(value[origName], serverTableSchema[serverName])}`,\n ),\n ', ',\n )} WHERE ${primaryKeyClause(schema, serverTableSchema, value)}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async delete(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const stmt = formatPgInternalConvert(\n sql`DELETE FROM ${sql.ident(\n serverName(schema),\n )} WHERE ${primaryKeyClause(schema, serverTableSchema, value)}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n };\n}\n\nfunction serverName(x: {name: string; serverName?: string | undefined}) {\n return x.serverName ?? x.name;\n}\n\nfunction primaryKeyClause(\n schema: TableSchema,\n serverTableSchema: ServerTableSchema,\n row: Record<string, unknown>,\n) {\n const primaryKey = origAndServerNamesFor(schema.primaryKey, schema);\n return sql`${sql.join(\n primaryKey.map(\n ([origName, serverName]) =>\n sql`${sql.ident(serverName)}${maybeCastColumn(serverTableSchema[serverName])} = ${sqlValue(row[origName], serverTableSchema[serverName])}`,\n ),\n ' AND ',\n )}`;\n}\n\nfunction maybeCastColumn(col: ServerColumnSchema) {\n if (col.type === 'uuid' || col.isEnum) {\n return sql`::text`;\n }\n return sql``;\n}\n\nfunction origAndServerNamesFor(\n originalNames: readonly string[],\n schema: TableSchema,\n): [origName: string, serverName: string][] {\n return originalNames.map(\n name => [name, serverNameFor(name, schema)] as const,\n );\n}\n\nfunction serverNameFor(originalName: string, schema: TableSchema): string {\n const col = schema.columns[originalName];\n assert(\n col,\n `Column ${originalName} was not found in the Zero schema for the table ${schema.name}`,\n );\n return col.serverName ?? originalName;\n}\n\nfunction sqlValue(value: unknown, serverColumnSchema: ServerColumnSchema) {\n return sqlConvertColumnArg(serverColumnSchema, value, false, true);\n}\n\nfunction sqlInsertValue(\n value: unknown,\n serverColumnSchema: ServerColumnSchema,\n) {\n return sqlConvertColumnArg(serverColumnSchema, value, false, false);\n}\n"],"names":["serverName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"custom.js","sources":["../../../../zero-server/src/custom.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\nimport {\n formatPgInternalConvert,\n sql,\n sqlConvertColumnArg,\n} from '../../z2s/src/sql.ts';\nimport type {TableSchema} from '../../zero-schema/src/table-schema.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {\n ServerColumnSchema,\n ServerSchema,\n ServerTableSchema,\n} from '../../zero-types/src/server-schema.ts';\nimport type {\n DBTransaction,\n SchemaCRUD,\n ServerTransaction,\n TableCRUD,\n} from '../../zql/src/mutate/custom.ts';\nimport {createRunnableBuilder} from '../../zql/src/query/create-builder.ts';\nimport {QueryDelegateBase} from '../../zql/src/query/query-delegate-base.ts';\nimport {asQueryInternals} from '../../zql/src/query/query-internals.ts';\nimport type {\n HumanReadable,\n Query,\n RunOptions,\n} from '../../zql/src/query/query.ts';\nimport type {SchemaQuery} from '../../zql/src/query/schema-query.ts';\nimport {getServerSchema} from './schema.ts';\n\nexport type CustomMutatorDefs<TDBTransaction> = {\n [namespaceOrKey: string]:\n | CustomMutatorImpl<TDBTransaction>\n | CustomMutatorDefs<TDBTransaction>;\n};\n\nexport type CustomMutatorImpl<\n TDBTransaction,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n TArgs = any,\n Context = unknown,\n> = (tx: TDBTransaction, args: TArgs, ctx: Context) => Promise<void>;\n\n/**\n * QueryDelegate implementation for server-side transactions.\n * Extends QueryDelegateBase to satisfy the QueryDelegate interface,\n * but overrides run() to execute against Postgres and throws on\n * preload()/materialize() which don't make sense server-side.\n */\nclass ServerTransactionQueryDelegate extends QueryDelegateBase {\n readonly #dbTransaction: DBTransaction<unknown>;\n readonly #schema: Schema;\n readonly #serverSchema: ServerSchema;\n\n readonly defaultQueryComplete = true;\n\n constructor(\n dbTransaction: DBTransaction<unknown>,\n schema: Schema,\n serverSchema: ServerSchema,\n ) {\n super();\n this.#dbTransaction = dbTransaction;\n this.#schema = schema;\n this.#serverSchema = serverSchema;\n }\n\n getSource(): never {\n throw new Error('not implemented');\n }\n\n override run<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n >(\n query: Query<TTable, TSchema, TReturn>,\n _options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n const queryInternals = asQueryInternals(query);\n return this.#dbTransaction.runQuery<TReturn>(\n queryInternals.ast,\n queryInternals.format,\n this.#schema,\n this.#serverSchema,\n );\n }\n\n override preload(): never {\n throw new Error('preload() is not supported in server transactions');\n }\n\n override materialize(): never {\n throw new Error('materialize() is not supported in server transactions');\n }\n}\n\nexport class TransactionImpl<TSchema extends Schema, TWrappedTransaction>\n implements ServerTransaction<TSchema, TWrappedTransaction>\n{\n readonly location = 'server';\n readonly reason = 'authoritative';\n readonly dbTransaction: DBTransaction<TWrappedTransaction>;\n readonly clientID: string;\n readonly mutationID: number;\n readonly mutate: SchemaCRUD<TSchema>;\n readonly query: SchemaQuery<TSchema>;\n readonly #schema: TSchema;\n readonly #serverSchema: ServerSchema;\n\n constructor(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n mutate: SchemaCRUD<TSchema>,\n schema: TSchema,\n serverSchema: ServerSchema,\n ) {\n this.dbTransaction = dbTransaction;\n this.clientID = clientID;\n this.mutationID = mutationID;\n this.mutate = mutate;\n this.#schema = schema;\n this.#serverSchema = serverSchema;\n\n const delegate = new ServerTransactionQueryDelegate(\n dbTransaction,\n schema,\n serverSchema,\n );\n this.query = createRunnableBuilder(delegate, schema);\n }\n\n run<TTable extends keyof TSchema['tables'] & string, TReturn>(\n query: Query<TTable, TSchema, TReturn>,\n _options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n const queryInternals = asQueryInternals(query);\n\n // Execute the query using the database-specific executor\n return this.dbTransaction.runQuery<TReturn>(\n queryInternals.ast,\n queryInternals.format,\n this.#schema,\n this.#serverSchema,\n );\n }\n}\n\nconst dbTxSymbol = Symbol();\n\nconst serverSchemaSymbol = Symbol();\n\ntype WithHiddenTxAndSchema = {\n [dbTxSymbol]: DBTransaction<unknown>;\n [serverSchemaSymbol]: ServerSchema;\n};\n\nexport async function makeServerTransaction<\n TSchema extends Schema,\n TWrappedTransaction,\n>(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n schema: TSchema,\n mutate: (\n dbTransaction: DBTransaction<TWrappedTransaction>,\n serverSchema: ServerSchema,\n ) => SchemaCRUD<TSchema>,\n) {\n const serverSchema = await getServerSchema(dbTransaction, schema);\n return new TransactionImpl(\n dbTransaction,\n clientID,\n mutationID,\n mutate(dbTransaction, serverSchema),\n schema,\n serverSchema,\n );\n}\n\nexport function makeSchemaCRUD<S extends Schema>(\n schema: S,\n): (\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n) => SchemaCRUD<S> {\n const schemaCRUDs: Record<string, TableCRUD<TableSchema>> = {};\n for (const tableSchema of Object.values(schema.tables)) {\n schemaCRUDs[tableSchema.name] = makeTableCRUD(tableSchema);\n }\n\n /**\n * For users with very large schemas it is expensive to re-create\n * all the CRUD mutators for each transaction. Instead, we create\n * them all once up-front and then bind them to the transaction\n * as requested.\n */\n class CRUDHandler {\n readonly #dbTransaction: DBTransaction<unknown>;\n readonly #serverSchema: ServerSchema;\n constructor(\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n ) {\n this.#dbTransaction = dbTransaction;\n this.#serverSchema = serverSchema;\n }\n\n get(target: Record<string, TableCRUD<TableSchema>>, prop: string) {\n if (prop in target) {\n return target[prop];\n }\n\n const txHolder: WithHiddenTxAndSchema = {\n [dbTxSymbol]: this.#dbTransaction,\n [serverSchemaSymbol]: this.#serverSchema,\n };\n target[prop] = Object.fromEntries(\n Object.entries(schemaCRUDs[prop]).map(([name, method]) => [\n name,\n method.bind(txHolder),\n ]),\n ) as TableCRUD<TableSchema>;\n\n return target[prop];\n }\n }\n\n return (dbTransaction: DBTransaction<unknown>, serverSchema: ServerSchema) =>\n new Proxy(\n {},\n new CRUDHandler(dbTransaction, serverSchema),\n ) as SchemaCRUD<S>;\n}\n\nfunction removeUndefined<T extends Record<string, unknown>>(value: T): T {\n const valueWithoutUndefined: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (val !== undefined) {\n valueWithoutUndefined[key] = val;\n }\n }\n return valueWithoutUndefined as T;\n}\n\nfunction makeTableCRUD(schema: TableSchema): TableCRUD<TableSchema> {\n return {\n async insert(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const stmt = formatPgInternalConvert(\n sql`INSERT INTO ${sql.ident(serverName(schema))} (${sql.join(\n targetedColumns.map(([, serverName]) => sql.ident(serverName)),\n ',',\n )}) VALUES (${sql.join(\n Object.entries(value).map(([col, v]) =>\n sqlInsertValue(v, serverTableSchema[serverNameFor(col, schema)]),\n ),\n ', ',\n )})`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async upsert(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const primaryKeyColumns = origAndServerNamesFor(\n schema.primaryKey,\n schema,\n );\n const stmt = formatPgInternalConvert(\n sql`INSERT INTO ${sql.ident(serverName(schema))} (${sql.join(\n targetedColumns.map(([, serverName]) => sql.ident(serverName)),\n ',',\n )}) VALUES (${sql.join(\n Object.entries(value).map(([col, val]) =>\n sqlInsertValue(val, serverTableSchema[serverNameFor(col, schema)]),\n ),\n ', ',\n )}) ON CONFLICT (${sql.join(\n primaryKeyColumns.map(([, serverName]) => sql.ident(serverName)),\n ', ',\n )}) DO UPDATE SET ${sql.join(\n Object.entries(value).map(\n ([col, val]) =>\n sql`${sql.ident(\n schema.columns[col].serverName ?? col,\n )} = ${sqlInsertValue(val, serverTableSchema[serverNameFor(col, schema)])}`,\n ),\n ', ',\n )}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async update(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const stmt = formatPgInternalConvert(\n sql`UPDATE ${sql.ident(serverName(schema))} SET ${sql.join(\n targetedColumns.map(\n ([origName, serverName]) =>\n sql`${sql.ident(serverName)} = ${sqlInsertValue(value[origName], serverTableSchema[serverName])}`,\n ),\n ', ',\n )} WHERE ${primaryKeyClause(schema, serverTableSchema, value)}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async delete(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const stmt = formatPgInternalConvert(\n sql`DELETE FROM ${sql.ident(\n serverName(schema),\n )} WHERE ${primaryKeyClause(schema, serverTableSchema, value)}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n };\n}\n\nfunction serverName(x: {name: string; serverName?: string | undefined}) {\n return x.serverName ?? x.name;\n}\n\nfunction primaryKeyClause(\n schema: TableSchema,\n serverTableSchema: ServerTableSchema,\n row: Record<string, unknown>,\n) {\n const primaryKey = origAndServerNamesFor(schema.primaryKey, schema);\n return sql`${sql.join(\n primaryKey.map(\n ([origName, serverName]) =>\n sql`${sql.ident(serverName)}${maybeCastColumn(serverTableSchema[serverName])} = ${sqlValue(row[origName], serverTableSchema[serverName])}`,\n ),\n ' AND ',\n )}`;\n}\n\nfunction maybeCastColumn(col: ServerColumnSchema) {\n if (col.type === 'uuid' || col.isEnum) {\n return sql`::text`;\n }\n return sql``;\n}\n\nfunction origAndServerNamesFor(\n originalNames: readonly string[],\n schema: TableSchema,\n): [origName: string, serverName: string][] {\n return originalNames.map(\n name => [name, serverNameFor(name, schema)] as const,\n );\n}\n\nfunction serverNameFor(originalName: string, schema: TableSchema): string {\n const col = schema.columns[originalName];\n assert(\n col,\n `Column ${originalName} was not found in the Zero schema for the table ${schema.name}`,\n );\n return col.serverName ?? originalName;\n}\n\nfunction sqlValue(value: unknown, serverColumnSchema: ServerColumnSchema) {\n return sqlConvertColumnArg(serverColumnSchema, value, false, true);\n}\n\nfunction sqlInsertValue(\n value: unknown,\n serverColumnSchema: ServerColumnSchema,\n) {\n return sqlConvertColumnArg(serverColumnSchema, value, false, false);\n}\n"],"names":["serverName"],"mappings":"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"}
|
|
@@ -4,6 +4,6 @@ export * from './custom.ts';
|
|
|
4
4
|
export * from './process-mutations.ts';
|
|
5
5
|
export * from './push-processor.ts';
|
|
6
6
|
export * from './queries/process-queries.ts';
|
|
7
|
-
export { handleTransformRequest, type TransformQueryFunction, } from './queries/process-queries.ts';
|
|
7
|
+
export { handleQueryRequest, handleTransformRequest, handleGetQueriesRequest, type TransformQueryFunction, } from './queries/process-queries.ts';
|
|
8
8
|
export * from './zql-database.ts';
|
|
9
9
|
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/mod.ts"],"names":[],"mappings":"AAAA,cAAc,8CAA8C,CAAC;AAC7D,cAAc,gCAAgC,CAAC;AAC/C,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EACL,sBAAsB,EACtB,KAAK,sBAAsB,GAC5B,MAAM,8BAA8B,CAAC;AACtC,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/mod.ts"],"names":[],"mappings":"AAAA,cAAc,8CAA8C,CAAC;AAC7D,cAAc,gCAAgC,CAAC;AAC/C,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,sBAAsB,GAC5B,MAAM,8BAA8B,CAAC;AACtC,cAAc,mBAAmB,CAAC"}
|
|
@@ -26,14 +26,18 @@ export interface Database<T> {
|
|
|
26
26
|
}
|
|
27
27
|
export type ExtractTransactionType<D> = D extends Database<infer T> ? T : never;
|
|
28
28
|
export type Params = v.Infer<typeof pushParamsSchema>;
|
|
29
|
-
export type TransactFn<D extends Database<ExtractTransactionType<D
|
|
30
|
-
export type TransactFnCallback<D extends Database<ExtractTransactionType<D
|
|
31
|
-
export type Parsed<D extends Database<ExtractTransactionType<D
|
|
32
|
-
transact: TransactFn<D
|
|
29
|
+
export type TransactFn<D extends Database<ExtractTransactionType<D>>> = (cb: TransactFnCallback<D>) => Promise<MutationResponse>;
|
|
30
|
+
export type TransactFnCallback<D extends Database<ExtractTransactionType<D>>> = (tx: ExtractTransactionType<D>, mutatorName: string, mutatorArgs: ReadonlyJSONValue | undefined) => Promise<void>;
|
|
31
|
+
export type Parsed<D extends Database<ExtractTransactionType<D>>> = {
|
|
32
|
+
transact: TransactFn<D>;
|
|
33
33
|
mutations: CustomMutation[];
|
|
34
34
|
};
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated Use {@linkcode handleMutateRequest} instead.
|
|
37
|
+
*/
|
|
38
|
+
export declare const handleMutationRequest: typeof handleMutateRequest;
|
|
39
|
+
export declare function handleMutateRequest<D extends Database<ExtractTransactionType<D>>>(dbProvider: D, cb: (transact: TransactFn<D>, mutation: CustomMutation) => Promise<MutationResponse>, queryString: URLSearchParams | Record<string, string>, body: ReadonlyJSONValue, logLevel?: LogLevel): Promise<PushResponse>;
|
|
40
|
+
export declare function handleMutateRequest<D extends Database<ExtractTransactionType<D>>>(dbProvider: D, cb: (transact: TransactFn<D>, mutation: CustomMutation) => Promise<MutationResponse>, request: Request, logLevel?: LogLevel): Promise<PushResponse>;
|
|
37
41
|
export declare class OutOfOrderMutation extends Error {
|
|
38
42
|
constructor(clientID: string, receivedMutationID: number, lastMutationID: number | bigint);
|
|
39
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-mutations.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/process-mutations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAG3D,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAEhE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,CAAC,MAAM,4BAA4B,CAAC;AAWhD,OAAO,EAEL,gBAAgB,EAChB,KAAK,cAAc,EAGnB,KAAK,gBAAgB,EAErB,KAAK,YAAY,EAClB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,0CAA0C,CAAC;AAEjF,OAAO,KAAK,EAAC,iBAAiB,EAAE,iBAAiB,EAAC,MAAM,aAAa,CAAC;AAGtE,MAAM,WAAW,wBAAwB;IACvC,sBAAsB,EAAE,MAAM,OAAO,CAAC;QAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAAA;KAAC,CAAC,CAAC;IACzE,mBAAmB,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC;IACzB,WAAW,EAAE,CAAC,CAAC,EACb,QAAQ,EAAE,CACR,EAAE,EAAE,CAAC,EACL,gBAAgB,EAAE,wBAAwB,KACvC,YAAY,CAAC,CAAC,CAAC,EACpB,gBAAgB,CAAC,EAAE,wBAAwB,KACxC,OAAO,CAAC,CAAC,CAAC,CAAC;CACjB;AAED,MAAM,MAAM,sBAAsB,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAChF,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEtD,MAAM,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"process-mutations.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/process-mutations.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,17 +20,16 @@ const applicationErrorWrapper = async (fn) => {
|
|
|
20
20
|
throw wrapWithApplicationError(error);
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
|
-
|
|
23
|
+
const handleMutationRequest = handleMutateRequest;
|
|
24
|
+
async function handleMutateRequest(dbProvider, cb, queryStringOrRequest, bodyOrLogLevel, logLevel) {
|
|
24
25
|
const isRequestOverload = queryStringOrRequest instanceof Request;
|
|
25
26
|
let request;
|
|
26
27
|
let queryString;
|
|
27
28
|
let jsonBody;
|
|
28
|
-
let context;
|
|
29
29
|
let lc;
|
|
30
30
|
if (isRequestOverload) {
|
|
31
31
|
request = queryStringOrRequest;
|
|
32
|
-
|
|
33
|
-
const level = contextOrLogLevel ?? "info";
|
|
32
|
+
const level = bodyOrLogLevel ?? "info";
|
|
34
33
|
lc = createLogContext(level).withContext("PushProcessor");
|
|
35
34
|
const url = new URL(request.url);
|
|
36
35
|
queryString = url.searchParams;
|
|
@@ -51,8 +50,7 @@ async function handleMutationRequest(dbProvider, cb, queryStringOrRequest, bodyO
|
|
|
51
50
|
}
|
|
52
51
|
} else {
|
|
53
52
|
queryString = queryStringOrRequest;
|
|
54
|
-
jsonBody =
|
|
55
|
-
context = contextOrLogLevel;
|
|
53
|
+
jsonBody = bodyOrLogLevel;
|
|
56
54
|
const level = logLevel ?? "info";
|
|
57
55
|
lc = createLogContext(level).withContext("PushProcessor");
|
|
58
56
|
}
|
|
@@ -107,13 +105,7 @@ async function handleMutationRequest(dbProvider, cb, queryStringOrRequest, bodyO
|
|
|
107
105
|
const responses = [];
|
|
108
106
|
let processedCount = 0;
|
|
109
107
|
try {
|
|
110
|
-
const transactor = new Transactor(
|
|
111
|
-
dbProvider,
|
|
112
|
-
pushBody,
|
|
113
|
-
queryParams,
|
|
114
|
-
lc,
|
|
115
|
-
context
|
|
116
|
-
);
|
|
108
|
+
const transactor = new Transactor(dbProvider, pushBody, queryParams, lc);
|
|
117
109
|
for (const m of pushBody.mutations) {
|
|
118
110
|
assert(m.type === "custom", "Expected custom mutation");
|
|
119
111
|
lc.debug?.(
|
|
@@ -125,7 +117,7 @@ async function handleMutationRequest(dbProvider, cb, queryStringOrRequest, bodyO
|
|
|
125
117
|
mutationPhase = "transactionPending";
|
|
126
118
|
const result = await transactor.transact(
|
|
127
119
|
m,
|
|
128
|
-
(tx, name, args) => applicationErrorWrapper(() => innerCb(tx, name, args
|
|
120
|
+
(tx, name, args) => applicationErrorWrapper(() => innerCb(tx, name, args))
|
|
129
121
|
);
|
|
130
122
|
mutationPhase = "postCommit";
|
|
131
123
|
return result;
|
|
@@ -178,13 +170,11 @@ class Transactor {
|
|
|
178
170
|
#req;
|
|
179
171
|
#params;
|
|
180
172
|
#lc;
|
|
181
|
-
|
|
182
|
-
constructor(dbProvider, req, params, lc, context) {
|
|
173
|
+
constructor(dbProvider, req, params, lc) {
|
|
183
174
|
this.#dbProvider = dbProvider;
|
|
184
175
|
this.#req = req;
|
|
185
176
|
this.#params = params;
|
|
186
177
|
this.#lc = lc;
|
|
187
|
-
this.#context = context;
|
|
188
178
|
}
|
|
189
179
|
transact = async (mutation, cb) => {
|
|
190
180
|
let appError = void 0;
|
|
@@ -258,7 +248,7 @@ class Transactor {
|
|
|
258
248
|
`Executing mutator '${mutation.name}' (id=${mutation.id})`
|
|
259
249
|
);
|
|
260
250
|
try {
|
|
261
|
-
await cb(dbTx, mutation.name, mutation.args[0]
|
|
251
|
+
await cb(dbTx, mutation.name, mutation.args[0]);
|
|
262
252
|
} catch (appError2) {
|
|
263
253
|
throw wrapWithApplicationError(appError2);
|
|
264
254
|
}
|
|
@@ -360,6 +350,7 @@ class DatabaseTransactionError extends Error {
|
|
|
360
350
|
export {
|
|
361
351
|
OutOfOrderMutation,
|
|
362
352
|
getMutation,
|
|
353
|
+
handleMutateRequest,
|
|
363
354
|
handleMutationRequest
|
|
364
355
|
};
|
|
365
356
|
//# sourceMappingURL=process-mutations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-mutations.js","sources":["../../../../zero-server/src/process-mutations.ts"],"sourcesContent":["import type {LogContext, LogLevel} from '@rocicorp/logger';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {getErrorDetails, getErrorMessage} from '../../shared/src/error.ts';\nimport type {ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {promiseVoid} from '../../shared/src/resolved-promises.ts';\nimport type {MaybePromise} from '../../shared/src/types.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {MutationAlreadyProcessedError} from '../../zero-cache/src/services/mutagen/error.ts';\nimport type {ApplicationError} from '../../zero-protocol/src/application-error.ts';\nimport {\n isApplicationError,\n wrapWithApplicationError,\n} from '../../zero-protocol/src/application-error.ts';\nimport {ErrorKind} from '../../zero-protocol/src/error-kind.ts';\nimport {ErrorOrigin} from '../../zero-protocol/src/error-origin.ts';\nimport {ErrorReason} from '../../zero-protocol/src/error-reason.ts';\nimport type {PushFailedBody} from '../../zero-protocol/src/error.ts';\nimport {\n pushBodySchema,\n pushParamsSchema,\n type CustomMutation,\n type Mutation,\n type MutationID,\n type MutationResponse,\n type PushBody,\n type PushResponse,\n} from '../../zero-protocol/src/push.ts';\nimport type {AnyMutatorRegistry} from '../../zql/src/mutate/mutator-registry.ts';\nimport {isMutator} from '../../zql/src/mutate/mutator.ts';\nimport type {CustomMutatorDefs, CustomMutatorImpl} from './custom.ts';\nimport {createLogContext} from './logging.ts';\n\nexport interface TransactionProviderHooks {\n updateClientMutationID: () => Promise<{lastMutationID: number | bigint}>;\n writeMutationResult: (result: MutationResponse) => Promise<void>;\n}\n\nexport interface TransactionProviderInput {\n upstreamSchema: string;\n clientGroupID: string;\n clientID: string;\n mutationID: number;\n}\n\n/**\n * Defines the abstract interface for a database that PushProcessor can execute\n * transactions against.\n */\nexport interface Database<T> {\n transaction: <R>(\n callback: (\n tx: T,\n transactionHooks: TransactionProviderHooks,\n ) => MaybePromise<R>,\n transactionInput?: TransactionProviderInput,\n ) => Promise<R>;\n}\n\nexport type ExtractTransactionType<D> = D extends Database<infer T> ? T : never;\nexport type Params = v.Infer<typeof pushParamsSchema>;\n\nexport type TransactFn<\n D extends Database<ExtractTransactionType<D>>,\n Context,\n> = (cb: TransactFnCallback<D, Context>) => Promise<MutationResponse>;\n\nexport type TransactFnCallback<\n D extends Database<ExtractTransactionType<D>>,\n Context,\n> = (\n tx: ExtractTransactionType<D>,\n mutatorName: string,\n mutatorArgs: ReadonlyJSONValue | undefined,\n ctx: Context,\n) => Promise<void>;\n\nexport type Parsed<D extends Database<ExtractTransactionType<D>>, Context> = {\n transact: TransactFn<D, Context>;\n mutations: CustomMutation[];\n};\n\ntype MutationPhase = 'preTransaction' | 'transactionPending' | 'postCommit';\n\nconst applicationErrorWrapper = async <T>(fn: () => Promise<T>): Promise<T> => {\n try {\n return await fn();\n } catch (error) {\n if (\n error instanceof DatabaseTransactionError ||\n error instanceof OutOfOrderMutation ||\n error instanceof MutationAlreadyProcessedError ||\n isApplicationError(error)\n ) {\n throw error;\n }\n\n throw wrapWithApplicationError(error);\n }\n};\n\nexport function handleMutationRequest<\n D extends Database<ExtractTransactionType<D>>,\n C = undefined,\n>(\n dbProvider: D,\n cb: (\n transact: TransactFn<D, C>,\n mutation: CustomMutation,\n ) => Promise<MutationResponse>,\n queryString: URLSearchParams | Record<string, string>,\n body: ReadonlyJSONValue,\n context?: C,\n logLevel?: LogLevel,\n): Promise<PushResponse>;\n\nexport function handleMutationRequest<\n D extends Database<ExtractTransactionType<D>>,\n C = undefined,\n>(\n dbProvider: D,\n cb: (\n transact: TransactFn<D, C>,\n mutation: CustomMutation,\n ) => Promise<MutationResponse>,\n request: Request,\n context?: C,\n logLevel?: LogLevel,\n): Promise<PushResponse>;\n\nexport async function handleMutationRequest<\n D extends Database<ExtractTransactionType<D>>,\n C,\n>(\n dbProvider: D,\n cb: (\n transact: TransactFn<D, C>,\n mutation: CustomMutation,\n ) => Promise<MutationResponse>,\n queryStringOrRequest: Request | URLSearchParams | Record<string, string>,\n bodyOrContext: ReadonlyJSONValue | C,\n contextOrLogLevel?: C | LogLevel,\n logLevel?: LogLevel,\n): Promise<PushResponse> {\n // Parse overload arguments\n const isRequestOverload = queryStringOrRequest instanceof Request;\n\n let request: Request | undefined;\n let queryString: URLSearchParams | Record<string, string>;\n let jsonBody: unknown;\n let context: C;\n let lc: LogContext;\n\n if (isRequestOverload) {\n request = queryStringOrRequest;\n context = bodyOrContext as C;\n const level = (contextOrLogLevel as LogLevel | undefined) ?? 'info';\n\n // Create log context early, before extracting JSON from Request\n lc = createLogContext(level).withContext('PushProcessor');\n\n const url = new URL(request.url);\n queryString = url.searchParams;\n\n try {\n jsonBody = await request.json();\n } catch (error) {\n lc.error?.('Failed to parse push body', error);\n const message = `Failed to parse push body: ${getErrorMessage(error)}`;\n const details = getErrorDetails(error);\n return {\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.Server,\n reason: ErrorReason.Parse,\n message,\n mutationIDs: [],\n ...(details ? {details} : {}),\n } as const satisfies PushFailedBody;\n }\n } else {\n queryString = queryStringOrRequest;\n jsonBody = bodyOrContext;\n context = contextOrLogLevel as C;\n const level = logLevel ?? 'info';\n lc = createLogContext(level).withContext('PushProcessor');\n }\n\n let mutationIDs: MutationID[] = [];\n\n let pushBody: PushBody;\n try {\n pushBody = v.parse(jsonBody, pushBodySchema);\n mutationIDs = pushBody.mutations.map(m => ({\n id: m.id,\n clientID: m.clientID,\n }));\n } catch (error) {\n lc.error?.('Failed to parse push body', error);\n const message = `Failed to parse push body: ${getErrorMessage(error)}`;\n const details = getErrorDetails(error);\n return {\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.Server,\n reason: ErrorReason.Parse,\n message,\n mutationIDs,\n ...(details ? {details} : {}),\n } as const satisfies PushFailedBody;\n }\n\n let queryParams: Params;\n try {\n const queryStringObj =\n queryString instanceof URLSearchParams\n ? Object.fromEntries(queryString)\n : queryString;\n queryParams = v.parse(queryStringObj, pushParamsSchema, 'passthrough');\n } catch (error) {\n lc.error?.('Failed to parse push query parameters', error);\n const message = `Failed to parse push query parameters: ${getErrorMessage(error)}`;\n const details = getErrorDetails(error);\n return {\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.Server,\n reason: ErrorReason.Parse,\n message,\n mutationIDs,\n ...(details ? {details} : {}),\n } as const satisfies PushFailedBody;\n }\n\n if (pushBody.pushVersion !== 1) {\n const response = {\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.Server,\n reason: ErrorReason.UnsupportedPushVersion,\n mutationIDs,\n message: `Unsupported push version: ${pushBody.pushVersion}`,\n } as const satisfies PushFailedBody;\n return response;\n }\n\n const responses: MutationResponse[] = [];\n let processedCount = 0;\n\n try {\n const transactor = new Transactor(\n dbProvider,\n pushBody,\n queryParams,\n lc,\n context,\n );\n\n // Each mutation goes through three phases:\n // 1. Pre-transaction: user logic that runs before `transact` is called. If\n // this throws we still advance LMID and persist the failure result.\n // 2. Transaction: the callback passed to `transact`, which can be retried\n // if it fails with an ApplicationError.\n // 3. Post-commit: any logic that runs after `transact` resolves. Failures\n // here are logged but the mutation remains committed.\n for (const m of pushBody.mutations) {\n assert(m.type === 'custom', 'Expected custom mutation');\n lc.debug?.(\n `Processing mutation '${m.name}' (id=${m.id}, clientID=${m.clientID})`,\n m.args,\n );\n\n let mutationPhase: MutationPhase = 'preTransaction';\n\n const transactProxy: TransactFn<D, C> = async innerCb => {\n mutationPhase = 'transactionPending';\n const result = await transactor.transact(m, (tx, name, args) =>\n applicationErrorWrapper(() => innerCb(tx, name, args, context)),\n );\n mutationPhase = 'postCommit';\n return result;\n };\n\n try {\n const res = await applicationErrorWrapper(() => cb(transactProxy, m));\n responses.push(res);\n lc.debug?.(`Mutation '${m.name}' (id=${m.id}) completed successfully`);\n\n processedCount++;\n } catch (error) {\n if (!isApplicationError(error)) {\n throw error;\n }\n\n if (mutationPhase === 'preTransaction') {\n // Pre-transaction\n await transactor.persistPreTransactionFailure(m, error);\n } else if (mutationPhase === 'postCommit') {\n // Post-commit\n lc.error?.(\n `Post-commit mutation handler failed for mutation ${m.id} for client ${m.clientID}`,\n error,\n );\n }\n\n lc.warn?.(\n `Application error processing mutation ${m.id} for client ${m.clientID}`,\n error,\n );\n responses.push(makeAppErrorResponse(m, error));\n\n processedCount++;\n }\n }\n\n return {\n mutations: responses,\n };\n } catch (error) {\n lc.error?.('Failed to process push request', error);\n // only include mutationIDs for mutations that were not processed\n const unprocessedMutationIDs = mutationIDs.slice(processedCount);\n\n const message = getErrorMessage(error);\n const details = getErrorDetails(error);\n\n return {\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.Server,\n reason:\n error instanceof OutOfOrderMutation\n ? ErrorReason.OutOfOrderMutation\n : error instanceof DatabaseTransactionError\n ? ErrorReason.Database\n : ErrorReason.Internal,\n message,\n mutationIDs: unprocessedMutationIDs,\n ...(details ? {details} : {}),\n };\n }\n}\n\nclass Transactor<D extends Database<ExtractTransactionType<D>>, Context> {\n readonly #dbProvider: D;\n readonly #req: PushBody;\n readonly #params: Params;\n readonly #lc: LogContext;\n readonly #context: Context;\n\n constructor(\n dbProvider: D,\n req: PushBody,\n params: Params,\n lc: LogContext,\n context: Context,\n ) {\n this.#dbProvider = dbProvider;\n this.#req = req;\n this.#params = params;\n this.#lc = lc;\n this.#context = context;\n }\n\n transact = async (\n mutation: CustomMutation,\n cb: TransactFnCallback<D, Context>,\n ): Promise<MutationResponse> => {\n let appError: ApplicationError | undefined = undefined;\n for (;;) {\n try {\n const ret = await this.#transactImpl(mutation, cb, appError);\n if (appError !== undefined) {\n this.#lc.warn?.(\n `Mutation ${mutation.id} for client ${mutation.clientID} was retried after an error`,\n appError,\n );\n return makeAppErrorResponse(mutation, appError);\n }\n\n return ret;\n } catch (error) {\n if (error instanceof OutOfOrderMutation) {\n this.#lc.error?.(error);\n throw error;\n }\n\n if (error instanceof MutationAlreadyProcessedError) {\n this.#lc.warn?.(error);\n return {\n id: {\n clientID: mutation.clientID,\n id: mutation.id,\n },\n result: {\n error: 'alreadyProcessed',\n details: error.message,\n },\n };\n }\n\n if (isApplicationError(error)) {\n appError = error;\n this.#lc.warn?.(\n `Application error processing mutation ${mutation.id} for client ${mutation.clientID}`,\n appError,\n );\n continue;\n }\n\n this.#lc.error?.(\n `Unexpected error processing mutation ${mutation.id} for client ${mutation.clientID}`,\n error,\n );\n\n throw error;\n }\n }\n };\n\n async persistPreTransactionFailure(\n mutation: CustomMutation,\n appError: ApplicationError<ReadonlyJSONValue | undefined>,\n ): Promise<MutationResponse> {\n // User-land code threw before calling `transact`. We still need to bump the\n // LMID for this mutation and persist the error so that the client knows it failed.\n const ret = await this.#transactImpl(\n mutation,\n // noop callback since there's no transaction to execute\n () => promiseVoid,\n appError,\n );\n return ret;\n }\n\n async #transactImpl(\n mutation: CustomMutation,\n cb: TransactFnCallback<D, Context>,\n appError: ApplicationError | undefined,\n ): Promise<MutationResponse> {\n let transactionPhase: DatabaseTransactionPhase = 'open';\n\n try {\n const ret = await this.#dbProvider.transaction(\n async (dbTx, transactionHooks) => {\n // update the transaction phase to 'execute' after the transaction is opened\n transactionPhase = 'execute';\n\n await this.#checkAndIncrementLastMutationID(\n transactionHooks,\n mutation.clientID,\n mutation.id,\n );\n\n if (appError === undefined) {\n this.#lc.debug?.(\n `Executing mutator '${mutation.name}' (id=${mutation.id})`,\n );\n try {\n await cb(dbTx, mutation.name, mutation.args[0], this.#context);\n } catch (appError) {\n throw wrapWithApplicationError(appError);\n }\n } else {\n const mutationResult = makeAppErrorResponse(mutation, appError);\n await transactionHooks.writeMutationResult(mutationResult);\n }\n\n return {\n id: {\n clientID: mutation.clientID,\n id: mutation.id,\n },\n result: {},\n };\n },\n this.#getTransactionInput(mutation),\n );\n\n return ret;\n } catch (error) {\n if (\n isApplicationError(error) ||\n error instanceof OutOfOrderMutation ||\n error instanceof MutationAlreadyProcessedError\n ) {\n throw error;\n }\n\n throw new DatabaseTransactionError(transactionPhase, {cause: error});\n }\n }\n\n #getTransactionInput(mutation: CustomMutation): TransactionProviderInput {\n return {\n upstreamSchema: this.#params.schema,\n clientGroupID: this.#req.clientGroupID,\n clientID: mutation.clientID,\n mutationID: mutation.id,\n };\n }\n\n async #checkAndIncrementLastMutationID(\n transactionHooks: TransactionProviderHooks,\n clientID: string,\n receivedMutationID: number,\n ) {\n const {lastMutationID} = await transactionHooks.updateClientMutationID();\n\n if (receivedMutationID < lastMutationID) {\n throw new MutationAlreadyProcessedError(\n clientID,\n receivedMutationID,\n lastMutationID,\n );\n } else if (receivedMutationID > lastMutationID) {\n throw new OutOfOrderMutation(\n clientID,\n receivedMutationID,\n lastMutationID,\n );\n }\n }\n}\n\nexport class OutOfOrderMutation extends Error {\n constructor(\n clientID: string,\n receivedMutationID: number,\n lastMutationID: number | bigint,\n ) {\n super(\n `Client ${clientID} sent mutation ID ${receivedMutationID} but expected ${lastMutationID}`,\n );\n }\n}\n\nfunction makeAppErrorResponse(\n m: Mutation,\n error: ApplicationError<ReadonlyJSONValue | undefined>,\n): MutationResponse {\n return {\n id: {\n clientID: m.clientID,\n id: m.id,\n },\n result: {\n error: 'app',\n message: error.message,\n ...(error.details ? {details: error.details} : {}),\n },\n };\n}\n\n/** @deprecated Use getMutator instead */\nexport function getMutation(\n // oxlint-disable-next-line no-explicit-any\n mutators: AnyMutatorRegistry | CustomMutatorDefs<any>,\n name: string,\n // oxlint-disable-next-line no-explicit-any\n): CustomMutatorImpl<any> {\n const path = name.split(/\\.|\\|/);\n const mutator = getObjectAtPath(mutators, path);\n assert(typeof mutator === 'function', `could not find mutator ${name}`);\n\n if (isMutator(mutator)) {\n // mutator needs to be called with {tx, args, ctx}\n // CustomMutatorImpl is called with (tx, args, ctx)\n return (tx, args, ctx) => mutator.fn({args, ctx, tx});\n }\n\n // oxlint-disable-next-line no-explicit-any\n return mutator as CustomMutatorImpl<any>;\n}\n\nfunction getObjectAtPath(\n obj: Record<string, unknown>,\n path: string[],\n): unknown {\n let current: unknown = obj;\n for (const part of path) {\n if (typeof current !== 'object' || current === null || !(part in current)) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n\ntype DatabaseTransactionPhase = 'open' | 'execute';\nclass DatabaseTransactionError extends Error {\n constructor(phase: DatabaseTransactionPhase, options?: ErrorOptions) {\n super(\n phase === 'open'\n ? `Failed to open database transaction: ${getErrorMessage(options?.cause)}`\n : `Database transaction failed after opening: ${getErrorMessage(options?.cause)}`,\n options,\n );\n this.name = 'DatabaseTransactionError';\n }\n}\n"],"names":["ErrorKind.PushFailed","ErrorOrigin.Server","ErrorReason.Parse","v.parse","ErrorReason.UnsupportedPushVersion","ErrorReason.OutOfOrderMutation","ErrorReason.Database","ErrorReason.Internal","appError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"process-mutations.js","sources":["../../../../zero-server/src/process-mutations.ts"],"sourcesContent":["import type {LogContext, LogLevel} from '@rocicorp/logger';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {getErrorDetails, getErrorMessage} from '../../shared/src/error.ts';\nimport type {ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {promiseVoid} from '../../shared/src/resolved-promises.ts';\nimport type {MaybePromise} from '../../shared/src/types.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {MutationAlreadyProcessedError} from '../../zero-cache/src/services/mutagen/error.ts';\nimport type {ApplicationError} from '../../zero-protocol/src/application-error.ts';\nimport {\n isApplicationError,\n wrapWithApplicationError,\n} from '../../zero-protocol/src/application-error.ts';\nimport {ErrorKind} from '../../zero-protocol/src/error-kind.ts';\nimport {ErrorOrigin} from '../../zero-protocol/src/error-origin.ts';\nimport {ErrorReason} from '../../zero-protocol/src/error-reason.ts';\nimport type {PushFailedBody} from '../../zero-protocol/src/error.ts';\nimport {\n pushBodySchema,\n pushParamsSchema,\n type CustomMutation,\n type Mutation,\n type MutationID,\n type MutationResponse,\n type PushBody,\n type PushResponse,\n} from '../../zero-protocol/src/push.ts';\nimport type {AnyMutatorRegistry} from '../../zql/src/mutate/mutator-registry.ts';\nimport {isMutator} from '../../zql/src/mutate/mutator.ts';\nimport type {CustomMutatorDefs, CustomMutatorImpl} from './custom.ts';\nimport {createLogContext} from './logging.ts';\n\nexport interface TransactionProviderHooks {\n updateClientMutationID: () => Promise<{lastMutationID: number | bigint}>;\n writeMutationResult: (result: MutationResponse) => Promise<void>;\n}\n\nexport interface TransactionProviderInput {\n upstreamSchema: string;\n clientGroupID: string;\n clientID: string;\n mutationID: number;\n}\n\n/**\n * Defines the abstract interface for a database that PushProcessor can execute\n * transactions against.\n */\nexport interface Database<T> {\n transaction: <R>(\n callback: (\n tx: T,\n transactionHooks: TransactionProviderHooks,\n ) => MaybePromise<R>,\n transactionInput?: TransactionProviderInput,\n ) => Promise<R>;\n}\n\nexport type ExtractTransactionType<D> = D extends Database<infer T> ? T : never;\nexport type Params = v.Infer<typeof pushParamsSchema>;\n\nexport type TransactFn<D extends Database<ExtractTransactionType<D>>> = (\n cb: TransactFnCallback<D>,\n) => Promise<MutationResponse>;\n\nexport type TransactFnCallback<D extends Database<ExtractTransactionType<D>>> =\n (\n tx: ExtractTransactionType<D>,\n mutatorName: string,\n mutatorArgs: ReadonlyJSONValue | undefined,\n ) => Promise<void>;\n\nexport type Parsed<D extends Database<ExtractTransactionType<D>>> = {\n transact: TransactFn<D>;\n mutations: CustomMutation[];\n};\n\ntype MutationPhase = 'preTransaction' | 'transactionPending' | 'postCommit';\n\nconst applicationErrorWrapper = async <T>(fn: () => Promise<T>): Promise<T> => {\n try {\n return await fn();\n } catch (error) {\n if (\n error instanceof DatabaseTransactionError ||\n error instanceof OutOfOrderMutation ||\n error instanceof MutationAlreadyProcessedError ||\n isApplicationError(error)\n ) {\n throw error;\n }\n\n throw wrapWithApplicationError(error);\n }\n};\n\n/**\n * @deprecated Use {@linkcode handleMutateRequest} instead.\n */\nexport const handleMutationRequest = handleMutateRequest;\n\nexport function handleMutateRequest<\n D extends Database<ExtractTransactionType<D>>,\n>(\n dbProvider: D,\n cb: (\n transact: TransactFn<D>,\n mutation: CustomMutation,\n ) => Promise<MutationResponse>,\n queryString: URLSearchParams | Record<string, string>,\n body: ReadonlyJSONValue,\n logLevel?: LogLevel,\n): Promise<PushResponse>;\n\nexport function handleMutateRequest<\n D extends Database<ExtractTransactionType<D>>,\n>(\n dbProvider: D,\n cb: (\n transact: TransactFn<D>,\n mutation: CustomMutation,\n ) => Promise<MutationResponse>,\n request: Request,\n logLevel?: LogLevel,\n): Promise<PushResponse>;\n\nexport async function handleMutateRequest<\n D extends Database<ExtractTransactionType<D>>,\n>(\n dbProvider: D,\n cb: (\n transact: TransactFn<D>,\n mutation: CustomMutation,\n ) => Promise<MutationResponse>,\n queryStringOrRequest: Request | URLSearchParams | Record<string, string>,\n bodyOrLogLevel?: ReadonlyJSONValue | LogLevel,\n logLevel?: LogLevel,\n): Promise<PushResponse> {\n // Parse overload arguments\n const isRequestOverload = queryStringOrRequest instanceof Request;\n\n let request: Request | undefined;\n let queryString: URLSearchParams | Record<string, string>;\n let jsonBody: unknown;\n\n let lc: LogContext;\n\n if (isRequestOverload) {\n request = queryStringOrRequest;\n const level = (bodyOrLogLevel as LogLevel | undefined) ?? 'info';\n\n // Create log context early, before extracting JSON from Request\n lc = createLogContext(level).withContext('PushProcessor');\n\n const url = new URL(request.url);\n queryString = url.searchParams;\n\n try {\n jsonBody = await request.json();\n } catch (error) {\n lc.error?.('Failed to parse push body', error);\n const message = `Failed to parse push body: ${getErrorMessage(error)}`;\n const details = getErrorDetails(error);\n return {\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.Server,\n reason: ErrorReason.Parse,\n message,\n mutationIDs: [],\n ...(details ? {details} : {}),\n } as const satisfies PushFailedBody;\n }\n } else {\n queryString = queryStringOrRequest;\n jsonBody = bodyOrLogLevel;\n const level = logLevel ?? 'info';\n lc = createLogContext(level).withContext('PushProcessor');\n }\n\n let mutationIDs: MutationID[] = [];\n\n let pushBody: PushBody;\n try {\n pushBody = v.parse(jsonBody, pushBodySchema);\n mutationIDs = pushBody.mutations.map(m => ({\n id: m.id,\n clientID: m.clientID,\n }));\n } catch (error) {\n lc.error?.('Failed to parse push body', error);\n const message = `Failed to parse push body: ${getErrorMessage(error)}`;\n const details = getErrorDetails(error);\n return {\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.Server,\n reason: ErrorReason.Parse,\n message,\n mutationIDs,\n ...(details ? {details} : {}),\n } as const satisfies PushFailedBody;\n }\n\n let queryParams: Params;\n try {\n const queryStringObj =\n queryString instanceof URLSearchParams\n ? Object.fromEntries(queryString)\n : queryString;\n queryParams = v.parse(queryStringObj, pushParamsSchema, 'passthrough');\n } catch (error) {\n lc.error?.('Failed to parse push query parameters', error);\n const message = `Failed to parse push query parameters: ${getErrorMessage(error)}`;\n const details = getErrorDetails(error);\n return {\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.Server,\n reason: ErrorReason.Parse,\n message,\n mutationIDs,\n ...(details ? {details} : {}),\n } as const satisfies PushFailedBody;\n }\n\n if (pushBody.pushVersion !== 1) {\n const response = {\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.Server,\n reason: ErrorReason.UnsupportedPushVersion,\n mutationIDs,\n message: `Unsupported push version: ${pushBody.pushVersion}`,\n } as const satisfies PushFailedBody;\n return response;\n }\n\n const responses: MutationResponse[] = [];\n let processedCount = 0;\n\n try {\n const transactor = new Transactor(dbProvider, pushBody, queryParams, lc);\n\n // Each mutation goes through three phases:\n // 1. Pre-transaction: user logic that runs before `transact` is called. If\n // this throws we still advance LMID and persist the failure result.\n // 2. Transaction: the callback passed to `transact`, which can be retried\n // if it fails with an ApplicationError.\n // 3. Post-commit: any logic that runs after `transact` resolves. Failures\n // here are logged but the mutation remains committed.\n for (const m of pushBody.mutations) {\n assert(m.type === 'custom', 'Expected custom mutation');\n lc.debug?.(\n `Processing mutation '${m.name}' (id=${m.id}, clientID=${m.clientID})`,\n m.args,\n );\n\n let mutationPhase: MutationPhase = 'preTransaction';\n\n const transactProxy: TransactFn<D> = async innerCb => {\n mutationPhase = 'transactionPending';\n const result = await transactor.transact(m, (tx, name, args) =>\n applicationErrorWrapper(() => innerCb(tx, name, args)),\n );\n mutationPhase = 'postCommit';\n return result;\n };\n\n try {\n const res = await applicationErrorWrapper(() => cb(transactProxy, m));\n responses.push(res);\n lc.debug?.(`Mutation '${m.name}' (id=${m.id}) completed successfully`);\n\n processedCount++;\n } catch (error) {\n if (!isApplicationError(error)) {\n throw error;\n }\n\n if (mutationPhase === 'preTransaction') {\n // Pre-transaction\n await transactor.persistPreTransactionFailure(m, error);\n } else if (mutationPhase === 'postCommit') {\n // Post-commit\n lc.error?.(\n `Post-commit mutation handler failed for mutation ${m.id} for client ${m.clientID}`,\n error,\n );\n }\n\n lc.warn?.(\n `Application error processing mutation ${m.id} for client ${m.clientID}`,\n error,\n );\n responses.push(makeAppErrorResponse(m, error));\n\n processedCount++;\n }\n }\n\n return {\n mutations: responses,\n };\n } catch (error) {\n lc.error?.('Failed to process push request', error);\n // only include mutationIDs for mutations that were not processed\n const unprocessedMutationIDs = mutationIDs.slice(processedCount);\n\n const message = getErrorMessage(error);\n const details = getErrorDetails(error);\n\n return {\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.Server,\n reason:\n error instanceof OutOfOrderMutation\n ? ErrorReason.OutOfOrderMutation\n : error instanceof DatabaseTransactionError\n ? ErrorReason.Database\n : ErrorReason.Internal,\n message,\n mutationIDs: unprocessedMutationIDs,\n ...(details ? {details} : {}),\n };\n }\n}\n\nclass Transactor<D extends Database<ExtractTransactionType<D>>> {\n readonly #dbProvider: D;\n readonly #req: PushBody;\n readonly #params: Params;\n readonly #lc: LogContext;\n\n constructor(dbProvider: D, req: PushBody, params: Params, lc: LogContext) {\n this.#dbProvider = dbProvider;\n this.#req = req;\n this.#params = params;\n this.#lc = lc;\n }\n\n transact = async (\n mutation: CustomMutation,\n cb: TransactFnCallback<D>,\n ): Promise<MutationResponse> => {\n let appError: ApplicationError | undefined = undefined;\n for (;;) {\n try {\n const ret = await this.#transactImpl(mutation, cb, appError);\n if (appError !== undefined) {\n this.#lc.warn?.(\n `Mutation ${mutation.id} for client ${mutation.clientID} was retried after an error`,\n appError,\n );\n return makeAppErrorResponse(mutation, appError);\n }\n\n return ret;\n } catch (error) {\n if (error instanceof OutOfOrderMutation) {\n this.#lc.error?.(error);\n throw error;\n }\n\n if (error instanceof MutationAlreadyProcessedError) {\n this.#lc.warn?.(error);\n return {\n id: {\n clientID: mutation.clientID,\n id: mutation.id,\n },\n result: {\n error: 'alreadyProcessed',\n details: error.message,\n },\n };\n }\n\n if (isApplicationError(error)) {\n appError = error;\n this.#lc.warn?.(\n `Application error processing mutation ${mutation.id} for client ${mutation.clientID}`,\n appError,\n );\n continue;\n }\n\n this.#lc.error?.(\n `Unexpected error processing mutation ${mutation.id} for client ${mutation.clientID}`,\n error,\n );\n\n throw error;\n }\n }\n };\n\n async persistPreTransactionFailure(\n mutation: CustomMutation,\n appError: ApplicationError<ReadonlyJSONValue | undefined>,\n ): Promise<MutationResponse> {\n // User-land code threw before calling `transact`. We still need to bump the\n // LMID for this mutation and persist the error so that the client knows it failed.\n const ret = await this.#transactImpl(\n mutation,\n // noop callback since there's no transaction to execute\n () => promiseVoid,\n appError,\n );\n return ret;\n }\n\n async #transactImpl(\n mutation: CustomMutation,\n cb: TransactFnCallback<D>,\n appError: ApplicationError | undefined,\n ): Promise<MutationResponse> {\n let transactionPhase: DatabaseTransactionPhase = 'open';\n\n try {\n const ret = await this.#dbProvider.transaction(\n async (dbTx, transactionHooks) => {\n // update the transaction phase to 'execute' after the transaction is opened\n transactionPhase = 'execute';\n\n await this.#checkAndIncrementLastMutationID(\n transactionHooks,\n mutation.clientID,\n mutation.id,\n );\n\n if (appError === undefined) {\n this.#lc.debug?.(\n `Executing mutator '${mutation.name}' (id=${mutation.id})`,\n );\n try {\n await cb(dbTx, mutation.name, mutation.args[0]);\n } catch (appError) {\n throw wrapWithApplicationError(appError);\n }\n } else {\n const mutationResult = makeAppErrorResponse(mutation, appError);\n await transactionHooks.writeMutationResult(mutationResult);\n }\n\n return {\n id: {\n clientID: mutation.clientID,\n id: mutation.id,\n },\n result: {},\n };\n },\n this.#getTransactionInput(mutation),\n );\n\n return ret;\n } catch (error) {\n if (\n isApplicationError(error) ||\n error instanceof OutOfOrderMutation ||\n error instanceof MutationAlreadyProcessedError\n ) {\n throw error;\n }\n\n throw new DatabaseTransactionError(transactionPhase, {cause: error});\n }\n }\n\n #getTransactionInput(mutation: CustomMutation): TransactionProviderInput {\n return {\n upstreamSchema: this.#params.schema,\n clientGroupID: this.#req.clientGroupID,\n clientID: mutation.clientID,\n mutationID: mutation.id,\n };\n }\n\n async #checkAndIncrementLastMutationID(\n transactionHooks: TransactionProviderHooks,\n clientID: string,\n receivedMutationID: number,\n ) {\n const {lastMutationID} = await transactionHooks.updateClientMutationID();\n\n if (receivedMutationID < lastMutationID) {\n throw new MutationAlreadyProcessedError(\n clientID,\n receivedMutationID,\n lastMutationID,\n );\n } else if (receivedMutationID > lastMutationID) {\n throw new OutOfOrderMutation(\n clientID,\n receivedMutationID,\n lastMutationID,\n );\n }\n }\n}\n\nexport class OutOfOrderMutation extends Error {\n constructor(\n clientID: string,\n receivedMutationID: number,\n lastMutationID: number | bigint,\n ) {\n super(\n `Client ${clientID} sent mutation ID ${receivedMutationID} but expected ${lastMutationID}`,\n );\n }\n}\n\nfunction makeAppErrorResponse(\n m: Mutation,\n error: ApplicationError<ReadonlyJSONValue | undefined>,\n): MutationResponse {\n return {\n id: {\n clientID: m.clientID,\n id: m.id,\n },\n result: {\n error: 'app',\n message: error.message,\n ...(error.details ? {details: error.details} : {}),\n },\n };\n}\n\n/** @deprecated Use getMutator instead */\nexport function getMutation(\n // oxlint-disable-next-line no-explicit-any\n mutators: AnyMutatorRegistry | CustomMutatorDefs<any>,\n name: string,\n // oxlint-disable-next-line no-explicit-any\n): CustomMutatorImpl<any> {\n const path = name.split(/\\.|\\|/);\n const mutator = getObjectAtPath(mutators, path);\n assert(typeof mutator === 'function', `could not find mutator ${name}`);\n\n if (isMutator(mutator)) {\n // mutator needs to be called with {tx, args, ctx}\n // CustomMutatorImpl is called with (tx, args, ctx)\n return (tx, args, ctx) => mutator.fn({args, ctx, tx});\n }\n\n // oxlint-disable-next-line no-explicit-any\n return mutator as CustomMutatorImpl<any>;\n}\n\nfunction getObjectAtPath(\n obj: Record<string, unknown>,\n path: string[],\n): unknown {\n let current: unknown = obj;\n for (const part of path) {\n if (typeof current !== 'object' || current === null || !(part in current)) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n\ntype DatabaseTransactionPhase = 'open' | 'execute';\nclass DatabaseTransactionError extends Error {\n constructor(phase: DatabaseTransactionPhase, options?: ErrorOptions) {\n super(\n phase === 'open'\n ? `Failed to open database transaction: ${getErrorMessage(options?.cause)}`\n : `Database transaction failed after opening: ${getErrorMessage(options?.cause)}`,\n options,\n );\n this.name = 'DatabaseTransactionError';\n }\n}\n"],"names":["ErrorKind.PushFailed","ErrorOrigin.Server","ErrorReason.Parse","v.parse","ErrorReason.UnsupportedPushVersion","ErrorReason.OutOfOrderMutation","ErrorReason.Database","ErrorReason.Internal","appError"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push-processor.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/push-processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAGhE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,sBAAsB,EAG5B,MAAM,4CAA4C,CAAC;AACpD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAE3D,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,0CAA0C,CAAC;AAEjF,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,aAAa,CAAC;AAEnD,qBAAa,aAAa,CACxB,EAAE,SAAS,MAAM,EACjB,CAAC,SAAS,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,EAC7C,EAAE,SAAS,kBAAkB,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,EAC5E,CAAC,GAAG,SAAS;;gBAMD,UAAU,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,QAAQ,GAAE,QAAiB;IAMnE;;;;;;;;;;OAUG;IACH,OAAO,CACL,QAAQ,EAAE,EAAE,EACZ,WAAW,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrD,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,YAAY,CAAC;IAExB;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"push-processor.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/push-processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAGhE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,sBAAsB,EAG5B,MAAM,4CAA4C,CAAC;AACpD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAE3D,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,0CAA0C,CAAC;AAEjF,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,aAAa,CAAC;AAEnD,qBAAa,aAAa,CACxB,EAAE,SAAS,MAAM,EACjB,CAAC,SAAS,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,EAC7C,EAAE,SAAS,kBAAkB,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,EAC5E,CAAC,GAAG,SAAS;;gBAMD,UAAU,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,QAAQ,GAAE,QAAiB;IAMnE;;;;;;;;;;OAUG;IACH,OAAO,CACL,QAAQ,EAAE,EAAE,EACZ,WAAW,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrD,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,YAAY,CAAC;IAExB;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC;CAqD/D"}
|
|
@@ -3,7 +3,7 @@ import { assert } from "../../shared/src/asserts.js";
|
|
|
3
3
|
import { must } from "../../shared/src/must.js";
|
|
4
4
|
import { getValueAtPath } from "../../shared/src/object-traversal.js";
|
|
5
5
|
import "../../zero-protocol/src/push.js";
|
|
6
|
-
import {
|
|
6
|
+
import { handleMutateRequest } from "./process-mutations.js";
|
|
7
7
|
import { isMutator } from "../../zql/src/mutate/mutator.js";
|
|
8
8
|
class PushProcessor {
|
|
9
9
|
#dbProvider;
|
|
@@ -16,33 +16,35 @@ class PushProcessor {
|
|
|
16
16
|
}
|
|
17
17
|
process(mutators, queryOrQueryString, body) {
|
|
18
18
|
if (queryOrQueryString instanceof Request) {
|
|
19
|
-
return
|
|
19
|
+
return handleMutateRequest(
|
|
20
20
|
this.#dbProvider,
|
|
21
21
|
(transact, mutation) => this.#processMutation(mutators, transact, mutation),
|
|
22
22
|
queryOrQueryString,
|
|
23
|
-
this.#context,
|
|
24
23
|
this.#logLevel
|
|
25
24
|
);
|
|
26
25
|
}
|
|
27
|
-
return
|
|
26
|
+
return handleMutateRequest(
|
|
28
27
|
this.#dbProvider,
|
|
29
28
|
(transact, mutation) => this.#processMutation(mutators, transact, mutation),
|
|
30
29
|
queryOrQueryString,
|
|
31
30
|
must(body),
|
|
32
|
-
this.#context,
|
|
33
31
|
this.#logLevel
|
|
34
32
|
);
|
|
35
33
|
}
|
|
36
34
|
#processMutation(mutators, transact, _mutation) {
|
|
37
35
|
return transact(
|
|
38
|
-
(tx, name, args
|
|
36
|
+
(tx, name, args) => this.#dispatchMutation(mutators, tx, name, args)
|
|
39
37
|
);
|
|
40
38
|
}
|
|
41
|
-
#dispatchMutation(mutators, dbTx, key, args
|
|
39
|
+
#dispatchMutation(mutators, dbTx, key, args) {
|
|
42
40
|
const mutator = getValueAtPath(mutators, key, /\.|\|/);
|
|
43
41
|
assert(typeof mutator === "function", `could not find mutator ${key}`);
|
|
44
42
|
if (isMutator(mutator)) {
|
|
45
|
-
return mutator.fn({
|
|
43
|
+
return mutator.fn({
|
|
44
|
+
args,
|
|
45
|
+
ctx: this.#context,
|
|
46
|
+
tx: dbTx
|
|
47
|
+
});
|
|
46
48
|
}
|
|
47
49
|
return mutator(dbTx, args);
|
|
48
50
|
}
|