@rocicorp/zero 1.11.0-canary.41 → 1.11.0-canary.42

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.
Files changed (103) hide show
  1. package/out/replicache/src/deleted-clients.d.ts +2 -2
  2. package/out/replicache/src/deleted-clients.js +2 -2
  3. package/out/replicache/src/deleted-clients.js.map +1 -1
  4. package/out/replicache/src/persist/client-group-gc.d.ts +1 -1
  5. package/out/replicache/src/persist/client-group-gc.js +1 -1
  6. package/out/replicache/src/persist/client-group-gc.js.map +1 -1
  7. package/out/replicache/src/replicache-options.d.ts +1 -1
  8. package/out/shared/src/browser-env.d.ts +1 -1
  9. package/out/shared/src/browser-env.js.map +1 -1
  10. package/out/shared/src/set-utils.d.ts +1 -1
  11. package/out/shared/src/set-utils.js +1 -1
  12. package/out/shared/src/set-utils.js.map +1 -1
  13. package/out/zero/package.js +1 -1
  14. package/out/zero/package.js.map +1 -1
  15. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  16. package/out/zero-cache/src/server/change-streamer.js +2 -0
  17. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  18. package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts.map +1 -1
  19. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +4 -2
  20. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  21. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  22. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +17 -6
  23. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  24. package/out/zero-cache/src/types/pg-patch.d.ts +21 -0
  25. package/out/zero-cache/src/types/pg-patch.d.ts.map +1 -0
  26. package/out/zero-cache/src/types/pg-patch.js +29 -0
  27. package/out/zero-cache/src/types/pg-patch.js.map +1 -0
  28. package/out/zero-client/src/client/connection-manager.js +1 -1
  29. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  30. package/out/zero-client/src/client/custom.d.ts +1 -1
  31. package/out/zero-client/src/client/custom.js +1 -1
  32. package/out/zero-client/src/client/custom.js.map +1 -1
  33. package/out/zero-client/src/client/options.d.ts +6 -6
  34. package/out/zero-client/src/client/options.js.map +1 -1
  35. package/out/zero-client/src/client/version.js +1 -1
  36. package/out/zero-client/src/client/zero.d.ts +1 -1
  37. package/out/zero-client/src/client/zero.js +1 -1
  38. package/out/zero-client/src/client/zero.js.map +1 -1
  39. package/out/zero-protocol/src/inspect-up.d.ts +3 -3
  40. package/out/zero-protocol/src/inspect-up.d.ts.map +1 -1
  41. package/out/zero-protocol/src/inspect-up.js +2 -2
  42. package/out/zero-protocol/src/inspect-up.js.map +1 -1
  43. package/out/zero-react/src/use-zero-online.d.ts +1 -1
  44. package/out/zero-react/src/use-zero-online.js +1 -1
  45. package/out/zero-react/src/use-zero-online.js.map +1 -1
  46. package/out/zero-react/src/zero-provider.d.ts +1 -1
  47. package/out/zero-react/src/zero-provider.js +1 -1
  48. package/out/zero-react/src/zero-provider.js.map +1 -1
  49. package/out/zero-server/src/closable-db-transaction.d.ts +1 -1
  50. package/out/zero-server/src/closable-db-transaction.js +1 -1
  51. package/out/zero-server/src/closable-db-transaction.js.map +1 -1
  52. package/out/zero-server/src/custom.d.ts +1 -1
  53. package/out/zero-server/src/custom.js +1 -1
  54. package/out/zero-server/src/custom.js.map +1 -1
  55. package/out/zero-server/src/process-mutations.d.ts +3 -3
  56. package/out/zero-server/src/process-mutations.js +1 -1
  57. package/out/zero-server/src/process-mutations.js.map +1 -1
  58. package/out/zero-server/src/push-processor.d.ts +1 -1
  59. package/out/zero-server/src/push-processor.js +1 -1
  60. package/out/zero-server/src/push-processor.js.map +1 -1
  61. package/out/zero-server/src/queries/process-queries.d.ts +3 -3
  62. package/out/zero-server/src/queries/process-queries.js +2 -2
  63. package/out/zero-server/src/queries/process-queries.js.map +1 -1
  64. package/out/zero-server/src/schema.d.ts +1 -1
  65. package/out/zero-server/src/schema.js +1 -1
  66. package/out/zero-server/src/schema.js.map +1 -1
  67. package/out/zero-server/src/zql-database.d.ts +2 -2
  68. package/out/zero-server/src/zql-database.js +2 -2
  69. package/out/zero-server/src/zql-database.js.map +1 -1
  70. package/out/zero-solid/src/use-query.d.ts +2 -2
  71. package/out/zero-solid/src/use-query.js +1 -1
  72. package/out/zero-solid/src/use-query.js.map +1 -1
  73. package/out/zero-solid/src/use-zero-online.d.ts +1 -1
  74. package/out/zero-solid/src/use-zero-online.js +1 -1
  75. package/out/zero-solid/src/use-zero-online.js.map +1 -1
  76. package/out/zero-solid/src/use-zero.d.ts +2 -2
  77. package/out/zero-solid/src/use-zero.js +2 -2
  78. package/out/zero-solid/src/use-zero.js.map +1 -1
  79. package/out/zql/src/ivm/change.d.ts +3 -3
  80. package/out/zql/src/ivm/change.js.map +1 -1
  81. package/out/zql/src/ivm/data.d.ts +1 -1
  82. package/out/zql/src/ivm/data.js.map +1 -1
  83. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
  84. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +1 -1
  85. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  86. package/out/zql/src/mutate/custom.d.ts +3 -3
  87. package/out/zql/src/mutate/custom.js.map +1 -1
  88. package/out/zql/src/query/create-builder.d.ts +1 -1
  89. package/out/zql/src/query/create-builder.d.ts.map +1 -1
  90. package/out/zql/src/query/create-builder.js +1 -1
  91. package/out/zql/src/query/create-builder.js.map +1 -1
  92. package/out/zql/src/query/named.d.ts +2 -2
  93. package/out/zql/src/query/named.js +2 -2
  94. package/out/zql/src/query/named.js.map +1 -1
  95. package/out/zql/src/query/query-impl.js +3 -3
  96. package/out/zql/src/query/query-impl.js.map +1 -1
  97. package/out/zql/src/query/query-internals.d.ts +5 -5
  98. package/out/zql/src/query/query-internals.js.map +1 -1
  99. package/out/zql/src/query/query-transitions.d.ts +5 -5
  100. package/out/zql/src/query/query-transitions.js +2 -2
  101. package/out/zql/src/query/query-transitions.js.map +1 -1
  102. package/out/zql/src/query/query.d.ts +8 -8
  103. package/package.json +1 -1
@@ -2,7 +2,7 @@ import type { Row } from '../../../zero-protocol/src/data.ts';
2
2
  import { type EditChange } from './change.ts';
3
3
  import type { InputBase, Output } from './operator.ts';
4
4
  /**
5
- * This takes an {@linkcode EditChange} and a predicate that determines if a row
5
+ * This takes an {@link EditChange} and a predicate that determines if a row
6
6
  * should be present based on the row's data. It then splits the change and
7
7
  * pushes the appropriate changes to the output based on the predicate.
8
8
  */
@@ -2,7 +2,7 @@ import { emptyArray } from "../../../shared/src/sentinels.js";
2
2
  import { makeAddChange, makeRemoveChange } from "./change.js";
3
3
  //#region ../zql/src/ivm/maybe-split-and-push-edit-change.ts
4
4
  /**
5
- * This takes an {@linkcode EditChange} and a predicate that determines if a row
5
+ * This takes an {@link EditChange} and a predicate that determines if a row
6
6
  * should be present based on the row's data. It then splits the change and
7
7
  * pushes the appropriate changes to the output based on the predicate.
8
8
  */
