@rocicorp/zero 0.26.0 → 0.26.1-canary.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/analyze-query/src/run-ast.d.ts.map +1 -1
- package/out/analyze-query/src/run-ast.js +4 -1
- package/out/analyze-query/src/run-ast.js.map +1 -1
- package/out/replicache/src/btree/node.js +4 -4
- package/out/replicache/src/btree/node.js.map +1 -1
- package/out/replicache/src/btree/write.js +2 -2
- package/out/replicache/src/btree/write.js.map +1 -1
- package/out/replicache/src/dag/gc.js +5 -2
- package/out/replicache/src/dag/gc.js.map +1 -1
- package/out/replicache/src/db/write.d.ts.map +1 -1
- package/out/replicache/src/db/write.js +21 -6
- package/out/replicache/src/db/write.js.map +1 -1
- package/out/replicache/src/error-responses.d.ts.map +1 -1
- package/out/replicache/src/error-responses.js +4 -1
- package/out/replicache/src/error-responses.js.map +1 -1
- package/out/replicache/src/persist/clients.d.ts.map +1 -1
- package/out/replicache/src/persist/clients.js +4 -1
- package/out/replicache/src/persist/clients.js.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.js +2 -1
- package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
- package/out/replicache/src/persist/idb-databases-store.d.ts.map +1 -1
- package/out/replicache/src/persist/idb-databases-store.js +4 -1
- package/out/replicache/src/persist/idb-databases-store.js.map +1 -1
- package/out/replicache/src/process-scheduler.js +4 -1
- package/out/replicache/src/process-scheduler.js.map +1 -1
- package/out/replicache/src/replicache-impl.js +2 -2
- package/out/replicache/src/replicache-impl.js.map +1 -1
- package/out/replicache/src/subscriptions.d.ts.map +1 -1
- package/out/replicache/src/subscriptions.js +5 -2
- package/out/replicache/src/subscriptions.js.map +1 -1
- package/out/replicache/src/sync/diff.d.ts.map +1 -1
- package/out/replicache/src/sync/diff.js +4 -1
- package/out/replicache/src/sync/diff.js.map +1 -1
- package/out/replicache/src/sync/pull.d.ts.map +1 -1
- package/out/replicache/src/sync/pull.js +4 -1
- package/out/replicache/src/sync/pull.js.map +1 -1
- package/out/replicache/src/sync/push.d.ts.map +1 -1
- package/out/replicache/src/sync/push.js +5 -2
- package/out/replicache/src/sync/push.js.map +1 -1
- package/out/shared/src/asserts.d.ts +1 -1
- package/out/shared/src/asserts.d.ts.map +1 -1
- package/out/shared/src/asserts.js +1 -1
- package/out/shared/src/asserts.js.map +1 -1
- package/out/z2s/src/compiler.d.ts.map +1 -1
- package/out/z2s/src/compiler.js +8 -2
- package/out/z2s/src/compiler.js.map +1 -1
- package/out/zero/package.json.js +1 -1
- package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.js +17 -11
- package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
- package/out/zero-cache/src/observability/events.d.ts.map +1 -1
- package/out/zero-cache/src/observability/events.js +28 -9
- package/out/zero-cache/src/observability/events.js.map +1 -1
- package/out/zero-cache/src/services/analyze.js +1 -0
- package/out/zero-cache/src/services/analyze.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +29 -14
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +6 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +69 -25
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +6 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/init.js +12 -8
- package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +26 -0
- package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.js +15 -3
- package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +30 -0
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current.js +2 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +8 -2
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +10 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.d.ts +2 -0
- package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.js +8 -6
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js +39 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.d.ts +4 -3
- package/out/zero-cache/src/services/replicator/replication-status.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.js +25 -10
- package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
- package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
- package/out/zero-cache/src/services/run-ast.js +22 -2
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/running-state.d.ts +1 -0
- package/out/zero-cache/src/services/running-state.d.ts.map +1 -1
- package/out/zero-cache/src/services/running-state.js +4 -0
- package/out/zero-cache/src/services/running-state.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +8 -2
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +10 -1
- 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 +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +15 -7
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/types/subscription.d.ts +3 -1
- package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
- package/out/zero-cache/src/types/subscription.js +29 -9
- package/out/zero-cache/src/types/subscription.js.map +1 -1
- package/out/zero-client/src/client/http-string.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-events/src/status.d.ts +8 -0
- package/out/zero-events/src/status.d.ts.map +1 -1
- package/out/zero-schema/src/permissions.d.ts.map +1 -1
- package/out/zero-schema/src/permissions.js +4 -1
- package/out/zero-schema/src/permissions.js.map +1 -1
- package/out/zero-server/src/process-mutations.d.ts.map +1 -1
- package/out/zero-server/src/process-mutations.js +13 -19
- package/out/zero-server/src/process-mutations.js.map +1 -1
- package/out/zql/src/builder/filter.d.ts.map +1 -1
- package/out/zql/src/builder/filter.js +5 -2
- package/out/zql/src/builder/filter.js.map +1 -1
- package/out/zql/src/ivm/constraint.js.map +1 -1
- package/package.json +1 -1
|
@@ -205,7 +205,10 @@ function maybeEndPull(store, lc, expectedSyncHead, clientID, diffConfig, formatV
|
|
|
205
205
|
const localMutations$1 = await localMutations(mainHeadHash, dagRead);
|
|
206
206
|
for (const commit of localMutations$1) {
|
|
207
207
|
let cid = clientID;
|
|
208
|
-
assert(
|
|
208
|
+
assert(
|
|
209
|
+
commitIsLocalDD31(commit),
|
|
210
|
+
"Expected commit to be a local DD31 commit"
|
|
211
|
+
);
|
|
209
212
|
cid = commit.meta.clientID;
|
|
210
213
|
if (await commit.getMutationID(cid, dagRead) > await syncHead.getMutationID(cid, dagRead)) {
|
|
211
214
|
pending.push(commit);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.js","sources":["../../../../../replicache/src/sync/pull.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {deepEqual} from '../../../shared/src/json.ts';\nimport {diff} from '../btree/diff.ts';\nimport {BTreeRead} from '../btree/read.ts';\nimport {compareCookies, type Cookie} from '../cookies.ts';\nimport type {Store} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {\n assertSnapshotMetaDD31,\n baseSnapshotFromHash,\n commitFromHash,\n commitIsLocalDD31,\n DEFAULT_HEAD_NAME,\n type LocalMeta,\n localMutations as localMutations_1,\n snapshotMetaParts,\n} from '../db/commit.ts';\nimport {newWriteSnapshotDD31} from '../db/write.ts';\nimport {isErrorResponse} from '../error-responses.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport {deepFreeze, type FrozenJSONValue} from '../frozen-json.ts';\nimport {assertPullerResultV1} from '../get-default-puller.ts';\nimport {emptyHash, type Hash} from '../hash.ts';\nimport type {HTTPRequestInfo} from '../http-request-info.ts';\nimport type {\n Puller,\n PullerResult,\n PullResponseOKV1Internal,\n PullResponseV1,\n} from '../puller.ts';\nimport {ReportError} from '../report-error.ts';\nimport {toError} from '../to-error.ts';\nimport {withRead, withWriteNoImplicitCommit} from '../with-transactions.ts';\nimport {\n addDiffsForIndexes,\n type DiffComputationConfig,\n DiffsMap,\n} from './diff.ts';\nimport * as HandlePullResponseResultType from './handle-pull-response-result-type-enum.ts';\nimport type {ClientGroupID, ClientID} from './ids.ts';\nimport * as patch from './patch.ts';\nimport {PullError} from './pull-error.ts';\nimport {SYNC_HEAD_NAME} from './sync-head-name.ts';\n\ntype FormatVersion = (typeof FormatVersion)[keyof typeof FormatVersion];\n\nexport const PULL_VERSION_SDD = 0;\nexport const PULL_VERSION_DD31 = 1;\n\n/**\n * The JSON value used as the body when doing a POST to the [pull\n * endpoint](/reference/server-pull).\n */\nexport type PullRequest = PullRequestV1;\n\n/**\n * The JSON value used as the body when doing a POST to the [pull\n * endpoint](/reference/server-pull).\n */\nexport type PullRequestV1 = {\n pullVersion: 1;\n // schemaVersion can optionally be used by the customer's app\n // to indicate to the data layer what format of Client View the\n // app understands.\n schemaVersion: string;\n profileID: string;\n cookie: Cookie;\n\n clientGroupID: ClientGroupID;\n};\n\nexport function isPullRequestV1(pr: PullRequest): pr is PullRequestV1 {\n return pr.pullVersion === PULL_VERSION_DD31;\n}\n\nexport type BeginPullResponseV1 = {\n httpRequestInfo: HTTPRequestInfo;\n pullResponse?: PullResponseV1;\n syncHead: Hash;\n};\n\nexport async function beginPullV1(\n profileID: string,\n clientID: ClientID,\n clientGroupID: ClientGroupID,\n schemaVersion: string,\n puller: Puller,\n requestID: string,\n store: Store,\n formatVersion: FormatVersion,\n lc: LogContext,\n createSyncBranch = true,\n): Promise<BeginPullResponseV1> {\n const baseCookie = await withRead(store, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head found');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n assertSnapshotMetaDD31(baseSnapshotMeta);\n return baseSnapshotMeta.cookieJSON;\n });\n\n const pullReq: PullRequestV1 = {\n profileID,\n clientGroupID,\n cookie: baseCookie,\n pullVersion: PULL_VERSION_DD31,\n schemaVersion,\n };\n\n const {response, httpRequestInfo} = await callPuller(\n lc,\n puller,\n pullReq,\n requestID,\n );\n\n // If Puller did not get a pull response we still want to return the HTTP\n // request info.\n if (!response) {\n return {\n httpRequestInfo,\n syncHead: emptyHash,\n };\n }\n\n if (!createSyncBranch || isErrorResponse(response)) {\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead: emptyHash,\n };\n }\n\n const result = await handlePullResponseV1(\n lc,\n store,\n baseCookie,\n response,\n clientID,\n formatVersion,\n );\n\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead:\n result.type === HandlePullResponseResultType.Applied\n ? result.syncHead\n : emptyHash,\n };\n}\n\nasync function callPuller(\n lc: LogContext,\n puller: Puller,\n pullReq: PullRequest,\n requestID: string,\n): Promise<PullerResult> {\n lc.debug?.('Starting pull...');\n const pullStart = Date.now();\n let pullerResult: PullerResult;\n try {\n pullerResult = await puller(pullReq, requestID);\n lc.debug?.(\n `...Pull ${pullerResult.response ? 'complete' : 'failed'} in `,\n Date.now() - pullStart,\n 'ms',\n );\n } catch (e) {\n throw new PullError(toError(e));\n }\n try {\n assertPullerResultV1(pullerResult);\n return pullerResult;\n } catch (e) {\n throw new ReportError('Invalid puller result', toError(e));\n }\n}\n\ntype HandlePullResponseResult =\n | {\n type: HandlePullResponseResultType.Applied;\n syncHead: Hash;\n }\n | {\n type:\n | HandlePullResponseResultType.NoOp\n | HandlePullResponseResultType.CookieMismatch;\n };\n\nfunction badOrderMessage(\n name: string,\n receivedValue: string,\n lastSnapshotValue: string,\n) {\n return `Received ${name} ${receivedValue} is < than last snapshot ${name} ${lastSnapshotValue}; ignoring client view`;\n}\n\nexport function handlePullResponseV1(\n lc: LogContext,\n store: Store,\n expectedBaseCookie: FrozenJSONValue,\n response: PullResponseOKV1Internal,\n clientID: ClientID,\n formatVersion: FormatVersion,\n): Promise<HandlePullResponseResult> {\n // It is possible that another sync completed while we were pulling. Ensure\n // that is not the case by re-checking the base snapshot.\n return withWriteNoImplicitCommit(store, async dagWrite => {\n const dagRead = dagWrite;\n const mainHead = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (mainHead === undefined) {\n throw new Error('Main head disappeared');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHead, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n assertSnapshotMetaDD31(baseSnapshotMeta);\n const baseCookie = baseSnapshotMeta.cookieJSON;\n\n // TODO(MP) Here we are using whether the cookie has changed as a proxy for whether\n // the base snapshot changed, which is the check we used to do. I don't think this\n // is quite right. We need to firm up under what conditions we will/not accept an\n // update from the server: https://github.com/rocicorp/replicache/issues/713.\n // In DD31 this is expected to happen if a refresh occurs during a pull.\n if (!deepEqual(expectedBaseCookie, baseCookie)) {\n lc.debug?.(\n 'handlePullResponse: cookie mismatch, response is not applicable',\n );\n return {\n type: HandlePullResponseResultType.CookieMismatch,\n };\n }\n\n // Check that the lastMutationIDs are not going backwards.\n for (const [clientID, lmidChange] of Object.entries(\n response.lastMutationIDChanges,\n )) {\n const lastMutationID = baseSnapshotMeta.lastMutationIDs[clientID];\n if (lastMutationID !== undefined && lmidChange < lastMutationID) {\n throw new Error(\n badOrderMessage(\n `${clientID} lastMutationID`,\n String(lmidChange),\n String(lastMutationID),\n ),\n );\n }\n }\n\n const frozenResponseCookie = deepFreeze(response.cookie);\n if (compareCookies(frozenResponseCookie, baseCookie) < 0) {\n throw new Error(\n badOrderMessage(\n 'cookie',\n JSON.stringify(frozenResponseCookie),\n JSON.stringify(baseCookie),\n ),\n );\n }\n\n if (deepEqual(frozenResponseCookie, baseCookie)) {\n if (response.patch.length > 0) {\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but patch is not empty`,\n );\n }\n if (Object.keys(response.lastMutationIDChanges).length > 0) {\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but lastMutationIDChanges is not empty`,\n );\n }\n // If the cookie doesn't change, it's a nop.\n return {\n type: HandlePullResponseResultType.NoOp,\n };\n }\n\n const dbWrite = await newWriteSnapshotDD31(\n baseSnapshot.chunk.hash,\n {...baseSnapshotMeta.lastMutationIDs, ...response.lastMutationIDChanges},\n frozenResponseCookie,\n dagWrite,\n clientID,\n formatVersion,\n );\n\n await patch.apply(lc, dbWrite, response.patch);\n\n return {\n type: HandlePullResponseResultType.Applied,\n syncHead: await dbWrite.commit(SYNC_HEAD_NAME),\n };\n });\n}\n\nexport function maybeEndPull<M extends LocalMeta>(\n store: Store,\n lc: LogContext,\n expectedSyncHead: Hash,\n clientID: ClientID,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n): Promise<{\n syncHead: Hash;\n mainHead: Hash;\n oldMainHead: Hash;\n replayMutations: Commit<M>[];\n diffs: DiffsMap;\n}> {\n return withWriteNoImplicitCommit(store, async dagWrite => {\n const dagRead = dagWrite;\n // Ensure sync head is what the caller thinks it is.\n const syncHeadHash = await dagRead.getHead(SYNC_HEAD_NAME);\n if (syncHeadHash === undefined) {\n throw new Error('Missing sync head');\n }\n if (syncHeadHash !== expectedSyncHead) {\n lc.error?.(\n 'maybeEndPull, Wrong sync head. Expecting:',\n expectedSyncHead,\n 'got:',\n syncHeadHash,\n );\n throw new Error('Wrong sync head');\n }\n\n // Ensure another sync has not landed a new snapshot on the main chain.\n // TODO: In DD31, it is expected that a newer snapshot might have appeared\n // on the main chain. In that case, we just abort this pull.\n const syncSnapshot = await baseSnapshotFromHash(syncHeadHash, dagRead);\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (mainHeadHash === undefined) {\n throw new Error('Missing main head');\n }\n const mainSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n\n const {meta} = syncSnapshot;\n const syncSnapshotBasis = meta.basisHash;\n if (syncSnapshot === null) {\n throw new Error('Sync snapshot with no basis');\n }\n if (syncSnapshotBasis !== mainSnapshot.chunk.hash) {\n throw new Error('Overlapping syncs');\n }\n\n // Collect pending commits from the main chain and determine which\n // of them if any need to be replayed.\n const syncHead = await commitFromHash(syncHeadHash, dagRead);\n const pending: Commit<M>[] = [];\n const localMutations = await localMutations_1(mainHeadHash, dagRead);\n for (const commit of localMutations) {\n let cid = clientID;\n assert(commitIsLocalDD31(commit));\n cid = commit.meta.clientID;\n\n if (\n (await commit.getMutationID(cid, dagRead)) >\n (await syncHead.getMutationID(cid, dagRead))\n ) {\n // We know that the dag can only contain either LocalMetaSDD or LocalMetaDD31\n pending.push(commit as Commit<M>);\n }\n }\n // pending() gave us the pending mutations in sync-head-first order whereas\n // caller wants them in the order to replay (lower mutation ids first).\n pending.reverse();\n\n // We return the keys that changed due to this pull. This is used by\n // subscriptions in the JS API when there are no more pending mutations.\n const diffsMap = new DiffsMap();\n\n // Return replay commits if any.\n if (pending.length > 0) {\n return {\n syncHead: syncHeadHash,\n oldMainHead: mainHeadHash,\n mainHead: mainHeadHash,\n replayMutations: pending,\n // The changed keys are not reported when further replays are\n // needed. The diffs will be reported at the end when there\n // are no more mutations to be replay and then it will be reported\n // relative to DEFAULT_HEAD_NAME.\n diffs: diffsMap,\n };\n }\n\n // TODO check invariants\n\n // Compute diffs (changed keys) for value map and index maps.\n const mainHead = await commitFromHash(mainHeadHash, dagRead);\n if (diffConfig.shouldComputeDiffs()) {\n const mainHeadMap = new BTreeRead(\n dagRead,\n formatVersion,\n mainHead.valueHash,\n );\n const syncHeadMap = new BTreeRead(\n dagRead,\n formatVersion,\n syncHead.valueHash,\n );\n const valueDiff = await diff(mainHeadMap, syncHeadMap);\n diffsMap.set('', valueDiff);\n await addDiffsForIndexes(\n mainHead,\n syncHead,\n dagRead,\n diffsMap,\n diffConfig,\n formatVersion,\n );\n }\n\n // No mutations to replay so set the main head to the sync head and sync complete!\n await Promise.all([\n dagWrite.setHead(DEFAULT_HEAD_NAME, syncHeadHash),\n dagWrite.removeHead(SYNC_HEAD_NAME),\n ]);\n await dagWrite.commit();\n // main head was set to sync head\n const newMainHeadHash = syncHeadHash;\n\n if (lc.debug) {\n const [oldLastMutationID, oldCookie] = snapshotMetaParts(\n mainSnapshot,\n clientID,\n );\n const [newLastMutationID, newCookie] = snapshotMetaParts(\n syncSnapshot,\n clientID,\n );\n lc.debug(\n `Successfully pulled new snapshot with lastMutationID:`,\n newLastMutationID,\n `(prev:`,\n oldLastMutationID,\n `), cookie: `,\n newCookie,\n `(prev:`,\n oldCookie,\n `), sync head hash:`,\n syncHeadHash,\n ', main head hash:',\n mainHeadHash,\n `, valueHash:`,\n syncHead.valueHash,\n `(prev:`,\n mainSnapshot.valueHash,\n );\n }\n\n return {\n syncHead: syncHeadHash,\n oldMainHead: mainHeadHash,\n mainHead: newMainHeadHash,\n replayMutations: [],\n diffs: diffsMap,\n };\n });\n}\n"],"names":["HandlePullResponseResultType.Applied","HandlePullResponseResultType.CookieMismatch","clientID","HandlePullResponseResultType.NoOp","patch.apply","localMutations","localMutations_1"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pull.js","sources":["../../../../../replicache/src/sync/pull.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {deepEqual} from '../../../shared/src/json.ts';\nimport {diff} from '../btree/diff.ts';\nimport {BTreeRead} from '../btree/read.ts';\nimport {compareCookies, type Cookie} from '../cookies.ts';\nimport type {Store} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {\n assertSnapshotMetaDD31,\n baseSnapshotFromHash,\n commitFromHash,\n commitIsLocalDD31,\n DEFAULT_HEAD_NAME,\n type LocalMeta,\n localMutations as localMutations_1,\n snapshotMetaParts,\n} from '../db/commit.ts';\nimport {newWriteSnapshotDD31} from '../db/write.ts';\nimport {isErrorResponse} from '../error-responses.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport {deepFreeze, type FrozenJSONValue} from '../frozen-json.ts';\nimport {assertPullerResultV1} from '../get-default-puller.ts';\nimport {emptyHash, type Hash} from '../hash.ts';\nimport type {HTTPRequestInfo} from '../http-request-info.ts';\nimport type {\n Puller,\n PullerResult,\n PullResponseOKV1Internal,\n PullResponseV1,\n} from '../puller.ts';\nimport {ReportError} from '../report-error.ts';\nimport {toError} from '../to-error.ts';\nimport {withRead, withWriteNoImplicitCommit} from '../with-transactions.ts';\nimport {\n addDiffsForIndexes,\n type DiffComputationConfig,\n DiffsMap,\n} from './diff.ts';\nimport * as HandlePullResponseResultType from './handle-pull-response-result-type-enum.ts';\nimport type {ClientGroupID, ClientID} from './ids.ts';\nimport * as patch from './patch.ts';\nimport {PullError} from './pull-error.ts';\nimport {SYNC_HEAD_NAME} from './sync-head-name.ts';\n\ntype FormatVersion = (typeof FormatVersion)[keyof typeof FormatVersion];\n\nexport const PULL_VERSION_SDD = 0;\nexport const PULL_VERSION_DD31 = 1;\n\n/**\n * The JSON value used as the body when doing a POST to the [pull\n * endpoint](/reference/server-pull).\n */\nexport type PullRequest = PullRequestV1;\n\n/**\n * The JSON value used as the body when doing a POST to the [pull\n * endpoint](/reference/server-pull).\n */\nexport type PullRequestV1 = {\n pullVersion: 1;\n // schemaVersion can optionally be used by the customer's app\n // to indicate to the data layer what format of Client View the\n // app understands.\n schemaVersion: string;\n profileID: string;\n cookie: Cookie;\n\n clientGroupID: ClientGroupID;\n};\n\nexport function isPullRequestV1(pr: PullRequest): pr is PullRequestV1 {\n return pr.pullVersion === PULL_VERSION_DD31;\n}\n\nexport type BeginPullResponseV1 = {\n httpRequestInfo: HTTPRequestInfo;\n pullResponse?: PullResponseV1;\n syncHead: Hash;\n};\n\nexport async function beginPullV1(\n profileID: string,\n clientID: ClientID,\n clientGroupID: ClientGroupID,\n schemaVersion: string,\n puller: Puller,\n requestID: string,\n store: Store,\n formatVersion: FormatVersion,\n lc: LogContext,\n createSyncBranch = true,\n): Promise<BeginPullResponseV1> {\n const baseCookie = await withRead(store, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head found');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n assertSnapshotMetaDD31(baseSnapshotMeta);\n return baseSnapshotMeta.cookieJSON;\n });\n\n const pullReq: PullRequestV1 = {\n profileID,\n clientGroupID,\n cookie: baseCookie,\n pullVersion: PULL_VERSION_DD31,\n schemaVersion,\n };\n\n const {response, httpRequestInfo} = await callPuller(\n lc,\n puller,\n pullReq,\n requestID,\n );\n\n // If Puller did not get a pull response we still want to return the HTTP\n // request info.\n if (!response) {\n return {\n httpRequestInfo,\n syncHead: emptyHash,\n };\n }\n\n if (!createSyncBranch || isErrorResponse(response)) {\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead: emptyHash,\n };\n }\n\n const result = await handlePullResponseV1(\n lc,\n store,\n baseCookie,\n response,\n clientID,\n formatVersion,\n );\n\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead:\n result.type === HandlePullResponseResultType.Applied\n ? result.syncHead\n : emptyHash,\n };\n}\n\nasync function callPuller(\n lc: LogContext,\n puller: Puller,\n pullReq: PullRequest,\n requestID: string,\n): Promise<PullerResult> {\n lc.debug?.('Starting pull...');\n const pullStart = Date.now();\n let pullerResult: PullerResult;\n try {\n pullerResult = await puller(pullReq, requestID);\n lc.debug?.(\n `...Pull ${pullerResult.response ? 'complete' : 'failed'} in `,\n Date.now() - pullStart,\n 'ms',\n );\n } catch (e) {\n throw new PullError(toError(e));\n }\n try {\n assertPullerResultV1(pullerResult);\n return pullerResult;\n } catch (e) {\n throw new ReportError('Invalid puller result', toError(e));\n }\n}\n\ntype HandlePullResponseResult =\n | {\n type: HandlePullResponseResultType.Applied;\n syncHead: Hash;\n }\n | {\n type:\n | HandlePullResponseResultType.NoOp\n | HandlePullResponseResultType.CookieMismatch;\n };\n\nfunction badOrderMessage(\n name: string,\n receivedValue: string,\n lastSnapshotValue: string,\n) {\n return `Received ${name} ${receivedValue} is < than last snapshot ${name} ${lastSnapshotValue}; ignoring client view`;\n}\n\nexport function handlePullResponseV1(\n lc: LogContext,\n store: Store,\n expectedBaseCookie: FrozenJSONValue,\n response: PullResponseOKV1Internal,\n clientID: ClientID,\n formatVersion: FormatVersion,\n): Promise<HandlePullResponseResult> {\n // It is possible that another sync completed while we were pulling. Ensure\n // that is not the case by re-checking the base snapshot.\n return withWriteNoImplicitCommit(store, async dagWrite => {\n const dagRead = dagWrite;\n const mainHead = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (mainHead === undefined) {\n throw new Error('Main head disappeared');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHead, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n assertSnapshotMetaDD31(baseSnapshotMeta);\n const baseCookie = baseSnapshotMeta.cookieJSON;\n\n // TODO(MP) Here we are using whether the cookie has changed as a proxy for whether\n // the base snapshot changed, which is the check we used to do. I don't think this\n // is quite right. We need to firm up under what conditions we will/not accept an\n // update from the server: https://github.com/rocicorp/replicache/issues/713.\n // In DD31 this is expected to happen if a refresh occurs during a pull.\n if (!deepEqual(expectedBaseCookie, baseCookie)) {\n lc.debug?.(\n 'handlePullResponse: cookie mismatch, response is not applicable',\n );\n return {\n type: HandlePullResponseResultType.CookieMismatch,\n };\n }\n\n // Check that the lastMutationIDs are not going backwards.\n for (const [clientID, lmidChange] of Object.entries(\n response.lastMutationIDChanges,\n )) {\n const lastMutationID = baseSnapshotMeta.lastMutationIDs[clientID];\n if (lastMutationID !== undefined && lmidChange < lastMutationID) {\n throw new Error(\n badOrderMessage(\n `${clientID} lastMutationID`,\n String(lmidChange),\n String(lastMutationID),\n ),\n );\n }\n }\n\n const frozenResponseCookie = deepFreeze(response.cookie);\n if (compareCookies(frozenResponseCookie, baseCookie) < 0) {\n throw new Error(\n badOrderMessage(\n 'cookie',\n JSON.stringify(frozenResponseCookie),\n JSON.stringify(baseCookie),\n ),\n );\n }\n\n if (deepEqual(frozenResponseCookie, baseCookie)) {\n if (response.patch.length > 0) {\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but patch is not empty`,\n );\n }\n if (Object.keys(response.lastMutationIDChanges).length > 0) {\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but lastMutationIDChanges is not empty`,\n );\n }\n // If the cookie doesn't change, it's a nop.\n return {\n type: HandlePullResponseResultType.NoOp,\n };\n }\n\n const dbWrite = await newWriteSnapshotDD31(\n baseSnapshot.chunk.hash,\n {...baseSnapshotMeta.lastMutationIDs, ...response.lastMutationIDChanges},\n frozenResponseCookie,\n dagWrite,\n clientID,\n formatVersion,\n );\n\n await patch.apply(lc, dbWrite, response.patch);\n\n return {\n type: HandlePullResponseResultType.Applied,\n syncHead: await dbWrite.commit(SYNC_HEAD_NAME),\n };\n });\n}\n\nexport function maybeEndPull<M extends LocalMeta>(\n store: Store,\n lc: LogContext,\n expectedSyncHead: Hash,\n clientID: ClientID,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n): Promise<{\n syncHead: Hash;\n mainHead: Hash;\n oldMainHead: Hash;\n replayMutations: Commit<M>[];\n diffs: DiffsMap;\n}> {\n return withWriteNoImplicitCommit(store, async dagWrite => {\n const dagRead = dagWrite;\n // Ensure sync head is what the caller thinks it is.\n const syncHeadHash = await dagRead.getHead(SYNC_HEAD_NAME);\n if (syncHeadHash === undefined) {\n throw new Error('Missing sync head');\n }\n if (syncHeadHash !== expectedSyncHead) {\n lc.error?.(\n 'maybeEndPull, Wrong sync head. Expecting:',\n expectedSyncHead,\n 'got:',\n syncHeadHash,\n );\n throw new Error('Wrong sync head');\n }\n\n // Ensure another sync has not landed a new snapshot on the main chain.\n // TODO: In DD31, it is expected that a newer snapshot might have appeared\n // on the main chain. In that case, we just abort this pull.\n const syncSnapshot = await baseSnapshotFromHash(syncHeadHash, dagRead);\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (mainHeadHash === undefined) {\n throw new Error('Missing main head');\n }\n const mainSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n\n const {meta} = syncSnapshot;\n const syncSnapshotBasis = meta.basisHash;\n if (syncSnapshot === null) {\n throw new Error('Sync snapshot with no basis');\n }\n if (syncSnapshotBasis !== mainSnapshot.chunk.hash) {\n throw new Error('Overlapping syncs');\n }\n\n // Collect pending commits from the main chain and determine which\n // of them if any need to be replayed.\n const syncHead = await commitFromHash(syncHeadHash, dagRead);\n const pending: Commit<M>[] = [];\n const localMutations = await localMutations_1(mainHeadHash, dagRead);\n for (const commit of localMutations) {\n let cid = clientID;\n assert(\n commitIsLocalDD31(commit),\n 'Expected commit to be a local DD31 commit',\n );\n cid = commit.meta.clientID;\n\n if (\n (await commit.getMutationID(cid, dagRead)) >\n (await syncHead.getMutationID(cid, dagRead))\n ) {\n // We know that the dag can only contain either LocalMetaSDD or LocalMetaDD31\n pending.push(commit as Commit<M>);\n }\n }\n // pending() gave us the pending mutations in sync-head-first order whereas\n // caller wants them in the order to replay (lower mutation ids first).\n pending.reverse();\n\n // We return the keys that changed due to this pull. This is used by\n // subscriptions in the JS API when there are no more pending mutations.\n const diffsMap = new DiffsMap();\n\n // Return replay commits if any.\n if (pending.length > 0) {\n return {\n syncHead: syncHeadHash,\n oldMainHead: mainHeadHash,\n mainHead: mainHeadHash,\n replayMutations: pending,\n // The changed keys are not reported when further replays are\n // needed. The diffs will be reported at the end when there\n // are no more mutations to be replay and then it will be reported\n // relative to DEFAULT_HEAD_NAME.\n diffs: diffsMap,\n };\n }\n\n // TODO check invariants\n\n // Compute diffs (changed keys) for value map and index maps.\n const mainHead = await commitFromHash(mainHeadHash, dagRead);\n if (diffConfig.shouldComputeDiffs()) {\n const mainHeadMap = new BTreeRead(\n dagRead,\n formatVersion,\n mainHead.valueHash,\n );\n const syncHeadMap = new BTreeRead(\n dagRead,\n formatVersion,\n syncHead.valueHash,\n );\n const valueDiff = await diff(mainHeadMap, syncHeadMap);\n diffsMap.set('', valueDiff);\n await addDiffsForIndexes(\n mainHead,\n syncHead,\n dagRead,\n diffsMap,\n diffConfig,\n formatVersion,\n );\n }\n\n // No mutations to replay so set the main head to the sync head and sync complete!\n await Promise.all([\n dagWrite.setHead(DEFAULT_HEAD_NAME, syncHeadHash),\n dagWrite.removeHead(SYNC_HEAD_NAME),\n ]);\n await dagWrite.commit();\n // main head was set to sync head\n const newMainHeadHash = syncHeadHash;\n\n if (lc.debug) {\n const [oldLastMutationID, oldCookie] = snapshotMetaParts(\n mainSnapshot,\n clientID,\n );\n const [newLastMutationID, newCookie] = snapshotMetaParts(\n syncSnapshot,\n clientID,\n );\n lc.debug(\n `Successfully pulled new snapshot with lastMutationID:`,\n newLastMutationID,\n `(prev:`,\n oldLastMutationID,\n `), cookie: `,\n newCookie,\n `(prev:`,\n oldCookie,\n `), sync head hash:`,\n syncHeadHash,\n ', main head hash:',\n mainHeadHash,\n `, valueHash:`,\n syncHead.valueHash,\n `(prev:`,\n mainSnapshot.valueHash,\n );\n }\n\n return {\n syncHead: syncHeadHash,\n oldMainHead: mainHeadHash,\n mainHead: newMainHeadHash,\n replayMutations: [],\n diffs: diffsMap,\n };\n });\n}\n"],"names":["HandlePullResponseResultType.Applied","HandlePullResponseResultType.CookieMismatch","clientID","HandlePullResponseResultType.NoOp","patch.apply","localMutations","localMutations_1"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/sync/push.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAGjD,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AAEnE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAQ3C,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,YAAY,EAElB,MAAM,cAAc,CAAC;AAItB,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,QAAQ,EAGd,MAAM,UAAU,CAAC;AAElB,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC;AAUlC;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,WAAW,EAAE,CAAC,CAAC;IACf;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAElB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,UAAU,EAAE,CAAC;CACzB,CAAC;AAUF,MAAM,MAAM,WAAW,GAAG,aAAa,CAAC;AAExC,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,KAAK,IAAI,aAAa,CAEhC;AAuBD,wBAAsB,IAAI,CACxB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,KAAK,EACZ,EAAE,EAAE,UAAU,EACd,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,SAAS,EAAE,QAAQ,EACnB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,OAAO,gBAAgB,GAAG,OAAO,iBAAiB,GAC9D,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/sync/push.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAGjD,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AAEnE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAQ3C,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,YAAY,EAElB,MAAM,cAAc,CAAC;AAItB,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,QAAQ,EAGd,MAAM,UAAU,CAAC;AAElB,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC;AAUlC;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,WAAW,EAAE,CAAC,CAAC;IACf;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAElB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,UAAU,EAAE,CAAC;CACzB,CAAC;AAUF,MAAM,MAAM,WAAW,GAAG,aAAa,CAAC;AAExC,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,KAAK,IAAI,aAAa,CAEhC;AAuBD,wBAAsB,IAAI,CACxB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,KAAK,EACZ,EAAE,EAAE,UAAU,EACd,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,SAAS,EAAE,QAAQ,EACnB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,OAAO,gBAAgB,GAAG,OAAO,iBAAiB,GAC9D,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CA+CnC"}
|
|
@@ -44,7 +44,10 @@ async function push(requestID, store, lc, profileID, clientGroupID, _clientID, p
|
|
|
44
44
|
return void 0;
|
|
45
45
|
}
|
|
46
46
|
pending.reverse();
|
|
47
|
-
assert(
|
|
47
|
+
assert(
|
|
48
|
+
pushVersion === PUSH_VERSION_DD31,
|
|
49
|
+
"Expected pushVersion to be PUSH_VERSION_DD31"
|
|
50
|
+
);
|
|
48
51
|
const pushMutations = [];
|
|
49
52
|
for (const commit of pending) {
|
|
50
53
|
if (commitIsLocalDD31(commit)) {
|
|
@@ -53,7 +56,7 @@ async function push(requestID, store, lc, profileID, clientGroupID, _clientID, p
|
|
|
53
56
|
throw new Error("Internal non local pending commit");
|
|
54
57
|
}
|
|
55
58
|
}
|
|
56
|
-
assert(clientGroupID);
|
|
59
|
+
assert(clientGroupID, "Expected clientGroupID to be defined");
|
|
57
60
|
const pushReq = {
|
|
58
61
|
profileID,
|
|
59
62
|
clientGroupID,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.js","sources":["../../../../../replicache/src/sync/push.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {jsonSchema} from '../../../shared/src/json-schema.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport * as valita from '../../../shared/src/valita.ts';\nimport type {Store} from '../dag/store.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type LocalMetaDD31,\n commitIsLocalDD31,\n localMutations,\n} from '../db/commit.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {\n PushError,\n type Pusher,\n type PusherResult,\n assertPusherResult,\n} from '../pusher.ts';\nimport {ReportError} from '../report-error.ts';\nimport {toError} from '../to-error.ts';\nimport {withRead} from '../with-transactions.ts';\nimport {\n type ClientGroupID,\n type ClientID,\n clientGroupIDSchema,\n clientIDSchema,\n} from './ids.ts';\n\nexport const PUSH_VERSION_SDD = 0;\nexport const PUSH_VERSION_DD31 = 1;\n\n/**\n * Mutation describes a single mutation done on the client.\n */\nexport type MutationV1 = {\n readonly id: number;\n readonly name: string;\n readonly args: ReadonlyJSONValue;\n readonly timestamp: number;\n readonly clientID: ClientID;\n};\n\nexport type Mutation = MutationV1;\n\nconst mutationV1Schema: valita.Type<MutationV1> = valita.readonlyObject({\n id: valita.number(),\n name: valita.string(),\n args: jsonSchema,\n timestamp: valita.number(),\n clientID: clientIDSchema,\n});\n\n/**\n * The JSON value used as the body when doing a POST to the [push\n * endpoint](/reference/server-push).\n */\nexport type PushRequestV1 = {\n pushVersion: 1;\n /**\n * `schemaVersion` can optionally be used to specify to the push endpoint\n * version information about the mutators the app is using (e.g., format of\n * mutator args).\n */\n schemaVersion: string;\n profileID: string;\n\n clientGroupID: ClientGroupID;\n mutations: MutationV1[];\n};\n\nconst pushRequestV1Schema = valita.object({\n pushVersion: valita.literal(1),\n schemaVersion: valita.string(),\n profileID: valita.string(),\n clientGroupID: clientGroupIDSchema,\n mutations: valita.array(mutationV1Schema),\n});\n\nexport type PushRequest = PushRequestV1;\n\nexport function assertPushRequestV1(\n value: unknown,\n): asserts value is PushRequestV1 {\n valita.assert(value, pushRequestV1Schema);\n}\n\n/**\n * Mutation describes a single mutation done on the client.\n */\ntype FrozenMutationV1 = {\n readonly id: number;\n readonly name: string;\n readonly args: FrozenJSONValue;\n readonly timestamp: number;\n readonly clientID: ClientID;\n};\n\nfunction convertDD31(lm: LocalMetaDD31): FrozenMutationV1 {\n return {\n id: lm.mutationID,\n name: lm.mutatorName,\n args: lm.mutatorArgsJSON,\n timestamp: lm.timestamp,\n clientID: lm.clientID,\n };\n}\n\nexport async function push(\n requestID: string,\n store: Store,\n lc: LogContext,\n profileID: string,\n clientGroupID: ClientGroupID | undefined,\n _clientID: ClientID,\n pusher: Pusher,\n schemaVersion: string,\n pushVersion: typeof PUSH_VERSION_SDD | typeof PUSH_VERSION_DD31,\n): Promise<PusherResult | undefined> {\n // Find pending commits between the base snapshot and the main head and push\n // them to the data layer.\n const pending = await withRead(store, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head');\n }\n return localMutations(mainHeadHash, dagRead);\n // Important! Don't hold the lock through an HTTP request!\n });\n\n if (pending.length === 0) {\n return undefined;\n }\n\n // Commit.pending gave us commits in head-first order; the bindings\n // want tail first (in mutation id order).\n pending.reverse();\n\n assert(pushVersion === PUSH_VERSION_DD31);\n\n const pushMutations: FrozenMutationV1[] = [];\n for (const commit of pending) {\n if (commitIsLocalDD31(commit)) {\n pushMutations.push(convertDD31(commit.meta));\n } else {\n throw new Error('Internal non local pending commit');\n }\n }\n assert(clientGroupID);\n const pushReq: PushRequestV1 = {\n profileID,\n clientGroupID,\n mutations: pushMutations,\n pushVersion: PUSH_VERSION_DD31,\n schemaVersion,\n };\n\n lc.debug?.('Starting push...');\n const pushStart = Date.now();\n const pusherResult = await callPusher(pusher, pushReq, requestID);\n lc.debug?.('...Push complete in ', Date.now() - pushStart, 'ms');\n return pusherResult;\n}\n\nasync function callPusher(\n pusher: Pusher,\n body: PushRequestV1,\n requestID: string,\n): Promise<PusherResult> {\n let pusherResult: PusherResult;\n try {\n pusherResult = await pusher(body, requestID);\n } catch (e) {\n throw new PushError(toError(e));\n }\n try {\n assertPusherResult(pusherResult);\n return pusherResult;\n } catch (e) {\n throw new ReportError('Invalid pusher result', toError(e));\n }\n}\n"],"names":["valita.readonlyObject","valita.number","valita.string","valita.object","valita.literal","valita.array"],"mappings":";;;;;;;;;;AA8BO,MAAM,oBAAoB;AAejC,MAAM,mBAA4CA,eAAsB;AAAA,EACtE,IAAIC,OAAO;AAAA,EACX,MAAMC,OAAO;AAAA,EACb,MAAM;AAAA,EACN,WAAWD,OAAO;AAAA,EAClB,UAAU;AACZ,CAAC;AAoB2BE,OAAc;AAAA,EACxC,aAAaC,QAAe,CAAC;AAAA,EAC7B,eAAeF,OAAO;AAAA,EACtB,WAAWA,OAAO;AAAA,EAClB,eAAe;AAAA,EACf,WAAWG,MAAa,gBAAgB;AAC1C,CAAC;AAqBD,SAAS,YAAY,IAAqC;AACxD,SAAO;AAAA,IACL,IAAI,GAAG;AAAA,IACP,MAAM,GAAG;AAAA,IACT,MAAM,GAAG;AAAA,IACT,WAAW,GAAG;AAAA,IACd,UAAU,GAAG;AAAA,EAAA;AAEjB;AAEA,eAAsB,KACpB,WACA,OACA,IACA,WACA,eACA,WACA,QACA,eACA,aACmC;AAGnC,QAAM,UAAU,MAAM,SAAS,OAAO,OAAM,YAAW;AACrD,UAAM,eAAe,MAAM,QAAQ,QAAQ,iBAAiB;AAC5D,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AACA,WAAO,eAAe,cAAc,OAAO;AAAA,EAE7C,CAAC;AAED,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,EACT;AAIA,UAAQ,QAAA;AAER,
|
|
1
|
+
{"version":3,"file":"push.js","sources":["../../../../../replicache/src/sync/push.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {jsonSchema} from '../../../shared/src/json-schema.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport * as valita from '../../../shared/src/valita.ts';\nimport type {Store} from '../dag/store.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type LocalMetaDD31,\n commitIsLocalDD31,\n localMutations,\n} from '../db/commit.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {\n PushError,\n type Pusher,\n type PusherResult,\n assertPusherResult,\n} from '../pusher.ts';\nimport {ReportError} from '../report-error.ts';\nimport {toError} from '../to-error.ts';\nimport {withRead} from '../with-transactions.ts';\nimport {\n type ClientGroupID,\n type ClientID,\n clientGroupIDSchema,\n clientIDSchema,\n} from './ids.ts';\n\nexport const PUSH_VERSION_SDD = 0;\nexport const PUSH_VERSION_DD31 = 1;\n\n/**\n * Mutation describes a single mutation done on the client.\n */\nexport type MutationV1 = {\n readonly id: number;\n readonly name: string;\n readonly args: ReadonlyJSONValue;\n readonly timestamp: number;\n readonly clientID: ClientID;\n};\n\nexport type Mutation = MutationV1;\n\nconst mutationV1Schema: valita.Type<MutationV1> = valita.readonlyObject({\n id: valita.number(),\n name: valita.string(),\n args: jsonSchema,\n timestamp: valita.number(),\n clientID: clientIDSchema,\n});\n\n/**\n * The JSON value used as the body when doing a POST to the [push\n * endpoint](/reference/server-push).\n */\nexport type PushRequestV1 = {\n pushVersion: 1;\n /**\n * `schemaVersion` can optionally be used to specify to the push endpoint\n * version information about the mutators the app is using (e.g., format of\n * mutator args).\n */\n schemaVersion: string;\n profileID: string;\n\n clientGroupID: ClientGroupID;\n mutations: MutationV1[];\n};\n\nconst pushRequestV1Schema = valita.object({\n pushVersion: valita.literal(1),\n schemaVersion: valita.string(),\n profileID: valita.string(),\n clientGroupID: clientGroupIDSchema,\n mutations: valita.array(mutationV1Schema),\n});\n\nexport type PushRequest = PushRequestV1;\n\nexport function assertPushRequestV1(\n value: unknown,\n): asserts value is PushRequestV1 {\n valita.assert(value, pushRequestV1Schema);\n}\n\n/**\n * Mutation describes a single mutation done on the client.\n */\ntype FrozenMutationV1 = {\n readonly id: number;\n readonly name: string;\n readonly args: FrozenJSONValue;\n readonly timestamp: number;\n readonly clientID: ClientID;\n};\n\nfunction convertDD31(lm: LocalMetaDD31): FrozenMutationV1 {\n return {\n id: lm.mutationID,\n name: lm.mutatorName,\n args: lm.mutatorArgsJSON,\n timestamp: lm.timestamp,\n clientID: lm.clientID,\n };\n}\n\nexport async function push(\n requestID: string,\n store: Store,\n lc: LogContext,\n profileID: string,\n clientGroupID: ClientGroupID | undefined,\n _clientID: ClientID,\n pusher: Pusher,\n schemaVersion: string,\n pushVersion: typeof PUSH_VERSION_SDD | typeof PUSH_VERSION_DD31,\n): Promise<PusherResult | undefined> {\n // Find pending commits between the base snapshot and the main head and push\n // them to the data layer.\n const pending = await withRead(store, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head');\n }\n return localMutations(mainHeadHash, dagRead);\n // Important! Don't hold the lock through an HTTP request!\n });\n\n if (pending.length === 0) {\n return undefined;\n }\n\n // Commit.pending gave us commits in head-first order; the bindings\n // want tail first (in mutation id order).\n pending.reverse();\n\n assert(\n pushVersion === PUSH_VERSION_DD31,\n 'Expected pushVersion to be PUSH_VERSION_DD31',\n );\n\n const pushMutations: FrozenMutationV1[] = [];\n for (const commit of pending) {\n if (commitIsLocalDD31(commit)) {\n pushMutations.push(convertDD31(commit.meta));\n } else {\n throw new Error('Internal non local pending commit');\n }\n }\n assert(clientGroupID, 'Expected clientGroupID to be defined');\n const pushReq: PushRequestV1 = {\n profileID,\n clientGroupID,\n mutations: pushMutations,\n pushVersion: PUSH_VERSION_DD31,\n schemaVersion,\n };\n\n lc.debug?.('Starting push...');\n const pushStart = Date.now();\n const pusherResult = await callPusher(pusher, pushReq, requestID);\n lc.debug?.('...Push complete in ', Date.now() - pushStart, 'ms');\n return pusherResult;\n}\n\nasync function callPusher(\n pusher: Pusher,\n body: PushRequestV1,\n requestID: string,\n): Promise<PusherResult> {\n let pusherResult: PusherResult;\n try {\n pusherResult = await pusher(body, requestID);\n } catch (e) {\n throw new PushError(toError(e));\n }\n try {\n assertPusherResult(pusherResult);\n return pusherResult;\n } catch (e) {\n throw new ReportError('Invalid pusher result', toError(e));\n }\n}\n"],"names":["valita.readonlyObject","valita.number","valita.string","valita.object","valita.literal","valita.array"],"mappings":";;;;;;;;;;AA8BO,MAAM,oBAAoB;AAejC,MAAM,mBAA4CA,eAAsB;AAAA,EACtE,IAAIC,OAAO;AAAA,EACX,MAAMC,OAAO;AAAA,EACb,MAAM;AAAA,EACN,WAAWD,OAAO;AAAA,EAClB,UAAU;AACZ,CAAC;AAoB2BE,OAAc;AAAA,EACxC,aAAaC,QAAe,CAAC;AAAA,EAC7B,eAAeF,OAAO;AAAA,EACtB,WAAWA,OAAO;AAAA,EAClB,eAAe;AAAA,EACf,WAAWG,MAAa,gBAAgB;AAC1C,CAAC;AAqBD,SAAS,YAAY,IAAqC;AACxD,SAAO;AAAA,IACL,IAAI,GAAG;AAAA,IACP,MAAM,GAAG;AAAA,IACT,MAAM,GAAG;AAAA,IACT,WAAW,GAAG;AAAA,IACd,UAAU,GAAG;AAAA,EAAA;AAEjB;AAEA,eAAsB,KACpB,WACA,OACA,IACA,WACA,eACA,WACA,QACA,eACA,aACmC;AAGnC,QAAM,UAAU,MAAM,SAAS,OAAO,OAAM,YAAW;AACrD,UAAM,eAAe,MAAM,QAAQ,QAAQ,iBAAiB;AAC5D,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AACA,WAAO,eAAe,cAAc,OAAO;AAAA,EAE7C,CAAC;AAED,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,EACT;AAIA,UAAQ,QAAA;AAER;AAAA,IACE,gBAAgB;AAAA,IAChB;AAAA,EAAA;AAGF,QAAM,gBAAoC,CAAA;AAC1C,aAAW,UAAU,SAAS;AAC5B,QAAI,kBAAkB,MAAM,GAAG;AAC7B,oBAAc,KAAK,YAAY,OAAO,IAAI,CAAC;AAAA,IAC7C,OAAO;AACL,YAAM,IAAI,MAAM,mCAAmC;AAAA,IACrD;AAAA,EACF;AACA,SAAO,eAAe,sCAAsC;AAC5D,QAAM,UAAyB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,aAAa;AAAA,IACb;AAAA,EAAA;AAGF,KAAG,QAAQ,kBAAkB;AAC7B,QAAM,YAAY,KAAK,IAAA;AACvB,QAAM,eAAe,MAAM,WAAW,QAAQ,SAAS,SAAS;AAChE,KAAG,QAAQ,wBAAwB,KAAK,IAAA,IAAQ,WAAW,IAAI;AAC/D,SAAO;AACT;AAEA,eAAe,WACb,QACA,MACA,WACuB;AACvB,MAAI;AACJ,MAAI;AACF,mBAAe,MAAM,OAAO,MAAM,SAAS;AAAA,EAC7C,SAAS,GAAG;AACV,UAAM,IAAI,UAAU,QAAQ,CAAC,CAAC;AAAA,EAChC;AACA,MAAI;AACF,uBAAmB,YAAY;AAC/B,WAAO;AAAA,EACT,SAAS,GAAG;AACV,UAAM,IAAI,YAAY,yBAAyB,QAAQ,CAAC,CAAC;AAAA,EAC3D;AACF;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare function assert(b: unknown, msg
|
|
1
|
+
export declare function assert(b: unknown, msg: string | (() => string)): asserts b;
|
|
2
2
|
export declare function assertString(v: unknown): asserts v is string;
|
|
3
3
|
export declare function assertNumber(v: unknown): asserts v is number;
|
|
4
4
|
export declare function assertBoolean(v: unknown): asserts v is boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asserts.d.ts","sourceRoot":"","sources":["../../../../shared/src/asserts.ts"],"names":[],"mappings":"AAAA,wBAAgB,MAAM,
|
|
1
|
+
{"version":3,"file":"asserts.d.ts","sourceRoot":"","sources":["../../../../shared/src/asserts.ts"],"names":[],"mappings":"AAAA,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAI1E;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,IAAI,MAAM,CAE5D;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,IAAI,MAAM,CAE5D;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,IAAI,OAAO,CAE9D;AAQD,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAK7E;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,IAAI,OAAO,EAAE,CAI9D;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAQzD;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,CAE7D;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAI5D;AAED,wBAAgB,eAAe,CAAC,CAAC,EAC/B,CAAC,EAAE,CAAC,GAAG,SAAS,EAChB,GAAG,SAA6B,GAC/B,OAAO,CAAC,CAAC,IAAI,CAAC,CAIhB;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,CAAC,EAAE,CAAC,GAAG,SAAS,EAChB,GAAG,SAAiC,GACnC,OAAO,CAAC,CAAC,IAAI,CAAC,CAIhB;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,CAAC,EAAE,OAAO,EACV,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,GAC/B,OAAO,CAAC,CAAC,IAAI,CAAC,CAIhB;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,IAAI,UAAU,CAEpE;AAED,wBAAgB,WAAW,IAAI,KAAK,CAAC;AACrC,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;AAK7C,wBAAgB,cAAc,IAAI,KAAK,CAEtC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asserts.js","sources":["../../../../shared/src/asserts.ts"],"sourcesContent":["export function assert(
|
|
1
|
+
{"version":3,"file":"asserts.js","sources":["../../../../shared/src/asserts.ts"],"sourcesContent":["export function assert(b: unknown, msg: string | (() => string)): asserts b {\n if (!b) {\n throw new Error(typeof msg === 'string' ? msg : msg());\n }\n}\n\nexport function assertString(v: unknown): asserts v is string {\n assertType(v, 'string');\n}\n\nexport function assertNumber(v: unknown): asserts v is number {\n assertType(v, 'number');\n}\n\nexport function assertBoolean(v: unknown): asserts v is boolean {\n assertType(v, 'boolean');\n}\n\nfunction assertType(v: unknown, t: string) {\n if (typeof v !== t) {\n throwInvalidType(v, t);\n }\n}\n\nexport function assertObject(v: unknown): asserts v is Record<string, unknown> {\n if (v === null) {\n throwInvalidType(v, 'object');\n }\n assertType(v, 'object');\n}\n\nexport function assertArray(v: unknown): asserts v is unknown[] {\n if (!Array.isArray(v)) {\n throwInvalidType(v, 'array');\n }\n}\n\nexport function invalidType(v: unknown, t: string): string {\n let s = 'Invalid type: ';\n if (v === null || v === undefined) {\n s += v;\n } else {\n s += `${typeof v} \\`${v}\\``;\n }\n return s + `, expected ${t}`;\n}\n\nexport function throwInvalidType(v: unknown, t: string): never {\n throw new Error(invalidType(v, t));\n}\n\nexport function assertNotNull<T>(v: T | null): asserts v is T {\n if (v === null) {\n throw new Error('Expected non-null value');\n }\n}\n\nexport function assertUndefined<T>(\n v: T | undefined,\n msg = 'Expected undefined value',\n): asserts v is T {\n if (v !== undefined) {\n throw new Error(msg);\n }\n}\n\nexport function assertNotUndefined<T>(\n v: T | undefined,\n msg = 'Expected non undefined value',\n): asserts v is T {\n if (v === undefined) {\n throw new Error(msg);\n }\n}\n\nexport function assertInstanceof<T>(\n v: unknown,\n t: new (...args: unknown[]) => T,\n): asserts v is T {\n if (!(v instanceof t)) {\n throw new Error(`Expected instanceof ${t.name}`);\n }\n}\n\nexport function assertUint8Array(v: unknown): asserts v is Uint8Array {\n assertInstanceof(v, Uint8Array);\n}\n\nexport function unreachable(): never;\nexport function unreachable(v: never): never;\nexport function unreachable(_?: never): never {\n throw new Error('Unreachable');\n}\n\nexport function notImplemented(): never {\n throw new Error('Not implemented');\n}\n"],"names":[],"mappings":"AAAO,SAAS,OAAO,GAAY,KAAyC;AAC1E,MAAI,CAAC,GAAG;AACN,UAAM,IAAI,MAAM,OAAO,QAAQ,WAAW,MAAM,KAAK;AAAA,EACvD;AACF;AAEO,SAAS,aAAa,GAAiC;AAC5D,aAAW,GAAG,QAAQ;AACxB;AAEO,SAAS,aAAa,GAAiC;AAC5D,aAAW,GAAG,QAAQ;AACxB;AAEO,SAAS,cAAc,GAAkC;AAC9D,aAAW,GAAG,SAAS;AACzB;AAEA,SAAS,WAAW,GAAY,GAAW;AACzC,MAAI,OAAO,MAAM,GAAG;AAClB,qBAAiB,GAAG,CAAC;AAAA,EACvB;AACF;AAEO,SAAS,aAAa,GAAkD;AAC7E,MAAI,MAAM,MAAM;AACd,qBAAiB,GAAG,QAAQ;AAAA,EAC9B;AACA,aAAW,GAAG,QAAQ;AACxB;AAEO,SAAS,YAAY,GAAoC;AAC9D,MAAI,CAAC,MAAM,QAAQ,CAAC,GAAG;AACrB,qBAAiB,GAAG,OAAO;AAAA,EAC7B;AACF;AAEO,SAAS,YAAY,GAAY,GAAmB;AACzD,MAAI,IAAI;AACR,MAAI,MAAM,QAAQ,MAAM,QAAW;AACjC,SAAK;AAAA,EACP,OAAO;AACL,SAAK,GAAG,OAAO,CAAC,MAAM,CAAC;AAAA,EACzB;AACA,SAAO,IAAI,cAAc,CAAC;AAC5B;AAEO,SAAS,iBAAiB,GAAY,GAAkB;AAC7D,QAAM,IAAI,MAAM,YAAY,GAAG,CAAC,CAAC;AACnC;AAEO,SAAS,cAAiB,GAA6B;AAC5D,MAAI,MAAM,MAAM;AACd,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AACF;AAWO,SAAS,mBACd,GACA,MAAM,gCACU;AAChB,MAAI,MAAM,QAAW;AACnB,UAAM,IAAI,MAAM,GAAG;AAAA,EACrB;AACF;AAiBO,SAAS,YAAY,GAAkB;AAC5C,QAAM,IAAI,MAAM,aAAa;AAC/B;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../../z2s/src/compiler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAQ7C,OAAO,EAAC,KAAK,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAGxD,OAAO,KAAK,EACV,GAAG,EAEH,kBAAkB,EAElB,WAAW,EAEX,QAAQ,EACR,eAAe,EAEhB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAEL,KAAK,UAAU,EAChB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAEV,YAAY,EACb,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,2BAA2B,CAAC;AAWtD,KAAK,KAAK,GAAG;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,MAAM,EAAE,YAAY,CAAC;IAErB,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAQF,wBAAgB,OAAO,CACrB,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,GAAG,EACR,MAAM,CAAC,EAAE,MAAM,GACd,QAAQ,CAgBV;AA4CD,wBAAgB,KAAK,CACnB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,QAAQ,EAAE,OAAO,GAAG,SAAS,GAC5B,QAAQ,CAWV;AAUD,wBAAgB,OAAO,CACrB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,QAAQ,GAAG,SAAS,EAC7B,KAAK,EAAE,KAAK,GACX,QAAQ,CAqBV;AAuMD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,SAAS,eAAe,EAAE,EACxC,cAAc,EAAE,SAAS,MAAM,EAAE,GAChC,CAAC,UAAU,EAAE,KAAK,KAAK,QAAQ,CAiBjC;AAED,wBAAgB,MAAM,CACpB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,GACX,QAAQ,CAgCV;AAED,wBAAgB,GAAG,CACjB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,GACX,QAAQ,CAMV;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,GACX,QAAQ,CAIV;
|
|
1
|
+
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../../z2s/src/compiler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAQ7C,OAAO,EAAC,KAAK,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAGxD,OAAO,KAAK,EACV,GAAG,EAEH,kBAAkB,EAElB,WAAW,EAEX,QAAQ,EACR,eAAe,EAEhB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAEL,KAAK,UAAU,EAChB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAEV,YAAY,EACb,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,2BAA2B,CAAC;AAWtD,KAAK,KAAK,GAAG;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,MAAM,EAAE,YAAY,CAAC;IAErB,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAQF,wBAAgB,OAAO,CACrB,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,GAAG,EACR,MAAM,CAAC,EAAE,MAAM,GACd,QAAQ,CAgBV;AA4CD,wBAAgB,KAAK,CACnB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,QAAQ,EAAE,OAAO,GAAG,SAAS,GAC5B,QAAQ,CAWV;AAUD,wBAAgB,OAAO,CACrB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,QAAQ,GAAG,SAAS,EAC7B,KAAK,EAAE,KAAK,GACX,QAAQ,CAqBV;AAuMD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,SAAS,eAAe,EAAE,EACxC,cAAc,EAAE,SAAS,MAAM,EAAE,GAChC,CAAC,UAAU,EAAE,KAAK,KAAK,QAAQ,CAiBjC;AAED,wBAAgB,MAAM,CACpB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,GACX,QAAQ,CAgCV;AAED,wBAAgB,GAAG,CACjB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,GACX,QAAQ,CAMV;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,GACX,QAAQ,CAIV;AA2GD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,kBAAkB,GAC/B;IACD,IAAI,EAAE,QAAQ,CAAC;IACf,mBAAmB,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;CAC/D,CA2BA;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,kBAAkB,GAC/B;IACD;QACE,KAAK,EAAE,KAAK,CAAC;QACb,WAAW,EAAE,WAAW,CAAC;QACzB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;KAC3B;IACD;QAAC,KAAK,EAAE,KAAK,CAAC;QAAC,WAAW,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;KAAC;CACpE,CAsBA;AAiDD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAMhE"}
|
package/out/z2s/src/compiler.js
CHANGED
|
@@ -362,7 +362,10 @@ function literalValueComparison(spec, valuePos, table, otherValuePos, plural) {
|
|
|
362
362
|
true
|
|
363
363
|
);
|
|
364
364
|
case "literal": {
|
|
365
|
-
assert(
|
|
365
|
+
assert(
|
|
366
|
+
plural === Array.isArray(valuePos.value),
|
|
367
|
+
"Expected plural flag to match whether value is an array"
|
|
368
|
+
);
|
|
366
369
|
if (Array.isArray(valuePos.value)) {
|
|
367
370
|
if (valuePos.value.length > 0) {
|
|
368
371
|
return sqlConvertPluralLiteralArg(
|
|
@@ -425,7 +428,10 @@ function pullTablesForJunction(spec, relationship) {
|
|
|
425
428
|
"Too many related tables for a junction edge"
|
|
426
429
|
);
|
|
427
430
|
const otherRelationship = relationship.subquery.related[0];
|
|
428
|
-
assert(
|
|
431
|
+
assert(
|
|
432
|
+
!otherRelationship.hidden,
|
|
433
|
+
"Expected junction edge relationship to not be hidden"
|
|
434
|
+
);
|
|
429
435
|
return [
|
|
430
436
|
{
|
|
431
437
|
table: makeTable(spec, relationship.subquery.table),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.js","sources":["../../../../z2s/src/compiler.ts"],"sourcesContent":["import type {SQLQuery} from '@databases/sql';\nimport {last, zip} from '../../shared/src/arrays.ts';\nimport {assert, unreachable} from '../../shared/src/asserts.ts';\nimport {\n parse as parseBigIntJson,\n type JSONValue as BigIntJSONValue,\n} from '../../shared/src/bigint-json.ts';\nimport {hasOwn} from '../../shared/src/has-own.ts';\nimport {type JSONValue} from '../../shared/src/json.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {pgToZqlStringTypeMap} from '../../zero-cache/src/types/pg-data-type.ts';\nimport type {\n AST,\n Condition,\n CorrelatedSubquery,\n CorrelatedSubqueryCondition,\n Correlation,\n LiteralReference,\n Ordering,\n SimpleCondition,\n ValuePosition,\n} from '../../zero-protocol/src/ast.ts';\nimport {\n clientToServer,\n type NameMapper,\n} from '../../zero-schema/src/name-mapper.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {\n ServerColumnSchema,\n ServerSchema,\n} from '../../zero-types/src/server-schema.ts';\nimport type {Format} from '../../zql/src/ivm/view.ts';\nimport {completeOrdering} from '../../zql/src/query/complete-ordering.ts';\nimport {\n sql,\n sqlConvertColumnArg,\n sqlConvertPluralLiteralArg,\n sqlConvertSingularLiteralArg,\n Z2S_COLLATION,\n type PluralLiteralType,\n} from './sql.ts';\n\ntype Table = {\n zql: string;\n alias: string;\n};\n\ntype QualifiedColumn = {\n table: Table;\n zql: string;\n};\n\ntype ServerSpec = {\n schema: ServerSchema;\n // maps zql names to server names\n mapper: NameMapper;\n};\n\nexport type Spec = {\n server: ServerSpec;\n zql: Schema['tables'];\n aliasCount: number;\n};\n\nconst ZQL_RESULT_KEY = 'zql_result';\nconst ZQL_RESULT_KEY_IDENT = sql.ident(ZQL_RESULT_KEY);\n\nconst ZQL_RESULT_TABLE_KEY = 'zql_root';\nconst ZQL_RESULT_TABLE_IDENT = sql.ident(ZQL_RESULT_TABLE_KEY);\n\nexport function compile(\n serverSchema: ServerSchema,\n zqlSchema: Schema,\n ast: AST,\n format?: Format,\n): SQLQuery {\n ast = completeOrdering(\n ast,\n tableName => zqlSchema.tables[tableName].primaryKey,\n );\n const spec: Spec = {\n aliasCount: 0,\n server: {\n schema: serverSchema,\n mapper: clientToServer(zqlSchema.tables),\n },\n zql: zqlSchema.tables,\n };\n return sql`SELECT \n ${toJSON(ZQL_RESULT_TABLE_KEY, format?.singular)}::text AS ${ZQL_RESULT_KEY_IDENT}\n FROM (${select(spec, ast, format)}) ${ZQL_RESULT_TABLE_IDENT}`;\n}\n\nfunction select(\n spec: Spec,\n ast: AST,\n format: Format | undefined,\n correlate?: (childTable: Table) => SQLQuery,\n): SQLQuery {\n const table = makeTable(spec, ast.table);\n const selectionSet = related(spec, ast.related ?? [], format, table);\n const tableSchema = spec.zql[ast.table];\n const usedAliases = new Set<string>(\n ast.related?.map(r => r.subquery.alias ?? ''),\n );\n for (const column of Object.keys(tableSchema.columns)) {\n if (!usedAliases.has(column)) {\n selectionSet.push(\n selectIdent(spec.server, {\n table,\n zql: column,\n }),\n );\n }\n }\n\n let appliedWhere = false;\n function maybeWhere(test: unknown | undefined) {\n if (!test) {\n return sql``;\n }\n\n const ret = appliedWhere ? sql`AND` : sql`WHERE`;\n appliedWhere = true;\n return ret;\n }\n\n return sql`SELECT ${sql.join(selectionSet, ',')}\n FROM ${fromIdent(spec.server, table)}\n ${maybeWhere(ast.where)} ${where(spec, ast.where, table)}\n ${maybeWhere(correlate)} ${correlate ? correlate(table) : sql``}\n ${orderBy(spec, ast.orderBy, table)}\n ${limit(ast.limit, format?.singular)}`;\n}\n\nexport function limit(\n limit: number | undefined,\n singular: boolean | undefined,\n): SQLQuery {\n if (limit === 0) {\n return sql`LIMIT 0`;\n }\n if (singular) {\n return sql`LIMIT 1`;\n }\n if (limit === undefined) {\n return sql``;\n }\n return sql`LIMIT ${sqlConvertSingularLiteralArg(limit)}`;\n}\n\nfunction makeTable(spec: Spec, zql: string, alias?: string): Table {\n alias = alias ?? zql + '_' + spec.aliasCount++;\n return {\n zql,\n alias,\n };\n}\n\nexport function orderBy(\n spec: Spec,\n orderBy: Ordering | undefined,\n table: Table,\n): SQLQuery {\n if (!orderBy) {\n return sql``;\n }\n return sql`ORDER BY ${sql.join(\n orderBy.map(([col, dir]) => {\n const serverColumnSchema = getServerColumn(spec.server, table, col);\n return dir === 'asc'\n ? // Oh postgres. The table must be referred to by client name but the column by server name.\n // E.g., `SELECT server_col as client_col FROM server_table as client_table ORDER BY client_Table.server_col`\n sql`${colIdent(spec.server, {\n table,\n zql: col,\n })}${maybeCollate(serverColumnSchema)} ASC NULLS FIRST`\n : sql`${colIdent(spec.server, {\n table,\n zql: col,\n })}${maybeCollate(serverColumnSchema)} DESC NULLS LAST`;\n }),\n ', ',\n )}`;\n}\n\nfunction maybeCollate(serverColumnSchema: ServerColumnSchema): SQLQuery {\n if (serverColumnSchema.type === 'uuid' || serverColumnSchema.isEnum) {\n return sql`::text COLLATE ${sql.ident(Z2S_COLLATION)}`;\n }\n if (Object.hasOwn(pgToZqlStringTypeMap, serverColumnSchema.type)) {\n return sql` COLLATE ${sql.ident(Z2S_COLLATION)}`;\n }\n\n return sql``;\n}\n\nfunction related(\n spec: Spec,\n relationships: readonly CorrelatedSubquery[],\n format: Format | undefined,\n parentTable: Table,\n): SQLQuery[] {\n return relationships.map(relationship =>\n relationshipSubquery(\n spec,\n relationship,\n format?.relationships[must(relationship.subquery.alias)],\n parentTable,\n ),\n );\n}\n\nfunction relationshipSubquery(\n spec: Spec,\n relationship: CorrelatedSubquery,\n format: Format | undefined,\n parentTable: Table,\n): SQLQuery {\n const innerAlias = `inner_${relationship.subquery.alias}`;\n if (relationship.hidden) {\n const {join, participatingTables} = makeJunctionJoin(spec, relationship);\n const lastTable = must(last(participatingTables)).table;\n\n assert(\n relationship.subquery.related,\n 'hidden relationship must be a junction',\n );\n const nestedAst = relationship.subquery.related[0].subquery;\n const selectionSet = related(\n spec,\n nestedAst.related ?? [],\n format,\n lastTable,\n );\n const tableSchema = spec.zql[nestedAst.table];\n for (const column of Object.keys(tableSchema.columns)) {\n selectionSet.push(\n selectIdent(spec.server, {\n table: lastTable,\n zql: column,\n }),\n );\n }\n\n return sql`(\n SELECT ${toJSON(innerAlias, format?.singular)} FROM (SELECT ${sql.join(\n selectionSet,\n ',',\n )} FROM ${join} WHERE (${makeCorrelator(\n spec,\n relationship.correlation.parentField.map(f => ({\n table: parentTable,\n zql: f,\n })),\n relationship.correlation.childField,\n )(participatingTables[0].table)}) ${\n nestedAst.where\n ? sql`AND ${where(spec, nestedAst.where, lastTable)}`\n : sql``\n } ${orderBy(spec, nestedAst.orderBy, lastTable)} ${limit(\n last(participatingTables)?.limit,\n format?.singular,\n )} ) ${sql.ident(innerAlias)}\n ) as ${sql.ident(relationship.subquery.alias)}`;\n }\n\n return sql`(\n SELECT ${toJSON(innerAlias, format?.singular)} FROM (${select(\n spec,\n relationship.subquery,\n format,\n makeCorrelator(\n spec,\n relationship.correlation.parentField.map(f => ({\n table: parentTable,\n zql: f,\n })),\n relationship.correlation.childField,\n ),\n )}) ${sql.ident(innerAlias)}\n ) as ${sql.ident(relationship.subquery.alias)}`;\n}\n\nfunction where(\n spec: Spec,\n condition: Condition | undefined,\n table: Table,\n): SQLQuery {\n if (!condition) {\n return sql``;\n }\n\n switch (condition.type) {\n case 'and':\n return sql`(${sql.join(\n condition.conditions.map(c => where(spec, c, table)),\n ' AND ',\n )})`;\n case 'or':\n return sql`(${sql.join(\n condition.conditions.map(c => where(spec, c, table)),\n ' OR ',\n )})`;\n case 'correlatedSubquery':\n if (condition.scalar) {\n return scalarSubquery(spec, condition, table);\n }\n return exists(spec, condition, table);\n case 'simple':\n return simple(spec, condition, table);\n }\n}\n\nfunction exists(\n spec: Spec,\n condition: CorrelatedSubqueryCondition,\n parentTable: Table,\n): SQLQuery {\n switch (condition.op) {\n case 'EXISTS':\n return sql`EXISTS (${select(\n spec,\n condition.related.subquery,\n undefined,\n makeCorrelator(\n spec,\n condition.related.correlation.parentField.map(f => ({\n table: parentTable,\n zql: f,\n })),\n condition.related.correlation.childField,\n ),\n )})`;\n case 'NOT EXISTS':\n return sql`NOT EXISTS (${select(\n spec,\n condition.related.subquery,\n undefined,\n makeCorrelator(\n spec,\n condition.related.correlation.parentField.map(f => ({\n table: parentTable,\n zql: f,\n })),\n condition.related.correlation.childField,\n ),\n )})`;\n }\n}\n\nfunction scalarSubquery(\n spec: Spec,\n condition: CorrelatedSubqueryCondition,\n parentTable: Table,\n): SQLQuery {\n const parentField = condition.related.correlation.parentField[0];\n const childField = condition.related.correlation.childField[0];\n const subqueryAST = condition.related.subquery;\n\n const parentCol = colIdent(spec.server, {\n table: parentTable,\n zql: parentField,\n });\n\n const subqueryTable = makeTable(spec, subqueryAST.table);\n const childCol = colIdent(spec.server, {\n table: subqueryTable,\n zql: childField,\n });\n\n const op = sql.__dangerous__rawValue(\n condition.op === 'EXISTS' ? '=' : 'IS NOT',\n );\n\n const subqueryWhere = subqueryAST.where\n ? sql`WHERE ${where(spec, subqueryAST.where, subqueryTable)}`\n : sql``;\n const subqueryOrderBy = orderBy(spec, subqueryAST.orderBy, subqueryTable);\n\n return sql`${parentCol} ${op} (SELECT ${childCol} FROM ${fromIdent(spec.server, subqueryTable)} ${subqueryWhere} ${subqueryOrderBy} LIMIT 1)`;\n}\n\nexport function makeCorrelator(\n spec: Spec,\n parentFields: readonly QualifiedColumn[],\n childZqlFields: readonly string[],\n): (childTable: Table) => SQLQuery {\n return (childTable: Table) => {\n const childFields = childZqlFields.map(zqlField => ({\n table: childTable,\n zql: zqlField,\n }));\n return sql.join(\n zip(parentFields, childFields).map(\n ([parentColumn, childColumn]) =>\n sql`${colIdent(spec.server, parentColumn)} = ${colIdent(\n spec.server,\n childColumn,\n )}`,\n ),\n ' AND ',\n );\n };\n}\n\nexport function simple(\n spec: Spec,\n condition: SimpleCondition,\n table: Table,\n): SQLQuery {\n switch (condition.op) {\n case '!=':\n case '<':\n case '<=':\n case '=':\n case '>':\n case '>=':\n case 'ILIKE':\n case 'LIKE':\n case 'NOT ILIKE':\n case 'NOT LIKE':\n return sql`${valueComparison(\n spec,\n condition.left,\n table,\n condition.right,\n false,\n )} ${sql.__dangerous__rawValue(condition.op)} ${valueComparison(\n spec,\n condition.right,\n table,\n condition.left,\n false,\n )}`;\n case 'NOT IN':\n case 'IN':\n return any(spec, condition, table);\n case 'IS':\n case 'IS NOT':\n return distinctFrom(spec, condition, table);\n }\n}\n\nexport function any(\n spec: Spec,\n condition: SimpleCondition,\n table: Table,\n): SQLQuery {\n return sql`${condition.op === 'NOT IN' ? sql`NOT` : sql``}\n (\n ${valueComparison(spec, condition.left, table, condition.right, false)} = ANY \n (${valueComparison(spec, condition.right, table, condition.left, true)})\n )`;\n}\n\nexport function distinctFrom(\n spec: Spec,\n condition: SimpleCondition,\n table: Table,\n): SQLQuery {\n return sql`${valueComparison(spec, condition.left, table, condition.right, false)} ${\n condition.op === 'IS' ? sql`IS NOT DISTINCT FROM` : sql`IS DISTINCT FROM`\n } ${valueComparison(spec, condition.right, table, condition.left, false)}`;\n}\n\nfunction valueComparison(\n spec: Spec,\n valuePos: ValuePosition,\n table: Table,\n otherValuePos: ValuePosition,\n plural: boolean,\n): SQLQuery {\n const valuePosType = valuePos.type;\n switch (valuePosType) {\n case 'column': {\n const serverColumnSchema = getServerColumn(\n spec.server,\n table,\n valuePos.name,\n );\n const qualified: QualifiedColumn = {\n table,\n zql: valuePos.name,\n };\n if (serverColumnSchema.type === 'uuid' || serverColumnSchema.isEnum) {\n return sql`${colIdent(spec.server, qualified)}::text`;\n }\n return colIdent(spec.server, qualified);\n }\n case 'literal':\n return literalValueComparison(\n spec,\n valuePos,\n table,\n otherValuePos,\n plural,\n );\n case 'static':\n throw new Error(\n 'Static parameters must be bound to a value before compiling to SQL',\n );\n default:\n unreachable(valuePosType);\n break;\n }\n}\n\nfunction literalValueComparison(\n spec: Spec,\n valuePos: LiteralReference,\n table: Table,\n otherValuePos: ValuePosition,\n plural: boolean,\n): SQLQuery {\n const otherType = otherValuePos.type;\n switch (otherType) {\n case 'column':\n return sqlConvertColumnArg(\n getServerColumn(spec.server, table, otherValuePos.name),\n valuePos.value,\n plural,\n true,\n );\n case 'literal': {\n assert(plural === Array.isArray(valuePos.value));\n if (Array.isArray(valuePos.value)) {\n if (valuePos.value.length > 0) {\n // If the array is non-empty base its type on its first\n // element\n return sqlConvertPluralLiteralArg(\n typeof valuePos.value[0] as PluralLiteralType,\n valuePos.value as PluralLiteralType[],\n );\n }\n // If the array is empty, base its type on the other value\n // position's type (as long as the other value position is non-null,\n // cannot have a null[]).\n if (otherValuePos.value !== null) {\n return sqlConvertPluralLiteralArg(\n typeof otherValuePos.value as PluralLiteralType,\n [],\n );\n }\n // If the other value position is null, it can be compared to any\n // type of empty array, chose 'string' arbitrarily.\n return sqlConvertPluralLiteralArg('string', []);\n }\n if (\n typeof valuePos.value === 'string' ||\n typeof valuePos.value === 'number' ||\n typeof valuePos.value === 'boolean'\n ) {\n return sqlConvertSingularLiteralArg(valuePos.value);\n }\n throw new Error(\n `Literal of unexpected type. ${valuePos.value} of type ${typeof valuePos.value}`,\n );\n }\n case 'static':\n throw new Error(\n 'Static parameters must be bound to a value before compiling to SQL',\n );\n default:\n unreachable(otherType);\n }\n}\n\nexport function makeJunctionJoin(\n spec: Spec,\n relationship: CorrelatedSubquery,\n): {\n join: SQLQuery;\n participatingTables: ReturnType<typeof pullTablesForJunction>;\n} {\n const participatingTables = pullTablesForJunction(spec, relationship);\n const joins: SQLQuery[] = [];\n\n for (const {table} of participatingTables) {\n if (joins.length === 0) {\n joins.push(fromIdent(spec.server, table));\n continue;\n }\n joins.push(\n sql` JOIN ${fromIdent(spec.server, table)} ON ${makeCorrelator(\n spec,\n participatingTables[joins.length].correlation.parentField.map(f => ({\n table: participatingTables[joins.length - 1].table,\n zql: f,\n })),\n participatingTables[joins.length].correlation.childField,\n )(participatingTables[joins.length].table)}`,\n );\n }\n\n return {\n join: sql`${sql.join(joins, '')}`,\n participatingTables,\n // lastTable: participatingTables[participatingTables.length - 1].table,\n // lastLimit: participatingTables[participatingTables.length - 1].limit,\n };\n}\n\nexport function pullTablesForJunction(\n spec: Spec,\n relationship: CorrelatedSubquery,\n): [\n {\n table: Table;\n correlation: Correlation;\n limit: number | undefined;\n },\n {table: Table; correlation: Correlation; limit: number | undefined},\n] {\n assert(\n relationship.subquery.related?.length === 1,\n 'Too many related tables for a junction edge',\n );\n const otherRelationship = relationship.subquery.related[0];\n assert(!otherRelationship.hidden);\n return [\n {\n table: makeTable(spec, relationship.subquery.table),\n correlation: relationship.correlation,\n limit: relationship.subquery.limit,\n },\n {\n table: makeTable(spec, otherRelationship.subquery.table),\n correlation: otherRelationship.correlation,\n limit: otherRelationship.subquery.limit,\n },\n ];\n}\n\nfunction toJSON(table: string, singular = false): SQLQuery {\n return sql`${\n singular ? sql`` : sql`COALESCE(json_agg`\n }(row_to_json(${sql.ident(table)}))${singular ? sql`` : sql`, '[]'::json)`}`;\n}\n\nfunction selectIdent(server: ServerSpec, column: QualifiedColumn): SQLQuery {\n const serverColumnSchema =\n server.schema[server.mapper.tableName(column.table.zql)][\n server.mapper.columnName(column.table.zql, column.zql)\n ];\n const serverType = serverColumnSchema.type;\n if (\n !serverColumnSchema.isEnum &&\n (serverType === 'date' ||\n serverType === 'timestamp' ||\n serverType === 'timestamp without time zone' ||\n serverType === 'timestamptz' ||\n serverType === 'timestamp with time zone')\n ) {\n if (serverColumnSchema.isArray) {\n // Map EXTRACT(EPOCH FROM ...) * 1000 over array elements\n return sql`ARRAY(SELECT EXTRACT(EPOCH FROM unnest(${colIdent(server, column)})) * 1000) as ${sql.ident(column.zql)}`;\n }\n return sql`EXTRACT(EPOCH FROM ${colIdent(server, column)}) * 1000 as ${sql.ident(column.zql)}`;\n }\n return sql`${colIdent(server, column)} as ${sql.ident(column.zql)}`;\n}\n\nfunction colIdent(server: ServerSpec, column: QualifiedColumn) {\n return sql.ident(\n column.table.alias,\n server.mapper.columnName(column.table.zql, column.zql),\n );\n}\n\nfunction fromIdent(server: ServerSpec, table: Table) {\n return sql`${sql.ident(server.mapper.tableName(table.zql))} AS ${sql.ident(table.alias)}`;\n}\n\nfunction getServerColumn(spec: ServerSpec, table: Table, zqlColumn: string) {\n return spec.schema[spec.mapper.tableName(table.zql)][\n spec.mapper.columnName(table.zql, zqlColumn)\n ];\n}\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport function extractZqlResult(pgResult: Array<any>): JSONValue {\n const bigIntJson: BigIntJSONValue = parseBigIntJson(\n pgResult[0][ZQL_RESULT_KEY],\n );\n assertJSONValue(bigIntJson);\n return bigIntJson;\n}\n\nfunction assertJSONValue(v: BigIntJSONValue): asserts v is JSONValue {\n const path = findPathToBigInt(v);\n if (path) {\n throw new Error(`Value exceeds safe Number range. ${path}`);\n }\n}\n\nfunction findPathToBigInt(v: BigIntJSONValue): string | undefined {\n const typeOfV = typeof v;\n switch (typeOfV) {\n case 'bigint':\n return ` = ${v}`;\n case 'object': {\n if (v === null) {\n return;\n }\n if (Array.isArray(v)) {\n for (let i = 0; i < v.length; i++) {\n const path = findPathToBigInt(v[i]);\n if (path) {\n return `[${i}]${path}`;\n }\n }\n return undefined;\n }\n\n const o = v as Record<string, BigIntJSONValue>;\n for (const k in o) {\n if (hasOwn(o, k)) {\n const path = findPathToBigInt(o[k]);\n if (path) {\n return `['${k}']${path}`;\n }\n }\n }\n return undefined;\n }\n case 'number':\n return undefined;\n case 'boolean':\n return undefined;\n default:\n return undefined;\n }\n}\n"],"names":["limit","orderBy","parseBigIntJson"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compiler.js","sources":["../../../../z2s/src/compiler.ts"],"sourcesContent":["import type {SQLQuery} from '@databases/sql';\nimport {last, zip} from '../../shared/src/arrays.ts';\nimport {assert, unreachable} from '../../shared/src/asserts.ts';\nimport {\n parse as parseBigIntJson,\n type JSONValue as BigIntJSONValue,\n} from '../../shared/src/bigint-json.ts';\nimport {hasOwn} from '../../shared/src/has-own.ts';\nimport {type JSONValue} from '../../shared/src/json.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {pgToZqlStringTypeMap} from '../../zero-cache/src/types/pg-data-type.ts';\nimport type {\n AST,\n Condition,\n CorrelatedSubquery,\n CorrelatedSubqueryCondition,\n Correlation,\n LiteralReference,\n Ordering,\n SimpleCondition,\n ValuePosition,\n} from '../../zero-protocol/src/ast.ts';\nimport {\n clientToServer,\n type NameMapper,\n} from '../../zero-schema/src/name-mapper.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {\n ServerColumnSchema,\n ServerSchema,\n} from '../../zero-types/src/server-schema.ts';\nimport type {Format} from '../../zql/src/ivm/view.ts';\nimport {completeOrdering} from '../../zql/src/query/complete-ordering.ts';\nimport {\n sql,\n sqlConvertColumnArg,\n sqlConvertPluralLiteralArg,\n sqlConvertSingularLiteralArg,\n Z2S_COLLATION,\n type PluralLiteralType,\n} from './sql.ts';\n\ntype Table = {\n zql: string;\n alias: string;\n};\n\ntype QualifiedColumn = {\n table: Table;\n zql: string;\n};\n\ntype ServerSpec = {\n schema: ServerSchema;\n // maps zql names to server names\n mapper: NameMapper;\n};\n\nexport type Spec = {\n server: ServerSpec;\n zql: Schema['tables'];\n aliasCount: number;\n};\n\nconst ZQL_RESULT_KEY = 'zql_result';\nconst ZQL_RESULT_KEY_IDENT = sql.ident(ZQL_RESULT_KEY);\n\nconst ZQL_RESULT_TABLE_KEY = 'zql_root';\nconst ZQL_RESULT_TABLE_IDENT = sql.ident(ZQL_RESULT_TABLE_KEY);\n\nexport function compile(\n serverSchema: ServerSchema,\n zqlSchema: Schema,\n ast: AST,\n format?: Format,\n): SQLQuery {\n ast = completeOrdering(\n ast,\n tableName => zqlSchema.tables[tableName].primaryKey,\n );\n const spec: Spec = {\n aliasCount: 0,\n server: {\n schema: serverSchema,\n mapper: clientToServer(zqlSchema.tables),\n },\n zql: zqlSchema.tables,\n };\n return sql`SELECT \n ${toJSON(ZQL_RESULT_TABLE_KEY, format?.singular)}::text AS ${ZQL_RESULT_KEY_IDENT}\n FROM (${select(spec, ast, format)}) ${ZQL_RESULT_TABLE_IDENT}`;\n}\n\nfunction select(\n spec: Spec,\n ast: AST,\n format: Format | undefined,\n correlate?: (childTable: Table) => SQLQuery,\n): SQLQuery {\n const table = makeTable(spec, ast.table);\n const selectionSet = related(spec, ast.related ?? [], format, table);\n const tableSchema = spec.zql[ast.table];\n const usedAliases = new Set<string>(\n ast.related?.map(r => r.subquery.alias ?? ''),\n );\n for (const column of Object.keys(tableSchema.columns)) {\n if (!usedAliases.has(column)) {\n selectionSet.push(\n selectIdent(spec.server, {\n table,\n zql: column,\n }),\n );\n }\n }\n\n let appliedWhere = false;\n function maybeWhere(test: unknown | undefined) {\n if (!test) {\n return sql``;\n }\n\n const ret = appliedWhere ? sql`AND` : sql`WHERE`;\n appliedWhere = true;\n return ret;\n }\n\n return sql`SELECT ${sql.join(selectionSet, ',')}\n FROM ${fromIdent(spec.server, table)}\n ${maybeWhere(ast.where)} ${where(spec, ast.where, table)}\n ${maybeWhere(correlate)} ${correlate ? correlate(table) : sql``}\n ${orderBy(spec, ast.orderBy, table)}\n ${limit(ast.limit, format?.singular)}`;\n}\n\nexport function limit(\n limit: number | undefined,\n singular: boolean | undefined,\n): SQLQuery {\n if (limit === 0) {\n return sql`LIMIT 0`;\n }\n if (singular) {\n return sql`LIMIT 1`;\n }\n if (limit === undefined) {\n return sql``;\n }\n return sql`LIMIT ${sqlConvertSingularLiteralArg(limit)}`;\n}\n\nfunction makeTable(spec: Spec, zql: string, alias?: string): Table {\n alias = alias ?? zql + '_' + spec.aliasCount++;\n return {\n zql,\n alias,\n };\n}\n\nexport function orderBy(\n spec: Spec,\n orderBy: Ordering | undefined,\n table: Table,\n): SQLQuery {\n if (!orderBy) {\n return sql``;\n }\n return sql`ORDER BY ${sql.join(\n orderBy.map(([col, dir]) => {\n const serverColumnSchema = getServerColumn(spec.server, table, col);\n return dir === 'asc'\n ? // Oh postgres. The table must be referred to by client name but the column by server name.\n // E.g., `SELECT server_col as client_col FROM server_table as client_table ORDER BY client_Table.server_col`\n sql`${colIdent(spec.server, {\n table,\n zql: col,\n })}${maybeCollate(serverColumnSchema)} ASC NULLS FIRST`\n : sql`${colIdent(spec.server, {\n table,\n zql: col,\n })}${maybeCollate(serverColumnSchema)} DESC NULLS LAST`;\n }),\n ', ',\n )}`;\n}\n\nfunction maybeCollate(serverColumnSchema: ServerColumnSchema): SQLQuery {\n if (serverColumnSchema.type === 'uuid' || serverColumnSchema.isEnum) {\n return sql`::text COLLATE ${sql.ident(Z2S_COLLATION)}`;\n }\n if (Object.hasOwn(pgToZqlStringTypeMap, serverColumnSchema.type)) {\n return sql` COLLATE ${sql.ident(Z2S_COLLATION)}`;\n }\n\n return sql``;\n}\n\nfunction related(\n spec: Spec,\n relationships: readonly CorrelatedSubquery[],\n format: Format | undefined,\n parentTable: Table,\n): SQLQuery[] {\n return relationships.map(relationship =>\n relationshipSubquery(\n spec,\n relationship,\n format?.relationships[must(relationship.subquery.alias)],\n parentTable,\n ),\n );\n}\n\nfunction relationshipSubquery(\n spec: Spec,\n relationship: CorrelatedSubquery,\n format: Format | undefined,\n parentTable: Table,\n): SQLQuery {\n const innerAlias = `inner_${relationship.subquery.alias}`;\n if (relationship.hidden) {\n const {join, participatingTables} = makeJunctionJoin(spec, relationship);\n const lastTable = must(last(participatingTables)).table;\n\n assert(\n relationship.subquery.related,\n 'hidden relationship must be a junction',\n );\n const nestedAst = relationship.subquery.related[0].subquery;\n const selectionSet = related(\n spec,\n nestedAst.related ?? [],\n format,\n lastTable,\n );\n const tableSchema = spec.zql[nestedAst.table];\n for (const column of Object.keys(tableSchema.columns)) {\n selectionSet.push(\n selectIdent(spec.server, {\n table: lastTable,\n zql: column,\n }),\n );\n }\n\n return sql`(\n SELECT ${toJSON(innerAlias, format?.singular)} FROM (SELECT ${sql.join(\n selectionSet,\n ',',\n )} FROM ${join} WHERE (${makeCorrelator(\n spec,\n relationship.correlation.parentField.map(f => ({\n table: parentTable,\n zql: f,\n })),\n relationship.correlation.childField,\n )(participatingTables[0].table)}) ${\n nestedAst.where\n ? sql`AND ${where(spec, nestedAst.where, lastTable)}`\n : sql``\n } ${orderBy(spec, nestedAst.orderBy, lastTable)} ${limit(\n last(participatingTables)?.limit,\n format?.singular,\n )} ) ${sql.ident(innerAlias)}\n ) as ${sql.ident(relationship.subquery.alias)}`;\n }\n\n return sql`(\n SELECT ${toJSON(innerAlias, format?.singular)} FROM (${select(\n spec,\n relationship.subquery,\n format,\n makeCorrelator(\n spec,\n relationship.correlation.parentField.map(f => ({\n table: parentTable,\n zql: f,\n })),\n relationship.correlation.childField,\n ),\n )}) ${sql.ident(innerAlias)}\n ) as ${sql.ident(relationship.subquery.alias)}`;\n}\n\nfunction where(\n spec: Spec,\n condition: Condition | undefined,\n table: Table,\n): SQLQuery {\n if (!condition) {\n return sql``;\n }\n\n switch (condition.type) {\n case 'and':\n return sql`(${sql.join(\n condition.conditions.map(c => where(spec, c, table)),\n ' AND ',\n )})`;\n case 'or':\n return sql`(${sql.join(\n condition.conditions.map(c => where(spec, c, table)),\n ' OR ',\n )})`;\n case 'correlatedSubquery':\n if (condition.scalar) {\n return scalarSubquery(spec, condition, table);\n }\n return exists(spec, condition, table);\n case 'simple':\n return simple(spec, condition, table);\n }\n}\n\nfunction exists(\n spec: Spec,\n condition: CorrelatedSubqueryCondition,\n parentTable: Table,\n): SQLQuery {\n switch (condition.op) {\n case 'EXISTS':\n return sql`EXISTS (${select(\n spec,\n condition.related.subquery,\n undefined,\n makeCorrelator(\n spec,\n condition.related.correlation.parentField.map(f => ({\n table: parentTable,\n zql: f,\n })),\n condition.related.correlation.childField,\n ),\n )})`;\n case 'NOT EXISTS':\n return sql`NOT EXISTS (${select(\n spec,\n condition.related.subquery,\n undefined,\n makeCorrelator(\n spec,\n condition.related.correlation.parentField.map(f => ({\n table: parentTable,\n zql: f,\n })),\n condition.related.correlation.childField,\n ),\n )})`;\n }\n}\n\nfunction scalarSubquery(\n spec: Spec,\n condition: CorrelatedSubqueryCondition,\n parentTable: Table,\n): SQLQuery {\n const parentField = condition.related.correlation.parentField[0];\n const childField = condition.related.correlation.childField[0];\n const subqueryAST = condition.related.subquery;\n\n const parentCol = colIdent(spec.server, {\n table: parentTable,\n zql: parentField,\n });\n\n const subqueryTable = makeTable(spec, subqueryAST.table);\n const childCol = colIdent(spec.server, {\n table: subqueryTable,\n zql: childField,\n });\n\n const op = sql.__dangerous__rawValue(\n condition.op === 'EXISTS' ? '=' : 'IS NOT',\n );\n\n const subqueryWhere = subqueryAST.where\n ? sql`WHERE ${where(spec, subqueryAST.where, subqueryTable)}`\n : sql``;\n const subqueryOrderBy = orderBy(spec, subqueryAST.orderBy, subqueryTable);\n\n return sql`${parentCol} ${op} (SELECT ${childCol} FROM ${fromIdent(spec.server, subqueryTable)} ${subqueryWhere} ${subqueryOrderBy} LIMIT 1)`;\n}\n\nexport function makeCorrelator(\n spec: Spec,\n parentFields: readonly QualifiedColumn[],\n childZqlFields: readonly string[],\n): (childTable: Table) => SQLQuery {\n return (childTable: Table) => {\n const childFields = childZqlFields.map(zqlField => ({\n table: childTable,\n zql: zqlField,\n }));\n return sql.join(\n zip(parentFields, childFields).map(\n ([parentColumn, childColumn]) =>\n sql`${colIdent(spec.server, parentColumn)} = ${colIdent(\n spec.server,\n childColumn,\n )}`,\n ),\n ' AND ',\n );\n };\n}\n\nexport function simple(\n spec: Spec,\n condition: SimpleCondition,\n table: Table,\n): SQLQuery {\n switch (condition.op) {\n case '!=':\n case '<':\n case '<=':\n case '=':\n case '>':\n case '>=':\n case 'ILIKE':\n case 'LIKE':\n case 'NOT ILIKE':\n case 'NOT LIKE':\n return sql`${valueComparison(\n spec,\n condition.left,\n table,\n condition.right,\n false,\n )} ${sql.__dangerous__rawValue(condition.op)} ${valueComparison(\n spec,\n condition.right,\n table,\n condition.left,\n false,\n )}`;\n case 'NOT IN':\n case 'IN':\n return any(spec, condition, table);\n case 'IS':\n case 'IS NOT':\n return distinctFrom(spec, condition, table);\n }\n}\n\nexport function any(\n spec: Spec,\n condition: SimpleCondition,\n table: Table,\n): SQLQuery {\n return sql`${condition.op === 'NOT IN' ? sql`NOT` : sql``}\n (\n ${valueComparison(spec, condition.left, table, condition.right, false)} = ANY \n (${valueComparison(spec, condition.right, table, condition.left, true)})\n )`;\n}\n\nexport function distinctFrom(\n spec: Spec,\n condition: SimpleCondition,\n table: Table,\n): SQLQuery {\n return sql`${valueComparison(spec, condition.left, table, condition.right, false)} ${\n condition.op === 'IS' ? sql`IS NOT DISTINCT FROM` : sql`IS DISTINCT FROM`\n } ${valueComparison(spec, condition.right, table, condition.left, false)}`;\n}\n\nfunction valueComparison(\n spec: Spec,\n valuePos: ValuePosition,\n table: Table,\n otherValuePos: ValuePosition,\n plural: boolean,\n): SQLQuery {\n const valuePosType = valuePos.type;\n switch (valuePosType) {\n case 'column': {\n const serverColumnSchema = getServerColumn(\n spec.server,\n table,\n valuePos.name,\n );\n const qualified: QualifiedColumn = {\n table,\n zql: valuePos.name,\n };\n if (serverColumnSchema.type === 'uuid' || serverColumnSchema.isEnum) {\n return sql`${colIdent(spec.server, qualified)}::text`;\n }\n return colIdent(spec.server, qualified);\n }\n case 'literal':\n return literalValueComparison(\n spec,\n valuePos,\n table,\n otherValuePos,\n plural,\n );\n case 'static':\n throw new Error(\n 'Static parameters must be bound to a value before compiling to SQL',\n );\n default:\n unreachable(valuePosType);\n break;\n }\n}\n\nfunction literalValueComparison(\n spec: Spec,\n valuePos: LiteralReference,\n table: Table,\n otherValuePos: ValuePosition,\n plural: boolean,\n): SQLQuery {\n const otherType = otherValuePos.type;\n switch (otherType) {\n case 'column':\n return sqlConvertColumnArg(\n getServerColumn(spec.server, table, otherValuePos.name),\n valuePos.value,\n plural,\n true,\n );\n case 'literal': {\n assert(\n plural === Array.isArray(valuePos.value),\n 'Expected plural flag to match whether value is an array',\n );\n if (Array.isArray(valuePos.value)) {\n if (valuePos.value.length > 0) {\n // If the array is non-empty base its type on its first\n // element\n return sqlConvertPluralLiteralArg(\n typeof valuePos.value[0] as PluralLiteralType,\n valuePos.value as PluralLiteralType[],\n );\n }\n // If the array is empty, base its type on the other value\n // position's type (as long as the other value position is non-null,\n // cannot have a null[]).\n if (otherValuePos.value !== null) {\n return sqlConvertPluralLiteralArg(\n typeof otherValuePos.value as PluralLiteralType,\n [],\n );\n }\n // If the other value position is null, it can be compared to any\n // type of empty array, chose 'string' arbitrarily.\n return sqlConvertPluralLiteralArg('string', []);\n }\n if (\n typeof valuePos.value === 'string' ||\n typeof valuePos.value === 'number' ||\n typeof valuePos.value === 'boolean'\n ) {\n return sqlConvertSingularLiteralArg(valuePos.value);\n }\n throw new Error(\n `Literal of unexpected type. ${valuePos.value} of type ${typeof valuePos.value}`,\n );\n }\n case 'static':\n throw new Error(\n 'Static parameters must be bound to a value before compiling to SQL',\n );\n default:\n unreachable(otherType);\n }\n}\n\nexport function makeJunctionJoin(\n spec: Spec,\n relationship: CorrelatedSubquery,\n): {\n join: SQLQuery;\n participatingTables: ReturnType<typeof pullTablesForJunction>;\n} {\n const participatingTables = pullTablesForJunction(spec, relationship);\n const joins: SQLQuery[] = [];\n\n for (const {table} of participatingTables) {\n if (joins.length === 0) {\n joins.push(fromIdent(spec.server, table));\n continue;\n }\n joins.push(\n sql` JOIN ${fromIdent(spec.server, table)} ON ${makeCorrelator(\n spec,\n participatingTables[joins.length].correlation.parentField.map(f => ({\n table: participatingTables[joins.length - 1].table,\n zql: f,\n })),\n participatingTables[joins.length].correlation.childField,\n )(participatingTables[joins.length].table)}`,\n );\n }\n\n return {\n join: sql`${sql.join(joins, '')}`,\n participatingTables,\n // lastTable: participatingTables[participatingTables.length - 1].table,\n // lastLimit: participatingTables[participatingTables.length - 1].limit,\n };\n}\n\nexport function pullTablesForJunction(\n spec: Spec,\n relationship: CorrelatedSubquery,\n): [\n {\n table: Table;\n correlation: Correlation;\n limit: number | undefined;\n },\n {table: Table; correlation: Correlation; limit: number | undefined},\n] {\n assert(\n relationship.subquery.related?.length === 1,\n 'Too many related tables for a junction edge',\n );\n const otherRelationship = relationship.subquery.related[0];\n assert(\n !otherRelationship.hidden,\n 'Expected junction edge relationship to not be hidden',\n );\n return [\n {\n table: makeTable(spec, relationship.subquery.table),\n correlation: relationship.correlation,\n limit: relationship.subquery.limit,\n },\n {\n table: makeTable(spec, otherRelationship.subquery.table),\n correlation: otherRelationship.correlation,\n limit: otherRelationship.subquery.limit,\n },\n ];\n}\n\nfunction toJSON(table: string, singular = false): SQLQuery {\n return sql`${\n singular ? sql`` : sql`COALESCE(json_agg`\n }(row_to_json(${sql.ident(table)}))${singular ? sql`` : sql`, '[]'::json)`}`;\n}\n\nfunction selectIdent(server: ServerSpec, column: QualifiedColumn): SQLQuery {\n const serverColumnSchema =\n server.schema[server.mapper.tableName(column.table.zql)][\n server.mapper.columnName(column.table.zql, column.zql)\n ];\n const serverType = serverColumnSchema.type;\n if (\n !serverColumnSchema.isEnum &&\n (serverType === 'date' ||\n serverType === 'timestamp' ||\n serverType === 'timestamp without time zone' ||\n serverType === 'timestamptz' ||\n serverType === 'timestamp with time zone')\n ) {\n if (serverColumnSchema.isArray) {\n // Map EXTRACT(EPOCH FROM ...) * 1000 over array elements\n return sql`ARRAY(SELECT EXTRACT(EPOCH FROM unnest(${colIdent(server, column)})) * 1000) as ${sql.ident(column.zql)}`;\n }\n return sql`EXTRACT(EPOCH FROM ${colIdent(server, column)}) * 1000 as ${sql.ident(column.zql)}`;\n }\n return sql`${colIdent(server, column)} as ${sql.ident(column.zql)}`;\n}\n\nfunction colIdent(server: ServerSpec, column: QualifiedColumn) {\n return sql.ident(\n column.table.alias,\n server.mapper.columnName(column.table.zql, column.zql),\n );\n}\n\nfunction fromIdent(server: ServerSpec, table: Table) {\n return sql`${sql.ident(server.mapper.tableName(table.zql))} AS ${sql.ident(table.alias)}`;\n}\n\nfunction getServerColumn(spec: ServerSpec, table: Table, zqlColumn: string) {\n return spec.schema[spec.mapper.tableName(table.zql)][\n spec.mapper.columnName(table.zql, zqlColumn)\n ];\n}\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport function extractZqlResult(pgResult: Array<any>): JSONValue {\n const bigIntJson: BigIntJSONValue = parseBigIntJson(\n pgResult[0][ZQL_RESULT_KEY],\n );\n assertJSONValue(bigIntJson);\n return bigIntJson;\n}\n\nfunction assertJSONValue(v: BigIntJSONValue): asserts v is JSONValue {\n const path = findPathToBigInt(v);\n if (path) {\n throw new Error(`Value exceeds safe Number range. ${path}`);\n }\n}\n\nfunction findPathToBigInt(v: BigIntJSONValue): string | undefined {\n const typeOfV = typeof v;\n switch (typeOfV) {\n case 'bigint':\n return ` = ${v}`;\n case 'object': {\n if (v === null) {\n return;\n }\n if (Array.isArray(v)) {\n for (let i = 0; i < v.length; i++) {\n const path = findPathToBigInt(v[i]);\n if (path) {\n return `[${i}]${path}`;\n }\n }\n return undefined;\n }\n\n const o = v as Record<string, BigIntJSONValue>;\n for (const k in o) {\n if (hasOwn(o, k)) {\n const path = findPathToBigInt(o[k]);\n if (path) {\n return `['${k}']${path}`;\n }\n }\n }\n return undefined;\n }\n case 'number':\n return undefined;\n case 'boolean':\n return undefined;\n default:\n return undefined;\n }\n}\n"],"names":["limit","orderBy","parseBigIntJson"],"mappings":"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"}
|
package/out/zero/package.json.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction-pool.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/db/transaction-pool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAErC,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AAGtD,OAAO,EAAC,KAAK,UAAU,EAAE,KAAK,mBAAmB,EAAC,MAAM,gBAAgB,CAAC;AACzE,OAAO,KAAK,KAAK,IAAI,MAAM,gBAAgB,CAAC;AAG5C,KAAK,IAAI,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;AAE9B,KAAK,YAAY,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAEtC,MAAM,MAAM,SAAS,GACjB,QAAQ,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAChE,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,MAAM,IAAI,GAAG,CACjB,EAAE,EAAE,mBAAmB,EACvB,EAAE,EAAE,UAAU,KACX,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC;AAE/B;;;;GAIG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CACxB,EAAE,EAAE,mBAAmB,EACvB,EAAE,EAAE,UAAU,KACX,YAAY,CAAC,CAAC,CAAC,CAAC;AAErB;;;;;;;GAOG;AACH,qBAAa,eAAe;;IAkB1B;;;;;;;;;;;;;;;OAeG;gBAED,EAAE,EAAE,UAAU,EACd,IAAI,EAAE,IAAI,EACV,IAAI,CAAC,EAAE,IAAI,EACX,OAAO,CAAC,EAAE,IAAI,EACd,cAAc,SAAI,EAClB,UAAU,SAAiB,EAC3B,YAAY,eAAgB;IAkB9B;;;OAGG;IACH,GAAG,CAAC,EAAE,EAAE,UAAU,GAAG,IAAI;IASzB;;;;;;OAMG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;iCAIf,MAAM,SAAS,MAAM;;IAKlD;;;;;;;;;;;;;;;;;;;OAmBG;IACG,IAAI;
|
|
1
|
+
{"version":3,"file":"transaction-pool.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/db/transaction-pool.ts"],"names":[],"mappings":"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"}
|
|
@@ -147,15 +147,16 @@ class TransactionPool {
|
|
|
147
147
|
throw e;
|
|
148
148
|
}
|
|
149
149
|
};
|
|
150
|
-
this.#
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
);
|
|
150
|
+
const workerTx = runTx(db, worker, { mode: this.#mode }).catch((e) => {
|
|
151
|
+
if (e instanceof RollbackSignal) {
|
|
152
|
+
lc.debug?.("aborted transaction");
|
|
153
|
+
} else {
|
|
154
|
+
throw e;
|
|
155
|
+
}
|
|
156
|
+
}).finally(() => this.#numWorkers--);
|
|
157
|
+
workerTx.catch(() => {
|
|
158
|
+
});
|
|
159
|
+
this.#workers.push(workerTx);
|
|
159
160
|
if (this.#done) {
|
|
160
161
|
this.#tasks.enqueue("done");
|
|
161
162
|
}
|
|
@@ -383,8 +384,13 @@ function ensureError(err) {
|
|
|
383
384
|
return error;
|
|
384
385
|
}
|
|
385
386
|
const IDLE_TIMEOUT_MS = 5e3;
|
|
386
|
-
const KEEPALIVE_TIMEOUT_MS =
|
|
387
|
-
|
|
387
|
+
const KEEPALIVE_TIMEOUT_MS = parseInt(
|
|
388
|
+
process.env.ZERO_TRANSACTION_POOL_KEEPALIVE_MS ?? "5000"
|
|
389
|
+
);
|
|
390
|
+
const KEEPALIVE_TASK = (tx, lc) => {
|
|
391
|
+
lc.debug?.(`sending tx keepalive`);
|
|
392
|
+
return [tx`SELECT 1`.simple()];
|
|
393
|
+
};
|
|
388
394
|
const TIMEOUT_TASKS = {
|
|
389
395
|
forInitialWorkers: {
|
|
390
396
|
timeoutMs: KEEPALIVE_TIMEOUT_MS,
|