velocious 1.0.547 → 1.0.549

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/README.md CHANGED
@@ -1187,6 +1187,16 @@ npx velocious db:schema:load
1187
1187
 
1188
1188
  `db:schema:load` reads `db/structure-<identifier>.sql` for each configured database identifier and executes those statements against the current connections. Because the structure file includes the migration ledger rows, a load marks every listed version as already applied. The next `db:migrate` sees those versions and skips them, so migrations whose schema changes are already part of the loaded structure do not run again.
1189
1189
 
1190
+ The same load logic is available programmatically for provisioning a database from a structure dump (for example a tenant or test database) in one pass — much faster than materializing a schema table by table:
1191
+
1192
+ ```js
1193
+ import StructureSqlLoader from "velocious/build/src/database/structure-sql-loader.js"
1194
+
1195
+ await new StructureSqlLoader().load({db, structureSql})
1196
+ ```
1197
+
1198
+ `load({db, structureSql})` disables foreign keys around the load (so the order tables reference each other in the dump does not matter) and uses the driver's native multi-statement `exec` in a single round-trip when available. See [docs/database-migrations.md](docs/database-migrations.md).
1199
+
1190
1200
  ## Schema metadata cache
1191
1201
 
1192
1202
  Velocious caches schema metadata on each database driver instance so repeated model initialization, table lookups, column introspection, and structure SQL generation can reuse the same database results. The cache is cleared automatically after schema-changing SQL runs through Velocious, such as migrations, `createTable`, `dropTable`, `renameColumn`, `ALTER TABLE`, `CREATE INDEX`, and `COMMENT ON`. See [docs/schema-metadata-cache.md](docs/schema-metadata-cache.md) for details.
@@ -2354,6 +2364,8 @@ npx velocious db:tenants:migrate projectTenant
2354
2364
  npx velocious db:tenants:migrate projectTenant --parallel 20
2355
2365
  ```
2356
2366
 
2367
+ Tenant lifecycle commands print start and final counts, report each completed tenant, and emit a heartbeat every 30 seconds with completed and active tenant counts while work is still running.
2368
+
2357
2369
  `afterMigrateTenant` hooks run inside the active default and tenant database connection scope for the tenant being migrated.
2358
2370
 
2359
2371
  At runtime, the apartment-style `Tenant` façade (`velocious/build/src/tenants/tenant.js`) is the single entry point: `Tenant.with(tenant, callback)` / `Tenant.current()` to switch into and read a tenant context, `Tenant.each({identifier, callback, parallel?, filter?})` to run a callback within every provider-listed tenant, and `Tenant.drop({identifier, tenant})` (plus the `db:tenants:drop` CLI command) to drop a tenant's database through the provider's `dropDatabase` hook. `Tenant.with` and `Tenant.each` run their callbacks inside `ensureConnections`, so switching into a tenant establishes its database connections (global + tenant) and passes them to the callback — the tenant is immediately queryable without the caller wiring up connections (already-open connections are reused, so nesting does not double-connect). `Tenant.with` is generic over its callback's return type, so a value returned from inside the tenant context comes back to the caller with its type preserved (no cast needed). `Tenant.aggregateAcross({identifier, aggregates, keyColumns, subquery, tenants?, filter?})` runs one aggregate over the same table across many tenant databases and returns the merged result — grouping tenants by server and using a single cross-database `UNION ALL` where the driver supports two-part `` `database`.`table` `` references (MySQL/MariaDB) or one query per tenant otherwise (PostgreSQL/SQLite/MSSQL).
@@ -2,19 +2,25 @@
2
2
 
3
3
  import TenantIterator from "../tenants/tenant-iterator.js"
4
4
 
5
+ const DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000
6
+
5
7
  export default class TenantDatabaseCommandHelper {
6
8
  /**
7
9
  * Runs constructor.
8
10
  * @param {object} args - Options object.
9
11
  * @param {import("./base-command.js").default} args.command - CLI command instance.
12
+ * @param {number} [args.heartbeatIntervalMs] - Interval between progress heartbeats.
10
13
  * @param {string | undefined} args.identifier - Tenant database identifier.
14
+ * @param {(message: string) => void} [args.output] - Progress output handler.
11
15
  */
12
- constructor({command, identifier}) {
16
+ constructor({command, heartbeatIntervalMs = DEFAULT_HEARTBEAT_INTERVAL_MS, identifier, output = console.log}) {
13
17
  if (!identifier) throw new Error("Missing tenant database identifier argument")
14
18
 
15
19
  this.command = command
16
20
  this.configuration = command.getConfiguration()
21
+ this.heartbeatIntervalMs = heartbeatIntervalMs
17
22
  this.identifier = identifier
23
+ this.output = output
18
24
  this.provider = this.configuration.getTenantDatabaseProvider(identifier)
19
25
  }
20
26
 
@@ -78,13 +84,42 @@ export default class TenantDatabaseCommandHelper {
78
84
  */
79
85
  async eachTenant(callback) {
80
86
  const tenants = await this.listTenants()
87
+ const commandName = this.command.processArgs?.[0] || "db:tenants"
88
+ const parallelCount = this.parallelCount()
89
+ const progressPrefix = `${commandName} ${this.identifier}`
90
+ let activeTenantCount = 0
91
+ let completedTenantCount = 0
81
92
  const iterator = new TenantIterator({
82
93
  configuration: this.configuration,
83
94
  identifier: this.identifier,
84
- parallelCount: this.parallelCount()
95
+ parallelCount
85
96
  })
97
+ const progressHeartbeat = setInterval(() => {
98
+ this.output(`${progressPrefix}: heartbeat: ${completedTenantCount}/${tenants.length} completed, ${activeTenantCount} active`)
99
+ }, this.heartbeatIntervalMs)
100
+
101
+ progressHeartbeat.unref()
102
+ this.output(`${progressPrefix}: processing ${tenants.length} tenant(s) with parallelism ${parallelCount}`)
103
+
104
+ try {
105
+ const processedTenantCount = await iterator.run(tenants, async (args) => {
106
+ activeTenantCount++
107
+
108
+ try {
109
+ await callback(args)
110
+ completedTenantCount++
111
+ this.output(`${progressPrefix}: completed ${TenantIterator.tenantLabel(args.tenant)} (${completedTenantCount}/${tenants.length})`)
112
+ } finally {
113
+ activeTenantCount--
114
+ }
115
+ })
86
116
 
87
- return await iterator.run(tenants, callback)
117
+ this.output(`${progressPrefix}: finished ${processedTenantCount}/${tenants.length} tenant(s)`)
118
+
119
+ return processedTenantCount
120
+ } finally {
121
+ clearInterval(progressHeartbeat)
122
+ }
88
123
  }
89
124
 
90
125
  /**
@@ -0,0 +1,68 @@
1
+ // @ts-check
2
+
3
+ import splitSqlStatements from "../utils/split-sql-statements.js"
4
+
5
+ /**
6
+ * Loads a database structure SQL dump into a connection in one pass. Foreign keys are
7
+ * disabled around the load so tables can be created in any order, and the driver's
8
+ * native multi-statement `exec` is used when available (a single round-trip) instead
9
+ * of issuing every statement separately. This is much faster than materializing a
10
+ * schema table by table (e.g. cloning), so it is the preferred way to provision a
11
+ * tenant/test database from a structure dump.
12
+ *
13
+ * Used by the `db:schema:load` CLI command and reusable by any caller that needs to
14
+ * apply a structure dump to a specific connection.
15
+ */
16
+ export default class StructureSqlLoader {
17
+ /**
18
+ * Loads `structureSql` into `db`.
19
+ * @param {object} args - Options object.
20
+ * @param {import("./drivers/base.js").default} args.db - Target database connection.
21
+ * @param {string} args.structureSql - Structure SQL to load.
22
+ * @returns {Promise<void>} - Resolves when the structure has been loaded.
23
+ */
24
+ async load({db, structureSql}) {
25
+ const statements = splitSqlStatements(structureSql)
26
+
27
+ if (statements.length == 0) return
28
+
29
+ const executableConnection = this.executableConnection(db)
30
+
31
+ await db.disableForeignKeys()
32
+
33
+ try {
34
+ if (executableConnection) {
35
+ await executableConnection.exec(structureSql)
36
+ } else {
37
+ for (const statement of statements) {
38
+ await db.query(statement)
39
+ }
40
+ }
41
+ } finally {
42
+ await db.enableForeignKeys()
43
+
44
+ // The native `exec` path mutates the schema outside `Base#query`, so the
45
+ // usual post-DDL schema-cache invalidation never runs. Clear it here so a
46
+ // caller that read schema metadata before provisioning (e.g. an empty table
47
+ // list) does not keep seeing the pre-load schema afterwards. Harmless for the
48
+ // per-statement path, which already invalidates as each DDL statement runs.
49
+ db.clearSchemaCache()
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Returns the underlying connection when it exposes a native multi-statement
55
+ * `exec` (a single round-trip for the whole dump), otherwise undefined so the
56
+ * caller falls back to per-statement execution.
57
+ * @param {import("./drivers/base.js").default} db - Database connection.
58
+ * @returns {{exec: (sql: string) => Promise<?>} | undefined} - Connection with exec support.
59
+ */
60
+ executableConnection(db) {
61
+ const dbWithConnection = /** @type {import("./drivers/base.js").default & {connection?: ?}} */ (db)
62
+ const connection = dbWithConnection.connection
63
+
64
+ if (connection && typeof connection == "object" && "exec" in connection && typeof connection.exec == "function") {
65
+ return /** @type {{exec: (sql: string) => Promise<?>}} */ (connection)
66
+ }
67
+ }
68
+ }
@@ -1,7 +1,7 @@
1
1
  import BaseCommand from "../../../../../../cli/base-command.js"
2
2
  import fs from "fs/promises"
3
3
  import path from "path"
4
- import splitSqlStatements from "../../../../../../utils/split-sql-statements.js"
4
+ import StructureSqlLoader from "../../../../../../database/structure-sql-loader.js"
5
5
 
6
6
  /** Node CLI command for loading DB structure SQL files. */
