velocious 1.0.489 → 1.0.492
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 +3 -0
- package/build/cli/commands/db/tenants/create.js +7 -5
- package/build/cli/commands/db/tenants/drop.js +6 -6
- package/build/configuration-types.js +8 -0
- package/build/configuration.js +29 -0
- package/build/database/query/index.js +30 -0
- package/build/database/query/model-class-query.js +17 -0
- package/build/database/record/index.js +16 -0
- package/build/src/application.d.ts.map +1 -1
- package/build/src/application.js +3 -1
- package/build/src/cli/commands/db/tenants/create.d.ts.map +1 -1
- package/build/src/cli/commands/db/tenants/create.js +8 -5
- package/build/src/cli/commands/db/tenants/drop.d.ts +1 -1
- package/build/src/cli/commands/db/tenants/drop.d.ts.map +1 -1
- package/build/src/cli/commands/db/tenants/drop.js +7 -6
- package/build/src/configuration-types.d.ts +24 -0
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +8 -1
- package/build/src/configuration.d.ts +6 -0
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +26 -1
- package/build/src/database/query/index.d.ts +25 -0
- package/build/src/database/query/index.d.ts.map +1 -1
- package/build/src/database/query/index.js +26 -1
- package/build/src/database/query/model-class-query.d.ts +10 -0
- package/build/src/database/query/model-class-query.d.ts.map +1 -1
- package/build/src/database/query/model-class-query.js +16 -1
- package/build/src/database/record/index.d.ts +7 -0
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +15 -1
- package/build/src/sync/query-scope.d.ts +18 -0
- package/build/src/sync/query-scope.d.ts.map +1 -0
- package/build/src/sync/query-scope.js +77 -0
- package/build/src/sync/server-change-feed.d.ts.map +1 -1
- package/build/src/sync/server-change-feed.js +2 -24
- package/build/src/sync/stable-json.d.ts +9 -0
- package/build/src/sync/stable-json.d.ts.map +1 -0
- package/build/src/sync/stable-json.js +27 -0
- package/build/src/sync/sync-api-client.d.ts +185 -5
- package/build/src/sync/sync-api-client.d.ts.map +1 -1
- package/build/src/sync/sync-api-client.js +309 -17
- package/build/src/sync/sync-api-controller.d.ts +8 -0
- package/build/src/sync/sync-api-controller.d.ts.map +1 -1
- package/build/src/sync/sync-api-controller.js +17 -1
- package/build/src/sync/sync-client-registry.d.ts +12 -0
- package/build/src/sync/sync-client-registry.d.ts.map +1 -0
- package/build/src/sync/sync-client-registry.js +27 -0
- package/build/src/sync/sync-client-types.d.ts +127 -0
- package/build/src/sync/sync-client-types.d.ts.map +1 -0
- package/build/src/sync/sync-client-types.js +3 -0
- package/build/src/sync/sync-client.d.ts +176 -0
- package/build/src/sync/sync-client.d.ts.map +1 -0
- package/build/src/sync/sync-client.js +380 -0
- package/build/src/sync/sync-envelope-replay-service.d.ts +38 -4
- package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
- package/build/src/sync/sync-envelope-replay-service.js +73 -6
- package/build/src/sync/sync-resource-base.d.ts +98 -0
- package/build/src/sync/sync-resource-base.d.ts.map +1 -0
- package/build/src/sync/sync-resource-base.js +122 -0
- package/build/src/sync/sync-scope-store.d.ts +128 -0
- package/build/src/sync/sync-scope-store.d.ts.map +1 -0
- package/build/src/sync/sync-scope-store.js +282 -0
- package/build/src/tenants/default-tenant-database-provisioning.d.ts +21 -0
- package/build/src/tenants/default-tenant-database-provisioning.d.ts.map +1 -0
- package/build/src/tenants/default-tenant-database-provisioning.js +106 -0
- package/build/src/tenants/tenant.d.ts.map +1 -1
- package/build/src/tenants/tenant.js +6 -5
- package/build/sync/query-scope.js +84 -0
- package/build/sync/server-change-feed.js +1 -25
- package/build/sync/stable-json.js +28 -0
- package/build/sync/sync-api-client.js +331 -17
- package/build/sync/sync-api-controller.js +20 -0
- package/build/sync/sync-client-registry.js +30 -0
- package/build/sync/sync-client-types.js +41 -0
- package/build/sync/sync-client.js +433 -0
- package/build/sync/sync-envelope-replay-service.js +77 -5
- package/build/sync/sync-resource-base.js +143 -0
- package/build/sync/sync-scope-store.js +327 -0
- package/build/tenants/default-tenant-database-provisioning.js +124 -0
- package/build/tenants/tenant.js +5 -5
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/application.js +3 -0
- package/src/cli/commands/db/tenants/create.js +7 -5
- package/src/cli/commands/db/tenants/drop.js +6 -6
- package/src/configuration-types.js +8 -0
- package/src/configuration.js +29 -0
- package/src/database/query/index.js +30 -0
- package/src/database/query/model-class-query.js +17 -0
- package/src/database/record/index.js +16 -0
- package/src/sync/query-scope.js +84 -0
- package/src/sync/server-change-feed.js +1 -25
- package/src/sync/stable-json.js +28 -0
- package/src/sync/sync-api-client.js +331 -17
- package/src/sync/sync-api-controller.js +20 -0
- package/src/sync/sync-client-registry.js +30 -0
- package/src/sync/sync-client-types.js +41 -0
- package/src/sync/sync-client.js +433 -0
- package/src/sync/sync-envelope-replay-service.js +77 -5
- package/src/sync/sync-resource-base.js +143 -0
- package/src/sync/sync-scope-store.js +327 -0
- package/src/tenants/default-tenant-database-provisioning.js +124 -0
- package/src/tenants/tenant.js +5 -5
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import TableData from "../database/table-data/index.js"
|
|
4
|
+
import UUID from "pure-uuid"
|
|
5
|
+
|
|
6
|
+
import {scopeKey} from "./query-scope.js"
|
|
7
|
+
import stableJsonStringify from "./stable-json.js"
|
|
8
|
+
|
|
9
|
+
const TABLE_NAME = "velocious_sync_scopes"
|
|
10
|
+
const SCOPE_DIGEST_PREFIX = "velocious-sync-scope:"
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Digests a serialized scope into a fixed-size deterministic key, so scope
|
|
14
|
+
* identities with long condition values fit an indexed string column.
|
|
15
|
+
* @param {import("./sync-client-types.js").SerializedSyncScope} scope - Serialized sync scope.
|
|
16
|
+
* @returns {string} Deterministic UUIDv5 digest of the canonical scope key.
|
|
17
|
+
*/
|
|
18
|
+
function scopeDigestForScope(scope) {
|
|
19
|
+
return new UUID(5, "ns:URL", `${SCOPE_DIGEST_PREFIX}${scopeKey(scope)}`).format()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {object} SyncScopeRow
|
|
24
|
+
* @property {Record<string, ?>} conditions - Scope attribute conditions.
|
|
25
|
+
* @property {string | null} cursorPayload - Persisted cursor JSON payload.
|
|
26
|
+
* @property {string} id - Scope row id.
|
|
27
|
+
* @property {string} resourceType - Scope resource/model name.
|
|
28
|
+
* @property {string} scopeDigest - Fixed-size deterministic digest of the canonical scope key.
|
|
29
|
+
* @property {string} state - Scope state ("active" or "removed").
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Framework-owned local persistence for declared sync scopes and their cursors.
|
|
34
|
+
*
|
|
35
|
+
* Backed by an auto-created `velocious_sync_scopes` table on the configured
|
|
36
|
+
* database, with a process-local memory fallback when no database is
|
|
37
|
+
* configured (mirroring the server change-feed store).
|
|
38
|
+
*/
|
|
39
|
+
export default class SyncScopeStore {
|
|
40
|
+
/**
|
|
41
|
+
* Creates a sync scope store.
|
|
42
|
+
* @param {object} args - Options.
|
|
43
|
+
* @param {import("../configuration.js").default} args.configuration - Configuration owning the database.
|
|
44
|
+
* @param {string} [args.databaseIdentifier] - Database identifier.
|
|
45
|
+
*/
|
|
46
|
+
constructor({configuration, databaseIdentifier = "default"}) {
|
|
47
|
+
this.configuration = configuration
|
|
48
|
+
this.databaseIdentifier = databaseIdentifier
|
|
49
|
+
/** @type {Map<string, SyncScopeRow>} */
|
|
50
|
+
this._memoryScopes = new Map()
|
|
51
|
+
this._isReady = false
|
|
52
|
+
/** @type {Promise<void> | null} */
|
|
53
|
+
this._readyPromise = null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Ensures the backing table exists.
|
|
58
|
+
* @returns {Promise<void>} Resolves when ready.
|
|
59
|
+
*/
|
|
60
|
+
async ensureReady() {
|
|
61
|
+
if (this._isReady) return
|
|
62
|
+
|
|
63
|
+
if (this._usesMemoryStorage()) {
|
|
64
|
+
this._isReady = true
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (this._readyPromise) return await this._readyPromise
|
|
69
|
+
|
|
70
|
+
this._readyPromise = this._withDb(async (db) => {
|
|
71
|
+
await this._ensureScopesTable(db)
|
|
72
|
+
this._isReady = true
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
await this._readyPromise
|
|
77
|
+
} finally {
|
|
78
|
+
if (!this._isReady) this._readyPromise = null
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Finds or creates the scope row for a serialized scope, reactivating removed scopes.
|
|
84
|
+
* @param {import("./sync-client-types.js").SerializedSyncScope} scope - Serialized sync scope.
|
|
85
|
+
* @returns {Promise<SyncScopeRow>} Persisted scope row.
|
|
86
|
+
*/
|
|
87
|
+
async findOrCreateScope(scope) {
|
|
88
|
+
await this.ensureReady()
|
|
89
|
+
|
|
90
|
+
const digest = scopeDigestForScope(scope)
|
|
91
|
+
|
|
92
|
+
if (this._usesMemoryStorage()) {
|
|
93
|
+
const existingScope = this._memoryScopes.get(digest)
|
|
94
|
+
|
|
95
|
+
if (existingScope) {
|
|
96
|
+
if (existingScope.state !== "active") existingScope.state = "active"
|
|
97
|
+
|
|
98
|
+
return existingScope
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const newScope = {
|
|
102
|
+
conditions: scope.conditions,
|
|
103
|
+
cursorPayload: null,
|
|
104
|
+
id: new UUID(4).format(),
|
|
105
|
+
resourceType: scope.resourceType,
|
|
106
|
+
scopeDigest: digest,
|
|
107
|
+
state: "active"
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
this._memoryScopes.set(digest, newScope)
|
|
111
|
+
|
|
112
|
+
return newScope
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return await this._withDb(async (db) => {
|
|
116
|
+
const existingRow = await this._rowByScopeDigest(db, digest)
|
|
117
|
+
|
|
118
|
+
if (existingRow) {
|
|
119
|
+
if (existingRow.state !== "active") {
|
|
120
|
+
await db.update({conditions: {id: existingRow.id}, data: {state: "active", updated_at: new Date()}, tableName: TABLE_NAME})
|
|
121
|
+
existingRow.state = "active"
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return existingRow
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
await db.insert({
|
|
128
|
+
tableName: TABLE_NAME,
|
|
129
|
+
data: {
|
|
130
|
+
conditions_json: stableJsonStringify(scope.conditions),
|
|
131
|
+
created_at: new Date(),
|
|
132
|
+
cursor_json: null,
|
|
133
|
+
id: new UUID(4).format(),
|
|
134
|
+
resource_type: scope.resourceType,
|
|
135
|
+
scope_digest: digest,
|
|
136
|
+
state: "active",
|
|
137
|
+
updated_at: new Date()
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
const createdRow = await this._rowByScopeDigest(db, digest)
|
|
142
|
+
|
|
143
|
+
if (!createdRow) throw new Error("Failed to persist sync scope")
|
|
144
|
+
|
|
145
|
+
return createdRow
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Returns all active scope rows.
|
|
151
|
+
* @returns {Promise<SyncScopeRow[]>} Active scope rows.
|
|
152
|
+
*/
|
|
153
|
+
async activeScopes() {
|
|
154
|
+
await this.ensureReady()
|
|
155
|
+
|
|
156
|
+
if (this._usesMemoryStorage()) {
|
|
157
|
+
return [...this._memoryScopes.values()].filter((scope) => scope.state === "active")
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return await this._withDb(async (db) => {
|
|
161
|
+
const rows = /** @type {Array<Record<string, ?>>} */ (await db
|
|
162
|
+
.newQuery()
|
|
163
|
+
.from(TABLE_NAME)
|
|
164
|
+
.where({state: "active"})
|
|
165
|
+
.order("created_at ASC")
|
|
166
|
+
.results())
|
|
167
|
+
|
|
168
|
+
return rows.map((row) => this._normalizeScopeRow(row))
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Loads the persisted cursor payload for a scope row.
|
|
174
|
+
* @param {SyncScopeRow} scopeRow - Scope row.
|
|
175
|
+
* @returns {Promise<string | null>} Cursor JSON payload.
|
|
176
|
+
*/
|
|
177
|
+
async loadCursor(scopeRow) {
|
|
178
|
+
await this.ensureReady()
|
|
179
|
+
|
|
180
|
+
if (this._usesMemoryStorage()) {
|
|
181
|
+
return this._memoryScopes.get(scopeRow.scopeDigest)?.cursorPayload ?? null
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return await this._withDb(async (db) => {
|
|
185
|
+
const row = await this._rowByScopeDigest(db, scopeRow.scopeDigest)
|
|
186
|
+
|
|
187
|
+
return row ? row.cursorPayload : null
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Persists the acknowledged cursor for a scope row.
|
|
193
|
+
* @param {SyncScopeRow} scopeRow - Scope row.
|
|
194
|
+
* @param {import("./sync-api-client-types.js").SyncCursor} cursor - Acknowledged cursor.
|
|
195
|
+
* @returns {Promise<void>}
|
|
196
|
+
*/
|
|
197
|
+
async saveCursor(scopeRow, cursor) {
|
|
198
|
+
if (!cursor) return
|
|
199
|
+
|
|
200
|
+
await this.ensureReady()
|
|
201
|
+
|
|
202
|
+
const cursorPayload = JSON.stringify(cursor)
|
|
203
|
+
|
|
204
|
+
if (this._usesMemoryStorage()) {
|
|
205
|
+
const memoryScope = this._memoryScopes.get(scopeRow.scopeDigest)
|
|
206
|
+
|
|
207
|
+
if (!memoryScope) throw new Error(`No sync scope found for: ${scopeRow.scopeDigest}`)
|
|
208
|
+
|
|
209
|
+
memoryScope.cursorPayload = cursorPayload
|
|
210
|
+
return
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
await this._withDb(async (db) => {
|
|
214
|
+
await db.update({
|
|
215
|
+
conditions: {scope_digest: scopeRow.scopeDigest},
|
|
216
|
+
data: {cursor_json: cursorPayload, updated_at: new Date()},
|
|
217
|
+
tableName: TABLE_NAME
|
|
218
|
+
})
|
|
219
|
+
})
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Deactivates the scope row for a serialized scope.
|
|
224
|
+
* @param {import("./sync-client-types.js").SerializedSyncScope} scope - Serialized sync scope.
|
|
225
|
+
* @returns {Promise<void>}
|
|
226
|
+
*/
|
|
227
|
+
async deactivate(scope) {
|
|
228
|
+
await this.ensureReady()
|
|
229
|
+
|
|
230
|
+
const digest = scopeDigestForScope(scope)
|
|
231
|
+
|
|
232
|
+
if (this._usesMemoryStorage()) {
|
|
233
|
+
const memoryScope = this._memoryScopes.get(digest)
|
|
234
|
+
|
|
235
|
+
if (memoryScope) memoryScope.state = "removed"
|
|
236
|
+
|
|
237
|
+
return
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
await this._withDb(async (db) => {
|
|
241
|
+
await db.update({conditions: {scope_digest: digest}, data: {state: "removed", updated_at: new Date()}, tableName: TABLE_NAME})
|
|
242
|
+
})
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Whether the store runs without a configured database.
|
|
247
|
+
* @returns {boolean} Whether memory storage is used.
|
|
248
|
+
*/
|
|
249
|
+
_usesMemoryStorage() {
|
|
250
|
+
try {
|
|
251
|
+
return !this.configuration.getDatabaseConfiguration()[this.databaseIdentifier]
|
|
252
|
+
} catch {
|
|
253
|
+
return true
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Runs a callback with a database connection.
|
|
259
|
+
* @template Result
|
|
260
|
+
* @param {(db: import("../database/drivers/base.js").default) => Promise<Result>} callback - Database callback.
|
|
261
|
+
* @returns {Promise<Result>} Callback result.
|
|
262
|
+
*/
|
|
263
|
+
async _withDb(callback) {
|
|
264
|
+
return await this.configuration.ensureConnections({name: "Sync scope store"}, async (dbs) => {
|
|
265
|
+
const db = dbs[this.databaseIdentifier]
|
|
266
|
+
|
|
267
|
+
if (!db) throw new Error(`No database connection available for identifier: ${this.databaseIdentifier}`)
|
|
268
|
+
|
|
269
|
+
return await callback(db)
|
|
270
|
+
})
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Ensures the scopes table exists.
|
|
275
|
+
* @param {import("../database/drivers/base.js").default} db - Database connection.
|
|
276
|
+
* @returns {Promise<void>}
|
|
277
|
+
*/
|
|
278
|
+
async _ensureScopesTable(db) {
|
|
279
|
+
if (await db.tableExists(TABLE_NAME)) return
|
|
280
|
+
|
|
281
|
+
const table = new TableData(TABLE_NAME, {ifNotExists: true})
|
|
282
|
+
|
|
283
|
+
table.string("id", {null: false, primaryKey: true})
|
|
284
|
+
table.string("scope_digest", {index: true, null: false})
|
|
285
|
+
table.string("resource_type", {index: true, null: false})
|
|
286
|
+
table.text("conditions_json", {null: false})
|
|
287
|
+
table.text("cursor_json", {null: true})
|
|
288
|
+
table.string("state", {index: true, null: false})
|
|
289
|
+
table.datetime("created_at", {null: false})
|
|
290
|
+
table.datetime("updated_at", {null: false})
|
|
291
|
+
|
|
292
|
+
await db.createTable(table)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Resolves a scope row by its digest.
|
|
297
|
+
* @param {import("../database/drivers/base.js").default} db - Database connection.
|
|
298
|
+
* @param {string} digest - Fixed-size scope digest.
|
|
299
|
+
* @returns {Promise<SyncScopeRow | null>} Scope row or null.
|
|
300
|
+
*/
|
|
301
|
+
async _rowByScopeDigest(db, digest) {
|
|
302
|
+
const rows = /** @type {Array<Record<string, ?>>} */ (await db
|
|
303
|
+
.newQuery()
|
|
304
|
+
.from(TABLE_NAME)
|
|
305
|
+
.where({scope_digest: digest})
|
|
306
|
+
.limit(1)
|
|
307
|
+
.results())
|
|
308
|
+
|
|
309
|
+
return rows[0] ? this._normalizeScopeRow(rows[0]) : null
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Normalizes a raw scope table row.
|
|
314
|
+
* @param {Record<string, ?>} row - Raw table row.
|
|
315
|
+
* @returns {SyncScopeRow} Normalized scope row.
|
|
316
|
+
*/
|
|
317
|
+
_normalizeScopeRow(row) {
|
|
318
|
+
return {
|
|
319
|
+
conditions: /** @type {Record<string, ?>} */ (JSON.parse(String(row.conditions_json))),
|
|
320
|
+
cursorPayload: row.cursor_json === null || row.cursor_json === undefined ? null : String(row.cursor_json),
|
|
321
|
+
id: String(row.id),
|
|
322
|
+
resourceType: String(row.resource_type),
|
|
323
|
+
scopeDigest: String(row.scope_digest),
|
|
324
|
+
state: String(row.state)
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default tenant-database provisioning used by `db:tenants:create`,
|
|
5
|
+
* `db:tenants:drop`, and `Tenant.drop` when a tenant-database provider does not
|
|
6
|
+
* define its own `createDatabase`/`dropDatabase`. This is the generic,
|
|
7
|
+
* driver-agnostic lifecycle every app on the tenant framework needs, so it lives
|
|
8
|
+
* in the framework instead of being reimplemented in each consuming project.
|
|
9
|
+
*
|
|
10
|
+
* File-backed drivers (sqlite) have no server-side CREATE/DROP DATABASE — the file
|
|
11
|
+
* is created on connect and left in place on drop — so creating just ensures the
|
|
12
|
+
* tenant's connection and dropping is a no-op. Server drivers (mysql, pgsql, …)
|
|
13
|
+
* connect to the configured maintenance database (`useDatabase`) and run the
|
|
14
|
+
* driver's own `createDatabaseSql`/`dropDatabaseSql`.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const SAFE_TENANT_DATABASE_NAME = /^[a-z0-9_]+$/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Whether the driver stores each database as a local file instead of on a server.
|
|
21
|
+
* @param {import("../configuration-types.js").DatabaseConfigurationType} databaseConfiguration - Resolved tenant database configuration.
|
|
22
|
+
* @returns {boolean} - True for file-backed drivers such as sqlite.
|
|
23
|
+
*/
|
|
24
|
+
function fileBackedDriver(databaseConfiguration) {
|
|
25
|
+
return databaseConfiguration.type === "sqlite"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Validates the tenant database name against a strict allowlist before it is
|
|
30
|
+
* interpolated into DDL.
|
|
31
|
+
* @param {import("../configuration-types.js").DatabaseConfigurationType} databaseConfiguration - Resolved tenant database configuration.
|
|
32
|
+
* @returns {string} - The validated tenant database name.
|
|
33
|
+
*/
|
|
34
|
+
function guardedDatabaseName(databaseConfiguration) {
|
|
35
|
+
const databaseName = databaseConfiguration.database
|
|
36
|
+
|
|
37
|
+
if (!databaseName || !SAFE_TENANT_DATABASE_NAME.test(databaseName)) {
|
|
38
|
+
throw new Error(`Unsafe tenant database name: ${databaseName}`)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return databaseName
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Opens a driver connected to the server's maintenance database (`useDatabase`),
|
|
46
|
+
* from which `CREATE DATABASE` / `DROP DATABASE` for the tenant can be issued.
|
|
47
|
+
* @param {import("../configuration-types.js").DatabaseConfigurationType} databaseConfiguration - Resolved tenant database configuration.
|
|
48
|
+
* @param {import("../configuration.js").default} configuration - The Velocious configuration.
|
|
49
|
+
* @returns {import("../database/drivers/base.js").default} - A driver bound to the maintenance database.
|
|
50
|
+
*/
|
|
51
|
+
function maintenanceConnection(databaseConfiguration, configuration) {
|
|
52
|
+
const DriverClass = databaseConfiguration.driver
|
|
53
|
+
|
|
54
|
+
if (!DriverClass) {
|
|
55
|
+
throw new Error("Tenant database configuration is missing a driver.")
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!databaseConfiguration.useDatabase) {
|
|
59
|
+
throw new Error("Tenant database configuration is missing a maintenance database in useDatabase.")
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return new DriverClass({...databaseConfiguration, database: databaseConfiguration.useDatabase}, configuration)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Creates the tenant database for one tenant.
|
|
67
|
+
* @param {{configuration: import("../configuration.js").default, databaseConfiguration: import("../configuration-types.js").DatabaseConfigurationType, tenant: ?}} args - Provisioning arguments.
|
|
68
|
+
* @returns {Promise<void>} - Resolves once the tenant database exists.
|
|
69
|
+
*/
|
|
70
|
+
export async function createTenantDatabase({configuration, databaseConfiguration, tenant}) {
|
|
71
|
+
if (fileBackedDriver(databaseConfiguration)) {
|
|
72
|
+
await configuration.runWithTenant(tenant, async () => {
|
|
73
|
+
await configuration.ensureConnections(async () => {})
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const databaseName = guardedDatabaseName(databaseConfiguration)
|
|
80
|
+
const connection = maintenanceConnection(databaseConfiguration, configuration)
|
|
81
|
+
|
|
82
|
+
await connection.connect()
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
const sqls = connection.createDatabaseSql(databaseName, {
|
|
86
|
+
databaseCharset: databaseConfiguration.databaseCharset,
|
|
87
|
+
databaseCollation: databaseConfiguration.databaseCollation,
|
|
88
|
+
ifNotExists: true
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
for (const sql of sqls) {
|
|
92
|
+
await connection.query(sql)
|
|
93
|
+
}
|
|
94
|
+
} finally {
|
|
95
|
+
await connection.close()
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Drops the tenant database for one tenant. Uses `DROP DATABASE IF EXISTS`, so it
|
|
101
|
+
* is a safe no-op for a tenant that was never fully provisioned.
|
|
102
|
+
* @param {{configuration: import("../configuration.js").default, databaseConfiguration: import("../configuration-types.js").DatabaseConfigurationType}} args - Provisioning arguments.
|
|
103
|
+
* @returns {Promise<void>} - Resolves once the tenant database is gone.
|
|
104
|
+
*/
|
|
105
|
+
export async function dropTenantDatabase({configuration, databaseConfiguration}) {
|
|
106
|
+
if (fileBackedDriver(databaseConfiguration)) {
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const databaseName = guardedDatabaseName(databaseConfiguration)
|
|
111
|
+
const connection = maintenanceConnection(databaseConfiguration, configuration)
|
|
112
|
+
|
|
113
|
+
await connection.connect()
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
const sqls = connection.dropDatabaseSql(databaseName, {ifExists: true})
|
|
117
|
+
|
|
118
|
+
for (const sql of sqls) {
|
|
119
|
+
await connection.query(sql)
|
|
120
|
+
}
|
|
121
|
+
} finally {
|
|
122
|
+
await connection.close()
|
|
123
|
+
}
|
|
124
|
+
}
|
package/build/tenants/tenant.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
import Current from "../current.js"
|
|
4
|
+
import {dropTenantDatabase} from "./default-tenant-database-provisioning.js"
|
|
4
5
|
import TenantIterator from "./tenant-iterator.js"
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -80,10 +81,9 @@ export default class Tenant {
|
|
|
80
81
|
*/
|
|
81
82
|
static async drop({identifier, tenant, configuration = Current.configuration()}) {
|
|
82
83
|
const provider = configuration.getTenantDatabaseProvider(identifier)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
84
|
+
const dropDatabase = typeof provider.dropDatabase === "function"
|
|
85
|
+
? provider.dropDatabase.bind(provider)
|
|
86
|
+
: dropTenantDatabase
|
|
87
87
|
|
|
88
88
|
await configuration.runWithTenant(tenant, async () => {
|
|
89
89
|
// Guard against an unresolved tenant. resolveDatabaseConfiguration falls back to the
|
|
@@ -94,7 +94,7 @@ export default class Tenant {
|
|
|
94
94
|
throw new Error(`Tenant database identifier ${identifier} is inactive for tenant: ${TenantIterator.tenantLabel(tenant)}`)
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
await
|
|
97
|
+
await dropDatabase({
|
|
98
98
|
configuration,
|
|
99
99
|
databaseConfiguration: configuration.resolveDatabaseConfiguration(identifier),
|
|
100
100
|
identifier,
|
|
@@ -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/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/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/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/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/server-change-feed.js","../src/sync/sync-api-client-types.js","../src/sync/sync-api-client.js","../src/sync/sync-api-controller.js","../src/sync/sync-envelope-replay-service.js","../src/sync/sync-model-change-feed-service.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/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/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/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/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/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-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
package/src/application.js
CHANGED
|
@@ -4,6 +4,7 @@ import AppRoutes from "./routes/app-routes.js"
|
|
|
4
4
|
import Logger from "./logger.js"
|
|
5
5
|
import HttpServer from "./http-server/index.js"
|
|
6
6
|
import HttpServerLock from "./http-server/server-lock.js"
|
|
7
|
+
import SyncApiController from "./sync/sync-api-controller.js"
|
|
7
8
|
import websocketEventsHost from "./http-server/websocket-events-host.js"
|
|
8
9
|
import restArgsError from "./utils/rest-args-error.js"
|
|
9
10
|
|
|
@@ -54,6 +55,8 @@ export default class VelociousApplication {
|
|
|
54
55
|
|
|
55
56
|
await this.configuration.initialize({type: this.getType()})
|
|
56
57
|
|
|
58
|
+
SyncApiController.mountFromConfiguration(this.configuration)
|
|
59
|
+
|
|
57
60
|
this.configuration.setRoutes(routes)
|
|
58
61
|
|
|
59
62
|
if (!this.configuration.isDatabasePoolInitialized()) {
|