@@ -1 +1 @@
1
- {"version":3,"file":"maybe-split-and-push-edit-change.js","names":[],"sources":["../../../../../zql/src/ivm/maybe-split-and-push-edit-change.ts"],"sourcesContent":["import {emptyArray} from '../../../shared/src/sentinels.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport {ChangeIndex} from './change-index.ts';\nimport {makeAddChange, makeRemoveChange, type EditChange} from './change.ts';\nimport type {InputBase, Output} from './operator.ts';\n\n/**\n * This takes an {@linkcode EditChange} and a predicate that determines if a row\n * should be present based on the row's data. It then splits the change and\n * pushes the appropriate changes to the output based on the predicate.\n */\nexport function maybeSplitAndPushEditChange(\n change: EditChange,\n predicate: (row: Row) => boolean,\n output: Output,\n pusher: InputBase,\n) {\n const oldWasPresent = predicate(change[ChangeIndex.OLD_NODE].row);\n const newIsPresent = predicate(change[ChangeIndex.NODE].row);\n\n if (oldWasPresent && newIsPresent) {\n return output.push(change, pusher);\n }\n if (oldWasPresent && !newIsPresent) {\n return output.push(makeRemoveChange(change[ChangeIndex.OLD_NODE]), pusher);\n }\n if (!oldWasPresent && newIsPresent) {\n return output.push(makeAddChange(change[ChangeIndex.NODE]), pusher);\n }\n\n return emptyArray;\n}\n"],"mappings":";;;;;;;;AAWA,SAAgB,4BACd,QACA,WACA,QACA,QACA;CACA,MAAM,gBAAgB,UAAU,OAAO,GAAsB,GAAG;CAChE,MAAM,eAAe,UAAU,OAAO,GAAkB,GAAG;CAE3D,IAAI,iBAAiB,cACnB,OAAO,OAAO,KAAK,QAAQ,MAAM;CAEnC,IAAI,iBAAiB,CAAC,cACpB,OAAO,OAAO,KAAK,iBAAiB,OAAO,EAAqB,GAAG,MAAM;CAE3E,IAAI,CAAC,iBAAiB,cACpB,OAAO,OAAO,KAAK,cAAc,OAAO,EAAiB,GAAG,MAAM;CAGpE,OAAO;AACT"}
1
+ {"version":3,"file":"maybe-split-and-push-edit-change.js","names":[],"sources":["../../../../../zql/src/ivm/maybe-split-and-push-edit-change.ts"],"sourcesContent":["import {emptyArray} from '../../../shared/src/sentinels.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport {ChangeIndex} from './change-index.ts';\nimport {makeAddChange, makeRemoveChange, type EditChange} from './change.ts';\nimport type {InputBase, Output} from './operator.ts';\n\n/**\n * This takes an {@link EditChange} and a predicate that determines if a row\n * should be present based on the row's data. It then splits the change and\n * pushes the appropriate changes to the output based on the predicate.\n */\nexport function maybeSplitAndPushEditChange(\n change: EditChange,\n predicate: (row: Row) => boolean,\n output: Output,\n pusher: InputBase,\n) {\n const oldWasPresent = predicate(change[ChangeIndex.OLD_NODE].row);\n const newIsPresent = predicate(change[ChangeIndex.NODE].row);\n\n if (oldWasPresent && newIsPresent) {\n return output.push(change, pusher);\n }\n if (oldWasPresent && !newIsPresent) {\n return output.push(makeRemoveChange(change[ChangeIndex.OLD_NODE]), pusher);\n }\n if (!oldWasPresent && newIsPresent) {\n return output.push(makeAddChange(change[ChangeIndex.NODE]), pusher);\n }\n\n return emptyArray;\n}\n"],"mappings":";;;;;;;;AAWA,SAAgB,4BACd,QACA,WACA,QACA,QACA;CACA,MAAM,gBAAgB,UAAU,OAAO,GAAsB,GAAG;CAChE,MAAM,eAAe,UAAU,OAAO,GAAkB,GAAG;CAE3D,IAAI,iBAAiB,cACnB,OAAO,OAAO,KAAK,QAAQ,MAAM;CAEnC,IAAI,iBAAiB,CAAC,cACpB,OAAO,OAAO,KAAK,iBAAiB,OAAO,EAAqB,GAAG,MAAM;CAE3E,IAAI,CAAC,iBAAiB,cACpB,OAAO,OAAO,KAAK,cAAc,OAAO,EAAiB,GAAG,MAAM;CAGpE,OAAO;AACT"}
@@ -33,7 +33,7 @@ export interface TransactionBase<S extends Schema> {
33
33
  readonly reason: TransactionReason;
34
34
  readonly mutate: TransactionMutate<S>;
35
35
  /**
36
- * @deprecated Use {@linkcode createBuilder} with `tx.run(zql.table.where(...))` instead.
36
+ * @deprecated Use {@link createBuilder} with `tx.run(zql.table.where(...))` instead.
37
37
  */
38
38
  readonly query: ConditionalSchemaQuery<S>;
39
39
  run<TTable extends keyof S['tables'] & string, TReturn>(query: Query<TTable, S, TReturn>, options?: RunOptions): Promise<HumanReadable<TReturn>>;
@@ -103,8 +103,8 @@ export interface DBConnection<TWrappedTransaction> {
103
103
  */
104
104
  query?: Queryable['query'] | undefined;
105
105
  /**
106
- * Mirrors {@linkcode DBTransaction.runQuery} for reads issued through
107
- * {@linkcode query}. An adapter that customizes `DBTransaction.runQuery`
106
+ * Mirrors {@link DBTransaction.runQuery} for reads issued through
107
+ * {@link query}. An adapter that customizes `DBTransaction.runQuery`
108
108
  * should implement this too so that `ZQLDatabase.run` and `tx.run` execute
109
109
  * a query the same way. Optional; when absent, the default Postgres
110
110
  * executor is used.
@@ -1 +1 @@
1
- {"version":3,"file":"custom.js","names":[],"sources":["../../../../../zql/src/mutate/custom.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {AST} from '../../../zero-protocol/src/ast.ts';\nimport type {\n DefaultSchema,\n DefaultWrappedTransaction,\n} from '../../../zero-types/src/default-types.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport type {ServerSchema} from '../../../zero-types/src/server-schema.ts';\nimport type {Format} from '../ivm/view.ts';\nimport type {HumanReadable, Query, RunOptions} from '../query/query.ts';\nimport type {ConditionalSchemaQuery} from '../query/schema-query.ts';\nimport type {CRUDMutateRequest, SchemaCRUD, TransactionMutate} from './crud.ts';\n\ntype ClientID = string;\n\n/**\n * A base transaction interface that any Transaction<S, T> is assignable to.\n * Used in places where the schema type doesn't need to be preserved,\n * like the public signature of Mutator.fn.\n */\nexport interface AnyTransaction {\n readonly location: Location;\n readonly clientID: string;\n readonly mutationID: number;\n readonly reason: TransactionReason;\n}\n\nexport type Location = 'client' | 'server';\nexport type TransactionReason = 'optimistic' | 'rebase' | 'authoritative';\n\nexport interface TransactionBase<S extends Schema> {\n readonly location: Location;\n readonly clientID: ClientID;\n /**\n * The ID of the mutation that is being applied.\n */\n readonly mutationID: number;\n\n /**\n * The reason for the transaction.\n */\n readonly reason: TransactionReason;\n\n readonly mutate: TransactionMutate<S>;\n /**\n * @deprecated Use {@linkcode createBuilder} with `tx.run(zql.table.where(...))` instead.\n */\n readonly query: ConditionalSchemaQuery<S>;\n\n run<TTable extends keyof S['tables'] & string, TReturn>(\n query: Query<TTable, S, TReturn>,\n options?: RunOptions,\n ): Promise<HumanReadable<TReturn>>;\n}\n\nexport type Transaction<\n S extends Schema = DefaultSchema,\n TWrappedTransaction = DefaultWrappedTransaction,\n> = ServerTransaction<S, TWrappedTransaction> | ClientTransaction<S>;\n\n/**\n * Decides whether to run a mutator again after a run fails. Gets what was\n * thrown and the number of the re-run being decided: 1 after the first\n * failure. Return `true` to re-run, or a promise resolving to `true` to re-run\n * once it resolves, which is how to back off. Anything else, including a\n * throw, counts as no.\n */\nexport type RetryPredicate = (\n error: unknown,\n attempt: number,\n) => boolean | Promise<boolean>;\n\nexport interface ServerTransaction<\n S extends Schema = DefaultSchema,\n TWrappedTransaction = DefaultWrappedTransaction,\n> extends TransactionBase<S> {\n readonly location: 'server';\n readonly reason: 'authoritative';\n readonly dbTransaction: DBTransaction<TWrappedTransaction>;\n\n /**\n * If this run fails, asks `shouldRetry` whether to run the mutator again in\n * a fresh transaction. It sees any failure of the run: what the mutator\n * throws, and errors the database raises at `COMMIT`, which the mutator\n * cannot catch. Everything the failed run wrote is rolled back, and the\n * re-run reads a new snapshot.\n *\n * Calls add up: the mutator is re-run if any predicate registered in the\n * run says yes. They are all asked at once, so the re-run starts as soon as\n * the first one answers yes, and the other answers are ignored. If none\n * says yes, the error is recorded as the mutation's result.\n *\n * It covers this run only, so the re-run must call `retryOn` again to be\n * retried again. Call it before anything that can fail. Within one push the\n * mutator runs at most 5 times. Only use it for a mutator that is safe to\n * run again.\n *\n * `shouldRetry` runs after this run's transaction is over, so it cannot use\n * `tx`: reading, writing or reaching `dbTransaction` through it throws.\n */\n retryOn(shouldRetry: RetryPredicate): void;\n}\n\n/**\n * An instance of this is passed to custom mutator implementations and\n * allows reading and writing to the database and IVM at the head at which the\n * mutator is being applied.\n */\nexport interface ClientTransaction<\n S extends Schema = DefaultSchema,\n> extends TransactionBase<S> {\n readonly location: 'client';\n readonly reason: 'optimistic' | 'rebase';\n}\n\nexport interface Row {\n [column: string]: unknown;\n}\n\nexport interface DBConnection<TWrappedTransaction> {\n transaction: <T>(\n cb: (tx: DBTransaction<TWrappedTransaction>) => Promise<T>,\n ) => Promise<T>;\n\n /**\n * Executes a single SQL statement on the connection without opening,\n * committing, or rolling back a transaction of its own. With a pooled\n * handle this is a plain autocommit statement. With a single dedicated\n * connection, driver semantics apply: a `pg` `Client` queues it behind, and\n * inside, whatever transaction is open on that connection, while postgres.js\n * waits for the reserved connection to be released.\n *\n * Optional. When present, `ZQLDatabase.run` uses it for single-statement\n * reads instead of `transaction`, so no `BEGIN`/`COMMIT` round-trips are\n * needed and any setup done inside `transaction` does not apply to those\n * reads. Custom adapters must implement this to get that behavior; when\n * absent, `ZQLDatabase.run` falls back to `transaction`.\n */\n query?: Queryable['query'] | undefined;\n\n /**\n * Mirrors {@linkcode DBTransaction.runQuery} for reads issued through\n * {@linkcode query}. An adapter that customizes `DBTransaction.runQuery`\n * should implement this too so that `ZQLDatabase.run` and `tx.run` execute\n * a query the same way. Optional; when absent, the default Postgres\n * executor is used.\n */\n runQuery?: DBTransaction<TWrappedTransaction>['runQuery'] | undefined;\n}\n\nexport interface DBTransaction<T> extends Queryable {\n readonly wrappedTransaction: T;\n runQuery<TReturn>(\n ast: AST,\n format: Format,\n schema: Schema,\n serverSchema: ServerSchema,\n ): Promise<HumanReadable<TReturn>>;\n}\n\nexport interface Queryable {\n query: (query: string, args: unknown[]) => Promise<Iterable<Row>>;\n}\n\n/**\n * A callable mutate shape with optional table helpers used by helper factories\n * like `makeMutateCRUD`. Transactions expose `SchemaCRUD` instead of this type.\n */\nexport type MutateCRUD<S extends Schema, AddSchemaCRUD extends boolean> = {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n (request: CRUDMutateRequest<S, any, any, any>): Promise<void>;\n} & (AddSchemaCRUD extends true ? SchemaCRUD<S> : {});\n\nexport function customMutatorKey(sep: string, parts: string[]) {\n for (const part of parts) {\n assert(\n !part.includes(sep),\n `mutator names/namespaces must not include a ${sep}`,\n );\n }\n return parts.join(sep);\n}\n"],"mappings":";;AA6KA,SAAgB,iBAAiB,KAAa,OAAiB;CAC7D,KAAK,MAAM,QAAQ,OACjB,OACE,CAAC,KAAK,SAAS,GAAG,GAClB,+CAA+C,KACjD;CAEF,OAAO,MAAM,KAAK,GAAG;AACvB"}
1
+ {"version":3,"file":"custom.js","names":[],"sources":["../../../../../zql/src/mutate/custom.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {AST} from '../../../zero-protocol/src/ast.ts';\nimport type {\n DefaultSchema,\n DefaultWrappedTransaction,\n} from '../../../zero-types/src/default-types.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport type {ServerSchema} from '../../../zero-types/src/server-schema.ts';\nimport type {Format} from '../ivm/view.ts';\nimport type {HumanReadable, Query, RunOptions} from '../query/query.ts';\nimport type {ConditionalSchemaQuery} from '../query/schema-query.ts';\nimport type {CRUDMutateRequest, SchemaCRUD, TransactionMutate} from './crud.ts';\n\ntype ClientID = string;\n\n/**\n * A base transaction interface that any Transaction<S, T> is assignable to.\n * Used in places where the schema type doesn't need to be preserved,\n * like the public signature of Mutator.fn.\n */\nexport interface AnyTransaction {\n readonly location: Location;\n readonly clientID: string;\n readonly mutationID: number;\n readonly reason: TransactionReason;\n}\n\nexport type Location = 'client' | 'server';\nexport type TransactionReason = 'optimistic' | 'rebase' | 'authoritative';\n\nexport interface TransactionBase<S extends Schema> {\n readonly location: Location;\n readonly clientID: ClientID;\n /**\n * The ID of the mutation that is being applied.\n */\n readonly mutationID: number;\n\n /**\n * The reason for the transaction.\n */\n readonly reason: TransactionReason;\n\n readonly mutate: TransactionMutate<S>;\n /**\n * @deprecated Use {@link createBuilder} with `tx.run(zql.table.where(...))` instead.\n */\n readonly query: ConditionalSchemaQuery<S>;\n\n run<TTable extends keyof S['tables'] & string, TReturn>(\n query: Query<TTable, S, TReturn>,\n options?: RunOptions,\n ): Promise<HumanReadable<TReturn>>;\n}\n\nexport type Transaction<\n S extends Schema = DefaultSchema,\n TWrappedTransaction = DefaultWrappedTransaction,\n> = ServerTransaction<S, TWrappedTransaction> | ClientTransaction<S>;\n\n/**\n * Decides whether to run a mutator again after a run fails. Gets what was\n * thrown and the number of the re-run being decided: 1 after the first\n * failure. Return `true` to re-run, or a promise resolving to `true` to re-run\n * once it resolves, which is how to back off. Anything else, including a\n * throw, counts as no.\n */\nexport type RetryPredicate = (\n error: unknown,\n attempt: number,\n) => boolean | Promise<boolean>;\n\nexport interface ServerTransaction<\n S extends Schema = DefaultSchema,\n TWrappedTransaction = DefaultWrappedTransaction,\n> extends TransactionBase<S> {\n readonly location: 'server';\n readonly reason: 'authoritative';\n readonly dbTransaction: DBTransaction<TWrappedTransaction>;\n\n /**\n * If this run fails, asks `shouldRetry` whether to run the mutator again in\n * a fresh transaction. It sees any failure of the run: what the mutator\n * throws, and errors the database raises at `COMMIT`, which the mutator\n * cannot catch. Everything the failed run wrote is rolled back, and the\n * re-run reads a new snapshot.\n *\n * Calls add up: the mutator is re-run if any predicate registered in the\n * run says yes. They are all asked at once, so the re-run starts as soon as\n * the first one answers yes, and the other answers are ignored. If none\n * says yes, the error is recorded as the mutation's result.\n *\n * It covers this run only, so the re-run must call `retryOn` again to be\n * retried again. Call it before anything that can fail. Within one push the\n * mutator runs at most 5 times. Only use it for a mutator that is safe to\n * run again.\n *\n * `shouldRetry` runs after this run's transaction is over, so it cannot use\n * `tx`: reading, writing or reaching `dbTransaction` through it throws.\n */\n retryOn(shouldRetry: RetryPredicate): void;\n}\n\n/**\n * An instance of this is passed to custom mutator implementations and\n * allows reading and writing to the database and IVM at the head at which the\n * mutator is being applied.\n */\nexport interface ClientTransaction<\n S extends Schema = DefaultSchema,\n> extends TransactionBase<S> {\n readonly location: 'client';\n readonly reason: 'optimistic' | 'rebase';\n}\n\nexport interface Row {\n [column: string]: unknown;\n}\n\nexport interface DBConnection<TWrappedTransaction> {\n transaction: <T>(\n cb: (tx: DBTransaction<TWrappedTransaction>) => Promise<T>,\n ) => Promise<T>;\n\n /**\n * Executes a single SQL statement on the connection without opening,\n * committing, or rolling back a transaction of its own. With a pooled\n * handle this is a plain autocommit statement. With a single dedicated\n * connection, driver semantics apply: a `pg` `Client` queues it behind, and\n * inside, whatever transaction is open on that connection, while postgres.js\n * waits for the reserved connection to be released.\n *\n * Optional. When present, `ZQLDatabase.run` uses it for single-statement\n * reads instead of `transaction`, so no `BEGIN`/`COMMIT` round-trips are\n * needed and any setup done inside `transaction` does not apply to those\n * reads. Custom adapters must implement this to get that behavior; when\n * absent, `ZQLDatabase.run` falls back to `transaction`.\n */\n query?: Queryable['query'] | undefined;\n\n /**\n * Mirrors {@link DBTransaction.runQuery} for reads issued through\n * {@link query}. An adapter that customizes `DBTransaction.runQuery`\n * should implement this too so that `ZQLDatabase.run` and `tx.run` execute\n * a query the same way. Optional; when absent, the default Postgres\n * executor is used.\n */\n runQuery?: DBTransaction<TWrappedTransaction>['runQuery'] | undefined;\n}\n\nexport interface DBTransaction<T> extends Queryable {\n readonly wrappedTransaction: T;\n runQuery<TReturn>(\n ast: AST,\n format: Format,\n schema: Schema,\n serverSchema: ServerSchema,\n ): Promise<HumanReadable<TReturn>>;\n}\n\nexport interface Queryable {\n query: (query: string, args: unknown[]) => Promise<Iterable<Row>>;\n}\n\n/**\n * A callable mutate shape with optional table helpers used by helper factories\n * like `makeMutateCRUD`. Transactions expose `SchemaCRUD` instead of this type.\n */\nexport type MutateCRUD<S extends Schema, AddSchemaCRUD extends boolean> = {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n (request: CRUDMutateRequest<S, any, any, any>): Promise<void>;\n} & (AddSchemaCRUD extends true ? SchemaCRUD<S> : {});\n\nexport function customMutatorKey(sep: string, parts: string[]) {\n for (const part of parts) {\n assert(\n !part.includes(sep),\n `mutator names/namespaces must not include a ${sep}`,\n );\n }\n return parts.join(sep);\n}\n"],"mappings":";;AA6KA,SAAgB,iBAAiB,KAAa,OAAiB;CAC7D,KAAK,MAAM,QAAQ,OACjB,OACE,CAAC,KAAK,SAAS,GAAG,GAClB,+CAA+C,KACjD;CAEF,OAAO,MAAM,KAAK,GAAG;AACvB"}
@@ -5,6 +5,6 @@ import type { ConditionalSchemaQuery, SchemaQuery } from './schema-query.ts';
5
5
  * Returns a set of query builders for the given schema.
6
6
  */
7
7
  export declare function createBuilder<S extends Schema>(schema: S): SchemaQuery<S>;
8
- /** @deprecated Use {@linkcode createBuilder} with `tx.run(zql.table.where(...))` instead. */
8
+ /** @deprecated Use {@link createBuilder} with `tx.run(zql.table.where(...))` instead. */
9
9
  export declare function createRunnableBuilder<S extends Schema>(delegate: QueryDelegate, schema: S): ConditionalSchemaQuery<S>;
10
10
  //# sourceMappingURL=create-builder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-builder.d.ts","sourceRoot":"","sources":["../../../../../zql/src/query/create-builder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAC9D,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAIvD,OAAO,KAAK,EAAC,sBAAsB,EAAE,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAE3E;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAIzE;AAED,6FAA6F;AAC7F,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,EACpD,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,CAAC,GACR,sBAAsB,CAAC,CAAC,CAAC,CAQ3B"}
1
+ {"version":3,"file":"create-builder.d.ts","sourceRoot":"","sources":["../../../../../zql/src/query/create-builder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAC9D,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAIvD,OAAO,KAAK,EAAC,sBAAsB,EAAE,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAE3E;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAIzE;AAED,yFAAyF;AACzF,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,EACpD,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,CAAC,GACR,sBAAsB,CAAC,CAAC,CAAC,CAQ3B"}
@@ -8,7 +8,7 @@ import { newRunnableQuery } from "./runnable-query-impl.js";
8
8
  function createBuilder(schema) {
9
9
  return createBuilderWithQueryFactory(schema, (table) => newQuery(schema, table));
10
10
  }
11
- /** @deprecated Use {@linkcode createBuilder} with `tx.run(zql.table.where(...))` instead. */
11
+ /** @deprecated Use {@link createBuilder} with `tx.run(zql.table.where(...))` instead. */
12
12
  function createRunnableBuilder(delegate, schema) {
13
13
  if (!schema.enableLegacyQueries) return;
14
14
  return createBuilderWithQueryFactory(schema, (table) => newRunnableQuery(delegate, schema, table));
@@ -1 +1 @@
1
- {"version":3,"file":"create-builder.js","names":[],"sources":["../../../../../zql/src/query/create-builder.ts"],"sourcesContent":["import {recordProxy} from '../../../shared/src/record-proxy.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport type {QueryDelegate} from './query-delegate.ts';\nimport {newQuery} from './query-impl.ts';\nimport type {Query} from './query.ts';\nimport {newRunnableQuery} from './runnable-query-impl.ts';\nimport type {ConditionalSchemaQuery, SchemaQuery} from './schema-query.ts';\n\n/**\n * Returns a set of query builders for the given schema.\n */\nexport function createBuilder<S extends Schema>(schema: S): SchemaQuery<S> {\n return createBuilderWithQueryFactory(schema, table =>\n newQuery(schema, table),\n );\n}\n\n/** @deprecated Use {@linkcode createBuilder} with `tx.run(zql.table.where(...))` instead. */\nexport function createRunnableBuilder<S extends Schema>(\n delegate: QueryDelegate,\n schema: S,\n): ConditionalSchemaQuery<S> {\n if (!schema.enableLegacyQueries) {\n return undefined as ConditionalSchemaQuery<S>;\n }\n\n return createBuilderWithQueryFactory(schema, table =>\n newRunnableQuery(delegate, schema, table),\n ) as ConditionalSchemaQuery<S>;\n}\n\nfunction createBuilderWithQueryFactory<S extends Schema>(\n schema: S,\n queryFactory: (table: keyof S['tables'] & string) => Query<string, S>,\n): SchemaQuery<S> {\n // Create a target with no prototype so accessing unknown properties returns\n // undefined instead of inherited Object.prototype methods (e.g., toString).\n // This fixes React 19 dev mode compatibility where accessing $$typeof should\n // return undefined rather than throwing.\n const target = Object.assign(Object.create(null), schema.tables) as Record<\n string,\n unknown\n >;\n\n // No onMissing handler needed - unknown properties return undefined due to\n // null prototype, which is the desired behavior for normal JS object semantics.\n return recordProxy(target, (_tableSchema, prop) =>\n queryFactory(prop),\n ) as SchemaQuery<S>;\n}\n"],"mappings":";;;;;;;AAWA,SAAgB,cAAgC,QAA2B;CACzE,OAAO,8BAA8B,SAAQ,UAC3C,SAAS,QAAQ,KAAK,CACxB;AACF;;AAGA,SAAgB,sBACd,UACA,QAC2B;CAC3B,IAAI,CAAC,OAAO,qBACV;CAGF,OAAO,8BAA8B,SAAQ,UAC3C,iBAAiB,UAAU,QAAQ,KAAK,CAC1C;AACF;AAEA,SAAS,8BACP,QACA,cACgB;CAYhB,OAAO,YAPQ,OAAO,OAAO,OAAO,OAAO,IAAI,GAAG,OAAO,MAOtC,IAAS,cAAc,SACxC,aAAa,IAAI,CACnB;AACF"}
1
+ {"version":3,"file":"create-builder.js","names":[],"sources":["../../../../../zql/src/query/create-builder.ts"],"sourcesContent":["import {recordProxy} from '../../../shared/src/record-proxy.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport type {QueryDelegate} from './query-delegate.ts';\nimport {newQuery} from './query-impl.ts';\nimport type {Query} from './query.ts';\nimport {newRunnableQuery} from './runnable-query-impl.ts';\nimport type {ConditionalSchemaQuery, SchemaQuery} from './schema-query.ts';\n\n/**\n * Returns a set of query builders for the given schema.\n */\nexport function createBuilder<S extends Schema>(schema: S): SchemaQuery<S> {\n return createBuilderWithQueryFactory(schema, table =>\n newQuery(schema, table),\n );\n}\n\n/** @deprecated Use {@link createBuilder} with `tx.run(zql.table.where(...))` instead. */\nexport function createRunnableBuilder<S extends Schema>(\n delegate: QueryDelegate,\n schema: S,\n): ConditionalSchemaQuery<S> {\n if (!schema.enableLegacyQueries) {\n return undefined as ConditionalSchemaQuery<S>;\n }\n\n return createBuilderWithQueryFactory(schema, table =>\n newRunnableQuery(delegate, schema, table),\n ) as ConditionalSchemaQuery<S>;\n}\n\nfunction createBuilderWithQueryFactory<S extends Schema>(\n schema: S,\n queryFactory: (table: keyof S['tables'] & string) => Query<string, S>,\n): SchemaQuery<S> {\n // Create a target with no prototype so accessing unknown properties returns\n // undefined instead of inherited Object.prototype methods (e.g., toString).\n // This fixes React 19 dev mode compatibility where accessing $$typeof should\n // return undefined rather than throwing.\n const target = Object.assign(Object.create(null), schema.tables) as Record<\n string,\n unknown\n >;\n\n // No onMissing handler needed - unknown properties return undefined due to\n // null prototype, which is the desired behavior for normal JS object semantics.\n return recordProxy(target, (_tableSchema, prop) =>\n queryFactory(prop),\n ) as SchemaQuery<S>;\n}\n"],"mappings":";;;;;;;AAWA,SAAgB,cAAgC,QAA2B;CACzE,OAAO,8BAA8B,SAAQ,UAC3C,SAAS,QAAQ,KAAK,CACxB;AACF;;AAGA,SAAgB,sBACd,UACA,QAC2B;CAC3B,IAAI,CAAC,OAAO,qBACV;CAGF,OAAO,8BAA8B,SAAQ,UAC3C,iBAAiB,UAAU,QAAQ,KAAK,CAC1C;AACF;AAEA,SAAS,8BACP,QACA,cACgB;CAYhB,OAAO,YAPQ,OAAO,OAAO,OAAO,OAAO,IAAI,GAAG,OAAO,MAOtC,IAAS,cAAc,SACxC,aAAa,IAAI,CACnB;AACF"}
@@ -13,11 +13,11 @@ export type SyncedQuery<TName extends string, TContext, TTakesContext extends bo
13
13
  takesContext: TTakesContext;
14
14
  };
15
15
  /**
16
- * @deprecated Use {@linkcode defineQuery} instead.
16
+ * @deprecated Use {@link defineQuery} instead.
17
17
  */
18
18
  export declare function syncedQuery<TName extends string, TArg extends ReadonlyJSONValue[], TReturnQuery extends AnyQuery>(name: TName, parser: ParseFn<TArg> | HasParseFn<TArg> | undefined, fn: QueryFn<unknown, false, TArg, TReturnQuery>): SyncedQuery<TName, unknown, false, TArg, TReturnQuery>;
19
19
  /**
20
- * @deprecated Use {@linkcode defineQuery} instead.
20
+ * @deprecated Use {@link defineQuery} instead.
21
21
  */
22
22
  export declare function syncedQueryWithContext<TName extends string, TContext, TArg extends ReadonlyJSONValue[], TReturnQuery extends AnyQuery>(name: TName, parser: ParseFn<TArg> | HasParseFn<TArg> | undefined, fn: QueryFn<TContext, true, TArg, TReturnQuery>): SyncedQuery<TName, TContext, true, TArg, TReturnQuery>;
23
23
  /** @deprecated */
@@ -9,7 +9,7 @@ function normalizeParser(parser) {
9
9
  }
10
10
  }
11
11
  /**
12
- * @deprecated Use {@linkcode defineQuery} instead.
12
+ * @deprecated Use {@link defineQuery} instead.
13
13
  */
14
14
  function syncedQuery(name, parser, fn) {
15
15
  const impl = syncedQueryImpl(name, fn, false);
@@ -20,7 +20,7 @@ function syncedQuery(name, parser, fn) {
20
20
  return ret;
21
21
  }
22
22
  /**
23
- * @deprecated Use {@linkcode defineQuery} instead.
23
+ * @deprecated Use {@link defineQuery} instead.
24
24
  */
25
25
  function syncedQueryWithContext(name, parser, fn) {
26
26
  const impl = syncedQueryImpl(name, fn, true);
@@ -1 +1 @@
1
- {"version":3,"file":"named.js","names":[],"sources":["../../../../../zql/src/query/named.ts"],"sourcesContent":["import type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {QueryParseError} from './error.ts';\nimport {asQueryInternals} from './query-internals.ts';\nimport {type AnyQuery} from './query.ts';\n\n/** @deprecated */\nexport type QueryFn<\n TContext,\n TTakesContext extends boolean,\n TArg extends ReadonlyJSONValue[],\n TReturnQuery extends AnyQuery,\n> = TTakesContext extends false\n ? {(...args: TArg): TReturnQuery}\n : {(context: TContext, ...args: TArg): TReturnQuery};\n\n/** @deprecated */\nexport type SyncedQuery<\n TName extends string,\n TContext,\n TTakesContext extends boolean,\n TArg extends ReadonlyJSONValue[],\n TReturnQuery extends AnyQuery,\n> = QueryFn<TContext, TTakesContext, TArg, TReturnQuery> & {\n queryName: TName;\n parse: ParseFn<TArg> | undefined;\n takesContext: TTakesContext;\n};\n\nfunction normalizeParser<T extends ReadonlyJSONValue[]>(\n parser: ParseFn<T> | HasParseFn<T> | undefined,\n): ParseFn<T> | undefined {\n if (parser) {\n if ('parse' in parser) {\n return parser.parse.bind(parser);\n }\n return parser;\n }\n return undefined;\n}\n\n/**\n * @deprecated Use {@linkcode defineQuery} instead.\n */\nexport function syncedQuery<\n TName extends string,\n TArg extends ReadonlyJSONValue[],\n TReturnQuery extends AnyQuery,\n>(\n name: TName,\n parser: ParseFn<TArg> | HasParseFn<TArg> | undefined,\n fn: QueryFn<unknown, false, TArg, TReturnQuery>,\n): SyncedQuery<TName, unknown, false, TArg, TReturnQuery> {\n const impl = syncedQueryImpl(name, fn, false);\n // oxlint-disable-next-line no-explicit-any\n const ret: any = (...args: TArg) => impl(undefined, args);\n ret.queryName = name;\n ret.parse = normalizeParser(parser);\n ret.takesContext = false;\n return ret;\n}\n\n/**\n * @deprecated Use {@linkcode defineQuery} instead.\n */\nexport function syncedQueryWithContext<\n TName extends string,\n TContext,\n TArg extends ReadonlyJSONValue[],\n TReturnQuery extends AnyQuery,\n>(\n name: TName,\n parser: ParseFn<TArg> | HasParseFn<TArg> | undefined,\n fn: QueryFn<TContext, true, TArg, TReturnQuery>,\n): SyncedQuery<TName, TContext, true, TArg, TReturnQuery> {\n const impl = syncedQueryImpl(name, fn, true);\n // oxlint-disable-next-line no-explicit-any\n const ret: any = (context: TContext, ...args: TArg) => impl(context, args);\n ret.queryName = name;\n ret.parse = normalizeParser(parser);\n ret.takesContext = true;\n return ret;\n}\n\n/** @deprecated */\nfunction syncedQueryImpl<\n TName extends string,\n TContext,\n TArg extends ReadonlyJSONValue[],\n // oxlint-disable-next-line no-explicit-any\n>(name: TName, fn: any, takesContext: boolean) {\n return (context: TContext, args: TArg) => {\n const q = takesContext ? fn(context, ...args) : fn(...args);\n return asQueryInternals(q).nameAndArgs(name, args);\n };\n}\n\n/** @deprecated */\n\n// oxlint-disable-next-line no-explicit-any\ntype AnySyncedQuery = SyncedQuery<any, any, any, any, any>;\n\n/** @deprecated */\nexport function withValidation<F extends AnySyncedQuery>(\n fn: F,\n // oxlint-disable-next-line no-explicit-any\n): F extends SyncedQuery<infer N, infer C, any, any, infer R>\n ? SyncedQuery<N, C, true, ReadonlyJSONValue[], R>\n : F {\n // If we have a parse function this is a SyncedQuery\n if ('parse' in fn) {\n const {parse} = fn;\n if (!parse) {\n throw new Error('ret does not have a parse function defined');\n }\n // oxlint-disable-next-line no-explicit-any\n const ret: any = (context: unknown, ...args: unknown[]) => {\n let parsed;\n try {\n parsed = parse(args);\n } catch (error) {\n throw new QueryParseError({cause: error});\n }\n // oxlint-disable-next-line no-explicit-any\n return fn.takesContext ? fn(context, ...parsed) : (fn as any)(...parsed);\n };\n ret.queryName = fn.queryName;\n ret.parse = fn.parse;\n ret.takesContext = true;\n\n return ret;\n }\n\n // If we don't have a parse function, return the function as-is\n // (this shouldn't happen in practice)\n // oxlint-disable-next-line no-explicit-any\n return fn as any;\n}\n\n/** @deprecated */\nexport type ParseFn<T extends ReadonlyJSONValue[]> = (args: unknown[]) => T;\n\n/** @deprecated */\nexport type HasParseFn<T extends ReadonlyJSONValue[]> = {\n parse: ParseFn<T>;\n};\n\n/** @deprecated */\nexport type Parser<T extends ReadonlyJSONValue[]> = ParseFn<T> | HasParseFn<T>;\n\nexport type CustomQueryID = {\n name: string;\n args: ReadonlyArray<ReadonlyJSONValue>;\n};\n"],"mappings":";;;;AA4BA,SAAS,gBACP,QACwB;CACxB,IAAI,QAAQ;EACV,IAAI,WAAW,QACb,OAAO,OAAO,MAAM,KAAK,MAAM;EAEjC,OAAO;CACT;AAEF;;;;AAKA,SAAgB,YAKd,MACA,QACA,IACwD;CACxD,MAAM,OAAO,gBAAgB,MAAM,IAAI,KAAK;CAE5C,MAAM,OAAY,GAAG,SAAe,KAAK,KAAA,GAAW,IAAI;CACxD,IAAI,YAAY;CAChB,IAAI,QAAQ,gBAAgB,MAAM;CAClC,IAAI,eAAe;CACnB,OAAO;AACT;;;;AAKA,SAAgB,uBAMd,MACA,QACA,IACwD;CACxD,MAAM,OAAO,gBAAgB,MAAM,IAAI,IAAI;CAE3C,MAAM,OAAY,SAAmB,GAAG,SAAe,KAAK,SAAS,IAAI;CACzE,IAAI,YAAY;CAChB,IAAI,QAAQ,gBAAgB,MAAM;CAClC,IAAI,eAAe;CACnB,OAAO;AACT;;AAGA,SAAS,gBAKP,MAAa,IAAS,cAAuB;CAC7C,QAAQ,SAAmB,SAAe;EAExC,OAAO,iBADG,eAAe,GAAG,SAAS,GAAG,IAAI,IAAI,GAAG,GAAG,IAAI,CACjC,EAAE,YAAY,MAAM,IAAI;CACnD;AACF;;AAQA,SAAgB,eACd,IAII;CAEJ,IAAI,WAAW,IAAI;EACjB,MAAM,EAAC,UAAS;EAChB,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,4CAA4C;EAG9D,MAAM,OAAY,SAAkB,GAAG,SAAoB;GACzD,IAAI;GACJ,IAAI;IACF,SAAS,MAAM,IAAI;GACrB,SAAS,OAAO;IACd,MAAM,IAAI,gBAAgB,EAAC,OAAO,MAAK,CAAC;GAC1C;GAEA,OAAO,GAAG,eAAe,GAAG,SAAS,GAAG,MAAM,IAAK,GAAW,GAAG,MAAM;EACzE;EACA,IAAI,YAAY,GAAG;EACnB,IAAI,QAAQ,GAAG;EACf,IAAI,eAAe;EAEnB,OAAO;CACT;CAKA,OAAO;AACT"}
1
+ {"version":3,"file":"named.js","names":[],"sources":["../../../../../zql/src/query/named.ts"],"sourcesContent":["import type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {QueryParseError} from './error.ts';\nimport {asQueryInternals} from './query-internals.ts';\nimport {type AnyQuery} from './query.ts';\n\n/** @deprecated */\nexport type QueryFn<\n TContext,\n TTakesContext extends boolean,\n TArg extends ReadonlyJSONValue[],\n TReturnQuery extends AnyQuery,\n> = TTakesContext extends false\n ? {(...args: TArg): TReturnQuery}\n : {(context: TContext, ...args: TArg): TReturnQuery};\n\n/** @deprecated */\nexport type SyncedQuery<\n TName extends string,\n TContext,\n TTakesContext extends boolean,\n TArg extends ReadonlyJSONValue[],\n TReturnQuery extends AnyQuery,\n> = QueryFn<TContext, TTakesContext, TArg, TReturnQuery> & {\n queryName: TName;\n parse: ParseFn<TArg> | undefined;\n takesContext: TTakesContext;\n};\n\nfunction normalizeParser<T extends ReadonlyJSONValue[]>(\n parser: ParseFn<T> | HasParseFn<T> | undefined,\n): ParseFn<T> | undefined {\n if (parser) {\n if ('parse' in parser) {\n return parser.parse.bind(parser);\n }\n return parser;\n }\n return undefined;\n}\n\n/**\n * @deprecated Use {@link defineQuery} instead.\n */\nexport function syncedQuery<\n TName extends string,\n TArg extends ReadonlyJSONValue[],\n TReturnQuery extends AnyQuery,\n>(\n name: TName,\n parser: ParseFn<TArg> | HasParseFn<TArg> | undefined,\n fn: QueryFn<unknown, false, TArg, TReturnQuery>,\n): SyncedQuery<TName, unknown, false, TArg, TReturnQuery> {\n const impl = syncedQueryImpl(name, fn, false);\n // oxlint-disable-next-line no-explicit-any\n const ret: any = (...args: TArg) => impl(undefined, args);\n ret.queryName = name;\n ret.parse = normalizeParser(parser);\n ret.takesContext = false;\n return ret;\n}\n\n/**\n * @deprecated Use {@link defineQuery} instead.\n */\nexport function syncedQueryWithContext<\n TName extends string,\n TContext,\n TArg extends ReadonlyJSONValue[],\n TReturnQuery extends AnyQuery,\n>(\n name: TName,\n parser: ParseFn<TArg> | HasParseFn<TArg> | undefined,\n fn: QueryFn<TContext, true, TArg, TReturnQuery>,\n): SyncedQuery<TName, TContext, true, TArg, TReturnQuery> {\n const impl = syncedQueryImpl(name, fn, true);\n // oxlint-disable-next-line no-explicit-any\n const ret: any = (context: TContext, ...args: TArg) => impl(context, args);\n ret.queryName = name;\n ret.parse = normalizeParser(parser);\n ret.takesContext = true;\n return ret;\n}\n\n/** @deprecated */\nfunction syncedQueryImpl<\n TName extends string,\n TContext,\n TArg extends ReadonlyJSONValue[],\n // oxlint-disable-next-line no-explicit-any\n>(name: TName, fn: any, takesContext: boolean) {\n return (context: TContext, args: TArg) => {\n const q = takesContext ? fn(context, ...args) : fn(...args);\n return asQueryInternals(q).nameAndArgs(name, args);\n };\n}\n\n/** @deprecated */\n\n// oxlint-disable-next-line no-explicit-any\ntype AnySyncedQuery = SyncedQuery<any, any, any, any, any>;\n\n/** @deprecated */\nexport function withValidation<F extends AnySyncedQuery>(\n fn: F,\n // oxlint-disable-next-line no-explicit-any\n): F extends SyncedQuery<infer N, infer C, any, any, infer R>\n ? SyncedQuery<N, C, true, ReadonlyJSONValue[], R>\n : F {\n // If we have a parse function this is a SyncedQuery\n if ('parse' in fn) {\n const {parse} = fn;\n if (!parse) {\n throw new Error('ret does not have a parse function defined');\n }\n // oxlint-disable-next-line no-explicit-any\n const ret: any = (context: unknown, ...args: unknown[]) => {\n let parsed;\n try {\n parsed = parse(args);\n } catch (error) {\n throw new QueryParseError({cause: error});\n }\n // oxlint-disable-next-line no-explicit-any\n return fn.takesContext ? fn(context, ...parsed) : (fn as any)(...parsed);\n };\n ret.queryName = fn.queryName;\n ret.parse = fn.parse;\n ret.takesContext = true;\n\n return ret;\n }\n\n // If we don't have a parse function, return the function as-is\n // (this shouldn't happen in practice)\n // oxlint-disable-next-line no-explicit-any\n return fn as any;\n}\n\n/** @deprecated */\nexport type ParseFn<T extends ReadonlyJSONValue[]> = (args: unknown[]) => T;\n\n/** @deprecated */\nexport type HasParseFn<T extends ReadonlyJSONValue[]> = {\n parse: ParseFn<T>;\n};\n\n/** @deprecated */\nexport type Parser<T extends ReadonlyJSONValue[]> = ParseFn<T> | HasParseFn<T>;\n\nexport type CustomQueryID = {\n name: string;\n args: ReadonlyArray<ReadonlyJSONValue>;\n};\n"],"mappings":";;;;AA4BA,SAAS,gBACP,QACwB;CACxB,IAAI,QAAQ;EACV,IAAI,WAAW,QACb,OAAO,OAAO,MAAM,KAAK,MAAM;EAEjC,OAAO;CACT;AAEF;;;;AAKA,SAAgB,YAKd,MACA,QACA,IACwD;CACxD,MAAM,OAAO,gBAAgB,MAAM,IAAI,KAAK;CAE5C,MAAM,OAAY,GAAG,SAAe,KAAK,KAAA,GAAW,IAAI;CACxD,IAAI,YAAY;CAChB,IAAI,QAAQ,gBAAgB,MAAM;CAClC,IAAI,eAAe;CACnB,OAAO;AACT;;;;AAKA,SAAgB,uBAMd,MACA,QACA,IACwD;CACxD,MAAM,OAAO,gBAAgB,MAAM,IAAI,IAAI;CAE3C,MAAM,OAAY,SAAmB,GAAG,SAAe,KAAK,SAAS,IAAI;CACzE,IAAI,YAAY;CAChB,IAAI,QAAQ,gBAAgB,MAAM;CAClC,IAAI,eAAe;CACnB,OAAO;AACT;;AAGA,SAAS,gBAKP,MAAa,IAAS,cAAuB;CAC7C,QAAQ,SAAmB,SAAe;EAExC,OAAO,iBADG,eAAe,GAAG,SAAS,GAAG,IAAI,IAAI,GAAG,GAAG,IAAI,CACjC,EAAE,YAAY,MAAM,IAAI;CACnD;AACF;;AAQA,SAAgB,eACd,IAII;CAEJ,IAAI,WAAW,IAAI;EACjB,MAAM,EAAC,UAAS;EAChB,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,4CAA4C;EAG9D,MAAM,OAAY,SAAkB,GAAG,SAAoB;GACzD,IAAI;GACJ,IAAI;IACF,SAAS,MAAM,IAAI;GACrB,SAAS,OAAO;IACd,MAAM,IAAI,gBAAgB,EAAC,OAAO,MAAK,CAAC;GAC1C;GAEA,OAAO,GAAG,eAAe,GAAG,SAAS,GAAG,MAAM,IAAK,GAAW,GAAG,MAAM;EACzE;EACA,IAAI,YAAY,GAAG;EACnB,IAAI,QAAQ,GAAG;EACf,IAAI,eAAe;EAEnB,OAAO;CACT;CAKA,OAAO;AACT"}
@@ -102,7 +102,7 @@ var QueryImpl = class {
102
102
  }
103
103
  /**
104
104
  * Interns a transition whose key space is finite and schema-derived; see
105
- * {@linkcode Transitions.storeBounded}. Used for the base sub-query handed to
105
+ * {@link Transitions.storeBounded}. Used for the base sub-query handed to
106
106
  * a `related`/`exists` callback, which is determined entirely by the
107
107
  * relationship name.
108
108
  */
@@ -531,7 +531,7 @@ function tri(b) {
531
531
  }
532
532
  /**
533
533
  * An exact key for a whole condition tree, or `undefined` for a shape we cannot
534
- * encode (which falls back to {@linkcode treeKey} plus a delta).
534
+ * encode (which falls back to {@link treeKey} plus a delta).
535
535
  *
536
536
  * Everything variable-length is length-prefixed, so distinct trees cannot
537
537
  * produce the same string and the key needs no `deepEqual` to back it up. That
@@ -562,7 +562,7 @@ function condKey(cond) {
562
562
  }
563
563
  }
564
564
  /**
565
- * A coarse bucket key for the conditions {@linkcode condKey} cannot encode --
565
+ * A coarse bucket key for the conditions {@link condKey} cannot encode --
566
566
  * a two-hop `exists`, whose junction AST is built inline and so has no identity
567
567
  * of its own. Reads only the top of the tree, so it is cheap; the delta tells
568
568
  * apart what shares it.
@@ -1 +1 @@
1
- {"version":3,"file":"query-impl.js","names":["#schema","#tableName","#ast","#system","#currentJunction","#newQuery","#transitions","#record","#parent","#derive","#hash","#canonicalize","#byHash","#sameAs","#deriveBounded","#expressionBuilder","#exists"],"sources":["../../../../../zql/src/query/query-impl.ts"],"sourcesContent":["// oxlint-disable no-explicit-any\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {\n deepEqual,\n type ReadonlyJSONObject,\n type ReadonlyJSONValue,\n} from '../../../shared/src/json.ts';\nimport {getOrInsertComputed, newMap} from '../../../shared/src/map.ts';\nimport {\n type AST,\n type CompoundKey,\n type Condition,\n type NormalizedAST,\n type Parameter,\n type LiteralValue,\n type SimpleCondition,\n type SimpleOperator,\n type System,\n insertRelated,\n normalizeAST,\n normalizeCondition,\n normalizedRelated,\n SUBQ_PREFIX,\n tableAST,\n} from '../../../zero-protocol/src/ast.ts';\nimport {hashOfQueryInternals} from '../../../zero-protocol/src/query-hash-visitor.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {NotImplementedError} from '../error.ts';\nimport {defaultFormat} from '../ivm/default-format.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport {\n type ExpressionFactory,\n ExpressionBuilder,\n and,\n cmp,\n simplifyCondition,\n} from './expression.ts';\nimport type {CustomQueryID} from './named.ts';\nimport {type QueryInternals, queryInternalsTag} from './query-internals.ts';\nimport {\n HashIndex,\n Transitions,\n type Delta,\n type TransitionValue,\n} from './query-transitions.ts';\nimport type {\n AnyQuery,\n ExistsOptions,\n GetFilterType,\n HumanReadable,\n PreloadOptions,\n PullRow,\n Query,\n RunOptions,\n} from './query.ts';\nimport type {TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\ntype GetFilterTypeAny = GetFilterType<any, any, any>;\n\ntype NewQueryFunction<TSchema extends Schema> = <\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n this: unknown,\n tableName: TTable,\n ast: NormalizedAST,\n format: Format,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n) => QueryImpl<TTable, TSchema, TReturn>;\n\nexport function newQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n>(schema: TSchema, table: TTable): Query<TTable, TSchema> {\n return newQueryInternal(\n schema,\n table,\n tableAST(table),\n defaultFormat,\n 'client',\n );\n}\n\nexport function newQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>(\n schema: TSchema,\n tableName: TTable,\n ast: AST,\n format: Format,\n system: System,\n): QueryImpl<TTable, TSchema, TReturn> {\n // This is the entry point for ASTs that were not built by QueryImpl, so\n // normalize it here to establish the invariant that #ast is normalized.\n return newQueryInternal(schema, tableName, normalizeAST(ast), format, system);\n}\n\n/**\n * Root queries are interned per schema so that two `createBuilder(schema)` calls\n * hand out the same starting point, and therefore share the whole transition\n * tree below it. Only cleared entries accumulate here, at most one per\n * system/table pair, so no sweeping is needed.\n */\nconst rootsBySchema = new WeakMap<\n Schema,\n Map<string, WeakRef<QueryImpl<any, any, any>>>\n>();\n\n/**\n * Whether this is the AST `tableAST(tableName)` produces -- the whole table,\n * nothing else. A normalized AST carries every field, so this cannot be a key\n * count; each one has to be checked.\n */\nfunction isRootAST(ast: NormalizedAST, tableName: string): boolean {\n return (\n ast.table === tableName &&\n ast.schema === undefined &&\n ast.alias === undefined &&\n ast.where === undefined &&\n ast.related === undefined &&\n ast.start === undefined &&\n ast.limit === undefined &&\n ast.orderBy === undefined\n );\n}\n\nfunction newQueryInternal<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>(\n schema: TSchema,\n tableName: TTable,\n ast: NormalizedAST,\n format: Format,\n system: System,\n): QueryImpl<TTable, TSchema, TReturn> {\n // Callers that hand in a pre-built AST -- benchmarks and the integration-test\n // harnesses -- are not roots and are not interned.\n const interned = format === defaultFormat && isRootAST(ast, tableName);\n const key = `${system}:${tableName}`;\n let roots: Map<string, WeakRef<QueryImpl<any, any, any>>> | undefined;\n\n if (interned) {\n roots = rootsBySchema.get(schema);\n const existing = roots?.get(key)?.deref();\n if (existing) {\n return existing as QueryImpl<TTable, TSchema, TReturn>;\n }\n }\n\n const inner: NewQueryFunction<TSchema> = (\n tableName,\n ast,\n format,\n customQueryID,\n currentJunction,\n ) =>\n new QueryImpl(\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n inner,\n );\n\n const created = inner<TTable, TReturn>(\n tableName,\n ast,\n format,\n undefined,\n undefined,\n );\n\n if (interned) {\n if (!roots) {\n roots = new Map();\n rootsBySchema.set(schema, roots);\n }\n roots.set(key, new WeakRef(created));\n }\n\n return created;\n}\n\n/**\n * The AST of a QueryImpl is always normalized. Each step builds its AST in\n * normalized form rather than normalizing afterwards: a normalized AST has\n * every field, so spreading one and replacing a field keeps the field order\n * intact, and only the field a step actually changes needs normalizing (the\n * conditions of a `where`, the position of a new `related`). The ASTs that\n * come in from the outside are normalized by {@link newQueryImpl}, which is\n * what the `NormalizedAST` of the AST it holds stands for.\n */\nexport class QueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>\n implements\n Query<TTable, TSchema, TReturn>,\n QueryInternals<TTable, TSchema, TReturn>\n{\n readonly [queryInternalsTag] = true;\n\n readonly #schema: TSchema;\n readonly #tableName: TTable;\n readonly #ast: NormalizedAST;\n readonly format: Format;\n #hash: string = '';\n readonly #system: System;\n readonly #currentJunction: string | undefined;\n readonly customQueryID: CustomQueryID | undefined;\n readonly #newQuery: NewQueryFunction<TSchema>;\n\n /**\n * The query this one was derived from, held *strongly*, and the queries\n * derived from this one, held *weakly*. This is the arrangement V8 uses for\n * hidden-class transitions, and it is what makes interning stable: as long as\n * a query is reachable its whole ancestor spine is too, so re-deriving it from\n * the root yields the same instance. See `query-transitions.ts`.\n */\n #parent: QueryImpl<any, any, any> | undefined;\n #transitions: Transitions<QueryImpl<any, any, any>> | undefined;\n\n /**\n * The second level of interning, keyed by hash; see `HashIndex`. Set on the\n * root only, which is what scopes it to one schema and one delegate.\n */\n #byHash: HashIndex<QueryImpl<any, any, any>> | undefined;\n\n /**\n * Memoized because a query is interned: the same node serves every rebuild of\n * a chain, so building this once rather than per `where(fn)` call takes the\n * whole thing -- the builder and the bound `#exists` -- off the repeat path.\n */\n #expressionBuilder: ExpressionBuilder<TTable, TSchema> | undefined;\n\n constructor(\n schema: TSchema,\n tableName: TTable,\n ast: NormalizedAST,\n format: Format,\n system: System,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n newQuery: NewQueryFunction<TSchema>,\n ) {\n this.#schema = schema;\n this.#tableName = tableName;\n this.#ast = ast;\n this.format = format;\n this.#system = system;\n this.#currentJunction = currentJunction;\n this.customQueryID = customQueryID;\n this.#newQuery = newQuery;\n }\n\n /**\n * Interns a transition whose key space is finite and schema-derived; see\n * {@linkcode Transitions.storeBounded}. Used for the base sub-query handed to\n * a `related`/`exists` callback, which is determined entirely by the\n * relationship name.\n */\n #deriveBounded<T>(key: string, build: () => T): T {\n const existing = this.#transitions?.lookupBounded(key);\n if (existing !== undefined) {\n return existing as T;\n }\n return this.#record(key, undefined, undefined, build(), true);\n }\n\n /**\n * Interns the result of applying a builder operation to this query.\n *\n * `key` names the operation and `value` carries its varying argument, kept\n * apart so the key stays a string V8 has already hashed. When the two do not\n * settle it, `delta` carries the rest and is compared with `deepEqual`. Only\n * the delta is compared, never the whole AST: this query is already canonical,\n * so two of its children are equal exactly when the operations that produced\n * them are.\n *\n * `T` is deliberately unconstrained so that the contextual return type at each\n * call site still drives `#newQuery`'s inference, exactly as it did when the\n * call sites returned `this.#newQuery(...)` directly.\n */\n #derive<T>(\n key: string,\n value: TransitionValue,\n delta: Delta,\n build: () => T,\n ): T {\n const existing = this.#transitions?.lookup(key, value, delta);\n if (existing !== undefined) {\n return existing as T;\n }\n return this.#record(key, value, delta, build(), false);\n }\n\n #record<T>(\n key: string,\n value: TransitionValue,\n delta: Delta,\n created: T,\n bounded: boolean,\n ): T {\n const q = created as unknown as QueryImpl<any, any, any>;\n q.#parent = this;\n const transitions = (this.#transitions ??= new Transitions());\n if (bounded) {\n transitions.storeBounded(key, q);\n } else {\n transitions.store(key, value, delta, q);\n }\n return created;\n }\n\n run(_options?: RunOptions): Promise<HumanReadable<TReturn>> {\n throwQueryNotRunnable();\n }\n\n preload(_options?: PreloadOptions): {\n cleanup: () => void;\n complete: Promise<void>;\n cached: Promise<void>;\n } {\n throwQueryNotRunnable();\n }\n\n materialize(ttl?: TTL): TypedView<HumanReadable<TReturn>>;\n materialize<T>(\n factory: ViewFactory<TTable, TSchema, TReturn, T>,\n ttl?: TTL,\n ): T;\n materialize<T>(\n _factoryOrTTL?: ViewFactory<TTable, TSchema, TReturn, T> | TTL,\n _ttl?: TTL,\n ): T | TypedView<HumanReadable<TReturn>> {\n throwQueryNotRunnable();\n }\n\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TTable, TSchema, TReturn> {\n return this.#derive('nameAndArgs', name, args, () =>\n this.#newQuery(\n this.#tableName,\n this.#ast,\n this.format,\n {\n name,\n args,\n },\n this.#currentJunction,\n ),\n );\n }\n\n hash(): string {\n if (!this.#hash) {\n this.#hash = hashOfQueryInternals(\n this.#ast,\n this.format,\n this.#system,\n this.#currentJunction,\n this.customQueryID?.name,\n this.customQueryID?.args,\n );\n this.#canonicalize();\n }\n return this.#hash;\n }\n\n /**\n * Folds this query into its root's hash index, now that its hash is known.\n *\n * If an equal query is already indexed, the transition that produced this\n * one is re-pointed at it, so the next rebuild along this path yields that\n * instance rather than a second copy. This query itself is left alone: its\n * identity has already been handed out. Content is verified with `#sameAs`\n * before anything is redirected, so a hash collision costs nothing worse\n * than a missed unification.\n */\n #canonicalize(): void {\n const parent = this.#parent;\n if (parent === undefined) {\n // A root has no path to redirect and is its own canonical form.\n return;\n }\n let root = parent;\n while (root.#parent !== undefined) {\n root = root.#parent;\n }\n const index = (root.#byHash ??= new HashIndex());\n const existing = index.get(this.#hash);\n if (existing === undefined) {\n index.set(this.#hash, this);\n } else if (existing !== this && this.#sameAs(existing)) {\n parent.#transitions?.replace(this, existing);\n }\n }\n\n /**\n * Whether `other` is interchangeable with this query: everything `hash()`\n * covers, compared structurally. Schema and delegate are not compared. Both\n * are fixed by the root, and this only ever compares queries under one root.\n */\n #sameAs(other: QueryImpl<any, any, any>): boolean {\n return (\n this.#system === other.#system &&\n this.#currentJunction === other.#currentJunction &&\n this.customQueryID?.name === other.customQueryID?.name &&\n deepEqual(this.customQueryID?.args, other.customQueryID?.args) &&\n deepEqual(this.format, other.format) &&\n deepEqual(this.#ast, other.#ast)\n );\n }\n\n one(): Query<TTable, TSchema, TReturn | undefined> {\n return this.#derive('one', undefined, undefined, () =>\n this.#newQuery(\n this.#tableName,\n {...this.#ast, limit: 1},\n {\n ...this.format,\n singular: true,\n },\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n whereExists(\n relationship: string,\n cbOrOptions?: ((q: AnyQuery) => AnyQuery) | ExistsOptions,\n options?: ExistsOptions,\n ): Query<TTable, TSchema, TReturn> {\n const cb = typeof cbOrOptions === 'function' ? cbOrOptions : undefined;\n const opts = typeof cbOrOptions === 'function' ? options : cbOrOptions;\n return this.where(({exists}) => exists(relationship, cb, opts)) as Query<\n TTable,\n TSchema,\n TReturn\n >;\n }\n\n related(\n relationship: string,\n cb?: (q: AnyQuery) => AnyQuery,\n ): Query<TTable, TSchema, any> {\n if (relationship.startsWith(SUBQ_PREFIX)) {\n throw new Error(\n `Relationship names may not start with \"${SUBQ_PREFIX}\". That is a reserved prefix.`,\n );\n }\n cb = cb ?? (q => q);\n\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n if (isOneHop(related)) {\n const {destSchema, destField, sourceField, cardinality} = related[0];\n // Intern the base handed to the callback too. A deterministic callback\n // then walks the same interned chain and hands back the *same* sub-query,\n // which makes the comparison below a pointer compare.\n const q: AnyQuery = this.#deriveBounded(\n `relatedBase:${relationship}`,\n () =>\n this.#newQuery(\n destSchema,\n tableAST(destSchema, relationship),\n {\n relationships: {},\n singular: cardinality === 'one',\n },\n this.customQueryID,\n undefined,\n ),\n ) as AnyQuery;\n // Intentionally not setting to `one` as it is a perf degradation\n // and the user should not be making the mistake of setting cardinality to\n // `one` when it is actually not.\n // if (cardinality === 'one') {\n // q = q.one();\n // }\n const subQuery = asQueryImpl(cb(q));\n assert(\n isCompoundKey(sourceField),\n 'The source of a relationship must specify at last 1 field',\n );\n assert(\n isCompoundKey(destField),\n 'The destination of a relationship must specify at last 1 field',\n );\n assert(\n sourceField.length === destField.length,\n 'The source and destination of a relationship must have the same number of fields',\n );\n\n // Keyed by the sub-query's identity. Each query owns its AST object, so\n // this distinguishes even `q.one()` from `q.limit(1)`, whose ASTs are\n // structurally equal but whose formats differ. Comparing them as a delta\n // instead would put every sibling under one key and scan.\n return this.#derive(\n relatedKey(relationship),\n astID(subQuery.#ast),\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: insertRelated(this.#ast.related, {\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n system: this.#system,\n }),\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: subQuery.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ),\n ) as AnyQuery;\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const sq = asQueryImpl(\n cb(\n this.#deriveBounded(`relatedBase:${relationship}`, () =>\n this.#newQuery(\n destSchema,\n tableAST(destSchema, relationship),\n {\n relationships: {},\n singular: secondRelation.cardinality === 'one',\n },\n this.customQueryID,\n relationship,\n ),\n ) as AnyQuery,\n ),\n );\n\n // Bound to consts so the `isCompoundKey` narrowing survives into the\n // closure below; TypeScript drops narrowing of property accesses there.\n const {sourceField: firstSource, destField: firstDest} = firstRelation;\n const {sourceField: secondSource, destField: secondDest} = secondRelation;\n assert(isCompoundKey(firstSource), 'Invalid relationship');\n assert(isCompoundKey(firstDest), 'Invalid relationship');\n assert(isCompoundKey(secondSource), 'Invalid relationship');\n assert(isCompoundKey(secondDest), 'Invalid relationship');\n\n return this.#derive(\n relatedKey(relationship),\n astID(sq.#ast),\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: insertRelated(this.#ast.related, {\n correlation: {\n parentField: firstSource,\n childField: firstDest,\n },\n hidden: true,\n subquery: {\n ...tableAST(junctionSchema, relationship),\n // A single subquery is sorted.\n related: [\n normalizedRelated({\n correlation: {\n parentField: secondSource,\n childField: secondDest,\n },\n subquery: sq.#ast,\n system: this.#system,\n }),\n ],\n },\n system: this.#system,\n }),\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: sq.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ),\n ) as AnyQuery;\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n }\n\n // The declared return is the *bottom* of the pinned dimension, which is\n // assignable to every `where` overload's declared return. The overloads\n // refine `TPinned` for callers only; a single non-generic implementation\n // signature cannot express that refinement.\n where(\n fieldOrExpressionFactory: string | ExpressionFactory<TTable, TSchema>,\n opOrValue?: SimpleOperator | GetFilterTypeAny | Parameter,\n value?: GetFilterTypeAny | Parameter,\n ): Query<TTable, TSchema, TReturn, any> {\n let cond: Condition;\n\n if (typeof fieldOrExpressionFactory === 'function') {\n cond = fieldOrExpressionFactory(this.expressionBuilder());\n } else {\n assert(arguments.length >= 2, 'Invalid condition. Too few arguments.');\n // Distinguish between 2-arg form (field, value) and 3-arg form (field, op, value)\n // using arguments.length to allow explicit undefined in 3-arg form.\n const twoArg = arguments.length === 2;\n const op = (twoArg ? '=' : opOrValue) as SimpleOperator;\n const raw = twoArg ? opOrValue : value;\n\n // Comparing a column to a primitive is by far the most common thing anyone\n // does with a query, and the transition it names is fully determined by\n // (column, op, value) -- so check for it before building anything. On a hit\n // this returns without allocating the `Condition` at all. Objects are\n // excluded, which covers both parameter references and `IN` arrays; `cmp`\n // maps a missing value to null, so this must too.\n if (raw === null || typeof raw !== 'object') {\n const hit = this.#transitions?.lookup(\n whereKey(fieldOrExpressionFactory, op),\n (raw ?? null) as TransitionValue,\n undefined,\n );\n if (hit !== undefined) {\n return hit as unknown as Query<TTable, TSchema, TReturn, any>;\n }\n }\n\n cond = twoArg\n ? cmp(fieldOrExpressionFactory, opOrValue)\n : cmp(fieldOrExpressionFactory, opOrValue, value);\n }\n\n // The delta is the condition as built here, *before* it is merged with the\n // existing where and normalized. Both steps are deterministic and the\n // existing where is fixed by this query, so an equal `cond` always produces\n // an equal result.\n //\n // A simple comparison against a column splits cleanly: the column and\n // operator come from a small fixed set and give a memoized, stable key,\n // while the compared value -- the part that varies per call -- is handed\n // through as the transition value and never concatenated into a string.\n let key: string;\n let tValue: TransitionValue;\n let delta: Delta = cond;\n if (cond.type === 'simple' && cond.left.type === 'column') {\n key = whereKey(cond.left.name, cond.op);\n const right = cond.right;\n tValue =\n right.type === 'literal' && isPrimitive(right.value)\n ? right.value\n : rightTag(right);\n delta = undefined;\n } else {\n // A sub-query an `exists` correlates to is itself interned, so its\n // identity settles that part of the tree without walking it.\n const exact = condKey(cond);\n if (exact === undefined) {\n key = treeKey(cond);\n } else {\n key = 'where:tree';\n tValue = exact;\n delta = undefined;\n }\n }\n\n return this.#derive(key, tValue, delta, () => {\n const existingWhere = this.#ast.where;\n const merged = existingWhere ? and(existingWhere, cond) : cond;\n return this.#newQuery(\n this.#tableName,\n {...this.#ast, where: normalizeCondition(simplifyCondition(merged))},\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n }) as unknown as Query<TTable, TSchema, TReturn, any>;\n }\n\n start(\n row: Partial<Record<string, ReadonlyJSONValue | undefined>>,\n opts?: {inclusive: boolean},\n ): Query<TTable, TSchema, TReturn> {\n // The row is an object, so it is encoded to a string to serve as the\n // lookup key. Property order is part of that string.\n return this.#derive(\n opts?.inclusive ? 'start:inclusive' : 'start:exclusive',\n valueTag(row as ReadonlyJSONValue),\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n start: {\n row,\n exclusive: !opts?.inclusive,\n },\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n limit(limit: number): Query<TTable, TSchema, TReturn> {\n if (limit < 0) {\n throw new Error('Limit must be non-negative');\n }\n if ((limit | 0) !== limit) {\n throw new Error('Limit must be an integer');\n }\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Limit is not supported in junction relationships yet. Junction relationship being limited: ' +\n this.#currentJunction,\n );\n }\n\n return this.#derive('limit', limit, undefined, () =>\n this.#newQuery(\n this.#tableName,\n {...this.#ast, limit},\n this.format,\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n orderBy<TSelector extends keyof TSchema['tables'][TTable]['columns']>(\n field: TSelector,\n direction: 'asc' | 'desc',\n ): Query<TTable, TSchema, TReturn> {\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Order by is not supported in junction relationships yet. Junction relationship being ordered: ' +\n this.#currentJunction,\n );\n }\n return this.#derive(\n direction === 'asc' ? 'orderBy:asc' : 'orderBy:desc',\n field as string,\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n orderBy: [\n ...(this.#ast.orderBy ?? []),\n [field as string, direction],\n ],\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n #exists(\n relationship: string,\n cb: ((query: AnyQuery) => AnyQuery) | undefined,\n options?: ExistsOptions,\n ): Condition {\n cb = cb ?? (q => q);\n const flip = options?.flip;\n const scalar = options?.scalar;\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n\n if (isOneHop(related)) {\n const {destSchema: destTableName, sourceField, destField} = related[0];\n assert(isCompoundKey(sourceField), 'Invalid relationship');\n assert(isCompoundKey(destField), 'Invalid relationship');\n\n const subQuery = asQueryImpl(\n cb(\n this.#deriveBounded(`existsBase:${relationship}`, () =>\n this.#newQuery(\n destTableName,\n tableAST(destTableName, `${SUBQ_PREFIX}${relationship}`),\n defaultFormat,\n this.customQueryID,\n undefined,\n ),\n ) as AnyQuery,\n ),\n );\n // Give the sub-query's AST an id so the enclosing `where` can key on it\n // exactly rather than comparing the sub-tree.\n astID(subQuery.#ast);\n // Unlike the entries of `related`, the correlated subqueries of a\n // condition keep the order their fields are written in: normalization\n // does not reorder them either.\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n ...(scalar !== undefined ? {scalar} : {}),\n };\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const queryToDest = cb(\n this.#deriveBounded(`existsJunctionBase:${relationship}`, () =>\n this.#newQuery(\n destSchema,\n tableAST(destSchema, `${SUBQ_PREFIX}zhidden_${relationship}`),\n defaultFormat,\n this.customQueryID,\n relationship,\n ),\n ) as AnyQuery,\n );\n\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n subquery: {\n ...tableAST(junctionSchema, `${SUBQ_PREFIX}${relationship}`),\n // A single condition needs no flattening or sorting, but the node\n // itself still has to be rebuilt into the canonical field order.\n where: normalizeCondition({\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n subquery: asQueryImpl(queryToDest).#ast,\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n ...(scalar !== undefined ? {scalar} : {}),\n }),\n },\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n };\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n }\n\n get ast(): NormalizedAST {\n return this.#ast;\n }\n\n expressionBuilder(): ExpressionBuilder<TTable, TSchema> {\n // Built on demand rather than held as an eagerly initialized field: a field\n // would cost a closure on every query constructed, where this costs one only\n // for queries that actually use an expression factory.\n return (this.#expressionBuilder ??= new ExpressionBuilder<TTable, TSchema>(\n this.#exists.bind(this) as ConstructorParameters<\n typeof ExpressionBuilder<TTable, TSchema>\n >[0],\n ));\n }\n}\n\nexport function asQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n>(q: Query<TTable, TSchema, TReturn>): QueryImpl<TTable, TSchema, TReturn> {\n assert(q instanceof QueryImpl, 'Expected QueryImpl instance');\n return q;\n}\n\n/**\n * A stable id per query AST.\n *\n * Every `QueryImpl` allocates its own AST object, so these are one-to-one with\n * queries, and interning makes the object identity stable across rebuilds. That\n * lets a `related` or `exists` transition key on *which* sub-query it points at\n * rather than comparing the sub-tree.\n *\n * Assigned only where it is needed. A `WeakMap.set` costs on the order of a\n * hundred nanoseconds, so doing this for every query rather than for the few\n * that are sub-queries was one of the largest single costs of building a query\n * from cold. ASTs that never pass through here -- including the junction AST a\n * two-hop `exists` builds inline -- are absent, and fall back to a delta.\n */\nconst astIDs = new WeakMap<AST, number>();\nlet nextASTID = 0;\n\nconst newASTID = () => ++nextASTID;\n\nfunction astID(ast: AST): number {\n return getOrInsertComputed(astIDs, ast, newASTID);\n}\n\n/**\n * Memoized transition keys.\n *\n * A transition key must be a string V8 has already hashed, or the `Map` lookup\n * has to hash it from scratch -- measured at ~148ns against ~10ns, which dwarfs\n * everything else a lookup does. Both tables are keyed by schema-derived names,\n * so they are bounded by the schema.\n */\nconst whereKeys = new Map<string, Map<string, string>>();\n\nfunction whereKey(column: string, op: string): string {\n const byOp = getOrInsertComputed(whereKeys, column, newMap);\n return getOrInsertComputed(byOp, op, op => `where:${column}:${op}`);\n}\n\nconst relatedKeys = new Map<string, string>();\n\nconst newRelatedKey = (relationship: string) => `related:${relationship}`;\n\nfunction relatedKey(relationship: string): string {\n return getOrInsertComputed(relatedKeys, relationship, newRelatedKey);\n}\n\nfunction isPrimitive(v: LiteralValue): v is string | number | boolean | null {\n return v === null || typeof v !== 'object';\n}\n\n/**\n * Folds a JSON value into a self-delimiting token: a string is\n * length-prefixed, a number is terminated, an array or object is\n * count-prefixed and encodes its members recursively, and the rest are fixed\n * width. Tokens can therefore be concatenated into a key with no way for one\n * to run into the next, and the leading tag keeps `'1'` and `1` apart.\n *\n * Not `JSON.stringify`: it writes `Infinity`, `NaN` and `null` all as `null`,\n * and this token is trusted as exact, so a nested value that serialized like\n * another's would hand back a query with the wrong value in its AST. Numbers\n * are written the way `String` writes them, which keeps those apart. An\n * `undefined` property is skipped, as `deepEqual` would skip it; property\n * order is part of the encoding, so an object spelled in another order\n * interns separately.\n */\nfunction valueTag(v: ReadonlyJSONValue): string {\n switch (typeof v) {\n case 'string':\n return `:s${enc(v)}`;\n case 'number':\n return `:n${v};`;\n case 'boolean':\n return v ? ':t' : ':f';\n default: {\n if (v === null) {\n return ':z';\n }\n if (Array.isArray(v)) {\n let out = `:a${v.length}:`;\n for (const e of v) {\n out += valueTag(e);\n }\n return out;\n }\n // `Array.isArray` does not narrow a readonly array out of the union.\n const o = v as ReadonlyJSONObject;\n let body = '';\n let n = 0;\n for (const key in o) {\n const e = o[key];\n if (e !== undefined && Object.hasOwn(o, key)) {\n body += enc(key) + valueTag(e);\n n++;\n }\n }\n return `:o${n}:${body}`;\n }\n }\n}\n\n/**\n * Folds the right-hand side of a simple condition into a transition value, so\n * that the transition is exact and the lookup needs no comparison at all.\n *\n * Arrays (`IN`) and parameter references are encoded in full: that is one\n * pass over a small value, where leaving them in the delta would instead cost\n * a `deepEqual` over the whole condition for every sibling a lookup walks\n * past.\n */\nfunction rightTag(right: SimpleCondition['right']): string {\n if (right.type !== 'literal') {\n return `:p${valueTag(right as unknown as ReadonlyJSONValue)}`;\n }\n return valueTag(right.value);\n}\n\n/**\n * Length-prefixes a free-form string so it can be concatenated into a key\n * without a separator being ambiguous with the content.\n */\nfunction enc(s: string): string {\n return `${s.length}:${s}`;\n}\n\n/** Encodes an optional boolean without collapsing `undefined` into `false`. */\nfunction tri(b: boolean | undefined): string {\n return b === undefined ? '-' : b ? 't' : 'f';\n}\n\n/**\n * An exact key for a whole condition tree, or `undefined` for a shape we cannot\n * encode (which falls back to {@linkcode treeKey} plus a delta).\n *\n * Everything variable-length is length-prefixed, so distinct trees cannot\n * produce the same string and the key needs no `deepEqual` to back it up. That\n * matters because the alternative -- one coarse bucket per shape -- turns N\n * sibling conditions off the same parent into an N-deep scan of tree\n * comparisons, which measured far slower than not interning at all.\n */\nfunction condKey(cond: Condition): string | undefined {\n switch (cond.type) {\n case 'simple': {\n if (cond.left.type !== 'column') {\n return undefined;\n }\n return `S${enc(cond.left.name)}${enc(cond.op)}${rightTag(cond.right)}`;\n }\n case 'correlatedSubquery': {\n const id = astIDs.get(cond.related.subquery);\n return id === undefined\n ? undefined\n : `E${id}:${enc(cond.op)}${tri(cond.flip)}${tri(cond.scalar)}`;\n }\n case 'and':\n case 'or': {\n let out = `${cond.type === 'and' ? 'A' : 'O'}${cond.conditions.length}:`;\n for (const c of cond.conditions) {\n const k = condKey(c);\n if (k === undefined) {\n return undefined;\n }\n out += k;\n }\n return out;\n }\n default:\n return undefined;\n }\n}\n\n/**\n * A coarse bucket key for the conditions {@linkcode condKey} cannot encode --\n * a two-hop `exists`, whose junction AST is built inline and so has no identity\n * of its own. Reads only the top of the tree, so it is cheap; the delta tells\n * apart what shares it.\n */\nfunction treeKey(cond: Condition): string {\n switch (cond.type) {\n case 'correlatedSubquery':\n return `where:e:${cond.related.subquery.alias}:${cond.op}`;\n case 'and':\n case 'or':\n return `where:${cond.type}:${cond.conditions.length}`;\n default:\n return 'where:*';\n }\n}\n\nfunction throwQueryNotRunnable(): never {\n throw new Error('Query is not runnable');\n}\n\nfunction isCompoundKey(field: readonly string[]): field is CompoundKey {\n return Array.isArray(field) && field.length >= 1;\n}\n\nfunction isOneHop<T>(r: readonly T[]): r is readonly [T] {\n return r.length === 1;\n}\n\nfunction isTwoHop<T>(r: readonly T[]): r is readonly [T, T] {\n return r.length === 2;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"query-impl.js","names":["#schema","#tableName","#ast","#system","#currentJunction","#newQuery","#transitions","#record","#parent","#derive","#hash","#canonicalize","#byHash","#sameAs","#deriveBounded","#expressionBuilder","#exists"],"sources":["../../../../../zql/src/query/query-impl.ts"],"sourcesContent":["// oxlint-disable no-explicit-any\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {\n deepEqual,\n type ReadonlyJSONObject,\n type ReadonlyJSONValue,\n} from '../../../shared/src/json.ts';\nimport {getOrInsertComputed, newMap} from '../../../shared/src/map.ts';\nimport {\n type AST,\n type CompoundKey,\n type Condition,\n type NormalizedAST,\n type Parameter,\n type LiteralValue,\n type SimpleCondition,\n type SimpleOperator,\n type System,\n insertRelated,\n normalizeAST,\n normalizeCondition,\n normalizedRelated,\n SUBQ_PREFIX,\n tableAST,\n} from '../../../zero-protocol/src/ast.ts';\nimport {hashOfQueryInternals} from '../../../zero-protocol/src/query-hash-visitor.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {NotImplementedError} from '../error.ts';\nimport {defaultFormat} from '../ivm/default-format.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport {\n type ExpressionFactory,\n ExpressionBuilder,\n and,\n cmp,\n simplifyCondition,\n} from './expression.ts';\nimport type {CustomQueryID} from './named.ts';\nimport {type QueryInternals, queryInternalsTag} from './query-internals.ts';\nimport {\n HashIndex,\n Transitions,\n type Delta,\n type TransitionValue,\n} from './query-transitions.ts';\nimport type {\n AnyQuery,\n ExistsOptions,\n GetFilterType,\n HumanReadable,\n PreloadOptions,\n PullRow,\n Query,\n RunOptions,\n} from './query.ts';\nimport type {TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\ntype GetFilterTypeAny = GetFilterType<any, any, any>;\n\ntype NewQueryFunction<TSchema extends Schema> = <\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n this: unknown,\n tableName: TTable,\n ast: NormalizedAST,\n format: Format,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n) => QueryImpl<TTable, TSchema, TReturn>;\n\nexport function newQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n>(schema: TSchema, table: TTable): Query<TTable, TSchema> {\n return newQueryInternal(\n schema,\n table,\n tableAST(table),\n defaultFormat,\n 'client',\n );\n}\n\nexport function newQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>(\n schema: TSchema,\n tableName: TTable,\n ast: AST,\n format: Format,\n system: System,\n): QueryImpl<TTable, TSchema, TReturn> {\n // This is the entry point for ASTs that were not built by QueryImpl, so\n // normalize it here to establish the invariant that #ast is normalized.\n return newQueryInternal(schema, tableName, normalizeAST(ast), format, system);\n}\n\n/**\n * Root queries are interned per schema so that two `createBuilder(schema)` calls\n * hand out the same starting point, and therefore share the whole transition\n * tree below it. Only cleared entries accumulate here, at most one per\n * system/table pair, so no sweeping is needed.\n */\nconst rootsBySchema = new WeakMap<\n Schema,\n Map<string, WeakRef<QueryImpl<any, any, any>>>\n>();\n\n/**\n * Whether this is the AST `tableAST(tableName)` produces -- the whole table,\n * nothing else. A normalized AST carries every field, so this cannot be a key\n * count; each one has to be checked.\n */\nfunction isRootAST(ast: NormalizedAST, tableName: string): boolean {\n return (\n ast.table === tableName &&\n ast.schema === undefined &&\n ast.alias === undefined &&\n ast.where === undefined &&\n ast.related === undefined &&\n ast.start === undefined &&\n ast.limit === undefined &&\n ast.orderBy === undefined\n );\n}\n\nfunction newQueryInternal<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>(\n schema: TSchema,\n tableName: TTable,\n ast: NormalizedAST,\n format: Format,\n system: System,\n): QueryImpl<TTable, TSchema, TReturn> {\n // Callers that hand in a pre-built AST -- benchmarks and the integration-test\n // harnesses -- are not roots and are not interned.\n const interned = format === defaultFormat && isRootAST(ast, tableName);\n const key = `${system}:${tableName}`;\n let roots: Map<string, WeakRef<QueryImpl<any, any, any>>> | undefined;\n\n if (interned) {\n roots = rootsBySchema.get(schema);\n const existing = roots?.get(key)?.deref();\n if (existing) {\n return existing as QueryImpl<TTable, TSchema, TReturn>;\n }\n }\n\n const inner: NewQueryFunction<TSchema> = (\n tableName,\n ast,\n format,\n customQueryID,\n currentJunction,\n ) =>\n new QueryImpl(\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n inner,\n );\n\n const created = inner<TTable, TReturn>(\n tableName,\n ast,\n format,\n undefined,\n undefined,\n );\n\n if (interned) {\n if (!roots) {\n roots = new Map();\n rootsBySchema.set(schema, roots);\n }\n roots.set(key, new WeakRef(created));\n }\n\n return created;\n}\n\n/**\n * The AST of a QueryImpl is always normalized. Each step builds its AST in\n * normalized form rather than normalizing afterwards: a normalized AST has\n * every field, so spreading one and replacing a field keeps the field order\n * intact, and only the field a step actually changes needs normalizing (the\n * conditions of a `where`, the position of a new `related`). The ASTs that\n * come in from the outside are normalized by {@link newQueryImpl}, which is\n * what the `NormalizedAST` of the AST it holds stands for.\n */\nexport class QueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>\n implements\n Query<TTable, TSchema, TReturn>,\n QueryInternals<TTable, TSchema, TReturn>\n{\n readonly [queryInternalsTag] = true;\n\n readonly #schema: TSchema;\n readonly #tableName: TTable;\n readonly #ast: NormalizedAST;\n readonly format: Format;\n #hash: string = '';\n readonly #system: System;\n readonly #currentJunction: string | undefined;\n readonly customQueryID: CustomQueryID | undefined;\n readonly #newQuery: NewQueryFunction<TSchema>;\n\n /**\n * The query this one was derived from, held *strongly*, and the queries\n * derived from this one, held *weakly*. This is the arrangement V8 uses for\n * hidden-class transitions, and it is what makes interning stable: as long as\n * a query is reachable its whole ancestor spine is too, so re-deriving it from\n * the root yields the same instance. See `query-transitions.ts`.\n */\n #parent: QueryImpl<any, any, any> | undefined;\n #transitions: Transitions<QueryImpl<any, any, any>> | undefined;\n\n /**\n * The second level of interning, keyed by hash; see `HashIndex`. Set on the\n * root only, which is what scopes it to one schema and one delegate.\n */\n #byHash: HashIndex<QueryImpl<any, any, any>> | undefined;\n\n /**\n * Memoized because a query is interned: the same node serves every rebuild of\n * a chain, so building this once rather than per `where(fn)` call takes the\n * whole thing -- the builder and the bound `#exists` -- off the repeat path.\n */\n #expressionBuilder: ExpressionBuilder<TTable, TSchema> | undefined;\n\n constructor(\n schema: TSchema,\n tableName: TTable,\n ast: NormalizedAST,\n format: Format,\n system: System,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n newQuery: NewQueryFunction<TSchema>,\n ) {\n this.#schema = schema;\n this.#tableName = tableName;\n this.#ast = ast;\n this.format = format;\n this.#system = system;\n this.#currentJunction = currentJunction;\n this.customQueryID = customQueryID;\n this.#newQuery = newQuery;\n }\n\n /**\n * Interns a transition whose key space is finite and schema-derived; see\n * {@link Transitions.storeBounded}. Used for the base sub-query handed to\n * a `related`/`exists` callback, which is determined entirely by the\n * relationship name.\n */\n #deriveBounded<T>(key: string, build: () => T): T {\n const existing = this.#transitions?.lookupBounded(key);\n if (existing !== undefined) {\n return existing as T;\n }\n return this.#record(key, undefined, undefined, build(), true);\n }\n\n /**\n * Interns the result of applying a builder operation to this query.\n *\n * `key` names the operation and `value` carries its varying argument, kept\n * apart so the key stays a string V8 has already hashed. When the two do not\n * settle it, `delta` carries the rest and is compared with `deepEqual`. Only\n * the delta is compared, never the whole AST: this query is already canonical,\n * so two of its children are equal exactly when the operations that produced\n * them are.\n *\n * `T` is deliberately unconstrained so that the contextual return type at each\n * call site still drives `#newQuery`'s inference, exactly as it did when the\n * call sites returned `this.#newQuery(...)` directly.\n */\n #derive<T>(\n key: string,\n value: TransitionValue,\n delta: Delta,\n build: () => T,\n ): T {\n const existing = this.#transitions?.lookup(key, value, delta);\n if (existing !== undefined) {\n return existing as T;\n }\n return this.#record(key, value, delta, build(), false);\n }\n\n #record<T>(\n key: string,\n value: TransitionValue,\n delta: Delta,\n created: T,\n bounded: boolean,\n ): T {\n const q = created as unknown as QueryImpl<any, any, any>;\n q.#parent = this;\n const transitions = (this.#transitions ??= new Transitions());\n if (bounded) {\n transitions.storeBounded(key, q);\n } else {\n transitions.store(key, value, delta, q);\n }\n return created;\n }\n\n run(_options?: RunOptions): Promise<HumanReadable<TReturn>> {\n throwQueryNotRunnable();\n }\n\n preload(_options?: PreloadOptions): {\n cleanup: () => void;\n complete: Promise<void>;\n cached: Promise<void>;\n } {\n throwQueryNotRunnable();\n }\n\n materialize(ttl?: TTL): TypedView<HumanReadable<TReturn>>;\n materialize<T>(\n factory: ViewFactory<TTable, TSchema, TReturn, T>,\n ttl?: TTL,\n ): T;\n materialize<T>(\n _factoryOrTTL?: ViewFactory<TTable, TSchema, TReturn, T> | TTL,\n _ttl?: TTL,\n ): T | TypedView<HumanReadable<TReturn>> {\n throwQueryNotRunnable();\n }\n\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TTable, TSchema, TReturn> {\n return this.#derive('nameAndArgs', name, args, () =>\n this.#newQuery(\n this.#tableName,\n this.#ast,\n this.format,\n {\n name,\n args,\n },\n this.#currentJunction,\n ),\n );\n }\n\n hash(): string {\n if (!this.#hash) {\n this.#hash = hashOfQueryInternals(\n this.#ast,\n this.format,\n this.#system,\n this.#currentJunction,\n this.customQueryID?.name,\n this.customQueryID?.args,\n );\n this.#canonicalize();\n }\n return this.#hash;\n }\n\n /**\n * Folds this query into its root's hash index, now that its hash is known.\n *\n * If an equal query is already indexed, the transition that produced this\n * one is re-pointed at it, so the next rebuild along this path yields that\n * instance rather than a second copy. This query itself is left alone: its\n * identity has already been handed out. Content is verified with `#sameAs`\n * before anything is redirected, so a hash collision costs nothing worse\n * than a missed unification.\n */\n #canonicalize(): void {\n const parent = this.#parent;\n if (parent === undefined) {\n // A root has no path to redirect and is its own canonical form.\n return;\n }\n let root = parent;\n while (root.#parent !== undefined) {\n root = root.#parent;\n }\n const index = (root.#byHash ??= new HashIndex());\n const existing = index.get(this.#hash);\n if (existing === undefined) {\n index.set(this.#hash, this);\n } else if (existing !== this && this.#sameAs(existing)) {\n parent.#transitions?.replace(this, existing);\n }\n }\n\n /**\n * Whether `other` is interchangeable with this query: everything `hash()`\n * covers, compared structurally. Schema and delegate are not compared. Both\n * are fixed by the root, and this only ever compares queries under one root.\n */\n #sameAs(other: QueryImpl<any, any, any>): boolean {\n return (\n this.#system === other.#system &&\n this.#currentJunction === other.#currentJunction &&\n this.customQueryID?.name === other.customQueryID?.name &&\n deepEqual(this.customQueryID?.args, other.customQueryID?.args) &&\n deepEqual(this.format, other.format) &&\n deepEqual(this.#ast, other.#ast)\n );\n }\n\n one(): Query<TTable, TSchema, TReturn | undefined> {\n return this.#derive('one', undefined, undefined, () =>\n this.#newQuery(\n this.#tableName,\n {...this.#ast, limit: 1},\n {\n ...this.format,\n singular: true,\n },\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n whereExists(\n relationship: string,\n cbOrOptions?: ((q: AnyQuery) => AnyQuery) | ExistsOptions,\n options?: ExistsOptions,\n ): Query<TTable, TSchema, TReturn> {\n const cb = typeof cbOrOptions === 'function' ? cbOrOptions : undefined;\n const opts = typeof cbOrOptions === 'function' ? options : cbOrOptions;\n return this.where(({exists}) => exists(relationship, cb, opts)) as Query<\n TTable,\n TSchema,\n TReturn\n >;\n }\n\n related(\n relationship: string,\n cb?: (q: AnyQuery) => AnyQuery,\n ): Query<TTable, TSchema, any> {\n if (relationship.startsWith(SUBQ_PREFIX)) {\n throw new Error(\n `Relationship names may not start with \"${SUBQ_PREFIX}\". That is a reserved prefix.`,\n );\n }\n cb = cb ?? (q => q);\n\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n if (isOneHop(related)) {\n const {destSchema, destField, sourceField, cardinality} = related[0];\n // Intern the base handed to the callback too. A deterministic callback\n // then walks the same interned chain and hands back the *same* sub-query,\n // which makes the comparison below a pointer compare.\n const q: AnyQuery = this.#deriveBounded(\n `relatedBase:${relationship}`,\n () =>\n this.#newQuery(\n destSchema,\n tableAST(destSchema, relationship),\n {\n relationships: {},\n singular: cardinality === 'one',\n },\n this.customQueryID,\n undefined,\n ),\n ) as AnyQuery;\n // Intentionally not setting to `one` as it is a perf degradation\n // and the user should not be making the mistake of setting cardinality to\n // `one` when it is actually not.\n // if (cardinality === 'one') {\n // q = q.one();\n // }\n const subQuery = asQueryImpl(cb(q));\n assert(\n isCompoundKey(sourceField),\n 'The source of a relationship must specify at last 1 field',\n );\n assert(\n isCompoundKey(destField),\n 'The destination of a relationship must specify at last 1 field',\n );\n assert(\n sourceField.length === destField.length,\n 'The source and destination of a relationship must have the same number of fields',\n );\n\n // Keyed by the sub-query's identity. Each query owns its AST object, so\n // this distinguishes even `q.one()` from `q.limit(1)`, whose ASTs are\n // structurally equal but whose formats differ. Comparing them as a delta\n // instead would put every sibling under one key and scan.\n return this.#derive(\n relatedKey(relationship),\n astID(subQuery.#ast),\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: insertRelated(this.#ast.related, {\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n system: this.#system,\n }),\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: subQuery.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ),\n ) as AnyQuery;\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const sq = asQueryImpl(\n cb(\n this.#deriveBounded(`relatedBase:${relationship}`, () =>\n this.#newQuery(\n destSchema,\n tableAST(destSchema, relationship),\n {\n relationships: {},\n singular: secondRelation.cardinality === 'one',\n },\n this.customQueryID,\n relationship,\n ),\n ) as AnyQuery,\n ),\n );\n\n // Bound to consts so the `isCompoundKey` narrowing survives into the\n // closure below; TypeScript drops narrowing of property accesses there.\n const {sourceField: firstSource, destField: firstDest} = firstRelation;\n const {sourceField: secondSource, destField: secondDest} = secondRelation;\n assert(isCompoundKey(firstSource), 'Invalid relationship');\n assert(isCompoundKey(firstDest), 'Invalid relationship');\n assert(isCompoundKey(secondSource), 'Invalid relationship');\n assert(isCompoundKey(secondDest), 'Invalid relationship');\n\n return this.#derive(\n relatedKey(relationship),\n astID(sq.#ast),\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: insertRelated(this.#ast.related, {\n correlation: {\n parentField: firstSource,\n childField: firstDest,\n },\n hidden: true,\n subquery: {\n ...tableAST(junctionSchema, relationship),\n // A single subquery is sorted.\n related: [\n normalizedRelated({\n correlation: {\n parentField: secondSource,\n childField: secondDest,\n },\n subquery: sq.#ast,\n system: this.#system,\n }),\n ],\n },\n system: this.#system,\n }),\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: sq.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ),\n ) as AnyQuery;\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n }\n\n // The declared return is the *bottom* of the pinned dimension, which is\n // assignable to every `where` overload's declared return. The overloads\n // refine `TPinned` for callers only; a single non-generic implementation\n // signature cannot express that refinement.\n where(\n fieldOrExpressionFactory: string | ExpressionFactory<TTable, TSchema>,\n opOrValue?: SimpleOperator | GetFilterTypeAny | Parameter,\n value?: GetFilterTypeAny | Parameter,\n ): Query<TTable, TSchema, TReturn, any> {\n let cond: Condition;\n\n if (typeof fieldOrExpressionFactory === 'function') {\n cond = fieldOrExpressionFactory(this.expressionBuilder());\n } else {\n assert(arguments.length >= 2, 'Invalid condition. Too few arguments.');\n // Distinguish between 2-arg form (field, value) and 3-arg form (field, op, value)\n // using arguments.length to allow explicit undefined in 3-arg form.\n const twoArg = arguments.length === 2;\n const op = (twoArg ? '=' : opOrValue) as SimpleOperator;\n const raw = twoArg ? opOrValue : value;\n\n // Comparing a column to a primitive is by far the most common thing anyone\n // does with a query, and the transition it names is fully determined by\n // (column, op, value) -- so check for it before building anything. On a hit\n // this returns without allocating the `Condition` at all. Objects are\n // excluded, which covers both parameter references and `IN` arrays; `cmp`\n // maps a missing value to null, so this must too.\n if (raw === null || typeof raw !== 'object') {\n const hit = this.#transitions?.lookup(\n whereKey(fieldOrExpressionFactory, op),\n (raw ?? null) as TransitionValue,\n undefined,\n );\n if (hit !== undefined) {\n return hit as unknown as Query<TTable, TSchema, TReturn, any>;\n }\n }\n\n cond = twoArg\n ? cmp(fieldOrExpressionFactory, opOrValue)\n : cmp(fieldOrExpressionFactory, opOrValue, value);\n }\n\n // The delta is the condition as built here, *before* it is merged with the\n // existing where and normalized. Both steps are deterministic and the\n // existing where is fixed by this query, so an equal `cond` always produces\n // an equal result.\n //\n // A simple comparison against a column splits cleanly: the column and\n // operator come from a small fixed set and give a memoized, stable key,\n // while the compared value -- the part that varies per call -- is handed\n // through as the transition value and never concatenated into a string.\n let key: string;\n let tValue: TransitionValue;\n let delta: Delta = cond;\n if (cond.type === 'simple' && cond.left.type === 'column') {\n key = whereKey(cond.left.name, cond.op);\n const right = cond.right;\n tValue =\n right.type === 'literal' && isPrimitive(right.value)\n ? right.value\n : rightTag(right);\n delta = undefined;\n } else {\n // A sub-query an `exists` correlates to is itself interned, so its\n // identity settles that part of the tree without walking it.\n const exact = condKey(cond);\n if (exact === undefined) {\n key = treeKey(cond);\n } else {\n key = 'where:tree';\n tValue = exact;\n delta = undefined;\n }\n }\n\n return this.#derive(key, tValue, delta, () => {\n const existingWhere = this.#ast.where;\n const merged = existingWhere ? and(existingWhere, cond) : cond;\n return this.#newQuery(\n this.#tableName,\n {...this.#ast, where: normalizeCondition(simplifyCondition(merged))},\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n }) as unknown as Query<TTable, TSchema, TReturn, any>;\n }\n\n start(\n row: Partial<Record<string, ReadonlyJSONValue | undefined>>,\n opts?: {inclusive: boolean},\n ): Query<TTable, TSchema, TReturn> {\n // The row is an object, so it is encoded to a string to serve as the\n // lookup key. Property order is part of that string.\n return this.#derive(\n opts?.inclusive ? 'start:inclusive' : 'start:exclusive',\n valueTag(row as ReadonlyJSONValue),\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n start: {\n row,\n exclusive: !opts?.inclusive,\n },\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n limit(limit: number): Query<TTable, TSchema, TReturn> {\n if (limit < 0) {\n throw new Error('Limit must be non-negative');\n }\n if ((limit | 0) !== limit) {\n throw new Error('Limit must be an integer');\n }\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Limit is not supported in junction relationships yet. Junction relationship being limited: ' +\n this.#currentJunction,\n );\n }\n\n return this.#derive('limit', limit, undefined, () =>\n this.#newQuery(\n this.#tableName,\n {...this.#ast, limit},\n this.format,\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n orderBy<TSelector extends keyof TSchema['tables'][TTable]['columns']>(\n field: TSelector,\n direction: 'asc' | 'desc',\n ): Query<TTable, TSchema, TReturn> {\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Order by is not supported in junction relationships yet. Junction relationship being ordered: ' +\n this.#currentJunction,\n );\n }\n return this.#derive(\n direction === 'asc' ? 'orderBy:asc' : 'orderBy:desc',\n field as string,\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n orderBy: [\n ...(this.#ast.orderBy ?? []),\n [field as string, direction],\n ],\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n #exists(\n relationship: string,\n cb: ((query: AnyQuery) => AnyQuery) | undefined,\n options?: ExistsOptions,\n ): Condition {\n cb = cb ?? (q => q);\n const flip = options?.flip;\n const scalar = options?.scalar;\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n\n if (isOneHop(related)) {\n const {destSchema: destTableName, sourceField, destField} = related[0];\n assert(isCompoundKey(sourceField), 'Invalid relationship');\n assert(isCompoundKey(destField), 'Invalid relationship');\n\n const subQuery = asQueryImpl(\n cb(\n this.#deriveBounded(`existsBase:${relationship}`, () =>\n this.#newQuery(\n destTableName,\n tableAST(destTableName, `${SUBQ_PREFIX}${relationship}`),\n defaultFormat,\n this.customQueryID,\n undefined,\n ),\n ) as AnyQuery,\n ),\n );\n // Give the sub-query's AST an id so the enclosing `where` can key on it\n // exactly rather than comparing the sub-tree.\n astID(subQuery.#ast);\n // Unlike the entries of `related`, the correlated subqueries of a\n // condition keep the order their fields are written in: normalization\n // does not reorder them either.\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n ...(scalar !== undefined ? {scalar} : {}),\n };\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const queryToDest = cb(\n this.#deriveBounded(`existsJunctionBase:${relationship}`, () =>\n this.#newQuery(\n destSchema,\n tableAST(destSchema, `${SUBQ_PREFIX}zhidden_${relationship}`),\n defaultFormat,\n this.customQueryID,\n relationship,\n ),\n ) as AnyQuery,\n );\n\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n subquery: {\n ...tableAST(junctionSchema, `${SUBQ_PREFIX}${relationship}`),\n // A single condition needs no flattening or sorting, but the node\n // itself still has to be rebuilt into the canonical field order.\n where: normalizeCondition({\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n subquery: asQueryImpl(queryToDest).#ast,\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n ...(scalar !== undefined ? {scalar} : {}),\n }),\n },\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n };\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n }\n\n get ast(): NormalizedAST {\n return this.#ast;\n }\n\n expressionBuilder(): ExpressionBuilder<TTable, TSchema> {\n // Built on demand rather than held as an eagerly initialized field: a field\n // would cost a closure on every query constructed, where this costs one only\n // for queries that actually use an expression factory.\n return (this.#expressionBuilder ??= new ExpressionBuilder<TTable, TSchema>(\n this.#exists.bind(this) as ConstructorParameters<\n typeof ExpressionBuilder<TTable, TSchema>\n >[0],\n ));\n }\n}\n\nexport function asQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n>(q: Query<TTable, TSchema, TReturn>): QueryImpl<TTable, TSchema, TReturn> {\n assert(q instanceof QueryImpl, 'Expected QueryImpl instance');\n return q;\n}\n\n/**\n * A stable id per query AST.\n *\n * Every `QueryImpl` allocates its own AST object, so these are one-to-one with\n * queries, and interning makes the object identity stable across rebuilds. That\n * lets a `related` or `exists` transition key on *which* sub-query it points at\n * rather than comparing the sub-tree.\n *\n * Assigned only where it is needed. A `WeakMap.set` costs on the order of a\n * hundred nanoseconds, so doing this for every query rather than for the few\n * that are sub-queries was one of the largest single costs of building a query\n * from cold. ASTs that never pass through here -- including the junction AST a\n * two-hop `exists` builds inline -- are absent, and fall back to a delta.\n */\nconst astIDs = new WeakMap<AST, number>();\nlet nextASTID = 0;\n\nconst newASTID = () => ++nextASTID;\n\nfunction astID(ast: AST): number {\n return getOrInsertComputed(astIDs, ast, newASTID);\n}\n\n/**\n * Memoized transition keys.\n *\n * A transition key must be a string V8 has already hashed, or the `Map` lookup\n * has to hash it from scratch -- measured at ~148ns against ~10ns, which dwarfs\n * everything else a lookup does. Both tables are keyed by schema-derived names,\n * so they are bounded by the schema.\n */\nconst whereKeys = new Map<string, Map<string, string>>();\n\nfunction whereKey(column: string, op: string): string {\n const byOp = getOrInsertComputed(whereKeys, column, newMap);\n return getOrInsertComputed(byOp, op, op => `where:${column}:${op}`);\n}\n\nconst relatedKeys = new Map<string, string>();\n\nconst newRelatedKey = (relationship: string) => `related:${relationship}`;\n\nfunction relatedKey(relationship: string): string {\n return getOrInsertComputed(relatedKeys, relationship, newRelatedKey);\n}\n\nfunction isPrimitive(v: LiteralValue): v is string | number | boolean | null {\n return v === null || typeof v !== 'object';\n}\n\n/**\n * Folds a JSON value into a self-delimiting token: a string is\n * length-prefixed, a number is terminated, an array or object is\n * count-prefixed and encodes its members recursively, and the rest are fixed\n * width. Tokens can therefore be concatenated into a key with no way for one\n * to run into the next, and the leading tag keeps `'1'` and `1` apart.\n *\n * Not `JSON.stringify`: it writes `Infinity`, `NaN` and `null` all as `null`,\n * and this token is trusted as exact, so a nested value that serialized like\n * another's would hand back a query with the wrong value in its AST. Numbers\n * are written the way `String` writes them, which keeps those apart. An\n * `undefined` property is skipped, as `deepEqual` would skip it; property\n * order is part of the encoding, so an object spelled in another order\n * interns separately.\n */\nfunction valueTag(v: ReadonlyJSONValue): string {\n switch (typeof v) {\n case 'string':\n return `:s${enc(v)}`;\n case 'number':\n return `:n${v};`;\n case 'boolean':\n return v ? ':t' : ':f';\n default: {\n if (v === null) {\n return ':z';\n }\n if (Array.isArray(v)) {\n let out = `:a${v.length}:`;\n for (const e of v) {\n out += valueTag(e);\n }\n return out;\n }\n // `Array.isArray` does not narrow a readonly array out of the union.\n const o = v as ReadonlyJSONObject;\n let body = '';\n let n = 0;\n for (const key in o) {\n const e = o[key];\n if (e !== undefined && Object.hasOwn(o, key)) {\n body += enc(key) + valueTag(e);\n n++;\n }\n }\n return `:o${n}:${body}`;\n }\n }\n}\n\n/**\n * Folds the right-hand side of a simple condition into a transition value, so\n * that the transition is exact and the lookup needs no comparison at all.\n *\n * Arrays (`IN`) and parameter references are encoded in full: that is one\n * pass over a small value, where leaving them in the delta would instead cost\n * a `deepEqual` over the whole condition for every sibling a lookup walks\n * past.\n */\nfunction rightTag(right: SimpleCondition['right']): string {\n if (right.type !== 'literal') {\n return `:p${valueTag(right as unknown as ReadonlyJSONValue)}`;\n }\n return valueTag(right.value);\n}\n\n/**\n * Length-prefixes a free-form string so it can be concatenated into a key\n * without a separator being ambiguous with the content.\n */\nfunction enc(s: string): string {\n return `${s.length}:${s}`;\n}\n\n/** Encodes an optional boolean without collapsing `undefined` into `false`. */\nfunction tri(b: boolean | undefined): string {\n return b === undefined ? '-' : b ? 't' : 'f';\n}\n\n/**\n * An exact key for a whole condition tree, or `undefined` for a shape we cannot\n * encode (which falls back to {@link treeKey} plus a delta).\n *\n * Everything variable-length is length-prefixed, so distinct trees cannot\n * produce the same string and the key needs no `deepEqual` to back it up. That\n * matters because the alternative -- one coarse bucket per shape -- turns N\n * sibling conditions off the same parent into an N-deep scan of tree\n * comparisons, which measured far slower than not interning at all.\n */\nfunction condKey(cond: Condition): string | undefined {\n switch (cond.type) {\n case 'simple': {\n if (cond.left.type !== 'column') {\n return undefined;\n }\n return `S${enc(cond.left.name)}${enc(cond.op)}${rightTag(cond.right)}`;\n }\n case 'correlatedSubquery': {\n const id = astIDs.get(cond.related.subquery);\n return id === undefined\n ? undefined\n : `E${id}:${enc(cond.op)}${tri(cond.flip)}${tri(cond.scalar)}`;\n }\n case 'and':\n case 'or': {\n let out = `${cond.type === 'and' ? 'A' : 'O'}${cond.conditions.length}:`;\n for (const c of cond.conditions) {\n const k = condKey(c);\n if (k === undefined) {\n return undefined;\n }\n out += k;\n }\n return out;\n }\n default:\n return undefined;\n }\n}\n\n/**\n * A coarse bucket key for the conditions {@link condKey} cannot encode --\n * a two-hop `exists`, whose junction AST is built inline and so has no identity\n * of its own. Reads only the top of the tree, so it is cheap; the delta tells\n * apart what shares it.\n */\nfunction treeKey(cond: Condition): string {\n switch (cond.type) {\n case 'correlatedSubquery':\n return `where:e:${cond.related.subquery.alias}:${cond.op}`;\n case 'and':\n case 'or':\n return `where:${cond.type}:${cond.conditions.length}`;\n default:\n return 'where:*';\n }\n}\n\nfunction throwQueryNotRunnable(): never {\n throw new Error('Query is not runnable');\n}\n\nfunction isCompoundKey(field: readonly string[]): field is CompoundKey {\n return Array.isArray(field) && field.length >= 1;\n}\n\nfunction isOneHop<T>(r: readonly T[]): r is readonly [T] {\n return r.length === 1;\n}\n\nfunction isTwoHop<T>(r: readonly T[]): r is readonly [T, T] {\n return r.length === 2;\n}\n"],"mappings":"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"}
@@ -8,7 +8,7 @@ export declare const queryInternalsTag: unique symbol;
8
8
  /**
9
9
  * Internal interface for query implementation details.
10
10
  * This is not part of the public API and should only be accessed via
11
- * the {@linkcode asQueryInternals} function.
11
+ * the {@link asQueryInternals} function.
12
12
  *
13
13
  * @typeParam TSchema The database schema type extending ZeroSchema
14
14
  * @typeParam TTable The name of the table being queried, must be a key of TSchema['tables']
@@ -18,8 +18,8 @@ export interface QueryInternals<TTable extends keyof TSchema['tables'] & string,
18
18
  readonly [queryInternalsTag]: true;
19
19
  /**
20
20
  * Format is used to specify the shape of the query results. This is used by
21
- * {@linkcode one} and it also describes the shape when using
22
- * {@linkcode related}.
21
+ * {@link one} and it also describes the shape when using
22
+ * {@link related}.
23
23
  */
24
24
  readonly format: Format;
25
25
  /**
@@ -27,11 +27,11 @@ export interface QueryInternals<TTable extends keyof TSchema['tables'] & string,
27
27
  * exactly when they are interchangeable, down to how their builder methods
28
28
  * behave.
29
29
  *
30
- * It covers the AST, the {@linkcode format} the results take, the system the
30
+ * It covers the AST, the {@link format} the results take, the system the
31
31
  * query was built for, the junction relationship it is being built inside,
32
32
  * and, for a custom query, the name and arguments it was declared with.
33
33
  * Everything past the AST is hashed explicitly because it leaves no trace
34
- * there: {@linkcode nameAndArgs} reuses the AST it is given, a query with no
34
+ * there: {@link nameAndArgs} reuses the AST it is given, a query with no
35
35
  * relationship and no `exists` has nowhere to stamp its system, and the
36
36
  * junction flag -- which decides whether `limit` and `orderBy` throw --
37
37
  * appears nowhere in the AST at all. Without them, such queries would share a
@@ -1 +1 @@
1
- {"version":3,"file":"query-internals.js","names":[],"sources":["../../../../../zql/src/query/query-internals.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport type {AST} from '../../../zero-protocol/src/ast.ts';\nimport type {Schema as ZeroSchema} from '../../../zero-types/src/schema.ts';\nimport type {Format} from '../ivm/view.ts';\nimport type {CustomQueryID} from './named.ts';\nimport type {Query} from './query.ts';\n\nexport const queryInternalsTag = Symbol();\n\n/**\n * Internal interface for query implementation details.\n * This is not part of the public API and should only be accessed via\n * the {@linkcode asQueryInternals} function.\n *\n * @typeParam TSchema The database schema type extending ZeroSchema\n * @typeParam TTable The name of the table being queried, must be a key of TSchema['tables']\n * @typeParam TReturn The return type of the query, defaults to PullRow<TTable, TSchema>\n */\nexport interface QueryInternals<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n> {\n readonly [queryInternalsTag]: true;\n\n /**\n * Format is used to specify the shape of the query results. This is used by\n * {@linkcode one} and it also describes the shape when using\n * {@linkcode related}.\n */\n readonly format: Format;\n\n /**\n * A string that uniquely identifies this query object: two queries share it\n * exactly when they are interchangeable, down to how their builder methods\n * behave.\n *\n * It covers the AST, the {@linkcode format} the results take, the system the\n * query was built for, the junction relationship it is being built inside,\n * and, for a custom query, the name and arguments it was declared with.\n * Everything past the AST is hashed explicitly because it leaves no trace\n * there: {@linkcode nameAndArgs} reuses the AST it is given, a query with no\n * relationship and no `exists` has nowhere to stamp its system, and the\n * junction flag -- which decides whether `limit` and `orderBy` throw --\n * appears nowhere in the AST at all. Without them, such queries would share a\n * hash and anything keyed by it would conflate them.\n *\n * It does *not* cover the schema, which has no stable identity to hash.\n * Anything keyed by this that could see more than one schema has to scope\n * itself by schema as well.\n *\n * This is entirely client-side and never reaches the server. The server knows\n * a custom query by the hash of its name and args, and any other query by the\n * hash of its AST alone -- see `materializeImpl`.\n */\n hash(): string;\n\n /**\n * The completed AST for this query, with any missing primary keys added to\n * orderBy and start.\n *\n * A QueryImpl hands out a `NormalizedAST`; this stays an `AST` so that the\n * ASTs derived from it (e.g. by binding static parameters) still fit.\n */\n readonly ast: AST;\n\n readonly customQueryID: CustomQueryID | undefined;\n\n /**\n * Associates a name and arguments with this query for custom query tracking.\n * This is used internally to track named queries on the server.\n *\n * @internal\n */\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TTable, TSchema, TReturn>;\n}\n\n/**\n * Helper function to cast a Query to QueryInternals.\n * This is used in tests and internal code to access query implementation details.\n * The function asserts that the query has the queryInternalsTag to ensure it\n * properly implements the QueryInternals interface.\n *\n * @internal\n */\nexport function asQueryInternals<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n>(\n query: Query<TTable, TSchema, TReturn>,\n): QueryInternals<TTable, TSchema, TReturn> {\n assert(\n queryInternalsTag in query,\n 'Query does not implement QueryInternals. This likely means there are two copies of Zero in your runtime.',\n );\n return query as unknown as QueryInternals<TTable, TSchema, TReturn>;\n}\n\nexport function isQueryInternals<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n>(obj: unknown): obj is QueryInternals<TTable, TSchema, TReturn> {\n return typeof obj === 'object' && obj !== null && queryInternalsTag in obj;\n}\n\nexport function asQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n>(\n queryInternals: QueryInternals<TTable, TSchema, TReturn>,\n): Query<TTable, TSchema, TReturn> {\n assert(queryInternalsTag in queryInternals, 'Expected query internals tag');\n return queryInternals as unknown as Query<TTable, TSchema, TReturn>;\n}\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyQueryInternals = QueryInternals<string, ZeroSchema, any>;\n"],"mappings":";;AAQA,IAAa,oBAAoB,OAAO;;;;;;;;;AAiFxC,SAAgB,iBAKd,OAC0C;CAC1C,OACE,qBAAqB,OACrB,0GACF;CACA,OAAO;AACT"}
1
+ {"version":3,"file":"query-internals.js","names":[],"sources":["../../../../../zql/src/query/query-internals.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport type {AST} from '../../../zero-protocol/src/ast.ts';\nimport type {Schema as ZeroSchema} from '../../../zero-types/src/schema.ts';\nimport type {Format} from '../ivm/view.ts';\nimport type {CustomQueryID} from './named.ts';\nimport type {Query} from './query.ts';\n\nexport const queryInternalsTag = Symbol();\n\n/**\n * Internal interface for query implementation details.\n * This is not part of the public API and should only be accessed via\n * the {@link asQueryInternals} function.\n *\n * @typeParam TSchema The database schema type extending ZeroSchema\n * @typeParam TTable The name of the table being queried, must be a key of TSchema['tables']\n * @typeParam TReturn The return type of the query, defaults to PullRow<TTable, TSchema>\n */\nexport interface QueryInternals<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n> {\n readonly [queryInternalsTag]: true;\n\n /**\n * Format is used to specify the shape of the query results. This is used by\n * {@link one} and it also describes the shape when using\n * {@link related}.\n */\n readonly format: Format;\n\n /**\n * A string that uniquely identifies this query object: two queries share it\n * exactly when they are interchangeable, down to how their builder methods\n * behave.\n *\n * It covers the AST, the {@link format} the results take, the system the\n * query was built for, the junction relationship it is being built inside,\n * and, for a custom query, the name and arguments it was declared with.\n * Everything past the AST is hashed explicitly because it leaves no trace\n * there: {@link nameAndArgs} reuses the AST it is given, a query with no\n * relationship and no `exists` has nowhere to stamp its system, and the\n * junction flag -- which decides whether `limit` and `orderBy` throw --\n * appears nowhere in the AST at all. Without them, such queries would share a\n * hash and anything keyed by it would conflate them.\n *\n * It does *not* cover the schema, which has no stable identity to hash.\n * Anything keyed by this that could see more than one schema has to scope\n * itself by schema as well.\n *\n * This is entirely client-side and never reaches the server. The server knows\n * a custom query by the hash of its name and args, and any other query by the\n * hash of its AST alone -- see `materializeImpl`.\n */\n hash(): string;\n\n /**\n * The completed AST for this query, with any missing primary keys added to\n * orderBy and start.\n *\n * A QueryImpl hands out a `NormalizedAST`; this stays an `AST` so that the\n * ASTs derived from it (e.g. by binding static parameters) still fit.\n */\n readonly ast: AST;\n\n readonly customQueryID: CustomQueryID | undefined;\n\n /**\n * Associates a name and arguments with this query for custom query tracking.\n * This is used internally to track named queries on the server.\n *\n * @internal\n */\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TTable, TSchema, TReturn>;\n}\n\n/**\n * Helper function to cast a Query to QueryInternals.\n * This is used in tests and internal code to access query implementation details.\n * The function asserts that the query has the queryInternalsTag to ensure it\n * properly implements the QueryInternals interface.\n *\n * @internal\n */\nexport function asQueryInternals<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n>(\n query: Query<TTable, TSchema, TReturn>,\n): QueryInternals<TTable, TSchema, TReturn> {\n assert(\n queryInternalsTag in query,\n 'Query does not implement QueryInternals. This likely means there are two copies of Zero in your runtime.',\n );\n return query as unknown as QueryInternals<TTable, TSchema, TReturn>;\n}\n\nexport function isQueryInternals<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n>(obj: unknown): obj is QueryInternals<TTable, TSchema, TReturn> {\n return typeof obj === 'object' && obj !== null && queryInternalsTag in obj;\n}\n\nexport function asQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n>(\n queryInternals: QueryInternals<TTable, TSchema, TReturn>,\n): Query<TTable, TSchema, TReturn> {\n assert(queryInternalsTag in queryInternals, 'Expected query internals tag');\n return queryInternals as unknown as Query<TTable, TSchema, TReturn>;\n}\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyQueryInternals = QueryInternals<string, ZeroSchema, any>;\n"],"mappings":";;AAQA,IAAa,oBAAoB,OAAO;;;;;;;;;AAiFxC,SAAgB,iBAKd,OAC0C;CAC1C,OACE,qBAAqB,OACrB,0GACF;CACA,OAAO;AACT"}
@@ -17,7 +17,7 @@ import { type ReadonlyJSONValue } from '../../../shared/src/json.ts';
17
17
  * in a *stable* string rather than build one per call; see below.
18
18
  * 2. `value` — the operation's varying argument, when it is a primitive, used
19
19
  * directly as a `Map` key.
20
- * 3. `delta` — anything left over, compared with {@linkcode deepEqual}.
20
+ * 3. `delta` — anything left over, compared with {@link deepEqual}.
21
21
  *
22
22
  * Splitting 1 from 2 is what makes this fast. Folding the value into the key
23
23
  * instead means building a fresh string on every call, and a fresh string has to
@@ -61,7 +61,7 @@ import { type ReadonlyJSONValue } from '../../../shared/src/json.ts';
61
61
  * ## Best effort
62
62
  *
63
63
  * Interning is a cache, not a guarantee: a missed lookup only costs an extra
64
- * object. See {@linkcode MAX_SCAN} for the one case where we deliberately give
64
+ * object. See {@link MAX_SCAN} for the one case where we deliberately give
65
65
  * up.
66
66
  *
67
67
  * ## Identity vs. hash
@@ -69,7 +69,7 @@ import { type ReadonlyJSONValue } from '../../../shared/src/json.ts';
69
69
  * Identity implies an equal query hash, but the tree alone does not give the
70
70
  * converse. `normalizeAST` sorts `related` and `and`/`or` conditions, so
71
71
  * `q.where(a).where(b)` and `q.where(b).where(a)` hash the same while being
72
- * distinct paths, and so distinct nodes. {@linkcode HashIndex} is the second
72
+ * distinct paths, and so distinct nodes. {@link HashIndex} is the second
73
73
  * level that folds those together once they have been hashed. Callers that
74
74
  * need the normalizing behavior for a query that may not have been must keep
75
75
  * using the hash.
@@ -122,7 +122,7 @@ export declare class Transitions<T extends object> {
122
122
  store(key: string, value: TransitionValue, delta: Delta, node: T): void;
123
123
  /**
124
124
  * Re-points the transition that produced `from` at `to`, so the next lookup
125
- * along that path yields `to` instead. This is how {@linkcode HashIndex}
125
+ * along that path yields `to` instead. This is how {@link HashIndex}
126
126
  * converges two paths on one node: `from` keeps its identity, since it has
127
127
  * already been handed out, and its path is redirected for the rebuilds that
128
128
  * follow.
@@ -153,7 +153,7 @@ export declare class Transitions<T extends object> {
153
153
  *
154
154
  * On a hit the query being hashed keeps its identity, since it has already
155
155
  * been handed out. Its *transition* is re-pointed at the existing node instead
156
- * (see {@linkcode Transitions.replace}), so the next rebuild along that path
156
+ * (see {@link Transitions.replace}), so the next rebuild along that path
157
157
  * yields the shared instance. As with the tree this is a cache: the rebuild
158
158
  * after a redirect is what converges, not the call that found the duplicate.
159
159
  *
@@ -80,7 +80,7 @@ var Transitions = class {
80
80
  }
81
81
  /**
82
82
  * Re-points the transition that produced `from` at `to`, so the next lookup
83
- * along that path yields `to` instead. This is how {@linkcode HashIndex}
83
+ * along that path yields `to` instead. This is how {@link HashIndex}
84
84
  * converges two paths on one node: `from` keeps its identity, since it has
85
85
  * already been handed out, and its path is redirected for the rebuilds that
86
86
  * follow.
@@ -170,7 +170,7 @@ var Transitions = class {
170
170
  *
171
171
  * On a hit the query being hashed keeps its identity, since it has already
172
172
  * been handed out. Its *transition* is re-pointed at the existing node instead
173
- * (see {@linkcode Transitions.replace}), so the next rebuild along that path
173
+ * (see {@link Transitions.replace}), so the next rebuild along that path
174
174
  * yields the shared instance. As with the tree this is a cache: the rebuild
175
175
  * after a redirect is what converges, not the call that found the duplicate.
176
176
  *