@rocicorp/zero 0.25.0-canary.14 → 0.25.0-canary.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/shared/src/record-proxy.d.ts +13 -0
- package/out/shared/src/record-proxy.d.ts.map +1 -0
- package/out/shared/src/record-proxy.js +59 -0
- package/out/shared/src/record-proxy.js.map +1 -0
- package/out/zero/package.json.js +1 -1
- package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js +20 -13
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +8 -0
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +12 -0
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/server/otel-start.d.ts.map +1 -1
- package/out/zero-cache/src/server/otel-start.js +1 -5
- package/out/zero-cache/src/server/otel-start.js.map +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +6 -1
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +8 -9
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +17 -11
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +2 -2
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +19 -4
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +1 -7
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-client/src/client/crud.d.ts +3 -3
- package/out/zero-client/src/client/crud.d.ts.map +1 -1
- package/out/zero-client/src/client/crud.js +23 -13
- package/out/zero-client/src/client/crud.js.map +1 -1
- package/out/zero-client/src/client/custom.d.ts.map +1 -1
- package/out/zero-client/src/client/custom.js +4 -11
- package/out/zero-client/src/client/custom.js.map +1 -1
- package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
- package/out/zero-client/src/client/ivm-branch.js +20 -13
- package/out/zero-client/src/client/ivm-branch.js.map +1 -1
- package/out/zero-client/src/client/make-mutate-property.d.ts +1 -1
- package/out/zero-client/src/client/make-mutate-property.d.ts.map +1 -1
- package/out/zero-client/src/client/make-mutate-property.js.map +1 -1
- package/out/zero-client/src/client/make-replicache-mutators.d.ts.map +1 -1
- package/out/zero-client/src/client/make-replicache-mutators.js +10 -6
- package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero.js +1 -1
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-server/src/custom.d.ts.map +1 -1
- package/out/zero-server/src/custom.js +12 -28
- package/out/zero-server/src/custom.js.map +1 -1
- package/out/zero-solid/src/solid-view.d.ts +1 -1
- package/out/zero-solid/src/solid-view.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.js +2 -0
- package/out/zero-solid/src/solid-view.js.map +1 -1
- package/out/zero-types/src/schema.d.ts +4 -4
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js +1 -11
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/error.js +1 -10
- package/out/zql/src/error.js.map +1 -1
- package/out/zql/src/ivm/array-view.d.ts +1 -1
- package/out/zql/src/ivm/array-view.d.ts.map +1 -1
- package/out/zql/src/ivm/array-view.js +2 -0
- package/out/zql/src/ivm/array-view.js.map +1 -1
- package/out/zql/src/ivm/exists.d.ts +3 -2
- package/out/zql/src/ivm/exists.d.ts.map +1 -1
- package/out/zql/src/ivm/exists.js +25 -23
- package/out/zql/src/ivm/exists.js.map +1 -1
- package/out/zql/src/ivm/fan-in.d.ts +3 -3
- package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-in.js +6 -5
- package/out/zql/src/ivm/fan-in.js.map +1 -1
- package/out/zql/src/ivm/fan-out.d.ts +2 -2
- package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-out.js +5 -5
- package/out/zql/src/ivm/fan-out.js.map +1 -1
- package/out/zql/src/ivm/filter-operators.d.ts +5 -5
- package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
- package/out/zql/src/ivm/filter-operators.js +8 -8
- package/out/zql/src/ivm/filter-operators.js.map +1 -1
- package/out/zql/src/ivm/filter-push.d.ts +2 -1
- package/out/zql/src/ivm/filter-push.d.ts.map +1 -1
- package/out/zql/src/ivm/filter-push.js +5 -5
- package/out/zql/src/ivm/filter-push.js.map +1 -1
- package/out/zql/src/ivm/filter.d.ts +2 -2
- package/out/zql/src/ivm/filter.d.ts.map +1 -1
- package/out/zql/src/ivm/filter.js +4 -4
- package/out/zql/src/ivm/filter.js.map +1 -1
- package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
- package/out/zql/src/ivm/flipped-join.js +100 -83
- package/out/zql/src/ivm/flipped-join.js.map +1 -1
- package/out/zql/src/ivm/join.d.ts.map +1 -1
- package/out/zql/src/ivm/join.js +52 -50
- package/out/zql/src/ivm/join.js.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +4 -4
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts +3 -3
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +7 -4
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/operator.d.ts +10 -3
- package/out/zql/src/ivm/operator.d.ts.map +1 -1
- package/out/zql/src/ivm/operator.js.map +1 -1
- package/out/zql/src/ivm/push-accumulated.d.ts +1 -1
- package/out/zql/src/ivm/push-accumulated.d.ts.map +1 -1
- package/out/zql/src/ivm/push-accumulated.js +8 -8
- package/out/zql/src/ivm/push-accumulated.js.map +1 -1
- package/out/zql/src/ivm/skip.d.ts +1 -1
- package/out/zql/src/ivm/skip.d.ts.map +1 -1
- package/out/zql/src/ivm/skip.js +8 -3
- package/out/zql/src/ivm/skip.js.map +1 -1
- package/out/zql/src/ivm/source.d.ts +15 -7
- package/out/zql/src/ivm/source.d.ts.map +1 -1
- package/out/zql/src/ivm/stream.d.ts +2 -0
- package/out/zql/src/ivm/stream.d.ts.map +1 -1
- package/out/zql/src/ivm/stream.js +5 -14
- package/out/zql/src/ivm/stream.js.map +1 -1
- package/out/zql/src/ivm/take.d.ts +1 -1
- package/out/zql/src/ivm/take.d.ts.map +1 -1
- package/out/zql/src/ivm/take.js +164 -147
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.d.ts +2 -2
- package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +7 -7
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zql/src/ivm/union-fan-out.d.ts +1 -1
- package/out/zql/src/ivm/union-fan-out.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-out.js +3 -3
- package/out/zql/src/ivm/union-fan-out.js.map +1 -1
- package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
- package/out/zql/src/mutate/mutator-registry.js +1 -0
- package/out/zql/src/mutate/mutator-registry.js.map +1 -1
- package/out/zql/src/mutate/mutator.d.ts +10 -0
- package/out/zql/src/mutate/mutator.d.ts.map +1 -1
- package/out/zql/src/mutate/mutator.js.map +1 -1
- package/out/zql/src/planner/planner-builder.d.ts +2 -1
- package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
- package/out/zql/src/planner/planner-builder.js +5 -5
- package/out/zql/src/planner/planner-builder.js.map +1 -1
- package/out/zql/src/planner/planner-graph.d.ts +3 -1
- package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
- package/out/zql/src/planner/planner-graph.js +5 -5
- package/out/zql/src/planner/planner-graph.js.map +1 -1
- package/out/zql/src/query/create-builder.d.ts.map +1 -1
- package/out/zql/src/query/create-builder.js +7 -36
- package/out/zql/src/query/create-builder.js.map +1 -1
- package/out/zql/src/query/measure-push-operator.d.ts +1 -1
- package/out/zql/src/query/measure-push-operator.d.ts.map +1 -1
- package/out/zql/src/query/measure-push-operator.js +2 -2
- package/out/zql/src/query/measure-push-operator.js.map +1 -1
- package/out/zqlite/src/internal/sql-inline.d.ts +13 -0
- package/out/zqlite/src/internal/sql-inline.d.ts.map +1 -0
- package/out/zqlite/src/internal/sql-inline.js +45 -0
- package/out/zqlite/src/internal/sql-inline.js.map +1 -0
- package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.js +2 -2
- package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
- package/out/zqlite/src/table-source.d.ts +3 -2
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +5 -2
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { assert } from "../../shared/src/asserts.js";
|
|
2
|
+
import { mapValues } from "../../shared/src/objects.js";
|
|
3
|
+
import { recordProxy } from "../../shared/src/record-proxy.js";
|
|
2
4
|
import { formatPgInternalConvert, sql, sqlConvertColumnArg } from "../../z2s/src/sql.js";
|
|
3
5
|
import { createRunnableBuilder } from "../../zql/src/query/create-builder.js";
|
|
4
6
|
import { QueryDelegateBase } from "../../zql/src/query/query-delegate-base.js";
|
|
@@ -86,34 +88,16 @@ function makeSchemaCRUD(schema) {
|
|
|
86
88
|
for (const tableSchema of Object.values(schema.tables)) {
|
|
87
89
|
schemaCRUDs[tableSchema.name] = makeTableCRUD(tableSchema);
|
|
88
90
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
const txHolder = {
|
|
101
|
-
[dbTxSymbol]: this.#dbTransaction,
|
|
102
|
-
[serverSchemaSymbol]: this.#serverSchema
|
|
103
|
-
};
|
|
104
|
-
target[prop] = Object.fromEntries(
|
|
105
|
-
Object.entries(schemaCRUDs[prop]).map(([name, method]) => [
|
|
106
|
-
name,
|
|
107
|
-
method.bind(txHolder)
|
|
108
|
-
])
|
|
109
|
-
);
|
|
110
|
-
return target[prop];
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return (dbTransaction, serverSchema) => new Proxy(
|
|
114
|
-
{},
|
|
115
|
-
new CRUDHandler(dbTransaction, serverSchema)
|
|
116
|
-
);
|
|
91
|
+
return (dbTransaction, serverSchema) => {
|
|
92
|
+
const txHolder = {
|
|
93
|
+
[dbTxSymbol]: dbTransaction,
|
|
94
|
+
[serverSchemaSymbol]: serverSchema
|
|
95
|
+
};
|
|
96
|
+
return recordProxy(
|
|
97
|
+
schemaCRUDs,
|
|
98
|
+
(tableCRUD) => mapValues(tableCRUD, (method) => method.bind(txHolder))
|
|
99
|
+
);
|
|
100
|
+
};
|
|
117
101
|
}
|
|
118
102
|
function removeUndefined(value) {
|
|
119
103
|
const valueWithoutUndefined = {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom.js","sources":["../../../../zero-server/src/custom.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\nimport {\n formatPgInternalConvert,\n sql,\n sqlConvertColumnArg,\n} from '../../z2s/src/sql.ts';\nimport type {TableSchema} from '../../zero-schema/src/table-schema.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {\n ServerColumnSchema,\n ServerSchema,\n ServerTableSchema,\n} from '../../zero-types/src/server-schema.ts';\nimport type {\n DBTransaction,\n SchemaCRUD,\n ServerTransaction,\n TableCRUD,\n} from '../../zql/src/mutate/custom.ts';\nimport {createRunnableBuilder} from '../../zql/src/query/create-builder.ts';\nimport {QueryDelegateBase} from '../../zql/src/query/query-delegate-base.ts';\nimport {asQueryInternals} from '../../zql/src/query/query-internals.ts';\nimport type {\n HumanReadable,\n Query,\n RunOptions,\n} from '../../zql/src/query/query.ts';\nimport type {SchemaQuery} from '../../zql/src/query/schema-query.ts';\nimport {getServerSchema} from './schema.ts';\n\nexport type CustomMutatorDefs<TDBTransaction> = {\n [namespaceOrKey: string]:\n | CustomMutatorImpl<TDBTransaction>\n | CustomMutatorDefs<TDBTransaction>;\n};\n\nexport type CustomMutatorImpl<\n TDBTransaction,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n TArgs = any,\n Context = unknown,\n> = (tx: TDBTransaction, args: TArgs, ctx: Context) => Promise<void>;\n\n/**\n * QueryDelegate implementation for server-side transactions.\n * Extends QueryDelegateBase to satisfy the QueryDelegate interface,\n * but overrides run() to execute against Postgres and throws on\n * preload()/materialize() which don't make sense server-side.\n */\nclass ServerTransactionQueryDelegate extends QueryDelegateBase {\n readonly #dbTransaction: DBTransaction<unknown>;\n readonly #schema: Schema;\n readonly #serverSchema: ServerSchema;\n\n readonly defaultQueryComplete = true;\n\n constructor(\n dbTransaction: DBTransaction<unknown>,\n schema: Schema,\n serverSchema: ServerSchema,\n ) {\n super();\n this.#dbTransaction = dbTransaction;\n this.#schema = schema;\n this.#serverSchema = serverSchema;\n }\n\n getSource(): never {\n throw new Error('not implemented');\n }\n\n override run<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n >(\n query: Query<TTable, TSchema, TReturn>,\n _options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n const queryInternals = asQueryInternals(query);\n return this.#dbTransaction.runQuery<TReturn>(\n queryInternals.ast,\n queryInternals.format,\n this.#schema,\n this.#serverSchema,\n );\n }\n\n override preload(): never {\n throw new Error('preload() is not supported in server transactions');\n }\n\n override materialize(): never {\n throw new Error('materialize() is not supported in server transactions');\n }\n}\n\nexport class TransactionImpl<TSchema extends Schema, TWrappedTransaction>\n implements ServerTransaction<TSchema, TWrappedTransaction>\n{\n readonly location = 'server';\n readonly reason = 'authoritative';\n readonly dbTransaction: DBTransaction<TWrappedTransaction>;\n readonly clientID: string;\n readonly mutationID: number;\n readonly mutate: SchemaCRUD<TSchema>;\n readonly query: SchemaQuery<TSchema>;\n readonly #schema: TSchema;\n readonly #serverSchema: ServerSchema;\n\n constructor(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n mutate: SchemaCRUD<TSchema>,\n schema: TSchema,\n serverSchema: ServerSchema,\n ) {\n this.dbTransaction = dbTransaction;\n this.clientID = clientID;\n this.mutationID = mutationID;\n this.mutate = mutate;\n this.#schema = schema;\n this.#serverSchema = serverSchema;\n\n const delegate = new ServerTransactionQueryDelegate(\n dbTransaction,\n schema,\n serverSchema,\n );\n this.query = createRunnableBuilder(delegate, schema);\n }\n\n run<TTable extends keyof TSchema['tables'] & string, TReturn>(\n query: Query<TTable, TSchema, TReturn>,\n _options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n const queryInternals = asQueryInternals(query);\n\n // Execute the query using the database-specific executor\n return this.dbTransaction.runQuery<TReturn>(\n queryInternals.ast,\n queryInternals.format,\n this.#schema,\n this.#serverSchema,\n );\n }\n}\n\nconst dbTxSymbol = Symbol();\n\nconst serverSchemaSymbol = Symbol();\n\ntype WithHiddenTxAndSchema = {\n [dbTxSymbol]: DBTransaction<unknown>;\n [serverSchemaSymbol]: ServerSchema;\n};\n\nexport async function makeServerTransaction<\n TSchema extends Schema,\n TWrappedTransaction,\n>(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n schema: TSchema,\n mutate: (\n dbTransaction: DBTransaction<TWrappedTransaction>,\n serverSchema: ServerSchema,\n ) => SchemaCRUD<TSchema>,\n) {\n const serverSchema = await getServerSchema(dbTransaction, schema);\n return new TransactionImpl(\n dbTransaction,\n clientID,\n mutationID,\n mutate(dbTransaction, serverSchema),\n schema,\n serverSchema,\n );\n}\n\nexport function makeSchemaCRUD<S extends Schema>(\n schema: S,\n): (\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n) => SchemaCRUD<S> {\n const schemaCRUDs: Record<string, TableCRUD<TableSchema>> = {};\n for (const tableSchema of Object.values(schema.tables)) {\n schemaCRUDs[tableSchema.name] = makeTableCRUD(tableSchema);\n }\n\n /**\n * For users with very large schemas it is expensive to re-create\n * all the CRUD mutators for each transaction. Instead, we create\n * them all once up-front and then bind them to the transaction\n * as requested.\n */\n class CRUDHandler {\n readonly #dbTransaction: DBTransaction<unknown>;\n readonly #serverSchema: ServerSchema;\n constructor(\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n ) {\n this.#dbTransaction = dbTransaction;\n this.#serverSchema = serverSchema;\n }\n\n get(target: Record<string, TableCRUD<TableSchema>>, prop: string) {\n if (prop in target) {\n return target[prop];\n }\n\n const txHolder: WithHiddenTxAndSchema = {\n [dbTxSymbol]: this.#dbTransaction,\n [serverSchemaSymbol]: this.#serverSchema,\n };\n target[prop] = Object.fromEntries(\n Object.entries(schemaCRUDs[prop]).map(([name, method]) => [\n name,\n method.bind(txHolder),\n ]),\n ) as TableCRUD<TableSchema>;\n\n return target[prop];\n }\n }\n\n return (dbTransaction: DBTransaction<unknown>, serverSchema: ServerSchema) =>\n new Proxy(\n {},\n new CRUDHandler(dbTransaction, serverSchema),\n ) as SchemaCRUD<S>;\n}\n\nfunction removeUndefined<T extends Record<string, unknown>>(value: T): T {\n const valueWithoutUndefined: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (val !== undefined) {\n valueWithoutUndefined[key] = val;\n }\n }\n return valueWithoutUndefined as T;\n}\n\nfunction makeTableCRUD(schema: TableSchema): TableCRUD<TableSchema> {\n return {\n async insert(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const stmt = formatPgInternalConvert(\n sql`INSERT INTO ${sql.ident(serverName(schema))} (${sql.join(\n targetedColumns.map(([, serverName]) => sql.ident(serverName)),\n ',',\n )}) VALUES (${sql.join(\n Object.entries(value).map(([col, v]) =>\n sqlInsertValue(v, serverTableSchema[serverNameFor(col, schema)]),\n ),\n ', ',\n )})`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async upsert(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const primaryKeyColumns = origAndServerNamesFor(\n schema.primaryKey,\n schema,\n );\n const stmt = formatPgInternalConvert(\n sql`INSERT INTO ${sql.ident(serverName(schema))} (${sql.join(\n targetedColumns.map(([, serverName]) => sql.ident(serverName)),\n ',',\n )}) VALUES (${sql.join(\n Object.entries(value).map(([col, val]) =>\n sqlInsertValue(val, serverTableSchema[serverNameFor(col, schema)]),\n ),\n ', ',\n )}) ON CONFLICT (${sql.join(\n primaryKeyColumns.map(([, serverName]) => sql.ident(serverName)),\n ', ',\n )}) DO UPDATE SET ${sql.join(\n Object.entries(value).map(\n ([col, val]) =>\n sql`${sql.ident(\n schema.columns[col].serverName ?? col,\n )} = ${sqlInsertValue(val, serverTableSchema[serverNameFor(col, schema)])}`,\n ),\n ', ',\n )}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async update(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const stmt = formatPgInternalConvert(\n sql`UPDATE ${sql.ident(serverName(schema))} SET ${sql.join(\n targetedColumns.map(\n ([origName, serverName]) =>\n sql`${sql.ident(serverName)} = ${sqlInsertValue(value[origName], serverTableSchema[serverName])}`,\n ),\n ', ',\n )} WHERE ${primaryKeyClause(schema, serverTableSchema, value)}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async delete(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const stmt = formatPgInternalConvert(\n sql`DELETE FROM ${sql.ident(\n serverName(schema),\n )} WHERE ${primaryKeyClause(schema, serverTableSchema, value)}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n };\n}\n\nfunction serverName(x: {name: string; serverName?: string | undefined}) {\n return x.serverName ?? x.name;\n}\n\nfunction primaryKeyClause(\n schema: TableSchema,\n serverTableSchema: ServerTableSchema,\n row: Record<string, unknown>,\n) {\n const primaryKey = origAndServerNamesFor(schema.primaryKey, schema);\n return sql`${sql.join(\n primaryKey.map(\n ([origName, serverName]) =>\n sql`${sql.ident(serverName)}${maybeCastColumn(serverTableSchema[serverName])} = ${sqlValue(row[origName], serverTableSchema[serverName])}`,\n ),\n ' AND ',\n )}`;\n}\n\nfunction maybeCastColumn(col: ServerColumnSchema) {\n if (col.type === 'uuid' || col.isEnum) {\n return sql`::text`;\n }\n return sql``;\n}\n\nfunction origAndServerNamesFor(\n originalNames: readonly string[],\n schema: TableSchema,\n): [origName: string, serverName: string][] {\n return originalNames.map(\n name => [name, serverNameFor(name, schema)] as const,\n );\n}\n\nfunction serverNameFor(originalName: string, schema: TableSchema): string {\n const col = schema.columns[originalName];\n assert(\n col,\n `Column ${originalName} was not found in the Zero schema for the table ${schema.name}`,\n );\n return col.serverName ?? originalName;\n}\n\nfunction sqlValue(value: unknown, serverColumnSchema: ServerColumnSchema) {\n return sqlConvertColumnArg(serverColumnSchema, value, false, true);\n}\n\nfunction sqlInsertValue(\n value: unknown,\n serverColumnSchema: ServerColumnSchema,\n) {\n return sqlConvertColumnArg(serverColumnSchema, value, false, false);\n}\n"],"names":["serverName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"custom.js","sources":["../../../../zero-server/src/custom.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\nimport {mapValues} from '../../shared/src/objects.ts';\nimport {recordProxy} from '../../shared/src/record-proxy.ts';\nimport {\n formatPgInternalConvert,\n sql,\n sqlConvertColumnArg,\n} from '../../z2s/src/sql.ts';\nimport type {TableSchema} from '../../zero-schema/src/table-schema.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {\n ServerColumnSchema,\n ServerSchema,\n ServerTableSchema,\n} from '../../zero-types/src/server-schema.ts';\nimport type {\n DBTransaction,\n SchemaCRUD,\n ServerTransaction,\n TableCRUD,\n} from '../../zql/src/mutate/custom.ts';\nimport {createRunnableBuilder} from '../../zql/src/query/create-builder.ts';\nimport {QueryDelegateBase} from '../../zql/src/query/query-delegate-base.ts';\nimport {asQueryInternals} from '../../zql/src/query/query-internals.ts';\nimport type {\n HumanReadable,\n Query,\n RunOptions,\n} from '../../zql/src/query/query.ts';\nimport type {SchemaQuery} from '../../zql/src/query/schema-query.ts';\nimport {getServerSchema} from './schema.ts';\n\nexport type CustomMutatorDefs<TDBTransaction> = {\n [namespaceOrKey: string]:\n | CustomMutatorImpl<TDBTransaction>\n | CustomMutatorDefs<TDBTransaction>;\n};\n\nexport type CustomMutatorImpl<\n TDBTransaction,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n TArgs = any,\n Context = unknown,\n> = (tx: TDBTransaction, args: TArgs, ctx: Context) => Promise<void>;\n\n/**\n * QueryDelegate implementation for server-side transactions.\n * Extends QueryDelegateBase to satisfy the QueryDelegate interface,\n * but overrides run() to execute against Postgres and throws on\n * preload()/materialize() which don't make sense server-side.\n */\nclass ServerTransactionQueryDelegate extends QueryDelegateBase {\n readonly #dbTransaction: DBTransaction<unknown>;\n readonly #schema: Schema;\n readonly #serverSchema: ServerSchema;\n\n readonly defaultQueryComplete = true;\n\n constructor(\n dbTransaction: DBTransaction<unknown>,\n schema: Schema,\n serverSchema: ServerSchema,\n ) {\n super();\n this.#dbTransaction = dbTransaction;\n this.#schema = schema;\n this.#serverSchema = serverSchema;\n }\n\n getSource(): never {\n throw new Error('not implemented');\n }\n\n override run<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n >(\n query: Query<TTable, TSchema, TReturn>,\n _options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n const queryInternals = asQueryInternals(query);\n return this.#dbTransaction.runQuery<TReturn>(\n queryInternals.ast,\n queryInternals.format,\n this.#schema,\n this.#serverSchema,\n );\n }\n\n override preload(): never {\n throw new Error('preload() is not supported in server transactions');\n }\n\n override materialize(): never {\n throw new Error('materialize() is not supported in server transactions');\n }\n}\n\nexport class TransactionImpl<TSchema extends Schema, TWrappedTransaction>\n implements ServerTransaction<TSchema, TWrappedTransaction>\n{\n readonly location = 'server';\n readonly reason = 'authoritative';\n readonly dbTransaction: DBTransaction<TWrappedTransaction>;\n readonly clientID: string;\n readonly mutationID: number;\n readonly mutate: SchemaCRUD<TSchema>;\n readonly query: SchemaQuery<TSchema>;\n readonly #schema: TSchema;\n readonly #serverSchema: ServerSchema;\n\n constructor(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n mutate: SchemaCRUD<TSchema>,\n schema: TSchema,\n serverSchema: ServerSchema,\n ) {\n this.dbTransaction = dbTransaction;\n this.clientID = clientID;\n this.mutationID = mutationID;\n this.mutate = mutate;\n this.#schema = schema;\n this.#serverSchema = serverSchema;\n\n const delegate = new ServerTransactionQueryDelegate(\n dbTransaction,\n schema,\n serverSchema,\n );\n this.query = createRunnableBuilder(delegate, schema);\n }\n\n run<TTable extends keyof TSchema['tables'] & string, TReturn>(\n query: Query<TTable, TSchema, TReturn>,\n _options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n const queryInternals = asQueryInternals(query);\n\n // Execute the query using the database-specific executor\n return this.dbTransaction.runQuery<TReturn>(\n queryInternals.ast,\n queryInternals.format,\n this.#schema,\n this.#serverSchema,\n );\n }\n}\n\nconst dbTxSymbol = Symbol();\n\nconst serverSchemaSymbol = Symbol();\n\ntype WithHiddenTxAndSchema = {\n [dbTxSymbol]: DBTransaction<unknown>;\n [serverSchemaSymbol]: ServerSchema;\n};\n\nexport async function makeServerTransaction<\n TSchema extends Schema,\n TWrappedTransaction,\n>(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n schema: TSchema,\n mutate: (\n dbTransaction: DBTransaction<TWrappedTransaction>,\n serverSchema: ServerSchema,\n ) => SchemaCRUD<TSchema>,\n) {\n const serverSchema = await getServerSchema(dbTransaction, schema);\n return new TransactionImpl(\n dbTransaction,\n clientID,\n mutationID,\n mutate(dbTransaction, serverSchema),\n schema,\n serverSchema,\n );\n}\n\nexport function makeSchemaCRUD<S extends Schema>(\n schema: S,\n): (\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n) => SchemaCRUD<S> {\n /**\n * For users with very large schemas it is expensive to re-create\n * all the CRUD mutators for each transaction. Instead, we create\n * them all once up-front and then bind them to the transaction\n * as requested.\n */\n const schemaCRUDs: Record<string, TableCRUD<TableSchema>> = {};\n for (const tableSchema of Object.values(schema.tables)) {\n schemaCRUDs[tableSchema.name] = makeTableCRUD(tableSchema);\n }\n\n return (\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n ) => {\n const txHolder: WithHiddenTxAndSchema = {\n [dbTxSymbol]: dbTransaction,\n [serverSchemaSymbol]: serverSchema,\n };\n return recordProxy(schemaCRUDs, tableCRUD =>\n mapValues(tableCRUD, method => method.bind(txHolder)),\n ) as unknown as SchemaCRUD<S>;\n };\n}\n\nfunction removeUndefined<T extends Record<string, unknown>>(value: T): T {\n const valueWithoutUndefined: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (val !== undefined) {\n valueWithoutUndefined[key] = val;\n }\n }\n return valueWithoutUndefined as T;\n}\n\nfunction makeTableCRUD(schema: TableSchema): TableCRUD<TableSchema> {\n return {\n async insert(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const stmt = formatPgInternalConvert(\n sql`INSERT INTO ${sql.ident(serverName(schema))} (${sql.join(\n targetedColumns.map(([, serverName]) => sql.ident(serverName)),\n ',',\n )}) VALUES (${sql.join(\n Object.entries(value).map(([col, v]) =>\n sqlInsertValue(v, serverTableSchema[serverNameFor(col, schema)]),\n ),\n ', ',\n )})`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async upsert(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const primaryKeyColumns = origAndServerNamesFor(\n schema.primaryKey,\n schema,\n );\n const stmt = formatPgInternalConvert(\n sql`INSERT INTO ${sql.ident(serverName(schema))} (${sql.join(\n targetedColumns.map(([, serverName]) => sql.ident(serverName)),\n ',',\n )}) VALUES (${sql.join(\n Object.entries(value).map(([col, val]) =>\n sqlInsertValue(val, serverTableSchema[serverNameFor(col, schema)]),\n ),\n ', ',\n )}) ON CONFLICT (${sql.join(\n primaryKeyColumns.map(([, serverName]) => sql.ident(serverName)),\n ', ',\n )}) DO UPDATE SET ${sql.join(\n Object.entries(value).map(\n ([col, val]) =>\n sql`${sql.ident(\n schema.columns[col].serverName ?? col,\n )} = ${sqlInsertValue(val, serverTableSchema[serverNameFor(col, schema)])}`,\n ),\n ', ',\n )}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async update(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const stmt = formatPgInternalConvert(\n sql`UPDATE ${sql.ident(serverName(schema))} SET ${sql.join(\n targetedColumns.map(\n ([origName, serverName]) =>\n sql`${sql.ident(serverName)} = ${sqlInsertValue(value[origName], serverTableSchema[serverName])}`,\n ),\n ', ',\n )} WHERE ${primaryKeyClause(schema, serverTableSchema, value)}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async delete(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const stmt = formatPgInternalConvert(\n sql`DELETE FROM ${sql.ident(\n serverName(schema),\n )} WHERE ${primaryKeyClause(schema, serverTableSchema, value)}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n };\n}\n\nfunction serverName(x: {name: string; serverName?: string | undefined}) {\n return x.serverName ?? x.name;\n}\n\nfunction primaryKeyClause(\n schema: TableSchema,\n serverTableSchema: ServerTableSchema,\n row: Record<string, unknown>,\n) {\n const primaryKey = origAndServerNamesFor(schema.primaryKey, schema);\n return sql`${sql.join(\n primaryKey.map(\n ([origName, serverName]) =>\n sql`${sql.ident(serverName)}${maybeCastColumn(serverTableSchema[serverName])} = ${sqlValue(row[origName], serverTableSchema[serverName])}`,\n ),\n ' AND ',\n )}`;\n}\n\nfunction maybeCastColumn(col: ServerColumnSchema) {\n if (col.type === 'uuid' || col.isEnum) {\n return sql`::text`;\n }\n return sql``;\n}\n\nfunction origAndServerNamesFor(\n originalNames: readonly string[],\n schema: TableSchema,\n): [origName: string, serverName: string][] {\n return originalNames.map(\n name => [name, serverNameFor(name, schema)] as const,\n );\n}\n\nfunction serverNameFor(originalName: string, schema: TableSchema): string {\n const col = schema.columns[originalName];\n assert(\n col,\n `Column ${originalName} was not found in the Zero schema for the table ${schema.name}`,\n );\n return col.serverName ?? originalName;\n}\n\nfunction sqlValue(value: unknown, serverColumnSchema: ServerColumnSchema) {\n return sqlConvertColumnArg(serverColumnSchema, value, false, true);\n}\n\nfunction sqlInsertValue(\n value: unknown,\n serverColumnSchema: ServerColumnSchema,\n) {\n return sqlConvertColumnArg(serverColumnSchema, value, false, false);\n}\n"],"names":["serverName"],"mappings":";;;;;;;;AAmDA,MAAM,uCAAuC,kBAAkB;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EAEA,uBAAuB;AAAA,EAEhC,YACE,eACA,QACA,cACA;AACA,UAAA;AACA,SAAK,iBAAiB;AACtB,SAAK,UAAU;AACf,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,YAAmB;AACjB,UAAM,IAAI,MAAM,iBAAiB;AAAA,EACnC;AAAA,EAES,IAKP,OACA,UACiC;AACjC,UAAM,iBAAiB,iBAAiB,KAAK;AAC7C,WAAO,KAAK,eAAe;AAAA,MACzB,eAAe;AAAA,MACf,eAAe;AAAA,MACf,KAAK;AAAA,MACL,KAAK;AAAA,IAAA;AAAA,EAET;AAAA,EAES,UAAiB;AACxB,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AAAA,EAES,cAAqB;AAC5B,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACF;AAEO,MAAM,gBAEb;AAAA,EACW,WAAW;AAAA,EACX,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,eACA,UACA,YACA,QACA,QACA,cACA;AACA,SAAK,gBAAgB;AACrB,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,SAAS;AACd,SAAK,UAAU;AACf,SAAK,gBAAgB;AAErB,UAAM,WAAW,IAAI;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAEF,SAAK,QAAQ,sBAAsB,UAAU,MAAM;AAAA,EACrD;AAAA,EAEA,IACE,OACA,UACiC;AACjC,UAAM,iBAAiB,iBAAiB,KAAK;AAG7C,WAAO,KAAK,cAAc;AAAA,MACxB,eAAe;AAAA,MACf,eAAe;AAAA,MACf,KAAK;AAAA,MACL,KAAK;AAAA,IAAA;AAAA,EAET;AACF;AAEA,MAAM,aAAa,OAAA;AAEnB,MAAM,qBAAqB,OAAA;AAO3B,eAAsB,sBAIpB,eACA,UACA,YACA,QACA,QAIA;AACA,QAAM,eAAe,MAAM,gBAAgB,eAAe,MAAM;AAChE,SAAO,IAAI;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,eAAe,YAAY;AAAA,IAClC;AAAA,IACA;AAAA,EAAA;AAEJ;AAEO,SAAS,eACd,QAIiB;AAOjB,QAAM,cAAsD,CAAA;AAC5D,aAAW,eAAe,OAAO,OAAO,OAAO,MAAM,GAAG;AACtD,gBAAY,YAAY,IAAI,IAAI,cAAc,WAAW;AAAA,EAC3D;AAEA,SAAO,CACL,eACA,iBACG;AACH,UAAM,WAAkC;AAAA,MACtC,CAAC,UAAU,GAAG;AAAA,MACd,CAAC,kBAAkB,GAAG;AAAA,IAAA;AAExB,WAAO;AAAA,MAAY;AAAA,MAAa,eAC9B,UAAU,WAAW,YAAU,OAAO,KAAK,QAAQ,CAAC;AAAA,IAAA;AAAA,EAExD;AACF;AAEA,SAAS,gBAAmD,OAAa;AACvE,QAAM,wBAAiD,CAAA;AACvD,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC9C,QAAI,QAAQ,QAAW;AACrB,4BAAsB,GAAG,IAAI;AAAA,IAC/B;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,cAAc,QAA6C;AAClE,SAAO;AAAA,IACL,MAAM,OAAoC,OAAO;AAC/C,cAAQ,gBAAgB,KAAK;AAC7B,YAAM,oBAAoB,KAAK,kBAAkB,EAAE,WAAW,MAAM,CAAC;AAErE,YAAM,kBAAkB,sBAAsB,OAAO,KAAK,KAAK,GAAG,MAAM;AACxE,YAAM,OAAO;AAAA,QACX,kBAAkB,IAAI,MAAM,WAAW,MAAM,CAAC,CAAC,KAAK,IAAI;AAAA,UACtD,gBAAgB,IAAI,CAAC,CAAA,EAAGA,WAAU,MAAM,IAAI,MAAMA,WAAU,CAAC;AAAA,UAC7D;AAAA,QAAA,CACD,aAAa,IAAI;AAAA,UAChB,OAAO,QAAQ,KAAK,EAAE;AAAA,YAAI,CAAC,CAAC,KAAK,CAAC,MAChC,eAAe,GAAG,kBAAkB,cAAc,KAAK,MAAM,CAAC,CAAC;AAAA,UAAA;AAAA,UAEjE;AAAA,QAAA,CACD;AAAA,MAAA;AAEH,YAAM,KAAK,KAAK,UAAU;AAC1B,YAAM,GAAG,MAAM,KAAK,MAAM,KAAK,MAAM;AAAA,IACvC;AAAA,IACA,MAAM,OAAoC,OAAO;AAC/C,cAAQ,gBAAgB,KAAK;AAC7B,YAAM,oBAAoB,KAAK,kBAAkB,EAAE,WAAW,MAAM,CAAC;AACrE,YAAM,kBAAkB,sBAAsB,OAAO,KAAK,KAAK,GAAG,MAAM;AACxE,YAAM,oBAAoB;AAAA,QACxB,OAAO;AAAA,QACP;AAAA,MAAA;AAEF,YAAM,OAAO;AAAA,QACX,kBAAkB,IAAI,MAAM,WAAW,MAAM,CAAC,CAAC,KAAK,IAAI;AAAA,UACtD,gBAAgB,IAAI,CAAC,CAAA,EAAGA,WAAU,MAAM,IAAI,MAAMA,WAAU,CAAC;AAAA,UAC7D;AAAA,QAAA,CACD,aAAa,IAAI;AAAA,UAChB,OAAO,QAAQ,KAAK,EAAE;AAAA,YAAI,CAAC,CAAC,KAAK,GAAG,MAClC,eAAe,KAAK,kBAAkB,cAAc,KAAK,MAAM,CAAC,CAAC;AAAA,UAAA;AAAA,UAEnE;AAAA,QAAA,CACD,kBAAkB,IAAI;AAAA,UACrB,kBAAkB,IAAI,CAAC,CAAA,EAAGA,WAAU,MAAM,IAAI,MAAMA,WAAU,CAAC;AAAA,UAC/D;AAAA,QAAA,CACD,mBAAmB,IAAI;AAAA,UACtB,OAAO,QAAQ,KAAK,EAAE;AAAA,YACpB,CAAC,CAAC,KAAK,GAAG,MACR,MAAM,IAAI;AAAA,cACR,OAAO,QAAQ,GAAG,EAAE,cAAc;AAAA,YAAA,CACnC,MAAM,eAAe,KAAK,kBAAkB,cAAc,KAAK,MAAM,CAAC,CAAC,CAAC;AAAA,UAAA;AAAA,UAE7E;AAAA,QAAA,CACD;AAAA,MAAA;AAEH,YAAM,KAAK,KAAK,UAAU;AAC1B,YAAM,GAAG,MAAM,KAAK,MAAM,KAAK,MAAM;AAAA,IACvC;AAAA,IACA,MAAM,OAAoC,OAAO;AAC/C,cAAQ,gBAAgB,KAAK;AAC7B,YAAM,oBAAoB,KAAK,kBAAkB,EAAE,WAAW,MAAM,CAAC;AACrE,YAAM,kBAAkB,sBAAsB,OAAO,KAAK,KAAK,GAAG,MAAM;AACxE,YAAM,OAAO;AAAA,QACX,aAAa,IAAI,MAAM,WAAW,MAAM,CAAC,CAAC,QAAQ,IAAI;AAAA,UACpD,gBAAgB;AAAA,YACd,CAAC,CAAC,UAAUA,WAAU,MACpB,MAAM,IAAI,MAAMA,WAAU,CAAC,MAAM,eAAe,MAAM,QAAQ,GAAG,kBAAkBA,WAAU,CAAC,CAAC;AAAA,UAAA;AAAA,UAEnG;AAAA,QAAA,CACD,UAAU,iBAAiB,QAAQ,mBAAmB,KAAK,CAAC;AAAA,MAAA;AAE/D,YAAM,KAAK,KAAK,UAAU;AAC1B,YAAM,GAAG,MAAM,KAAK,MAAM,KAAK,MAAM;AAAA,IACvC;AAAA,IACA,MAAM,OAAoC,OAAO;AAC/C,cAAQ,gBAAgB,KAAK;AAC7B,YAAM,oBAAoB,KAAK,kBAAkB,EAAE,WAAW,MAAM,CAAC;AACrE,YAAM,OAAO;AAAA,QACX,kBAAkB,IAAI;AAAA,UACpB,WAAW,MAAM;AAAA,QAAA,CAClB,UAAU,iBAAiB,QAAQ,mBAAmB,KAAK,CAAC;AAAA,MAAA;AAE/D,YAAM,KAAK,KAAK,UAAU;AAC1B,YAAM,GAAG,MAAM,KAAK,MAAM,KAAK,MAAM;AAAA,IACvC;AAAA,EAAA;AAEJ;AAEA,SAAS,WAAW,GAAoD;AACtE,SAAO,EAAE,cAAc,EAAE;AAC3B;AAEA,SAAS,iBACP,QACA,mBACA,KACA;AACA,QAAM,aAAa,sBAAsB,OAAO,YAAY,MAAM;AAClE,SAAO,MAAM,IAAI;AAAA,IACf,WAAW;AAAA,MACT,CAAC,CAAC,UAAUA,WAAU,MACpB,MAAM,IAAI,MAAMA,WAAU,CAAC,GAAG,gBAAgB,kBAAkBA,WAAU,CAAC,CAAC,MAAM,SAAS,IAAI,QAAQ,GAAG,kBAAkBA,WAAU,CAAC,CAAC;AAAA,IAAA;AAAA,IAE5I;AAAA,EAAA,CACD;AACH;AAEA,SAAS,gBAAgB,KAAyB;AAChD,MAAI,IAAI,SAAS,UAAU,IAAI,QAAQ;AACrC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,sBACP,eACA,QAC0C;AAC1C,SAAO,cAAc;AAAA,IACnB,UAAQ,CAAC,MAAM,cAAc,MAAM,MAAM,CAAC;AAAA,EAAA;AAE9C;AAEA,SAAS,cAAc,cAAsB,QAA6B;AACxE,QAAM,MAAM,OAAO,QAAQ,YAAY;AACvC;AAAA,IACE;AAAA,IACA,UAAU,YAAY,mDAAmD,OAAO,IAAI;AAAA,EAAA;AAEtF,SAAO,IAAI,cAAc;AAC3B;AAEA,SAAS,SAAS,OAAgB,oBAAwC;AACxE,SAAO,oBAAoB,oBAAoB,OAAO,OAAO,IAAI;AACnE;AAEA,SAAS,eACP,OACA,oBACA;AACA,SAAO,oBAAoB,oBAAoB,OAAO,OAAO,KAAK;AACpE;"}
|
|
@@ -9,7 +9,7 @@ export declare class SolidView implements Output {
|
|
|
9
9
|
#private;
|
|
10
10
|
constructor(input: Input, onTransactionCommit: (cb: () => void) => void, format: Format, onDestroy: () => void, queryComplete: true | ErroredQuery | Promise<true>, updateTTL: (ttl: TTL) => void, setState: SetStoreFunction<State>, retry: () => void);
|
|
11
11
|
destroy(): void;
|
|
12
|
-
push(change: Change):
|
|
12
|
+
push(change: Change): readonly never[];
|
|
13
13
|
updateTTL(ttl: TTL): void;
|
|
14
14
|
}
|
|
15
15
|
export declare function createSolidViewFactory(setState: SetStoreFunction<State>, retry?: () => void): <TTable extends keyof TSchema["tables"] & string, TSchema extends Schema, TReturn>(_query: Query<TTable, TSchema, TReturn>, input: Input, format: Format, onDestroy: () => void, onTransactionCommit: (cb: () => void) => void, queryComplete: true | ErroredQuery | Promise<true>, updateTTL: (ttl: TTL) => void) => SolidView;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"solid-view.d.ts","sourceRoot":"","sources":["../../../../zero-solid/src/solid-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,gBAAgB,EAAC,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAGL,KAAK,MAAM,EACX,KAAK,KAAK,EACV,KAAK,MAAM,EACX,KAAK,KAAK,EAEV,KAAK,MAAM,EACX,KAAK,KAAK,EACV,KAAK,MAAM,EAEX,KAAK,GAAG,EAET,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAEV,kBAAkB,EACnB,MAAM,6CAA6C,CAAC;AACrD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"solid-view.d.ts","sourceRoot":"","sources":["../../../../zero-solid/src/solid-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,gBAAgB,EAAC,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAGL,KAAK,MAAM,EACX,KAAK,KAAK,EACV,KAAK,MAAM,EACX,KAAK,KAAK,EAEV,KAAK,MAAM,EACX,KAAK,KAAK,EACV,KAAK,MAAM,EAEX,KAAK,GAAG,EAET,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAEV,kBAAkB,EACnB,MAAM,6CAA6C,CAAC;AACrD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,2CAA2C,CAAC;AAK5E,MAAM,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;AAEhD,eAAO,MAAM,QAAQ,EAAE,kBAAsD,CAAC;AAC9E,eAAO,MAAM,OAAO,EAAE,kBAAqD,CAAC;AAE5E,qBAAa,SAAU,YAAW,MAAM;;gBAqBpC,KAAK,EAAE,KAAK,EACZ,mBAAmB,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,EAC7C,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,IAAI,EACrB,aAAa,EAAE,IAAI,GAAG,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,EAClD,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,EAC7B,QAAQ,EAAE,gBAAgB,CAAC,KAAK,CAAC,EACjC,KAAK,EAAE,MAAM,IAAI;IAiEnB,OAAO,IAAI,IAAI;IA2Bf,IAAI,CAAC,MAAM,EAAE,MAAM;IAqDnB,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI;CAG1B;AA8CD,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,gBAAgB,CAAC,KAAK,CAAC,EACjC,KAAK,CAAC,EAAE,MAAM,IAAI,IAGhB,MAAM,SAAS,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,EAC/C,OAAO,SAAS,MAAM,EACtB,OAAO,UAEC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,SAChC,KAAK,UACJ,MAAM,aACH,MAAM,IAAI,uBACA,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,iBAC9B,IAAI,GAAG,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,aACvC,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,eAiBhC"}
|
|
@@ -20,6 +20,7 @@ import "../../shared/src/document-visible.js";
|
|
|
20
20
|
import "../../replicache/src/btree/node.js";
|
|
21
21
|
import "compare-utf8";
|
|
22
22
|
import "../../replicache/src/sync/push.js";
|
|
23
|
+
import { emptyArray } from "../../shared/src/sentinels.js";
|
|
23
24
|
import "../../shared/src/valita.js";
|
|
24
25
|
import "../../zero-protocol/src/connect.js";
|
|
25
26
|
import "../../zero-protocol/src/down.js";
|
|
@@ -133,6 +134,7 @@ class SolidView {
|
|
|
133
134
|
} else {
|
|
134
135
|
this.#pendingChanges.push(materializeRelationships(change));
|
|
135
136
|
}
|
|
137
|
+
return emptyArray;
|
|
136
138
|
}
|
|
137
139
|
#applyChanges(changes, mapper) {
|
|
138
140
|
this.#setState(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"solid-view.js","sources":["../../../../zero-solid/src/solid-view.ts"],"sourcesContent":["import {produce, reconcile, type SetStoreFunction} from 'solid-js/store';\nimport {\n applyChange,\n type AnyViewFactory,\n type Change,\n type Entry,\n type Format,\n type Input,\n type Node,\n type Output,\n type Query,\n type Schema,\n type Stream,\n type TTL,\n type ViewChange,\n} from '../../zero-client/src/mod.js';\nimport type {\n QueryErrorDetails,\n QueryResultDetails,\n} from '../../zero-client/src/types/query-result.ts';\nimport type {ErroredQuery} from '../../zero-protocol/src/custom-queries.ts';\nimport {idSymbol} from '../../zql/src/ivm/view-apply-change.ts';\nimport {skipYields} from '../../zql/src/ivm/operator.ts';\n\nexport type State = [Entry, QueryResultDetails];\n\nexport const COMPLETE: QueryResultDetails = Object.freeze({type: 'complete'});\nexport const UNKNOWN: QueryResultDetails = Object.freeze({type: 'unknown'});\n\nexport class SolidView implements Output {\n readonly #input: Input;\n readonly #format: Format;\n readonly #onDestroy: () => void;\n readonly #retry: () => void;\n\n #setState: SetStoreFunction<State>;\n\n // Optimization: if the store is currently empty we build up\n // the view on a plain old JS object stored at #builderRoot, and return\n // that for the new state on transaction commit. This avoids building up\n // large views from scratch via solid produce. The proxy object used by\n // solid produce is slow and in this case we don't care about solid tracking\n // the fine grained changes (everything has changed, it's all new). For a\n // test case with a view with 3000 rows, each row having 2 children, this\n // optimization reduced #applyChanges time from 743ms to 133ms.\n #builderRoot: Entry | undefined;\n #pendingChanges: ViewChange[] = [];\n readonly #updateTTL: (ttl: TTL) => void;\n\n constructor(\n input: Input,\n onTransactionCommit: (cb: () => void) => void,\n format: Format,\n onDestroy: () => void,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n setState: SetStoreFunction<State>,\n retry: () => void,\n ) {\n this.#input = input;\n onTransactionCommit(this.#onTransactionCommit);\n this.#format = format;\n this.#onDestroy = onDestroy;\n this.#updateTTL = updateTTL;\n this.#retry = retry;\n\n input.setOutput(this);\n\n const initialRoot = this.#createEmptyRoot();\n this.#applyChangesToRoot(\n skipYields(input.fetch({})),\n node => ({type: 'add', node}),\n initialRoot,\n );\n\n this.#setState = setState;\n this.#setState(\n reconcile(\n [\n initialRoot,\n queryComplete === true\n ? COMPLETE\n : 'error' in queryComplete\n ? this.#makeError(queryComplete)\n : UNKNOWN,\n ],\n {\n // solidjs's types want a string, but a symbol works\n key: idSymbol as unknown as string,\n },\n ),\n );\n\n if (isEmptyRoot(initialRoot)) {\n this.#builderRoot = this.#createEmptyRoot();\n }\n\n if (queryComplete !== true && !('error' in queryComplete)) {\n void queryComplete\n .then(() => {\n this.#setState(prev => [prev[0], COMPLETE]);\n })\n .catch((error: ErroredQuery) => {\n this.#setState(prev => [prev[0], this.#makeError(error)]);\n });\n }\n }\n\n #makeError(error: ErroredQuery): QueryErrorDetails {\n const message = error.message ?? 'An unknown error occurred';\n return {\n type: 'error',\n retry: this.#retry,\n refetch: this.#retry,\n error: {\n type: error.error,\n message,\n ...(error.details ? {details: error.details} : {}),\n },\n };\n }\n\n destroy(): void {\n this.#onDestroy();\n }\n\n #onTransactionCommit = () => {\n const builderRoot = this.#builderRoot;\n if (builderRoot) {\n if (!isEmptyRoot(builderRoot)) {\n this.#setState(\n 0,\n reconcile(builderRoot, {\n // solidjs's types want a string, but a symbol works\n key: idSymbol as unknown as string,\n }),\n );\n this.#setState(prev => [builderRoot, prev[1]]);\n this.#builderRoot = undefined;\n }\n } else {\n try {\n this.#applyChanges(this.#pendingChanges, c => c);\n } finally {\n this.#pendingChanges = [];\n }\n }\n };\n\n push(change: Change): void {\n // Delay updating the solid store state until the transaction commit\n // (because each update of the solid store is quite expensive). If\n // this.#builderRoot is defined apply the changes to it (we are building\n // from an empty root), otherwise queue the changes to be applied\n // using produce at the end of the transaction but read the relationships\n // now as they are only valid to read when the push is received.\n if (this.#builderRoot) {\n this.#applyChangeToRoot(change, this.#builderRoot);\n } else {\n this.#pendingChanges.push(materializeRelationships(change));\n }\n }\n\n #applyChanges<T>(changes: Iterable<T>, mapper: (v: T) => ViewChange): void {\n this.#setState(\n produce((draftState: State) => {\n this.#applyChangesToRoot<T>(changes, mapper, draftState[0]);\n if (isEmptyRoot(draftState[0])) {\n this.#builderRoot = this.#createEmptyRoot();\n }\n }),\n );\n }\n\n #applyChangesToRoot<T>(\n changes: Iterable<T>,\n mapper: (v: T) => ViewChange,\n root: Entry,\n ) {\n for (const change of changes) {\n this.#applyChangeToRoot(mapper(change), root);\n }\n }\n\n #applyChangeToRoot(change: ViewChange, root: Entry) {\n applyChange(\n root,\n change,\n this.#input.getSchema(),\n '',\n this.#format,\n true /* withIDs */,\n );\n }\n\n #createEmptyRoot(): Entry {\n return {\n '': this.#format.singular ? undefined : [],\n };\n }\n\n updateTTL(ttl: TTL): void {\n this.#updateTTL(ttl);\n }\n}\n\nfunction materializeRelationships(change: Change): ViewChange {\n switch (change.type) {\n case 'add':\n return {type: 'add', node: materializeNodeRelationships(change.node)};\n case 'remove':\n return {type: 'remove', node: materializeNodeRelationships(change.node)};\n case 'child':\n return {\n type: 'child',\n node: {row: change.node.row},\n child: {\n relationshipName: change.child.relationshipName,\n change: materializeRelationships(change.child.change),\n },\n };\n case 'edit':\n return {\n type: 'edit',\n node: {row: change.node.row},\n oldNode: {row: change.oldNode.row},\n };\n }\n}\n\nfunction materializeNodeRelationships(node: Node): Node {\n const relationships: Record<string, () => Stream<Node>> = {};\n for (const relationship in node.relationships) {\n const materialized: Node[] = [];\n for (const n of skipYields(node.relationships[relationship]())) {\n materialized.push(materializeNodeRelationships(n));\n }\n relationships[relationship] = () => materialized;\n }\n return {\n row: node.row,\n relationships,\n };\n}\n\nfunction isEmptyRoot(entry: Entry) {\n const data = entry[''];\n return data === undefined || (Array.isArray(data) && data.length === 0);\n}\n\nexport function createSolidViewFactory(\n setState: SetStoreFunction<State>,\n retry?: () => void,\n) {\n function solidViewFactory<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n >(\n _query: Query<TTable, TSchema, TReturn>,\n input: Input,\n format: Format,\n onDestroy: () => void,\n onTransactionCommit: (cb: () => void) => void,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n ) {\n return new SolidView(\n input,\n onTransactionCommit,\n format,\n onDestroy,\n queryComplete,\n updateTTL,\n setState,\n retry || (() => {}),\n );\n }\n\n solidViewFactory satisfies AnyViewFactory;\n\n return solidViewFactory;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"solid-view.js","sources":["../../../../zero-solid/src/solid-view.ts"],"sourcesContent":["import {produce, reconcile, type SetStoreFunction} from 'solid-js/store';\nimport {\n applyChange,\n type AnyViewFactory,\n type Change,\n type Entry,\n type Format,\n type Input,\n type Node,\n type Output,\n type Query,\n type Schema,\n type Stream,\n type TTL,\n type ViewChange,\n} from '../../zero-client/src/mod.js';\nimport type {\n QueryErrorDetails,\n QueryResultDetails,\n} from '../../zero-client/src/types/query-result.ts';\nimport type {ErroredQuery} from '../../zero-protocol/src/custom-queries.ts';\nimport {idSymbol} from '../../zql/src/ivm/view-apply-change.ts';\nimport {skipYields} from '../../zql/src/ivm/operator.ts';\nimport {emptyArray} from '../../shared/src/sentinels.ts';\n\nexport type State = [Entry, QueryResultDetails];\n\nexport const COMPLETE: QueryResultDetails = Object.freeze({type: 'complete'});\nexport const UNKNOWN: QueryResultDetails = Object.freeze({type: 'unknown'});\n\nexport class SolidView implements Output {\n readonly #input: Input;\n readonly #format: Format;\n readonly #onDestroy: () => void;\n readonly #retry: () => void;\n\n #setState: SetStoreFunction<State>;\n\n // Optimization: if the store is currently empty we build up\n // the view on a plain old JS object stored at #builderRoot, and return\n // that for the new state on transaction commit. This avoids building up\n // large views from scratch via solid produce. The proxy object used by\n // solid produce is slow and in this case we don't care about solid tracking\n // the fine grained changes (everything has changed, it's all new). For a\n // test case with a view with 3000 rows, each row having 2 children, this\n // optimization reduced #applyChanges time from 743ms to 133ms.\n #builderRoot: Entry | undefined;\n #pendingChanges: ViewChange[] = [];\n readonly #updateTTL: (ttl: TTL) => void;\n\n constructor(\n input: Input,\n onTransactionCommit: (cb: () => void) => void,\n format: Format,\n onDestroy: () => void,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n setState: SetStoreFunction<State>,\n retry: () => void,\n ) {\n this.#input = input;\n onTransactionCommit(this.#onTransactionCommit);\n this.#format = format;\n this.#onDestroy = onDestroy;\n this.#updateTTL = updateTTL;\n this.#retry = retry;\n\n input.setOutput(this);\n\n const initialRoot = this.#createEmptyRoot();\n this.#applyChangesToRoot(\n skipYields(input.fetch({})),\n node => ({type: 'add', node}),\n initialRoot,\n );\n\n this.#setState = setState;\n this.#setState(\n reconcile(\n [\n initialRoot,\n queryComplete === true\n ? COMPLETE\n : 'error' in queryComplete\n ? this.#makeError(queryComplete)\n : UNKNOWN,\n ],\n {\n // solidjs's types want a string, but a symbol works\n key: idSymbol as unknown as string,\n },\n ),\n );\n\n if (isEmptyRoot(initialRoot)) {\n this.#builderRoot = this.#createEmptyRoot();\n }\n\n if (queryComplete !== true && !('error' in queryComplete)) {\n void queryComplete\n .then(() => {\n this.#setState(prev => [prev[0], COMPLETE]);\n })\n .catch((error: ErroredQuery) => {\n this.#setState(prev => [prev[0], this.#makeError(error)]);\n });\n }\n }\n\n #makeError(error: ErroredQuery): QueryErrorDetails {\n const message = error.message ?? 'An unknown error occurred';\n return {\n type: 'error',\n retry: this.#retry,\n refetch: this.#retry,\n error: {\n type: error.error,\n message,\n ...(error.details ? {details: error.details} : {}),\n },\n };\n }\n\n destroy(): void {\n this.#onDestroy();\n }\n\n #onTransactionCommit = () => {\n const builderRoot = this.#builderRoot;\n if (builderRoot) {\n if (!isEmptyRoot(builderRoot)) {\n this.#setState(\n 0,\n reconcile(builderRoot, {\n // solidjs's types want a string, but a symbol works\n key: idSymbol as unknown as string,\n }),\n );\n this.#setState(prev => [builderRoot, prev[1]]);\n this.#builderRoot = undefined;\n }\n } else {\n try {\n this.#applyChanges(this.#pendingChanges, c => c);\n } finally {\n this.#pendingChanges = [];\n }\n }\n };\n\n push(change: Change) {\n // Delay updating the solid store state until the transaction commit\n // (because each update of the solid store is quite expensive). If\n // this.#builderRoot is defined apply the changes to it (we are building\n // from an empty root), otherwise queue the changes to be applied\n // using produce at the end of the transaction but read the relationships\n // now as they are only valid to read when the push is received.\n if (this.#builderRoot) {\n this.#applyChangeToRoot(change, this.#builderRoot);\n } else {\n this.#pendingChanges.push(materializeRelationships(change));\n }\n return emptyArray;\n }\n\n #applyChanges<T>(changes: Iterable<T>, mapper: (v: T) => ViewChange): void {\n this.#setState(\n produce((draftState: State) => {\n this.#applyChangesToRoot<T>(changes, mapper, draftState[0]);\n if (isEmptyRoot(draftState[0])) {\n this.#builderRoot = this.#createEmptyRoot();\n }\n }),\n );\n }\n\n #applyChangesToRoot<T>(\n changes: Iterable<T>,\n mapper: (v: T) => ViewChange,\n root: Entry,\n ) {\n for (const change of changes) {\n this.#applyChangeToRoot(mapper(change), root);\n }\n }\n\n #applyChangeToRoot(change: ViewChange, root: Entry) {\n applyChange(\n root,\n change,\n this.#input.getSchema(),\n '',\n this.#format,\n true /* withIDs */,\n );\n }\n\n #createEmptyRoot(): Entry {\n return {\n '': this.#format.singular ? undefined : [],\n };\n }\n\n updateTTL(ttl: TTL): void {\n this.#updateTTL(ttl);\n }\n}\n\nfunction materializeRelationships(change: Change): ViewChange {\n switch (change.type) {\n case 'add':\n return {type: 'add', node: materializeNodeRelationships(change.node)};\n case 'remove':\n return {type: 'remove', node: materializeNodeRelationships(change.node)};\n case 'child':\n return {\n type: 'child',\n node: {row: change.node.row},\n child: {\n relationshipName: change.child.relationshipName,\n change: materializeRelationships(change.child.change),\n },\n };\n case 'edit':\n return {\n type: 'edit',\n node: {row: change.node.row},\n oldNode: {row: change.oldNode.row},\n };\n }\n}\n\nfunction materializeNodeRelationships(node: Node): Node {\n const relationships: Record<string, () => Stream<Node>> = {};\n for (const relationship in node.relationships) {\n const materialized: Node[] = [];\n for (const n of skipYields(node.relationships[relationship]())) {\n materialized.push(materializeNodeRelationships(n));\n }\n relationships[relationship] = () => materialized;\n }\n return {\n row: node.row,\n relationships,\n };\n}\n\nfunction isEmptyRoot(entry: Entry) {\n const data = entry[''];\n return data === undefined || (Array.isArray(data) && data.length === 0);\n}\n\nexport function createSolidViewFactory(\n setState: SetStoreFunction<State>,\n retry?: () => void,\n) {\n function solidViewFactory<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n >(\n _query: Query<TTable, TSchema, TReturn>,\n input: Input,\n format: Format,\n onDestroy: () => void,\n onTransactionCommit: (cb: () => void) => void,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n ) {\n return new SolidView(\n input,\n onTransactionCommit,\n format,\n onDestroy,\n queryComplete,\n updateTTL,\n setState,\n retry || (() => {}),\n );\n }\n\n solidViewFactory satisfies AnyViewFactory;\n\n return solidViewFactory;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -36,17 +36,17 @@ export type Schema = {
|
|
|
36
36
|
/**
|
|
37
37
|
* Enables legacy query support.
|
|
38
38
|
* When this is true, old-style queries that do not require server side implementations will be enabled.
|
|
39
|
-
*
|
|
39
|
+
* What we currently call "custom queries" will become "queries" and
|
|
40
40
|
* the only option for reading data.
|
|
41
|
-
* The default is
|
|
41
|
+
* The default is false.
|
|
42
42
|
*/
|
|
43
43
|
readonly enableLegacyQueries?: boolean | undefined;
|
|
44
44
|
/**
|
|
45
45
|
* Enables legacy mutator support.
|
|
46
46
|
* When this is true, old-style mutations that do not require server side implementations will be enabled.
|
|
47
|
-
*
|
|
47
|
+
* What we currently call "custom mutations" will become "mutations" and
|
|
48
48
|
* the only option for writing data.
|
|
49
|
-
* The default is
|
|
49
|
+
* The default is false.
|
|
50
50
|
*/
|
|
51
51
|
readonly enableLegacyMutators?: boolean | undefined;
|
|
52
52
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../../../zql/src/builder/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../../../zql/src/builder/builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { unreachable, assert } from "../../../shared/src/asserts.js";
|
|
2
2
|
import { must } from "../../../shared/src/must.js";
|
|
3
|
-
import { PlannerException } from "../error.js";
|
|
4
3
|
import { Exists } from "../ivm/exists.js";
|
|
5
4
|
import { FanIn } from "../ivm/fan-in.js";
|
|
6
5
|
import { FanOut } from "../ivm/fan-out.js";
|
|
@@ -22,16 +21,7 @@ function buildPipeline(ast, delegate, queryID, costModel, lc, planDebugger) {
|
|
|
22
21
|
(tableName) => must(delegate.getSource(tableName)).tableSchema.primaryKey
|
|
23
22
|
);
|
|
24
23
|
if (costModel) {
|
|
25
|
-
|
|
26
|
-
ast = planQuery(ast, costModel, planDebugger);
|
|
27
|
-
} catch (e) {
|
|
28
|
-
if (e instanceof PlannerException) {
|
|
29
|
-
const message = `Query planner failed (${e.kind}), falling back to unoptimized query: ${e.message}`;
|
|
30
|
-
lc?.warn?.(message);
|
|
31
|
-
} else {
|
|
32
|
-
throw e;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
24
|
+
ast = planQuery(ast, costModel, planDebugger, lc);
|
|
35
25
|
}
|
|
36
26
|
return buildPipelineInternal(ast, delegate, queryID, "");
|
|
37
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.js","sources":["../../../../../zql/src/builder/builder.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {JSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {PlannerException} from '../error.ts';\nimport type {\n AST,\n ColumnReference,\n CompoundKey,\n Condition,\n Conjunction,\n CorrelatedSubquery,\n CorrelatedSubqueryCondition,\n Disjunction,\n LiteralValue,\n Ordering,\n Parameter,\n SimpleCondition,\n ValuePosition,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport {Exists} from '../ivm/exists.ts';\nimport {FanIn} from '../ivm/fan-in.ts';\nimport {FanOut} from '../ivm/fan-out.ts';\nimport {\n buildFilterPipeline,\n type FilterInput,\n} from '../ivm/filter-operators.ts';\nimport {Filter} from '../ivm/filter.ts';\nimport {FlippedJoin} from '../ivm/flipped-join.ts';\nimport {Join} from '../ivm/join.ts';\nimport type {Input, InputBase, Storage} from '../ivm/operator.ts';\nimport {Skip} from '../ivm/skip.ts';\nimport type {Source, SourceInput} from '../ivm/source.ts';\nimport {Take} from '../ivm/take.ts';\nimport {UnionFanIn} from '../ivm/union-fan-in.ts';\nimport {UnionFanOut} from '../ivm/union-fan-out.ts';\nimport {planQuery} from '../planner/planner-builder.ts';\nimport type {ConnectionCostModel} from '../planner/planner-connection.ts';\nimport {completeOrdering} from '../query/complete-ordering.ts';\nimport type {PlanDebugger} from '../planner/planner-debug.ts';\nimport type {DebugDelegate} from './debug-delegate.ts';\nimport {createPredicate, type NoSubqueryCondition} from './filter.ts';\n\nexport type StaticQueryParameters = {\n authData: Record<string, JSONValue>;\n preMutationRow?: Row | undefined;\n};\n\n/**\n * Interface required of caller to buildPipeline. Connects to constructed\n * pipeline to delegate environment to provide sources and storage.\n */\nexport interface BuilderDelegate {\n readonly applyFiltersAnyway?: boolean | undefined;\n debug?: DebugDelegate | undefined;\n\n /**\n * When true, allows NOT EXISTS conditions in queries.\n * Defaults to false.\n *\n * We only set this to true on the server.\n * The client-side query engine cannot support NOT EXISTS because:\n * 1. Zero only syncs a subset of data to the client\n * 2. On the client, we can't distinguish between a row not existing vs.\n * a row not being synced to the client\n * 3. NOT EXISTS requires complete knowledge of what doesn't exist\n */\n readonly enableNotExists?: boolean | undefined;\n\n /**\n * Called once for each source needed by the AST.\n * Might be called multiple times with same tableName. It is OK to return\n * same storage instance in that case.\n */\n getSource(tableName: string): Source | undefined;\n\n /**\n * Called once for each operator that requires storage. Should return a new\n * unique storage object for each call.\n */\n createStorage(name: string): Storage;\n\n decorateInput(input: Input, name: string): Input;\n\n addEdge(source: InputBase, dest: InputBase): void;\n\n decorateFilterInput(input: FilterInput, name: string): FilterInput;\n\n decorateSourceInput(input: SourceInput, queryID: string): Input;\n\n /**\n * The AST is mapped on-the-wire between client and server names.\n *\n * There is no \"wire\" for zqlite tests so this function is provided\n * to allow tests to remap the AST.\n */\n mapAst?: ((ast: AST) => AST) | undefined;\n}\n\n/**\n * Builds a pipeline from an AST. Caller must provide a delegate to create source\n * and storage interfaces as necessary.\n *\n * Usage:\n *\n * ```ts\n * class MySink implements Output {\n * readonly #input: Input;\n *\n * constructor(input: Input) {\n * this.#input = input;\n * input.setOutput(this);\n * }\n *\n * push(change: Change, _: Operator) {\n * console.log(change);\n * }\n * }\n *\n * const input = buildPipeline(ast, myDelegate, hash(ast));\n * const sink = new MySink(input);\n * ```\n */\nexport function buildPipeline(\n ast: AST,\n delegate: BuilderDelegate,\n queryID: string,\n costModel?: ConnectionCostModel,\n lc?: LogContext,\n planDebugger?: PlanDebugger,\n): Input {\n ast = delegate.mapAst ? delegate.mapAst(ast) : ast;\n ast = completeOrdering(\n ast,\n tableName => must(delegate.getSource(tableName)).tableSchema.primaryKey,\n );\n if (costModel) {\n try {\n ast = planQuery(ast, costModel, planDebugger);\n } catch (e) {\n // If the planner fails (e.g., too many joins), fall back to the\n // unoptimized query rather than failing the entire query.\n if (e instanceof PlannerException) {\n const message = `Query planner failed (${e.kind}), falling back to unoptimized query: ${e.message}`;\n lc?.warn?.(message);\n } else {\n // Re-throw unexpected errors\n throw e;\n }\n }\n }\n return buildPipelineInternal(ast, delegate, queryID, '');\n}\n\nexport function bindStaticParameters(\n ast: AST,\n staticQueryParameters: StaticQueryParameters | undefined,\n) {\n const visit = (node: AST): AST => ({\n ...node,\n where: node.where ? bindCondition(node.where) : undefined,\n related: node.related?.map(sq => ({\n ...sq,\n subquery: visit(sq.subquery),\n })),\n });\n\n function bindCondition(condition: Condition): Condition {\n if (condition.type === 'simple') {\n return {\n ...condition,\n left: bindValue(condition.left),\n right: bindValue(condition.right) as Exclude<\n ValuePosition,\n ColumnReference\n >,\n };\n }\n if (condition.type === 'correlatedSubquery') {\n return {\n ...condition,\n related: {\n ...condition.related,\n subquery: visit(condition.related.subquery),\n },\n };\n }\n return {\n ...condition,\n conditions: condition.conditions.map(bindCondition),\n };\n }\n\n const bindValue = (value: ValuePosition): ValuePosition => {\n if (isParameter(value)) {\n const anchor = must(\n staticQueryParameters,\n 'Static query params do not exist',\n )[value.anchor];\n const resolvedValue = resolveField(anchor, value.field);\n return {\n type: 'literal',\n value: resolvedValue as LiteralValue,\n };\n }\n return value;\n };\n\n return visit(ast);\n}\n\nfunction resolveField(\n anchor: Record<string, JSONValue> | Row | undefined,\n field: string | string[],\n): unknown {\n if (anchor === undefined) {\n return null;\n }\n\n if (Array.isArray(field)) {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n return field.reduce((acc, f) => (acc as any)?.[f], anchor) ?? null;\n }\n\n return anchor[field] ?? null;\n}\n\nfunction isParameter(value: ValuePosition): value is Parameter {\n return value.type === 'static';\n}\n\nconst EXISTS_LIMIT = 3;\nconst PERMISSIONS_EXISTS_LIMIT = 1;\n\n/**\n * Checks if a condition tree contains any NOT EXISTS operations.\n * Recursively checks AND/OR branches but does not recurse into nested subqueries\n * (those are checked when buildPipelineInternal processes them).\n */\nexport function assertNoNotExists(condition: Condition): void {\n switch (condition.type) {\n case 'simple':\n return;\n\n case 'correlatedSubquery':\n if (condition.op === 'NOT EXISTS') {\n throw new Error(\n 'not(exists()) is not supported on the client - see https://bugs.rocicorp.dev/issue/3438',\n );\n }\n return;\n\n case 'and':\n case 'or':\n for (const c of condition.conditions) {\n assertNoNotExists(c);\n }\n return;\n default:\n unreachable(condition);\n }\n}\n\nfunction buildPipelineInternal(\n ast: AST,\n delegate: BuilderDelegate,\n queryID: string,\n name: string,\n partitionKey?: CompoundKey,\n): Input {\n const source = delegate.getSource(ast.table);\n if (!source) {\n throw new Error(`Source not found: ${ast.table}`);\n }\n ast = uniquifyCorrelatedSubqueryConditionAliases(ast);\n\n if (!delegate.enableNotExists && ast.where) {\n assertNoNotExists(ast.where);\n }\n\n const csqConditions = gatherCorrelatedSubqueryQueryConditions(ast.where);\n const splitEditKeys: Set<string> = partitionKey\n ? new Set(partitionKey)\n : new Set();\n const aliases = new Set<string>();\n for (const csq of csqConditions) {\n aliases.add(csq.related.subquery.alias || '');\n for (const key of csq.related.correlation.parentField) {\n splitEditKeys.add(key);\n }\n }\n if (ast.related) {\n for (const csq of ast.related) {\n for (const key of csq.correlation.parentField) {\n splitEditKeys.add(key);\n }\n }\n }\n const conn = source.connect(\n must(ast.orderBy),\n ast.where,\n splitEditKeys,\n delegate.debug,\n );\n\n let end: Input = delegate.decorateSourceInput(conn, queryID);\n end = delegate.decorateInput(end, `${name}:source(${ast.table})`);\n const {fullyAppliedFilters} = conn;\n\n if (ast.start) {\n const skip = new Skip(end, ast.start);\n delegate.addEdge(end, skip);\n end = delegate.decorateInput(skip, `${name}:skip)`);\n }\n\n for (const csqCondition of csqConditions) {\n // flipped EXISTS are handled in applyWhere\n if (!csqCondition.flip) {\n end = applyCorrelatedSubQuery(\n {\n ...csqCondition.related,\n subquery: {\n ...csqCondition.related.subquery,\n limit:\n csqCondition.related.system === 'permissions'\n ? PERMISSIONS_EXISTS_LIMIT\n : EXISTS_LIMIT,\n },\n },\n delegate,\n queryID,\n end,\n name,\n true,\n );\n }\n }\n\n if (ast.where && (!fullyAppliedFilters || delegate.applyFiltersAnyway)) {\n end = applyWhere(end, ast.where, delegate, name);\n }\n\n if (ast.limit !== undefined) {\n const takeName = `${name}:take`;\n const take = new Take(\n end,\n delegate.createStorage(takeName),\n ast.limit,\n partitionKey,\n );\n delegate.addEdge(end, take);\n end = delegate.decorateInput(take, takeName);\n }\n\n if (ast.related) {\n for (const csq of ast.related) {\n end = applyCorrelatedSubQuery(csq, delegate, queryID, end, name, false);\n }\n }\n\n return end;\n}\n\nfunction applyWhere(\n input: Input,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n): Input {\n if (!conditionIncludesFlippedSubqueryAtAnyLevel(condition)) {\n return buildFilterPipeline(input, delegate, filterInput =>\n applyFilter(filterInput, condition, delegate, name),\n );\n }\n\n return applyFilterWithFlips(input, condition, delegate, name);\n}\n\nfunction applyFilterWithFlips(\n input: Input,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n): Input {\n let end = input;\n assert(condition.type !== 'simple', 'Simple conditions cannot have flips');\n\n switch (condition.type) {\n case 'and': {\n const [withFlipped, withoutFlipped] = partitionBranches(\n condition.conditions,\n conditionIncludesFlippedSubqueryAtAnyLevel,\n );\n if (withoutFlipped.length > 0) {\n end = buildFilterPipeline(input, delegate, filterInput =>\n applyAnd(\n filterInput,\n {\n type: 'and',\n conditions: withoutFlipped,\n },\n delegate,\n name,\n ),\n );\n }\n assert(withFlipped.length > 0, 'Impossible to have no flips here');\n for (const cond of withFlipped) {\n end = applyFilterWithFlips(end, cond, delegate, name);\n }\n break;\n }\n case 'or': {\n const [withFlipped, withoutFlipped] = partitionBranches(\n condition.conditions,\n conditionIncludesFlippedSubqueryAtAnyLevel,\n );\n assert(withFlipped.length > 0, 'Impossible to have no flips here');\n\n const ufo = new UnionFanOut(end);\n delegate.addEdge(end, ufo);\n end = delegate.decorateInput(ufo, `${name}:ufo`);\n\n const branches: Input[] = [];\n if (withoutFlipped.length > 0) {\n branches.push(\n buildFilterPipeline(end, delegate, filterInput =>\n applyOr(\n filterInput,\n {\n type: 'or',\n conditions: withoutFlipped,\n },\n delegate,\n name,\n ),\n ),\n );\n }\n\n for (const cond of withFlipped) {\n branches.push(applyFilterWithFlips(end, cond, delegate, name));\n }\n\n const ufi = new UnionFanIn(ufo, branches);\n for (const branch of branches) {\n delegate.addEdge(branch, ufi);\n }\n end = delegate.decorateInput(ufi, `${name}:ufi`);\n\n break;\n }\n case 'correlatedSubquery': {\n const sq = condition.related;\n const child = buildPipelineInternal(\n sq.subquery,\n delegate,\n '',\n `${name}.${sq.subquery.alias}`,\n sq.correlation.childField,\n );\n const flippedJoin = new FlippedJoin({\n parent: end,\n child,\n parentKey: sq.correlation.parentField,\n childKey: sq.correlation.childField,\n relationshipName: must(\n sq.subquery.alias,\n 'Subquery must have an alias',\n ),\n hidden: sq.hidden ?? false,\n system: sq.system ?? 'client',\n });\n delegate.addEdge(end, flippedJoin);\n delegate.addEdge(child, flippedJoin);\n end = delegate.decorateInput(\n flippedJoin,\n `${name}:flipped-join(${sq.subquery.alias})`,\n );\n break;\n }\n }\n\n return end;\n}\n\nfunction applyFilter(\n input: FilterInput,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n) {\n switch (condition.type) {\n case 'and':\n return applyAnd(input, condition, delegate, name);\n case 'or':\n return applyOr(input, condition, delegate, name);\n case 'correlatedSubquery':\n return applyCorrelatedSubqueryCondition(input, condition, delegate, name);\n case 'simple':\n return applySimpleCondition(input, delegate, condition);\n }\n}\n\nfunction applyAnd(\n input: FilterInput,\n condition: Conjunction,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n for (const subCondition of condition.conditions) {\n input = applyFilter(input, subCondition, delegate, name);\n }\n return input;\n}\n\nexport function applyOr(\n input: FilterInput,\n condition: Disjunction,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n const [subqueryConditions, otherConditions] =\n groupSubqueryConditions(condition);\n // if there are no subquery conditions, no fan-in / fan-out is needed\n if (subqueryConditions.length === 0) {\n const filter = new Filter(\n input,\n createPredicate({\n type: 'or',\n conditions: otherConditions,\n }),\n );\n delegate.addEdge(input, filter);\n return filter;\n }\n\n const fanOut = new FanOut(input);\n delegate.addEdge(input, fanOut);\n const branches = subqueryConditions.map(subCondition =>\n applyFilter(fanOut, subCondition, delegate, name),\n );\n if (otherConditions.length > 0) {\n const filter = new Filter(\n fanOut,\n createPredicate({\n type: 'or',\n conditions: otherConditions,\n }),\n );\n delegate.addEdge(fanOut, filter);\n branches.push(filter);\n }\n const ret = new FanIn(fanOut, branches);\n for (const branch of branches) {\n delegate.addEdge(branch, ret);\n }\n fanOut.setFanIn(ret);\n return ret;\n}\n\nexport function groupSubqueryConditions(condition: Disjunction) {\n const partitioned: [\n subqueryConditions: Condition[],\n otherConditions: NoSubqueryCondition[],\n ] = [[], []];\n for (const subCondition of condition.conditions) {\n if (isNotAndDoesNotContainSubquery(subCondition)) {\n partitioned[1].push(subCondition);\n } else {\n partitioned[0].push(subCondition);\n }\n }\n return partitioned;\n}\n\nexport function isNotAndDoesNotContainSubquery(\n condition: Condition,\n): condition is NoSubqueryCondition {\n if (condition.type === 'correlatedSubquery') {\n return false;\n }\n if (condition.type === 'simple') {\n return true;\n }\n return condition.conditions.every(isNotAndDoesNotContainSubquery);\n}\n\nfunction applySimpleCondition(\n input: FilterInput,\n delegate: BuilderDelegate,\n condition: SimpleCondition,\n): FilterInput {\n const filter = new Filter(input, createPredicate(condition));\n delegate.decorateFilterInput(\n filter,\n `${valuePosName(condition.left)}:${condition.op}:${valuePosName(condition.right)}`,\n );\n delegate.addEdge(input, filter);\n return filter;\n}\n\nfunction valuePosName(left: ValuePosition) {\n switch (left.type) {\n case 'static':\n return left.field;\n case 'literal':\n return left.value;\n case 'column':\n return left.name;\n }\n}\n\nfunction applyCorrelatedSubQuery(\n sq: CorrelatedSubquery,\n delegate: BuilderDelegate,\n queryID: string,\n end: Input,\n name: string,\n fromCondition: boolean,\n) {\n // TODO: we only omit the join if the CSQ if from a condition since\n // we want to create an empty array for `related` fields that are `limit(0)`\n if (sq.subquery.limit === 0 && fromCondition) {\n return end;\n }\n\n assert(sq.subquery.alias, 'Subquery must have an alias');\n const child = buildPipelineInternal(\n sq.subquery,\n delegate,\n queryID,\n `${name}.${sq.subquery.alias}`,\n sq.correlation.childField,\n );\n\n const joinName = `${name}:join(${sq.subquery.alias})`;\n const join = new Join({\n parent: end,\n child,\n parentKey: sq.correlation.parentField,\n childKey: sq.correlation.childField,\n relationshipName: sq.subquery.alias,\n hidden: sq.hidden ?? false,\n system: sq.system ?? 'client',\n });\n delegate.addEdge(end, join);\n delegate.addEdge(child, join);\n return delegate.decorateInput(join, joinName);\n}\n\nfunction applyCorrelatedSubqueryCondition(\n input: FilterInput,\n condition: CorrelatedSubqueryCondition,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n assert(condition.op === 'EXISTS' || condition.op === 'NOT EXISTS');\n if (condition.related.subquery.limit === 0) {\n if (condition.op === 'EXISTS') {\n const filter = new Filter(input, () => false);\n delegate.addEdge(input, filter);\n return filter;\n }\n const filter = new Filter(input, () => true);\n delegate.addEdge(input, filter);\n return filter;\n }\n const existsName = `${name}:exists(${condition.related.subquery.alias})`;\n const exists = new Exists(\n input,\n must(condition.related.subquery.alias),\n condition.related.correlation.parentField,\n condition.op,\n );\n delegate.addEdge(input, exists);\n return delegate.decorateFilterInput(exists, existsName);\n}\n\nfunction gatherCorrelatedSubqueryQueryConditions(\n condition: Condition | undefined,\n) {\n const csqs: CorrelatedSubqueryCondition[] = [];\n const gather = (condition: Condition) => {\n if (condition.type === 'correlatedSubquery') {\n csqs.push(condition);\n return;\n }\n if (condition.type === 'and' || condition.type === 'or') {\n for (const c of condition.conditions) {\n gather(c);\n }\n return;\n }\n };\n if (condition) {\n gather(condition);\n }\n return csqs;\n}\n\nexport function assertOrderingIncludesPK(\n ordering: Ordering,\n pk: PrimaryKey,\n): void {\n // oxlint-disable-next-line unicorn/prefer-set-has -- Array is more appropriate here for small collections\n const orderingFields = ordering.map(([field]) => field);\n const missingFields = pk.filter(pkField => !orderingFields.includes(pkField));\n\n if (missingFields.length > 0) {\n throw new Error(\n `Ordering must include all primary key fields. Missing: ${missingFields.join(\n ', ',\n )}. ZQL automatically appends primary key fields to the ordering if they are missing \n so a common cause of this error is a casing mismatch between Postgres and ZQL.\n E.g., \"userid\" vs \"userID\".\n You may want to add double-quotes around your Postgres column names to prevent Postgres from lower-casing them:\n https://www.postgresql.org/docs/current/sql-syntax-lexical.htm`,\n );\n }\n}\n\nfunction uniquifyCorrelatedSubqueryConditionAliases(ast: AST): AST {\n if (!ast.where) {\n return ast;\n }\n const {where} = ast;\n if (where.type !== 'and' && where.type !== 'or') {\n return ast;\n }\n\n let count = 0;\n const uniquifyCorrelatedSubquery = (csqc: CorrelatedSubqueryCondition) => ({\n ...csqc,\n related: {\n ...csqc.related,\n subquery: {\n ...csqc.related.subquery,\n alias: (csqc.related.subquery.alias ?? '') + '_' + count++,\n },\n },\n });\n\n const uniquify = (cond: Condition): Condition => {\n if (cond.type === 'simple') {\n return cond;\n } else if (cond.type === 'correlatedSubquery') {\n return uniquifyCorrelatedSubquery(cond);\n }\n const conditions = [];\n for (const c of cond.conditions) {\n conditions.push(uniquify(c));\n }\n return {\n type: cond.type,\n conditions,\n };\n };\n\n const result = {\n ...ast,\n where: uniquify(where),\n };\n return result;\n}\n\nexport function conditionIncludesFlippedSubqueryAtAnyLevel(\n cond: Condition,\n): boolean {\n if (cond.type === 'correlatedSubquery') {\n return !!cond.flip;\n }\n if (cond.type === 'and' || cond.type === 'or') {\n return cond.conditions.some(c =>\n conditionIncludesFlippedSubqueryAtAnyLevel(c),\n );\n }\n return false;\n}\n\nexport function partitionBranches(\n conditions: readonly Condition[],\n predicate: (c: Condition) => boolean,\n) {\n const matched: Condition[] = [];\n const notMatched: Condition[] = [];\n for (const c of conditions) {\n if (predicate(c)) {\n matched.push(c);\n } else {\n notMatched.push(c);\n }\n }\n return [matched, notMatched] as const;\n}\n"],"names":["filter","condition"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"builder.js","sources":["../../../../../zql/src/builder/builder.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {JSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {\n AST,\n ColumnReference,\n CompoundKey,\n Condition,\n Conjunction,\n CorrelatedSubquery,\n CorrelatedSubqueryCondition,\n Disjunction,\n LiteralValue,\n Ordering,\n Parameter,\n SimpleCondition,\n ValuePosition,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport {Exists} from '../ivm/exists.ts';\nimport {FanIn} from '../ivm/fan-in.ts';\nimport {FanOut} from '../ivm/fan-out.ts';\nimport {\n buildFilterPipeline,\n type FilterInput,\n} from '../ivm/filter-operators.ts';\nimport {Filter} from '../ivm/filter.ts';\nimport {FlippedJoin} from '../ivm/flipped-join.ts';\nimport {Join} from '../ivm/join.ts';\nimport type {Input, InputBase, Storage} from '../ivm/operator.ts';\nimport {Skip} from '../ivm/skip.ts';\nimport type {Source, SourceInput} from '../ivm/source.ts';\nimport {Take} from '../ivm/take.ts';\nimport {UnionFanIn} from '../ivm/union-fan-in.ts';\nimport {UnionFanOut} from '../ivm/union-fan-out.ts';\nimport {planQuery} from '../planner/planner-builder.ts';\nimport type {ConnectionCostModel} from '../planner/planner-connection.ts';\nimport {completeOrdering} from '../query/complete-ordering.ts';\nimport type {PlanDebugger} from '../planner/planner-debug.ts';\nimport type {DebugDelegate} from './debug-delegate.ts';\nimport {createPredicate, type NoSubqueryCondition} from './filter.ts';\n\nexport type StaticQueryParameters = {\n authData: Record<string, JSONValue>;\n preMutationRow?: Row | undefined;\n};\n\n/**\n * Interface required of caller to buildPipeline. Connects to constructed\n * pipeline to delegate environment to provide sources and storage.\n */\nexport interface BuilderDelegate {\n readonly applyFiltersAnyway?: boolean | undefined;\n debug?: DebugDelegate | undefined;\n\n /**\n * When true, allows NOT EXISTS conditions in queries.\n * Defaults to false.\n *\n * We only set this to true on the server.\n * The client-side query engine cannot support NOT EXISTS because:\n * 1. Zero only syncs a subset of data to the client\n * 2. On the client, we can't distinguish between a row not existing vs.\n * a row not being synced to the client\n * 3. NOT EXISTS requires complete knowledge of what doesn't exist\n */\n readonly enableNotExists?: boolean | undefined;\n\n /**\n * Called once for each source needed by the AST.\n * Might be called multiple times with same tableName. It is OK to return\n * same storage instance in that case.\n */\n getSource(tableName: string): Source | undefined;\n\n /**\n * Called once for each operator that requires storage. Should return a new\n * unique storage object for each call.\n */\n createStorage(name: string): Storage;\n\n decorateInput(input: Input, name: string): Input;\n\n addEdge(source: InputBase, dest: InputBase): void;\n\n decorateFilterInput(input: FilterInput, name: string): FilterInput;\n\n decorateSourceInput(input: SourceInput, queryID: string): Input;\n\n /**\n * The AST is mapped on-the-wire between client and server names.\n *\n * There is no \"wire\" for zqlite tests so this function is provided\n * to allow tests to remap the AST.\n */\n mapAst?: ((ast: AST) => AST) | undefined;\n}\n\n/**\n * Builds a pipeline from an AST. Caller must provide a delegate to create source\n * and storage interfaces as necessary.\n *\n * Usage:\n *\n * ```ts\n * class MySink implements Output {\n * readonly #input: Input;\n *\n * constructor(input: Input) {\n * this.#input = input;\n * input.setOutput(this);\n * }\n *\n * push(change: Change, _: Operator) {\n * console.log(change);\n * }\n * }\n *\n * const input = buildPipeline(ast, myDelegate, hash(ast));\n * const sink = new MySink(input);\n * ```\n */\nexport function buildPipeline(\n ast: AST,\n delegate: BuilderDelegate,\n queryID: string,\n costModel?: ConnectionCostModel,\n lc?: LogContext,\n planDebugger?: PlanDebugger,\n): Input {\n ast = delegate.mapAst ? delegate.mapAst(ast) : ast;\n ast = completeOrdering(\n ast,\n tableName => must(delegate.getSource(tableName)).tableSchema.primaryKey,\n );\n if (costModel) {\n ast = planQuery(ast, costModel, planDebugger, lc);\n }\n return buildPipelineInternal(ast, delegate, queryID, '');\n}\n\nexport function bindStaticParameters(\n ast: AST,\n staticQueryParameters: StaticQueryParameters | undefined,\n) {\n const visit = (node: AST): AST => ({\n ...node,\n where: node.where ? bindCondition(node.where) : undefined,\n related: node.related?.map(sq => ({\n ...sq,\n subquery: visit(sq.subquery),\n })),\n });\n\n function bindCondition(condition: Condition): Condition {\n if (condition.type === 'simple') {\n return {\n ...condition,\n left: bindValue(condition.left),\n right: bindValue(condition.right) as Exclude<\n ValuePosition,\n ColumnReference\n >,\n };\n }\n if (condition.type === 'correlatedSubquery') {\n return {\n ...condition,\n related: {\n ...condition.related,\n subquery: visit(condition.related.subquery),\n },\n };\n }\n return {\n ...condition,\n conditions: condition.conditions.map(bindCondition),\n };\n }\n\n const bindValue = (value: ValuePosition): ValuePosition => {\n if (isParameter(value)) {\n const anchor = must(\n staticQueryParameters,\n 'Static query params do not exist',\n )[value.anchor];\n const resolvedValue = resolveField(anchor, value.field);\n return {\n type: 'literal',\n value: resolvedValue as LiteralValue,\n };\n }\n return value;\n };\n\n return visit(ast);\n}\n\nfunction resolveField(\n anchor: Record<string, JSONValue> | Row | undefined,\n field: string | string[],\n): unknown {\n if (anchor === undefined) {\n return null;\n }\n\n if (Array.isArray(field)) {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n return field.reduce((acc, f) => (acc as any)?.[f], anchor) ?? null;\n }\n\n return anchor[field] ?? null;\n}\n\nfunction isParameter(value: ValuePosition): value is Parameter {\n return value.type === 'static';\n}\n\nconst EXISTS_LIMIT = 3;\nconst PERMISSIONS_EXISTS_LIMIT = 1;\n\n/**\n * Checks if a condition tree contains any NOT EXISTS operations.\n * Recursively checks AND/OR branches but does not recurse into nested subqueries\n * (those are checked when buildPipelineInternal processes them).\n */\nexport function assertNoNotExists(condition: Condition): void {\n switch (condition.type) {\n case 'simple':\n return;\n\n case 'correlatedSubquery':\n if (condition.op === 'NOT EXISTS') {\n throw new Error(\n 'not(exists()) is not supported on the client - see https://bugs.rocicorp.dev/issue/3438',\n );\n }\n return;\n\n case 'and':\n case 'or':\n for (const c of condition.conditions) {\n assertNoNotExists(c);\n }\n return;\n default:\n unreachable(condition);\n }\n}\n\nfunction buildPipelineInternal(\n ast: AST,\n delegate: BuilderDelegate,\n queryID: string,\n name: string,\n partitionKey?: CompoundKey,\n): Input {\n const source = delegate.getSource(ast.table);\n if (!source) {\n throw new Error(`Source not found: ${ast.table}`);\n }\n ast = uniquifyCorrelatedSubqueryConditionAliases(ast);\n\n if (!delegate.enableNotExists && ast.where) {\n assertNoNotExists(ast.where);\n }\n\n const csqConditions = gatherCorrelatedSubqueryQueryConditions(ast.where);\n const splitEditKeys: Set<string> = partitionKey\n ? new Set(partitionKey)\n : new Set();\n const aliases = new Set<string>();\n for (const csq of csqConditions) {\n aliases.add(csq.related.subquery.alias || '');\n for (const key of csq.related.correlation.parentField) {\n splitEditKeys.add(key);\n }\n }\n if (ast.related) {\n for (const csq of ast.related) {\n for (const key of csq.correlation.parentField) {\n splitEditKeys.add(key);\n }\n }\n }\n const conn = source.connect(\n must(ast.orderBy),\n ast.where,\n splitEditKeys,\n delegate.debug,\n );\n\n let end: Input = delegate.decorateSourceInput(conn, queryID);\n end = delegate.decorateInput(end, `${name}:source(${ast.table})`);\n const {fullyAppliedFilters} = conn;\n\n if (ast.start) {\n const skip = new Skip(end, ast.start);\n delegate.addEdge(end, skip);\n end = delegate.decorateInput(skip, `${name}:skip)`);\n }\n\n for (const csqCondition of csqConditions) {\n // flipped EXISTS are handled in applyWhere\n if (!csqCondition.flip) {\n end = applyCorrelatedSubQuery(\n {\n ...csqCondition.related,\n subquery: {\n ...csqCondition.related.subquery,\n limit:\n csqCondition.related.system === 'permissions'\n ? PERMISSIONS_EXISTS_LIMIT\n : EXISTS_LIMIT,\n },\n },\n delegate,\n queryID,\n end,\n name,\n true,\n );\n }\n }\n\n if (ast.where && (!fullyAppliedFilters || delegate.applyFiltersAnyway)) {\n end = applyWhere(end, ast.where, delegate, name);\n }\n\n if (ast.limit !== undefined) {\n const takeName = `${name}:take`;\n const take = new Take(\n end,\n delegate.createStorage(takeName),\n ast.limit,\n partitionKey,\n );\n delegate.addEdge(end, take);\n end = delegate.decorateInput(take, takeName);\n }\n\n if (ast.related) {\n for (const csq of ast.related) {\n end = applyCorrelatedSubQuery(csq, delegate, queryID, end, name, false);\n }\n }\n\n return end;\n}\n\nfunction applyWhere(\n input: Input,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n): Input {\n if (!conditionIncludesFlippedSubqueryAtAnyLevel(condition)) {\n return buildFilterPipeline(input, delegate, filterInput =>\n applyFilter(filterInput, condition, delegate, name),\n );\n }\n\n return applyFilterWithFlips(input, condition, delegate, name);\n}\n\nfunction applyFilterWithFlips(\n input: Input,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n): Input {\n let end = input;\n assert(condition.type !== 'simple', 'Simple conditions cannot have flips');\n\n switch (condition.type) {\n case 'and': {\n const [withFlipped, withoutFlipped] = partitionBranches(\n condition.conditions,\n conditionIncludesFlippedSubqueryAtAnyLevel,\n );\n if (withoutFlipped.length > 0) {\n end = buildFilterPipeline(input, delegate, filterInput =>\n applyAnd(\n filterInput,\n {\n type: 'and',\n conditions: withoutFlipped,\n },\n delegate,\n name,\n ),\n );\n }\n assert(withFlipped.length > 0, 'Impossible to have no flips here');\n for (const cond of withFlipped) {\n end = applyFilterWithFlips(end, cond, delegate, name);\n }\n break;\n }\n case 'or': {\n const [withFlipped, withoutFlipped] = partitionBranches(\n condition.conditions,\n conditionIncludesFlippedSubqueryAtAnyLevel,\n );\n assert(withFlipped.length > 0, 'Impossible to have no flips here');\n\n const ufo = new UnionFanOut(end);\n delegate.addEdge(end, ufo);\n end = delegate.decorateInput(ufo, `${name}:ufo`);\n\n const branches: Input[] = [];\n if (withoutFlipped.length > 0) {\n branches.push(\n buildFilterPipeline(end, delegate, filterInput =>\n applyOr(\n filterInput,\n {\n type: 'or',\n conditions: withoutFlipped,\n },\n delegate,\n name,\n ),\n ),\n );\n }\n\n for (const cond of withFlipped) {\n branches.push(applyFilterWithFlips(end, cond, delegate, name));\n }\n\n const ufi = new UnionFanIn(ufo, branches);\n for (const branch of branches) {\n delegate.addEdge(branch, ufi);\n }\n end = delegate.decorateInput(ufi, `${name}:ufi`);\n\n break;\n }\n case 'correlatedSubquery': {\n const sq = condition.related;\n const child = buildPipelineInternal(\n sq.subquery,\n delegate,\n '',\n `${name}.${sq.subquery.alias}`,\n sq.correlation.childField,\n );\n const flippedJoin = new FlippedJoin({\n parent: end,\n child,\n parentKey: sq.correlation.parentField,\n childKey: sq.correlation.childField,\n relationshipName: must(\n sq.subquery.alias,\n 'Subquery must have an alias',\n ),\n hidden: sq.hidden ?? false,\n system: sq.system ?? 'client',\n });\n delegate.addEdge(end, flippedJoin);\n delegate.addEdge(child, flippedJoin);\n end = delegate.decorateInput(\n flippedJoin,\n `${name}:flipped-join(${sq.subquery.alias})`,\n );\n break;\n }\n }\n\n return end;\n}\n\nfunction applyFilter(\n input: FilterInput,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n) {\n switch (condition.type) {\n case 'and':\n return applyAnd(input, condition, delegate, name);\n case 'or':\n return applyOr(input, condition, delegate, name);\n case 'correlatedSubquery':\n return applyCorrelatedSubqueryCondition(input, condition, delegate, name);\n case 'simple':\n return applySimpleCondition(input, delegate, condition);\n }\n}\n\nfunction applyAnd(\n input: FilterInput,\n condition: Conjunction,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n for (const subCondition of condition.conditions) {\n input = applyFilter(input, subCondition, delegate, name);\n }\n return input;\n}\n\nexport function applyOr(\n input: FilterInput,\n condition: Disjunction,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n const [subqueryConditions, otherConditions] =\n groupSubqueryConditions(condition);\n // if there are no subquery conditions, no fan-in / fan-out is needed\n if (subqueryConditions.length === 0) {\n const filter = new Filter(\n input,\n createPredicate({\n type: 'or',\n conditions: otherConditions,\n }),\n );\n delegate.addEdge(input, filter);\n return filter;\n }\n\n const fanOut = new FanOut(input);\n delegate.addEdge(input, fanOut);\n const branches = subqueryConditions.map(subCondition =>\n applyFilter(fanOut, subCondition, delegate, name),\n );\n if (otherConditions.length > 0) {\n const filter = new Filter(\n fanOut,\n createPredicate({\n type: 'or',\n conditions: otherConditions,\n }),\n );\n delegate.addEdge(fanOut, filter);\n branches.push(filter);\n }\n const ret = new FanIn(fanOut, branches);\n for (const branch of branches) {\n delegate.addEdge(branch, ret);\n }\n fanOut.setFanIn(ret);\n return ret;\n}\n\nexport function groupSubqueryConditions(condition: Disjunction) {\n const partitioned: [\n subqueryConditions: Condition[],\n otherConditions: NoSubqueryCondition[],\n ] = [[], []];\n for (const subCondition of condition.conditions) {\n if (isNotAndDoesNotContainSubquery(subCondition)) {\n partitioned[1].push(subCondition);\n } else {\n partitioned[0].push(subCondition);\n }\n }\n return partitioned;\n}\n\nexport function isNotAndDoesNotContainSubquery(\n condition: Condition,\n): condition is NoSubqueryCondition {\n if (condition.type === 'correlatedSubquery') {\n return false;\n }\n if (condition.type === 'simple') {\n return true;\n }\n return condition.conditions.every(isNotAndDoesNotContainSubquery);\n}\n\nfunction applySimpleCondition(\n input: FilterInput,\n delegate: BuilderDelegate,\n condition: SimpleCondition,\n): FilterInput {\n const filter = new Filter(input, createPredicate(condition));\n delegate.decorateFilterInput(\n filter,\n `${valuePosName(condition.left)}:${condition.op}:${valuePosName(condition.right)}`,\n );\n delegate.addEdge(input, filter);\n return filter;\n}\n\nfunction valuePosName(left: ValuePosition) {\n switch (left.type) {\n case 'static':\n return left.field;\n case 'literal':\n return left.value;\n case 'column':\n return left.name;\n }\n}\n\nfunction applyCorrelatedSubQuery(\n sq: CorrelatedSubquery,\n delegate: BuilderDelegate,\n queryID: string,\n end: Input,\n name: string,\n fromCondition: boolean,\n) {\n // TODO: we only omit the join if the CSQ if from a condition since\n // we want to create an empty array for `related` fields that are `limit(0)`\n if (sq.subquery.limit === 0 && fromCondition) {\n return end;\n }\n\n assert(sq.subquery.alias, 'Subquery must have an alias');\n const child = buildPipelineInternal(\n sq.subquery,\n delegate,\n queryID,\n `${name}.${sq.subquery.alias}`,\n sq.correlation.childField,\n );\n\n const joinName = `${name}:join(${sq.subquery.alias})`;\n const join = new Join({\n parent: end,\n child,\n parentKey: sq.correlation.parentField,\n childKey: sq.correlation.childField,\n relationshipName: sq.subquery.alias,\n hidden: sq.hidden ?? false,\n system: sq.system ?? 'client',\n });\n delegate.addEdge(end, join);\n delegate.addEdge(child, join);\n return delegate.decorateInput(join, joinName);\n}\n\nfunction applyCorrelatedSubqueryCondition(\n input: FilterInput,\n condition: CorrelatedSubqueryCondition,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n assert(condition.op === 'EXISTS' || condition.op === 'NOT EXISTS');\n if (condition.related.subquery.limit === 0) {\n if (condition.op === 'EXISTS') {\n const filter = new Filter(input, () => false);\n delegate.addEdge(input, filter);\n return filter;\n }\n const filter = new Filter(input, () => true);\n delegate.addEdge(input, filter);\n return filter;\n }\n const existsName = `${name}:exists(${condition.related.subquery.alias})`;\n const exists = new Exists(\n input,\n must(condition.related.subquery.alias),\n condition.related.correlation.parentField,\n condition.op,\n );\n delegate.addEdge(input, exists);\n return delegate.decorateFilterInput(exists, existsName);\n}\n\nfunction gatherCorrelatedSubqueryQueryConditions(\n condition: Condition | undefined,\n) {\n const csqs: CorrelatedSubqueryCondition[] = [];\n const gather = (condition: Condition) => {\n if (condition.type === 'correlatedSubquery') {\n csqs.push(condition);\n return;\n }\n if (condition.type === 'and' || condition.type === 'or') {\n for (const c of condition.conditions) {\n gather(c);\n }\n return;\n }\n };\n if (condition) {\n gather(condition);\n }\n return csqs;\n}\n\nexport function assertOrderingIncludesPK(\n ordering: Ordering,\n pk: PrimaryKey,\n): void {\n // oxlint-disable-next-line unicorn/prefer-set-has -- Array is more appropriate here for small collections\n const orderingFields = ordering.map(([field]) => field);\n const missingFields = pk.filter(pkField => !orderingFields.includes(pkField));\n\n if (missingFields.length > 0) {\n throw new Error(\n `Ordering must include all primary key fields. Missing: ${missingFields.join(\n ', ',\n )}. ZQL automatically appends primary key fields to the ordering if they are missing \n so a common cause of this error is a casing mismatch between Postgres and ZQL.\n E.g., \"userid\" vs \"userID\".\n You may want to add double-quotes around your Postgres column names to prevent Postgres from lower-casing them:\n https://www.postgresql.org/docs/current/sql-syntax-lexical.htm`,\n );\n }\n}\n\nfunction uniquifyCorrelatedSubqueryConditionAliases(ast: AST): AST {\n if (!ast.where) {\n return ast;\n }\n const {where} = ast;\n if (where.type !== 'and' && where.type !== 'or') {\n return ast;\n }\n\n let count = 0;\n const uniquifyCorrelatedSubquery = (csqc: CorrelatedSubqueryCondition) => ({\n ...csqc,\n related: {\n ...csqc.related,\n subquery: {\n ...csqc.related.subquery,\n alias: (csqc.related.subquery.alias ?? '') + '_' + count++,\n },\n },\n });\n\n const uniquify = (cond: Condition): Condition => {\n if (cond.type === 'simple') {\n return cond;\n } else if (cond.type === 'correlatedSubquery') {\n return uniquifyCorrelatedSubquery(cond);\n }\n const conditions = [];\n for (const c of cond.conditions) {\n conditions.push(uniquify(c));\n }\n return {\n type: cond.type,\n conditions,\n };\n };\n\n const result = {\n ...ast,\n where: uniquify(where),\n };\n return result;\n}\n\nexport function conditionIncludesFlippedSubqueryAtAnyLevel(\n cond: Condition,\n): boolean {\n if (cond.type === 'correlatedSubquery') {\n return !!cond.flip;\n }\n if (cond.type === 'and' || cond.type === 'or') {\n return cond.conditions.some(c =>\n conditionIncludesFlippedSubqueryAtAnyLevel(c),\n );\n }\n return false;\n}\n\nexport function partitionBranches(\n conditions: readonly Condition[],\n predicate: (c: Condition) => boolean,\n) {\n const matched: Condition[] = [];\n const notMatched: Condition[] = [];\n for (const c of conditions) {\n if (predicate(c)) {\n matched.push(c);\n } else {\n notMatched.push(c);\n }\n }\n return [matched, notMatched] as const;\n}\n"],"names":["filter","condition"],"mappings":"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"}
|
package/out/zql/src/error.js
CHANGED
|
@@ -4,16 +4,7 @@ class NotImplementedError extends Error {
|
|
|
4
4
|
this.name = "NotImplementedError";
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
|
-
class PlannerException extends Error {
|
|
8
|
-
kind;
|
|
9
|
-
constructor(kind, message) {
|
|
10
|
-
super(message);
|
|
11
|
-
this.name = "PlannerException";
|
|
12
|
-
this.kind = kind;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
7
|
export {
|
|
16
|
-
NotImplementedError
|
|
17
|
-
PlannerException
|
|
8
|
+
NotImplementedError
|
|
18
9
|
};
|
|
19
10
|
//# sourceMappingURL=error.js.map
|
package/out/zql/src/error.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","sources":["../../../../zql/src/error.ts"],"sourcesContent":["export class NotImplementedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NotImplementedError';\n }\n}\n\nexport type PlannerExceptionKind = 'max_flippable_joins';\n\nexport class PlannerException extends Error {\n readonly kind: PlannerExceptionKind;\n\n constructor(kind: PlannerExceptionKind, message: string) {\n super(message);\n this.name = 'PlannerException';\n this.kind = kind;\n }\n}\n"],"names":[],"mappings":"AAAO,MAAM,4BAA4B,MAAM;AAAA,EAC7C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;
|
|
1
|
+
{"version":3,"file":"error.js","sources":["../../../../zql/src/error.ts"],"sourcesContent":["export class NotImplementedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NotImplementedError';\n }\n}\n\nexport type PlannerExceptionKind = 'max_flippable_joins';\n\nexport class PlannerException extends Error {\n readonly kind: PlannerExceptionKind;\n\n constructor(kind: PlannerExceptionKind, message: string) {\n super(message);\n this.name = 'PlannerException';\n this.kind = kind;\n }\n}\n"],"names":[],"mappings":"AAAO,MAAM,4BAA4B,MAAM;AAAA,EAC7C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;"}
|
|
@@ -22,7 +22,7 @@ export declare class ArrayView<V extends View> implements Output, TypedView<V> {
|
|
|
22
22
|
get data(): V;
|
|
23
23
|
addListener(listener: Listener<V>): () => void;
|
|
24
24
|
destroy(): void;
|
|
25
|
-
push(change: Change):
|
|
25
|
+
push(change: Change): readonly never[];
|
|
26
26
|
flush(): void;
|
|
27
27
|
updateTTL(ttl: TTL): void;
|
|
28
28
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array-view.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/array-view.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"array-view.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/array-view.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,8CAA8C,CAAC;AAC/E,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,iBAAiB,CAAC;AACzC,OAAO,KAAK,EAAC,QAAQ,EAAc,SAAS,EAAC,MAAM,wBAAwB,CAAC;AAC5E,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAAa,KAAK,KAAK,EAAE,KAAK,MAAM,EAAC,MAAM,eAAe,CAAC;AAGlE,OAAO,KAAK,EAAQ,MAAM,EAAE,IAAI,EAAC,MAAM,WAAW,CAAC;AAEnD;;;;;;;;;;GAUG;AACH,qBAAa,SAAS,CAAC,CAAC,SAAS,IAAI,CAAE,YAAW,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;;IAUpE,SAAS,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;gBAQlC,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,IAAI,GAAG,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,EAClD,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI;IA6B/B,IAAI,IAAI,IACmB,CAAC,CAC3B;IAED,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAqBjC,OAAO;IAkBP,IAAI,CAAC,MAAM,EAAE,MAAM;IAMnB,KAAK;IAQL,SAAS,CAAC,GAAG,EAAE,GAAG;CAGnB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { assert } from "../../../shared/src/asserts.js";
|
|
2
|
+
import { emptyArray } from "../../../shared/src/sentinels.js";
|
|
2
3
|
import { skipYields } from "./operator.js";
|
|
3
4
|
import { applyChange } from "./view-apply-change.js";
|
|
4
5
|
class ArrayView {
|
|
@@ -76,6 +77,7 @@ class ArrayView {
|
|
|
76
77
|
push(change) {
|
|
77
78
|
this.#dirty = true;
|
|
78
79
|
applyChange(this.#root, change, this.#schema, "", this.#format);
|
|
80
|
+
return emptyArray;
|
|
79
81
|
}
|
|
80
82
|
flush() {
|
|
81
83
|
if (!this.#dirty) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array-view.js","sources":["../../../../../zql/src/ivm/array-view.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {Immutable} from '../../../shared/src/immutable.ts';\nimport type {ErroredQuery} from '../../../zero-protocol/src/custom-queries.ts';\nimport type {TTL} from '../query/ttl.ts';\nimport type {Listener, ResultType, TypedView} from '../query/typed-view.ts';\nimport type {Change} from './change.ts';\nimport {skipYields, type Input, type Output} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {applyChange} from './view-apply-change.ts';\nimport type {Entry, Format, View} from './view.ts';\n\n/**\n * Implements a materialized view of the output of an operator.\n *\n * It might seem more efficient to use an immutable b-tree for the\n * materialization, but it's not so clear. Inserts in the middle are\n * asymptotically slower in an array, but can often be done with zero\n * allocations, where changes to the b-tree will often require several allocs.\n *\n * Also the plain array view is more convenient for consumers since you can dump\n * it into console to see what it is, rather than having to iterate it.\n */\nexport class ArrayView<V extends View> implements Output, TypedView<V> {\n readonly #input: Input;\n readonly #listeners = new Set<Listener<V>>();\n readonly #schema: SourceSchema;\n readonly #format: Format;\n\n // Synthetic \"root\" entry that has a single \"\" relationship, so that we can\n // treat all changes, including the root change, generically.\n readonly #root: Entry;\n\n onDestroy: (() => void) | undefined;\n\n #dirty = false;\n #resultType: ResultType = 'unknown';\n #error: ErroredQuery | undefined;\n readonly #updateTTL: (ttl: TTL) => void;\n\n constructor(\n input: Input,\n format: Format,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n ) {\n this.#input = input;\n this.#schema = input.getSchema();\n this.#format = format;\n this.#updateTTL = updateTTL;\n this.#root = {'': format.singular ? undefined : []};\n input.setOutput(this);\n\n if (queryComplete === true) {\n this.#resultType = 'complete';\n } else if ('error' in queryComplete) {\n this.#resultType = 'error';\n this.#error = queryComplete;\n } else {\n void queryComplete\n .then(() => {\n this.#resultType = 'complete';\n this.#fireListeners();\n })\n .catch(e => {\n this.#resultType = 'error';\n this.#error = e;\n this.#fireListeners();\n });\n }\n this.#hydrate();\n }\n\n get data() {\n return this.#root[''] as V;\n }\n\n addListener(listener: Listener<V>) {\n assert(!this.#listeners.has(listener), 'Listener already registered');\n this.#listeners.add(listener);\n\n this.#fireListener(listener);\n\n return () => {\n this.#listeners.delete(listener);\n };\n }\n\n #fireListeners() {\n for (const listener of this.#listeners) {\n this.#fireListener(listener);\n }\n }\n\n #fireListener(listener: Listener<V>) {\n listener(this.data as Immutable<V>, this.#resultType, this.#error);\n }\n\n destroy() {\n this.onDestroy?.();\n }\n\n #hydrate() {\n this.#dirty = true;\n for (const node of skipYields(this.#input.fetch({}))) {\n applyChange(\n this.#root,\n {type: 'add', node},\n this.#schema,\n '',\n this.#format,\n );\n }\n this.flush();\n }\n\n push(change: Change)
|
|
1
|
+
{"version":3,"file":"array-view.js","sources":["../../../../../zql/src/ivm/array-view.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {Immutable} from '../../../shared/src/immutable.ts';\nimport {emptyArray} from '../../../shared/src/sentinels.ts';\nimport type {ErroredQuery} from '../../../zero-protocol/src/custom-queries.ts';\nimport type {TTL} from '../query/ttl.ts';\nimport type {Listener, ResultType, TypedView} from '../query/typed-view.ts';\nimport type {Change} from './change.ts';\nimport {skipYields, type Input, type Output} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {applyChange} from './view-apply-change.ts';\nimport type {Entry, Format, View} from './view.ts';\n\n/**\n * Implements a materialized view of the output of an operator.\n *\n * It might seem more efficient to use an immutable b-tree for the\n * materialization, but it's not so clear. Inserts in the middle are\n * asymptotically slower in an array, but can often be done with zero\n * allocations, where changes to the b-tree will often require several allocs.\n *\n * Also the plain array view is more convenient for consumers since you can dump\n * it into console to see what it is, rather than having to iterate it.\n */\nexport class ArrayView<V extends View> implements Output, TypedView<V> {\n readonly #input: Input;\n readonly #listeners = new Set<Listener<V>>();\n readonly #schema: SourceSchema;\n readonly #format: Format;\n\n // Synthetic \"root\" entry that has a single \"\" relationship, so that we can\n // treat all changes, including the root change, generically.\n readonly #root: Entry;\n\n onDestroy: (() => void) | undefined;\n\n #dirty = false;\n #resultType: ResultType = 'unknown';\n #error: ErroredQuery | undefined;\n readonly #updateTTL: (ttl: TTL) => void;\n\n constructor(\n input: Input,\n format: Format,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n ) {\n this.#input = input;\n this.#schema = input.getSchema();\n this.#format = format;\n this.#updateTTL = updateTTL;\n this.#root = {'': format.singular ? undefined : []};\n input.setOutput(this);\n\n if (queryComplete === true) {\n this.#resultType = 'complete';\n } else if ('error' in queryComplete) {\n this.#resultType = 'error';\n this.#error = queryComplete;\n } else {\n void queryComplete\n .then(() => {\n this.#resultType = 'complete';\n this.#fireListeners();\n })\n .catch(e => {\n this.#resultType = 'error';\n this.#error = e;\n this.#fireListeners();\n });\n }\n this.#hydrate();\n }\n\n get data() {\n return this.#root[''] as V;\n }\n\n addListener(listener: Listener<V>) {\n assert(!this.#listeners.has(listener), 'Listener already registered');\n this.#listeners.add(listener);\n\n this.#fireListener(listener);\n\n return () => {\n this.#listeners.delete(listener);\n };\n }\n\n #fireListeners() {\n for (const listener of this.#listeners) {\n this.#fireListener(listener);\n }\n }\n\n #fireListener(listener: Listener<V>) {\n listener(this.data as Immutable<V>, this.#resultType, this.#error);\n }\n\n destroy() {\n this.onDestroy?.();\n }\n\n #hydrate() {\n this.#dirty = true;\n for (const node of skipYields(this.#input.fetch({}))) {\n applyChange(\n this.#root,\n {type: 'add', node},\n this.#schema,\n '',\n this.#format,\n );\n }\n this.flush();\n }\n\n push(change: Change) {\n this.#dirty = true;\n applyChange(this.#root, change, this.#schema, '', this.#format);\n return emptyArray;\n }\n\n flush() {\n if (!this.#dirty) {\n return;\n }\n this.#dirty = false;\n this.#fireListeners();\n }\n\n updateTTL(ttl: TTL) {\n this.#updateTTL(ttl);\n }\n}\n"],"names":[],"mappings":";;;;AAuBO,MAAM,UAA0D;AAAA,EAC5D;AAAA,EACA,iCAAiB,IAAA;AAAA,EACjB;AAAA,EACA;AAAA;AAAA;AAAA,EAIA;AAAA,EAET;AAAA,EAEA,SAAS;AAAA,EACT,cAA0B;AAAA,EAC1B;AAAA,EACS;AAAA,EAET,YACE,OACA,QACA,eACA,WACA;AACA,SAAK,SAAS;AACd,SAAK,UAAU,MAAM,UAAA;AACrB,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,QAAQ,EAAC,IAAI,OAAO,WAAW,SAAY,GAAC;AACjD,UAAM,UAAU,IAAI;AAEpB,QAAI,kBAAkB,MAAM;AAC1B,WAAK,cAAc;AAAA,IACrB,WAAW,WAAW,eAAe;AACnC,WAAK,cAAc;AACnB,WAAK,SAAS;AAAA,IAChB,OAAO;AACL,WAAK,cACF,KAAK,MAAM;AACV,aAAK,cAAc;AACnB,aAAK,eAAA;AAAA,MACP,CAAC,EACA,MAAM,CAAA,MAAK;AACV,aAAK,cAAc;AACnB,aAAK,SAAS;AACd,aAAK,eAAA;AAAA,MACP,CAAC;AAAA,IACL;AACA,SAAK,SAAA;AAAA,EACP;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK,MAAM,EAAE;AAAA,EACtB;AAAA,EAEA,YAAY,UAAuB;AACjC,WAAO,CAAC,KAAK,WAAW,IAAI,QAAQ,GAAG,6BAA6B;AACpE,SAAK,WAAW,IAAI,QAAQ;AAE5B,SAAK,cAAc,QAAQ;AAE3B,WAAO,MAAM;AACX,WAAK,WAAW,OAAO,QAAQ;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,iBAAiB;AACf,eAAW,YAAY,KAAK,YAAY;AACtC,WAAK,cAAc,QAAQ;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,cAAc,UAAuB;AACnC,aAAS,KAAK,MAAsB,KAAK,aAAa,KAAK,MAAM;AAAA,EACnE;AAAA,EAEA,UAAU;AACR,SAAK,YAAA;AAAA,EACP;AAAA,EAEA,WAAW;AACT,SAAK,SAAS;AACd,eAAW,QAAQ,WAAW,KAAK,OAAO,MAAM,CAAA,CAAE,CAAC,GAAG;AACpD;AAAA,QACE,KAAK;AAAA,QACL,EAAC,MAAM,OAAO,KAAA;AAAA,QACd,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MAAA;AAAA,IAET;AACA,SAAK,MAAA;AAAA,EACP;AAAA,EAEA,KAAK,QAAgB;AACnB,SAAK,SAAS;AACd,gBAAY,KAAK,OAAO,QAAQ,KAAK,SAAS,IAAI,KAAK,OAAO;AAC9D,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ;AACN,QAAI,CAAC,KAAK,QAAQ;AAChB;AAAA,IACF;AACA,SAAK,SAAS;AACd,SAAK,eAAA;AAAA,EACP;AAAA,EAEA,UAAU,KAAU;AAClB,SAAK,WAAW,GAAG;AAAA,EACrB;AACF;"}
|
|
@@ -3,6 +3,7 @@ import { type Change } from './change.ts';
|
|
|
3
3
|
import { type Node } from './data.ts';
|
|
4
4
|
import { type FilterInput, type FilterOperator, type FilterOutput } from './filter-operators.ts';
|
|
5
5
|
import type { SourceSchema } from './schema.ts';
|
|
6
|
+
import { type Stream } from './stream.ts';
|
|
6
7
|
/**
|
|
7
8
|
* The Exists operator filters data based on whether or not a relationship is
|
|
8
9
|
* non-empty.
|
|
@@ -13,9 +14,9 @@ export declare class Exists implements FilterOperator {
|
|
|
13
14
|
setFilterOutput(output: FilterOutput): void;
|
|
14
15
|
beginFilter(): void;
|
|
15
16
|
endFilter(): void;
|
|
16
|
-
filter(node: Node): boolean
|
|
17
|
+
filter(node: Node): Generator<'yield', boolean>;
|
|
17
18
|
destroy(): void;
|
|
18
19
|
getSchema(): SourceSchema;
|
|
19
|
-
push(change: Change):
|
|
20
|
+
push(change: Change): Stream<'yield'>;
|
|
20
21
|
}
|
|
21
22
|
//# sourceMappingURL=exists.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exists.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/exists.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAAqB,KAAK,IAAI,EAAuB,MAAM,WAAW,CAAC;AAC9E,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"exists.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/exists.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAAqB,KAAK,IAAI,EAAuB,MAAM,WAAW,CAAC;AAC9E,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC;;;GAGG;AACH,qBAAa,MAAO,YAAW,cAAc;;gBAqBzC,KAAK,EAAE,WAAW,EAClB,gBAAgB,EAAE,MAAM,EACxB,aAAa,EAAE,WAAW,EAC1B,IAAI,EAAE,QAAQ,GAAG,YAAY,EAC7B,wBAAwB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAqBhD,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAI3C,WAAW;IAIX,SAAS;IAKR,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;IAqBhD,OAAO,IAAI,IAAI;IAIf,SAAS,IAAI,YAAY;IAIxB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;CA+JvC"}
|