velocious 1.0.503 → 1.0.504
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/application.js +2 -0
- package/build/configuration-types.js +8 -8
- package/build/configuration.js +2 -2
- package/build/src/application.d.ts.map +1 -1
- package/build/src/application.js +3 -1
- package/build/src/configuration-types.d.ts +17 -17
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +9 -9
- package/build/src/configuration.d.ts +4 -4
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +3 -3
- package/build/src/sync/sync-channel-name.d.ts +9 -0
- package/build/src/sync/sync-channel-name.d.ts.map +1 -0
- package/build/src/sync/sync-channel-name.js +10 -0
- package/build/src/sync/sync-client-types.d.ts +10 -7
- 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 +1 -1
- package/build/src/sync/sync-client.js +2 -2
- package/build/src/sync/sync-model-change-feed-service.d.ts +6 -1
- package/build/src/sync/sync-model-change-feed-service.d.ts.map +1 -1
- package/build/src/sync/sync-model-change-feed-service.js +15 -4
- package/build/src/sync/sync-publisher-types.d.ts +53 -21
- package/build/src/sync/sync-publisher-types.d.ts.map +1 -1
- package/build/src/sync/sync-publisher-types.js +1 -1
- package/build/src/sync/sync-publisher.d.ts +32 -9
- package/build/src/sync/sync-publisher.d.ts.map +1 -1
- package/build/src/sync/sync-publisher.js +170 -37
- package/build/src/sync/sync-realtime-bridge.d.ts +33 -10
- package/build/src/sync/sync-realtime-bridge.d.ts.map +1 -1
- package/build/src/sync/sync-realtime-bridge.js +51 -12
- package/build/src/sync/sync-scope-attributes.d.ts +15 -0
- package/build/src/sync/sync-scope-attributes.d.ts.map +1 -0
- package/build/src/sync/sync-scope-attributes.js +24 -0
- package/build/src/sync/sync-websocket-channel.d.ts +58 -0
- package/build/src/sync/sync-websocket-channel.d.ts.map +1 -0
- package/build/src/sync/sync-websocket-channel.js +131 -0
- package/build/sync/sync-channel-name.js +10 -0
- package/build/sync/sync-client-types.js +12 -6
- package/build/sync/sync-client.js +1 -1
- package/build/sync/sync-model-change-feed-service.js +17 -3
- package/build/sync/sync-publisher-types.js +32 -12
- package/build/sync/sync-publisher.js +192 -41
- package/build/sync/sync-realtime-bridge.js +56 -11
- package/build/sync/sync-scope-attributes.js +26 -0
- package/build/sync/sync-websocket-channel.js +146 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/application.js +2 -0
- package/src/configuration-types.js +8 -8
- package/src/configuration.js +2 -2
- package/src/sync/sync-channel-name.js +10 -0
- package/src/sync/sync-client-types.js +12 -6
- package/src/sync/sync-client.js +1 -1
- package/src/sync/sync-model-change-feed-service.js +17 -3
- package/src/sync/sync-publisher-types.js +32 -12
- package/src/sync/sync-publisher.js +192 -41
- package/src/sync/sync-realtime-bridge.js +56 -11
- package/src/sync/sync-scope-attributes.js +26 -0
- package/src/sync/sync-websocket-channel.js +146 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import VelociousWebsocketChannel from "../http-server/websocket-channel.js"
|
|
4
|
+
import {VELOCIOUS_SYNC_CHANNEL} from "./sync-channel-name.js"
|
|
5
|
+
|
|
6
|
+
/** Configurations whose framework sync channel has already been registered. */
|
|
7
|
+
const registeredConfigurations = new WeakSet()
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Framework-owned websocket channel for synced resources
|
|
11
|
+
* ({@link VELOCIOUS_SYNC_CHANNEL}).
|
|
12
|
+
*
|
|
13
|
+
* Subscribe params mirror a declared pull scope — `{resourceType, conditions}`
|
|
14
|
+
* plus the client-injected `authenticationToken` — and subscribe-time
|
|
15
|
+
* authorization delegates to the app sync resource's existing
|
|
16
|
+
* `authorizeChanges({params, scope})` (the `sync.api.resourceClass`), so apps
|
|
17
|
+
* hook in through the authorization they already declared instead of writing
|
|
18
|
+
* their own channel classes. Broadcast routing matches the publisher's
|
|
19
|
+
* scoping params against the subscription's scope conditions.
|
|
20
|
+
*/
|
|
21
|
+
export default class SyncWebsocketChannel extends VelociousWebsocketChannel {
|
|
22
|
+
/**
|
|
23
|
+
* Scope the subscription was authorized for, set by {@link SyncWebsocketChannel#canSubscribe}.
|
|
24
|
+
* @type {import("./sync-resource-base.js").SerializedChangesScope | null}
|
|
25
|
+
*/
|
|
26
|
+
_scope = null
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Registers the framework sync channel on a configuration declaring a
|
|
30
|
+
* `sync.api` block (guarded so repeated server boots with the same
|
|
31
|
+
* configuration register it only once). No-op without `sync.api` — the
|
|
32
|
+
* channel authorizes through the app's sync resource class.
|
|
33
|
+
* @param {import("../configuration.js").default} configuration - Configuration instance.
|
|
34
|
+
* @returns {void}
|
|
35
|
+
*/
|
|
36
|
+
static registerFromConfiguration(configuration) {
|
|
37
|
+
if (!configuration.getSyncConfiguration().api || registeredConfigurations.has(configuration)) return
|
|
38
|
+
|
|
39
|
+
registeredConfigurations.add(configuration)
|
|
40
|
+
configuration.registerWebsocketChannel(VELOCIOUS_SYNC_CHANNEL, this)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Authorizes the subscription through the app sync resource: the subscribe
|
|
45
|
+
* params are parsed into the same serialized scope the changes endpoint
|
|
46
|
+
* consumes and passed to the resource's `authorizeChanges({params, scope})`.
|
|
47
|
+
* Denials and malformed scopes throw, rejecting the subscription.
|
|
48
|
+
* @returns {Promise<boolean>} Whether the subscription is allowed.
|
|
49
|
+
*/
|
|
50
|
+
async canSubscribe() {
|
|
51
|
+
const resource = await this.buildSyncResource()
|
|
52
|
+
const scope = resource.changesScope({scope: {conditions: this.params.conditions, resourceType: this.params.resourceType}})
|
|
53
|
+
|
|
54
|
+
await resource.authorizeChanges({params: this.params, scope})
|
|
55
|
+
|
|
56
|
+
this._scope = scope
|
|
57
|
+
|
|
58
|
+
return true
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Builds the app sync resource authorizing this subscription, mirroring the
|
|
63
|
+
* sync transport controller's resource construction with the ability
|
|
64
|
+
* resolved from the subscribe params (which carry the client-injected
|
|
65
|
+
* authenticationToken).
|
|
66
|
+
* @returns {Promise<import("./sync-resource-base.js").default>} App sync resource instance.
|
|
67
|
+
*/
|
|
68
|
+
async buildSyncResource() {
|
|
69
|
+
const configuration = this.session.configuration
|
|
70
|
+
const api = configuration.getSyncConfiguration().api
|
|
71
|
+
|
|
72
|
+
if (!api) {
|
|
73
|
+
throw new Error(`The ${VELOCIOUS_SYNC_CHANNEL} channel requires a sync.api configuration block with the app's sync resource class`)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Narrows the configured resource class to the sync resource contract
|
|
77
|
+
// (changesScope/authorizeChanges) the sync.api validation requires.
|
|
78
|
+
const ResourceClass = /** @type {typeof import("./sync-resource-base.js").default} */ (api.resourceClass)
|
|
79
|
+
// Narrows the websocket subscribe params to the resource params contract.
|
|
80
|
+
const params = /** @type {import("../configuration-types.js").VelociousParams} */ (/** @type {unknown} */ (this.params))
|
|
81
|
+
const request = this.session.upgradeRequest
|
|
82
|
+
const ability = await configuration.resolveAbility({params, request})
|
|
83
|
+
|
|
84
|
+
return new ResourceClass({
|
|
85
|
+
ability,
|
|
86
|
+
context: {
|
|
87
|
+
...(ability?.getContext() || {}),
|
|
88
|
+
params,
|
|
89
|
+
request
|
|
90
|
+
},
|
|
91
|
+
locals: ability?.getLocals() || {},
|
|
92
|
+
modelClass: ResourceClass.ModelClass,
|
|
93
|
+
modelName: ResourceClass.ModelClass?.name,
|
|
94
|
+
params,
|
|
95
|
+
resourceConfiguration: /** @type {import("../configuration-types.js").FrontendModelResourceConfiguration} */ ({
|
|
96
|
+
attributes: ResourceClass.attributes || {},
|
|
97
|
+
sync: {enabled: true}
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Routes a publisher broadcast to this subscription when the published
|
|
104
|
+
* resource type equals the type the subscription was authorized for and the
|
|
105
|
+
* scoping params satisfy every scope condition: each condition key must be
|
|
106
|
+
* present in the broadcast params and match by string comparison (array
|
|
107
|
+
* conditions match by membership). Broadcasts without a resource type and
|
|
108
|
+
* conditions the publisher's scoping params do not carry never match, so a
|
|
109
|
+
* subscription cannot receive changes outside its authorized scope.
|
|
110
|
+
* @param {import("../http-server/websocket-channel.js").WebsocketJsonValue} broadcastParams - Publisher scoping params (the published resourceType plus the change's scope-partition values).
|
|
111
|
+
* @returns {boolean} Whether the broadcast belongs to this subscription's scope.
|
|
112
|
+
*/
|
|
113
|
+
matches(broadcastParams) {
|
|
114
|
+
const scope = this._scope
|
|
115
|
+
|
|
116
|
+
if (!scope) return false
|
|
117
|
+
|
|
118
|
+
const scopingParams = broadcastParams && typeof broadcastParams === "object" && !Array.isArray(broadcastParams)
|
|
119
|
+
? /** @type {Record<string, ?>} */ (broadcastParams)
|
|
120
|
+
: {}
|
|
121
|
+
|
|
122
|
+
if (!Object.hasOwn(scopingParams, "resourceType") || String(scopingParams.resourceType) !== String(scope.resourceType)) return false
|
|
123
|
+
|
|
124
|
+
for (const [conditionName, conditionValue] of Object.entries(scope.conditions)) {
|
|
125
|
+
if (!Object.hasOwn(scopingParams, conditionName)) return false
|
|
126
|
+
|
|
127
|
+
const scopingValue = scopingParams[conditionName]
|
|
128
|
+
|
|
129
|
+
if (Array.isArray(conditionValue)) {
|
|
130
|
+
if (!conditionValue.some((value) => String(value) === String(scopingValue))) return false
|
|
131
|
+
} else if (String(conditionValue) !== String(scopingValue)) {
|
|
132
|
+
return false
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return true
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Returns the authorized scope for debug snapshots.
|
|
141
|
+
* @returns {Record<string, ?>} Debug-safe subscription details.
|
|
142
|
+
*/
|
|
143
|
+
debugSnapshot() {
|
|
144
|
+
return {scope: this._scope}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -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-change-fanout.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-publish-suppression.js","../src/sync/sync-publisher-types.js","../src/sync/sync-publisher.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"}
|
|
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-change-fanout.js","../src/sync/sync-channel-name.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-publish-suppression.js","../src/sync/sync-publisher-types.js","../src/sync/sync-publisher.js","../src/sync/sync-realtime-bridge.js","../src/sync/sync-replay-upsert-applier.js","../src/sync/sync-resource-base.js","../src/sync/sync-scope-attributes.js","../src/sync/sync-scope-store.js","../src/sync/sync-websocket-channel.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
package/src/application.js
CHANGED
|
@@ -6,6 +6,7 @@ import HttpServer from "./http-server/index.js"
|
|
|
6
6
|
import HttpServerLock from "./http-server/server-lock.js"
|
|
7
7
|
import SyncApiController from "./sync/sync-api-controller.js"
|
|
8
8
|
import SyncPublisher from "./sync/sync-publisher.js"
|
|
9
|
+
import SyncWebsocketChannel from "./sync/sync-websocket-channel.js"
|
|
9
10
|
import websocketEventsHost from "./http-server/websocket-events-host.js"
|
|
10
11
|
import restArgsError from "./utils/rest-args-error.js"
|
|
11
12
|
|
|
@@ -57,6 +58,7 @@ export default class VelociousApplication {
|
|
|
57
58
|
await this.configuration.initialize({type: this.getType()})
|
|
58
59
|
|
|
59
60
|
SyncApiController.mountFromConfiguration(this.configuration)
|
|
61
|
+
SyncWebsocketChannel.registerFromConfiguration(this.configuration)
|
|
60
62
|
await SyncPublisher.startFromConfiguration(this.configuration)
|
|
61
63
|
|
|
62
64
|
this.configuration.setRoutes(routes)
|
|
@@ -390,19 +390,19 @@
|
|
|
390
390
|
* One realtime channel subscription descriptor.
|
|
391
391
|
* @typedef {object} VelociousSyncRealtimeChannelDescriptor
|
|
392
392
|
* @property {string} channel - Server channel name to subscribe.
|
|
393
|
-
* @property {Record<string, ?>} [params] - Subscribe params (runtime values
|
|
393
|
+
* @property {Record<string, ?>} [params] - Subscribe params (runtime scope values). The framework injects `authenticationToken` automatically.
|
|
394
394
|
* @property {string} [resourceType] - Default resource/model name for pushed changes that do not carry their own resourceType.
|
|
395
395
|
*/
|
|
396
396
|
|
|
397
397
|
/**
|
|
398
|
-
* Realtime push configuration for the sync client. Only the genuinely
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
402
|
-
* pull-on-reconnect - is derived.
|
|
398
|
+
* Realtime push configuration for the sync client. Only the genuinely
|
|
399
|
+
* app-owned callback lives here: how to build the websocket client.
|
|
400
|
+
* Everything else - deriving the framework sync channel subscriptions from
|
|
401
|
+
* the declared pull scopes, subscribing, applying pushes through the derived
|
|
402
|
+
* resource applier, echo suppression, and pull-on-reconnect - is derived.
|
|
403
403
|
* @typedef {object} VelociousSyncClientRealtimeConfiguration
|
|
404
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] -
|
|
405
|
+
* @property {(context: ?) => Array<VelociousSyncRealtimeChannelDescriptor> | Promise<Array<VelociousSyncRealtimeChannelDescriptor>>} [channels] - Deprecated legacy escape hatch: resolves extra app-channel descriptors from the `subscribeRealtime(context)` context. Declared pull scopes subscribe the framework sync channel automatically.
|
|
406
406
|
* @property {() => string | Promise<string>} [localOrigin] - Resolves this device's echo origin; pushed messages with a matching `echoOrigin` are dropped.
|
|
407
407
|
* @property {boolean} [pullOnReconnect] - Fire a coalesced `pull()` when subscriptions become ready or resume after a drop, closing offline gaps. Defaults to true.
|
|
408
408
|
*/
|
|
@@ -541,7 +541,7 @@
|
|
|
541
541
|
*/
|
|
542
542
|
|
|
543
543
|
/**
|
|
544
|
-
* @typedef {function({configuration: import("./configuration.js").default, params: Record<string, ?>, request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default, response: import("./http-server/client/response.js").default}) : import("./authorization/ability.js").default | void | Promise<import("./authorization/ability.js").default | void>} AbilityResolverType
|
|
544
|
+
* @typedef {function({configuration: import("./configuration.js").default, params: Record<string, ?>, request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default | undefined, response: import("./http-server/client/response.js").default | undefined}) : import("./authorization/ability.js").default | void | Promise<import("./authorization/ability.js").default | void>} AbilityResolverType
|
|
545
545
|
*/
|
|
546
546
|
|
|
547
547
|
/**
|
package/src/configuration.js
CHANGED
|
@@ -2502,8 +2502,8 @@ export default class VelociousConfiguration {
|
|
|
2502
2502
|
* Runs resolve ability.
|
|
2503
2503
|
* @param {object} args - Ability resolver args.
|
|
2504
2504
|
* @param {Record<string, ?>} args.params - Request params.
|
|
2505
|
-
* @param {import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default} args.request - Request object.
|
|
2506
|
-
* @param {import("./http-server/client/response.js").default} args.response - Response object.
|
|
2505
|
+
* @param {import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default} [args.request] - Request object. Absent for websocket channel subscriptions resolved from subscribe params.
|
|
2506
|
+
* @param {import("./http-server/client/response.js").default} [args.response] - Response object. Absent outside HTTP request handling.
|
|
2507
2507
|
* @returns {Promise<import("./authorization/ability.js").default | undefined>} - Resolved ability.
|
|
2508
2508
|
*/
|
|
2509
2509
|
async resolveAbility({params, request, response}) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Canonical framework-owned websocket channel for synced resources. The server
|
|
5
|
+
* registers it automatically when `sync.api` is configured (subscribe
|
|
6
|
+
* authorization delegates to the app sync resource's `authorizeChanges`), the
|
|
7
|
+
* sync publisher broadcasts standard sync envelopes on it, and the derived
|
|
8
|
+
* sync client subscribes its declared pull scopes to it automatically.
|
|
9
|
+
*/
|
|
10
|
+
export const VELOCIOUS_SYNC_CHANNEL = "velocious-sync"
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Static realtime channel declaration on a model's `static sync`, for channels
|
|
12
|
-
* whose name and params are static.
|
|
13
|
-
*
|
|
12
|
+
* whose name and params are static.
|
|
13
|
+
* @deprecated Declared pull scopes subscribe the framework sync channel automatically; keep this only for legacy app channels.
|
|
14
14
|
* @typedef {object} ModelSyncRealtimeDeclaration
|
|
15
15
|
* @property {string} channel - Server channel name to subscribe.
|
|
16
16
|
* @property {Record<string, ?>} [params] - Static subscribe params. The framework injects `authenticationToken` automatically.
|
|
@@ -29,13 +29,14 @@
|
|
|
29
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".
|
|
30
30
|
* @property {(args: {operation: "create" | "update" | "destroy", record: ?}) => Record<string, ?>} [trackedData] - Custom queued-payload builder for tracked mutations.
|
|
31
31
|
* @property {boolean | {operations: Array<"create" | "update" | "destroy">}} [track] - Automatic mutation tracking policy. On by default (creates and updates queue automatically); `false` opts the resource out, `true` adds destroys, `{operations}` narrows the tracked operations.
|
|
32
|
-
* @property {ModelSyncRealtimeDeclaration} [realtime] -
|
|
32
|
+
* @property {ModelSyncRealtimeDeclaration} [realtime] - Deprecated: static legacy realtime channel this resource subscribes through `subscribeRealtime(...)`. Declared pull scopes subscribe the framework sync channel automatically.
|
|
33
33
|
*/
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* Model-level client sync declaration read from `static sync` by
|
|
37
37
|
* `SyncClient.fromConfiguration(...)`. `true` opts the model in with all
|
|
38
38
|
* defaults; an object customizes the derived resource config.
|
|
39
|
+
* @template [TModel=any]
|
|
39
40
|
* @typedef {object} ModelSyncDeclarationConfig
|
|
40
41
|
* @property {import("./sync-api-client-types.js").SyncResourceConfig["afterApply"]} [afterApply] - Post-apply hook.
|
|
41
42
|
* @property {import("./sync-api-client-types.js").SyncResourceConfig["attributes"]} [attributes] - Pull-apply attribute mapper. Required for resources that receive pulled changes.
|
|
@@ -43,14 +44,19 @@
|
|
|
43
44
|
* @property {import("./sync-api-client-types.js").SyncResourceConfig["findRecord"]} [findRecord] - Custom pull-apply record resolver.
|
|
44
45
|
* @property {import("./sync-api-client-types.js").SyncResourceConfig["findRecordForDelete"]} [findRecordForDelete] - Custom pull-apply delete resolver.
|
|
45
46
|
* @property {string[]} [localOnlyAttributes] - Extra local-only attributes merged with the derived primary key, createdAt/updatedAt, and sync bookkeeping attributes.
|
|
46
|
-
* @property {import("./sync-publisher-types.js").SyncPublishDeclaration} [publish] - Server-side publish declaration consumed by `SyncPublisher.fromConfiguration(...)` on the backend; ignored by the client.
|
|
47
|
+
* @property {import("./sync-publisher-types.js").SyncPublishDeclaration<TModel>} [publish] - Server-side publish declaration consumed by `SyncPublisher.fromConfiguration(...)` on the backend; ignored by the client.
|
|
47
48
|
* @property {"upsert" | ((args: {operation: "create" | "update" | "destroy", record: ?}) => string)} [syncType] - Sync type flag or mapper (see SyncClientResourceConfig).
|
|
48
49
|
* @property {boolean | Array<"create" | "update" | "destroy"> | {operations: Array<"create" | "update" | "destroy">}} [track] - Automatic mutation tracking policy; an array is shorthand for {operations}. On by default (creates and updates queue automatically); `false` opts the model out (for models written by non-user flows), `true` adds destroys.
|
|
49
50
|
* @property {(args: {operation: "create" | "update" | "destroy", record: ?}) => Record<string, ?>} [trackedData] - Custom queued-payload builder for tracked mutations.
|
|
50
|
-
* @property {ModelSyncRealtimeDeclaration} [realtime] -
|
|
51
|
+
* @property {ModelSyncRealtimeDeclaration} [realtime] - Deprecated: static legacy realtime channel this resource subscribes through `subscribeRealtime(...)`. Declared pull scopes subscribe the framework sync channel automatically.
|
|
51
52
|
*/
|
|
52
53
|
|
|
53
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* Model-level sync declaration value: `true` opts in with all defaults, an
|
|
56
|
+
* object customizes the derived resource config.
|
|
57
|
+
* @template [TModel=any]
|
|
58
|
+
* @typedef {boolean | ModelSyncDeclarationConfig<TModel>} ModelSyncDeclaration
|
|
59
|
+
*/
|
|
54
60
|
|
|
55
61
|
/**
|
|
56
62
|
* Options for building a sync client. Everything else — resources, transport
|
package/src/sync/sync-client.js
CHANGED
|
@@ -452,7 +452,7 @@ export default class SyncClient {
|
|
|
452
452
|
/**
|
|
453
453
|
* Subscribes the derived realtime channels so pushed websocket changes apply
|
|
454
454
|
* through the same derived applier as pulls (idempotent, single-flighted).
|
|
455
|
-
* @param {?} [context] - App context passed to the `sync.client.realtime.channels` callback (runtime values
|
|
455
|
+
* @param {?} [context] - App context passed to the deprecated `sync.client.realtime.channels` callback (runtime scope values).
|
|
456
456
|
* @returns {Promise<void>}
|
|
457
457
|
*/
|
|
458
458
|
async subscribeRealtime(context) {
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import VelociousError from "../velocious-error.js"
|
|
4
4
|
|
|
5
|
+
import {declaredSyncScopeAttributes} from "./sync-scope-attributes.js"
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* Generic cursor-paginated change feed over an app-owned sync/change model.
|
|
7
9
|
*
|
|
@@ -173,14 +175,20 @@ export default class SyncModelChangeFeedService {
|
|
|
173
175
|
}
|
|
174
176
|
|
|
175
177
|
/**
|
|
176
|
-
* Serializes a record using the standard sync envelope shape
|
|
178
|
+
* Serializes a record using the standard sync envelope shape plus the sync
|
|
179
|
+
* model's declared scope-partition attributes (`static syncScopeAttributes`),
|
|
180
|
+
* each emitted under its own attribute name. Models declaring no scope
|
|
181
|
+
* attributes keep the deprecated 1.0.503 wire and emit `eventId`. Keys are
|
|
182
|
+
* sorted so a declared `["eventId"]` partition stays byte-identical with the
|
|
183
|
+
* 1.0.503 wire.
|
|
177
184
|
* @param {?} record - Sync/change record.
|
|
178
185
|
* @returns {Record<string, unknown>} Default serialized row.
|
|
179
186
|
*/
|
|
180
187
|
defaultSerializeRecord(record) {
|
|
181
|
-
|
|
188
|
+
const scopeAttributes = declaredSyncScopeAttributes(this.modelClass)
|
|
189
|
+
/** @type {Record<string, unknown>} */
|
|
190
|
+
const serialized = {
|
|
182
191
|
data: this.recordData(record),
|
|
183
|
-
eventId: this.recordValue(record, "eventId"),
|
|
184
192
|
id: this.recordValue(record, "id"),
|
|
185
193
|
resourceId: this.recordValue(record, "resourceId"),
|
|
186
194
|
resourceType: this.recordValue(record, "resourceType"),
|
|
@@ -188,6 +196,12 @@ export default class SyncModelChangeFeedService {
|
|
|
188
196
|
syncType: this.recordValue(record, "syncType"),
|
|
189
197
|
updatedAt: this.isoDate(this.recordValue(record, "updatedAt"))
|
|
190
198
|
}
|
|
199
|
+
|
|
200
|
+
for (const scopeAttribute of scopeAttributes || ["eventId"]) {
|
|
201
|
+
serialized[scopeAttribute] = this.recordValue(record, scopeAttribute)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return Object.fromEntries(Object.entries(serialized).sort(([leftKey], [rightKey]) => leftKey.localeCompare(rightKey)))
|
|
191
205
|
}
|
|
192
206
|
|
|
193
207
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Args resolved against a publish declaration's broadcasts after a
|
|
5
|
-
* server-side mutation commits.
|
|
4
|
+
* Args resolved against a publish declaration's deprecated broadcasts after a
|
|
5
|
+
* published server-side mutation commits.
|
|
6
6
|
* @typedef {object} SyncPublishBroadcastArgs
|
|
7
7
|
* @property {Record<string, ?>} data - Payload snapshotted through the declaration's `serialize(record)` at mutation time.
|
|
8
8
|
* @property {"create" | "update" | "destroy"} operation - Mutation operation that published.
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
/**
|
|
17
17
|
* One declarative broadcast fanned out after a published server-side mutation
|
|
18
18
|
* commits — same shape the replay service's injected broadcaster consumes.
|
|
19
|
+
* @deprecated Publishing broadcasts the standard sync envelope on the framework sync channel automatically; declare app-channel broadcasts only for legacy channels old app versions still subscribe.
|
|
19
20
|
* @typedef {object} SyncPublishBroadcast
|
|
20
21
|
* @property {string | ((args: SyncPublishBroadcastArgs) => string)} channel - Channel name or resolver.
|
|
21
22
|
* @property {(args: SyncPublishBroadcastArgs) => Record<string, ?>} broadcastParams - Channel routing params.
|
|
@@ -27,38 +28,57 @@
|
|
|
27
28
|
* Server-side publish declaration on a model's `static sync`, consumed by
|
|
28
29
|
* `SyncPublisher.fromConfiguration(...)`. Publishing is on for models
|
|
29
30
|
* declaring it (server-side creates and updates write to the sync change
|
|
30
|
-
* feed and broadcast
|
|
31
|
-
*
|
|
31
|
+
* feed and broadcast the standard sync envelope on the framework sync
|
|
32
|
+
* channel automatically once their transaction commits); `publish: true`
|
|
33
|
+
* opts in with all defaults and `publish: false` opts a model out explicitly.
|
|
34
|
+
* @template [TModel=any]
|
|
32
35
|
* @typedef {object} SyncPublishDeclarationConfig
|
|
33
|
-
* @property {(record:
|
|
34
|
-
* @property {
|
|
35
|
-
* @property {
|
|
36
|
+
* @property {(record: TModel) => Record<string, ?> | Promise<Record<string, ?>>} [serialize] - Builds the published payload snapshot from the mutated record (snapshotted at mutation time). Defaults to the record's attributes with Date values serialized to ISO strings.
|
|
37
|
+
* @property {Record<string, string>} [scopeAttributes] - Record-attribute name overrides per scope attribute declared on the sync model's `static syncScopeAttributes`. By default each declared scope attribute reads the record's attribute of the same name when the model has one, else the record's own id (scope-root models).
|
|
38
|
+
* @property {string | ((record: TModel) => string | number | null | Promise<string | number | null>)} [eventId] - Deprecated 1.0.503 form: attribute-name string (or resolver function) persisted to a fixed event_id sync-row column and broadcast as a fixed `eventId` scoping param. Declare `static syncScopeAttributes` on the sync model plus `scopeAttributes` overrides instead.
|
|
39
|
+
* @property {SyncPublishBroadcast[]} [broadcasts] - Deprecated: declarative app-channel broadcasts fanned out after the framework sync channel broadcast. The framework broadcast happens automatically; keep this only for legacy channels old app versions still subscribe.
|
|
36
40
|
* @property {Array<"create" | "update" | "destroy">} [operations] - Published operations. Defaults to creates and updates; destroys are opt-in because a server destroy is often cleanup rather than a synced delete.
|
|
37
41
|
* @property {string} [resourceType] - Published resource type. Defaults to the model name.
|
|
38
42
|
*/
|
|
39
43
|
|
|
40
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* Model-level publish declaration value: `true` publishes with all defaults,
|
|
46
|
+
* `false` opts out explicitly, an object customizes the published payload and scoping.
|
|
47
|
+
* @template [TModel=any]
|
|
48
|
+
* @typedef {boolean | SyncPublishDeclarationConfig<TModel>} SyncPublishDeclaration
|
|
49
|
+
*/
|
|
41
50
|
|
|
42
51
|
/**
|
|
43
52
|
* Options for building a sync publisher. Published resources are derived from
|
|
44
53
|
* the configuration's registered models (`static sync` publish declarations).
|
|
45
54
|
* @typedef {object} SyncPublisherOptions
|
|
46
55
|
* @property {string} [actorForeignKeyColumn] - Sync model column linking rows to a device actor. Published server-origin rows set it to null (no device to echo). Defaults to "authentication_token_id".
|
|
47
|
-
* @property {(broadcast: {channel: string, params: Record<string, ?>, body: ?}) => Promise<void>} [broadcaster] - Delivers declared broadcasts. Defaults to the configuration's channel broadcast.
|
|
56
|
+
* @property {(broadcast: {channel: string, params: Record<string, ?>, body: ?}) => Promise<void>} [broadcaster] - Delivers the framework sync channel broadcast and any deprecated declared broadcasts. Defaults to the configuration's channel broadcast.
|
|
48
57
|
* @property {import("../configuration.js").default} [configuration] - Configuration owning the registered models. Defaults to the current configuration.
|
|
49
58
|
* @property {(error: Error) => void} [onError] - Reports post-commit publish failures. Defaults to loud logging.
|
|
50
59
|
* @property {?} [syncModel] - Sync/change model override. Defaults to the registered "Sync" model.
|
|
51
60
|
*/
|
|
52
61
|
|
|
62
|
+
/**
|
|
63
|
+
* One derived scope-partition source for a published resource — not an
|
|
64
|
+
* app-facing API. The value is persisted to the sync row's `columnName` and
|
|
65
|
+
* broadcast under `scopeAttribute` on the framework sync channel.
|
|
66
|
+
* @typedef {object} SyncPublisherScopePlanEntry
|
|
67
|
+
* @property {string} columnName - Sync-row column persisting the scope value.
|
|
68
|
+
* @property {string | null} recordAttribute - Record attribute read for the scope value, or null when the record's own id is the scope (scope-root models).
|
|
69
|
+
* @property {((record: ?) => string | number | null | Promise<string | number | null>) | undefined} resolver - Deprecated eventId resolver function.
|
|
70
|
+
* @property {string} scopeAttribute - Scope attribute name broadcast as the framework channel scoping param.
|
|
71
|
+
*/
|
|
72
|
+
|
|
53
73
|
/**
|
|
54
74
|
* Internal derived publish policy for one resource — not an app-facing API.
|
|
55
75
|
* @typedef {object} SyncPublisherResourceConfig
|
|
56
|
-
* @property {SyncPublishBroadcast[] | undefined} broadcasts -
|
|
57
|
-
* @property {SyncPublishDeclarationConfig["eventId"] | undefined} eventId - Event scope resolver.
|
|
76
|
+
* @property {SyncPublishBroadcast[] | undefined} broadcasts - Deprecated declared app-channel broadcasts.
|
|
58
77
|
* @property {?} modelClass - Server model class for this resource.
|
|
59
78
|
* @property {Array<"create" | "update" | "destroy">} operations - Published operations.
|
|
79
|
+
* @property {Array<SyncPublisherScopePlanEntry>} scopePlan - Derived scope-partition plan.
|
|
80
|
+
* @property {(record: ?) => Record<string, ?> | Promise<Record<string, ?>>} serialize - Payload snapshot builder (the declaration's serialize or the default attribute serializer).
|
|
60
81
|
* @property {string} resourceType - Published resource type.
|
|
61
|
-
* @property {SyncPublishDeclarationConfig["serialize"]} serialize - Payload snapshot builder.
|
|
62
82
|
*/
|
|
63
83
|
|
|
64
84
|
export {}
|