7
7
  export default class DbSchemaLoad extends BaseCommand {
@@ -11,57 +11,15 @@ export default class DbSchemaLoad extends BaseCommand {
11
11
  async execute() {
12
12
  await this.getConfiguration().ensureConnections({name: "DB schema load"}, async (dbs) => {
13
13
  const dbDir = path.join(this.directory(), "db")
14
+ const loader = new StructureSqlLoader()
14
15
 
15
16
  for (const identifier of Object.keys(dbs)) {
16
17
  const db = dbs[identifier]
17
18
  const structureFilePath = path.join(dbDir, `structure-${identifier}.sql`)
18
19
  const structureSql = await fs.readFile(structureFilePath, "utf8")
19
20
 
20
- await this.loadStructureSql({db, structureSql})
21
+ await loader.load({db, structureSql})
21
22
  }
22
23
  })
23
24
  }
24
-
25
- /**
26
- * Runs load structure sql.
27
- * @param {object} args - Options object.
28
- * @param {import("../../../../../../database/drivers/base.js").default} args.db - Database connection.
29
- * @param {string} args.structureSql - Structure SQL to load.
30
- * @returns {Promise<void>} - Resolves when complete.
31
- */
32
- async loadStructureSql({db, structureSql}) {
33
- const statements = splitSqlStatements(structureSql)
34
-
35
- if (statements.length == 0) return
36
-
37
- const executableConnection = this.executableConnection(db)
38
-
39
- await db.disableForeignKeys()
40
-
41
- try {
42
- if (executableConnection) {
43
- await executableConnection.exec(structureSql)
44
- } else {
45
- for (const statement of statements) {
46
- await db.query(statement)
47
- }
48
- }
49
- } finally {
50
- await db.enableForeignKeys()
51
- }
52
- }
53
-
54
- /**
55
- * Runs executable connection.
56
- * @param {import("../../../../../../database/drivers/base.js").default} db - Database connection.
57
- * @returns {{exec: (sql: string) => Promise<?>} | undefined} - Connection with exec support.
58
- */
59
- executableConnection(db) {
60
- const dbWithConnection = /** @type {import("../../../../../../database/drivers/base.js").default & {connection?: ?}} */ (db)
61
- const connection = dbWithConnection.connection
62
-
63
- if (connection && typeof connection == "object" && "exec" in connection && typeof connection.exec == "function") {
64
- return /** @type {{exec: (sql: string) => Promise<?>}} */ (connection)
65
- }
66
- }
67
25
  }
@@ -3,15 +3,21 @@ export default class TenantDatabaseCommandHelper {
3
3
  * Runs constructor.
4
4
  * @param {object} args - Options object.
5
5
  * @param {import("./base-command.js").default} args.command - CLI command instance.
6
+ * @param {number} [args.heartbeatIntervalMs] - Interval between progress heartbeats.
6
7
  * @param {string | undefined} args.identifier - Tenant database identifier.
8
+ * @param {(message: string) => void} [args.output] - Progress output handler.
7
9
  */
8
- constructor({ command, identifier }: {
10
+ constructor({ command, heartbeatIntervalMs, identifier, output }: {
9
11
  command: import("./base-command.js").default;
12
+ heartbeatIntervalMs?: number | undefined;
10
13
  identifier: string | undefined;
14
+ output?: ((message: string) => void) | undefined;
11
15
  });
12
16
  command: import("./base-command.js").default;
13
17
  configuration: import("../configuration.js").default;
18
+ heartbeatIntervalMs: number;
14
19
  identifier: string;
20
+ output: (message: string) => void;
15
21
  provider: import("../configuration-types.js").TenantDatabaseProviderType;
16
22
  /**
17
23
  * Runs validate tenant database identifier.
@@ -1 +1 @@
1
- {"version":3,"file":"tenant-database-command-helper.d.ts","sourceRoot":"","sources":["../../../src/cli/tenant-database-command-helper.js"],"names":[],"mappings":"AAIA;IACE;;;;;OAKG;IACH,qCAHG;QAAkD,OAAO,EAAjD,OAAO,mBAAmB,EAAE,OAAO;QACV,UAAU,EAAnC,MAAM,GAAG,SAAS;KAC5B,EAQA;IAJC,6CAAsB;IACtB,qDAA+C;IAC/C,mBAA4B;IAC5B,yEAAwE;IAG1E;;yBAEqB;IACrB,oCADa,IAAI,CAmBhB;IAED;;;OAGG;IACH,qBAFa,OAAO,CAAC,IAAI,CAAC,CAIzB;IAED;;;OAGG;IACH,eAFa,OAAO,CAAC,KAAK,CAAC,OAAC,CAAC,CAAC,CAkB7B;IAED;;;;OAIG;IACH,qBAHW,CAAS,IAAiG,EAAjG;QAAC,qBAAqB,EAAE,OAAO,2BAA2B,EAAE,yBAAyB,CAAC;QAAC,MAAM,EAAE,OAAC,CAAA;KAAC,KAAI,OAAO,CAAC,IAAI,CAAC,GACzH,OAAO,CAAC,MAAM,CAAC,CAW3B;IAED;;;OAGG;IACH,iBAFa,MAAM,CA0BlB;CACF"}
1
+ {"version":3,"file":"tenant-database-command-helper.d.ts","sourceRoot":"","sources":["../../../src/cli/tenant-database-command-helper.js"],"names":[],"mappings":"AAMA;IACE;;;;;;;OAOG;IACH,kEALG;QAAkD,OAAO,EAAjD,OAAO,mBAAmB,EAAE,OAAO;QACrB,mBAAmB;QACR,UAAU,EAAnC,MAAM,GAAG,SAAS;QACe,MAAM,cAA7B,MAAM,KAAK,IAAI;KACnC,EAUA;IANC,6CAAsB;IACtB,qDAA+C;IAC/C,4BAA8C;IAC9C,mBAA4B;IAC5B,kBATmB,MAAM,KAAK,IAAI,CASd;IACpB,yEAAwE;IAG1E;;yBAEqB;IACrB,oCADa,IAAI,CAmBhB;IAED;;;OAGG;IACH,qBAFa,OAAO,CAAC,IAAI,CAAC,CAIzB;IAED;;;OAGG;IACH,eAFa,OAAO,CAAC,KAAK,CAAC,OAAC,CAAC,CAAC,CAkB7B;IAED;;;;OAIG;IACH,qBAHW,CAAS,IAAiG,EAAjG;QAAC,qBAAqB,EAAE,OAAO,2BAA2B,EAAE,yBAAyB,CAAC;QAAC,MAAM,EAAE,OAAC,CAAA;KAAC,KAAI,OAAO,CAAC,IAAI,CAAC,GACzH,OAAO,CAAC,MAAM,CAAC,CAwC3B;IAED;;;OAGG;IACH,iBAFa,MAAM,CA0BlB;CACF"}
@@ -1,18 +1,23 @@
1
1
  // @ts-check
2
2
  import TenantIterator from "../tenants/tenant-iterator.js";
3
+ const DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000;
3
4
  export default class TenantDatabaseCommandHelper {
4
5
  /**
5
6
  * Runs constructor.
6
7
  * @param {object} args - Options object.
7
8
  * @param {import("./base-command.js").default} args.command - CLI command instance.
9
+ * @param {number} [args.heartbeatIntervalMs] - Interval between progress heartbeats.
8
10
  * @param {string | undefined} args.identifier - Tenant database identifier.
11
+ * @param {(message: string) => void} [args.output] - Progress output handler.
9
12
  */
10
- constructor({ command, identifier }) {
13
+ constructor({ command, heartbeatIntervalMs = DEFAULT_HEARTBEAT_INTERVAL_MS, identifier, output = console.log }) {
11
14
  if (!identifier)
12
15
  throw new Error("Missing tenant database identifier argument");
13
16
  this.command = command;
14
17
  this.configuration = command.getConfiguration();
18
+ this.heartbeatIntervalMs = heartbeatIntervalMs;
15
19
  this.identifier = identifier;
20
+ this.output = output;
16
21
  this.provider = this.configuration.getTenantDatabaseProvider(identifier);
17
22
  }
18
23
  /**
@@ -65,12 +70,39 @@ export default class TenantDatabaseCommandHelper {
65
70
  */
66
71
  async eachTenant(callback) {
67
72
  const tenants = await this.listTenants();
73
+ const commandName = this.command.processArgs?.[0] || "db:tenants";
74
+ const parallelCount = this.parallelCount();
75
+ const progressPrefix = `${commandName} ${this.identifier}`;
76
+ let activeTenantCount = 0;
77
+ let completedTenantCount = 0;
68
78
  const iterator = new TenantIterator({
69
79
  configuration: this.configuration,
70
80
  identifier: this.identifier,
71
- parallelCount: this.parallelCount()
81
+ parallelCount
72
82
  });
73
- return await iterator.run(tenants, callback);
83
+ const progressHeartbeat = setInterval(() => {
84
+ this.output(`${progressPrefix}: heartbeat: ${completedTenantCount}/${tenants.length} completed, ${activeTenantCount} active`);
85
+ }, this.heartbeatIntervalMs);
86
+ progressHeartbeat.unref();
87
+ this.output(`${progressPrefix}: processing ${tenants.length} tenant(s) with parallelism ${parallelCount}`);
88
+ try {
89
+ const processedTenantCount = await iterator.run(tenants, async (args) => {
90
+ activeTenantCount++;
91
+ try {
92
+ await callback(args);
93
+ completedTenantCount++;
94
+ this.output(`${progressPrefix}: completed ${TenantIterator.tenantLabel(args.tenant)} (${completedTenantCount}/${tenants.length})`);
95
+ }
96
+ finally {
97
+ activeTenantCount--;
98
+ }
99
+ });
100
+ this.output(`${progressPrefix}: finished ${processedTenantCount}/${tenants.length} tenant(s)`);
101
+ return processedTenantCount;
102
+ }
103
+ finally {
104
+ clearInterval(progressHeartbeat);
105
+ }
74
106
  }
75
107
  /**
76
108
  * Runs parallel count.
@@ -97,4 +129,4 @@ export default class TenantDatabaseCommandHelper {
97
129
  return parallelCount;
98
130
  }
99
131
  }
100
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVuYW50LWRhdGFiYXNlLWNvbW1hbmQtaGVscGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NsaS90ZW5hbnQtZGF0YWJhc2UtY29tbWFuZC1oZWxwZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sY0FBYyxNQUFNLCtCQUErQixDQUFBO0FBRTFELE1BQU0sQ0FBQyxPQUFPLE9BQU8sMkJBQTJCO0lBQzlDOzs7OztPQUtHO0lBQ0gsWUFBWSxFQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUM7UUFDL0IsSUFBSSxDQUFDLFVBQVU7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLDZDQUE2QyxDQUFDLENBQUE7UUFFL0UsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUE7UUFDdEIsSUFBSSxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQTtRQUMvQyxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQTtRQUM1QixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMseUJBQXlCLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDMUUsQ0FBQztJQUVEOzt5QkFFcUI7SUFDckIsZ0NBQWdDO1FBQzlCLE1BQU0scUJBQXFCLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUU1RixJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLDJDQUEyQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQTtRQUMvRSxDQUFDO1FBRUQsSUFBSSxDQUFDLHFCQUFxQixDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3RDLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLElBQUksQ0FBQyxVQUFVLDBDQUEwQyxDQUFDLENBQUE7UUFDbkcsQ0FBQztRQUVELElB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LFdBQVcsS0FBSyxTQUFTLElBQUksV0FBVyxLQUFLLEtBQUs7WUFBRSxPQUFPLENBQUMsQ0FBQTtRQUNoRSxJQUFJLFdBQVcsS0FBSyxJQUFJO1lBQUUsT0FBTyxFQUFFLENBQUE7UUFFbkMsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1FBRXpDLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxJQUFJLGFBQWEsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUMxRCxNQUFNLElBQUksS0FBSyxDQUFDLG1FQUFtRSxXQUFXLEVBQUUsQ0FBQyxDQUFBO1FBQ25HLENBQUM7UUFFRCxPQUFPLGFBQWEsQ0FBQTtJQUN0QixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IFRlbmFudEl0ZXJhdG9yIGZyb20gXCIuLi90ZW5hbnRzL3RlbmFudC1pdGVyYXRvci5qc1wiXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRlbmFudERhdGFiYXNlQ29tbWFuZEhlbHBlciB7XG4gIC8qKlxuICAgKiBSdW5zIGNvbnN0cnVjdG9yLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMgb2JqZWN0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vYmFzZS1jb21tYW5kLmpzXCIpLmRlZmF1bHR9IGFyZ3MuY29tbWFuZCAtIENMSSBjb21tYW5kIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZyB8IHVuZGVmaW5lZH0gYXJncy5pZGVudGlmaWVyIC0gVGVuYW50IGRhdGFiYXNlIGlkZW50aWZpZXIuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcih7Y29tbWFuZCwgaWRlbnRpZmllcn0pIHtcbiAgICBpZiAoIWlkZW50aWZpZXIpIHRocm93IG5ldyBFcnJvcihcIk1pc3NpbmcgdGVuYW50IGRhdGFiYXNlIGlkZW50aWZpZXIgYXJndW1lbnRcIilcblxuICAgIHRoaXMuY29tbWFuZCA9IGNvbW1hbmRcbiAgICB0aGlzLmNvbmZpZ3VyYXRpb24gPSBjb21tYW5kLmdldENvbmZpZ3VyYXRpb24oKVxuICAgIHRoaXMuaWRlbnRpZmllciA9IGlkZW50aWZpZXJcbiAgICB0aGlzLnByb3ZpZGVyID0gdGhpcy5jb25maWd1cmF0aW9uLmdldFRlbmFudERhdGFiYXNlUHJvdmlkZXIoaWRlbnRpZmllcilcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHZhbGlkYXRlIHRlbmFudCBkYXRhYmFzZSBpZGVudGlmaWVyLlxuICAgKiBAcmV0dXJucyB7dm9pZH0gKi9cbiAgdmFsaWRhdGVUZW5hbnREYXRhYmFzZUlkZW50aWZpZXIoKSB7XG4gICAgY29uc3QgZGF0YWJhc2VDb25maWd1cmF0aW9uID0gdGhpcy5jb25maWd1cmF0aW9uLmdldERhdGFiYXNlQ29uZmlndXJhdGlvbigpW3RoaXMuaWRlbnRpZmllcl1cblxuICAgIGlmICghZGF0YWJhc2VDb25maWd1cmF0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIHN1Y2ggZGF0YWJhc2UgaWRlbnRpZmllciBjb25maWd1cmVkOiAke3RoaXMuaWRlbnRpZmllcn1gKVxuICAgIH1cblxuICAgIGlmICghZGF0YWJhc2VDb25maWd1cmF0aW9uLnRlbmFudE9ubHkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRGF0YWJhc2UgaWRlbnRpZmllciAke3RoaXMuaWRlbnRpZmllcn0gaXMgbm90IGNvbmZpZ3VyZWQgd2l0aCB0ZW5hbnRPbmx5OiB0cnVlYClcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uLmdldERpc2FibGVkRGF0YWJhc2VJZGVudGlmaWVycygpLmhhcyh0aGlzLmlkZW50aWZpZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRlbmFudCBkYXRhYmFzZSBpZGVudGlmaWVyICR7dGhpcy5pZGVudGlmaWVyfSBpcyBkaXNhYmxlZCBieSBWRUxPQ0lPVVNfRElTQUJMRURfREFUQUJBU0VfSURFTlRJRklFUlNgKVxuICAgIH1cblxuICAgIGlmICh0eXBlb2YgdGhpcy5wcm92aWRlci5saXN0VGVuYW50cyAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRlbmFudCBkYXRhYmFzZSBwcm92aWRlciBmb3IgJHt0aGlzLmlkZW50aWZpZXJ9IG11c3QgZGVmaW5lIGxpc3RUZW5hbnRzYClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBpbml0aWFsaXplIHJ1bnRpbWUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gYXBwIHJ1bnRpbWUgaXMgaW5pdGlhbGl6ZWQuXG4gICAqL1xuICBhc3luYyBpbml0aWFsaXplUnVudGltZSgpIHtcbiAgICBhd2FpdCB0aGlzLmNvbmZpZ3VyYXRpb24uaW5pdGlhbGl6ZSh7dHlwZTogXCJkYi10ZW5hbnRzXCJ9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgbGlzdCB0ZW5hbnRzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxBcnJheTw/Pj59IC0gVGVuYW50cy5cbiAgICovXG4gIGFzeW5jIGxpc3RUZW5hbnRzKCkge1xuICAgIHRoaXMudmFsaWRhdGVUZW5hbnREYXRhYmFzZUlkZW50aWZpZXIoKVxuICAgIGF3YWl0IHRoaXMuaW5pdGlhbGl6ZVJ1bnRpbWUoKVxuXG4gICAgY29uc3QgdGVuYW50cyA9IGF3YWl0IHRoaXMuY29uZmlndXJhdGlvbi5lbnN1cmVDb25uZWN0aW9ucyh7bmFtZTogYFRlbmFudCBkYXRhYmFzZSBsaXN0OiAke3RoaXMuaWRlbnRpZmllcn1gfSwgYXN5bmMgKCkgPT4ge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMucHJvdmlkZXIubGlzdFRlbmFudHMoe1xuICAgICAgICBjb25maWd1cmF0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb24sXG4gICAgICAgIGlkZW50aWZpZXI6IHRoaXMuaWRlbnRpZmllclxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHRlbmFudHMpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRlbmFudCBkYXRhYmFzZSBwcm92aWRlciBmb3IgJHt0aGlzLmlkZW50aWZpZXJ9IG11c3QgcmV0dXJuIGFuIGFycmF5IGZyb20gbGlzdFRlbmFudHNgKVxuICAgIH1cblxuICAgIHJldHVybiB0ZW5hbnRzXG4gIH1cblxuICAvKipcbiAgICogUnVucyBlYWNoIHRlbmFudC5cbiAgICogQHBhcmFtIHtmdW5jdGlvbih7ZGF0YWJhc2VDb25maWd1cmF0aW9uOiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLXR5cGVzLmpzXCIpLkRhdGFiYXNlQ29uZmlndXJhdGlvblR5cGUsIHRlbmFudDogP30pIDogUHJvbWlzZTx2b2lkPn0gY2FsbGJhY2sgLSBDYWxsYmFjay5cbiAgICogQHJldHVybnMge1Byb21pc2U8bnVtYmVyPn0gLSBOdW1iZXIgb2YgdGVuYW50cyBwcm9jZXNzZWQuXG4gICAqL1xuICBhc3luYyBlYWNoVGVuYW50KGNhbGxiYWNrKSB7XG4gICAgY29uc3QgdGVuYW50cyA9IGF3YWl0IHRoaXMubGlzdFRlbmFudHMoKVxuICAgIGNvbnN0IGl0ZXJhdG9yID0gbmV3IFRlbmFudEl0ZXJhdG9yKHtcbiAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlndXJhdGlvbixcbiAgICAgIGlkZW50aWZpZXI6IHRoaXMuaWRlbnRpZmllcixcbiAgICAgIHBhcmFsbGVsQ291bnQ6IHRoaXMucGFyYWxsZWxDb3VudCgpXG4gICAgfSlcblxuICAgIHJldHVybiBhd2FpdCBpdGVyYXRvci5ydW4odGVuYW50cywgY2FsbGJhY2spXG4gIH1cblxuICAvKipcbiAgICogUnVucyBwYXJhbGxlbCBjb3VudC5cbiAgICogQHJldHVybnMge251bWJlcn0gLSBOdW1iZXIgb2YgdGVuYW50cyB0byBwcm9jZXNzIGNvbmN1cnJlbnRseS5cbiAgICovXG4gIHBhcmFsbGVsQ291bnQoKSB7XG4gICAgY29uc3QgcGFyc2VkUHJvY2Vzc0FyZ3MgPSB0aGlzLmNvbW1hbmQuYXJncz8ucGFyc2VkUHJvY2Vzc0FyZ3MgfHwge31cbiAgICBsZXQgcGFyYWxsZWxBcmcgPSBwYXJzZWRQcm9jZXNzQXJncy5wYXJhbGxlbFxuXG4gICAgaWYgKHBhcmFsbGVsQXJnID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IHBhcmFsbGVsQXJnSW5kZXggPSB0aGlzLmNvbW1hbmQucHJvY2Vzc0FyZ3M/LmluZGV4T2YoXCItLXBhcmFsbGVsXCIpID8/IC0xXG5cbiAgICAgIGlmIChwYXJhbGxlbEFyZ0luZGV4ID49IDApIHtcbiAgICAgICAgY29uc3QgbmV4dEFyZyA9IHRoaXMuY29tbWFuZC5wcm9jZXNzQXJncz8uW3BhcmFsbGVsQXJnSW5kZXggKyAxXVxuXG4gICAgICAgIHBhcmFsbGVsQXJnID0gbmV4dEFyZyAmJiAhbmV4dEFyZy5zdGFydHNXaXRoKFwiLVwiKSA/IG5leHRBcmcgOiB0cnVlXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHBhcmFsbGVsQXJnID09PSB1bmRlZmluZWQgfHwgcGFyYWxsZWxBcmcgPT09IGZhbHNlKSByZXR1cm4gMVxuICAgIGlmIChwYXJhbGxlbEFyZyA9PT0gdHJ1ZSkgcmV0dXJuIDIwXG5cbiAgICBjb25zdCBwYXJhbGxlbENvdW50ID0gTnVtYmVyKHBhcmFsbGVsQXJnKVxuXG4gICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHBhcmFsbGVsQ291bnQpIHx8IHBhcmFsbGVsQ291bnQgPCAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYC0tcGFyYWxsZWwgbXVzdCBiZSBhIHBvc2l0aXZlIGludGVnZXIgd2hlbiBhIHZhbHVlIGlzIHByb3ZpZGVkOiAke3BhcmFsbGVsQXJnfWApXG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcmFsbGVsQ291bnRcbiAgfVxufVxuIl19
132
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVuYW50LWRhdGFiYXNlLWNvbW1hbmQtaGVscGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NsaS90ZW5hbnQtZGF0YWJhc2UtY29tbWFuZC1oZWxwZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sY0FBYyxNQUFNLCtCQUErQixDQUFBO0FBRTFELE1BQU0sNkJBQTZCLEdBQUcsTUFBTSxDQUFBO0FBRTVDLE1BQU0sQ0FBQyxPQUFPLE9BQU8sMkJBQTJCO0lBQzlDOzs7Ozs7O09BT0c7SUFDSCxZQUFZLEVBQUMsT0FBTyxFQUFFLG1CQUFtQixHQUFHLDZCQUE2QixFQUFFLFVBQVUsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBQztRQUMxRyxJQUFJLENBQUMsVUFBVTtZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsNkNBQTZDLENBQUMsQ0FBQTtRQUUvRSxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQTtRQUN0QixJQUFJLENBQUMsYUFBYSxHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO1FBQy9DLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxtQkFBbUIsQ0FBQTtRQUM5QyxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQTtRQUM1QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQTtRQUNwQixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMseUJBQXlCLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDMUUsQ0FBQztJQUVEOzt5QkFFcUI7SUFDckIsZ0NBQWdDO1FBQzlCLE1BQU0scUJBQXFCLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUU1RixJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLDJDQUEyQyxJ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QUFXLEVBQUUsT0FBTyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFBO1lBRTlFLElBQUksZ0JBQWdCLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQzFCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUMsZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDLENBQUE7Z0JBRWhFLFdBQVcsR0FBRyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQTtZQUNwRSxDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksV0FBVyxLQUFLLFNBQVMsSUFBSSxXQUFXLEtBQUssS0FBSztZQUFFLE9BQU8sQ0FBQyxDQUFBO1FBQ2hFLElBQUksV0FBVyxLQUFLLElBQUk7WUFBRSxPQUFPLEVBQUUsQ0FBQTtRQUVuQyxNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUE7UUFFekMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLElBQUksYUFBYSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzFELE1BQU0sSUFBSSxLQUFLLENBQUMsbUVBQW1FLFdBQVcsRUFBRSxDQUFDLENBQUE7UUFDbkcsQ0FBQztRQUVELE9BQU8sYUFBYSxDQUFBO0lBQ3RCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgVGVuYW50SXRlcmF0b3IgZnJvbSBcIi4uL3RlbmFudHMvdGVuYW50LWl0ZXJhdG9yLmpzXCJcblxuY29uc3QgREVGQVVMVF9IRUFSVEJFQVRfSU5URVJWQUxfTVMgPSAzMF8wMDBcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGVuYW50RGF0YWJhc2VDb21tYW5kSGVscGVyIHtcbiAgLyoqXG4gICAqIFJ1bnMgY29uc3RydWN0b3IuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucyBvYmplY3QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9iYXNlLWNvbW1hbmQuanNcIikuZGVmYXVsdH0gYXJncy5jb21tYW5kIC0gQ0xJIGNvbW1hbmQgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJncy5oZWFydGJlYXRJbnRlcnZhbE1zXSAtIEludGVydmFsIGJldHdlZW4gcHJvZ3Jlc3MgaGVhcnRiZWF0cy5cbiAgICogQHBhcmFtIHtzdHJpbmcgfCB1bmRlZmluZWR9IGFyZ3MuaWRlbnRpZmllciAtIFRlbmFudCBkYXRhYmFzZSBpZGVudGlmaWVyLlxuICAgKiBAcGFyYW0geyhtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWR9IFthcmdzLm91dHB1dF0gLSBQcm9ncmVzcyBvdXRwdXQgaGFuZGxlci5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHtjb21tYW5kLCBoZWFydGJlYXRJbnRlcnZhbE1zID0gREVGQVVMVF9IRUFSVEJFQVRfSU5URVJWQUxfTVMsIGlkZW50aWZpZXIsIG91dHB1dCA9IGNvbnNvbGUubG9nfSkge1xuICAgIGlmICghaWRlbnRpZmllcikgdGhyb3cgbmV3IEVycm9yKFwiTWlzc2luZyB0ZW5hbnQgZGF0YWJhc2UgaWRlbnRpZmllciBhcmd1bWVudFwiKVxuXG4gICAgdGhpcy5jb21tYW5kID0gY29tbWFuZFxuICAgIHRoaXMuY29uZmlndXJhdGlvbiA9IGNvbW1hbmQuZ2V0Q29uZmlndXJhdGlvbigpXG4gICAgdGhpcy5oZWFydGJlYXRJbnRlcnZhbE1zID0gaGVhcnRiZWF0SW50ZXJ2YWxNc1xuICAgIHRoaXMuaWRlbnRpZmllciA9IGlkZW50aWZpZXJcbiAgICB0aGlzLm91dHB1dCA9IG91dHB1dFxuICAgIHRoaXMucHJvdmlkZXIgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0VGVuYW50RGF0YWJhc2VQcm92aWRlcihpZGVudGlmaWVyKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgdmFsaWRhdGUgdGVuYW50IGRhdGFiYXNlIGlkZW50aWZpZXIuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAqL1xuICB2YWxpZGF0ZVRlbmFudERhdGFiYXNlSWRlbnRpZmllcigpIHtcbiAgICBjb25zdCBkYXRhYmFzZUNvbmZpZ3VyYXRpb24gPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0RGF0YWJhc2VDb25maWd1cmF0aW9uKClbdGhpcy5pZGVudGlmaWVyXVxuXG4gICAgaWYgKCFkYXRhYmFzZUNvbmZpZ3VyYXRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gc3VjaCBkYXRhYmFzZSBpZGVudGlmaWVyIGNvbmZpZ3VyZWQ6ICR7dGhpcy5pZGVudGlmaWVyfWApXG4gICAgfVxuXG4gICAgaWYgKCFkYXRhYmFzZUNvbmZpZ3VyYXRpb24udGVuYW50T25seSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBEYXRhYmFzZSBpZGVudGlmaWVyICR7dGhpcy5pZGVudGlmaWVyfSBpcyBub3QgY29uZmlndXJlZCB3aXRoIHRlbmFudE9ubHk6IHRydWVgKVxuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0RGlzYWJsZWREYXRhYmFzZUlkZW50aWZpZXJzKCkuaGFzKHRoaXMuaWRlbnRpZmllcikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGVuYW50IGRhdGFiYXNlIGlkZW50aWZpZXIgJHt0aGlzLmlkZW50aWZpZXJ9IGlzIGRpc2FibGVkIGJ5IFZFTE9DSU9VU19ESVNBQkxFRF9EQVRBQkFTRV9JREVOVElGSUVSU2ApXG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiB0aGlzLnByb3ZpZGVyLmxpc3RUZW5hbnRzICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGVuYW50IGRhdGFiYXNlIHByb3ZpZGVyIGZvciAke3RoaXMuaWRlbnRpZmllcn0gbXVzdCBkZWZpbmUgbGlzdFRlbmFudHNgKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGluaXRpYWxpemUgcnVudGltZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBhcHAgcnVudGltZSBpcyBpbml0aWFsaXplZC5cbiAgICovXG4gIGFzeW5jIGluaXRpYWxpemVSdW50aW1lKCkge1xuICAgIGF3YWl0IHRoaXMuY29uZmlndXJhdGlvbi5pbml0aWFsaXplKHt0eXBlOiBcImRiLXRlbmFudHNcIn0pXG4gIH1cblxuICAvKipcbiAgICogUnVucyBsaXN0IHRlbmFudHMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPEFycmF5PD8+Pn0gLSBUZW5hbnRzLlxuICAgKi9cbiAgYXN5bmMgbGlzdFRlbmFudHMoKSB7XG4gICAgdGhpcy52YWxpZGF0ZVRlbmFudERhdGFiYXNlSWRlbnRpZmllcigpXG4gICAgYXdhaXQgdGhpcy5pbml0aWFsaXplUnVudGltZSgpXG5cbiAgICBjb25zdCB0ZW5hbnRzID0gYXdhaXQgdGhpcy5jb25maWd1cmF0aW9uLmVuc3VyZUNvbm5lY3Rpb25zKHtuYW1lOiBgVGVuYW50IGRhdGFiYXNlIGxpc3Q6ICR7dGhpcy5pZGVudGlmaWVyfWB9LCBhc3luYyAoKSA9PiB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5wcm92aWRlci5saXN0VGVuYW50cyh7XG4gICAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlndXJhdGlvbixcbiAgICAgICAgaWRlbnRpZmllcjogdGhpcy5pZGVudGlmaWVyXG4gICAgICB9KVxuICAgIH0pXG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodGVuYW50cykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGVuYW50IGRhdGFiYXNlIHByb3ZpZGVyIGZvciAke3RoaXMuaWRlbnRpZmllcn0gbXVzdCByZXR1cm4gYW4gYXJyYXkgZnJvbSBsaXN0VGVuYW50c2ApXG4gICAgfVxuXG4gICAgcmV0dXJuIHRlbmFudHNcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGVhY2ggdGVuYW50LlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKHtkYXRhYmFzZUNvbmZpZ3VyYXRpb246IGltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuRGF0YWJhc2VDb25maWd1cmF0aW9uVHlwZSwgdGVuYW50OiA/fSkgOiBQcm9taXNlPHZvaWQ+fSBjYWxsYmFjayAtIENhbGxiYWNrLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxudW1iZXI+fSAtIE51bWJlciBvZiB0ZW5hbnRzIHByb2Nlc3NlZC5cbiAgICovXG4gIGFzeW5jIGVhY2hUZW5hbnQoY2FsbGJhY2spIHtcbiAgICBjb25zdCB0ZW5hbnRzID0gYXdhaXQgdGhpcy5saXN0VGVuYW50cygpXG4gICAgY29uc3QgY29tbWFuZE5hbWUgPSB0aGlzLmNvbW1hbmQucHJvY2Vzc0FyZ3M/LlswXSB8fCBcImRiOnRlbmFudHNcIlxuICAgIGNvbnN0IHBhcmFsbGVsQ291bnQgPSB0aGlzLnBhcmFsbGVsQ291bnQoKVxuICAgIGNvbnN0IHByb2dyZXNzUHJlZml4ID0gYCR7Y29tbWFuZE5hbWV9ICR7dGhpcy5pZGVudGlmaWVyfWBcbiAgICBsZXQgYWN0aXZlVGVuYW50Q291bnQgPSAwXG4gICAgbGV0IGNvbXBsZXRlZFRlbmFudENvdW50ID0gMFxuICAgIGNvbnN0IGl0ZXJhdG9yID0gbmV3IFRlbmFudEl0ZXJhdG9yKHtcbiAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlndXJhdGlvbixcbiAgICAgIGlkZW50aWZpZXI6IHRoaXMuaWRlbnRpZmllcixcbiAgICAgIHBhcmFsbGVsQ291bnRcbiAgICB9KVxuICAgIGNvbnN0IHByb2dyZXNzSGVhcnRiZWF0ID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgdGhpcy5vdXRwdXQoYCR7cHJvZ3Jlc3NQcmVmaXh9OiBoZWFydGJlYXQ6ICR7Y29tcGxldGVkVGVuYW50Q291bnR9LyR7dGVuYW50cy5sZW5ndGh9IGNvbXBsZXRlZCwgJHthY3RpdmVUZW5hbnRDb3VudH0gYWN0aXZlYClcbiAgICB9LCB0aGlzLmhlYXJ0YmVhdEludGVydmFsTXMpXG5cbiAgICBwcm9ncmVzc0hlYXJ0YmVhdC51bnJlZigpXG4gICAgdGhpcy5vdXRwdXQoYCR7cHJvZ3Jlc3NQcmVmaXh9OiBwcm9jZXNzaW5nICR7dGVuYW50cy5sZW5ndGh9IHRlbmFudChzKSB3aXRoIHBhcmFsbGVsaXNtICR7cGFyYWxsZWxDb3VudH1gKVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHByb2Nlc3NlZFRlbmFudENvdW50ID0gYXdhaXQgaXRlcmF0b3IucnVuKHRlbmFudHMsIGFzeW5jIChhcmdzKSA9PiB7XG4gICAgICAgIGFjdGl2ZVRlbmFudENvdW50KytcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGNhbGxiYWNrKGFyZ3MpXG4gICAgICAgICAgY29tcGxldGVkVGVuYW50Q291bnQrK1xuICAgICAgICAgIHRoaXMub3V0cHV0KGAke3Byb2dyZXNzUHJlZml4fTogY29tcGxldGVkICR7VGVuYW50SXRlcmF0b3IudGVuYW50TGFiZWwoYXJncy50ZW5hbnQpfSAoJHtjb21wbGV0ZWRUZW5hbnRDb3VudH0vJHt0ZW5hbnRzLmxlbmd0aH0pYClcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBhY3RpdmVUZW5hbnRDb3VudC0tXG4gICAgICAgIH1cbiAgICAgIH0pXG5cbiAgICAgIHRoaXMub3V0cHV0KGAke3Byb2dyZXNzUHJlZml4fTogZmluaXNoZWQgJHtwcm9jZXNzZWRUZW5hbnRDb3VudH0vJHt0ZW5hbnRzLmxlbmd0aH0gdGVuYW50KHMpYClcblxuICAgICAgcmV0dXJuIHByb2Nlc3NlZFRlbmFudENvdW50XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGNsZWFySW50ZXJ2YWwocHJvZ3Jlc3NIZWFydGJlYXQpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgcGFyYWxsZWwgY291bnQuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IC0gTnVtYmVyIG9mIHRlbmFudHMgdG8gcHJvY2VzcyBjb25jdXJyZW50bHkuXG4gICAqL1xuICBwYXJhbGxlbENvdW50KCkge1xuICAgIGNvbnN0IHBhcnNlZFByb2Nlc3NBcmdzID0gdGhpcy5jb21tYW5kLmFyZ3M/LnBhcnNlZFByb2Nlc3NBcmdzIHx8IHt9XG4gICAgbGV0IHBhcmFsbGVsQXJnID0gcGFyc2VkUHJvY2Vzc0FyZ3MucGFyYWxsZWxcblxuICAgIGlmIChwYXJhbGxlbEFyZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCBwYXJhbGxlbEFyZ0luZGV4ID0gdGhpcy5jb21tYW5kLnByb2Nlc3NBcmdzPy5pbmRleE9mKFwiLS1wYXJhbGxlbFwiKSA/PyAtMVxuXG4gICAgICBpZiAocGFyYWxsZWxBcmdJbmRleCA+PSAwKSB7XG4gICAgICAgIGNvbnN0IG5leHRBcmcgPSB0aGlzLmNvbW1hbmQucHJvY2Vzc0FyZ3M/LltwYXJhbGxlbEFyZ0luZGV4ICsgMV1cblxuICAgICAgICBwYXJhbGxlbEFyZyA9IG5leHRBcmcgJiYgIW5leHRBcmcuc3RhcnRzV2l0aChcIi1cIikgPyBuZXh0QXJnIDogdHJ1ZVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChwYXJhbGxlbEFyZyA9PT0gdW5kZWZpbmVkIHx8IHBhcmFsbGVsQXJnID09PSBmYWxzZSkgcmV0dXJuIDFcbiAgICBpZiAocGFyYWxsZWxBcmcgPT09IHRydWUpIHJldHVybiAyMFxuXG4gICAgY29uc3QgcGFyYWxsZWxDb3VudCA9IE51bWJlcihwYXJhbGxlbEFyZylcblxuICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihwYXJhbGxlbENvdW50KSB8fCBwYXJhbGxlbENvdW50IDwgMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAtLXBhcmFsbGVsIG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyIHdoZW4gYSB2YWx1ZSBpcyBwcm92aWRlZDogJHtwYXJhbGxlbEFyZ31gKVxuICAgIH1cblxuICAgIHJldHVybiBwYXJhbGxlbENvdW50XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Loads a database structure SQL dump into a connection in one pass. Foreign keys are
3
+ * disabled around the load so tables can be created in any order, and the driver's
4
+ * native multi-statement `exec` is used when available (a single round-trip) instead
5
+ * of issuing every statement separately. This is much faster than materializing a
6
+ * schema table by table (e.g. cloning), so it is the preferred way to provision a
7
+ * tenant/test database from a structure dump.
8
+ *
9
+ * Used by the `db:schema:load` CLI command and reusable by any caller that needs to
10
+ * apply a structure dump to a specific connection.
11
+ */
12
+ export default class StructureSqlLoader {
13
+ /**
14
+ * Loads `structureSql` into `db`.
15
+ * @param {object} args - Options object.
16
+ * @param {import("./drivers/base.js").default} args.db - Target database connection.
17
+ * @param {string} args.structureSql - Structure SQL to load.
18
+ * @returns {Promise<void>} - Resolves when the structure has been loaded.
19
+ */
20
+ load({ db, structureSql }: {
21
+ db: import("./drivers/base.js").default;
22
+ structureSql: string;
23
+ }): Promise<void>;
24
+ /**
25
+ * Returns the underlying connection when it exposes a native multi-statement
26
+ * `exec` (a single round-trip for the whole dump), otherwise undefined so the
27
+ * caller falls back to per-statement execution.
28
+ * @param {import("./drivers/base.js").default} db - Database connection.
29
+ * @returns {{exec: (sql: string) => Promise<?>} | undefined} - Connection with exec support.
30
+ */
31
+ executableConnection(db: import("./drivers/base.js").default): {
32
+ exec: (sql: string) => Promise<unknown>;
33
+ } | undefined;
34
+ }
35
+ //# sourceMappingURL=structure-sql-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure-sql-loader.d.ts","sourceRoot":"","sources":["../../../src/database/structure-sql-loader.js"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AACH;IACE;;;;;;OAMG;IACH,2BAJG;QAAkD,EAAE,EAA5C,OAAO,mBAAmB,EAAE,OAAO;QACtB,YAAY,EAAzB,MAAM;KACd,GAAU,OAAO,CAAC,IAAI,CAAC,CA6BzB;IAED;;;;;;OAMG;IACH,yBAHW,OAAO,mBAAmB,EAAE,OAAO,GACjC;QAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAC,CAAC,CAAA;KAAC,GAAG,SAAS,CAS3D;CACF"}
@@ -0,0 +1,63 @@
1
+ // @ts-check
2
+ import splitSqlStatements from "../utils/split-sql-statements.js";
3
+ /**
4
+ * Loads a database structure SQL dump into a connection in one pass. Foreign keys are
5
+ * disabled around the load so tables can be created in any order, and the driver's
6
+ * native multi-statement `exec` is used when available (a single round-trip) instead
7
+ * of issuing every statement separately. This is much faster than materializing a
8
+ * schema table by table (e.g. cloning), so it is the preferred way to provision a
9
+ * tenant/test database from a structure dump.
10
+ *
11
+ * Used by the `db:schema:load` CLI command and reusable by any caller that needs to
12
+ * apply a structure dump to a specific connection.
13
+ */
14
+ export default class StructureSqlLoader {
15
+ /**
16
+ * Loads `structureSql` into `db`.
17
+ * @param {object} args - Options object.
18
+ * @param {import("./drivers/base.js").default} args.db - Target database connection.
19
+ * @param {string} args.structureSql - Structure SQL to load.
20
+ * @returns {Promise<void>} - Resolves when the structure has been loaded.
21
+ */
22
+ async load({ db, structureSql }) {
23
+ const statements = splitSqlStatements(structureSql);
24
+ if (statements.length == 0)
25
+ return;
26
+ const executableConnection = this.executableConnection(db);
27
+ await db.disableForeignKeys();
28
+ try {
29
+ if (executableConnection) {
30
+ await executableConnection.exec(structureSql);
31
+ }
32
+ else {
33
+ for (const statement of statements) {
34
+ await db.query(statement);
35
+ }
36
+ }
37
+ }
38
+ finally {
39
+ await db.enableForeignKeys();
40
+ // The native `exec` path mutates the schema outside `Base#query`, so the
41
+ // usual post-DDL schema-cache invalidation never runs. Clear it here so a
42
+ // caller that read schema metadata before provisioning (e.g. an empty table
43
+ // list) does not keep seeing the pre-load schema afterwards. Harmless for the
44
+ // per-statement path, which already invalidates as each DDL statement runs.
45
+ db.clearSchemaCache();
46
+ }
47
+ }
48
+ /**
49
+ * Returns the underlying connection when it exposes a native multi-statement
50
+ * `exec` (a single round-trip for the whole dump), otherwise undefined so the
51
+ * caller falls back to per-statement execution.
52
+ * @param {import("./drivers/base.js").default} db - Database connection.
53
+ * @returns {{exec: (sql: string) => Promise<?>} | undefined} - Connection with exec support.
54
+ */
55
+ executableConnection(db) {
56
+ const dbWithConnection = /** @type {import("./drivers/base.js").default & {connection?: ?}} */ (db);
57
+ const connection = dbWithConnection.connection;
58
+ if (connection && typeof connection == "object" && "exec" in connection && typeof connection.exec == "function") {
59
+ return /** @type {{exec: (sql: string) => Promise<?>}} */ (connection);
60
+ }
61
+ }
62
+ }
63
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RydWN0dXJlLXNxbC1sb2FkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZGF0YWJhc2Uvc3RydWN0dXJlLXNxbC1sb2FkZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sa0JBQWtCLE1BQU0sa0NBQWtDLENBQUE7QUFFakU7Ozs7Ozs7Ozs7R0FVRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sa0JBQWtCO0lBQ3JDOzs7Ozs7T0FNRztJQUNILEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBQyxFQUFFLEVBQUUsWUFBWSxFQUFDO1FBQzNCLE1BQU0sVUFBVSxHQUFHLGtCQUFrQixDQUFDLFlBQVksQ0FBQyxDQUFBO1FBRW5ELElBQUksVUFBVSxDQUFDLE1BQU0sSUFBSSxDQUFDO1lBQUUsT0FBTTtRQUVsQyxNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUUxRCxNQUFNLEVBQUUsQ0FBQyxrQkFBa0IsRUFBRSxDQUFBO1FBRTdCLElBQUksQ0FBQztZQUNILElBQUksb0JBQW9CLEVBQUUsQ0FBQztnQkFDekIsTUFBTSxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUE7WUFDL0MsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLEtBQUssTUFBTSxTQUFTLElBQUksVUFBVSxFQUFFLENBQUM7b0JBQ25DLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQTtnQkFDM0IsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO2dCQUFTLENBQUM7WUFDVCxNQUFNLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxDQUFBO1lBRTVCLHlFQUF5RTtZQUN6RSwwRUFBMEU7WUFDMUUsNEVBQTRFO1lBQzVFLDhFQUE4RTtZQUM5RSw0RUFBNEU7WUFDNUUsRUFBRSxDQUFDLGdCQUFnQixFQUFFLENBQUE7UUFDdkIsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSCxvQkFBb0IsQ0FBQyxFQUFFO1FBQ3JCLE1BQU0sZ0JBQWdCLEdBQUcscUVBQXFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUNuRyxNQUFNLFVBQVUsR0FBRyxnQkFBZ0IsQ0FBQyxVQUFVLENBQUE7UUFFOUMsSUFBSSxVQUFVLElBQUksT0FBTyxVQUFVLElBQUksUUFBUSxJQUFJLE1BQU0sSUFBSSxVQUFVLElBQUksT0FBTyxVQUFVLENBQUMsSUFBSSxJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ2hILE9BQU8sa0RBQWtELENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUN4RSxDQUFDO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBzcGxpdFNxbFN0YXRlbWVudHMgZnJvbSBcIi4uL3V0aWxzL3NwbGl0LXNxbC1zdGF0ZW1lbnRzLmpzXCJcblxuLyoqXG4gKiBMb2FkcyBhIGRhdGFiYXNlIHN0cnVjdHVyZSBTUUwgZHVtcCBpbnRvIGEgY29ubmVjdGlvbiBpbiBvbmUgcGFzcy4gRm9yZWlnbiBrZXlzIGFyZVxuICogZGlzYWJsZWQgYXJvdW5kIHRoZSBsb2FkIHNvIHRhYmxlcyBjYW4gYmUgY3JlYXRlZCBpbiBhbnkgb3JkZXIsIGFuZCB0aGUgZHJpdmVyJ3NcbiAqIG5hdGl2ZSBtdWx0aS1zdGF0ZW1lbnQgYGV4ZWNgIGlzIHVzZWQgd2hlbiBhdmFpbGFibGUgKGEgc2luZ2xlIHJvdW5kLXRyaXApIGluc3RlYWRcbiAqIG9mIGlzc3VpbmcgZXZlcnkgc3RhdGVtZW50IHNlcGFyYXRlbHkuIFRoaXMgaXMgbXVjaCBmYXN0ZXIgdGhhbiBtYXRlcmlhbGl6aW5nIGFcbiAqIHNjaGVtYSB0YWJsZSBieSB0YWJsZSAoZS5nLiBjbG9uaW5nKSwgc28gaXQgaXMgdGhlIHByZWZlcnJlZCB3YXkgdG8gcHJvdmlzaW9uIGFcbiAqIHRlbmFudC90ZXN0IGRhdGFiYXNlIGZyb20gYSBzdHJ1Y3R1cmUgZHVtcC5cbiAqXG4gKiBVc2VkIGJ5IHRoZSBgZGI6c2NoZW1hOmxvYWRgIENMSSBjb21tYW5kIGFuZCByZXVzYWJsZSBieSBhbnkgY2FsbGVyIHRoYXQgbmVlZHMgdG9cbiAqIGFwcGx5IGEgc3RydWN0dXJlIGR1bXAgdG8gYSBzcGVjaWZpYyBjb25uZWN0aW9uLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTdHJ1Y3R1cmVTcWxMb2FkZXIge1xuICAvKipcbiAgICogTG9hZHMgYHN0cnVjdHVyZVNxbGAgaW50byBgZGJgLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMgb2JqZWN0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHR9IGFyZ3MuZGIgLSBUYXJnZXQgZGF0YWJhc2UgY29ubmVjdGlvbi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3Muc3RydWN0dXJlU3FsIC0gU3RydWN0dXJlIFNRTCB0byBsb2FkLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIHRoZSBzdHJ1Y3R1cmUgaGFzIGJlZW4gbG9hZGVkLlxuICAgKi9cbiAgYXN5bmMgbG9hZCh7ZGIsIHN0cnVjdHVyZVNxbH0pIHtcbiAgICBjb25zdCBzdGF0ZW1lbnRzID0gc3BsaXRTcWxTdGF0ZW1lbnRzKHN0cnVjdHVyZVNxbClcblxuICAgIGlmIChzdGF0ZW1lbnRzLmxlbmd0aCA9PSAwKSByZXR1cm5cblxuICAgIGNvbnN0IGV4ZWN1dGFibGVDb25uZWN0aW9uID0gdGhpcy5leGVjdXRhYmxlQ29ubmVjdGlvbihkYilcblxuICAgIGF3YWl0IGRiLmRpc2FibGVGb3JlaWduS2V5cygpXG5cbiAgICB0cnkge1xuICAgICAgaWYgKGV4ZWN1dGFibGVDb25uZWN0aW9uKSB7XG4gICAgICAgIGF3YWl0IGV4ZWN1dGFibGVDb25uZWN0aW9uLmV4ZWMoc3RydWN0dXJlU3FsKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2Ygc3RhdGVtZW50cykge1xuICAgICAgICAgIGF3YWl0IGRiLnF1ZXJ5KHN0YXRlbWVudClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCBkYi5lbmFibGVGb3JlaWduS2V5cygpXG5cbiAgICAgIC8vIFRoZSBuYXRpdmUgYGV4ZWNgIHBhdGggbXV0YXRlcyB0aGUgc2NoZW1hIG91dHNpZGUgYEJhc2UjcXVlcnlgLCBzbyB0aGVcbiAgICAgIC8vIHVzdWFsIHBvc3QtRERMIHNjaGVtYS1jYWNoZSBpbnZhbGlkYXRpb24gbmV2ZXIgcnVucy4gQ2xlYXIgaXQgaGVyZSBzbyBhXG4gICAgICAvLyBjYWxsZXIgdGhhdCByZWFkIHNjaGVtYSBtZXRhZGF0YSBiZWZvcmUgcHJvdmlzaW9uaW5nIChlLmcuIGFuIGVtcHR5IHRhYmxlXG4gICAgICAvLyBsaXN0KSBkb2VzIG5vdCBrZWVwIHNlZWluZyB0aGUgcHJlLWxvYWQgc2NoZW1hIGFmdGVyd2FyZHMuIEhhcm1sZXNzIGZvciB0aGVcbiAgICAgIC8vIHBlci1zdGF0ZW1lbnQgcGF0aCwgd2hpY2ggYWxyZWFkeSBpbnZhbGlkYXRlcyBhcyBlYWNoIERETCBzdGF0ZW1lbnQgcnVucy5cbiAgICAgIGRiLmNsZWFyU2NoZW1hQ2FjaGUoKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB1bmRlcmx5aW5nIGNvbm5lY3Rpb24gd2hlbiBpdCBleHBvc2VzIGEgbmF0aXZlIG11bHRpLXN0YXRlbWVudFxuICAgKiBgZXhlY2AgKGEgc2luZ2xlIHJvdW5kLXRyaXAgZm9yIHRoZSB3aG9sZSBkdW1wKSwgb3RoZXJ3aXNlIHVuZGVmaW5lZCBzbyB0aGVcbiAgICogY2FsbGVyIGZhbGxzIGJhY2sgdG8gcGVyLXN0YXRlbWVudCBleGVjdXRpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9kcml2ZXJzL2Jhc2UuanNcIikuZGVmYXVsdH0gZGIgLSBEYXRhYmFzZSBjb25uZWN0aW9uLlxuICAgKiBAcmV0dXJucyB7e2V4ZWM6IChzcWw6IHN0cmluZykgPT4gUHJvbWlzZTw/Pn0gfCB1bmRlZmluZWR9IC0gQ29ubmVjdGlvbiB3aXRoIGV4ZWMgc3VwcG9ydC5cbiAgICovXG4gIGV4ZWN1dGFibGVDb25uZWN0aW9uKGRiKSB7XG4gICAgY29uc3QgZGJXaXRoQ29ubmVjdGlvbiA9IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9kcml2ZXJzL2Jhc2UuanNcIikuZGVmYXVsdCAmIHtjb25uZWN0aW9uPzogP319ICovIChkYilcbiAgICBjb25zdCBjb25uZWN0aW9uID0gZGJXaXRoQ29ubmVjdGlvbi5jb25uZWN0aW9uXG5cbiAgICBpZiAoY29ubmVjdGlvbiAmJiB0eXBlb2YgY29ubmVjdGlvbiA9PSBcIm9iamVjdFwiICYmIFwiZXhlY1wiIGluIGNvbm5lY3Rpb24gJiYgdHlwZW9mIGNvbm5lY3Rpb24uZXhlYyA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHJldHVybiAvKiogQHR5cGUge3tleGVjOiAoc3FsOiBzdHJpbmcpID0+IFByb21pc2U8Pz59fSAqLyAoY29ubmVjdGlvbilcbiAgICB9XG4gIH1cbn1cbiJdfQ==
@@ -4,25 +4,6 @@ export default class DbSchemaLoad extends BaseCommand {
4
4
  * Runs execute.
5
5
  * @returns {Promise<void>} */
6
6
  execute(): Promise<void>;
7
- /**
8
- * Runs load structure sql.
9
- * @param {object} args - Options object.
10
- * @param {import("../../../../../../database/drivers/base.js").default} args.db - Database connection.
11
- * @param {string} args.structureSql - Structure SQL to load.
12
- * @returns {Promise<void>} - Resolves when complete.
13
- */
14
- loadStructureSql({ db, structureSql }: {
15
- db: import("../../../../../../database/drivers/base.js").default;
16
- structureSql: string;
17
- }): Promise<void>;
18
- /**
19
- * Runs executable connection.
20
- * @param {import("../../../../../../database/drivers/base.js").default} db - Database connection.
21
- * @returns {{exec: (sql: string) => Promise<?>} | undefined} - Connection with exec support.
22
- */
23
- executableConnection(db: import("../../../../../../database/drivers/base.js").default): {
24
- exec: (sql: string) => Promise<unknown>;
25
- } | undefined;
26
7
  }
27
8
  import BaseCommand from "../../../../../../cli/base-command.js";
28
9
  //# sourceMappingURL=load.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../../../../../../../src/environment-handlers/node/cli/commands/db/schema/load.js"],"names":[],"mappings":"AAKA,2DAA2D;AAC3D;IACE;;kCAE8B;IAC9B,WADa,OAAO,CAAC,IAAI,CAAC,CAazB;IAED;;;;;;OAMG;IACH,uCAJG;QAA2E,EAAE,EAArE,OAAO,4CAA4C,EAAE,OAAO;QAC/C,YAAY,EAAzB,MAAM;KACd,GAAU,OAAO,CAAC,IAAI,CAAC,CAsBzB;IAED;;;;OAIG;IACH,yBAHW,OAAO,4CAA4C,EAAE,OAAO,GAC1D;QAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAC,CAAC,CAAA;KAAC,GAAG,SAAS,CAS3D;CACF;wBAlEuB,uCAAuC"}
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../../../../../../../src/environment-handlers/node/cli/commands/db/schema/load.js"],"names":[],"mappings":"AAKA,2DAA2D;AAC3D;IACE;;kCAE8B;IAC9B,WADa,OAAO,CAAC,IAAI,CAAC,CAczB;CACF;wBAxBuB,uCAAuC"}
@@ -1,7 +1,7 @@
1
1
  import BaseCommand from "../../../../../../cli/base-command.js";
2
2
  import fs from "fs/promises";
3
3
  import path from "path";
4
- import splitSqlStatements from "../../../../../../utils/split-sql-statements.js";
4
+ import StructureSqlLoader from "../../../../../../database/structure-sql-loader.js";
5
5
  /** Node CLI command for loading DB structure SQL files. */
6
6
  export default class DbSchemaLoad extends BaseCommand {
7
7
  /**
@@ -10,52 +10,14 @@ export default class DbSchemaLoad extends BaseCommand {
10
10
  async execute() {
11
11
  await this.getConfiguration().ensureConnections({ name: "DB schema load" }, async (dbs) => {
12
12
  const dbDir = path.join(this.directory(), "db");
13
+ const loader = new StructureSqlLoader();
13
14
  for (const identifier of Object.keys(dbs)) {
14
15
  const db = dbs[identifier];
15
16
  const structureFilePath = path.join(dbDir, `structure-${identifier}.sql`);
16
17
  const structureSql = await fs.readFile(structureFilePath, "utf8");
17
- await this.loadStructureSql({ db, structureSql });
18
+ await loader.load({ db, structureSql });
18
19
  }
19
20
  });
20
21
  }
21
- /**
22
- * Runs load structure sql.
23
- * @param {object} args - Options object.
24
- * @param {import("../../../../../../database/drivers/base.js").default} args.db - Database connection.
25
- * @param {string} args.structureSql - Structure SQL to load.
26
- * @returns {Promise<void>} - Resolves when complete.
27
- */
28
- async loadStructureSql({ db, structureSql }) {
29
- const statements = splitSqlStatements(structureSql);
30
- if (statements.length == 0)
31
- return;
32
- const executableConnection = this.executableConnection(db);
33
- await db.disableForeignKeys();
34
- try {
35
- if (executableConnection) {
36
- await executableConnection.exec(structureSql);
37
- }
38
- else {
39
- for (const statement of statements) {
40
- await db.query(statement);
41
- }
42
- }
43
- }
44
- finally {
45
- await db.enableForeignKeys();
46
- }
47
- }
48
- /**
49
- * Runs executable connection.
50
- * @param {import("../../../../../../database/drivers/base.js").default} db - Database connection.
51
- * @returns {{exec: (sql: string) => Promise<?>} | undefined} - Connection with exec support.
52
- */
53
- executableConnection(db) {
54
- const dbWithConnection = /** @type {import("../../../../../../database/drivers/base.js").default & {connection?: ?}} */ (db);
55
- const connection = dbWithConnection.connection;
56
- if (connection && typeof connection == "object" && "exec" in connection && typeof connection.exec == "function") {
57
- return /** @type {{exec: (sql: string) => Promise<?>}} */ (connection);
58
- }
59
- }
60
22
  }
61
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9lbnZpcm9ubWVudC1oYW5kbGVycy9ub2RlL2NsaS9jb21tYW5kcy9kYi9zY2hlbWEvbG9hZC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLFdBQVcsTUFBTSx1Q0FBdUMsQ0FBQTtBQUMvRCxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDNUIsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBQ3ZCLE9BQU8sa0JBQWtCLE1BQU0saURBQWlELENBQUE7QUFFaEYsMkRBQTJEO0FBQzNELE1BQU0sQ0FBQyxPQUFPLE9BQU8sWUFBYSxTQUFRLFdBQVc7SUFDbkQ7O2tDQUU4QjtJQUM5QixLQUFLLENBQUMsT0FBTztRQUNYLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsaUJBQWlCLENBQUMsRUFBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUMsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUU7WUFDdEYsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUE7WUFFL0MsS0FBSyxNQUFNLFVBQVUsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQzFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQTtnQkFDMUIsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxhQUFhLFVBQVUsTUFBTSxDQUFDLENBQUE7Z0JBQ3pFLE1BQU0sWUFBWSxHQUFHLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsRUFBRSxNQUFNLENBQUMsQ0FBQTtnQkFFakUsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBQyxFQUFFLEVBQUUsWUFBWSxFQUFDLENBQUMsQ0FBQTtZQUNqRCxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsS0FBSyxDQUFDLGdCQUFnQixDQUFDLEVBQUMsRUFBRSxFQUFFLFlBQVksRUFBQztRQUN2QyxNQUFNLFVBQVUsR0FBRyxrQkFBa0IsQ0FBQyxZQUFZLENBQUMsQ0FBQTtRQUVuRCxJQUFJLFVBQVUsQ0FBQyxNQUFNLElBQUksQ0FBQztZQUFFLE9BQU07UUFFbEMsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsRUFBRSxDQUFDLENBQUE7UUFFMUQsTUFBTSxFQUFFLENBQUMsa0JBQWtCLEVBQUUsQ0FBQTtRQUU3QixJQUFJLENBQUM7WUFDSCxJQUFJLG9CQUFvQixFQUFFLENBQUM7Z0JBQ3pCLE1BQU0sb0JBQW9CLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFBO1lBQy9DLENBQUM7aUJBQU0sQ0FBQztnQkFDTixLQUFLLE1BQU0sU0FBUyxJQUFJLFVBQVUsRUFBRSxDQUFDO29CQUNuQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUE7Z0JBQzNCLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsTUFBTSxFQUFFLENBQUMsaUJBQWlCLEVBQUUsQ0FBQTtRQUM5QixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxvQkFBb0IsQ0FBQyxFQUFFO1FBQ3JCLE1BQU0sZ0JBQWdCLEdBQUcsOEZBQThGLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUM1SCxNQUFNLFVBQVUsR0FBRyxnQkFBZ0IsQ0FBQyxVQUFVLENBQUE7UUFFOUMsSUFBSSxVQUFVLElBQUksT0FBTyxVQUFVLElBQUksUUFBUSxJQUFJLE1BQU0sSUFBSSxVQUFVLElBQUksT0FBTyxVQUFVLENBQUMsSUFBSSxJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ2hILE9BQU8sa0RBQWtELENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUN4RSxDQUFDO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IEJhc2VDb21tYW5kIGZyb20gXCIuLi8uLi8uLi8uLi8uLi8uLi9jbGkvYmFzZS1jb21tYW5kLmpzXCJcbmltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIlxuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIlxuaW1wb3J0IHNwbGl0U3FsU3RhdGVtZW50cyBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vLi4vdXRpbHMvc3BsaXQtc3FsLXN0YXRlbWVudHMuanNcIlxuXG4vKiogTm9kZSBDTEkgY29tbWFuZCBmb3IgbG9hZGluZyBEQiBzdHJ1Y3R1cmUgU1FMIGZpbGVzLiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRGJTY2hlbWFMb2FkIGV4dGVuZHMgQmFzZUNvbW1hbmQge1xuICAvKipcbiAgICogUnVucyBleGVjdXRlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gKi9cbiAgYXN5bmMgZXhlY3V0ZSgpIHtcbiAgICBhd2FpdCB0aGlzLmdldENvbmZpZ3VyYXRpb24oKS5lbnN1cmVDb25uZWN0aW9ucyh7bmFtZTogXCJEQiBzY2hlbWEgbG9hZFwifSwgYXN5bmMgKGRicykgPT4ge1xuICAgICAgY29uc3QgZGJEaXIgPSBwYXRoLmpvaW4odGhpcy5kaXJlY3RvcnkoKSwgXCJkYlwiKVxuXG4gICAgICBmb3IgKGNvbnN0IGlkZW50aWZpZXIgb2YgT2JqZWN0LmtleXMoZGJzKSkge1xuICAgICAgICBjb25zdCBkYiA9IGRic1tpZGVudGlmaWVyXVxuICAgICAgICBjb25zdCBzdHJ1Y3R1cmVGaWxlUGF0aCA9IHBhdGguam9pbihkYkRpciwgYHN0cnVjdHVyZS0ke2lkZW50aWZpZXJ9LnNxbGApXG4gICAgICAgIGNvbnN0IHN0cnVjdHVyZVNxbCA9IGF3YWl0IGZzLnJlYWRGaWxlKHN0cnVjdHVyZUZpbGVQYXRoLCBcInV0ZjhcIilcblxuICAgICAgICBhd2FpdCB0aGlzLmxvYWRTdHJ1Y3R1cmVTcWwoe2RiLCBzdHJ1Y3R1cmVTcWx9KVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogUnVucyBsb2FkIHN0cnVjdHVyZSBzcWwuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucyBvYmplY3QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vLi4vLi4vLi4vLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHR9IGFyZ3MuZGIgLSBEYXRhYmFzZSBjb25uZWN0aW9uLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy5zdHJ1Y3R1cmVTcWwgLSBTdHJ1Y3R1cmUgU1FMIHRvIGxvYWQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuXG4gICAqL1xuICBhc3luYyBsb2FkU3RydWN0dXJlU3FsKHtkYiwgc3RydWN0dXJlU3FsfSkge1xuICAgIGNvbnN0IHN0YXRlbWVudHMgPSBzcGxpdFNxbFN0YXRlbWVudHMoc3RydWN0dXJlU3FsKVxuXG4gICAgaWYgKHN0YXRlbWVudHMubGVuZ3RoID09IDApIHJldHVyblxuXG4gICAgY29uc3QgZXhlY3V0YWJsZUNvbm5lY3Rpb24gPSB0aGlzLmV4ZWN1dGFibGVDb25uZWN0aW9uKGRiKVxuXG4gICAgYXdhaXQgZGIuZGlzYWJsZUZvcmVpZ25LZXlzKClcblxuICAgIHRyeSB7XG4gICAgICBpZiAoZXhlY3V0YWJsZUNvbm5lY3Rpb24pIHtcbiAgICAgICAgYXdhaXQgZXhlY3V0YWJsZUNvbm5lY3Rpb24uZXhlYyhzdHJ1Y3R1cmVTcWwpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmb3IgKGNvbnN0IHN0YXRlbWVudCBvZiBzdGF0ZW1lbnRzKSB7XG4gICAgICAgICAgYXdhaXQgZGIucXVlcnkoc3RhdGVtZW50KVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGF3YWl0IGRiLmVuYWJsZUZvcmVpZ25LZXlzKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBleGVjdXRhYmxlIGNvbm5lY3Rpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vLi4vLi4vLi4vLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHR9IGRiIC0gRGF0YWJhc2UgY29ubmVjdGlvbi5cbiAgICogQHJldHVybnMge3tleGVjOiAoc3FsOiBzdHJpbmcpID0+IFByb21pc2U8Pz59IHwgdW5kZWZpbmVkfSAtIENvbm5lY3Rpb24gd2l0aCBleGVjIHN1cHBvcnQuXG4gICAqL1xuICBleGVjdXRhYmxlQ29ubmVjdGlvbihkYikge1xuICAgIGNvbnN0IGRiV2l0aENvbm5lY3Rpb24gPSAvKiogQHR5cGUge2ltcG9ydChcIi4uLy4uLy4uLy4uLy4uLy4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0ICYge2Nvbm5lY3Rpb24/OiA/fX0gKi8gKGRiKVxuICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBkYldpdGhDb25uZWN0aW9uLmNvbm5lY3Rpb25cblxuICAgIGlmIChjb25uZWN0aW9uICYmIHR5cGVvZiBjb25uZWN0aW9uID09IFwib2JqZWN0XCIgJiYgXCJleGVjXCIgaW4gY29ubmVjdGlvbiAmJiB0eXBlb2YgY29ubmVjdGlvbi5leGVjID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgcmV0dXJuIC8qKiBAdHlwZSB7e2V4ZWM6IChzcWw6IHN0cmluZykgPT4gUHJvbWlzZTw/Pn19ICovIChjb25uZWN0aW9uKVxuICAgIH1cbiAgfVxufVxuIl19
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9lbnZpcm9ubWVudC1oYW5kbGVycy9ub2RlL2NsaS9jb21tYW5kcy9kYi9zY2hlbWEvbG9hZC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLFdBQVcsTUFBTSx1Q0FBdUMsQ0FBQTtBQUMvRCxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDNUIsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBQ3ZCLE9BQU8sa0JBQWtCLE1BQU0sb0RBQW9ELENBQUE7QUFFbkYsMkRBQTJEO0FBQzNELE1BQU0sQ0FBQyxPQUFPLE9BQU8sWUFBYSxTQUFRLFdBQVc7SUFDbkQ7O2tDQUU4QjtJQUM5QixLQUFLLENBQUMsT0FBTztRQUNYLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsaUJBQWlCLENBQUMsRUFBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUMsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUU7WUFDdEYsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUE7WUFDL0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxrQkFBa0IsRUFBRSxDQUFBO1lBRXZDLEtBQUssTUFBTSxVQUFVLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUMxQyxNQUFNLEVBQUUsR0FBRyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUE7Z0JBQzFCLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsYUFBYSxVQUFVLE1BQU0sQ0FBQyxDQUFBO2dCQUN6RSxNQUFNLFlBQVksR0FBRyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsaUJBQWlCLEVBQUUsTUFBTSxDQUFDLENBQUE7Z0JBRWpFLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFDLEVBQUUsRUFBRSxZQUFZLEVBQUMsQ0FBQyxDQUFBO1lBQ3ZDLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBCYXNlQ29tbWFuZCBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vLi4vY2xpL2Jhc2UtY29tbWFuZC5qc1wiXG5pbXBvcnQgZnMgZnJvbSBcImZzL3Byb21pc2VzXCJcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCJcbmltcG9ydCBTdHJ1Y3R1cmVTcWxMb2FkZXIgZnJvbSBcIi4uLy4uLy4uLy4uLy4uLy4uL2RhdGFiYXNlL3N0cnVjdHVyZS1zcWwtbG9hZGVyLmpzXCJcblxuLyoqIE5vZGUgQ0xJIGNvbW1hbmQgZm9yIGxvYWRpbmcgREIgc3RydWN0dXJlIFNRTCBmaWxlcy4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIERiU2NoZW1hTG9hZCBleHRlbmRzIEJhc2VDb21tYW5kIHtcbiAgLyoqXG4gICAqIFJ1bnMgZXhlY3V0ZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59ICovXG4gIGFzeW5jIGV4ZWN1dGUoKSB7XG4gICAgYXdhaXQgdGhpcy5nZXRDb25maWd1cmF0aW9uKCkuZW5zdXJlQ29ubmVjdGlvbnMoe25hbWU6IFwiREIgc2NoZW1hIGxvYWRcIn0sIGFzeW5jIChkYnMpID0+IHtcbiAgICAgIGNvbnN0IGRiRGlyID0gcGF0aC5qb2luKHRoaXMuZGlyZWN0b3J5KCksIFwiZGJcIilcbiAgICAgIGNvbnN0IGxvYWRlciA9IG5ldyBTdHJ1Y3R1cmVTcWxMb2FkZXIoKVxuXG4gICAgICBmb3IgKGNvbnN0IGlkZW50aWZpZXIgb2YgT2JqZWN0LmtleXMoZGJzKSkge1xuICAgICAgICBjb25zdCBkYiA9IGRic1tpZGVudGlmaWVyXVxuICAgICAgICBjb25zdCBzdHJ1Y3R1cmVGaWxlUGF0aCA9IHBhdGguam9pbihkYkRpciwgYHN0cnVjdHVyZS0ke2lkZW50aWZpZXJ9LnNxbGApXG4gICAgICAgIGNvbnN0IHN0cnVjdHVyZVNxbCA9IGF3YWl0IGZzLnJlYWRGaWxlKHN0cnVjdHVyZUZpbGVQYXRoLCBcInV0ZjhcIilcblxuICAgICAgICBhd2FpdCBsb2FkZXIubG9hZCh7ZGIsIHN0cnVjdHVyZVNxbH0pXG4gICAgICB9XG4gICAgfSlcbiAgfVxufVxuIl19
@@ -1 +1 @@
1
- {"version":3,"file":"tenant-iterator.d.ts","sourceRoot":"","sources":["../../../src/tenants/tenant-iterator.js"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH;IAmFE;;;;OAIG;IACH,2BAHW,OAAC,GACC,MAAM,CAYlB;IAjGD;;;OAGG;IACH,0DAFW;QAAC,aAAa,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAC,EAM5G;IAHC,qDAAkC;IAClC,mBAA4B;IAC5B,sBAAkC;IAGpC;;;;;OAKG;IACH,aAJW,KAAK,CAAC,OAAC,CAAC,YACR,CAAS,IAAiG,EAAjG;QAAC,qBAAqB,EAAE,OAAO,2BAA2B,EAAE,yBAAyB,CAAC;QAAC,MAAM,EAAE,OAAC,CAAA;KAAC,KAAI,OAAO,CAAC,IAAI,CAAC,GACzH,OAAO,CAAC,MAAM,CAAC,CAgD3B;IAED;;;;OAIG;IACH,wCAHW;QAAC,QAAQ,EAAE,CAAS,IAAiG,EAAjG;YAAC,qBAAqB,EAAE,OAAO,2BAA2B,EAAE,yBAAyB,CAAC;YAAC,MAAM,EAAE,OAAC,CAAA;SAAC,KAAI,OAAO,CAAC,IAAI,CAAC,CAAC;QAAC,MAAM,EAAE,OAAC,CAAA;KAAC,GAChJ,OAAO,CAAC,IAAI,CAAC,CAazB;CAkBF"}
1
+ {"version":3,"file":"tenant-iterator.d.ts","sourceRoot":"","sources":["../../../src/tenants/tenant-iterator.js"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH;IAmFE;;;;OAIG;IACH,2BAHW,OAAC,GACC,MAAM,CAiBlB;IAtGD;;;OAGG;IACH,0DAFW;QAAC,aAAa,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAC,EAM5G;IAHC,qDAAkC;IAClC,mBAA4B;IAC5B,sBAAkC;IAGpC;;;;;OAKG;IACH,aAJW,KAAK,CAAC,OAAC,CAAC,YACR,CAAS,IAAiG,EAAjG;QAAC,qBAAqB,EAAE,OAAO,2BAA2B,EAAE,yBAAyB,CAAC;QAAC,MAAM,EAAE,OAAC,CAAA;KAAC,KAAI,OAAO,CAAC,IAAI,CAAC,GACzH,OAAO,CAAC,MAAM,CAAC,CAgD3B;IAED;;;;OAIG;IACH,wCAHW;QAAC,QAAQ,EAAE,CAAS,IAAiG,EAAjG;YAAC,qBAAqB,EAAE,OAAO,2BAA2B,EAAE,yBAAyB,CAAC;YAAC,MAAM,EAAE,OAAC,CAAA;SAAC,KAAI,OAAO,CAAC,IAAI,CAAC,CAAC;QAAC,MAAM,EAAE,OAAC,CAAA;KAAC,GAChJ,OAAO,CAAC,IAAI,CAAC,CAazB;CAuBF"}
@@ -84,14 +84,16 @@ export default class TenantIterator {
84
84
  static tenantLabel(tenant) {
85
85
  if (tenant && typeof tenant === "object") {
86
86
  const tenantObject = /** @type {{id?: ?, name?: ?, slug?: ?}} */ (tenant);
87
- if (tenantObject.slug)
88
- return String(tenantObject.slug);
89
- if (tenantObject.name)
90
- return String(tenantObject.name);
91
- if (tenantObject.id)
92
- return String(tenantObject.id);
87
+ for (const attributeName of /** @type {Array<"slug" | "name" | "id">} */ (["slug", "name", "id"])) {
88
+ const attributeOrAccessor = tenantObject[attributeName];
89
+ const attributeValue = typeof attributeOrAccessor === "function"
90
+ ? attributeOrAccessor.call(tenant)
91
+ : attributeOrAccessor;
92
+ if (attributeValue)
93
+ return String(attributeValue);
94
+ }
93
95
  }
94
96
  return JSON.stringify(tenant);
95
97
  }
96
98
  }
97
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVuYW50LWl0ZXJhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RlbmFudHMvdGVuYW50LWl0ZXJhdG9yLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWjs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sY0FBYztJQUNqQzs7O09BR0c7SUFDSCxZQUFZLEVBQUMsYUFBYSxFQUFFLFVBQVUsRUFBRSxhQUFhLEdBQUcsQ0FBQyxFQUFDO1FBQ3hELElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFBO1FBQ2xDLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFBO1FBQzVCLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFBO0lBQ3BDLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVE7UUFDekIsSUFBSSxJQUFJLENBQUMsYUFBYSxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQzVCLEtBQUssTUFBTSxNQUFNLElBQUksT0FBTyxFQUFFLENBQUM7Z0JBQzdCLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLEVBQUMsUUFBUSxFQUFFLE1BQU0sRUFBQyxDQUFDLENBQUE7WUFDbEQsQ0FBQztZQUVELE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQTtRQUN2QixDQUFDO1FBRUQsK0NBQStDO1FBQy9DLE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQTtRQUNuQixNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUE7UUFDbEIsSUFBSSxXQUFXLEdBQUcsQ0FBQyxDQUFBO1FBQ25CLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUE7UUFFaEUsS0FBSyxJQUFJLFdBQVcsR0FBRyxDQUFDLEVBQUUsV0FBVyxHQUFHLFdBQVcsRUFBRSxXQUFXLEVBQUUsRUFB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QU0sQ0FBQyxDQUFBO0lBQy9CLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG4vKipcbiAqIFJ1bnMgYSBjYWxsYmFjayBvbmNlIHdpdGhpbiBlYWNoIHRlbmFudCdzIGNvbnRleHQgZm9yIGEgdGVuYW50IGRhdGFiYXNlIGlkZW50aWZpZXIsXG4gKiBvcHRpb25hbGx5IHNldmVyYWwgdGVuYW50cyBhdCBhIHRpbWUuIEVhY2ggdGVuYW50IGlzIGVudGVyZWQgd2l0aCBgcnVuV2l0aFRlbmFudGAsIGFuZCBhXG4gKiB0ZW5hbnQgd2hvc2UgZGF0YWJhc2UgaWRlbnRpZmllciBpcyBpbmFjdGl2ZSB0aHJvd3MgcmF0aGVyIHRoYW4gcnVubmluZyB0aGUgY2FsbGJhY2tcbiAqIGFnYWluc3QgdGhlIHdyb25nIGNvbm5lY3Rpb24uIFdoZW4gaXRlcmF0aW5nIGluIHBhcmFsbGVsIHRoZSBwZXItdGVuYW50IGZhaWx1cmVzIGFyZVxuICogY29sbGVjdGVkIGFuZCByZXRocm93biB0b2dldGhlciBhcyBhbiBgQWdncmVnYXRlRXJyb3JgIHNvIG9uZSBiYWQgdGVuYW50IGRvZXMgbm90IGhpZGUgdGhlXG4gKiBvdGhlcnMuIFRoaXMgaXMgdGhlIGl0ZXJhdGlvbiBlbmdpbmUgc2hhcmVkIGJ5IHRoZSBgZGI6dGVuYW50czoqYCBDTEkgY29tbWFuZHMgYW5kIHRoZVxuICogcnVudGltZSB0ZW5hbnQgZmHDp2FkZTsgdGhlIGNhbGxlciBpcyByZXNwb25zaWJsZSBmb3IgcHJvZHVjaW5nIHRoZSB0ZW5hbnQgbGlzdC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGVuYW50SXRlcmF0b3Ige1xuICAvKipcbiAgICogQ3JlYXRlcyBhbiBpdGVyYXRvciBib3VuZCB0byBhIGNvbmZpZ3VyYXRpb24gYW5kIHRlbmFudCBkYXRhYmFzZSBpZGVudGlmaWVyLlxuICAgKiBAcGFyYW0ge3tjb25maWd1cmF0aW9uOiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHQsIGlkZW50aWZpZXI6IHN0cmluZywgcGFyYWxsZWxDb3VudD86IG51bWJlcn19IGFyZ3MgLSBUZW5hbnQgY29uZmlndXJhdGlvbiwgZGF0YWJhc2UgaWRlbnRpZmllciwgYW5kIGNvbmN1cnJlbmN5IGxpbWl0LlxuICAgKi9cbiAgY29uc3RydWN0b3Ioe2NvbmZpZ3VyYXRpb24sIGlkZW50aWZpZXIsIHBhcmFsbGVsQ291bnQgPSAxfSkge1xuICAgIHRoaXMuY29uZmlndXJhdGlvbiA9IGNvbmZpZ3VyYXRpb25cbiAgICB0aGlzLmlkZW50aWZpZXIgPSBpZGVudGlmaWVyXG4gICAgdGhpcy5wYXJhbGxlbENvdW50ID0gcGFyYWxsZWxDb3VudFxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgYGNhbGxiYWNrYCB3aXRoaW4gZWFjaCB0ZW5hbnQncyBjb250ZXh0IGFuZCByZXR1cm5zIGhvdyBtYW55IHRlbmFudHMgd2VyZSBwcm9jZXNzZWQuXG4gICAqIEBwYXJhbSB7QXJyYXk8Pz59IHRlbmFudHMgLSBUZW5hbnQgZGVzY3JpcHRvcnMgdG8gZW50ZXIgYW5kIHByb2Nlc3MuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oe2RhdGFiYXNlQ29uZmlndXJhdGlvbjogaW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5EYXRhYmFzZUNvbmZpZ3VyYXRpb25UeXBlLCB0ZW5hbnQ6ID99KSA6IFByb21pc2U8dm9pZD59IGNhbGxiYWNrIC0gUGVyLXRlbmFudCBvcGVyYXRpb24gcmVjZWl2aW5nIHRoZSBhY3RpdmUgZGF0YWJhc2UgY29uZmlndXJhdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8bnVtYmVyPn0gLSBOdW1iZXIgb2YgcHJvY2Vzc2VkIHRlbmFudHMuXG4gICAqL1xuICBhc3luYyBydW4odGVuYW50cywgY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy5wYXJhbGxlbENvdW50IDw9IDEpIHtcbiAgICAgIGZvciAoY29uc3QgdGVuYW50IG9mIHRlbmFudHMpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5ydW5UZW5hbnRDYWxsYmFjayh7Y2FsbGJhY2ssIHRlbmFudH0pXG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0ZW5hbnRzLmxlbmd0aFxuICAgIH1cblxuICAgIC8qKiBAdHlwZSB7QXJyYXk8e2Vycm9yOiBFcnJvciwgdGVuYW50OiA/fT59ICovXG4gICAgY29uc3QgZmFpbHVyZXMgPSBbXVxuICAgIGNvbnN0IHdvcmtlcnMgPSBbXVxuICAgIGxldCB0ZW5hbnRJbmRleCA9IDBcbiAgICBjb25zdCB3b3JrZXJDb3VudCA9IE1hdGgubWluKHRoaXMucGFyYWxsZWxDb3VudCwgdGVuYW50cy5sZW5ndGgpXG5cbiAgICBmb3IgKGxldCB3b3JrZXJJbmRleCA9IDA7IHdvcmtlckluZGV4IDwgd29ya2VyQ291bnQ7IHdvcmtlckluZGV4KyspIHtcbiAgICAgIHdvcmtlcnMucHVzaCgoYXN5bmMgKCkgPT4ge1xuICAgICAgICB3aGlsZSAodGVuYW50SW5kZXggPCB0ZW5hbnRzLmxlbmd0aCkge1xuICAgICAgICAgIGNvbnN0IHRlbmFudCA9IHRlbmFudHNbdGVuYW50SW5kZXhdXG5cbiAgICAgICAgICB0ZW5hbnRJbmRleCsrXG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5ydW5UZW5hbnRDYWxsYmFjayh7Y2FsbGJhY2ssIHRlbmFudH0pXG4gICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGZhaWx1cmVzLnB1c2goe1xuICAgICAgICAgICAgICBlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yIDogbmV3IEVycm9yKFN0cmluZyhlcnJvcikpLFxuICAgICAgICAgICAgICB0ZW5hbnRcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KSgpKVxuICAgIH1cblxuICAgIGF3YWl0IFByb21pc2UuYWxsKHdvcmtlcnMpXG5cbiAgICBpZiAoZmFpbHVyZXMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgZmFpbGVkVGVuYW50TGFiZWxzID0gZmFpbHVyZXMubWFwKChmYWlsdXJlKSA9PiBUZW5hbnRJdGVyYXRvci50ZW5hbnRMYWJlbChmYWlsdXJlLnRlbmFudCkpLmpvaW4oXCIsIFwiKVxuXG4gICAgICB0aHJvdyBuZXcgQWdncmVnYXRlRXJyb3IoXG4gICAgICAgIGZhaWx1cmVzLm1hcCgoZmFpbHVyZSkgPT4gZmFpbHVyZS5lcnJvciksXG4gICAgICAgIGBGYWlsZWQgdGVuYW50IGRhdGFiYXNlIGNvbW1hbmQgZm9yIHRlbmFudChzKTogJHtmYWlsZWRUZW5hbnRMYWJlbHN9YFxuICAgICAgKVxuICAgIH1cblxuICAgIHJldHVybiB0ZW5hbnRzLmxlbmd0aFxuICB9XG5cbiAgLyoqXG4gICAqIEVudGVycyBvbmUgdGVuYW50J3MgY29udGV4dCBhbmQgcnVucyB0aGUgY2FsbGJhY2ssIGFzc2VydGluZyB0aGUgZGF0YWJhc2UgaXMgYWN0aXZlIGZpcnN0LlxuICAgKiBAcGFyYW0ge3tjYWxsYmFjazogZnVuY3Rpb24oe2RhdGFiYXNlQ29uZmlndXJhdGlvbjogaW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5EYXRhYmFzZUNvbmZpZ3VyYXRpb25UeXBlLCB0ZW5hbnQ6ID99KSA6IFByb21pc2U8dm9pZD4sIHRlbmFudDogP319IGFyZ3MgLSBUZW5hbnQgZGVzY3JpcHRvciBhbmQgb3BlcmF0aW9uIHRvIHJ1biBpbiBpdHMgY29udGV4dC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBydW5UZW5hbnRDYWxsYmFjayh7Y2FsbGJhY2ssIHRlbmFudH0pIHtcbiAgICBhd2FpdCB0aGlzLmNvbmZpZ3VyYXRpb24ucnVuV2l0aFRlbmFudCh0ZW5hbnQsIGFzeW5jICgpID0+IHtcbiAgICAgIGlmICghdGhpcy5jb25maWd1cmF0aW9uLmlzRGF0YWJhc2VJZGVudGlmaWVyQWN0aXZlKHRoaXMuaWRlbnRpZmllcikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUZW5hbnQgZGF0YWJhc2UgaWRlbnRpZmllciAke3RoaXMuaWRlbnRpZmllcn0gaXMgaW5hY3RpdmUgZm9yIHRlbmFudDogJHtUZW5hbnRJdGVyYXRvci50ZW5hbnRMYWJlbCh0ZW5hbnQpfWApXG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGNhbGxiYWNrKHtcbiAgICAgICAgZGF0YWJhc2VDb25maWd1cmF0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb24ucmVzb2x2ZURhdGFiYXNlQ29uZmlndXJhdGlvbih0aGlzLmlkZW50aWZpZXIpLFxuICAgICAgICB0ZW5hbnRcbiAgICAgIH0pXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgYSBodW1hbi1yZWFkYWJsZSBsYWJlbCBmb3IgYSB0ZW5hbnQgZm9yIHVzZSBpbiBlcnJvciBtZXNzYWdlcy5cbiAgICogQHBhcmFtIHs/fSB0ZW5hbnQgLSBUZW5hbnQgZGVzY3JpcHRvciB0byBpZGVudGlmeSBpbiBhbiBlcnJvci5cbiAgICogQHJldHVybnMge3N0cmluZ30gLSBIdW1hbi1yZWFkYWJsZSB0ZW5hbnQgbGFiZWwuXG4gICAqL1xuICBzdGF0aWMgdGVuYW50TGFiZWwodGVuYW50KSB7XG4gICAgaWYgKHRlbmFudCAmJiB0eXBlb2YgdGVuYW50ID09PSBcIm9iamVjdFwiKSB7XG4gICAgICBjb25zdCB0ZW5hbnRPYmplY3QgPSAvKiogQHR5cGUge3tpZD86ID8sIG5hbWU/OiA/LCBzbHVnPzogP319ICovICh0ZW5hbnQpXG5cbiAgICAgIGlmICh0ZW5hbnRPYmplY3Quc2x1ZykgcmV0dXJuIFN0cmluZyh0ZW5hbnRPYmplY3Quc2x1ZylcbiAgICAgIGlmICh0ZW5hbnRPYmplY3QubmFtZSkgcmV0dXJuIFN0cmluZyh0ZW5hbnRPYmplY3QubmFtZSlcbiAgICAgIGlmICh0ZW5hbnRPYmplY3QuaWQpIHJldHVybiBTdHJpbmcodGVuYW50T2JqZWN0LmlkKVxuICAgIH1cblxuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh0ZW5hbnQpXG4gIH1cbn1cbiJdfQ==
99
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVuYW50LWl0ZXJhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RlbmFudHMvdGVuYW50LWl0ZXJhdG9yLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWjs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sY0FBYztJQUNqQzs7O09BR0c7SUFDSCxZQUFZLEVBQUMsYUFBYSxFQUFFLFVBQVUsRUFBRSxhQUFhLEdBQUcsQ0FBQyxFQUFDO1FBQ3hELElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFBO1FBQ2xDLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFBO1FBQzVCLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFBO0lBQ3BDLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVE7UUFDekIsSUFBSSxJQUFJLENBQUMsYUFBYSxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQzVCLEtBQUssTUFBTSxNQUFNLElBQUksT0FBTyxFQUFFLENBQUM7Z0JBQzdCLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLEVBQUMsUUFBUSxFQUFFLE1BQU0sRUFBQyxDQUFDLENBQUE7WUFDbEQsQ0FBQztZQUVELE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQTtRQUN2QixDQUFDO1FBRUQsK0NBQStDO1FBQy9DLE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQTtRQUNuQixNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUE7UUFDbEIsSUFBSSxXQUFXLEdBQUcsQ0FBQyxDQUFBO1FBQ25CLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUE7UUFFaEUsS0FBSyxJQUFJLFdBQVcsR0FBRyxDQUFDLEVBQUUsV0FBVyxHQUFHLFdBQVcsRUFBRSxXQUFXLEVBQUUsRUFB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Q0FBQTtnQkFFdkIsSUFBSSxjQUFjO29CQUFFLE9BQU8sTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFBO1lBQ25ELENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQy9CLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG4vKipcbiAqIFJ1bnMgYSBjYWxsYmFjayBvbmNlIHdpdGhpbiBlYWNoIHRlbmFudCdzIGNvbnRleHQgZm9yIGEgdGVuYW50IGRhdGFiYXNlIGlkZW50aWZpZXIsXG4gKiBvcHRpb25hbGx5IHNldmVyYWwgdGVuYW50cyBhdCBhIHRpbWUuIEVhY2ggdGVuYW50IGlzIGVudGVyZWQgd2l0aCBgcnVuV2l0aFRlbmFudGAsIGFuZCBhXG4gKiB0ZW5hbnQgd2hvc2UgZGF0YWJhc2UgaWRlbnRpZmllciBpcyBpbmFjdGl2ZSB0aHJvd3MgcmF0aGVyIHRoYW4gcnVubmluZyB0aGUgY2FsbGJhY2tcbiAqIGFnYWluc3QgdGhlIHdyb25nIGNvbm5lY3Rpb24uIFdoZW4gaXRlcmF0aW5nIGluIHBhcmFsbGVsIHRoZSBwZXItdGVuYW50IGZhaWx1cmVzIGFyZVxuICogY29sbGVjdGVkIGFuZCByZXRocm93biB0b2dldGhlciBhcyBhbiBgQWdncmVnYXRlRXJyb3JgIHNvIG9uZSBiYWQgdGVuYW50IGRvZXMgbm90IGhpZGUgdGhlXG4gKiBvdGhlcnMuIFRoaXMgaXMgdGhlIGl0ZXJhdGlvbiBlbmdpbmUgc2hhcmVkIGJ5IHRoZSBgZGI6dGVuYW50czoqYCBDTEkgY29tbWFuZHMgYW5kIHRoZVxuICogcnVudGltZSB0ZW5hbnQgZmHDp2FkZTsgdGhlIGNhbGxlciBpcyByZXNwb25zaWJsZSBmb3IgcHJvZHVjaW5nIHRoZSB0ZW5hbnQgbGlzdC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGVuYW50SXRlcmF0b3Ige1xuICAvKipcbiAgICogQ3JlYXRlcyBhbiBpdGVyYXRvciBib3VuZCB0byBhIGNvbmZpZ3VyYXRpb24gYW5kIHRlbmFudCBkYXRhYmFzZSBpZGVudGlmaWVyLlxuICAgKiBAcGFyYW0ge3tjb25maWd1cmF0aW9uOiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHQsIGlkZW50aWZpZXI6IHN0cmluZywgcGFyYWxsZWxDb3VudD86IG51bWJlcn19IGFyZ3MgLSBUZW5hbnQgY29uZmlndXJhdGlvbiwgZGF0YWJhc2UgaWRlbnRpZmllciwgYW5kIGNvbmN1cnJlbmN5IGxpbWl0LlxuICAgKi9cbiAgY29uc3RydWN0b3Ioe2NvbmZpZ3VyYXRpb24sIGlkZW50aWZpZXIsIHBhcmFsbGVsQ291bnQgPSAxfSkge1xuICAgIHRoaXMuY29uZmlndXJhdGlvbiA9IGNvbmZpZ3VyYXRpb25cbiAgICB0aGlzLmlkZW50aWZpZXIgPSBpZGVudGlmaWVyXG4gICAgdGhpcy5wYXJhbGxlbENvdW50ID0gcGFyYWxsZWxDb3VudFxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgYGNhbGxiYWNrYCB3aXRoaW4gZWFjaCB0ZW5hbnQncyBjb250ZXh0IGFuZCByZXR1cm5zIGhvdyBtYW55IHRlbmFudHMgd2VyZSBwcm9jZXNzZWQuXG4gICAqIEBwYXJhbSB7QXJyYXk8Pz59IHRlbmFudHMgLSBUZW5hbnQgZGVzY3JpcHRvcnMgdG8gZW50ZXIgYW5kIHByb2Nlc3MuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oe2RhdGFiYXNlQ29uZmlndXJhdGlvbjogaW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5EYXRhYmFzZUNvbmZpZ3VyYXRpb25UeXBlLCB0ZW5hbnQ6ID99KSA6IFByb21pc2U8dm9pZD59IGNhbGxiYWNrIC0gUGVyLXRlbmFudCBvcGVyYXRpb24gcmVjZWl2aW5nIHRoZSBhY3RpdmUgZGF0YWJhc2UgY29uZmlndXJhdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8bnVtYmVyPn0gLSBOdW1iZXIgb2YgcHJvY2Vzc2VkIHRlbmFudHMuXG4gICAqL1xuICBhc3luYyBydW4odGVuYW50cywgY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy5wYXJhbGxlbENvdW50IDw9IDEpIHtcbiAgICAgIGZvciAoY29uc3QgdGVuYW50IG9mIHRlbmFudHMpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5ydW5UZW5hbnRDYWxsYmFjayh7Y2FsbGJhY2ssIHRlbmFudH0pXG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0ZW5hbnRzLmxlbmd0aFxuICAgIH1cblxuICAgIC8qKiBAdHlwZSB7QXJyYXk8e2Vycm9yOiBFcnJvciwgdGVuYW50OiA/fT59ICovXG4gICAgY29uc3QgZmFpbHVyZXMgPSBbXVxuICAgIGNvbnN0IHdvcmtlcnMgPSBbXVxuICAgIGxldCB0ZW5hbnRJbmRleCA9IDBcbiAgICBjb25zdCB3b3JrZXJDb3VudCA9IE1hdGgubWluKHRoaXMucGFyYWxsZWxDb3VudCwgdGVuYW50cy5sZW5ndGgpXG5cbiAgICBmb3IgKGxldCB3b3JrZXJJbmRleCA9IDA7IHdvcmtlckluZGV4IDwgd29ya2VyQ291bnQ7IHdvcmtlckluZGV4KyspIHtcbiAgICAgIHdvcmtlcnMucHVzaCgoYXN5bmMgKCkgPT4ge1xuICAgICAgICB3aGlsZSAodGVuYW50SW5kZXggPCB0ZW5hbnRzLmxlbmd0aCkge1xuICAgICAgICAgIGNvbnN0IHRlbmFudCA9IHRlbmFudHNbdGVuYW50SW5kZXhdXG5cbiAgICAgICAgICB0ZW5hbnRJbmRleCsrXG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5ydW5UZW5hbnRDYWxsYmFjayh7Y2FsbGJhY2ssIHRlbmFudH0pXG4gICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGZhaWx1cmVzLnB1c2goe1xuICAgICAgICAgICAgICBlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yIDogbmV3IEVycm9yKFN0cmluZyhlcnJvcikpLFxuICAgICAgICAgICAgICB0ZW5hbnRcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KSgpKVxuICAgIH1cblxuICAgIGF3YWl0IFByb21pc2UuYWxsKHdvcmtlcnMpXG5cbiAgICBpZiAoZmFpbHVyZXMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgZmFpbGVkVGVuYW50TGFiZWxzID0gZmFpbHVyZXMubWFwKChmYWlsdXJlKSA9PiBUZW5hbnRJdGVyYXRvci50ZW5hbnRMYWJlbChmYWlsdXJlLnRlbmFudCkpLmpvaW4oXCIsIFwiKVxuXG4gICAgICB0aHJvdyBuZXcgQWdncmVnYXRlRXJyb3IoXG4gICAgICAgIGZhaWx1cmVzLm1hcCgoZmFpbHVyZSkgPT4gZmFpbHVyZS5lcnJvciksXG4gICAgICAgIGBGYWlsZWQgdGVuYW50IGRhdGFiYXNlIGNvbW1hbmQgZm9yIHRlbmFudChzKTogJHtmYWlsZWRUZW5hbnRMYWJlbHN9YFxuICAgICAgKVxuICAgIH1cblxuICAgIHJldHVybiB0ZW5hbnRzLmxlbmd0aFxuICB9XG5cbiAgLyoqXG4gICAqIEVudGVycyBvbmUgdGVuYW50J3MgY29udGV4dCBhbmQgcnVucyB0aGUgY2FsbGJhY2ssIGFzc2VydGluZyB0aGUgZGF0YWJhc2UgaXMgYWN0aXZlIGZpcnN0LlxuICAgKiBAcGFyYW0ge3tjYWxsYmFjazogZnVuY3Rpb24oe2RhdGFiYXNlQ29uZmlndXJhdGlvbjogaW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5EYXRhYmFzZUNvbmZpZ3VyYXRpb25UeXBlLCB0ZW5hbnQ6ID99KSA6IFByb21pc2U8dm9pZD4sIHRlbmFudDogP319IGFyZ3MgLSBUZW5hbnQgZGVzY3JpcHRvciBhbmQgb3BlcmF0aW9uIHRvIHJ1biBpbiBpdHMgY29udGV4dC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBydW5UZW5hbnRDYWxsYmFjayh7Y2FsbGJhY2ssIHRlbmFudH0pIHtcbiAgICBhd2FpdCB0aGlzLmNvbmZpZ3VyYXRpb24ucnVuV2l0aFRlbmFudCh0ZW5hbnQsIGFzeW5jICgpID0+IHtcbiAgICAgIGlmICghdGhpcy5jb25maWd1cmF0aW9uLmlzRGF0YWJhc2VJZGVudGlmaWVyQWN0aXZlKHRoaXMuaWRlbnRpZmllcikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUZW5hbnQgZGF0YWJhc2UgaWRlbnRpZmllciAke3RoaXMuaWRlbnRpZmllcn0gaXMgaW5hY3RpdmUgZm9yIHRlbmFudDogJHtUZW5hbnRJdGVyYXRvci50ZW5hbnRMYWJlbCh0ZW5hbnQpfWApXG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGNhbGxiYWNrKHtcbiAgICAgICAgZGF0YWJhc2VDb25maWd1cmF0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb24ucmVzb2x2ZURhdGFiYXNlQ29uZmlndXJhdGlvbih0aGlzLmlkZW50aWZpZXIpLFxuICAgICAgICB0ZW5hbnRcbiAgICAgIH0pXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgYSBodW1hbi1yZWFkYWJsZSBsYWJlbCBmb3IgYSB0ZW5hbnQgZm9yIHVzZSBpbiBlcnJvciBtZXNzYWdlcy5cbiAgICogQHBhcmFtIHs/fSB0ZW5hbnQgLSBUZW5hbnQgZGVzY3JpcHRvciB0byBpZGVudGlmeSBpbiBhbiBlcnJvci5cbiAgICogQHJldHVybnMge3N0cmluZ30gLSBIdW1hbi1yZWFkYWJsZSB0ZW5hbnQgbGFiZWwuXG4gICAqL1xuICBzdGF0aWMgdGVuYW50TGFiZWwodGVuYW50KSB7XG4gICAgaWYgKHRlbmFudCAmJiB0eXBlb2YgdGVuYW50ID09PSBcIm9iamVjdFwiKSB7XG4gICAgICBjb25zdCB0ZW5hbnRPYmplY3QgPSAvKiogQHR5cGUge3tpZD86ID8sIG5hbWU/OiA/LCBzbHVnPzogP319ICovICh0ZW5hbnQpXG5cbiAgICAgIGZvciAoY29uc3QgYXR0cmlidXRlTmFtZSBvZiAvKiogQHR5cGUge0FycmF5PFwic2x1Z1wiIHwgXCJuYW1lXCIgfCBcImlkXCI+fSAqLyAoW1wic2x1Z1wiLCBcIm5hbWVcIiwgXCJpZFwiXSkpIHtcbiAgICAgICAgY29uc3QgYXR0cmlidXRlT3JBY2Nlc3NvciA9IHRlbmFudE9iamVjdFthdHRyaWJ1dGVOYW1lXVxuICAgICAgICBjb25zdCBhdHRyaWJ1dGVWYWx1ZSA9IHR5cGVvZiBhdHRyaWJ1dGVPckFjY2Vzc29yID09PSBcImZ1bmN0aW9uXCJcbiAgICAgICAgICA/IGF0dHJpYnV0ZU9yQWNjZXNzb3IuY2FsbCh0ZW5hbnQpXG4gICAgICAgICAgOiBhdHRyaWJ1dGVPckFjY2Vzc29yXG5cbiAgICAgICAgaWYgKGF0dHJpYnV0ZVZhbHVlKSByZXR1cm4gU3RyaW5nKGF0dHJpYnV0ZVZhbHVlKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh0ZW5hbnQpXG4gIH1cbn1cbiJdfQ==
@@ -101,9 +101,14 @@ export default class TenantIterator {
101
101
  if (tenant && typeof tenant === "object") {
102
102
  const tenantObject = /** @type {{id?: ?, name?: ?, slug?: ?}} */ (tenant)
103
103
 
104
- if (tenantObject.slug) return String(tenantObject.slug)
105
- if (tenantObject.name) return String(tenantObject.name)
106
- if (tenantObject.id) return String(tenantObject.id)
104
+ for (const attributeName of /** @type {Array<"slug" | "name" | "id">} */ (["slug", "name", "id"])) {
105
+ const attributeOrAccessor = tenantObject[attributeName]
106
+ const attributeValue = typeof attributeOrAccessor === "function"
107
+ ? attributeOrAccessor.call(tenant)
108
+ : attributeOrAccessor
109
+
110
+ if (attributeValue) return String(attributeValue)
111
+ }
107
112
  }
108
113
 
109
114
  return JSON.stringify(tenant)
@@ -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/pooled-runner-child.js","../src/background-jobs/runner-process-title.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/advisory-lock-runner.js","../src/database/annotations-async-hooks.js","../src/database/annotations.js","../src/database/column-types.js","../src/database/datetime-storage.js","../src/database/handler.js","../src/database/initializer-from-require-context.js","../src/database/live-query.js","../src/database/migrations-ledger.js","../src/database/migrator.js","../src/database/record-changes.js","../src/database/use-database.js","../src/database/use-live-query.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-stream.js","../src/database/drivers/mysql/query.js","../src/database/drivers/mysql/structure-sql.js","../src/database/drivers/mysql/table.js","../src/database/drivers/mysql/sql/alter-table.js","../src/database/drivers/mysql/sql/create-database.js","../src/database/drivers/mysql/sql/create-index.js","../src/database/drivers/mysql/sql/create-table.js","../src/database/drivers/mysql/sql/delete.js","../src/database/drivers/mysql/sql/drop-database.js","../src/database/drivers/mysql/sql/drop-table.js","../src/database/drivers/mysql/sql/insert.js","../src/database/drivers/mysql/sql/remove-index.js","../src/database/drivers/mysql/sql/update.js","../src/database/drivers/mysql/sql/upsert.js","../src/database/drivers/pgsql/column.js","../src/database/drivers/pgsql/columns-index.js","../src/database/drivers/pgsql/foreign-key.js","../src/database/drivers/pgsql/index.js","../src/database/drivers/pgsql/options.js","../src/database/drivers/pgsql/query-parser.js","../src/database/drivers/pgsql/structure-sql.js","../src/database/drivers/pgsql/table.js","../src/database/drivers/pgsql/sql/alter-table.js","../src/database/drivers/pgsql/sql/create-database.js","../src/database/drivers/pgsql/sql/create-index.js","../src/database/drivers/pgsql/sql/create-table.js","../src/database/drivers/pgsql/sql/delete.js","../src/database/drivers/pgsql/sql/drop-database.js","../src/database/drivers/pgsql/sql/drop-table.js","../src/database/drivers/pgsql/sql/insert.js","../src/database/drivers/pgsql/sql/remove-index.js","../src/database/drivers/pgsql/sql/update.js","../src/database/drivers/pgsql/sql/upsert.js","../src/database/drivers/sqlite/base.js","../src/database/drivers/sqlite/column.js","../src/database/drivers/sqlite/columns-index.js","../src/database/drivers/sqlite/connection-sql-js.js","../src/database/drivers/sqlite/foreign-key.js","../src/database/drivers/sqlite/index.js","../src/database/drivers/sqlite/index.native.js","../src/database/drivers/sqlite/index.web.js","../src/database/drivers/sqlite/options.js","../src/database/drivers/sqlite/query-parser.js","../src/database/drivers/sqlite/query.js","../src/database/drivers/sqlite/query.native.js","../src/database/drivers/sqlite/query.web.js","../src/database/drivers/sqlite/structure-sql.js","../src/database/drivers/sqlite/table-rebuilder.js","../src/database/drivers/sqlite/table.js","../src/database/drivers/sqlite/web-persistence.js","../src/database/drivers/sqlite/sql/alter-table.js","../src/database/drivers/sqlite/sql/create-index.js","../src/database/drivers/sqlite/sql/create-table.js","../src/database/drivers/sqlite/sql/delete.js","../src/database/drivers/sqlite/sql/drop-table.js","../src/database/drivers/sqlite/sql/insert.js","../src/database/drivers/sqlite/sql/remove-index.js","../src/database/drivers/sqlite/sql/update.js","../src/database/drivers/sqlite/sql/upsert.js","../src/database/drivers/structure-sql/utils.js","../src/database/migration/index.js","../src/database/migrator/files-finder.js","../src/database/migrator/types.js","../src/database/pool/async-tracked-multi-connection.js","../src/database/pool/base-methods-forward.js","../src/database/pool/base.js","../src/database/pool/single-multi-use.js","../src/database/query/alter-table-base.js","../src/database/query/base.js","../src/database/query/create-database-base.js","../src/database/query/create-index-base.js","../src/database/query/create-table-base.js","../src/database/query/delete-base.js","../src/database/query/drop-database-base.js","../src/database/query/drop-table-base.js","../src/database/query/from-base.js","../src/database/query/from-plain.js","../src/database/query/from-table.js","../src/database/query/index.js","../src/database/query/insert-base.js","../src/database/query/join-base.js","../src/database/query/join-object.js","../src/database/query/join-plain.js","../src/database/query/join-tracker.js","../src/database/query/model-class-query.js","../src/database/query/order-base.js","../src/database/query/order-column.js","../src/database/query/order-plain.js","../src/database/query/preloader.js","../src/database/query/query-data.js","../src/database/query/remove-index-base.js","../src/database/query/select-base.js","../src/database/query/select-plain.js","../src/database/query/select-table-and-column.js","../src/database/query/update-base.js","../src/database/query/upsert-base.js","../src/database/query/where-base.js","../src/database/query/where-combinator.js","../src/database/query/where-hash.js","../src/database/query/where-model-class-hash.js","../src/database/query/where-not.js","../src/database/query/where-plain.js","../src/database/query/with-count.js","../src/database/query/preloader/belongs-to.js","../src/database/query/preloader/ensure-model-class-initialized.js","../src/database/query/preloader/has-many.js","../src/database/query/preloader/has-one.js","../src/database/query/preloader/selection.js","../src/database/query-parser/base-query-parser.js","../src/database/query-parser/from-parser.js","../src/database/query-parser/group-parser.js","../src/database/query-parser/joins-parser.js","../src/database/query-parser/limit-parser.js","../src/database/query-parser/options.js","../src/database/query-parser/order-parser.js","../src/database/query-parser/select-parser.js","../src/database/query-parser/where-parser.js","../src/database/record/acts-as-list.js","../src/database/record/auditing.js","../src/database/record/counter-cache-magnitude.js","../src/database/record/index.js","../src/database/record/record-not-found-error.js","../src/database/record/state-machine.js","../src/database/record/user-module.js","../src/database/record/validation-messages.js","../src/database/record/attachments/attachment-record.js","../src/database/record/attachments/download.js","../src/database/record/attachments/handle.js","../src/database/record/attachments/normalize-input.js","../src/database/record/attachments/store.js","../src/database/record/attachments/storage-drivers/filesystem.js","../src/database/record/attachments/storage-drivers/native.js","../src/database/record/attachments/storage-drivers/s3.js","../src/database/record/instance-relationships/base.js","../src/database/record/instance-relationships/belongs-to.js","../src/database/record/instance-relationships/has-many.js","../src/database/record/instance-relationships/has-one.js","../src/database/record/relationships/base.js","../src/database/record/relationships/belongs-to.js","../src/database/record/relationships/has-many.js","../src/database/record/relationships/has-one.js","../src/database/record/validators/base.js","../src/database/record/validators/format.js","../src/database/record/validators/length.js","../src/database/record/validators/presence.js","../src/database/record/validators/uniqueness.js","../src/database/table-data/index.js","../src/database/table-data/table-column.js","../src/database/table-data/table-foreign-key.js","../src/database/table-data/table-index.js","../src/database/table-data/table-reference.js","../src/database/tenants/data-copier.js","../src/database/tenants/schema-cloner.js","../src/database/tenants/tenant-table-plan.js","../src/environment-handlers/base.js","../src/environment-handlers/browser.js","../src/environment-handlers/node.js","../src/environment-handlers/node/cli/commands/background-jobs-main.js","../src/environment-handlers/node/cli/commands/background-jobs-runner.js","../src/environment-handlers/node/cli/commands/background-jobs-worker.js","../src/environment-handlers/node/cli/commands/beacon.js","../src/environment-handlers/node/cli/commands/cli-command-context.js","../src/environment-handlers/node/cli/commands/console.js","../src/environment-handlers/node/cli/commands/init.js","../src/environment-handlers/node/cli/commands/routes.js","../src/environment-handlers/node/cli/commands/run-script.js","../src/environment-handlers/node/cli/commands/runner.js","../src/environment-handlers/node/cli/commands/server.js","../src/environment-handlers/node/cli/commands/test.js","../src/environment-handlers/node/cli/commands/db/seed.js","../src/environment-handlers/node/cli/commands/db/schema/dump.js","../src/environment-handlers/node/cli/commands/db/schema/load.js","../src/environment-handlers/node/cli/commands/destroy/migration.js","../src/environment-handlers/node/cli/commands/generate/base-models.js","../src/environment-handlers/node/cli/commands/generate/frontend-models.js","../src/environment-handlers/node/cli/commands/generate/generated-file-banner.js","../src/environment-handlers/node/cli/commands/generate/migration.js","../src/environment-handlers/node/cli/commands/generate/model.js","../src/environment-handlers/node/cli/commands/lint/relationships.js","../src/error-reporting/request-details.js","../src/frontend-model-resource/base-resource.js","../src/frontend-model-resource/velocious-attachment-resource.js","../src/frontend-models/base.js","../src/frontend-models/built-in-resources.js","../src/frontend-models/clear-pending-debounced-callback.js","../src/frontend-models/event-hook-models.js","../src/frontend-models/model-registry.js","../src/frontend-models/outgoing-event-buffer.js","../src/frontend-models/preloader.js","../src/frontend-models/query.js","../src/frontend-models/resource-config-validation.js","../src/frontend-models/resource-definition.js","../src/frontend-models/transport-serialization.js","../src/frontend-models/use-created-event.js","../src/frontend-models/use-destroyed-event.js","../src/frontend-models/use-model-class-event.js","../src/frontend-models/use-updated-event.js","../src/frontend-models/websocket-channel.js","../src/frontend-models/websocket-publishers.js","../src/http-client/header.js","../src/http-client/index.js","../src/http-client/request.js","../src/http-client/response.js","../src/http-client/websocket-client.js","../src/http-server/cookie.js","../src/http-server/development-reloader.js","../src/http-server/index.js","../src/http-server/remote-address.js","../src/http-server/server-client.js","../src/http-server/server-lock.js","../src/http-server/websocket-channel-subscribers.js","../src/http-server/websocket-channel.js","../src/http-server/websocket-connection.js","../src/http-server/websocket-event-log-store.js","../src/http-server/websocket-events-host.js","../src/http-server/websocket-events.js","../src/http-server/client/index.js","../src/http-server/client/params-to-object.js","../src/http-server/client/request-parser.js","../src/http-server/client/request-runner.js","../src/http-server/client/request-timing.js","../src/http-server/client/request.js","../src/http-server/client/response.js","../src/http-server/client/websocket-request.js","../src/http-server/client/websocket-session.js","../src/http-server/client/request-buffer/form-data-part.js","../src/http-server/client/request-buffer/header.js","../src/http-server/client/request-buffer/index.js","../src/http-server/client/uploaded-file/memory-uploaded-file.js","../src/http-server/client/uploaded-file/temporary-uploaded-file.js","../src/http-server/client/uploaded-file/uploaded-file.js","../src/http-server/worker-handler/channel-subscriber-dispatch.js","../src/http-server/worker-handler/in-process.js","../src/http-server/worker-handler/index.js","../src/http-server/worker-handler/worker-script.js","../src/http-server/worker-handler/worker-thread.js","../src/jobs/mail-delivery.js","../src/jobs/prune-terminal-background-jobs.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/api-manifest/controller.js","../src/routes/built-in/debug/controller.js","../src/routes/built-in/errors/controller.js","../src/routes/hooks/frontend-model-command-route-hook.js","../src/sync/conflict-strategy.js","../src/sync/device-identity.js","../src/sync/local-mutation-log.js","../src/sync/offline-grant.js","../src/sync/peer-mutation-bundle.js","../src/sync/query-scope.js","../src/sync/server-change-feed.js","../src/sync/server-sequence-allocator.js","../src/sync/stable-json.js","../src/sync/sync-api-client-types.js","../src/sync/sync-api-client.js","../src/sync/sync-api-controller.js","../src/sync/sync-change-fanout.js","../src/sync/sync-channel-name.js","../src/sync/sync-client-registry.js","../src/sync/sync-client-types.js","../src/sync/sync-client.js","../src/sync/sync-envelope-replay-service.js","../src/sync/sync-model-change-feed-service.js","../src/sync/sync-publish-suppression.js","../src/sync/sync-publisher-types.js","../src/sync/sync-publisher.js","../src/sync/sync-realtime-bridge.js","../src/sync/sync-replay-upsert-applier.js","../src/sync/sync-resource-base.js","../src/sync/sync-scope-attributes.js","../src/sync/sync-scope-store.js","../src/sync/sync-websocket-channel.js","../src/tenants/default-tenant-database-provisioning.js","../src/tenants/tenant-aggregator.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/pooled-runner-child.js","../src/background-jobs/runner-process-title.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/advisory-lock-runner.js","../src/database/annotations-async-hooks.js","../src/database/annotations.js","../src/database/column-types.js","../src/database/datetime-storage.js","../src/database/handler.js","../src/database/initializer-from-require-context.js","../src/database/live-query.js","../src/database/migrations-ledger.js","../src/database/migrator.js","../src/database/record-changes.js","../src/database/structure-sql-loader.js","../src/database/use-database.js","../src/database/use-live-query.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-stream.js","../src/database/drivers/mysql/query.js","../src/database/drivers/mysql/structure-sql.js","../src/database/drivers/mysql/table.js","../src/database/drivers/mysql/sql/alter-table.js","../src/database/drivers/mysql/sql/create-database.js","../src/database/drivers/mysql/sql/create-index.js","../src/database/drivers/mysql/sql/create-table.js","../src/database/drivers/mysql/sql/delete.js","../src/database/drivers/mysql/sql/drop-database.js","../src/database/drivers/mysql/sql/drop-table.js","../src/database/drivers/mysql/sql/insert.js","../src/database/drivers/mysql/sql/remove-index.js","../src/database/drivers/mysql/sql/update.js","../src/database/drivers/mysql/sql/upsert.js","../src/database/drivers/pgsql/column.js","../src/database/drivers/pgsql/columns-index.js","../src/database/drivers/pgsql/foreign-key.js","../src/database/drivers/pgsql/index.js","../src/database/drivers/pgsql/options.js","../src/database/drivers/pgsql/query-parser.js","../src/database/drivers/pgsql/structure-sql.js","../src/database/drivers/pgsql/table.js","../src/database/drivers/pgsql/sql/alter-table.js","../src/database/drivers/pgsql/sql/create-database.js","../src/database/drivers/pgsql/sql/create-index.js","../src/database/drivers/pgsql/sql/create-table.js","../src/database/drivers/pgsql/sql/delete.js","../src/database/drivers/pgsql/sql/drop-database.js","../src/database/drivers/pgsql/sql/drop-table.js","../src/database/drivers/pgsql/sql/insert.js","../src/database/drivers/pgsql/sql/remove-index.js","../src/database/drivers/pgsql/sql/update.js","../src/database/drivers/pgsql/sql/upsert.js","../src/database/drivers/sqlite/base.js","../src/database/drivers/sqlite/column.js","../src/database/drivers/sqlite/columns-index.js","../src/database/drivers/sqlite/connection-sql-js.js","../src/database/drivers/sqlite/foreign-key.js","../src/database/drivers/sqlite/index.js","../src/database/drivers/sqlite/index.native.js","../src/database/drivers/sqlite/index.web.js","../src/database/drivers/sqlite/options.js","../src/database/drivers/sqlite/query-parser.js","../src/database/drivers/sqlite/query.js","../src/database/drivers/sqlite/query.native.js","../src/database/drivers/sqlite/query.web.js","../src/database/drivers/sqlite/structure-sql.js","../src/database/drivers/sqlite/table-rebuilder.js","../src/database/drivers/sqlite/table.js","../src/database/drivers/sqlite/web-persistence.js","../src/database/drivers/sqlite/sql/alter-table.js","../src/database/drivers/sqlite/sql/create-index.js","../src/database/drivers/sqlite/sql/create-table.js","../src/database/drivers/sqlite/sql/delete.js","../src/database/drivers/sqlite/sql/drop-table.js","../src/database/drivers/sqlite/sql/insert.js","../src/database/drivers/sqlite/sql/remove-index.js","../src/database/drivers/sqlite/sql/update.js","../src/database/drivers/sqlite/sql/upsert.js","../src/database/drivers/structure-sql/utils.js","../src/database/migration/index.js","../src/database/migrator/files-finder.js","../src/database/migrator/types.js","../src/database/pool/async-tracked-multi-connection.js","../src/database/pool/base-methods-forward.js","../src/database/pool/base.js","../src/database/pool/single-multi-use.js","../src/database/query/alter-table-base.js","../src/database/query/base.js","../src/database/query/create-database-base.js","../src/database/query/create-index-base.js","../src/database/query/create-table-base.js","../src/database/query/delete-base.js","../src/database/query/drop-database-base.js","../src/database/query/drop-table-base.js","../src/database/query/from-base.js","../src/database/query/from-plain.js","../src/database/query/from-table.js","../src/database/query/index.js","../src/database/query/insert-base.js","../src/database/query/join-base.js","../src/database/query/join-object.js","../src/database/query/join-plain.js","../src/database/query/join-tracker.js","../src/database/query/model-class-query.js","../src/database/query/order-base.js","../src/database/query/order-column.js","../src/database/query/order-plain.js","../src/database/query/preloader.js","../src/database/query/query-data.js","../src/database/query/remove-index-base.js","../src/database/query/select-base.js","../src/database/query/select-plain.js","../src/database/query/select-table-and-column.js","../src/database/query/update-base.js","../src/database/query/upsert-base.js","../src/database/query/where-base.js","../src/database/query/where-combinator.js","../src/database/query/where-hash.js","../src/database/query/where-model-class-hash.js","../src/database/query/where-not.js","../src/database/query/where-plain.js","../src/database/query/with-count.js","../src/database/query/preloader/belongs-to.js","../src/database/query/preloader/ensure-model-class-initialized.js","../src/database/query/preloader/has-many.js","../src/database/query/preloader/has-one.js","../src/database/query/preloader/selection.js","../src/database/query-parser/base-query-parser.js","../src/database/query-parser/from-parser.js","../src/database/query-parser/group-parser.js","../src/database/query-parser/joins-parser.js","../src/database/query-parser/limit-parser.js","../src/database/query-parser/options.js","../src/database/query-parser/order-parser.js","../src/database/query-parser/select-parser.js","../src/database/query-parser/where-parser.js","../src/database/record/acts-as-list.js","../src/database/record/auditing.js","../src/database/record/counter-cache-magnitude.js","../src/database/record/index.js","../src/database/record/record-not-found-error.js","../src/database/record/state-machine.js","../src/database/record/user-module.js","../src/database/record/validation-messages.js","../src/database/record/attachments/attachment-record.js","../src/database/record/attachments/download.js","../src/database/record/attachments/handle.js","../src/database/record/attachments/normalize-input.js","../src/database/record/attachments/store.js","../src/database/record/attachments/storage-drivers/filesystem.js","../src/database/record/attachments/storage-drivers/native.js","../src/database/record/attachments/storage-drivers/s3.js","../src/database/record/instance-relationships/base.js","../src/database/record/instance-relationships/belongs-to.js","../src/database/record/instance-relationships/has-many.js","../src/database/record/instance-relationships/has-one.js","../src/database/record/relationships/base.js","../src/database/record/relationships/belongs-to.js","../src/database/record/relationships/has-many.js","../src/database/record/relationships/has-one.js","../src/database/record/validators/base.js","../src/database/record/validators/format.js","../src/database/record/validators/length.js","../src/database/record/validators/presence.js","../src/database/record/validators/uniqueness.js","../src/database/table-data/index.js","../src/database/table-data/table-column.js","../src/database/table-data/table-foreign-key.js","../src/database/table-data/table-index.js","../src/database/table-data/table-reference.js","../src/database/tenants/data-copier.js","../src/database/tenants/schema-cloner.js","../src/database/tenants/tenant-table-plan.js","../src/environment-handlers/base.js","../src/environment-handlers/browser.js","../src/environment-handlers/node.js","../src/environment-handlers/node/cli/commands/background-jobs-main.js","../src/environment-handlers/node/cli/commands/background-jobs-runner.js","../src/environment-handlers/node/cli/commands/background-jobs-worker.js","../src/environment-handlers/node/cli/commands/beacon.js","../src/environment-handlers/node/cli/commands/cli-command-context.js","../src/environment-handlers/node/cli/commands/console.js","../src/environment-handlers/node/cli/commands/init.js","../src/environment-handlers/node/cli/commands/routes.js","../src/environment-handlers/node/cli/commands/run-script.js","../src/environment-handlers/node/cli/commands/runner.js","../src/environment-handlers/node/cli/commands/server.js","../src/environment-handlers/node/cli/commands/test.js","../src/environment-handlers/node/cli/commands/db/seed.js","../src/environment-handlers/node/cli/commands/db/schema/dump.js","../src/environment-handlers/node/cli/commands/db/schema/load.js","../src/environment-handlers/node/cli/commands/destroy/migration.js","../src/environment-handlers/node/cli/commands/generate/base-models.js","../src/environment-handlers/node/cli/commands/generate/frontend-models.js","../src/environment-handlers/node/cli/commands/generate/generated-file-banner.js","../src/environment-handlers/node/cli/commands/generate/migration.js","../src/environment-handlers/node/cli/commands/generate/model.js","../src/environment-handlers/node/cli/commands/lint/relationships.js","../src/error-reporting/request-details.js","../src/frontend-model-resource/base-resource.js","../src/frontend-model-resource/velocious-attachment-resource.js","../src/frontend-models/base.js","../src/frontend-models/built-in-resources.js","../src/frontend-models/clear-pending-debounced-callback.js","../src/frontend-models/event-hook-models.js","../src/frontend-models/model-registry.js","../src/frontend-models/outgoing-event-buffer.js","../src/frontend-models/preloader.js","../src/frontend-models/query.js","../src/frontend-models/resource-config-validation.js","../src/frontend-models/resource-definition.js","../src/frontend-models/transport-serialization.js","../src/frontend-models/use-created-event.js","../src/frontend-models/use-destroyed-event.js","../src/frontend-models/use-model-class-event.js","../src/frontend-models/use-updated-event.js","../src/frontend-models/websocket-channel.js","../src/frontend-models/websocket-publishers.js","../src/http-client/header.js","../src/http-client/index.js","../src/http-client/request.js","../src/http-client/response.js","../src/http-client/websocket-client.js","../src/http-server/cookie.js","../src/http-server/development-reloader.js","../src/http-server/index.js","../src/http-server/remote-address.js","../src/http-server/server-client.js","../src/http-server/server-lock.js","../src/http-server/websocket-channel-subscribers.js","../src/http-server/websocket-channel.js","../src/http-server/websocket-connection.js","../src/http-server/websocket-event-log-store.js","../src/http-server/websocket-events-host.js","../src/http-server/websocket-events.js","../src/http-server/client/index.js","../src/http-server/client/params-to-object.js","../src/http-server/client/request-parser.js","../src/http-server/client/request-runner.js","../src/http-server/client/request-timing.js","../src/http-server/client/request.js","../src/http-server/client/response.js","../src/http-server/client/websocket-request.js","../src/http-server/client/websocket-session.js","../src/http-server/client/request-buffer/form-data-part.js","../src/http-server/client/request-buffer/header.js","../src/http-server/client/request-buffer/index.js","../src/http-server/client/uploaded-file/memory-uploaded-file.js","../src/http-server/client/uploaded-file/temporary-uploaded-file.js","../src/http-server/client/uploaded-file/uploaded-file.js","../src/http-server/worker-handler/channel-subscriber-dispatch.js","../src/http-server/worker-handler/in-process.js","../src/http-server/worker-handler/index.js","../src/http-server/worker-handler/worker-script.js","../src/http-server/worker-handler/worker-thread.js","../src/jobs/mail-delivery.js","../src/jobs/prune-terminal-background-jobs.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/api-manifest/controller.js","../src/routes/built-in/debug/controller.js","../src/routes/built-in/errors/controller.js","../src/routes/hooks/frontend-model-command-route-hook.js","../src/sync/conflict-strategy.js","../src/sync/device-identity.js","../src/sync/local-mutation-log.js","../src/sync/offline-grant.js","../src/sync/peer-mutation-bundle.js","../src/sync/query-scope.js","../src/sync/server-change-feed.js","../src/sync/server-sequence-allocator.js","../src/sync/stable-json.js","../src/sync/sync-api-client-types.js","../src/sync/sync-api-client.js","../src/sync/sync-api-controller.js","../src/sync/sync-change-fanout.js","../src/sync/sync-channel-name.js","../src/sync/sync-client-registry.js","../src/sync/sync-client-types.js","../src/sync/sync-client.js","../src/sync/sync-envelope-replay-service.js","../src/sync/sync-model-change-feed-service.js","../src/sync/sync-publish-suppression.js","../src/sync/sync-publisher-types.js","../src/sync/sync-publisher.js","../src/sync/sync-realtime-bridge.js","../src/sync/sync-replay-upsert-applier.js","../src/sync/sync-resource-base.js","../src/sync/sync-scope-attributes.js","../src/sync/sync-scope-store.js","../src/sync/sync-websocket-channel.js","../src/tenants/default-tenant-database-provisioning.js","../src/tenants/tenant-aggregator.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
@@ -3,7 +3,7 @@
3
3
  "velocious": "build/bin/velocious.js"
4
4
  },
5
5
  "name": "velocious",
6
- "version": "1.0.547",
6
+ "version": "1.0.549",
7
7
  "main": "build/index.js",
8
8
  "types": "build/index.d.ts",
9
9
  "files": [
@@ -2,19 +2,25 @@
2
2
 
3
3
  import TenantIterator from "../tenants/tenant-iterator.js"
4
4
 
5
+ const DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000
6
+
5
7
  export default class TenantDatabaseCommandHelper {
6
8
  /**
7
9
  * Runs constructor.
8
10
  * @param {object} args - Options object.
9
11
  * @param {import("./base-command.js").default} args.command - CLI command instance.
12
+ * @param {number} [args.heartbeatIntervalMs] - Interval between progress heartbeats.
10
13
  * @param {string | undefined} args.identifier - Tenant database identifier.
14
+ * @param {(message: string) => void} [args.output] - Progress output handler.
11
15
  */
12
- constructor({command, identifier}) {
16
+ constructor({command, heartbeatIntervalMs = DEFAULT_HEARTBEAT_INTERVAL_MS, identifier, output = console.log}) {
13
17
  if (!identifier) throw new Error("Missing tenant database identifier argument")
14
18
 
15
19
  this.command = command
16
20
  this.configuration = command.getConfiguration()
21
+ this.heartbeatIntervalMs = heartbeatIntervalMs
17
22
  this.identifier = identifier
23
+ this.output = output
18
24
  this.provider = this.configuration.getTenantDatabaseProvider(identifier)
19
25
  }
20
26
 
@@ -78,13 +84,42 @@ export default class TenantDatabaseCommandHelper {
78
84
  */
79
85
  async eachTenant(callback) {
80
86
  const tenants = await this.listTenants()
87
+ const commandName = this.command.processArgs?.[0] || "db:tenants"
88
+ const parallelCount = this.parallelCount()
89
+ const progressPrefix = `${commandName} ${this.identifier}`
90
+ let activeTenantCount = 0
91
+ let completedTenantCount = 0
81
92
  const iterator = new TenantIterator({
82
93
  configuration: this.configuration,
83
94
  identifier: this.identifier,
84
- parallelCount: this.parallelCount()
95
+ parallelCount
85
96
  })
97
+ const progressHeartbeat = setInterval(() => {
98
+ this.output(`${progressPrefix}: heartbeat: ${completedTenantCount}/${tenants.length} completed, ${activeTenantCount} active`)
99
+ }, this.heartbeatIntervalMs)
100
+
101
+ progressHeartbeat.unref()
102
+ this.output(`${progressPrefix}: processing ${tenants.length} tenant(s) with parallelism ${parallelCount}`)
103
+
104
+ try {
105
+ const processedTenantCount = await iterator.run(tenants, async (args) => {
106
+ activeTenantCount++
107
+
108
+ try {
109
+ await callback(args)
110
+ completedTenantCount++
111
+ this.output(`${progressPrefix}: completed ${TenantIterator.tenantLabel(args.tenant)} (${completedTenantCount}/${tenants.length})`)
112
+ } finally {
113
+ activeTenantCount--
114
+ }
115
+ })
86
116
 
87
- return await iterator.run(tenants, callback)
117
+ this.output(`${progressPrefix}: finished ${processedTenantCount}/${tenants.length} tenant(s)`)
118
+
119
+ return processedTenantCount
120
+ } finally {
121
+ clearInterval(progressHeartbeat)
122
+ }
88
123
  }
89
124
 
90
125
  /**
@@ -0,0 +1,68 @@
1
+ // @ts-check
2
+
3
+ import splitSqlStatements from "../utils/split-sql-statements.js"
4
+
5
+ /**
6
+ * Loads a database structure SQL dump into a connection in one pass. Foreign keys are
7
+ * disabled around the load so tables can be created in any order, and the driver's
8
+ * native multi-statement `exec` is used when available (a single round-trip) instead
9
+ * of issuing every statement separately. This is much faster than materializing a
10
+ * schema table by table (e.g. cloning), so it is the preferred way to provision a
11
+ * tenant/test database from a structure dump.
12
+ *
13
+ * Used by the `db:schema:load` CLI command and reusable by any caller that needs to
14
+ * apply a structure dump to a specific connection.
15
+ */
16
+ export default class StructureSqlLoader {
17
+ /**
18
+ * Loads `structureSql` into `db`.
19
+ * @param {object} args - Options object.
20
+ * @param {import("./drivers/base.js").default} args.db - Target database connection.
21
+ * @param {string} args.structureSql - Structure SQL to load.
22
+ * @returns {Promise<void>} - Resolves when the structure has been loaded.
23
+ */
24
+ async load({db, structureSql}) {
25
+ const statements = splitSqlStatements(structureSql)
26
+
27
+ if (statements.length == 0) return
28
+
29
+ const executableConnection = this.executableConnection(db)
30
+
31
+ await db.disableForeignKeys()
32
+
33
+ try {
34
+ if (executableConnection) {
35
+ await executableConnection.exec(structureSql)
36
+ } else {
37
+ for (const statement of statements) {
38
+ await db.query(statement)
39
+ }
40
+ }
41
+ } finally {
42
+ await db.enableForeignKeys()
43
+
44
+ // The native `exec` path mutates the schema outside `Base#query`, so the
45
+ // usual post-DDL schema-cache invalidation never runs. Clear it here so a
46
+ // caller that read schema metadata before provisioning (e.g. an empty table
47
+ // list) does not keep seeing the pre-load schema afterwards. Harmless for the
48
+ // per-statement path, which already invalidates as each DDL statement runs.
49
+ db.clearSchemaCache()
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Returns the underlying connection when it exposes a native multi-statement
55
+ * `exec` (a single round-trip for the whole dump), otherwise undefined so the
56
+ * caller falls back to per-statement execution.
57
+ * @param {import("./drivers/base.js").default} db - Database connection.
58
+ * @returns {{exec: (sql: string) => Promise<?>} | undefined} - Connection with exec support.
59
+ */
60
+ executableConnection(db) {
61
+ const dbWithConnection = /** @type {import("./drivers/base.js").default & {connection?: ?}} */ (db)
62
+ const connection = dbWithConnection.connection
63
+
64
+ if (connection && typeof connection == "object" && "exec" in connection && typeof connection.exec == "function") {
65
+ return /** @type {{exec: (sql: string) => Promise<?>}} */ (connection)
66
+ }
67
+ }
68
+ }
@@ -1,7 +1,7 @@
1
1
  import BaseCommand from "../../../../../../cli/base-command.js"
2
2
  import fs from "fs/promises"
3
3
  import path from "path"
4
- import splitSqlStatements from "../../../../../../utils/split-sql-statements.js"
4
+ import StructureSqlLoader from "../../../../../../database/structure-sql-loader.js"
5
5
 
6
6
  /** Node CLI command for loading DB structure SQL files. */
7
7
  export default class DbSchemaLoad extends BaseCommand {
@@ -11,57 +11,15 @@ export default class DbSchemaLoad extends BaseCommand {
11
11
  async execute() {
12
12
  await this.getConfiguration().ensureConnections({name: "DB schema load"}, async (dbs) => {
13
13
  const dbDir = path.join(this.directory(), "db")
14
+ const loader = new StructureSqlLoader()
14
15
 
15
16
  for (const identifier of Object.keys(dbs)) {
16
17
  const db = dbs[identifier]
17
18
  const structureFilePath = path.join(dbDir, `structure-${identifier}.sql`)
18
19
  const structureSql = await fs.readFile(structureFilePath, "utf8")
19
20
 
20
- await this.loadStructureSql({db, structureSql})
21
+ await loader.load({db, structureSql})
21
22
  }
22
23
  })
23
24
  }
24
-
25
- /**
26
- * Runs load structure sql.
27
- * @param {object} args - Options object.
28
- * @param {import("../../../../../../database/drivers/base.js").default} args.db - Database connection.
29
- * @param {string} args.structureSql - Structure SQL to load.
30
- * @returns {Promise<void>} - Resolves when complete.
31
- */
32
- async loadStructureSql({db, structureSql}) {
33
- const statements = splitSqlStatements(structureSql)
34
-
35
- if (statements.length == 0) return
36
-
37
- const executableConnection = this.executableConnection(db)
38
-
39
- await db.disableForeignKeys()
40
-
41
- try {
42
- if (executableConnection) {
43
- await executableConnection.exec(structureSql)
44
- } else {
45
- for (const statement of statements) {
46
- await db.query(statement)
47
- }
48
- }
49
- } finally {
50
- await db.enableForeignKeys()
51
- }
52
- }
53
-
54
- /**
55
- * Runs executable connection.
56
- * @param {import("../../../../../../database/drivers/base.js").default} db - Database connection.
57
- * @returns {{exec: (sql: string) => Promise<?>} | undefined} - Connection with exec support.
58
- */
59
- executableConnection(db) {
60
- const dbWithConnection = /** @type {import("../../../../../../database/drivers/base.js").default & {connection?: ?}} */ (db)
61
- const connection = dbWithConnection.connection
62
-
63
- if (connection && typeof connection == "object" && "exec" in connection && typeof connection.exec == "function") {
64
- return /** @type {{exec: (sql: string) => Promise<?>}} */ (connection)
65
- }
66
- }
67
25
  }
@@ -101,9 +101,14 @@ export default class TenantIterator {
101
101
  if (tenant && typeof tenant === "object") {
102
102
  const tenantObject = /** @type {{id?: ?, name?: ?, slug?: ?}} */ (tenant)
103
103
 
104
- if (tenantObject.slug) return String(tenantObject.slug)
105
- if (tenantObject.name) return String(tenantObject.name)
106
- if (tenantObject.id) return String(tenantObject.id)
104
+ for (const attributeName of /** @type {Array<"slug" | "name" | "id">} */ (["slug", "name", "id"])) {
105
+ const attributeOrAccessor = tenantObject[attributeName]
106
+ const attributeValue = typeof attributeOrAccessor === "function"
107
+ ? attributeOrAccessor.call(tenant)
108
+ : attributeOrAccessor
109
+
110
+ if (attributeValue) return String(attributeValue)
111
+ }
107
112
  }
108
113
 
109
114
  return JSON.stringify(tenant)