velocious 1.0.591 → 1.0.593

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +9 -1
  2. package/build/configuration-types.js +1 -1
  3. package/build/database/drivers/base.js +53 -34
  4. package/build/database/drivers/mssql/index.js +32 -0
  5. package/build/database/drivers/mysql/index.js +17 -0
  6. package/build/database/drivers/pgsql/index.js +11 -0
  7. package/build/database/drivers/sqlite/base.js +12 -0
  8. package/build/database/drivers/sqlite/connection-sql-js.js +3 -2
  9. package/build/database/drivers/sqlite/index.js +7 -1
  10. package/build/database/drivers/sqlite/index.native.js +9 -3
  11. package/build/database/drivers/sqlite/index.web.js +6 -3
  12. package/build/environment-handlers/base.js +18 -0
  13. package/build/environment-handlers/node.js +32 -0
  14. package/build/src/configuration-types.d.ts +2 -2
  15. package/build/src/configuration-types.js +2 -2
  16. package/build/src/database/drivers/base.d.ts +11 -0
  17. package/build/src/database/drivers/base.d.ts.map +1 -1
  18. package/build/src/database/drivers/base.js +54 -37
  19. package/build/src/database/drivers/mssql/index.d.ts +7 -0
  20. package/build/src/database/drivers/mssql/index.d.ts.map +1 -1
  21. package/build/src/database/drivers/mssql/index.js +15 -1
  22. package/build/src/database/drivers/mysql/index.d.ts +7 -0
  23. package/build/src/database/drivers/mysql/index.d.ts.map +1 -1
  24. package/build/src/database/drivers/mysql/index.js +15 -1
  25. package/build/src/database/drivers/pgsql/index.d.ts +6 -0
  26. package/build/src/database/drivers/pgsql/index.d.ts.map +1 -1
  27. package/build/src/database/drivers/pgsql/index.js +10 -1
  28. package/build/src/database/drivers/sqlite/base.d.ts +7 -0
  29. package/build/src/database/drivers/sqlite/base.d.ts.map +1 -1
  30. package/build/src/database/drivers/sqlite/base.js +11 -1
  31. package/build/src/database/drivers/sqlite/connection-sql-js.d.ts +4 -1
  32. package/build/src/database/drivers/sqlite/connection-sql-js.d.ts.map +1 -1
  33. package/build/src/database/drivers/sqlite/connection-sql-js.js +4 -3
  34. package/build/src/database/drivers/sqlite/index.d.ts +2 -1
  35. package/build/src/database/drivers/sqlite/index.d.ts.map +1 -1
  36. package/build/src/database/drivers/sqlite/index.js +7 -2
  37. package/build/src/database/drivers/sqlite/index.native.d.ts +2 -1
  38. package/build/src/database/drivers/sqlite/index.native.d.ts.map +1 -1
  39. package/build/src/database/drivers/sqlite/index.native.js +9 -4
  40. package/build/src/database/drivers/sqlite/index.web.d.ts +2 -1
  41. package/build/src/database/drivers/sqlite/index.web.d.ts.map +1 -1
  42. package/build/src/database/drivers/sqlite/index.web.js +7 -4
  43. package/build/src/environment-handlers/base.d.ts +16 -0
  44. package/build/src/environment-handlers/base.d.ts.map +1 -1
  45. package/build/src/environment-handlers/base.js +17 -1
  46. package/build/src/environment-handlers/node.d.ts +20 -0
  47. package/build/src/environment-handlers/node.d.ts.map +1 -1
  48. package/build/src/environment-handlers/node.js +29 -1
  49. package/build/src/sync/conflict-strategy.d.ts.map +1 -1
  50. package/build/src/sync/conflict-strategy.js +7 -1
  51. package/build/src/sync/local-mutation-log.d.ts +10 -0
  52. package/build/src/sync/local-mutation-log.d.ts.map +1 -1
  53. package/build/src/sync/local-mutation-log.js +21 -1
  54. package/build/src/sync/sync-api-client-types.d.ts +15 -0
  55. package/build/src/sync/sync-api-client-types.d.ts.map +1 -1
  56. package/build/src/sync/sync-api-client-types.js +4 -1
  57. package/build/src/sync/sync-api-client.d.ts +91 -0
  58. package/build/src/sync/sync-api-client.d.ts.map +1 -1
  59. package/build/src/sync/sync-api-client.js +184 -1
  60. package/build/src/sync/sync-client-types.d.ts +57 -0
  61. package/build/src/sync/sync-client-types.d.ts.map +1 -1
  62. package/build/src/sync/sync-client-types.js +16 -1
  63. package/build/src/sync/sync-client.d.ts +56 -7
  64. package/build/src/sync/sync-client.d.ts.map +1 -1
  65. package/build/src/sync/sync-client.js +180 -15
  66. package/build/src/sync/sync-envelope-replay-service.d.ts +31 -2
  67. package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
  68. package/build/src/sync/sync-envelope-replay-service.js +98 -16
  69. package/build/src/sync/sync-model-change-feed-service.d.ts.map +1 -1
  70. package/build/src/sync/sync-model-change-feed-service.js +3 -4
  71. package/build/src/sync/sync-replay-persisted-data.d.ts +26 -0
  72. package/build/src/sync/sync-replay-persisted-data.d.ts.map +1 -0
  73. package/build/src/sync/sync-replay-persisted-data.js +43 -0
  74. package/build/src/testing/shared-transaction-broker.d.ts +14 -0
  75. package/build/src/testing/shared-transaction-broker.d.ts.map +1 -1
  76. package/build/src/testing/shared-transaction-broker.js +44 -7
  77. package/build/src/testing/shared-transaction-connection-coordinator.d.ts +5 -4
  78. package/build/src/testing/shared-transaction-connection-coordinator.d.ts.map +1 -1
  79. package/build/src/testing/shared-transaction-connection-coordinator.js +21 -10
  80. package/build/sync/conflict-strategy.js +3 -0
  81. package/build/sync/local-mutation-log.js +24 -0
  82. package/build/sync/sync-api-client-types.js +3 -0
  83. package/build/sync/sync-api-client.js +203 -0
  84. package/build/sync/sync-client-types.js +16 -0
  85. package/build/sync/sync-client.js +198 -14
  86. package/build/sync/sync-envelope-replay-service.js +109 -12
  87. package/build/sync/sync-model-change-feed-service.js +2 -4
  88. package/build/sync/sync-replay-persisted-data.js +50 -0
  89. package/build/testing/shared-transaction-broker.js +48 -7
  90. package/build/testing/shared-transaction-connection-coordinator.js +23 -9
  91. package/build/tsconfig.tsbuildinfo +1 -1
  92. package/package.json +1 -1
  93. package/scripts/browser-test-session.js +489 -0
  94. package/scripts/prewarm-chromedriver.js +3 -22
  95. package/scripts/test-browser.js +47 -15
  96. package/src/configuration-types.js +1 -1
  97. package/src/database/drivers/base.js +53 -34
  98. package/src/database/drivers/mssql/index.js +32 -0
  99. package/src/database/drivers/mysql/index.js +17 -0
  100. package/src/database/drivers/pgsql/index.js +11 -0
  101. package/src/database/drivers/sqlite/base.js +12 -0
  102. package/src/database/drivers/sqlite/connection-sql-js.js +3 -2
  103. package/src/database/drivers/sqlite/index.js +7 -1
  104. package/src/database/drivers/sqlite/index.native.js +9 -3
  105. package/src/database/drivers/sqlite/index.web.js +6 -3
  106. package/src/environment-handlers/base.js +18 -0
  107. package/src/environment-handlers/node.js +32 -0
  108. package/src/sync/conflict-strategy.js +3 -0
  109. package/src/sync/local-mutation-log.js +24 -0
  110. package/src/sync/sync-api-client-types.js +3 -0
  111. package/src/sync/sync-api-client.js +203 -0
  112. package/src/sync/sync-client-types.js +16 -0
  113. package/src/sync/sync-client.js +198 -14
  114. package/src/sync/sync-envelope-replay-service.js +109 -12
  115. package/src/sync/sync-model-change-feed-service.js +2 -4
  116. package/src/sync/sync-replay-persisted-data.js +50 -0
  117. package/src/testing/shared-transaction-broker.js +48 -7
  118. package/src/testing/shared-transaction-connection-coordinator.js +23 -9
