velocious 1.0.500 → 1.0.501
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/build/configuration-types.js +39 -0
- package/build/configuration.js +3 -2
- package/build/src/configuration-types.d.ts +123 -0
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +36 -1
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +4 -3
- package/build/src/sync/sync-client-types.d.ts +27 -0
- package/build/src/sync/sync-client-types.d.ts.map +1 -1
- package/build/src/sync/sync-client-types.js +1 -1
- package/build/src/sync/sync-client.d.ts +42 -0
- package/build/src/sync/sync-client.d.ts.map +1 -1
- package/build/src/sync/sync-client.js +70 -20
- package/build/src/sync/sync-realtime-bridge.d.ts +125 -0
- package/build/src/sync/sync-realtime-bridge.d.ts.map +1 -0
- package/build/src/sync/sync-realtime-bridge.js +262 -0
- package/build/sync/sync-client-types.js +12 -0
- package/build/sync/sync-client.js +80 -22
- package/build/sync/sync-realtime-bridge.js +299 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/configuration-types.js +39 -0
- package/src/configuration.js +3 -2
- package/src/sync/sync-client-types.js +12 -0
- package/src/sync/sync-client.js +80 -22
- package/src/sync/sync-realtime-bridge.js +299 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import SyncApiClient from "./sync-api-client.js"
|
|
4
|
+
|
|
5
|
+
/** @typedef {import("../configuration-types.js").VelociousSyncRealtimeChannelDescriptor} VelociousSyncRealtimeChannelDescriptor */
|
|
6
|
+
/** @typedef {import("../configuration-types.js").VelociousSyncRealtimeWebsocketClient} VelociousSyncRealtimeWebsocketClient */
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Derived realtime push bridge for the sync client. Subscribes the declared
|
|
10
|
+
* websocket channels (config `sync.client.realtime.channels` callback plus
|
|
11
|
+
* model-level `static sync = {realtime: {channel}}` declarations), applies
|
|
12
|
+
* pushed changes through the same derived resource applier as pulls (with echo
|
|
13
|
+
* suppression against tracked re-queueing), drops own-device messages by echo
|
|
14
|
+
* origin, and fires a coalesced `pull()` when subscriptions become ready or
|
|
15
|
+
* resume so offline gaps close.
|
|
16
|
+
*/
|
|
17
|
+
export default class SyncRealtimeBridge {
|
|
18
|
+
/**
|
|
19
|
+
* Builds the bridge for a sync client.
|
|
20
|
+
* @param {{syncClient: import("./sync-client.js").default}} args - Bridge args.
|
|
21
|
+
*/
|
|
22
|
+
constructor({syncClient}) {
|
|
23
|
+
this.syncClient = syncClient
|
|
24
|
+
/** @type {Array<{channel: string, resourceType: string | null, subscription: import("../configuration-types.js").VelociousSyncRealtimeSubscription}>} */
|
|
25
|
+
this._channels = []
|
|
26
|
+
/** @type {VelociousSyncRealtimeWebsocketClient | null} */
|
|
27
|
+
this._client = null
|
|
28
|
+
/** @type {Promise<void>} */
|
|
29
|
+
this._applyPromise = Promise.resolve()
|
|
30
|
+
/** @type {number} Subscription generation - bumped by unsubscribe so in-flight subscribes detect they became stale. */
|
|
31
|
+
this._generation = 0
|
|
32
|
+
/** @type {Promise<void> | null} */
|
|
33
|
+
this._scheduledPull = null
|
|
34
|
+
/** @type {Promise<void> | null} */
|
|
35
|
+
this._subscribePromise = null
|
|
36
|
+
/** @type {"subscribed" | "subscribing" | "unsubscribed"} */
|
|
37
|
+
this._state = "unsubscribed"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Subscribes the derived realtime channels (idempotent and single-flighted):
|
|
42
|
+
* an active subscription is kept as-is and a concurrent subscribe awaits the
|
|
43
|
+
* in-flight attempt. Call `unsubscribe()` first to change the context.
|
|
44
|
+
* @param {?} [context] - App context passed to the `sync.client.realtime.channels` callback (runtime values like eventId).
|
|
45
|
+
* @returns {Promise<void>}
|
|
46
|
+
*/
|
|
47
|
+
async subscribe(context) {
|
|
48
|
+
if (this._state === "subscribed") return
|
|
49
|
+
|
|
50
|
+
if (!this._subscribePromise) {
|
|
51
|
+
this._subscribePromise = this._subscribe(context).finally(() => {
|
|
52
|
+
this._subscribePromise = null
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
await this._subscribePromise
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Connects the websocket client, subscribes every derived channel, and waits
|
|
61
|
+
* for each subscription's server acknowledgement before the gap-closing pull,
|
|
62
|
+
* so no change can land between the pull and the subscriptions going live.
|
|
63
|
+
* Locally created resources are only promoted to the bridge once everything
|
|
64
|
+
* is live; an unsubscribe arriving during any await marks this attempt stale
|
|
65
|
+
* and it tears its own resources down instead of resubscribing.
|
|
66
|
+
* @param {?} context - App context passed to the channels callback.
|
|
67
|
+
* @returns {Promise<void>}
|
|
68
|
+
*/
|
|
69
|
+
async _subscribe(context) {
|
|
70
|
+
const generation = this._generation
|
|
71
|
+
|
|
72
|
+
this._state = "subscribing"
|
|
73
|
+
|
|
74
|
+
/** @type {Array<{channel: string, resourceType: string | null, subscription: import("../configuration-types.js").VelociousSyncRealtimeSubscription}>} */
|
|
75
|
+
const channels = []
|
|
76
|
+
/** @type {VelociousSyncRealtimeWebsocketClient | null} */
|
|
77
|
+
let client = null
|
|
78
|
+
/**
|
|
79
|
+
* Tears down everything this stale/failed subscribe attempt created itself.
|
|
80
|
+
* @returns {Promise<void>}
|
|
81
|
+
*/
|
|
82
|
+
const teardown = async () => {
|
|
83
|
+
for (const {subscription} of channels) {
|
|
84
|
+
subscription.close()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (client) await client.disconnectAndStopReconnect()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const realtime = this.realtimeConfiguration()
|
|
92
|
+
const channelDescriptors = await this.channelDescriptors(context)
|
|
93
|
+
|
|
94
|
+
if (generation !== this._generation) return
|
|
95
|
+
|
|
96
|
+
client = await realtime.createClient()
|
|
97
|
+
|
|
98
|
+
if (generation !== this._generation) return
|
|
99
|
+
|
|
100
|
+
await client.connect()
|
|
101
|
+
|
|
102
|
+
if (generation !== this._generation) {
|
|
103
|
+
await teardown()
|
|
104
|
+
return
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const authenticationToken = await this.syncClient.config.authenticationToken()
|
|
108
|
+
|
|
109
|
+
if (generation !== this._generation) {
|
|
110
|
+
await teardown()
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
for (const channelDescriptor of channelDescriptors) {
|
|
115
|
+
if (channelDescriptor.params && "authenticationToken" in channelDescriptor.params) {
|
|
116
|
+
throw new Error(`Realtime channel "${channelDescriptor.channel}" params must not include authenticationToken - the framework injects the sync.client authenticationToken automatically`)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const resourceType = channelDescriptor.resourceType ?? null
|
|
120
|
+
const subscription = client.subscribeChannel(channelDescriptor.channel, {
|
|
121
|
+
onMessage: (body) => this.enqueueApply({body, resourceType}),
|
|
122
|
+
onResume: () => this.schedulePull(),
|
|
123
|
+
params: {...channelDescriptor.params, authenticationToken}
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
channels.push({channel: channelDescriptor.channel, resourceType, subscription})
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
await Promise.all(channels.map(({subscription}) => subscription.waitForReady()))
|
|
130
|
+
|
|
131
|
+
if (generation !== this._generation) {
|
|
132
|
+
await teardown()
|
|
133
|
+
return
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
this._channels = channels
|
|
137
|
+
this._client = client
|
|
138
|
+
this._state = "subscribed"
|
|
139
|
+
this.schedulePull()
|
|
140
|
+
} catch (error) {
|
|
141
|
+
await teardown()
|
|
142
|
+
|
|
143
|
+
if (generation === this._generation) this._state = "unsubscribed"
|
|
144
|
+
|
|
145
|
+
throw error
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Closes every channel subscription and disconnects the websocket client
|
|
151
|
+
* (idempotent). Also marks any in-flight subscribe attempt stale so it tears
|
|
152
|
+
* itself down instead of finishing the subscription afterwards.
|
|
153
|
+
* @returns {Promise<void>}
|
|
154
|
+
*/
|
|
155
|
+
async unsubscribe() {
|
|
156
|
+
this._generation += 1
|
|
157
|
+
|
|
158
|
+
const channels = this._channels
|
|
159
|
+
const client = this._client
|
|
160
|
+
|
|
161
|
+
this._channels = []
|
|
162
|
+
this._client = null
|
|
163
|
+
this._state = "unsubscribed"
|
|
164
|
+
|
|
165
|
+
for (const {subscription} of channels) {
|
|
166
|
+
subscription.close()
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (client) await client.disconnectAndStopReconnect()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Reports the bridge subscription state and per-channel readiness.
|
|
174
|
+
* @returns {{channels: Array<{channel: string, ready: boolean, resourceType: string | null}>, state: "subscribed" | "subscribing" | "unsubscribed"}} Realtime status.
|
|
175
|
+
*/
|
|
176
|
+
status() {
|
|
177
|
+
return {
|
|
178
|
+
channels: this._channels.map(({channel, resourceType, subscription}) => ({channel, ready: subscription.isReady(), resourceType})),
|
|
179
|
+
state: this._state
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Awaits all enqueued message applies and any scheduled pull (tests, shutdown flows).
|
|
185
|
+
* @returns {Promise<void>}
|
|
186
|
+
*/
|
|
187
|
+
async waitForApplied() {
|
|
188
|
+
await this._applyPromise
|
|
189
|
+
if (this._scheduledPull) await this._scheduledPull
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Resolves the realtime configuration, failing loudly when it is missing.
|
|
194
|
+
* @returns {import("../configuration-types.js").VelociousSyncClientRealtimeConfiguration} Realtime configuration.
|
|
195
|
+
*/
|
|
196
|
+
realtimeConfiguration() {
|
|
197
|
+
const realtime = this.syncClient.config.realtime
|
|
198
|
+
|
|
199
|
+
if (!realtime) {
|
|
200
|
+
throw new Error("subscribeRealtime requires a sync.client.realtime configuration block with a createClient callback")
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return realtime
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Derives the channel descriptors to subscribe: model-level static realtime
|
|
208
|
+
* declarations plus the config channels callback, failing loudly when none exist.
|
|
209
|
+
* @param {?} context - App context passed to the channels callback.
|
|
210
|
+
* @returns {Promise<Array<VelociousSyncRealtimeChannelDescriptor>>} Channel descriptors.
|
|
211
|
+
*/
|
|
212
|
+
async channelDescriptors(context) {
|
|
213
|
+
const realtime = this.realtimeConfiguration()
|
|
214
|
+
/** @type {Array<VelociousSyncRealtimeChannelDescriptor>} */
|
|
215
|
+
const channelDescriptors = []
|
|
216
|
+
|
|
217
|
+
for (const [resourceType, resourceConfig] of Object.entries(this.syncClient.config.resources)) {
|
|
218
|
+
if (!resourceConfig.realtime) continue
|
|
219
|
+
|
|
220
|
+
channelDescriptors.push({channel: resourceConfig.realtime.channel, params: resourceConfig.realtime.params, resourceType})
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (realtime.channels) {
|
|
224
|
+
channelDescriptors.push(...await realtime.channels(context))
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (channelDescriptors.length === 0) {
|
|
228
|
+
throw new Error("subscribeRealtime found no realtime channels - declare sync.client.realtime.channels or static sync = {realtime: {channel}} on a model")
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return channelDescriptors
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Chains one pushed message onto the serialized apply queue so changes apply
|
|
236
|
+
* in arrival order; failures go to the sync client's error reporting.
|
|
237
|
+
* @param {{body: ?, resourceType: string | null}} args - Message args.
|
|
238
|
+
* @returns {void}
|
|
239
|
+
*/
|
|
240
|
+
enqueueApply({body, resourceType}) {
|
|
241
|
+
this._applyPromise = this._applyPromise.then(async () => {
|
|
242
|
+
try {
|
|
243
|
+
await this.applyMessage({body, resourceType})
|
|
244
|
+
} catch (error) {
|
|
245
|
+
this.syncClient.reportError(/** @type {Error} */ (error))
|
|
246
|
+
}
|
|
247
|
+
})
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Applies one pushed message through the derived resource applier: drops
|
|
252
|
+
* own-device messages by echo origin, defaults the channel's resourceType onto
|
|
253
|
+
* envelopes without one, and fails loudly on unknown resource types.
|
|
254
|
+
* @param {{body: ?, resourceType: string | null}} args - Message args.
|
|
255
|
+
* @returns {Promise<void>}
|
|
256
|
+
*/
|
|
257
|
+
async applyMessage({body, resourceType}) {
|
|
258
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
259
|
+
throw new Error(`Realtime sync messages must be envelope objects, got: ${JSON.stringify(body)}`)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const realtime = this.realtimeConfiguration()
|
|
263
|
+
|
|
264
|
+
if (realtime.localOrigin && body.echoOrigin !== undefined && body.echoOrigin !== null) {
|
|
265
|
+
const localOrigin = String(await realtime.localOrigin())
|
|
266
|
+
|
|
267
|
+
if (String(body.echoOrigin) === localOrigin) return
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const syncPayloads = Array.isArray(body.syncs) ? body.syncs : [body]
|
|
271
|
+
const applySync = this.syncClient.remoteApplySync({source: "remote change"})
|
|
272
|
+
|
|
273
|
+
for (const syncPayload of syncPayloads) {
|
|
274
|
+
const sync = SyncApiClient.syncEnvelopeFromPayload({resourceType, ...syncPayload})
|
|
275
|
+
|
|
276
|
+
await applySync(sync)
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Schedules a coalesced background pull closing offline gaps after
|
|
282
|
+
* (re)subscription readiness. Resumes arriving while a pull is already
|
|
283
|
+
* scheduled or in flight coalesce into that pull instead of stacking.
|
|
284
|
+
* @returns {void}
|
|
285
|
+
*/
|
|
286
|
+
schedulePull() {
|
|
287
|
+
if (this.realtimeConfiguration().pullOnReconnect === false) return
|
|
288
|
+
|
|
289
|
+
this._scheduledPull ||= (async () => {
|
|
290
|
+
try {
|
|
291
|
+
await this.syncClient.pull()
|
|
292
|
+
} catch (error) {
|
|
293
|
+
this.syncClient.reportError(/** @type {Error} */ (error))
|
|
294
|
+
} finally {
|
|
295
|
+
this._scheduledPull = null
|
|
296
|
+
}
|
|
297
|
+
})()
|
|
298
|
+
}
|
|
299
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../index.js","../bin/velocious.js","../src/application.js","../src/configuration-resolver.js","../src/configuration-types.js","../src/configuration.js","../src/controller.js","../src/current-configuration.js","../src/current.js","../src/error-logger.js","../src/frontend-model-controller.js","../src/initializer.js","../src/logger.js","../src/mailer.js","../src/record-payload-values.js","../src/time-zone.js","../src/velocious-error.js","../src/authorization/ability.js","../src/authorization/base-resource.js","../src/background-jobs/client.js","../src/background-jobs/cron-expression.js","../src/background-jobs/forked-runner-child.js","../src/background-jobs/job-record.js","../src/background-jobs/job-registry.js","../src/background-jobs/job-runner.js","../src/background-jobs/job.js","../src/background-jobs/json-socket.js","../src/background-jobs/main.js","../src/background-jobs/normalize-error.js","../src/background-jobs/scheduler.js","../src/background-jobs/socket-request.js","../src/background-jobs/status-reporter.js","../src/background-jobs/store.js","../src/background-jobs/types.js","../src/background-jobs/worker.js","../src/background-jobs/web/authorization.js","../src/background-jobs/web/controller.js","../src/background-jobs/web/index.js","../src/background-jobs/web/path-matcher.js","../src/background-jobs/web/registry.js","../src/beacon/client.js","../src/beacon/in-process-broker.js","../src/beacon/in-process-client.js","../src/beacon/server.js","../src/beacon/types.js","../src/cli/base-command.js","../src/cli/browser-cli.js","../src/cli/index.js","../src/cli/tenant-database-command-helper.js","../src/cli/use-browser-cli.js","../src/cli/commands/background-jobs-main.js","../src/cli/commands/background-jobs-runner.js","../src/cli/commands/background-jobs-worker.js","../src/cli/commands/beacon.js","../src/cli/commands/console.js","../src/cli/commands/init.js","../src/cli/commands/routes.js","../src/cli/commands/run-script.js","../src/cli/commands/runner.js","../src/cli/commands/server.js","../src/cli/commands/test.js","../src/cli/commands/db/base-command.js","../src/cli/commands/db/create.js","../src/cli/commands/db/drop.js","../src/cli/commands/db/migrate.js","../src/cli/commands/db/reset.js","../src/cli/commands/db/rollback.js","../src/cli/commands/db/seed.js","../src/cli/commands/db/schema/dump.js","../src/cli/commands/db/schema/load.js","../src/cli/commands/db/tenants/check.js","../src/cli/commands/db/tenants/create.js","../src/cli/commands/db/tenants/drop.js","../src/cli/commands/db/tenants/migrate.js","../src/cli/commands/destroy/migration.js","../src/cli/commands/generate/base-models.js","../src/cli/commands/generate/frontend-models.js","../src/cli/commands/generate/migration.js","../src/cli/commands/generate/model.js","../src/cli/commands/lint/relationships.js","../src/database/annotations-async-hooks.js","../src/database/annotations.js","../src/database/column-types.js","../src/database/datetime-storage.js","../src/database/handler.js","../src/database/initializer-from-require-context.js","../src/database/migrations-ledger.js","../src/database/migrator.js","../src/database/use-database.js","../src/database/drivers/base-column.js","../src/database/drivers/base-columns-index.js","../src/database/drivers/base-foreign-key.js","../src/database/drivers/base-table.js","../src/database/drivers/base.js","../src/database/drivers/mssql/column.js","../src/database/drivers/mssql/columns-index.js","../src/database/drivers/mssql/connect-connection.js","../src/database/drivers/mssql/foreign-key.js","../src/database/drivers/mssql/index.js","../src/database/drivers/mssql/options.js","../src/database/drivers/mssql/query-parser.js","../src/database/drivers/mssql/structure-sql.js","../src/database/drivers/mssql/table.js","../src/database/drivers/mssql/sql/alter-table.js","../src/database/drivers/mssql/sql/create-database.js","../src/database/drivers/mssql/sql/create-index.js","../src/database/drivers/mssql/sql/create-table.js","../src/database/drivers/mssql/sql/delete.js","../src/database/drivers/mssql/sql/drop-database.js","../src/database/drivers/mssql/sql/drop-table.js","../src/database/drivers/mssql/sql/insert.js","../src/database/drivers/mssql/sql/remove-index.js","../src/database/drivers/mssql/sql/update.js","../src/database/drivers/mssql/sql/upsert.js","../src/database/drivers/mysql/column.js","../src/database/drivers/mysql/columns-index.js","../src/database/drivers/mysql/foreign-key.js","../src/database/drivers/mysql/index.js","../src/database/drivers/mysql/options.js","../src/database/drivers/mysql/query-parser.js","../src/database/drivers/mysql/query.js","../src/database/drivers/mysql/structure-sql.js","../src/database/drivers/mysql/table.js","../src/database/drivers/mysql/sql/alter-table.js","../src/database/drivers/mysql/sql/create-database.js","../src/database/drivers/mysql/sql/create-index.js","../src/database/drivers/mysql/sql/create-table.js","../src/database/drivers/mysql/sql/delete.js","../src/database/drivers/mysql/sql/drop-database.js","../src/database/drivers/mysql/sql/drop-table.js","../src/database/drivers/mysql/sql/insert.js","../src/database/drivers/mysql/sql/remove-index.js","../src/database/drivers/mysql/sql/update.js","../src/database/drivers/mysql/sql/upsert.js","../src/database/drivers/pgsql/column.js","../src/database/drivers/pgsql/columns-index.js","../src/database/drivers/pgsql/foreign-key.js","../src/database/drivers/pgsql/index.js","../src/database/drivers/pgsql/options.js","../src/database/drivers/pgsql/query-parser.js","../src/database/drivers/pgsql/structure-sql.js","../src/database/drivers/pgsql/table.js","../src/database/drivers/pgsql/sql/alter-table.js","../src/database/drivers/pgsql/sql/create-database.js","../src/database/drivers/pgsql/sql/create-index.js","../src/database/drivers/pgsql/sql/create-table.js","../src/database/drivers/pgsql/sql/delete.js","../src/database/drivers/pgsql/sql/drop-database.js","../src/database/drivers/pgsql/sql/drop-table.js","../src/database/drivers/pgsql/sql/insert.js","../src/database/drivers/pgsql/sql/remove-index.js","../src/database/drivers/pgsql/sql/update.js","../src/database/drivers/pgsql/sql/upsert.js","../src/database/drivers/sqlite/base.js","../src/database/drivers/sqlite/column.js","../src/database/drivers/sqlite/columns-index.js","../src/database/drivers/sqlite/connection-sql-js.js","../src/database/drivers/sqlite/foreign-key.js","../src/database/drivers/sqlite/index.js","../src/database/drivers/sqlite/index.native.js","../src/database/drivers/sqlite/index.web.js","../src/database/drivers/sqlite/options.js","../src/database/drivers/sqlite/query-parser.js","../src/database/drivers/sqlite/query.js","../src/database/drivers/sqlite/query.native.js","../src/database/drivers/sqlite/query.web.js","../src/database/drivers/sqlite/structure-sql.js","../src/database/drivers/sqlite/table-rebuilder.js","../src/database/drivers/sqlite/table.js","../src/database/drivers/sqlite/web-persistence.js","../src/database/drivers/sqlite/sql/alter-table.js","../src/database/drivers/sqlite/sql/create-index.js","../src/database/drivers/sqlite/sql/create-table.js","../src/database/drivers/sqlite/sql/delete.js","../src/database/drivers/sqlite/sql/drop-table.js","../src/database/drivers/sqlite/sql/insert.js","../src/database/drivers/sqlite/sql/remove-index.js","../src/database/drivers/sqlite/sql/update.js","../src/database/drivers/sqlite/sql/upsert.js","../src/database/drivers/structure-sql/utils.js","../src/database/migration/index.js","../src/database/migrator/files-finder.js","../src/database/migrator/types.js","../src/database/pool/async-tracked-multi-connection.js","../src/database/pool/base-methods-forward.js","../src/database/pool/base.js","../src/database/pool/single-multi-use.js","../src/database/query/alter-table-base.js","../src/database/query/base.js","../src/database/query/create-database-base.js","../src/database/query/create-index-base.js","../src/database/query/create-table-base.js","../src/database/query/delete-base.js","../src/database/query/drop-database-base.js","../src/database/query/drop-table-base.js","../src/database/query/from-base.js","../src/database/query/from-plain.js","../src/database/query/from-table.js","../src/database/query/index.js","../src/database/query/insert-base.js","../src/database/query/join-base.js","../src/database/query/join-object.js","../src/database/query/join-plain.js","../src/database/query/join-tracker.js","../src/database/query/model-class-query.js","../src/database/query/order-base.js","../src/database/query/order-column.js","../src/database/query/order-plain.js","../src/database/query/preloader.js","../src/database/query/query-data.js","../src/database/query/remove-index-base.js","../src/database/query/select-base.js","../src/database/query/select-plain.js","../src/database/query/select-table-and-column.js","../src/database/query/update-base.js","../src/database/query/upsert-base.js","../src/database/query/where-base.js","../src/database/query/where-combinator.js","../src/database/query/where-hash.js","../src/database/query/where-model-class-hash.js","../src/database/query/where-not.js","../src/database/query/where-plain.js","../src/database/query/with-count.js","../src/database/query/preloader/belongs-to.js","../src/database/query/preloader/ensure-model-class-initialized.js","../src/database/query/preloader/has-many.js","../src/database/query/preloader/has-one.js","../src/database/query/preloader/selection.js","../src/database/query-parser/base-query-parser.js","../src/database/query-parser/from-parser.js","../src/database/query-parser/group-parser.js","../src/database/query-parser/joins-parser.js","../src/database/query-parser/limit-parser.js","../src/database/query-parser/options.js","../src/database/query-parser/order-parser.js","../src/database/query-parser/select-parser.js","../src/database/query-parser/where-parser.js","../src/database/record/acts-as-list.js","../src/database/record/auditing.js","../src/database/record/counter-cache-magnitude.js","../src/database/record/index.js","../src/database/record/record-not-found-error.js","../src/database/record/state-machine.js","../src/database/record/user-module.js","../src/database/record/validation-messages.js","../src/database/record/attachments/attachment-record.js","../src/database/record/attachments/download.js","../src/database/record/attachments/handle.js","../src/database/record/attachments/normalize-input.js","../src/database/record/attachments/store.js","../src/database/record/attachments/storage-drivers/filesystem.js","../src/database/record/attachments/storage-drivers/native.js","../src/database/record/attachments/storage-drivers/s3.js","../src/database/record/instance-relationships/base.js","../src/database/record/instance-relationships/belongs-to.js","../src/database/record/instance-relationships/has-many.js","../src/database/record/instance-relationships/has-one.js","../src/database/record/relationships/base.js","../src/database/record/relationships/belongs-to.js","../src/database/record/relationships/has-many.js","../src/database/record/relationships/has-one.js","../src/database/record/validators/base.js","../src/database/record/validators/format.js","../src/database/record/validators/length.js","../src/database/record/validators/presence.js","../src/database/record/validators/uniqueness.js","../src/database/table-data/index.js","../src/database/table-data/table-column.js","../src/database/table-data/table-foreign-key.js","../src/database/table-data/table-index.js","../src/database/table-data/table-reference.js","../src/database/tenants/data-copier.js","../src/database/tenants/schema-cloner.js","../src/database/tenants/tenant-table-plan.js","../src/environment-handlers/base.js","../src/environment-handlers/browser.js","../src/environment-handlers/node.js","../src/environment-handlers/node/cli/commands/background-jobs-main.js","../src/environment-handlers/node/cli/commands/background-jobs-runner.js","../src/environment-handlers/node/cli/commands/background-jobs-worker.js","../src/environment-handlers/node/cli/commands/beacon.js","../src/environment-handlers/node/cli/commands/cli-command-context.js","../src/environment-handlers/node/cli/commands/console.js","../src/environment-handlers/node/cli/commands/init.js","../src/environment-handlers/node/cli/commands/routes.js","../src/environment-handlers/node/cli/commands/run-script.js","../src/environment-handlers/node/cli/commands/runner.js","../src/environment-handlers/node/cli/commands/server.js","../src/environment-handlers/node/cli/commands/test.js","../src/environment-handlers/node/cli/commands/db/seed.js","../src/environment-handlers/node/cli/commands/db/schema/dump.js","../src/environment-handlers/node/cli/commands/db/schema/load.js","../src/environment-handlers/node/cli/commands/destroy/migration.js","../src/environment-handlers/node/cli/commands/generate/base-models.js","../src/environment-handlers/node/cli/commands/generate/frontend-models.js","../src/environment-handlers/node/cli/commands/generate/generated-file-banner.js","../src/environment-handlers/node/cli/commands/generate/migration.js","../src/environment-handlers/node/cli/commands/generate/model.js","../src/environment-handlers/node/cli/commands/lint/relationships.js","../src/error-reporting/request-details.js","../src/frontend-model-resource/base-resource.js","../src/frontend-model-resource/velocious-attachment-resource.js","../src/frontend-models/base.js","../src/frontend-models/built-in-resources.js","../src/frontend-models/clear-pending-debounced-callback.js","../src/frontend-models/event-hook-models.js","../src/frontend-models/model-registry.js","../src/frontend-models/outgoing-event-buffer.js","../src/frontend-models/preloader.js","../src/frontend-models/query.js","../src/frontend-models/resource-config-validation.js","../src/frontend-models/resource-definition.js","../src/frontend-models/transport-serialization.js","../src/frontend-models/use-created-event.js","../src/frontend-models/use-destroyed-event.js","../src/frontend-models/use-model-class-event.js","../src/frontend-models/use-updated-event.js","../src/frontend-models/websocket-channel.js","../src/frontend-models/websocket-publishers.js","../src/http-client/header.js","../src/http-client/index.js","../src/http-client/request.js","../src/http-client/response.js","../src/http-client/websocket-client.js","../src/http-server/cookie.js","../src/http-server/development-reloader.js","../src/http-server/index.js","../src/http-server/remote-address.js","../src/http-server/server-client.js","../src/http-server/server-lock.js","../src/http-server/websocket-channel-subscribers.js","../src/http-server/websocket-channel.js","../src/http-server/websocket-connection.js","../src/http-server/websocket-event-log-store.js","../src/http-server/websocket-events-host.js","../src/http-server/websocket-events.js","../src/http-server/client/index.js","../src/http-server/client/params-to-object.js","../src/http-server/client/request-parser.js","../src/http-server/client/request-runner.js","../src/http-server/client/request-timing.js","../src/http-server/client/request.js","../src/http-server/client/response.js","../src/http-server/client/websocket-request.js","../src/http-server/client/websocket-session.js","../src/http-server/client/request-buffer/form-data-part.js","../src/http-server/client/request-buffer/header.js","../src/http-server/client/request-buffer/index.js","../src/http-server/client/uploaded-file/memory-uploaded-file.js","../src/http-server/client/uploaded-file/temporary-uploaded-file.js","../src/http-server/client/uploaded-file/uploaded-file.js","../src/http-server/worker-handler/channel-subscriber-dispatch.js","../src/http-server/worker-handler/in-process.js","../src/http-server/worker-handler/index.js","../src/http-server/worker-handler/worker-script.js","../src/http-server/worker-handler/worker-thread.js","../src/jobs/mail-delivery.js","../src/logger/base-logger.js","../src/logger/console-logger.js","../src/logger/file-logger.js","../src/logger/outputs/array-output.js","../src/logger/outputs/console-output.js","../src/logger/outputs/file-output.js","../src/logger/outputs/stdout-output.js","../src/mailer/base.js","../src/mailer/delivery.js","../src/mailer/index.js","../src/mailer/backends/smtp.js","../src/packages/velocious-package.js","../src/plugins/sqljs-wasm-route-controller.js","../src/plugins/sqljs-wasm-route.js","../src/routes/app-routes.js","../src/routes/base-route.js","../src/routes/basic-route.js","../src/routes/get-route.js","../src/routes/index.js","../src/routes/namespace-route.js","../src/routes/plugin-routes.js","../src/routes/post-route.js","../src/routes/resolver.js","../src/routes/resource-route.js","../src/routes/root-route.js","../src/routes/built-in/debug/controller.js","../src/routes/built-in/errors/controller.js","../src/routes/hooks/frontend-model-command-route-hook.js","../src/sync/conflict-strategy.js","../src/sync/device-identity.js","../src/sync/local-mutation-log.js","../src/sync/offline-grant.js","../src/sync/peer-mutation-bundle.js","../src/sync/query-scope.js","../src/sync/server-change-feed.js","../src/sync/server-sequence-allocator.js","../src/sync/stable-json.js","../src/sync/sync-api-client-types.js","../src/sync/sync-api-client.js","../src/sync/sync-api-controller.js","../src/sync/sync-client-registry.js","../src/sync/sync-client-types.js","../src/sync/sync-client.js","../src/sync/sync-envelope-replay-service.js","../src/sync/sync-model-change-feed-service.js","../src/sync/sync-replay-upsert-applier.js","../src/sync/sync-resource-base.js","../src/sync/sync-scope-store.js","../src/tenants/default-tenant-database-provisioning.js","../src/tenants/tenant-iterator.js","../src/tenants/tenant.js","../src/testing/base-expect.js","../src/testing/browser-frontend-model-event-hook-scenarios.js","../src/testing/browser-test-app.js","../src/testing/expect-to-change.js","../src/testing/expect-utils.js","../src/testing/expect.js","../src/testing/request-client.js","../src/testing/test-files-finder.js","../src/testing/test-filter-parser.js","../src/testing/test-runner.js","../src/testing/test-suite-splitter.js","../src/testing/test.js","../src/types/external-modules.d.ts","../src/utils/backtrace-cleaner-node.js","../src/utils/backtrace-cleaner.js","../src/utils/deburr-column-name.js","../src/utils/event-emitter.js","../src/utils/file-exists.js","../src/utils/format-value.js","../src/utils/is-date.js","../src/utils/model-scope.js","../src/utils/nest-callbacks.js","../src/utils/plain-object.js","../src/utils/ransack.js","../src/utils/rest-args-error.js","../src/utils/singularize-model-name.js","../src/utils/split-sql-statements.js","../src/utils/to-import-specifier.js","../src/utils/with-tracked-stack-async-hooks.js","../src/utils/with-tracked-stack.js"],"version":"6.0.3"}
|
|
1
|
+
{"root":["../index.js","../bin/velocious.js","../src/application.js","../src/configuration-resolver.js","../src/configuration-types.js","../src/configuration.js","../src/controller.js","../src/current-configuration.js","../src/current.js","../src/error-logger.js","../src/frontend-model-controller.js","../src/initializer.js","../src/logger.js","../src/mailer.js","../src/record-payload-values.js","../src/time-zone.js","../src/velocious-error.js","../src/authorization/ability.js","../src/authorization/base-resource.js","../src/background-jobs/client.js","../src/background-jobs/cron-expression.js","../src/background-jobs/forked-runner-child.js","../src/background-jobs/job-record.js","../src/background-jobs/job-registry.js","../src/background-jobs/job-runner.js","../src/background-jobs/job.js","../src/background-jobs/json-socket.js","../src/background-jobs/main.js","../src/background-jobs/normalize-error.js","../src/background-jobs/scheduler.js","../src/background-jobs/socket-request.js","../src/background-jobs/status-reporter.js","../src/background-jobs/store.js","../src/background-jobs/types.js","../src/background-jobs/worker.js","../src/background-jobs/web/authorization.js","../src/background-jobs/web/controller.js","../src/background-jobs/web/index.js","../src/background-jobs/web/path-matcher.js","../src/background-jobs/web/registry.js","../src/beacon/client.js","../src/beacon/in-process-broker.js","../src/beacon/in-process-client.js","../src/beacon/server.js","../src/beacon/types.js","../src/cli/base-command.js","../src/cli/browser-cli.js","../src/cli/index.js","../src/cli/tenant-database-command-helper.js","../src/cli/use-browser-cli.js","../src/cli/commands/background-jobs-main.js","../src/cli/commands/background-jobs-runner.js","../src/cli/commands/background-jobs-worker.js","../src/cli/commands/beacon.js","../src/cli/commands/console.js","../src/cli/commands/init.js","../src/cli/commands/routes.js","../src/cli/commands/run-script.js","../src/cli/commands/runner.js","../src/cli/commands/server.js","../src/cli/commands/test.js","../src/cli/commands/db/base-command.js","../src/cli/commands/db/create.js","../src/cli/commands/db/drop.js","../src/cli/commands/db/migrate.js","../src/cli/commands/db/reset.js","../src/cli/commands/db/rollback.js","../src/cli/commands/db/seed.js","../src/cli/commands/db/schema/dump.js","../src/cli/commands/db/schema/load.js","../src/cli/commands/db/tenants/check.js","../src/cli/commands/db/tenants/create.js","../src/cli/commands/db/tenants/drop.js","../src/cli/commands/db/tenants/migrate.js","../src/cli/commands/destroy/migration.js","../src/cli/commands/generate/base-models.js","../src/cli/commands/generate/frontend-models.js","../src/cli/commands/generate/migration.js","../src/cli/commands/generate/model.js","../src/cli/commands/lint/relationships.js","../src/database/annotations-async-hooks.js","../src/database/annotations.js","../src/database/column-types.js","../src/database/datetime-storage.js","../src/database/handler.js","../src/database/initializer-from-require-context.js","../src/database/migrations-ledger.js","../src/database/migrator.js","../src/database/use-database.js","../src/database/drivers/base-column.js","../src/database/drivers/base-columns-index.js","../src/database/drivers/base-foreign-key.js","../src/database/drivers/base-table.js","../src/database/drivers/base.js","../src/database/drivers/mssql/column.js","../src/database/drivers/mssql/columns-index.js","../src/database/drivers/mssql/connect-connection.js","../src/database/drivers/mssql/foreign-key.js","../src/database/drivers/mssql/index.js","../src/database/drivers/mssql/options.js","../src/database/drivers/mssql/query-parser.js","../src/database/drivers/mssql/structure-sql.js","../src/database/drivers/mssql/table.js","../src/database/drivers/mssql/sql/alter-table.js","../src/database/drivers/mssql/sql/create-database.js","../src/database/drivers/mssql/sql/create-index.js","../src/database/drivers/mssql/sql/create-table.js","../src/database/drivers/mssql/sql/delete.js","../src/database/drivers/mssql/sql/drop-database.js","../src/database/drivers/mssql/sql/drop-table.js","../src/database/drivers/mssql/sql/insert.js","../src/database/drivers/mssql/sql/remove-index.js","../src/database/drivers/mssql/sql/update.js","../src/database/drivers/mssql/sql/upsert.js","../src/database/drivers/mysql/column.js","../src/database/drivers/mysql/columns-index.js","../src/database/drivers/mysql/foreign-key.js","../src/database/drivers/mysql/index.js","../src/database/drivers/mysql/options.js","../src/database/drivers/mysql/query-parser.js","../src/database/drivers/mysql/query.js","../src/database/drivers/mysql/structure-sql.js","../src/database/drivers/mysql/table.js","../src/database/drivers/mysql/sql/alter-table.js","../src/database/drivers/mysql/sql/create-database.js","../src/database/drivers/mysql/sql/create-index.js","../src/database/drivers/mysql/sql/create-table.js","../src/database/drivers/mysql/sql/delete.js","../src/database/drivers/mysql/sql/drop-database.js","../src/database/drivers/mysql/sql/drop-table.js","../src/database/drivers/mysql/sql/insert.js","../src/database/drivers/mysql/sql/remove-index.js","../src/database/drivers/mysql/sql/update.js","../src/database/drivers/mysql/sql/upsert.js","../src/database/drivers/pgsql/column.js","../src/database/drivers/pgsql/columns-index.js","../src/database/drivers/pgsql/foreign-key.js","../src/database/drivers/pgsql/index.js","../src/database/drivers/pgsql/options.js","../src/database/drivers/pgsql/query-parser.js","../src/database/drivers/pgsql/structure-sql.js","../src/database/drivers/pgsql/table.js","../src/database/drivers/pgsql/sql/alter-table.js","../src/database/drivers/pgsql/sql/create-database.js","../src/database/drivers/pgsql/sql/create-index.js","../src/database/drivers/pgsql/sql/create-table.js","../src/database/drivers/pgsql/sql/delete.js","../src/database/drivers/pgsql/sql/drop-database.js","../src/database/drivers/pgsql/sql/drop-table.js","../src/database/drivers/pgsql/sql/insert.js","../src/database/drivers/pgsql/sql/remove-index.js","../src/database/drivers/pgsql/sql/update.js","../src/database/drivers/pgsql/sql/upsert.js","../src/database/drivers/sqlite/base.js","../src/database/drivers/sqlite/column.js","../src/database/drivers/sqlite/columns-index.js","../src/database/drivers/sqlite/connection-sql-js.js","../src/database/drivers/sqlite/foreign-key.js","../src/database/drivers/sqlite/index.js","../src/database/drivers/sqlite/index.native.js","../src/database/drivers/sqlite/index.web.js","../src/database/drivers/sqlite/options.js","../src/database/drivers/sqlite/query-parser.js","../src/database/drivers/sqlite/query.js","../src/database/drivers/sqlite/query.native.js","../src/database/drivers/sqlite/query.web.js","../src/database/drivers/sqlite/structure-sql.js","../src/database/drivers/sqlite/table-rebuilder.js","../src/database/drivers/sqlite/table.js","../src/database/drivers/sqlite/web-persistence.js","../src/database/drivers/sqlite/sql/alter-table.js","../src/database/drivers/sqlite/sql/create-index.js","../src/database/drivers/sqlite/sql/create-table.js","../src/database/drivers/sqlite/sql/delete.js","../src/database/drivers/sqlite/sql/drop-table.js","../src/database/drivers/sqlite/sql/insert.js","../src/database/drivers/sqlite/sql/remove-index.js","../src/database/drivers/sqlite/sql/update.js","../src/database/drivers/sqlite/sql/upsert.js","../src/database/drivers/structure-sql/utils.js","../src/database/migration/index.js","../src/database/migrator/files-finder.js","../src/database/migrator/types.js","../src/database/pool/async-tracked-multi-connection.js","../src/database/pool/base-methods-forward.js","../src/database/pool/base.js","../src/database/pool/single-multi-use.js","../src/database/query/alter-table-base.js","../src/database/query/base.js","../src/database/query/create-database-base.js","../src/database/query/create-index-base.js","../src/database/query/create-table-base.js","../src/database/query/delete-base.js","../src/database/query/drop-database-base.js","../src/database/query/drop-table-base.js","../src/database/query/from-base.js","../src/database/query/from-plain.js","../src/database/query/from-table.js","../src/database/query/index.js","../src/database/query/insert-base.js","../src/database/query/join-base.js","../src/database/query/join-object.js","../src/database/query/join-plain.js","../src/database/query/join-tracker.js","../src/database/query/model-class-query.js","../src/database/query/order-base.js","../src/database/query/order-column.js","../src/database/query/order-plain.js","../src/database/query/preloader.js","../src/database/query/query-data.js","../src/database/query/remove-index-base.js","../src/database/query/select-base.js","../src/database/query/select-plain.js","../src/database/query/select-table-and-column.js","../src/database/query/update-base.js","../src/database/query/upsert-base.js","../src/database/query/where-base.js","../src/database/query/where-combinator.js","../src/database/query/where-hash.js","../src/database/query/where-model-class-hash.js","../src/database/query/where-not.js","../src/database/query/where-plain.js","../src/database/query/with-count.js","../src/database/query/preloader/belongs-to.js","../src/database/query/preloader/ensure-model-class-initialized.js","../src/database/query/preloader/has-many.js","../src/database/query/preloader/has-one.js","../src/database/query/preloader/selection.js","../src/database/query-parser/base-query-parser.js","../src/database/query-parser/from-parser.js","../src/database/query-parser/group-parser.js","../src/database/query-parser/joins-parser.js","../src/database/query-parser/limit-parser.js","../src/database/query-parser/options.js","../src/database/query-parser/order-parser.js","../src/database/query-parser/select-parser.js","../src/database/query-parser/where-parser.js","../src/database/record/acts-as-list.js","../src/database/record/auditing.js","../src/database/record/counter-cache-magnitude.js","../src/database/record/index.js","../src/database/record/record-not-found-error.js","../src/database/record/state-machine.js","../src/database/record/user-module.js","../src/database/record/validation-messages.js","../src/database/record/attachments/attachment-record.js","../src/database/record/attachments/download.js","../src/database/record/attachments/handle.js","../src/database/record/attachments/normalize-input.js","../src/database/record/attachments/store.js","../src/database/record/attachments/storage-drivers/filesystem.js","../src/database/record/attachments/storage-drivers/native.js","../src/database/record/attachments/storage-drivers/s3.js","../src/database/record/instance-relationships/base.js","../src/database/record/instance-relationships/belongs-to.js","../src/database/record/instance-relationships/has-many.js","../src/database/record/instance-relationships/has-one.js","../src/database/record/relationships/base.js","../src/database/record/relationships/belongs-to.js","../src/database/record/relationships/has-many.js","../src/database/record/relationships/has-one.js","../src/database/record/validators/base.js","../src/database/record/validators/format.js","../src/database/record/validators/length.js","../src/database/record/validators/presence.js","../src/database/record/validators/uniqueness.js","../src/database/table-data/index.js","../src/database/table-data/table-column.js","../src/database/table-data/table-foreign-key.js","../src/database/table-data/table-index.js","../src/database/table-data/table-reference.js","../src/database/tenants/data-copier.js","../src/database/tenants/schema-cloner.js","../src/database/tenants/tenant-table-plan.js","../src/environment-handlers/base.js","../src/environment-handlers/browser.js","../src/environment-handlers/node.js","../src/environment-handlers/node/cli/commands/background-jobs-main.js","../src/environment-handlers/node/cli/commands/background-jobs-runner.js","../src/environment-handlers/node/cli/commands/background-jobs-worker.js","../src/environment-handlers/node/cli/commands/beacon.js","../src/environment-handlers/node/cli/commands/cli-command-context.js","../src/environment-handlers/node/cli/commands/console.js","../src/environment-handlers/node/cli/commands/init.js","../src/environment-handlers/node/cli/commands/routes.js","../src/environment-handlers/node/cli/commands/run-script.js","../src/environment-handlers/node/cli/commands/runner.js","../src/environment-handlers/node/cli/commands/server.js","../src/environment-handlers/node/cli/commands/test.js","../src/environment-handlers/node/cli/commands/db/seed.js","../src/environment-handlers/node/cli/commands/db/schema/dump.js","../src/environment-handlers/node/cli/commands/db/schema/load.js","../src/environment-handlers/node/cli/commands/destroy/migration.js","../src/environment-handlers/node/cli/commands/generate/base-models.js","../src/environment-handlers/node/cli/commands/generate/frontend-models.js","../src/environment-handlers/node/cli/commands/generate/generated-file-banner.js","../src/environment-handlers/node/cli/commands/generate/migration.js","../src/environment-handlers/node/cli/commands/generate/model.js","../src/environment-handlers/node/cli/commands/lint/relationships.js","../src/error-reporting/request-details.js","../src/frontend-model-resource/base-resource.js","../src/frontend-model-resource/velocious-attachment-resource.js","../src/frontend-models/base.js","../src/frontend-models/built-in-resources.js","../src/frontend-models/clear-pending-debounced-callback.js","../src/frontend-models/event-hook-models.js","../src/frontend-models/model-registry.js","../src/frontend-models/outgoing-event-buffer.js","../src/frontend-models/preloader.js","../src/frontend-models/query.js","../src/frontend-models/resource-config-validation.js","../src/frontend-models/resource-definition.js","../src/frontend-models/transport-serialization.js","../src/frontend-models/use-created-event.js","../src/frontend-models/use-destroyed-event.js","../src/frontend-models/use-model-class-event.js","../src/frontend-models/use-updated-event.js","../src/frontend-models/websocket-channel.js","../src/frontend-models/websocket-publishers.js","../src/http-client/header.js","../src/http-client/index.js","../src/http-client/request.js","../src/http-client/response.js","../src/http-client/websocket-client.js","../src/http-server/cookie.js","../src/http-server/development-reloader.js","../src/http-server/index.js","../src/http-server/remote-address.js","../src/http-server/server-client.js","../src/http-server/server-lock.js","../src/http-server/websocket-channel-subscribers.js","../src/http-server/websocket-channel.js","../src/http-server/websocket-connection.js","../src/http-server/websocket-event-log-store.js","../src/http-server/websocket-events-host.js","../src/http-server/websocket-events.js","../src/http-server/client/index.js","../src/http-server/client/params-to-object.js","../src/http-server/client/request-parser.js","../src/http-server/client/request-runner.js","../src/http-server/client/request-timing.js","../src/http-server/client/request.js","../src/http-server/client/response.js","../src/http-server/client/websocket-request.js","../src/http-server/client/websocket-session.js","../src/http-server/client/request-buffer/form-data-part.js","../src/http-server/client/request-buffer/header.js","../src/http-server/client/request-buffer/index.js","../src/http-server/client/uploaded-file/memory-uploaded-file.js","../src/http-server/client/uploaded-file/temporary-uploaded-file.js","../src/http-server/client/uploaded-file/uploaded-file.js","../src/http-server/worker-handler/channel-subscriber-dispatch.js","../src/http-server/worker-handler/in-process.js","../src/http-server/worker-handler/index.js","../src/http-server/worker-handler/worker-script.js","../src/http-server/worker-handler/worker-thread.js","../src/jobs/mail-delivery.js","../src/logger/base-logger.js","../src/logger/console-logger.js","../src/logger/file-logger.js","../src/logger/outputs/array-output.js","../src/logger/outputs/console-output.js","../src/logger/outputs/file-output.js","../src/logger/outputs/stdout-output.js","../src/mailer/base.js","../src/mailer/delivery.js","../src/mailer/index.js","../src/mailer/backends/smtp.js","../src/packages/velocious-package.js","../src/plugins/sqljs-wasm-route-controller.js","../src/plugins/sqljs-wasm-route.js","../src/routes/app-routes.js","../src/routes/base-route.js","../src/routes/basic-route.js","../src/routes/get-route.js","../src/routes/index.js","../src/routes/namespace-route.js","../src/routes/plugin-routes.js","../src/routes/post-route.js","../src/routes/resolver.js","../src/routes/resource-route.js","../src/routes/root-route.js","../src/routes/built-in/debug/controller.js","../src/routes/built-in/errors/controller.js","../src/routes/hooks/frontend-model-command-route-hook.js","../src/sync/conflict-strategy.js","../src/sync/device-identity.js","../src/sync/local-mutation-log.js","../src/sync/offline-grant.js","../src/sync/peer-mutation-bundle.js","../src/sync/query-scope.js","../src/sync/server-change-feed.js","../src/sync/server-sequence-allocator.js","../src/sync/stable-json.js","../src/sync/sync-api-client-types.js","../src/sync/sync-api-client.js","../src/sync/sync-api-controller.js","../src/sync/sync-client-registry.js","../src/sync/sync-client-types.js","../src/sync/sync-client.js","../src/sync/sync-envelope-replay-service.js","../src/sync/sync-model-change-feed-service.js","../src/sync/sync-realtime-bridge.js","../src/sync/sync-replay-upsert-applier.js","../src/sync/sync-resource-base.js","../src/sync/sync-scope-store.js","../src/tenants/default-tenant-database-provisioning.js","../src/tenants/tenant-iterator.js","../src/tenants/tenant.js","../src/testing/base-expect.js","../src/testing/browser-frontend-model-event-hook-scenarios.js","../src/testing/browser-test-app.js","../src/testing/expect-to-change.js","../src/testing/expect-utils.js","../src/testing/expect.js","../src/testing/request-client.js","../src/testing/test-files-finder.js","../src/testing/test-filter-parser.js","../src/testing/test-runner.js","../src/testing/test-suite-splitter.js","../src/testing/test.js","../src/types/external-modules.d.ts","../src/utils/backtrace-cleaner-node.js","../src/utils/backtrace-cleaner.js","../src/utils/deburr-column-name.js","../src/utils/event-emitter.js","../src/utils/file-exists.js","../src/utils/format-value.js","../src/utils/is-date.js","../src/utils/model-scope.js","../src/utils/nest-callbacks.js","../src/utils/plain-object.js","../src/utils/ransack.js","../src/utils/rest-args-error.js","../src/utils/singularize-model-name.js","../src/utils/split-sql-statements.js","../src/utils/to-import-specifier.js","../src/utils/with-tracked-stack-async-hooks.js","../src/utils/with-tracked-stack.js"],"version":"6.0.3"}
|
package/package.json
CHANGED
|
@@ -369,6 +369,44 @@
|
|
|
369
369
|
* @property {(path: string, body?: ?, options?: {headers?: Record<string, string>}) => Promise<{json: () => ?}>} post - Posts one request and resolves a response with a json accessor.
|
|
370
370
|
*/
|
|
371
371
|
|
|
372
|
+
/**
|
|
373
|
+
* Websocket client contract required from `sync.client.realtime.createClient`,
|
|
374
|
+
* matching `VelociousWebsocketClient` / snapreq's websocket client.
|
|
375
|
+
* @typedef {object} VelociousSyncRealtimeWebsocketClient
|
|
376
|
+
* @property {() => Promise<?>} connect - Connects the websocket.
|
|
377
|
+
* @property {(channelType: string, options?: {params?: Record<string, ?>, onMessage?: (body: ?) => void, onResume?: () => void, onClose?: (reason: string) => void}) => VelociousSyncRealtimeSubscription} subscribeChannel - Opens one channel subscription.
|
|
378
|
+
* @property {() => Promise<void>} disconnectAndStopReconnect - Closes the socket and stops auto-reconnect.
|
|
379
|
+
*/
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Channel subscription handle returned by `subscribeChannel`.
|
|
383
|
+
* @typedef {object} VelociousSyncRealtimeSubscription
|
|
384
|
+
* @property {() => void} close - Closes the subscription.
|
|
385
|
+
* @property {() => boolean} isReady - Whether the subscription is acknowledged and ready.
|
|
386
|
+
* @property {(params?: {timeoutMs?: number}) => Promise<void>} waitForReady - Resolves once the server acknowledges the subscription.
|
|
387
|
+
*/
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* One realtime channel subscription descriptor.
|
|
391
|
+
* @typedef {object} VelociousSyncRealtimeChannelDescriptor
|
|
392
|
+
* @property {string} channel - Server channel name to subscribe.
|
|
393
|
+
* @property {Record<string, ?>} [params] - Subscribe params (runtime values like eventId). The framework injects `authenticationToken` automatically.
|
|
394
|
+
* @property {string} [resourceType] - Default resource/model name for pushed changes that do not carry their own resourceType.
|
|
395
|
+
*/
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Realtime push configuration for the sync client. Only the genuinely app-owned
|
|
399
|
+
* callbacks live here: how to build the websocket client and which channels
|
|
400
|
+
* (with runtime params) to subscribe. Everything else - subscribing, applying
|
|
401
|
+
* pushes through the derived resource applier, echo suppression, and
|
|
402
|
+
* pull-on-reconnect - is derived.
|
|
403
|
+
* @typedef {object} VelociousSyncClientRealtimeConfiguration
|
|
404
|
+
* @property {() => VelociousSyncRealtimeWebsocketClient | Promise<VelociousSyncRealtimeWebsocketClient>} createClient - Builds the (unconnected) websocket client; the framework owns connect/disconnect.
|
|
405
|
+
* @property {(context: ?) => Array<VelociousSyncRealtimeChannelDescriptor> | Promise<Array<VelociousSyncRealtimeChannelDescriptor>>} [channels] - Resolves channel descriptors from the `subscribeRealtime(context)` context (runtime params like eventId). Optional when models declare `static sync = {realtime: {channel}}`.
|
|
406
|
+
* @property {() => string | Promise<string>} [localOrigin] - Resolves this device's echo origin; pushed messages with a matching `echoOrigin` are dropped.
|
|
407
|
+
* @property {boolean} [pullOnReconnect] - Fire a coalesced `pull()` when subscriptions become ready or resume after a drop, closing offline gaps. Defaults to true.
|
|
408
|
+
*/
|
|
409
|
+
|
|
372
410
|
/**
|
|
373
411
|
* Client-side sync configuration consumed by `SyncClient.fromConfiguration(...)`.
|
|
374
412
|
* The framework owns the `${mountPath}/changes` and `${mountPath}/replay`
|
|
@@ -379,6 +417,7 @@
|
|
|
379
417
|
* @property {() => boolean | Promise<boolean>} [isOnline] - Connectivity gate for pulls and replays. Defaults to always online.
|
|
380
418
|
* @property {string} [mountPath] - Mount path the server serves the sync endpoints under (match the server's `sync.api.mountPath`). Defaults to "/velocious/sync"; normalization strips trailing slashes and always fills in the default.
|
|
381
419
|
* @property {(error: Error) => void} [onError] - Reports background replay/pull failures. Defaults to rethrowing.
|
|
420
|
+
* @property {VelociousSyncClientRealtimeConfiguration} [realtime] - Realtime push configuration consumed by `subscribeRealtime(...)`.
|
|
382
421
|
* @property {VelociousSyncClientTransport} transport - Transport posting to the framework sync endpoints (e.g. the frontend-model websocket client).
|
|
383
422
|
*/
|
|
384
423
|
|
package/src/configuration.js
CHANGED
|
@@ -463,11 +463,11 @@ export default class VelociousConfiguration {
|
|
|
463
463
|
throw new Error("sync.client must be an object with transport and authenticationToken")
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
-
const {authenticationToken, batchSize, isOnline, mountPath, onError, transport, ...restClient} = client
|
|
466
|
+
const {authenticationToken, batchSize, isOnline, mountPath, onError, realtime, transport, ...restClient} = client
|
|
467
467
|
const restClientKeys = Object.keys(restClient)
|
|
468
468
|
|
|
469
469
|
if (restClientKeys.length > 0) {
|
|
470
|
-
throw new Error(`sync.client received unknown keys: ${restClientKeys.join(", ")} (supported: authenticationToken, batchSize, isOnline, mountPath, onError, transport)`)
|
|
470
|
+
throw new Error(`sync.client received unknown keys: ${restClientKeys.join(", ")} (supported: authenticationToken, batchSize, isOnline, mountPath, onError, realtime, transport)`)
|
|
471
471
|
}
|
|
472
472
|
if (!transport || typeof transport !== "object" || typeof transport.post !== "function") {
|
|
473
473
|
throw new Error("sync.client.transport must be an object with a post(path, body) method (like the frontend-model websocket client)")
|
|
@@ -494,6 +494,7 @@ export default class VelociousConfiguration {
|
|
|
494
494
|
isOnline,
|
|
495
495
|
mountPath: (mountPath || "/velocious/sync").replace(/\/+$/u, "") || "/",
|
|
496
496
|
onError,
|
|
497
|
+
realtime,
|
|
497
498
|
transport
|
|
498
499
|
}
|
|
499
500
|
}
|
|
@@ -7,6 +7,15 @@
|
|
|
7
7
|
* @property {string} resourceType - Resource/model name the scope was declared for.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Static realtime channel declaration on a model's `static sync`, for channels
|
|
12
|
+
* whose name and params are static. Channels needing runtime params (like
|
|
13
|
+
* eventId) belong in the `sync.client.realtime.channels` callback instead.
|
|
14
|
+
* @typedef {object} ModelSyncRealtimeDeclaration
|
|
15
|
+
* @property {string} channel - Server channel name to subscribe.
|
|
16
|
+
* @property {Record<string, ?>} [params] - Static subscribe params. The framework injects `authenticationToken` automatically.
|
|
17
|
+
*/
|
|
18
|
+
|
|
10
19
|
/**
|
|
11
20
|
* Declarative per-resource sync policy.
|
|
12
21
|
* @typedef {object} SyncClientResourceConfig
|
|
@@ -20,6 +29,7 @@
|
|
|
20
29
|
* @property {"upsert" | ((args: {operation: "create" | "update" | "destroy", record: ?}) => string)} [syncType] - Maps a mutation operation to a sync type. The "upsert" flag queues creates and updates as "update" rows (the server upserts by resource id) and destroys as "delete". Defaults to the operation name with destroy mapped to "delete".
|
|
21
30
|
* @property {(args: {operation: "create" | "update" | "destroy", record: ?}) => Record<string, ?>} [trackedData] - Custom queued-payload builder for tracked mutations.
|
|
22
31
|
* @property {boolean | {operations: Array<"create" | "update" | "destroy">}} [track] - Enables automatic mutation tracking through model lifecycle callbacks.
|
|
32
|
+
* @property {ModelSyncRealtimeDeclaration} [realtime] - Static realtime channel this resource subscribes through `subscribeRealtime(...)`.
|
|
23
33
|
*/
|
|
24
34
|
|
|
25
35
|
/**
|
|
@@ -36,6 +46,7 @@
|
|
|
36
46
|
* @property {"upsert" | ((args: {operation: "create" | "update" | "destroy", record: ?}) => string)} [syncType] - Sync type flag or mapper (see SyncClientResourceConfig).
|
|
37
47
|
* @property {boolean | Array<"create" | "update" | "destroy"> | {operations: Array<"create" | "update" | "destroy">}} [track] - Enables automatic mutation tracking; an array is shorthand for {operations}.
|
|
38
48
|
* @property {(args: {operation: "create" | "update" | "destroy", record: ?}) => Record<string, ?>} [trackedData] - Custom queued-payload builder for tracked mutations.
|
|
49
|
+
* @property {ModelSyncRealtimeDeclaration} [realtime] - Static realtime channel this resource subscribes through `subscribeRealtime(...)`; use the `sync.client.realtime.channels` callback for channels needing runtime params.
|
|
39
50
|
*/
|
|
40
51
|
|
|
41
52
|
/** @typedef {boolean | ModelSyncDeclarationConfig} ModelSyncDeclaration */
|
|
@@ -63,6 +74,7 @@
|
|
|
63
74
|
* @property {(error: Error) => void} [onError] - Reports background replay/pull failures. Defaults to rethrowing.
|
|
64
75
|
* @property {(payload: import("./sync-api-client-types.js").SyncChangesRequest & {scope: SerializedSyncScope}) => Promise<import("./sync-api-client-types.js").SyncChangesResponse>} postChanges - Posts one changes request.
|
|
65
76
|
* @property {(payload: {authenticationToken: string, syncs: Array<Record<string, ?>>}) => Promise<import("./sync-api-client-types.js").SyncReplayResponse>} postReplay - Posts one replay request.
|
|
77
|
+
* @property {import("../configuration-types.js").VelociousSyncClientRealtimeConfiguration} [realtime] - Realtime push configuration consumed by `subscribeRealtime(...)`.
|
|
66
78
|
* @property {Record<string, SyncClientResourceConfig>} resources - Derived resource policies keyed by resource/model name.
|
|
67
79
|
* @property {?} syncModel - Local pending-sync model class.
|
|
68
80
|
*/
|