@rocicorp/zero 1.2.0 → 1.3.0-canary.1
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/analyze-query/src/bin-analyze.js +25 -25
- package/out/analyze-query/src/bin-analyze.js.map +1 -1
- package/out/ast-to-zql/src/ast-to-zql.d.ts.map +1 -1
- package/out/ast-to-zql/src/ast-to-zql.js +2 -1
- package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
- package/out/replicache/src/btree/node.d.ts.map +1 -1
- package/out/replicache/src/btree/node.js +2 -2
- package/out/replicache/src/btree/node.js.map +1 -1
- package/out/replicache/src/connection-loop.js +3 -3
- package/out/replicache/src/connection-loop.js.map +1 -1
- package/out/replicache/src/deleted-clients.d.ts +0 -4
- package/out/replicache/src/deleted-clients.d.ts.map +1 -1
- package/out/replicache/src/deleted-clients.js +1 -1
- package/out/replicache/src/deleted-clients.js.map +1 -1
- package/out/replicache/src/hash.d.ts.map +1 -1
- package/out/replicache/src/hash.js.map +1 -1
- package/out/replicache/src/process-scheduler.d.ts.map +1 -1
- package/out/replicache/src/process-scheduler.js.map +1 -1
- package/out/replicache/src/request-idle.js +1 -1
- package/out/replicache/src/request-idle.js.map +1 -1
- package/out/replicache/src/sync/patch.d.ts +1 -1
- package/out/replicache/src/sync/patch.d.ts.map +1 -1
- package/out/replicache/src/sync/patch.js +1 -1
- package/out/replicache/src/sync/patch.js.map +1 -1
- package/out/shared/src/arrays.d.ts.map +1 -1
- package/out/shared/src/arrays.js +1 -2
- package/out/shared/src/arrays.js.map +1 -1
- package/out/shared/src/bigint-json.js +1 -1
- package/out/shared/src/bigint-json.js.map +1 -1
- package/out/shared/src/btree-set.js +1 -1
- package/out/shared/src/btree-set.js.map +1 -1
- package/out/shared/src/iterables.d.ts +7 -0
- package/out/shared/src/iterables.d.ts.map +1 -1
- package/out/shared/src/iterables.js +10 -1
- package/out/shared/src/iterables.js.map +1 -1
- package/out/shared/src/logging.d.ts.map +1 -1
- package/out/shared/src/logging.js +10 -9
- package/out/shared/src/logging.js.map +1 -1
- package/out/shared/src/options.js +1 -1
- package/out/shared/src/options.js.map +1 -1
- package/out/shared/src/sorted-entries.d.ts +2 -0
- package/out/shared/src/sorted-entries.d.ts.map +1 -0
- package/out/shared/src/sorted-entries.js +9 -0
- package/out/shared/src/sorted-entries.js.map +1 -0
- package/out/shared/src/tdigest-schema.d.ts.map +1 -1
- package/out/shared/src/tdigest-schema.js.map +1 -1
- package/out/shared/src/tdigest.d.ts.map +1 -1
- package/out/shared/src/tdigest.js +7 -7
- package/out/shared/src/tdigest.js.map +1 -1
- package/out/shared/src/valita.d.ts.map +1 -1
- package/out/shared/src/valita.js +1 -1
- package/out/shared/src/valita.js.map +1 -1
- package/out/z2s/src/sql.d.ts +2 -2
- package/out/z2s/src/sql.d.ts.map +1 -1
- package/out/z2s/src/sql.js +3 -3
- package/out/z2s/src/sql.js.map +1 -1
- package/out/zero/package.js +6 -7
- package/out/zero/package.js.map +1 -1
- package/out/zero/src/pg.js +1 -1
- package/out/zero/src/server.js +1 -1
- package/out/zero-cache/src/auth/auth.d.ts +8 -26
- package/out/zero-cache/src/auth/auth.d.ts.map +1 -1
- package/out/zero-cache/src/auth/auth.js +57 -82
- package/out/zero-cache/src/auth/auth.js.map +1 -1
- package/out/zero-cache/src/auth/jwt.d.ts +3 -3
- package/out/zero-cache/src/auth/jwt.d.ts.map +1 -1
- package/out/zero-cache/src/auth/jwt.js.map +1 -1
- package/out/zero-cache/src/auth/load-permissions.js +1 -1
- package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +38 -2
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +56 -1
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom/fetch.d.ts +2 -9
- package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
- package/out/zero-cache/src/custom/fetch.js +10 -4
- package/out/zero-cache/src/custom/fetch.js.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.d.ts +20 -9
- package/out/zero-cache/src/custom-queries/transform-query.d.ts.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.js +74 -37
- package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
- package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
- package/out/zero-cache/src/db/migration-lite.js +1 -1
- package/out/zero-cache/src/db/migration-lite.js.map +1 -1
- package/out/zero-cache/src/db/migration.d.ts.map +1 -1
- package/out/zero-cache/src/db/migration.js +1 -1
- package/out/zero-cache/src/db/migration.js.map +1 -1
- package/out/zero-cache/src/db/pg-copy-binary.d.ts +101 -0
- package/out/zero-cache/src/db/pg-copy-binary.d.ts.map +1 -0
- package/out/zero-cache/src/db/pg-copy-binary.js +381 -0
- package/out/zero-cache/src/db/pg-copy-binary.js.map +1 -0
- package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.js +3 -0
- package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
- package/out/zero-cache/src/db/warmup.d.ts.map +1 -1
- package/out/zero-cache/src/db/warmup.js +3 -1
- package/out/zero-cache/src/db/warmup.js.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.d.ts.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.js +2 -1
- package/out/zero-cache/src/server/anonymous-otel-start.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 +5 -2
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.d.ts +2 -2
- package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js +4 -4
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/server/main.js +1 -1
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/reaper.d.ts.map +1 -1
- package/out/zero-cache/src/server/reaper.js +4 -1
- package/out/zero-cache/src/server/reaper.js.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.js +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +41 -20
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/server/worker-urls.d.ts.map +1 -1
- package/out/zero-cache/src/server/worker-urls.js +2 -1
- package/out/zero-cache/src/server/worker-urls.js.map +1 -1
- package/out/zero-cache/src/services/change-source/change-source.d.ts +4 -0
- package/out/zero-cache/src/services/change-source/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js +3 -2
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +5 -2
- package/out/zero-cache/src/services/change-source/custom/change-source.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 +13 -4
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +3 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +91 -9
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js +2 -2
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/broadcast.js +1 -1
- package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +3 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
- package/out/zero-cache/src/services/life-cycle.d.ts +5 -4
- package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
- package/out/zero-cache/src/services/life-cycle.js +11 -11
- package/out/zero-cache/src/services/life-cycle.js.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.js +5 -5
- package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.d.ts +20 -20
- package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +91 -104
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.js +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-schema.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-schema.js +4 -3
- package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts +168 -0
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.js +385 -0
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +2 -2
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +5 -4
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +2 -3
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js +3 -3
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +5 -3
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js +13 -7
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +3 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +6 -9
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +24 -26
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +236 -124
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/lite.d.ts.map +1 -1
- package/out/zero-cache/src/types/lite.js +3 -2
- package/out/zero-cache/src/types/lite.js.map +1 -1
- package/out/zero-cache/src/types/pg-types.js +4 -1
- package/out/zero-cache/src/types/pg-types.js.map +1 -1
- package/out/zero-cache/src/types/pg-versions.d.ts +3 -0
- package/out/zero-cache/src/types/pg-versions.d.ts.map +1 -0
- package/out/zero-cache/src/types/pg-versions.js +7 -0
- package/out/zero-cache/src/types/pg-versions.js.map +1 -0
- package/out/zero-cache/src/types/pg.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg.js +6 -1
- package/out/zero-cache/src/types/pg.js.map +1 -1
- package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
- package/out/zero-cache/src/types/subscription.js +2 -2
- package/out/zero-cache/src/types/subscription.js.map +1 -1
- package/out/zero-cache/src/workers/connect-params.d.ts +1 -1
- package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connect-params.js +1 -1
- package/out/zero-cache/src/workers/connect-params.js.map +1 -1
- package/out/zero-cache/src/workers/connection.js +2 -2
- package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts +2 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js +64 -38
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts +2 -1
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +70 -31
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/connection.d.ts +4 -4
- package/out/zero-client/src/client/connection.d.ts.map +1 -1
- package/out/zero-client/src/client/connection.js.map +1 -1
- package/out/zero-client/src/client/http-string.d.ts.map +1 -1
- package/out/zero-client/src/client/http-string.js.map +1 -1
- package/out/zero-client/src/client/metrics.d.ts.map +1 -1
- package/out/zero-client/src/client/metrics.js +2 -1
- package/out/zero-client/src/client/metrics.js.map +1 -1
- package/out/zero-client/src/client/options.d.ts +30 -5
- package/out/zero-client/src/client/options.d.ts.map +1 -1
- package/out/zero-client/src/client/options.js.map +1 -1
- package/out/zero-client/src/client/server-option.js +1 -1
- package/out/zero-client/src/client/server-option.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-poke-handler.js +1 -1
- package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
- package/out/zero-client/src/client/zero.d.ts +4 -3
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +33 -11
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-pg/src/mod.js +1 -1
- package/out/zero-protocol/src/ast.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/change-desired-queries.d.ts +4 -0
- package/out/zero-protocol/src/change-desired-queries.d.ts.map +1 -1
- package/out/zero-protocol/src/change-desired-queries.js +4 -1
- package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
- package/out/zero-protocol/src/connect.d.ts +4 -0
- package/out/zero-protocol/src/connect.d.ts.map +1 -1
- package/out/zero-protocol/src/connect.js +2 -1
- package/out/zero-protocol/src/connect.js.map +1 -1
- package/out/zero-protocol/src/primary-key.d.ts.map +1 -1
- package/out/zero-protocol/src/primary-key.js.map +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
- package/out/zero-protocol/src/protocol-version.js.map +1 -1
- package/out/zero-protocol/src/push.d.ts +4 -0
- package/out/zero-protocol/src/push.d.ts.map +1 -1
- package/out/zero-protocol/src/push.js +2 -1
- package/out/zero-protocol/src/push.js.map +1 -1
- package/out/zero-protocol/src/up.d.ts +3 -0
- package/out/zero-protocol/src/up.d.ts.map +1 -1
- package/out/zero-react/src/zero-provider.d.ts.map +1 -1
- package/out/zero-react/src/zero-provider.js +11 -5
- package/out/zero-react/src/zero-provider.js.map +1 -1
- package/out/zero-schema/src/name-mapper.js +1 -1
- package/out/zero-schema/src/name-mapper.js.map +1 -1
- package/out/zero-server/src/mod.js +1 -1
- package/out/zero-server/src/process-mutations.d.ts.map +1 -1
- package/out/zero-server/src/process-mutations.js +2 -1
- package/out/zero-server/src/process-mutations.js.map +1 -1
- package/out/zero-server/src/push-processor.d.ts +1 -0
- package/out/zero-server/src/push-processor.d.ts.map +1 -1
- package/out/zero-server/src/push-processor.js +3 -2
- package/out/zero-server/src/push-processor.js.map +1 -1
- package/out/zero-solid/src/use-zero.d.ts.map +1 -1
- package/out/zero-solid/src/use-zero.js +8 -9
- package/out/zero-solid/src/use-zero.js.map +1 -1
- package/out/zql/src/builder/like.js +2 -1
- package/out/zql/src/builder/like.js.map +1 -1
- package/out/zql/src/ivm/data.d.ts.map +1 -1
- package/out/zql/src/ivm/data.js +6 -15
- package/out/zql/src/ivm/data.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +14 -8
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/query/complete-ordering.js +1 -1
- package/out/zql/src/query/complete-ordering.js.map +1 -1
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +2 -2
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query-registry.d.ts.map +1 -1
- package/out/zql/src/query/query-registry.js +2 -1
- package/out/zql/src/query/query-registry.js.map +1 -1
- package/out/zql/src/query/ttl.js +1 -1
- package/out/zql/src/query/ttl.js.map +1 -1
- package/out/zqlite/src/internal/sql.d.ts +2 -2
- package/out/zqlite/src/internal/sql.d.ts.map +1 -1
- package/out/zqlite/src/internal/sql.js +1 -2
- package/out/zqlite/src/internal/sql.js.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.d.ts +1 -1
- package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.js +1 -1
- package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
- package/out/zqlite/src/sqlite-stat-fanout.js +1 -1
- package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +8 -12
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +6 -7
|
@@ -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,EAIL,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,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;
|
|
1
|
+
{"version":3,"file":"process-mutations.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/process-mutations.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,7 @@ import { isMutator } from "../../zql/src/mutate/mutator.js";
|
|
|
10
10
|
import { cleanupResultsArgSchema, pushBodySchema, pushParamsSchema } from "../../zero-protocol/src/push.js";
|
|
11
11
|
import { MutationAlreadyProcessedError } from "../../zero-cache/src/services/mutagen/error.js";
|
|
12
12
|
import { createLogContext } from "./logging.js";
|
|
13
|
+
import { separatorRe } from "./push-processor.js";
|
|
13
14
|
//#region ../zero-server/src/process-mutations.ts
|
|
14
15
|
var applicationErrorWrapper = async (fn) => {
|
|
15
16
|
try {
|
|
@@ -262,7 +263,7 @@ function makeAppErrorResponse(m, error) {
|
|
|
262
263
|
}
|
|
263
264
|
/** @deprecated Use getMutator instead */
|
|
264
265
|
function getMutation(mutators, name) {
|
|
265
|
-
const mutator = getObjectAtPath(mutators, name.split(
|
|
266
|
+
const mutator = getObjectAtPath(mutators, name.split(separatorRe));
|
|
266
267
|
assert(typeof mutator === "function", `could not find mutator ${name}`);
|
|
267
268
|
if (isMutator(mutator)) return (tx, args, ctx) => mutator.fn({
|
|
268
269
|
args,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-mutations.js","names":["#dbProvider","#req","#params","#lc","#transactImpl","#checkAndIncrementLastMutationID","#getTransactionInput"],"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 CLEANUP_RESULTS_MUTATION_NAME,\n cleanupResultsArgSchema,\n pushBodySchema,\n pushParamsSchema,\n type CleanupResultsArg,\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 deleteMutationResults: (args: CleanupResultsArg) => 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 // Handle internal mutations (like cleanup) directly without user dispatch\n if (m.type === 'custom' && m.name === CLEANUP_RESULTS_MUTATION_NAME) {\n lc.debug?.(\n `Processing internal mutation '${m.name}' (clientID=${m.clientID})`,\n );\n try {\n await processCleanupResultsMutation(dbProvider, m, queryParams, lc);\n // No response added - this is fire-and-forget\n processedCount++;\n } catch (error) {\n lc.warn?.(\n `Failed to process cleanup mutation for client ${m.clientID}`,\n error,\n );\n // Don't fail the whole push for cleanup errors\n processedCount++;\n }\n continue;\n }\n\n assert(m.type === 'custom', 'Expected custom mutation');\n lc.debug?.(\n `Processing mutation '${m.name}' (id=${m.id}, clientID=${m.clientID})`,\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, innerCb);\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 (appError !== undefined) {\n // Retry also failed → internal error, cannot skip mutation\n this.#lc.error?.(\n `Retry also failed for mutation ${mutation.id} for client ${mutation.clientID}`,\n error,\n );\n throw error;\n }\n\n // First attempt failed → store error and retry without mutator\n const originalError =\n error instanceof DatabaseTransactionError\n ? (error.cause ?? error)\n : error;\n appError = wrapWithApplicationError(originalError);\n this.#lc.warn?.(\n `Error processing mutation ${mutation.id} for client ${mutation.clientID}, retrying without mutator`,\n appError,\n );\n continue;\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 await cb(dbTx, mutation.name, mutation.args[0]);\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\n/**\n * Processes internal cleanup mutation that deletes acknowledged mutation results\n * from the upstream database. This runs without LMID tracking since it's an\n * internal operation.\n */\nasync function processCleanupResultsMutation<\n D extends Database<ExtractTransactionType<D>>,\n>(\n dbProvider: D,\n mutation: CustomMutation,\n queryParams: Params,\n lc: LogContext,\n): Promise<void> {\n const parseResult = v.test(mutation.args[0], cleanupResultsArgSchema);\n if (!parseResult.ok) {\n lc.warn?.('Cleanup mutation has invalid args', parseResult.error);\n return;\n }\n const args: CleanupResultsArg = parseResult.value;\n\n // Determine clientID for transaction input based on cleanup type\n // Note: legacy format without type field is treated as single\n const clientID =\n 'type' in args && args.type === 'bulk' ? args.clientIDs[0] : args.clientID;\n\n // Run in a transaction, using the hook for DB-specific operation.\n // Note: only upstreamSchema is used by deleteMutationResults; the other\n // fields are required by the interface but ignored for this operation.\n await dbProvider.transaction(\n async (_, hooks) => {\n await hooks.deleteMutationResults(args);\n },\n {\n upstreamSchema: queryParams.schema,\n clientGroupID: args.clientGroupID,\n clientID,\n mutationID: 0,\n },\n );\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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"process-mutations.js","names":["#dbProvider","#req","#params","#lc","#transactImpl","#checkAndIncrementLastMutationID","#getTransactionInput"],"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 CLEANUP_RESULTS_MUTATION_NAME,\n cleanupResultsArgSchema,\n pushBodySchema,\n pushParamsSchema,\n type CleanupResultsArg,\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';\nimport {separatorRe} from './push-processor.ts';\n\nexport interface TransactionProviderHooks {\n updateClientMutationID: () => Promise<{lastMutationID: number | bigint}>;\n writeMutationResult: (result: MutationResponse) => Promise<void>;\n deleteMutationResults: (args: CleanupResultsArg) => 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 // Handle internal mutations (like cleanup) directly without user dispatch\n if (m.type === 'custom' && m.name === CLEANUP_RESULTS_MUTATION_NAME) {\n lc.debug?.(\n `Processing internal mutation '${m.name}' (clientID=${m.clientID})`,\n );\n try {\n await processCleanupResultsMutation(dbProvider, m, queryParams, lc);\n // No response added - this is fire-and-forget\n processedCount++;\n } catch (error) {\n lc.warn?.(\n `Failed to process cleanup mutation for client ${m.clientID}`,\n error,\n );\n // Don't fail the whole push for cleanup errors\n processedCount++;\n }\n continue;\n }\n\n assert(m.type === 'custom', 'Expected custom mutation');\n lc.debug?.(\n `Processing mutation '${m.name}' (id=${m.id}, clientID=${m.clientID})`,\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, innerCb);\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 (appError !== undefined) {\n // Retry also failed → internal error, cannot skip mutation\n this.#lc.error?.(\n `Retry also failed for mutation ${mutation.id} for client ${mutation.clientID}`,\n error,\n );\n throw error;\n }\n\n // First attempt failed → store error and retry without mutator\n const originalError =\n error instanceof DatabaseTransactionError\n ? (error.cause ?? error)\n : error;\n appError = wrapWithApplicationError(originalError);\n this.#lc.warn?.(\n `Error processing mutation ${mutation.id} for client ${mutation.clientID}, retrying without mutator`,\n appError,\n );\n continue;\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 await cb(dbTx, mutation.name, mutation.args[0]);\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(separatorRe);\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\n/**\n * Processes internal cleanup mutation that deletes acknowledged mutation results\n * from the upstream database. This runs without LMID tracking since it's an\n * internal operation.\n */\nasync function processCleanupResultsMutation<\n D extends Database<ExtractTransactionType<D>>,\n>(\n dbProvider: D,\n mutation: CustomMutation,\n queryParams: Params,\n lc: LogContext,\n): Promise<void> {\n const parseResult = v.test(mutation.args[0], cleanupResultsArgSchema);\n if (!parseResult.ok) {\n lc.warn?.('Cleanup mutation has invalid args', parseResult.error);\n return;\n }\n const args: CleanupResultsArg = parseResult.value;\n\n // Determine clientID for transaction input based on cleanup type\n // Note: legacy format without type field is treated as single\n const clientID =\n 'type' in args && args.type === 'bulk' ? args.clientIDs[0] : args.clientID;\n\n // Run in a transaction, using the hook for DB-specific operation.\n // Note: only upstreamSchema is used by deleteMutationResults; the other\n // fields are required by the interface but ignored for this operation.\n await dbProvider.transaction(\n async (_, hooks) => {\n await hooks.deleteMutationResults(args);\n },\n {\n upstreamSchema: queryParams.schema,\n clientGroupID: args.clientGroupID,\n clientID,\n mutationID: 0,\n },\n );\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"],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ import { type Database, type ExtractTransactionType } from '../../zero-server/sr
|
|
|
5
5
|
import type { Schema } from '../../zero-types/src/schema.ts';
|
|
6
6
|
import type { AnyMutatorRegistry } from '../../zql/src/mutate/mutator-registry.ts';
|
|
7
7
|
import type { CustomMutatorDefs } from './custom.ts';
|
|
8
|
+
export declare const separatorRe: RegExp;
|
|
8
9
|
export declare class PushProcessor<_S extends Schema, D extends Database<ExtractTransactionType<D>>, MD extends AnyMutatorRegistry | CustomMutatorDefs<ExtractTransactionType<D>>, C = undefined> {
|
|
9
10
|
#private;
|
|
10
11
|
constructor(dbProvider: D, context?: C, logLevel?: LogLevel);
|
|
@@ -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;CAqD/D"}
|
|
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,eAAO,MAAM,WAAW,QAAS,CAAC;AAElC,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"}
|
|
@@ -6,6 +6,7 @@ import "../../zero-protocol/src/push.js";
|
|
|
6
6
|
import { handleMutateRequest } from "./process-mutations.js";
|
|
7
7
|
import "@rocicorp/logger";
|
|
8
8
|
//#region ../zero-server/src/push-processor.ts
|
|
9
|
+
var separatorRe = /[.|]/;
|
|
9
10
|
var PushProcessor = class {
|
|
10
11
|
#dbProvider;
|
|
11
12
|
#logLevel;
|
|
@@ -23,7 +24,7 @@ var PushProcessor = class {
|
|
|
23
24
|
return transact((tx, name, args) => this.#dispatchMutation(mutators, tx, name, args));
|
|
24
25
|
}
|
|
25
26
|
#dispatchMutation(mutators, dbTx, key, args) {
|
|
26
|
-
const mutator = getValueAtPath(mutators, key,
|
|
27
|
+
const mutator = getValueAtPath(mutators, key, separatorRe);
|
|
27
28
|
assert(typeof mutator === "function", `could not find mutator ${key}`);
|
|
28
29
|
if (isMutator(mutator)) return mutator.fn({
|
|
29
30
|
args,
|
|
@@ -34,6 +35,6 @@ var PushProcessor = class {
|
|
|
34
35
|
}
|
|
35
36
|
};
|
|
36
37
|
//#endregion
|
|
37
|
-
export { PushProcessor };
|
|
38
|
+
export { PushProcessor, separatorRe };
|
|
38
39
|
|
|
39
40
|
//# sourceMappingURL=push-processor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push-processor.js","names":["#dbProvider","#logLevel","#context","#processMutation","#dispatchMutation"],"sources":["../../../../zero-server/src/push-processor.ts"],"sourcesContent":["import {type LogLevel} from '@rocicorp/logger';\nimport {assert} from '../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {getValueAtPath} from '../../shared/src/object-traversal.ts';\nimport {\n type CustomMutation,\n type MutationResponse,\n type PushResponse,\n} from '../../zero-protocol/src/push.ts';\nimport {\n type Database,\n type ExtractTransactionType,\n handleMutateRequest,\n type TransactFn,\n} from '../../zero-server/src/process-mutations.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {Transaction} from '../../zql/src/mutate/custom.ts';\nimport type {AnyMutatorRegistry} from '../../zql/src/mutate/mutator-registry.ts';\nimport {isMutator} from '../../zql/src/mutate/mutator.ts';\nimport type {CustomMutatorDefs} from './custom.ts';\n\nexport class PushProcessor<\n _S extends Schema,\n D extends Database<ExtractTransactionType<D>>,\n MD extends AnyMutatorRegistry | CustomMutatorDefs<ExtractTransactionType<D>>,\n C = undefined,\n> {\n readonly #dbProvider: D;\n readonly #logLevel: LogLevel;\n readonly #context: C;\n\n constructor(dbProvider: D, context?: C, logLevel: LogLevel = 'info') {\n this.#dbProvider = dbProvider;\n this.#context = context as C;\n this.#logLevel = logLevel;\n }\n\n /**\n * Processes a push request from zero-cache.\n * This function will parse the request, check the protocol version, and process each mutation in the request.\n * - If a mutation is out of order: processing will stop and an error will be returned. The zero client will retry the mutation.\n * - If a mutation has already been processed: it will be skipped and the processing will continue.\n * - If a mutation receives an application error: it will be skipped, the error will be returned to the client, and processing will continue.\n *\n * @param mutators the custom mutators for the application\n * @param queryString the query string from the request sent by zero-cache. This will include zero's postgres schema name and appID.\n * @param body the body of the request sent by zero-cache as a JSON object.\n */\n process(\n mutators: MD,\n queryString: URLSearchParams | Record<string, string>,\n body: ReadonlyJSONValue,\n ): Promise<PushResponse>;\n\n /**\n * This override gets the query string and the body from a Request object.\n *\n * @param mutators the custom mutators for the application\n * @param request A `Request` object.\n */\n process(mutators: MD, request: Request): Promise<PushResponse>;\n process(\n mutators: MD,\n queryOrQueryString: Request | URLSearchParams | Record<string, string>,\n body?: ReadonlyJSONValue,\n ): Promise<PushResponse> {\n if (queryOrQueryString instanceof Request) {\n return handleMutateRequest(\n this.#dbProvider,\n (transact, mutation) =>\n this.#processMutation(mutators, transact, mutation),\n queryOrQueryString,\n this.#logLevel,\n );\n }\n return handleMutateRequest(\n this.#dbProvider,\n (transact, mutation) =>\n this.#processMutation(mutators, transact, mutation),\n queryOrQueryString,\n must(body, 'body is required when using query params directly'),\n this.#logLevel,\n );\n }\n\n #processMutation(\n mutators: MD,\n transact: TransactFn<D>,\n _mutation: CustomMutation,\n ): Promise<MutationResponse> {\n return transact((tx, name, args) =>\n this.#dispatchMutation(mutators, tx, name, args),\n );\n }\n\n #dispatchMutation(\n mutators: MD,\n dbTx: ExtractTransactionType<D>,\n key: string,\n args: ReadonlyJSONValue | undefined,\n ): Promise<void> {\n // Legacy mutators used | as a separator, new mutators use .\n const mutator = getValueAtPath(mutators, key,
|
|
1
|
+
{"version":3,"file":"push-processor.js","names":["#dbProvider","#logLevel","#context","#processMutation","#dispatchMutation"],"sources":["../../../../zero-server/src/push-processor.ts"],"sourcesContent":["import {type LogLevel} from '@rocicorp/logger';\nimport {assert} from '../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {getValueAtPath} from '../../shared/src/object-traversal.ts';\nimport {\n type CustomMutation,\n type MutationResponse,\n type PushResponse,\n} from '../../zero-protocol/src/push.ts';\nimport {\n type Database,\n type ExtractTransactionType,\n handleMutateRequest,\n type TransactFn,\n} from '../../zero-server/src/process-mutations.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {Transaction} from '../../zql/src/mutate/custom.ts';\nimport type {AnyMutatorRegistry} from '../../zql/src/mutate/mutator-registry.ts';\nimport {isMutator} from '../../zql/src/mutate/mutator.ts';\nimport type {CustomMutatorDefs} from './custom.ts';\n\nexport const separatorRe = /[.|]/;\n\nexport class PushProcessor<\n _S extends Schema,\n D extends Database<ExtractTransactionType<D>>,\n MD extends AnyMutatorRegistry | CustomMutatorDefs<ExtractTransactionType<D>>,\n C = undefined,\n> {\n readonly #dbProvider: D;\n readonly #logLevel: LogLevel;\n readonly #context: C;\n\n constructor(dbProvider: D, context?: C, logLevel: LogLevel = 'info') {\n this.#dbProvider = dbProvider;\n this.#context = context as C;\n this.#logLevel = logLevel;\n }\n\n /**\n * Processes a push request from zero-cache.\n * This function will parse the request, check the protocol version, and process each mutation in the request.\n * - If a mutation is out of order: processing will stop and an error will be returned. The zero client will retry the mutation.\n * - If a mutation has already been processed: it will be skipped and the processing will continue.\n * - If a mutation receives an application error: it will be skipped, the error will be returned to the client, and processing will continue.\n *\n * @param mutators the custom mutators for the application\n * @param queryString the query string from the request sent by zero-cache. This will include zero's postgres schema name and appID.\n * @param body the body of the request sent by zero-cache as a JSON object.\n */\n process(\n mutators: MD,\n queryString: URLSearchParams | Record<string, string>,\n body: ReadonlyJSONValue,\n ): Promise<PushResponse>;\n\n /**\n * This override gets the query string and the body from a Request object.\n *\n * @param mutators the custom mutators for the application\n * @param request A `Request` object.\n */\n process(mutators: MD, request: Request): Promise<PushResponse>;\n process(\n mutators: MD,\n queryOrQueryString: Request | URLSearchParams | Record<string, string>,\n body?: ReadonlyJSONValue,\n ): Promise<PushResponse> {\n if (queryOrQueryString instanceof Request) {\n return handleMutateRequest(\n this.#dbProvider,\n (transact, mutation) =>\n this.#processMutation(mutators, transact, mutation),\n queryOrQueryString,\n this.#logLevel,\n );\n }\n return handleMutateRequest(\n this.#dbProvider,\n (transact, mutation) =>\n this.#processMutation(mutators, transact, mutation),\n queryOrQueryString,\n must(body, 'body is required when using query params directly'),\n this.#logLevel,\n );\n }\n\n #processMutation(\n mutators: MD,\n transact: TransactFn<D>,\n _mutation: CustomMutation,\n ): Promise<MutationResponse> {\n return transact((tx, name, args) =>\n this.#dispatchMutation(mutators, tx, name, args),\n );\n }\n\n #dispatchMutation(\n mutators: MD,\n dbTx: ExtractTransactionType<D>,\n key: string,\n args: ReadonlyJSONValue | undefined,\n ): Promise<void> {\n // Legacy mutators used | as a separator, new mutators use .\n const mutator = getValueAtPath(mutators, key, separatorRe);\n assert(typeof mutator === 'function', `could not find mutator ${key}`);\n if (isMutator(mutator)) {\n return mutator.fn({\n args,\n ctx: this.#context,\n tx: dbTx as Transaction<Schema, unknown>,\n });\n }\n return mutator(dbTx, args);\n }\n}\n"],"mappings":";;;;;;;;AAsBA,IAAa,cAAc;AAE3B,IAAa,gBAAb,MAKE;CACA;CACA;CACA;CAEA,YAAY,YAAe,SAAa,WAAqB,QAAQ;AACnE,QAAA,aAAmB;AACnB,QAAA,UAAgB;AAChB,QAAA,WAAiB;;CA2BnB,QACE,UACA,oBACA,MACuB;AACvB,MAAI,8BAA8B,QAChC,QAAO,oBACL,MAAA,aACC,UAAU,aACT,MAAA,gBAAsB,UAAU,UAAU,SAAS,EACrD,oBACA,MAAA,SACD;AAEH,SAAO,oBACL,MAAA,aACC,UAAU,aACT,MAAA,gBAAsB,UAAU,UAAU,SAAS,EACrD,oBACA,KAAK,MAAM,oDAAoD,EAC/D,MAAA,SACD;;CAGH,iBACE,UACA,UACA,WAC2B;AAC3B,SAAO,UAAU,IAAI,MAAM,SACzB,MAAA,iBAAuB,UAAU,IAAI,MAAM,KAAK,CACjD;;CAGH,kBACE,UACA,MACA,KACA,MACe;EAEf,MAAM,UAAU,eAAe,UAAU,KAAK,YAAY;AAC1D,SAAO,OAAO,YAAY,YAAY,0BAA0B,MAAM;AACtE,MAAI,UAAU,QAAQ,CACpB,QAAO,QAAQ,GAAG;GAChB;GACA,KAAK,MAAA;GACL,IAAI;GACL,CAAC;AAEJ,SAAO,QAAQ,MAAM,KAAK"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-zero.d.ts","sourceRoot":"","sources":["../../../../zero-solid/src/use-zero.ts"],"names":[],"mappings":"AAAA,OAAO,EAUL,KAAK,GAAG,EACT,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,IAAI,EACJ,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,WAAW,CAAC;AAOnB;;GAEG;AACH,wBAAgB,UAAU,CACxB,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,EACnD,OAAO,EAAE,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAM5D;AAED,wBAAgB,OAAO,CACrB,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,KAChD,MAAM,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAO9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,sCAGpD;
|
|
1
|
+
{"version":3,"file":"use-zero.d.ts","sourceRoot":"","sources":["../../../../zero-solid/src/use-zero.ts"],"names":[],"mappings":"AAAA,OAAO,EAUL,KAAK,GAAG,EACT,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,IAAI,EACJ,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,WAAW,CAAC;AAOnB;;GAEG;AACH,wBAAgB,UAAU,CACxB,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,EACnD,OAAO,EAAE,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAM5D;AAED,wBAAgB,OAAO,CACrB,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,KAChD,MAAM,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAO9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,sCAGpD;AAED,wBAAgB,YAAY,CAC1B,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,EAEnD,KAAK,EAAE;IACL,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAC7C,GAAG,CACA;IACE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;CAC5B,GACD,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAC9B,eAoDF"}
|
|
@@ -31,12 +31,16 @@ function useZero() {
|
|
|
31
31
|
function createUseZero() {
|
|
32
32
|
return () => useZero();
|
|
33
33
|
}
|
|
34
|
-
var NO_AUTH_SET = Symbol();
|
|
35
34
|
function ZeroProvider(props) {
|
|
35
|
+
let prevAuth = "auth" in props ? props.auth : void 0;
|
|
36
|
+
const auth = createMemo(() => "auth" in props ? props.auth : void 0);
|
|
37
|
+
const hasAuth = createMemo(() => typeof auth() === "string");
|
|
36
38
|
const zero = createMemo(() => {
|
|
37
39
|
if ("zero" in props) return props.zero;
|
|
40
|
+
hasAuth();
|
|
38
41
|
const [, options] = splitProps(props, ["children", "auth"]);
|
|
39
|
-
const authValue = untrack(
|
|
42
|
+
const authValue = untrack(auth);
|
|
43
|
+
prevAuth = authValue;
|
|
40
44
|
const createdZero = new Zero({
|
|
41
45
|
...options,
|
|
42
46
|
...authValue !== void 0 ? { auth: authValue } : {},
|
|
@@ -46,19 +50,14 @@ function ZeroProvider(props) {
|
|
|
46
50
|
onCleanup(() => createdZero.close());
|
|
47
51
|
return createdZero;
|
|
48
52
|
});
|
|
49
|
-
const auth = createMemo(() => "auth" in props ? props.auth : NO_AUTH_SET);
|
|
50
|
-
let prevAuth = NO_AUTH_SET;
|
|
51
53
|
createEffect(() => {
|
|
52
54
|
const currentZero = zero();
|
|
53
55
|
if (!currentZero || "zero" in props) return;
|
|
54
56
|
const currentAuth = auth();
|
|
55
|
-
if (prevAuth === NO_AUTH_SET) {
|
|
56
|
-
prevAuth = currentAuth;
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
57
|
if (currentAuth !== prevAuth) {
|
|
58
|
+
const previousAuth = prevAuth;
|
|
60
59
|
prevAuth = currentAuth;
|
|
61
|
-
currentZero.connection.connect({ auth: currentAuth
|
|
60
|
+
if (typeof previousAuth === "string" && typeof currentAuth === "string") currentZero.connection.connect({ auth: currentAuth });
|
|
62
61
|
}
|
|
63
62
|
});
|
|
64
63
|
return ZeroContext.Provider({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-zero.js","names":[],"sources":["../../../../zero-solid/src/use-zero.ts"],"sourcesContent":["import {\n batch,\n createContext,\n createEffect,\n createMemo,\n onCleanup,\n splitProps,\n untrack,\n useContext,\n type Accessor,\n type JSX,\n} from 'solid-js';\nimport {\n Zero,\n type BaseDefaultContext,\n type BaseDefaultSchema,\n type CustomMutatorDefs,\n type DefaultContext,\n type DefaultSchema,\n type ZeroOptions,\n} from './zero.ts';\n\nconst ZeroContext = createContext<\n // oxlint-disable-next-line no-explicit-any\n Accessor<Zero<any, any, any>> | undefined\n>(undefined);\n\n/**\n * @deprecated Use {@linkcode ZeroProvider} instead of managing your own Zero instance.\n */\nexport function createZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>(options: ZeroOptions<S, MD, Context>): Zero<S, MD, Context> {\n const opts = {\n ...options,\n batchViewUpdates: batch,\n };\n return new Zero<S, MD, Context>(opts);\n}\n\nexport function useZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>(): () => Zero<S, MD, Context> {\n const zero = useContext(ZeroContext);\n\n if (zero === undefined) {\n throw new Error('useZero must be used within a ZeroProvider');\n }\n return zero;\n}\n\n/**\n * @deprecated Use {@linkcode useZero} instead, alongside default types defined with:\n *\n * ```ts\n * declare module '@rocicorp/zero' {\n * interface DefaultTypes {\n * schema: typeof schema;\n * context: Context;\n * }\n * }\n */\nexport function createUseZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>() {\n return () => useZero<S, MD, Context>();\n}\n\
|
|
1
|
+
{"version":3,"file":"use-zero.js","names":[],"sources":["../../../../zero-solid/src/use-zero.ts"],"sourcesContent":["import {\n batch,\n createContext,\n createEffect,\n createMemo,\n onCleanup,\n splitProps,\n untrack,\n useContext,\n type Accessor,\n type JSX,\n} from 'solid-js';\nimport {\n Zero,\n type BaseDefaultContext,\n type BaseDefaultSchema,\n type CustomMutatorDefs,\n type DefaultContext,\n type DefaultSchema,\n type ZeroOptions,\n} from './zero.ts';\n\nconst ZeroContext = createContext<\n // oxlint-disable-next-line no-explicit-any\n Accessor<Zero<any, any, any>> | undefined\n>(undefined);\n\n/**\n * @deprecated Use {@linkcode ZeroProvider} instead of managing your own Zero instance.\n */\nexport function createZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>(options: ZeroOptions<S, MD, Context>): Zero<S, MD, Context> {\n const opts = {\n ...options,\n batchViewUpdates: batch,\n };\n return new Zero<S, MD, Context>(opts);\n}\n\nexport function useZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>(): () => Zero<S, MD, Context> {\n const zero = useContext(ZeroContext);\n\n if (zero === undefined) {\n throw new Error('useZero must be used within a ZeroProvider');\n }\n return zero;\n}\n\n/**\n * @deprecated Use {@linkcode useZero} instead, alongside default types defined with:\n *\n * ```ts\n * declare module '@rocicorp/zero' {\n * interface DefaultTypes {\n * schema: typeof schema;\n * context: Context;\n * }\n * }\n */\nexport function createUseZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>() {\n return () => useZero<S, MD, Context>();\n}\n\nexport function ZeroProvider<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>(\n props: {\n children: JSX.Element;\n init?: (zero: Zero<S, MD, Context>) => void;\n } & (\n | {\n zero: Zero<S, MD, Context>;\n }\n | ZeroOptions<S, MD, Context>\n ),\n) {\n let prevAuth = 'auth' in props ? props.auth : undefined;\n\n const auth = createMemo(() => ('auth' in props ? props.auth : undefined));\n const hasAuth = createMemo(() => typeof auth() === 'string');\n\n const zero = createMemo(() => {\n if ('zero' in props) {\n return props.zero;\n }\n\n hasAuth();\n\n const [, options] = splitProps(props, ['children', 'auth']);\n\n const authValue = untrack(auth);\n prevAuth = authValue;\n const createdZero = new Zero({\n ...options,\n ...(authValue !== undefined ? {auth: authValue} : {}),\n batchViewUpdates: batch,\n });\n options.init?.(createdZero);\n onCleanup(() => createdZero.close());\n return createdZero;\n });\n\n createEffect(() => {\n const currentZero = zero();\n if (!currentZero || 'zero' in props) {\n return;\n }\n\n const currentAuth = auth();\n\n if (currentAuth !== prevAuth) {\n const previousAuth = prevAuth;\n prevAuth = currentAuth;\n\n if (typeof previousAuth === 'string' && typeof currentAuth === 'string') {\n void currentZero.connection.connect({auth: currentAuth});\n }\n }\n });\n\n return ZeroContext.Provider({\n value: zero,\n get children() {\n return props.children;\n },\n });\n}\n"],"mappings":";;;;AAsBA,IAAM,cAAc,cAGlB,KAAA,EAAU;;;;AAKZ,SAAgB,WAId,SAA4D;AAK5D,QAAO,IAAI,KAJE;EACX,GAAG;EACH,kBAAkB;EACnB,CACoC;;AAGvC,SAAgB,UAIgB;CAC9B,MAAM,OAAO,WAAW,YAAY;AAEpC,KAAI,SAAS,KAAA,EACX,OAAM,IAAI,MAAM,6CAA6C;AAE/D,QAAO;;;;;;;;;;;;;AAcT,SAAgB,gBAIZ;AACF,cAAa,SAAyB;;AAGxC,SAAgB,aAKd,OASA;CACA,IAAI,WAAW,UAAU,QAAQ,MAAM,OAAO,KAAA;CAE9C,MAAM,OAAO,iBAAkB,UAAU,QAAQ,MAAM,OAAO,KAAA,EAAW;CACzE,MAAM,UAAU,iBAAiB,OAAO,MAAM,KAAK,SAAS;CAE5D,MAAM,OAAO,iBAAiB;AAC5B,MAAI,UAAU,MACZ,QAAO,MAAM;AAGf,WAAS;EAET,MAAM,GAAG,WAAW,WAAW,OAAO,CAAC,YAAY,OAAO,CAAC;EAE3D,MAAM,YAAY,QAAQ,KAAK;AAC/B,aAAW;EACX,MAAM,cAAc,IAAI,KAAK;GAC3B,GAAG;GACH,GAAI,cAAc,KAAA,IAAY,EAAC,MAAM,WAAU,GAAG,EAAE;GACpD,kBAAkB;GACnB,CAAC;AACF,UAAQ,OAAO,YAAY;AAC3B,kBAAgB,YAAY,OAAO,CAAC;AACpC,SAAO;GACP;AAEF,oBAAmB;EACjB,MAAM,cAAc,MAAM;AAC1B,MAAI,CAAC,eAAe,UAAU,MAC5B;EAGF,MAAM,cAAc,MAAM;AAE1B,MAAI,gBAAgB,UAAU;GAC5B,MAAM,eAAe;AACrB,cAAW;AAEX,OAAI,OAAO,iBAAiB,YAAY,OAAO,gBAAgB,SACxD,aAAY,WAAW,QAAQ,EAAC,MAAM,aAAY,CAAC;;GAG5D;AAEF,QAAO,YAAY,SAAS;EAC1B,OAAO;EACP,IAAI,WAAW;AACb,UAAO,MAAM;;EAEhB,CAAC"}
|
|
@@ -7,8 +7,9 @@ function getLikePredicate(pattern, flags) {
|
|
|
7
7
|
return op(String(lhs));
|
|
8
8
|
};
|
|
9
9
|
}
|
|
10
|
+
var likePatternRe = /_|%|\\/;
|
|
10
11
|
function getLikeOp(pattern, flags) {
|
|
11
|
-
if (
|
|
12
|
+
if (!likePatternRe.test(pattern)) {
|
|
12
13
|
if (flags === "i") {
|
|
13
14
|
const rhsLower = pattern.toLowerCase();
|
|
14
15
|
return (lhs) => lhs.toLowerCase() === rhsLower;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"like.js","names":[],"sources":["../../../../../zql/src/builder/like.ts"],"sourcesContent":["import {assertString} from '../../../shared/src/asserts.ts';\nimport type {NonNullValue, SimplePredicateNoNull} from './filter.ts';\n\nexport function getLikePredicate(\n pattern: NonNullValue,\n flags: 'i' | '',\n): SimplePredicateNoNull {\n const op = getLikeOp(String(pattern), flags);\n return (lhs: NonNullValue) => {\n assertString(lhs);\n return op(String(lhs));\n };\n}\n\nfunction getLikeOp(pattern: string, flags: 'i' | ''): (lhs: string) => boolean {\n // if lhs does not contain '%' or '_' then it is a simple string comparison.\n // if it does contain '%' or '_' then it is a regex comparison.\n // '%' is a wildcard for any number of characters\n // '_' is a wildcard for a single character\n // Postgres SQL allows escaping using `\\`.\n\n if (
|
|
1
|
+
{"version":3,"file":"like.js","names":[],"sources":["../../../../../zql/src/builder/like.ts"],"sourcesContent":["import {assertString} from '../../../shared/src/asserts.ts';\nimport type {NonNullValue, SimplePredicateNoNull} from './filter.ts';\n\nexport function getLikePredicate(\n pattern: NonNullValue,\n flags: 'i' | '',\n): SimplePredicateNoNull {\n const op = getLikeOp(String(pattern), flags);\n return (lhs: NonNullValue) => {\n assertString(lhs);\n return op(String(lhs));\n };\n}\n\nconst likePatternRe = /_|%|\\\\/;\n\nfunction getLikeOp(pattern: string, flags: 'i' | ''): (lhs: string) => boolean {\n // if lhs does not contain '%' or '_' then it is a simple string comparison.\n // if it does contain '%' or '_' then it is a regex comparison.\n // '%' is a wildcard for any number of characters\n // '_' is a wildcard for a single character\n // Postgres SQL allows escaping using `\\`.\n\n if (!likePatternRe.test(pattern)) {\n if (flags === 'i') {\n const rhsLower = pattern.toLowerCase();\n return (lhs: string) => lhs.toLowerCase() === rhsLower;\n }\n return (lhs: string) => lhs === pattern;\n }\n const re = patternToRegExp(pattern, flags);\n return (lhs: string) => re.test(lhs);\n}\n\nconst specialCharsRe = /[$()*+.?[\\]\\\\^{|}]/;\n\nfunction patternToRegExp(source: string, flags: '' | 'i' = ''): RegExp {\n // There are a few cases:\n // % => .*\n // _ => .\n // \\x => \\x for any x except special regexp chars\n // special regexp chars => \\special regexp chars\n let pattern = '^';\n for (let i = 0; i < source.length; i++) {\n let c = source[i];\n switch (c) {\n case '%':\n pattern += '.*';\n break;\n case '_':\n pattern += '.';\n break;\n\n // @ts-expect-error fallthrough\n case '\\\\':\n if (i === source.length - 1) {\n throw new Error('LIKE pattern must not end with escape character');\n }\n i++;\n c = source[i];\n\n // fall through\n default:\n if (specialCharsRe.test(c)) {\n pattern += '\\\\';\n }\n pattern += c;\n\n break;\n }\n }\n return new RegExp(pattern + '$', flags + 'm');\n}\n"],"mappings":";;AAGA,SAAgB,iBACd,SACA,OACuB;CACvB,MAAM,KAAK,UAAU,OAAO,QAAQ,EAAE,MAAM;AAC5C,SAAQ,QAAsB;AAC5B,eAAa,IAAI;AACjB,SAAO,GAAG,OAAO,IAAI,CAAC;;;AAI1B,IAAM,gBAAgB;AAEtB,SAAS,UAAU,SAAiB,OAA2C;AAO7E,KAAI,CAAC,cAAc,KAAK,QAAQ,EAAE;AAChC,MAAI,UAAU,KAAK;GACjB,MAAM,WAAW,QAAQ,aAAa;AACtC,WAAQ,QAAgB,IAAI,aAAa,KAAK;;AAEhD,UAAQ,QAAgB,QAAQ;;CAElC,MAAM,KAAK,gBAAgB,SAAS,MAAM;AAC1C,SAAQ,QAAgB,GAAG,KAAK,IAAI;;AAGtC,IAAM,iBAAiB;AAEvB,SAAS,gBAAgB,QAAgB,QAAkB,IAAY;CAMrE,IAAI,UAAU;AACd,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACtC,IAAI,IAAI,OAAO;AACf,UAAQ,GAAR;GACE,KAAK;AACH,eAAW;AACX;GACF,KAAK;AACH,eAAW;AACX;GAGF,KAAK;AACH,QAAI,MAAM,OAAO,SAAS,EACxB,OAAM,IAAI,MAAM,kDAAkD;AAEpE;AACA,QAAI,OAAO;GAGb;AACE,QAAI,eAAe,KAAK,EAAE,CACxB,YAAW;AAEb,eAAW;AAEX;;;AAGN,QAAO,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/data.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/data.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,mCAAmC,CAAC;AAChE,OAAO,KAAK,EAAC,GAAG,EAAE,KAAK,EAAC,MAAM,oCAAoC,CAAC;AACnE,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC;;;GAGG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB,GAAG,EAAE,GAAG,CAAC;IACT;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC;CAC7D,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,MAAM,CA4CxD;AAED,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAExD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,GAAG,eAAe,CAE5D;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,KAAK,MAAM,CAAC;AAEtD,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,UAAU,CAa7E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,OAAO,CAMvD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,QAShD"}
|
package/out/zql/src/ivm/data.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { assertBoolean, assertNumber, assertString } from "../../../shared/src/asserts.js";
|
|
2
1
|
import { compareUTF8 } from "compare-utf8";
|
|
3
2
|
//#region ../zql/src/ivm/data.ts
|
|
4
3
|
/**
|
|
@@ -14,23 +13,15 @@ import { compareUTF8 } from "compare-utf8";
|
|
|
14
13
|
* @returns < 0 if a < b, 0 if a === b, > 0 if a > b
|
|
15
14
|
*/
|
|
16
15
|
function compareValues(a, b) {
|
|
17
|
-
a =
|
|
18
|
-
b =
|
|
16
|
+
a = a ?? null;
|
|
17
|
+
b = b ?? null;
|
|
19
18
|
if (a === b) return 0;
|
|
19
|
+
if (typeof a === "string" && typeof b === "string") return compareUTF8(a, b);
|
|
20
|
+
if (typeof a === "number" && typeof b === "number") return a - b;
|
|
21
|
+
if (typeof a === "boolean" && typeof b === "boolean") return a ? 1 : -1;
|
|
20
22
|
if (a === null) return -1;
|
|
21
23
|
if (b === null) return 1;
|
|
22
|
-
if (typeof a
|
|
23
|
-
assertBoolean(b);
|
|
24
|
-
return a ? 1 : -1;
|
|
25
|
-
}
|
|
26
|
-
if (typeof a === "number") {
|
|
27
|
-
assertNumber(b);
|
|
28
|
-
return a - b;
|
|
29
|
-
}
|
|
30
|
-
if (typeof a === "string") {
|
|
31
|
-
assertString(b);
|
|
32
|
-
return compareUTF8(a, b);
|
|
33
|
-
}
|
|
24
|
+
if (typeof a !== typeof b) throw new Error(`Cannot compare values of different types: ${typeof a} and ${typeof b}`);
|
|
34
25
|
throw new Error(`Unsupported type: ${a}`);
|
|
35
26
|
}
|
|
36
27
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data.js","names":[],"sources":["../../../../../zql/src/ivm/data.ts"],"sourcesContent":["import {compareUTF8} from 'compare-utf8';\nimport
|
|
1
|
+
{"version":3,"file":"data.js","names":[],"sources":["../../../../../zql/src/ivm/data.ts"],"sourcesContent":["import {compareUTF8} from 'compare-utf8';\nimport type {Ordering} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {Stream} from './stream.ts';\n\n/**\n * A row flowing through the pipeline, plus its relationships.\n * Relationships are generated lazily as read.\n */\nexport type Node = {\n row: Row;\n /**\n * Relationships are generated lazily as read.\n * The stream may contain 'yield' to indicate the operator has yielded control.\n * See {@linkcode Operator.fetch} for more details about yields.\n */\n relationships: Record<string, () => Stream<Node | 'yield'>>;\n};\n\n/**\n * Compare two values. The values must be of the same type. This function\n * throws at runtime if the types differ.\n *\n * Note, this function considers `null === null` and\n * `undefined === undefined`. This is different than SQL. In join code,\n * null must be treated separately.\n *\n * See: https://github.com/rocicorp/mono/pull/2116/files#r1704811479\n *\n * @returns < 0 if a < b, 0 if a === b, > 0 if a > b\n */\nexport function compareValues(a: Value, b: Value): number {\n a = a ?? null;\n b = b ?? null;\n\n if (a === b) {\n return 0;\n }\n\n if (typeof a === 'string' && typeof b === 'string') {\n // We compare all strings in Zero as UTF-8. This is the default on SQLite\n // and we need to match it. See:\n // https://blog.replicache.dev/blog/replicache-11-adventures-in-text-encoding.\n //\n // TODO: We could change this since SQLite supports UTF-16. Microbenchmark\n // to see if there's a big win.\n //\n // https://www.sqlite.org/c3ref/create_collation.html\n return compareUTF8(a, b);\n }\n\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b;\n }\n\n if (typeof a === 'boolean' && typeof b === 'boolean') {\n return a ? 1 : -1;\n }\n\n // check with null after since it is less likely to be the common case and we\n // want to avoid the extra checks in that case\n if (a === null) {\n return -1;\n }\n if (b === null) {\n return 1;\n }\n\n if (typeof a !== typeof b) {\n throw new Error(\n `Cannot compare values of different types: ${typeof a} and ${typeof b}`,\n );\n }\n\n throw new Error(`Unsupported type: ${a}`);\n}\n\nexport type NormalizedValue = Exclude<Value, undefined>;\n\n/**\n * We allow undefined to be passed for the convenience of developers, but we\n * treat it equivalently to null. It's better for perf to not create an copy\n * of input values, so we just normalize at use when necessary.\n */\nexport function normalizeUndefined(v: Value): NormalizedValue {\n return v ?? null;\n}\n\nexport type Comparator = (r1: Row, r2: Row) => number;\n\nexport function makeComparator(order: Ordering, reverse?: boolean): Comparator {\n return (a, b) => {\n // Skip destructuring here since it is hot code.\n for (const ord of order) {\n const field = ord[0];\n const comp = compareValues(a[field], b[field]);\n if (comp !== 0) {\n const result = ord[1] === 'asc' ? comp : -comp;\n return reverse ? -result : result;\n }\n }\n return 0;\n };\n}\n\n/**\n * Determine if two values are equal. Note that unlike compareValues() above,\n * this function treats `null` as unequal to itself (and same for `undefined`).\n * This is required to make joins work correctly, but may not be the right\n * semantic for your application.\n */\nexport function valuesEqual(a: Value, b: Value): boolean {\n // oxlint-disable-next-line eqeqeq\n if (a == null || b == null) {\n return false;\n }\n return a === b;\n}\n\nexport function drainStreams(node: Node | 'yield') {\n if (node === 'yield') {\n return;\n }\n for (const stream of Object.values(node.relationships)) {\n for (const node of stream()) {\n drainStreams(node);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AA+BA,SAAgB,cAAc,GAAU,GAAkB;AACxD,KAAI,KAAK;AACT,KAAI,KAAK;AAET,KAAI,MAAM,EACR,QAAO;AAGT,KAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SASxC,QAAO,YAAY,GAAG,EAAE;AAG1B,KAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SACxC,QAAO,IAAI;AAGb,KAAI,OAAO,MAAM,aAAa,OAAO,MAAM,UACzC,QAAO,IAAI,IAAI;AAKjB,KAAI,MAAM,KACR,QAAO;AAET,KAAI,MAAM,KACR,QAAO;AAGT,KAAI,OAAO,MAAM,OAAO,EACtB,OAAM,IAAI,MACR,6CAA6C,OAAO,EAAE,OAAO,OAAO,IACrE;AAGH,OAAM,IAAI,MAAM,qBAAqB,IAAI;;;;;;;AAU3C,SAAgB,mBAAmB,GAA2B;AAC5D,QAAO,KAAK;;AAKd,SAAgB,eAAe,OAAiB,SAA+B;AAC7E,SAAQ,GAAG,MAAM;AAEf,OAAK,MAAM,OAAO,OAAO;GACvB,MAAM,QAAQ,IAAI;GAClB,MAAM,OAAO,cAAc,EAAE,QAAQ,EAAE,OAAO;AAC9C,OAAI,SAAS,GAAG;IACd,MAAM,SAAS,IAAI,OAAO,QAAQ,OAAO,CAAC;AAC1C,WAAO,UAAU,CAAC,SAAS;;;AAG/B,SAAO;;;;;;;;;AAUX,SAAgB,YAAY,GAAU,GAAmB;AAEvD,KAAI,KAAK,QAAQ,KAAK,KACpB,QAAO;AAET,QAAO,MAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-source.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/memory-source.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"memory-source.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/memory-source.ts"],"names":[],"mappings":"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"}
|
|
@@ -431,21 +431,27 @@ function rowMatchesPK(a, b, primaryKey) {
|
|
|
431
431
|
var minValue = Symbol("min-value");
|
|
432
432
|
var maxValue = Symbol("max-value");
|
|
433
433
|
function makeBoundComparator(sort) {
|
|
434
|
+
const len = sort.length;
|
|
435
|
+
const k0 = sort[0][0];
|
|
436
|
+
const a0 = sort[0][1] === "asc";
|
|
437
|
+
const k1 = len > 1 ? sort[1][0] : "";
|
|
438
|
+
const a1 = len > 1 ? sort[1][1] === "asc" : true;
|
|
434
439
|
return (a, b) => {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
440
|
+
const c0 = a0 ? compareBounds(a[k0], b[k0]) : compareBounds(b[k0], a[k0]);
|
|
441
|
+
if (len === 1 || c0 !== 0) return c0;
|
|
442
|
+
const c1 = a1 ? compareBounds(a[k1], b[k1]) : compareBounds(b[k1], a[k1]);
|
|
443
|
+
if (len === 2 || c1 !== 0) return c1;
|
|
444
|
+
for (let i = 2; i < len; i++) {
|
|
445
|
+
const cmp = compareBounds(a[sort[i][0]], b[sort[i][0]]);
|
|
446
|
+
if (cmp !== 0) return sort[i][1] === "asc" ? cmp : -cmp;
|
|
439
447
|
}
|
|
440
448
|
return 0;
|
|
441
449
|
};
|
|
442
450
|
}
|
|
443
451
|
function compareBounds(a, b) {
|
|
444
452
|
if (a === b) return 0;
|
|
445
|
-
if (a ===
|
|
446
|
-
if (b ===
|
|
447
|
-
if (a === maxValue) return 1;
|
|
448
|
-
if (b === maxValue) return -1;
|
|
453
|
+
if (typeof a === "symbol") return a === minValue ? -1 : 1;
|
|
454
|
+
if (typeof b === "symbol") return b === minValue ? 1 : -1;
|
|
449
455
|
return compareValues(a, b);
|
|
450
456
|
}
|
|
451
457
|
function* generateRows(data, scanStart, reverse) {
|