@@ -5,7 +5,7 @@ import { createServer } from "node:http"
5
5
  import { EventEmitter } from "node:events"
6
6
  import { WebSocketServer } from "ws"
7
7
  import { decodeBrokerValue, encodeBrokerValue } from "./shared-transaction-codec.js"
8
- import {clearSharedTransactionCoordinator, setSharedTransactionCoordinator} from "./shared-transaction-connection-coordinator.js"
8
+ import { clearSharedTransactionCoordinator, setSharedTransactionCoordinator } from "./shared-transaction-connection-coordinator.js"
9
9
 
10
10
  /** @typedef {{queue: Promise<void>, rootSessions: Set<import("ws").WebSocket>, lease?: {operations: Promise<void>, release: () => void, savePointName: string, socket: import("ws").WebSocket}}} ConnectionState */
11
11
 
@@ -38,6 +38,23 @@ function capabilityMatches(provided, expected) {
38
38
  return providedBytes.length === expectedBytes.length && timingSafeEqual(providedBytes, expectedBytes)
39
39
  }
40
40
 
41
+ /**
42
+ * Adds broker ownership to decoded driver options.
43
+ * @param {ReturnType<typeof JSON.parse>} value - Decoded options.
44
+ * @param {symbol} operationOwner - Broker coordinator owner.
45
+ * @returns {Record<string, ReturnType<typeof JSON.parse>> & {operationOwner: symbol}} - Owned options.
46
+ */
47
+ function ownedOperationOptions(value, operationOwner) {
48
+ if (value === undefined) return {operationOwner}
49
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
50
+ throw new TypeError("Shared transaction broker driver options must be an object")
51
+ }
52
+
53
+ const options = /** @type {Record<string, ReturnType<typeof JSON.parse>>} */ (value)
54
+
55
+ return {...options, operationOwner}
56
+ }
57
+
41
58
  export default class SharedTransactionBroker extends EventEmitter {
42
59
  /**
43
60
  * Creates a broker around parent-owned physical connections.
@@ -60,6 +77,8 @@ export default class SharedTransactionBroker extends EventEmitter {
60
77
  this.closePromise = undefined
61
78
  /** @type {Map<object, (callback: () => Promise<ReturnType<typeof JSON.parse>>) => Promise<ReturnType<typeof JSON.parse>>>} */
62
79
  this.connectionCoordinators = new Map()
80
+ /** @type {Map<object, symbol>} */
81
+ this.connectionCoordinatorOwners = new Map()
63
82
  for (const connection of new Set(Object.values(connections))) {
64
83
  /**
65
84
  * Serializes parent operations with child broker traffic.
@@ -68,7 +87,7 @@ export default class SharedTransactionBroker extends EventEmitter {
68
87
  */
69
88
  const coordinator = async (callback) => await this.serialize(this.connectionState(connection), callback)
70
89
  this.connectionCoordinators.set(connection, coordinator)
71
- setSharedTransactionCoordinator(connection, coordinator)
90
+ this.connectionCoordinatorOwners.set(connection, setSharedTransactionCoordinator(connection, coordinator))
72
91
  }
73
92
  this.httpServer = createServer()
74
93
  this.websocketServer = new WebSocketServer({server: this.httpServer, maxPayload: 16 * 1024 * 1024})
@@ -144,10 +163,10 @@ export default class SharedTransactionBroker extends EventEmitter {
144
163
  : request.method === "rootTransactionRollback"
145
164
  ? "rollbackSavePoint"
146
165
  : request.method
147
- const connectionMethods = /** @type {Record<string, (...methodArgs: Array<ReturnType<typeof JSON.parse>>) => ReturnType<typeof JSON.parse>>} */ (connection)
166
+ const connectionMethods = /** @type {Record<string, (...methodArgs: Array<ReturnType<typeof JSON.parse> | {operationOwner: symbol}>) => ReturnType<typeof JSON.parse>>} */ (connection)
148
167
  const method = connectionMethods[physicalMethod]
149
168
  if (typeof method !== "function") throw new Error(`Connection does not support shared transaction method: ${request.method}`)
150
- return await method.apply(connection, args)
169
+ return await method.apply(connection, this.ownedMethodArgs({args, connection, method: physicalMethod}))
151
170
  })
