velocious 1.0.489 → 1.0.493
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 +153 -10
- package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
- package/build/src/sync/sync-envelope-replay-service.js +174 -14
- package/build/src/sync/sync-replay-upsert-applier.d.ts +102 -0
- package/build/src/sync/sync-replay-upsert-applier.d.ts.map +1 -0
- package/build/src/sync/sync-replay-upsert-applier.js +158 -0
- 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 +190 -13
- package/build/sync/sync-replay-upsert-applier.js +179 -0
- 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 +190 -13
- package/src/sync/sync-replay-upsert-applier.js +179 -0
- 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,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-replay-upsert-applier.js","../src/sync/sync-resource-base.js","../src/sync/sync-scope-store.js","../src/tenants/default-tenant-database-provisioning.js","../src/tenants/tenant-iterator.js","../src/tenants/tenant.js","../src/testing/base-expect.js","../src/testing/browser-frontend-model-event-hook-scenarios.js","../src/testing/browser-test-app.js","../src/testing/expect-to-change.js","../src/testing/expect-utils.js","../src/testing/expect.js","../src/testing/request-client.js","../src/testing/test-files-finder.js","../src/testing/test-filter-parser.js","../src/testing/test-runner.js","../src/testing/test-suite-splitter.js","../src/testing/test.js","../src/types/external-modules.d.ts","../src/utils/backtrace-cleaner-node.js","../src/utils/backtrace-cleaner.js","../src/utils/deburr-column-name.js","../src/utils/event-emitter.js","../src/utils/file-exists.js","../src/utils/format-value.js","../src/utils/is-date.js","../src/utils/model-scope.js","../src/utils/nest-callbacks.js","../src/utils/plain-object.js","../src/utils/ransack.js","../src/utils/rest-args-error.js","../src/utils/singularize-model-name.js","../src/utils/split-sql-statements.js","../src/utils/to-import-specifier.js","../src/utils/with-tracked-stack-async-hooks.js","../src/utils/with-tracked-stack.js"],"version":"6.0.3"}
|
package/package.json
CHANGED
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()) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
import BaseCommand from "../../../base-command.js"
|
|
4
|
+
import {createTenantDatabase} from "../../../../tenants/default-tenant-database-provisioning.js"
|
|
4
5
|
import TenantDatabaseCommandHelper from "../../../tenant-database-command-helper.js"
|
|
5
6
|
|
|
6
7
|
export default class DbTenantsCreate extends BaseCommand {
|
|
@@ -14,13 +15,14 @@ export default class DbTenantsCreate extends BaseCommand {
|
|
|
14
15
|
identifier: this.processArgs?.[1]
|
|
15
16
|
})
|
|
16
17
|
const provider = helper.provider
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
// Providers may customize creation, but the generic driver-agnostic provisioning
|
|
19
|
+
// is the framework default so apps do not reimplement it.
|
|
20
|
+
const createDatabase = typeof provider.createDatabase === "function"
|
|
21
|
+
? provider.createDatabase.bind(provider)
|
|
22
|
+
: createTenantDatabase
|
|
21
23
|
|
|
22
24
|
const tenantCount = await helper.eachTenant(async ({databaseConfiguration, tenant}) => {
|
|
23
|
-
await
|
|
25
|
+
await createDatabase({
|
|
24
26
|
configuration: this.getConfiguration(),
|
|
25
27
|
databaseConfiguration,
|
|
26
28
|
identifier: helper.identifier,
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
import BaseCommand from "../../../base-command.js"
|
|
4
|
+
import {dropTenantDatabase} from "../../../../tenants/default-tenant-database-provisioning.js"
|
|
4
5
|
import TenantDatabaseCommandHelper from "../../../tenant-database-command-helper.js"
|
|
5
6
|
|
|
6
7
|
export default class DbTenantsDrop extends BaseCommand {
|
|
7
8
|
/**
|
|
8
9
|
* Drops the tenant database/schema for every listed tenant through the provider's
|
|
9
|
-
* `dropDatabase` hook.
|
|
10
|
+
* `dropDatabase` hook, or the framework default when the provider defines none.
|
|
10
11
|
* @returns {Promise<{identifier: string, tenantCount: number} | void>} - Result in test mode.
|
|
11
12
|
*/
|
|
12
13
|
async execute() {
|
|
@@ -15,13 +16,12 @@ export default class DbTenantsDrop extends BaseCommand {
|
|
|
15
16
|
identifier: this.processArgs?.[1]
|
|
16
17
|
})
|
|
17
18
|
const provider = helper.provider
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
19
|
+
const dropDatabase = typeof provider.dropDatabase === "function"
|
|
20
|
+
? provider.dropDatabase.bind(provider)
|
|
21
|
+
: dropTenantDatabase
|
|
22
22
|
|
|
23
23
|
const tenantCount = await helper.eachTenant(async ({databaseConfiguration, tenant}) => {
|
|
24
|
-
await
|
|
24
|
+
await dropDatabase({
|
|
25
25
|
configuration: this.getConfiguration(),
|
|
26
26
|
databaseConfiguration,
|
|
27
27
|
identifier: helper.identifier,
|
|
@@ -355,9 +355,17 @@
|
|
|
355
355
|
* @property {Record<string, FrontendModelSyncJsonValue>} [policy] - Deterministic non-secret policy inputs included in the policy hash only.
|
|
356
356
|
*/
|
|
357
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Velocious sync API endpoint configuration.
|
|
360
|
+
* @typedef {object} VelociousSyncApiConfiguration
|
|
361
|
+
* @property {string} [mountPath] - Mount path for the sync endpoints. Defaults to "/velocious/sync".
|
|
362
|
+
* @property {FrontendModelResourceClassType} resourceClass - App sync resource class served by the auto-mounted sync endpoints.
|
|
363
|
+
*/
|
|
364
|
+
|
|
358
365
|
/**
|
|
359
366
|
* Velocious sync configuration.
|
|
360
367
|
* @typedef {object} VelociousSyncConfiguration
|
|
368
|
+
* @property {VelociousSyncApiConfiguration} [api] - Auto-mounts the Velocious sync changes/replay endpoints for this resource class.
|
|
361
369
|
* @property {import("./sync/device-identity.js").SyncJsonWebKey | null} [deviceCertificateBackendPublicKey] - Public backend key used to verify offline device certificates for sync replay.
|
|
362
370
|
* @property {number} [changeFeedRetentionSize] - Number of accepted server changes retained before clients must refresh from snapshot.
|
|
363
371
|
* @property {Array<import("./sync/offline-grant.js").OfflineGrantSigningKey>} offlineGrantSigningKeys - Signing keys used to issue and verify offline grants. Secrets must never be exposed to clients.
|
package/src/configuration.js
CHANGED
|
@@ -424,6 +424,7 @@ export default class VelociousConfiguration {
|
|
|
424
424
|
* @returns {import("./configuration-types.js").VelociousSyncConfiguration} - Normalized sync configuration.
|
|
425
425
|
*/
|
|
426
426
|
_normalizeSyncConfiguration(sync) {
|
|
427
|
+
const api = sync?.api
|
|
427
428
|
const deviceCertificateBackendPublicKey = sync?.deviceCertificateBackendPublicKey || null
|
|
428
429
|
const changeFeedRetentionSize = sync?.changeFeedRetentionSize
|
|
429
430
|
const offlineGrantSigningKeys = sync?.offlineGrantSigningKeys || []
|
|
@@ -441,6 +442,7 @@ export default class VelociousConfiguration {
|
|
|
441
442
|
}
|
|
442
443
|
|
|
443
444
|
return {
|
|
445
|
+
api: this._normalizeSyncApiConfiguration(api),
|
|
444
446
|
changeFeedRetentionSize: changeFeedRetentionSize || 10000,
|
|
445
447
|
deviceCertificateBackendPublicKey,
|
|
446
448
|
offlineGrantSigningKeys: offlineGrantSigningKeys.map((key) => normalizeOfflineGrantSigningKey(key)),
|
|
@@ -448,6 +450,33 @@ export default class VelociousConfiguration {
|
|
|
448
450
|
}
|
|
449
451
|
}
|
|
450
452
|
|
|
453
|
+
/**
|
|
454
|
+
* Normalizes sync API endpoint configuration.
|
|
455
|
+
* @param {import("./configuration-types.js").VelociousSyncApiConfiguration | undefined} api - Sync API configuration.
|
|
456
|
+
* @returns {import("./configuration-types.js").VelociousSyncApiConfiguration | undefined} - Normalized sync API configuration.
|
|
457
|
+
*/
|
|
458
|
+
_normalizeSyncApiConfiguration(api) {
|
|
459
|
+
if (api === undefined || api === null) return undefined
|
|
460
|
+
|
|
461
|
+
if (typeof api !== "object" || Array.isArray(api)) {
|
|
462
|
+
throw new Error("sync.api must be an object with a resourceClass")
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const {mountPath, resourceClass} = api
|
|
466
|
+
|
|
467
|
+
if (typeof resourceClass !== "function") {
|
|
468
|
+
throw new Error(`sync.api.resourceClass must be a resource class, got: ${String(resourceClass)}`)
|
|
469
|
+
}
|
|
470
|
+
if (!resourceClass.ModelClass) {
|
|
471
|
+
throw new Error(`sync.api.resourceClass ${resourceClass.name} must define static ModelClass`)
|
|
472
|
+
}
|
|
473
|
+
if (mountPath !== undefined && (typeof mountPath !== "string" || !mountPath.startsWith("/"))) {
|
|
474
|
+
throw new Error(`sync.api.mountPath must start with '/', got: ${String(mountPath)}`)
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return {mountPath, resourceClass}
|
|
478
|
+
}
|
|
479
|
+
|
|
451
480
|
/**
|
|
452
481
|
* Runs get database configuration.
|
|
453
482
|
* @returns {Record<string, import("./configuration-types.js").DatabaseConfigurationType>} - The database configuration.
|
|
@@ -235,18 +235,48 @@ export default class VelociousDatabaseQuery {
|
|
|
235
235
|
return this._groups
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Runs get joins.
|
|
240
|
+
* @returns {Array<?>} - The joins.
|
|
241
|
+
*/
|
|
242
|
+
getJoins() { return this._joins }
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Runs get limit.
|
|
246
|
+
* @returns {number | null} - The limit.
|
|
247
|
+
*/
|
|
248
|
+
getLimit() { return this._limit }
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Runs get offset.
|
|
252
|
+
* @returns {number | null} - The offset.
|
|
253
|
+
*/
|
|
254
|
+
getOffset() { return this._offset }
|
|
255
|
+
|
|
238
256
|
/**
|
|
239
257
|
* Runs get options.
|
|
240
258
|
* @returns {import("../query-parser/options.js").default} - The options options.
|
|
241
259
|
*/
|
|
242
260
|
getOptions() { return this.driver.options() }
|
|
243
261
|
|
|
262
|
+
/**
|
|
263
|
+
* Runs get orders.
|
|
264
|
+
* @returns {Array<?>} - The orders.
|
|
265
|
+
*/
|
|
266
|
+
getOrders() { return this._orders }
|
|
267
|
+
|
|
244
268
|
/**
|
|
245
269
|
* Runs get selects.
|
|
246
270
|
* @returns {Array<import("./select-base.js").default>} - The selects.
|
|
247
271
|
*/
|
|
248
272
|
getSelects() { return this._selects }
|
|
249
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Runs get wheres.
|
|
276
|
+
* @returns {Array<import("./where-base.js").default>} - The wheres.
|
|
277
|
+
*/
|
|
278
|
+
getWheres() { return this._wheres }
|
|
279
|
+
|
|
250
280
|
/**
|
|
251
281
|
* Runs from.
|
|
252
282
|
* @param {string|import("./from-base.js").default} from - From.
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import {incorporate} from "incorporator"
|
|
4
4
|
import * as inflection from "inflection"
|
|
5
5
|
import {isPlainObject} from "is-plain-object"
|
|
6
|
+
import {currentSyncClient} from "../../sync/sync-client-registry.js"
|
|
6
7
|
import Logger from "../../logger.js"
|
|
7
8
|
import Preloader from "./preloader.js"
|
|
8
9
|
import {normalizeQueryDataSpec, runQueryData} from "./query-data.js"
|
|
@@ -1114,6 +1115,22 @@ export default class VelociousDatabaseQueryModelClassQuery extends DatabaseQuery
|
|
|
1114
1115
|
queryLogName(operation) {
|
|
1115
1116
|
return `${this.getModelClass().name} ${operation}`
|
|
1116
1117
|
}
|
|
1118
|
+
|
|
1119
|
+
/**
|
|
1120
|
+
* Declares this query as a sync scope on the current sync client.
|
|
1121
|
+
* @returns {Promise<?>} - Declared scope and pull result.
|
|
1122
|
+
*/
|
|
1123
|
+
async sync() {
|
|
1124
|
+
return await currentSyncClient().sync(this)
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
/**
|
|
1128
|
+
* Deactivates this query's sync scope on the current sync client.
|
|
1129
|
+
* @returns {Promise<void>} - Resolves when the scope is deactivated.
|
|
1130
|
+
*/
|
|
1131
|
+
async unsync() {
|
|
1132
|
+
await currentSyncClient().unsync(this)
|
|
1133
|
+
}
|
|
1117
1134
|
}
|
|
1118
1135
|
|
|
1119
1136
|
/**
|
|
@@ -535,6 +535,22 @@ class VelociousDatabaseRecord {
|
|
|
535
535
|
callbacks[callbackName].push(callback)
|
|
536
536
|
}
|
|
537
537
|
|
|
538
|
+
/**
|
|
539
|
+
* Runs unregister lifecycle callback.
|
|
540
|
+
* @param {"afterCreate" | "afterDestroy" | "afterSave" | "afterUpdate" | "beforeCreate" | "beforeDestroy" | "beforeSave" | "beforeUpdate" | "beforeValidation"} callbackName - Callback type.
|
|
541
|
+
* @param {LifecycleCallbackType} callback - Previously registered callback.
|
|
542
|
+
* @returns {void}
|
|
543
|
+
*/
|
|
544
|
+
static unregisterLifecycleCallback(callbackName, callback) {
|
|
545
|
+
const callbacks = this.getLifecycleCallbacksMap()[callbackName]
|
|
546
|
+
|
|
547
|
+
if (!callbacks) return
|
|
548
|
+
|
|
549
|
+
const callbackIndex = callbacks.indexOf(callback)
|
|
550
|
+
|
|
551
|
+
if (callbackIndex >= 0) callbacks.splice(callbackIndex, 1)
|
|
552
|
+
}
|
|
553
|
+
|
|
538
554
|
/**
|
|
539
555
|
* Runs before validation.
|
|
540
556
|
* @template R
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import stableJsonStringify from "./stable-json.js"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Serializes a model query into a transportable sync scope.
|
|
7
|
+
*
|
|
8
|
+
* Only plain attribute equality conditions are supported: the scope must be
|
|
9
|
+
* expressible as `{resourceType, conditions}` so servers can match it against
|
|
10
|
+
* their change feeds. Anything else (raw SQL, negations, joins, orders,
|
|
11
|
+
* limits, offsets, groups) fails loudly.
|
|
12
|
+
* @param {import("../database/query/model-class-query.js").default<?>} query - Model query declaring the sync scope.
|
|
13
|
+
* @returns {import("./sync-client-types.js").SerializedSyncScope} Serialized sync scope.
|
|
14
|
+
*/
|
|
15
|
+
export function serializedScopeFromQuery(query) {
|
|
16
|
+
if (query.getJoins().length > 0) throw new Error("sync(query) does not support joins")
|
|
17
|
+
if (query.getOrders().length > 0) throw new Error("sync(query) does not support orders")
|
|
18
|
+
if (query.getLimit() !== null && query.getLimit() !== undefined) throw new Error("sync(query) does not support limit")
|
|
19
|
+
if (query.getOffset() !== null && query.getOffset() !== undefined) throw new Error("sync(query) does not support offset")
|
|
20
|
+
if (query.getGroups().length > 0) throw new Error("sync(query) does not support groups")
|
|
21
|
+
|
|
22
|
+
const modelClass = query.getModelClass()
|
|
23
|
+
const conditions = /** @type {Record<string, ?>} */ ({})
|
|
24
|
+
|
|
25
|
+
for (const where of query.getWheres()) {
|
|
26
|
+
const whereHash = /** @type {{hash?: Record<string, ?>}} */ (where).hash
|
|
27
|
+
|
|
28
|
+
if (!whereHash || typeof whereHash !== "object" || Array.isArray(whereHash) || /** @type {{where?: ?}} */ (where).where) {
|
|
29
|
+
throw new Error(`sync(query) only supports plain attribute conditions, got: ${where.constructor.name}`)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
for (const [attributeName, value] of Object.entries(whereHash)) {
|
|
33
|
+
const conditionValue = scalarConditionValue(attributeName, value)
|
|
34
|
+
|
|
35
|
+
if (attributeName in conditions && stableJsonStringify(conditions[attributeName]) !== stableJsonStringify(conditionValue)) {
|
|
36
|
+
throw new Error(`sync(query) got conflicting conditions for: ${attributeName}`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
conditions[attributeName] = conditionValue
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return {conditions, resourceType: modelClass.getModelName()}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Returns a stable canonical key identifying a sync scope.
|
|
48
|
+
* @param {import("./sync-client-types.js").SerializedSyncScope} scope - Serialized sync scope.
|
|
49
|
+
* @returns {string} Stable scope key.
|
|
50
|
+
*/
|
|
51
|
+
export function scopeKey(scope) {
|
|
52
|
+
return `${scope.resourceType}:${stableJsonStringify(scope.conditions)}`
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Validates one scope condition value as a scalar or array of scalars.
|
|
57
|
+
* @param {string} attributeName - Condition attribute name for error messages.
|
|
58
|
+
* @param {?} value - Condition value.
|
|
59
|
+
* @returns {?} Validated condition value.
|
|
60
|
+
*/
|
|
61
|
+
function scalarConditionValue(attributeName, value) {
|
|
62
|
+
if (Array.isArray(value)) {
|
|
63
|
+
for (const item of value) validateScalar(attributeName, item)
|
|
64
|
+
|
|
65
|
+
return value
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
validateScalar(attributeName, value)
|
|
69
|
+
|
|
70
|
+
return value
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Validates one scalar condition value.
|
|
75
|
+
* @param {string} attributeName - Condition attribute name for error messages.
|
|
76
|
+
* @param {?} value - Condition value.
|
|
77
|
+
* @returns {void}
|
|
78
|
+
*/
|
|
79
|
+
function validateScalar(attributeName, value) {
|
|
80
|
+
if (value === null) return
|
|
81
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return
|
|
82
|
+
|
|
83
|
+
throw new Error(`sync(query) condition values must be scalar, got ${typeof value} for: ${attributeName}`)
|
|
84
|
+
}
|