152
171
  if (socket.readyState === socket.OPEN) socket.send(JSON.stringify({requestId, result: encodeBrokerValue(result)}))
153
172
  } catch (error) {
@@ -156,6 +175,25 @@ export default class SharedTransactionBroker extends EventEmitter {
156
175
  }
157
176
  }
158
177
 
178
+ /**
179
+ * Adds the broker owner to public driver methods that re-enter coordinated query work.
180
+ * @param {{args: Array<ReturnType<typeof JSON.parse>>, connection: object, method: string}} args - Physical invocation.
181
+ * @returns {Array<ReturnType<typeof JSON.parse> | {operationOwner: symbol}>} - Owned method arguments.
182
+ */
183
+ ownedMethodArgs({args, connection, method}) {
184
+ const operationOwner = this.connectionCoordinatorOwners.get(connection)
185
+
186
+ if (!operationOwner) throw new Error("Shared transaction broker connection owner is missing")
187
+ if (["_startTransactionAction", "_commitTransactionAction", "_rollbackTransactionAction"].includes(method)) {
188
+ return [ownedOperationOptions(args[0], operationOwner)]
189
+ }
190
+ if (["query", "affectedRows", "startSavePoint", "releaseSavePoint", "rollbackSavePoint"].includes(method)) {
191
+ return [args[0], ownedOperationOptions(args[1], operationOwner)]
192
+ }
193
+
194
+ return args
195
+ }
196
+
159
197
  /**
160
198
  * Gets mutable serialization state for one physical connection.
161
199
  * @param {object} connection - Physical connection.
@@ -324,16 +362,19 @@ export default class SharedTransactionBroker extends EventEmitter {
324
362
  * @returns {Promise<void>} - Resolves after rollback and release.
325
363
  */
326
364
  async rollbackRootSavePoint(connection, savePointName) {
327
- const methods = /** @type {{releaseSavePoint: (name: string) => Promise<void>, rollbackSavePoint: (name: string) => Promise<void>}} */ (connection)
365
+ const methods = /** @type {{releaseSavePoint: (name: string, options?: {operationOwner?: symbol}) => Promise<void>, rollbackSavePoint: (name: string, options?: {operationOwner?: symbol}) => Promise<void>}} */ (connection)
366
+ const operationOwner = this.connectionCoordinatorOwners.get(connection)
367
+
368
+ if (!operationOwner) throw new Error("Shared transaction broker connection owner is missing")
328
369
  /** @type {Array<Error>} */
329
370
  const errors = []
330
371
  try {
331
- await methods.rollbackSavePoint(savePointName)
372
+ await methods.rollbackSavePoint(savePointName, {operationOwner})
332
373
  } catch (error) {
333
374
  errors.push(error instanceof Error ? error : new Error(String(error)))
334
375
  }
335
376
  try {
336
- await methods.releaseSavePoint(savePointName)
377
+ await methods.releaseSavePoint(savePointName, {operationOwner})
337
378
  } catch (error) {
338
379
  errors.push(error instanceof Error ? error : new Error(String(error)))
339
380
  }
@@ -1,16 +1,19 @@
1
1
  // @ts-check
2
2
 
3
- /** @type {WeakMap<object, (callback: () => Promise<unknown>) => Promise<unknown>>} */
3
+ /** @type {WeakMap<object, {coordinator: (callback: () => Promise<unknown>) => Promise<unknown>, owner: symbol}>} */
4
4
  const coordinators = new WeakMap()
5
5
 
6
6
  /**
7
7
  * Registers test-only serialization owned by the active broker.
8
8
  * @param {object} connection - Parent physical connection.
9
9
  * @param {(callback: () => Promise<unknown>) => Promise<unknown>} coordinator - Serializer.
10
- * @returns {void}
10
+ * @returns {symbol} - Opaque owner for broker-internal connection calls.
11
11
  */
12
12
  export function setSharedTransactionCoordinator(connection, coordinator) {
13
- coordinators.set(connection, coordinator)
13
+ const owner = Symbol("shared-transaction-coordinator")
14
+
15
+ coordinators.set(connection, {coordinator, owner})
16
+ return owner
14
17
  }
15
18
 
16
19
  /**
@@ -20,19 +23,30 @@ export function setSharedTransactionCoordinator(connection, coordinator) {
20
23
  * @returns {void}
21
24
  */
22
25
  export function clearSharedTransactionCoordinator(connection, coordinator) {
23
- if (coordinators.get(connection) === coordinator) coordinators.delete(connection)
26
+ if (coordinators.get(connection)?.coordinator === coordinator) coordinators.delete(connection)
24
27
  }
25
28
 
26
29
  /**
27
30
  * Runs parent work through broker serialization when registered.
28
31
  * @template T
29
- * @param {object} connection - Parent physical connection.
32
+ * @param {import("../database/drivers/base.js").default} connection - Parent physical connection.
30
33
  * @param {() => Promise<T>} callback - Parent operation.
34
+ * @param {symbol} [operationOwner] - Broker owner for an already-coordinated operation.
31
35
  * @returns {Promise<T>} - Operation result.
32
36
  */
33
- export async function coordinateSharedTransactionConnection(connection, callback) {
34
- const coordinator = coordinators.get(connection)
37
+ export async function coordinateSharedTransactionConnection(connection, callback, operationOwner) {
38
+ const registration = coordinators.get(connection)
39
+
40
+ if (!registration) return await callback()
41
+ if (operationOwner === registration.owner) return await callback()
42
+
43
+ const environmentHandler = connection.configuration.getEnvironmentHandler()
44
+
45
+ if (environmentHandler.getSharedTransactionCoordinatorOwner(connection) === registration.owner) {
46
+ return await callback()
47
+ }
35
48
 
36
- if (!coordinator) return await callback()
37
- return /** @type {T} */ (await coordinator(callback))
49
+ return /** @type {T} */ (await registration.coordinator(async () => {
50
+ return await environmentHandler.runWithSharedTransactionCoordinatorOwner(connection, registration.owner, callback)
51
+ }))
38
52
  }