velocious 1.0.483 → 1.0.485
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 +1 -1
- package/build/current.js +3 -2
- package/build/src/current.d.ts +4 -3
- package/build/src/current.d.ts.map +1 -1
- package/build/src/current.js +4 -3
- package/build/src/tenants/tenant.d.ts +19 -8
- package/build/src/tenants/tenant.d.ts.map +1 -1
- package/build/src/tenants/tenant.js +28 -10
- package/build/tenants/tenant.js +28 -9
- package/package.json +1 -1
- package/src/current.js +3 -2
- package/src/tenants/tenant.js +28 -9
package/README.md
CHANGED
|
@@ -2242,6 +2242,6 @@ npx velocious db:tenants:migrate projectTenant --parallel 20
|
|
|
2242
2242
|
|
|
2243
2243
|
`afterMigrateTenant` hooks run inside the active default and tenant database connection scope for the tenant being migrated.
|
|
2244
2244
|
|
|
2245
|
-
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.
|
|
2245
|
+
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).
|
|
2246
2246
|
|
|
2247
2247
|
See [docs/tenant-databases.md](docs/tenant-databases.md) for the full configuration and migration pattern.
|
package/build/current.js
CHANGED
|
@@ -70,9 +70,10 @@ export default class Current {
|
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
72
|
* Runs with tenant.
|
|
73
|
+
* @template T
|
|
73
74
|
* @param {object} tenant - Tenant. Any caller-defined object shape; read back (and narrowed) via tenant().
|
|
74
|
-
* @param {() => Promise
|
|
75
|
-
* @returns {Promise
|
|
75
|
+
* @param {() => Promise<T>} callback - Callback.
|
|
76
|
+
* @returns {Promise<T>} - Callback result.
|
|
76
77
|
*/
|
|
77
78
|
static async withTenant(tenant, callback) {
|
|
78
79
|
return await this.configuration().runWithTenant(tenant, callback)
|
package/build/src/current.d.ts
CHANGED
|
@@ -35,10 +35,11 @@ export default class Current {
|
|
|
35
35
|
static setTenant(tenant: object): void;
|
|
36
36
|
/**
|
|
37
37
|
* Runs with tenant.
|
|
38
|
+
* @template T
|
|
38
39
|
* @param {object} tenant - Tenant. Any caller-defined object shape; read back (and narrowed) via tenant().
|
|
39
|
-
* @param {() => Promise
|
|
40
|
-
* @returns {Promise
|
|
40
|
+
* @param {() => Promise<T>} callback - Callback.
|
|
41
|
+
* @returns {Promise<T>} - Callback result.
|
|
41
42
|
*/
|
|
42
|
-
static withTenant(tenant: object, callback: () => Promise<
|
|
43
|
+
static withTenant<T>(tenant: object, callback: () => Promise<T>): Promise<T>;
|
|
43
44
|
}
|
|
44
45
|
//# sourceMappingURL=current.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"current.d.ts","sourceRoot":"","sources":["../../src/current.js"],"names":[],"mappings":"AAKA;IACE;;;OAGG;IACH,wBAFa,OAAO,oBAAoB,EAAE,OAAO,CAIhD;IAED;;;OAGG;IACH,kBAFa,OAAO,4BAA4B,EAAE,OAAO,GAAG,SAAS,CAUpE;IAED;;;;OAIG;IACH,2BAHW,OAAO,4BAA4B,EAAE,OAAO,GAAG,SAAS,GACtD,IAAI,CAIhB;IAED;;;;;OAKG;IACH,4BAJW,OAAO,4BAA4B,EAAE,OAAO,GAAG,SAAS,YACxD,MAAM,OAAO,CAAC,OAAC,CAAC,GACd,OAAO,CAAC,OAAC,CAAC,CAItB;IAED;;;OAGG;IACH,iBAFa,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAU/C;IAED;;;;OAIG;IACH,yBAHW,MAAM,GACJ,IAAI,CAIhB;IAED
|
|
1
|
+
{"version":3,"file":"current.d.ts","sourceRoot":"","sources":["../../src/current.js"],"names":[],"mappings":"AAKA;IACE;;;OAGG;IACH,wBAFa,OAAO,oBAAoB,EAAE,OAAO,CAIhD;IAED;;;OAGG;IACH,kBAFa,OAAO,4BAA4B,EAAE,OAAO,GAAG,SAAS,CAUpE;IAED;;;;OAIG;IACH,2BAHW,OAAO,4BAA4B,EAAE,OAAO,GAAG,SAAS,GACtD,IAAI,CAIhB;IAED;;;;;OAKG;IACH,4BAJW,OAAO,4BAA4B,EAAE,OAAO,GAAG,SAAS,YACxD,MAAM,OAAO,CAAC,OAAC,CAAC,GACd,OAAO,CAAC,OAAC,CAAC,CAItB;IAED;;;OAGG;IACH,iBAFa,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAU/C;IAED;;;;OAIG;IACH,yBAHW,MAAM,GACJ,IAAI,CAIhB;IAED;;;;;;OAMG;IACH,kBALa,CAAC,UACH,MAAM,YACN,MAAM,OAAO,CAAC,CAAC,CAAC,GACd,OAAO,CAAC,CAAC,CAAC,CAItB;CACF"}
|
package/build/src/current.js
CHANGED
|
@@ -64,12 +64,13 @@ export default class Current {
|
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
66
66
|
* Runs with tenant.
|
|
67
|
+
* @template T
|
|
67
68
|
* @param {object} tenant - Tenant. Any caller-defined object shape; read back (and narrowed) via tenant().
|
|
68
|
-
* @param {() => Promise
|
|
69
|
-
* @returns {Promise
|
|
69
|
+
* @param {() => Promise<T>} callback - Callback.
|
|
70
|
+
* @returns {Promise<T>} - Callback result.
|
|
70
71
|
*/
|
|
71
72
|
static async withTenant(tenant, callback) {
|
|
72
73
|
return await this.configuration().runWithTenant(tenant, callback);
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
76
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VycmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jdXJyZW50LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLGFBQWEsTUFBTSxvQkFBb0IsQ0FBQTtBQUM5QyxPQUFPLEVBQUMsK0JBQStCLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQTtBQUVsRSxNQUFNLENBQUMsT0FBTyxPQUFPLE9BQU87SUFDMUI7OztPQUdHO0lBQ0gsTUFBTSxDQUFDLGFBQWE7UUFDbEIsT0FBTyxhQUFhLENBQUMsT0FBTyxFQUFFLENBQUE7SUFDaEMsQ0FBQztJQUVEOzs7T0FHRztJQUNILE1BQU0sQ0FBQyxPQUFPO1FBQ1osSUFBSSxDQUFDO1lBQ0gsT0FBTyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUMsaUJBQWlCLEVBQUUsQ0FBQTtRQUNqRCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLElBQUksS0FBSyxZQUFZLCtCQUErQjtnQkFBRSxPQUFNO1lBRTVELE1BQU0sS0FBSyxDQUFBO1FBQ2IsQ0FBQztJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPO1FBQ3ZCLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQ3pFLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxRQUFRO1FBQ3hDLE9BQU8sTUFBTSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQTtJQUNyRSxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsTUFBTSxDQUFDLE1BQU07UUFDWCxJQUFJLENBQUM7WUFDSCxPQUFPLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO1FBQ2hELENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsSUFBSSxLQUFLLFlBQVksK0JBQStCO2dCQUFFLE9BQU07WUFFNUQsTUFBTSxLQUFLLENBQUE7UUFDYixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU07UUFDckIsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDLHFCQUFxQixFQUFFLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDdkUsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxRQUFRO1FBQ3RDLE9BQU8sTUFBTSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUMsYUFBYSxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQTtJQUNuRSxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IENvbmZpZ3VyYXRpb24gZnJvbSBcIi4vY29uZmlndXJhdGlvbi5qc1wiXG5pbXBvcnQge0N1cnJlbnRDb25maWd1cmF0aW9uTm90U2V0RXJyb3J9IGZyb20gXCIuL2NvbmZpZ3VyYXRpb24uanNcIlxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDdXJyZW50IHtcbiAgLyoqXG4gICAqIFJ1bnMgY29uZmlndXJhdGlvbi5cbiAgICogQHJldHVybnMge2ltcG9ydChcIi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSAtIEN1cnJlbnQgY29uZmlndXJhdGlvbi5cbiAgICovXG4gIHN0YXRpYyBjb25maWd1cmF0aW9uKCkge1xuICAgIHJldHVybiBDb25maWd1cmF0aW9uLmN1cnJlbnQoKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgYWJpbGl0eS5cbiAgICogQHJldHVybnMge2ltcG9ydChcIi4vYXV0aG9yaXphdGlvbi9hYmlsaXR5LmpzXCIpLmRlZmF1bHQgfCB1bmRlZmluZWR9IC0gQ3VycmVudCBhYmlsaXR5LlxuICAgKi9cbiAgc3RhdGljIGFiaWxpdHkoKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB0aGlzLmNvbmZpZ3VyYXRpb24oKS5nZXRDdXJyZW50QWJpbGl0eSgpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEN1cnJlbnRDb25maWd1cmF0aW9uTm90U2V0RXJyb3IpIHJldHVyblxuXG4gICAgICB0aHJvdyBlcnJvclxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHNldCBhYmlsaXR5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vYXV0aG9yaXphdGlvbi9hYmlsaXR5LmpzXCIpLmRlZmF1bHQgfCB1bmRlZmluZWR9IGFiaWxpdHkgLSBBYmlsaXR5LlxuICAgKiBAcmV0dXJucyB7dm9pZH0gLSBObyByZXR1cm4gdmFsdWUuXG4gICAqL1xuICBzdGF0aWMgc2V0QWJpbGl0eShhYmlsaXR5KSB7XG4gICAgdGhpcy5jb25maWd1cmF0aW9uKCkuZ2V0RW52aXJvbm1lbnRIYW5kbGVyKCkuc2V0Q3VycmVudEFiaWxpdHkoYWJpbGl0eSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHdpdGggYWJpbGl0eS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2F1dGhvcml6YXRpb24vYWJpbGl0eS5qc1wiKS5kZWZhdWx0IHwgdW5kZWZpbmVkfSBhYmlsaXR5IC0gQWJpbGl0eS5cbiAgICogQHBhcmFtIHsoKSA9PiBQcm9taXNlPD8+fSBjYWxsYmFjayAtIENhbGxiYWNrLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTw/Pn0gLSBDYWxsYmFjayByZXN1bHQuXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgd2l0aEFiaWxpdHkoYWJpbGl0eSwgY2FsbGJhY2spIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5jb25maWd1cmF0aW9uKCkucnVuV2l0aEFiaWxpdHkoYWJpbGl0eSwgY2FsbGJhY2spXG4gIH1cblxuICAvKipcbiAgICogUnVucyB0ZW5hbnQuXG4gICAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZH0gLSBDdXJyZW50IHRlbmFudC5cbiAgICovXG4gIHN0YXRpYyB0ZW5hbnQoKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB0aGlzLmNvbmZpZ3VyYXRpb24oKS5nZXRDdXJyZW50VGVuYW50KClcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgQ3VycmVudENvbmZpZ3VyYXRpb25Ob3RTZXRFcnJvcikgcmV0dXJuXG5cbiAgICAgIHRocm93IGVycm9yXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc2V0IHRlbmFudC5cbiAgICogQHBhcmFtIHtvYmplY3R9IHRlbmFudCAtIFRlbmFudC4gQW55IGNhbGxlci1kZWZpbmVkIG9iamVjdCBzaGFwZTsgcmVhZCBiYWNrIChhbmQgbmFycm93ZWQpIHZpYSB0ZW5hbnQoKS5cbiAgICogQHJldHVybnMge3ZvaWR9IC0gTm8gcmV0dXJuIHZhbHVlLlxuICAgKi9cbiAgc3RhdGljIHNldFRlbmFudCh0ZW5hbnQpIHtcbiAgICB0aGlzLmNvbmZpZ3VyYXRpb24oKS5nZXRFbnZpcm9ubWVudEhhbmRsZXIoKS5zZXRDdXJyZW50VGVuYW50KHRlbmFudClcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHdpdGggdGVuYW50LlxuICAgKiBAdGVtcGxhdGUgVFxuICAgKiBAcGFyYW0ge29iamVjdH0gdGVuYW50IC0gVGVuYW50LiBBbnkgY2FsbGVyLWRlZmluZWQgb2JqZWN0IHNoYXBlOyByZWFkIGJhY2sgKGFuZCBuYXJyb3dlZCkgdmlhIHRlbmFudCgpLlxuICAgKiBAcGFyYW0geygpID0+IFByb21pc2U8VD59IGNhbGxiYWNrIC0gQ2FsbGJhY2suXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFQ+fSAtIENhbGxiYWNrIHJlc3VsdC5cbiAgICovXG4gIHN0YXRpYyBhc3luYyB3aXRoVGVuYW50KHRlbmFudCwgY2FsbGJhY2spIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5jb25maWd1cmF0aW9uKCkucnVuV2l0aFRlbmFudCh0ZW5hbnQsIGNhbGxiYWNrKVxuICB9XG59XG4iXX0=
|
|
@@ -3,18 +3,27 @@
|
|
|
3
3
|
* object the app's `tenantDatabaseResolver` understands (an account, a project, …); this
|
|
4
4
|
* class is the single discoverable home for switching into a tenant's context, reading the
|
|
5
5
|
* current one, iterating every tenant of a database identifier, and dropping a tenant's
|
|
6
|
-
* database. Switching
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* database. Switching delegates to {@link Current} (which owns the async-context tenant
|
|
7
|
+
* state) and additionally runs the callback inside `ensureConnections`, so entering a tenant
|
|
8
|
+
* makes its database immediately queryable — the apartment-style "switch" semantics — without
|
|
9
|
+
* the caller establishing connections itself; iteration and drop drive the app's tenant
|
|
10
|
+
* database provider hooks.
|
|
9
11
|
*/
|
|
10
12
|
export default class Tenant {
|
|
11
13
|
/**
|
|
12
14
|
* Runs `callback` with `tenant` as the current tenant, restoring the previous tenant after.
|
|
15
|
+
* The callback runs inside `ensureConnections`, so every database identifier the tenant
|
|
16
|
+
* activates (the global database plus the tenant's database) has a checked-out connection
|
|
17
|
+
* available for the callback's duration: switching into a tenant makes it queryable without
|
|
18
|
+
* the caller wiring up connections. Already-checked-out connections are reused, so nesting
|
|
19
|
+
* `Tenant.with` calls does not open redundant connections. The callback receives the active
|
|
20
|
+
* connections keyed by identifier, the same as `ensureConnections`.
|
|
21
|
+
* @template T
|
|
13
22
|
* @param {object} tenant Descriptor understood by the app's tenantDatabaseResolver.
|
|
14
|
-
* @param {() => Promise
|
|
15
|
-
* @returns {Promise
|
|
23
|
+
* @param {(connections: Record<string, import("../database/drivers/base.js").default>) => Promise<T>} callback
|
|
24
|
+
* @returns {Promise<T>}
|
|
16
25
|
*/
|
|
17
|
-
static with(tenant: object, callback: () => Promise<
|
|
26
|
+
static with<T>(tenant: object, callback: (connections: Record<string, import("../database/drivers/base.js").default>) => Promise<T>): Promise<T>;
|
|
18
27
|
/**
|
|
19
28
|
* The current tenant descriptor, or undefined when running outside any tenant context.
|
|
20
29
|
* @returns {Record<string, unknown> | undefined}
|
|
@@ -22,8 +31,10 @@ export default class Tenant {
|
|
|
22
31
|
static current(): Record<string, unknown> | undefined;
|
|
23
32
|
/**
|
|
24
33
|
* Lists the tenants for a database identifier through the provider and runs `callback`
|
|
25
|
-
* within each tenant's context, optionally filtered and several at a time.
|
|
26
|
-
*
|
|
34
|
+
* within each tenant's context, optionally filtered and several at a time. Like
|
|
35
|
+
* {@link Tenant.with}, the callback runs inside `ensureConnections` so each tenant's
|
|
36
|
+
* database is queryable without the caller wiring up connections. Returns how many tenants
|
|
37
|
+
* the callback ran for (after filtering).
|
|
27
38
|
* @param {{identifier: string, callback: function({databaseConfiguration: import("../configuration-types.js").DatabaseConfigurationType, tenant: ?}) : Promise<void>, parallel?: number, filter?: (tenant: ?) => boolean, configuration?: import("../configuration.js").default}} args
|
|
28
39
|
* @returns {Promise<number>}
|
|
29
40
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant.d.ts","sourceRoot":"","sources":["../../../src/tenants/tenant.js"],"names":[],"mappings":"AAKA
|
|
1
|
+
{"version":3,"file":"tenant.d.ts","sourceRoot":"","sources":["../../../src/tenants/tenant.js"],"names":[],"mappings":"AAKA;;;;;;;;;;GAUG;AACH;IACE;;;;;;;;;;;;OAYG;IACH,YALa,CAAC,UACH,MAAM,YACN,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,6BAA6B,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACxF,OAAO,CAAC,CAAC,CAAC,CAMtB;IAED;;;OAGG;IACH,kBAFa,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAI/C;IAED;;;;;;;;OAQG;IACH,uEAHW;QAAC,UAAU,EAAE,MAAM,CAAC;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,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,OAAC,KAAK,OAAO,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAA;KAAC,GACpQ,OAAO,CAAC,MAAM,CAAC,CAsB3B;IAED;;;;OAIG;IACH,mDAHW;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAA;KAAC,GACzF,OAAO,CAAC,IAAI,CAAC,CAyBzB;CACF"}
|
|
@@ -6,19 +6,29 @@ import TenantIterator from "./tenant-iterator.js";
|
|
|
6
6
|
* object the app's `tenantDatabaseResolver` understands (an account, a project, …); this
|
|
7
7
|
* class is the single discoverable home for switching into a tenant's context, reading the
|
|
8
8
|
* current one, iterating every tenant of a database identifier, and dropping a tenant's
|
|
9
|
-
* database. Switching
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* database. Switching delegates to {@link Current} (which owns the async-context tenant
|
|
10
|
+
* state) and additionally runs the callback inside `ensureConnections`, so entering a tenant
|
|
11
|
+
* makes its database immediately queryable — the apartment-style "switch" semantics — without
|
|
12
|
+
* the caller establishing connections itself; iteration and drop drive the app's tenant
|
|
13
|
+
* database provider hooks.
|
|
12
14
|
*/
|
|
13
15
|
export default class Tenant {
|
|
14
16
|
/**
|
|
15
17
|
* Runs `callback` with `tenant` as the current tenant, restoring the previous tenant after.
|
|
18
|
+
* The callback runs inside `ensureConnections`, so every database identifier the tenant
|
|
19
|
+
* activates (the global database plus the tenant's database) has a checked-out connection
|
|
20
|
+
* available for the callback's duration: switching into a tenant makes it queryable without
|
|
21
|
+
* the caller wiring up connections. Already-checked-out connections are reused, so nesting
|
|
22
|
+
* `Tenant.with` calls does not open redundant connections. The callback receives the active
|
|
23
|
+
* connections keyed by identifier, the same as `ensureConnections`.
|
|
24
|
+
* @template T
|
|
16
25
|
* @param {object} tenant Descriptor understood by the app's tenantDatabaseResolver.
|
|
17
|
-
* @param {() => Promise
|
|
18
|
-
* @returns {Promise
|
|
26
|
+
* @param {(connections: Record<string, import("../database/drivers/base.js").default>) => Promise<T>} callback
|
|
27
|
+
* @returns {Promise<T>}
|
|
19
28
|
*/
|
|
20
29
|
static async with(tenant, callback) {
|
|
21
|
-
|
|
30
|
+
const configuration = Current.configuration();
|
|
31
|
+
return await Current.withTenant(tenant, async () => await configuration.ensureConnections(callback));
|
|
22
32
|
}
|
|
23
33
|
/**
|
|
24
34
|
* The current tenant descriptor, or undefined when running outside any tenant context.
|
|
@@ -29,8 +39,10 @@ export default class Tenant {
|
|
|
29
39
|
}
|
|
30
40
|
/**
|
|
31
41
|
* Lists the tenants for a database identifier through the provider and runs `callback`
|
|
32
|
-
* within each tenant's context, optionally filtered and several at a time.
|
|
33
|
-
*
|
|
42
|
+
* within each tenant's context, optionally filtered and several at a time. Like
|
|
43
|
+
* {@link Tenant.with}, the callback runs inside `ensureConnections` so each tenant's
|
|
44
|
+
* database is queryable without the caller wiring up connections. Returns how many tenants
|
|
45
|
+
* the callback ran for (after filtering).
|
|
34
46
|
* @param {{identifier: string, callback: function({databaseConfiguration: import("../configuration-types.js").DatabaseConfigurationType, tenant: ?}) : Promise<void>, parallel?: number, filter?: (tenant: ?) => boolean, configuration?: import("../configuration.js").default}} args
|
|
35
47
|
* @returns {Promise<number>}
|
|
36
48
|
*/
|
|
@@ -44,7 +56,13 @@ export default class Tenant {
|
|
|
44
56
|
}
|
|
45
57
|
const tenants = filter ? listedTenants.filter(filter) : listedTenants;
|
|
46
58
|
const iterator = new TenantIterator({ configuration, identifier, parallelCount: parallel });
|
|
47
|
-
|
|
59
|
+
// Run each tenant's callback inside ensureConnections so the iterator stays
|
|
60
|
+
// connection-agnostic (the db:tenants:* CLI commands share TenantIterator and must run
|
|
61
|
+
// their callbacks, such as create, before the tenant database exists) while runtime
|
|
62
|
+
// iteration here gets the tenant's connections established the same way Tenant.with does.
|
|
63
|
+
return await iterator.run(tenants, async (callbackArgs) => {
|
|
64
|
+
await configuration.ensureConnections({ name: `Tenant.each: ${identifier}` }, async () => await callback(callbackArgs));
|
|
65
|
+
});
|
|
48
66
|
}
|
|
49
67
|
/**
|
|
50
68
|
* Drops one tenant's database/schema through the provider's `dropDatabase` hook.
|
|
@@ -73,4 +91,4 @@ export default class Tenant {
|
|
|
73
91
|
});
|
|
74
92
|
}
|
|
75
93
|
}
|
|
76
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVuYW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RlbmFudHMvdGVuYW50LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLE9BQU8sTUFBTSxlQUFlLENBQUE7QUFDbkMsT0FBTyxjQUFjLE1BQU0sc0JBQXNCLENBQUE7QUFFakQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLE1BQU07SUFDekI7Ozs7O09BS0c7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsUUFBUTtRQUNoQyxPQUFPLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUE7SUFDbkQsQ0FBQztJQUVEOzs7T0FHRztJQUNILE1BQU0sQ0FBQyxPQUFPO1FBQ1osT0FBTyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUE7SUFDekIsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUMsVUFBVSxFQUFFLFFBQVEsRUFBRSxRQUFRLEdBQUcsQ0FBQyxFQUFFLE1BQU0sRUFBRSxhQUFhLEdBQUcsT0FBTyxDQUFDLGFBQWEsRUFBRSxFQUFDO1FBQ3JHLE1BQU0sUUFBUSxHQUFHLGFBQWEsQ0FBQyx5QkFBeUIsQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUNwRSxNQUFNLGFBQWEsR0FBRyxNQUFNLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFDLElBQUksRUFBRSxnQkFBZ0IsVUFBVSxFQUFFLEVBQUMsRUFBRSxLQUFLLElBQUksRUFBRTtZQUMzRyxPQUFPLE1BQU0sUUFBUSxDQUFDLFdBQVcsQ0FBQyxFQUFDLGFBQWEsRUFBRSxVQUFVLEVBQUMsQ0FBQyxDQUFBO1FBQ2hFLENBQUMsQ0FBQyxDQUFBO1FBRUYsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztZQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLGdDQUFnQyxVQUFVLHdDQUF3QyxDQUFDLENBQUE7UUFDckcsQ0FBQztRQUVELE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFBO1FBQ3JFLE1BQU0sUUFBUSxHQUFHLElBQUksY0FBYyxDQUFDLEVBQUMsYUFBYSxFQUFFLFVBQVUsRUFBRSxhQUFhLEVBQUUsUUFBUSxFQUFDLENBQUMsQ0FBQTtRQUV6RixPQUFPLE1BQU0sUUFBUSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7SUFDOUMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsYUFBYSxHQUFHLE9BQU8sQ0FBQyxhQUFhLEVBQUUsRUFBQztRQUM3RSxNQUFNLFFBQVEsR0FBRyxhQUFhLENBQUMseUJBQXlCLENBQUMsVUFBVSxDQUFDLENBQUE7UUFFcEUsSUFBSSxPQUFPLFFBQVEsQ0FBQyxZQUFZLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDaEQsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQ0FBZ0MsVUFBVSw0Q0FBNEMsQ0FBQyxDQUFBO1FBQ3pHLENBQUM7UUFFRCxNQUFNLGFBQWEsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ25ELHFGQUFxRjtZQUNyRixxRkFBcUY7WUFDckYsd0ZBQXdGO1lBQ3hGLHdFQUF3RTtZQUN4RSxJQUFJLENBQUMsYUFBYSxDQUFDLDBCQUEwQixDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7Z0JBQzFELE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLFVBQVUsNEJBQTRCLGNBQWMsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFBO1lBQzNILENBQUM7WUFFRCxNQUFNLFFBQVEsQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDNUIsYUFBYTtnQkFDYixxQkFBcUIsRUFBRSxhQUFhLENBQUMsNEJBQTRCLENBQUMsVUFBVSxDQUFDO2dCQUM3RSxVQUFVO2dCQUNWLE1BQU07YUFDUCxDQUFDLENBQUE7UUFDSixDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgQ3VycmVudCBmcm9tIFwiLi4vY3VycmVudC5qc1wiXG5pbXBvcnQgVGVuYW50SXRlcmF0b3IgZnJvbSBcIi4vdGVuYW50LWl0ZXJhdG9yLmpzXCJcblxuLyoqXG4gKiBBcGFydG1lbnQtc3R5bGUgcnVudGltZSBmYcOnYWRlIGZvciBtdWx0aS10ZW5hbnQgYXBwcy4gQSBcInRlbmFudFwiIGlzIHdoYXRldmVyIGRlc2NyaXB0b3JcbiAqIG9iamVjdCB0aGUgYXBwJ3MgYHRlbmFudERhdGFiYXNlUmVzb2x2ZXJgIHVuZGVyc3RhbmRzIChhbiBhY2NvdW50LCBhIHByb2plY3QsIOKApik7IHRoaXNcbiAqIGNsYXNzIGlzIHRoZSBzaW5nbGUgZGlzY292ZXJhYmxlIGhvbWUgZm9yIHN3aXRjaGluZyBpbnRvIGEgdGVuYW50J3MgY29udGV4dCwgcmVhZGluZyB0aGVcbiAqIGN1cnJlbnQgb25lLCBpdGVyYXRpbmcgZXZlcnkgdGVuYW50IG9mIGEgZGF0YWJhc2UgaWRlbnRpZmllciwgYW5kIGRyb3BwaW5nIGEgdGVuYW50J3NcbiAqIGRhdGFiYXNlLiBTd2l0Y2hpbmcvcmVhZGluZyBkZWxlZ2F0ZSB0byB7QGxpbmsgQ3VycmVudH0gKHdoaWNoIG93bnMgdGhlIGFzeW5jLWNvbnRleHRcbiAqIHRlbmFudCBzdGF0ZSksIHNvIHRoZXkgY29tcG9zZSB3aXRoIHRoZSBleGlzdGluZyBjb25uZWN0aW9uIHBvb2xzIGFuZCByZXF1ZXN0IGxpZmVjeWNsZTtcbiAqIGl0ZXJhdGlvbiBhbmQgZHJvcCBkcml2ZSB0aGUgYXBwJ3MgdGVuYW50IGRhdGFiYXNlIHByb3ZpZGVyIGhvb2tzLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUZW5hbnQge1xuICAvKipcbiAgICogUnVucyBgY2FsbGJhY2tgIHdpdGggYHRlbmFudGAgYXMgdGhlIGN1cnJlbnQgdGVuYW50LCByZXN0b3JpbmcgdGhlIHByZXZpb3VzIHRlbmFudCBhZnRlci5cbiAgICogQHBhcmFtIHtvYmplY3R9IHRlbmFudCBEZXNjcmlwdG9yIHVuZGVyc3Rvb2QgYnkgdGhlIGFwcCdzIHRlbmFudERhdGFiYXNlUmVzb2x2ZXIuXG4gICAqIEBwYXJhbSB7KCkgPT4gUHJvbWlzZTw/Pn0gY2FsbGJhY2tcbiAgICogQHJldHVybnMge1Byb21pc2U8Pz59XG4gICAqL1xuICBzdGF0aWMgYXN5bmMgd2l0aCh0ZW5hbnQsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIGF3YWl0IEN1cnJlbnQud2l0aFRlbmFudCh0ZW5hbnQsIGNhbGxiYWNrKVxuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBjdXJyZW50IHRlbmFudCBkZXNjcmlwdG9yLCBvciB1bmRlZmluZWQgd2hlbiBydW5uaW5nIG91dHNpZGUgYW55IHRlbmFudCBjb250ZXh0LlxuICAgKiBAcmV0dXJucyB7UmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWR9XG4gICAqL1xuICBzdGF0aWMgY3VycmVudCgpIHtcbiAgICByZXR1cm4gQ3VycmVudC50ZW5hbnQoKVxuICB9XG5cbiAgLyoqXG4gICAqIExpc3RzIHRoZSB0ZW5hbnRzIGZvciBhIGRhdGFiYXNlIGlkZW50aWZpZXIgdGhyb3VnaCB0aGUgcHJvdmlkZXIgYW5kIHJ1bnMgYGNhbGxiYWNrYFxuICAgKiB3aXRoaW4gZWFjaCB0ZW5hbnQncyBjb250ZXh0LCBvcHRpb25hbGx5IGZpbHRlcmVkIGFuZCBzZXZlcmFsIGF0IGEgdGltZS4gUmV0dXJucyBob3dcbiAgICogbWFueSB0ZW5hbnRzIHRoZSBjYWxsYmFjayByYW4gZm9yIChhZnRlciBmaWx0ZXJpbmcpLlxuICAgKiBAcGFyYW0ge3tpZGVudGlmaWVyOiBzdHJpbmcsIGNhbGxiYWNrOiBmdW5jdGlvbih7ZGF0YWJhc2VDb25maWd1cmF0aW9uOiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLXR5cGVzLmpzXCIpLkRhdGFiYXNlQ29uZmlndXJhdGlvblR5cGUsIHRlbmFudDogP30pIDogUHJvbWlzZTx2b2lkPiwgcGFyYWxsZWw/OiBudW1iZXIsIGZpbHRlcj86ICh0ZW5hbnQ6ID8pID0+IGJvb2xlYW4sIGNvbmZpZ3VyYXRpb24/OiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9fSBhcmdzXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPG51bWJlcj59XG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZWFjaCh7aWRlbnRpZmllciwgY2FsbGJhY2ssIHBhcmFsbGVsID0gMSwgZmlsdGVyLCBjb25maWd1cmF0aW9uID0gQ3VycmVudC5jb25maWd1cmF0aW9uKCl9KSB7XG4gICAgY29uc3QgcHJvdmlkZXIgPSBjb25maWd1cmF0aW9uLmdldFRlbmFudERhdGFiYXNlUHJvdmlkZXIoaWRlbnRpZmllcilcbiAgICBjb25zdCBsaXN0ZWRUZW5hbnRzID0gYXdhaXQgY29uZmlndXJhdGlvbi5lbnN1cmVDb25uZWN0aW9ucyh7bmFtZTogYFRlbmFudC5lYWNoOiAke2lkZW50aWZpZXJ9YH0sIGFzeW5jICgpID0+IHtcbiAgICAgIHJldHVybiBhd2FpdCBwcm92aWRlci5saXN0VGVuYW50cyh7Y29uZmlndXJhdGlvbiwgaWRlbnRpZmllcn0pXG4gICAgfSlcblxuICAgIGlmICghQXJyYXkuaXNBcnJheShsaXN0ZWRUZW5hbnRzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUZW5hbnQgZGF0YWJhc2UgcHJvdmlkZXIgZm9yICR7aWRlbnRpZmllcn0gbXVzdCByZXR1cm4gYW4gYXJyYXkgZnJvbSBsaXN0VGVuYW50c2ApXG4gICAgfVxuXG4gICAgY29uc3QgdGVuYW50cyA9IGZpbHRlciA/IGxpc3RlZFRlbmFudHMuZmlsdGVyKGZpbHRlcikgOiBsaXN0ZWRUZW5hbnRzXG4gICAgY29uc3QgaXRlcmF0b3IgPSBuZXcgVGVuYW50SXRlcmF0b3Ioe2NvbmZpZ3VyYXRpb24sIGlkZW50aWZpZXIsIHBhcmFsbGVsQ291bnQ6IHBhcmFsbGVsfSlcblxuICAgIHJldHVybiBhd2FpdCBpdGVyYXRvci5ydW4odGVuYW50cywgY2FsbGJhY2spXG4gIH1cblxuICAvKipcbiAgICogRHJvcHMgb25lIHRlbmFudCdzIGRhdGFiYXNlL3NjaGVtYSB0aHJvdWdoIHRoZSBwcm92aWRlcidzIGBkcm9wRGF0YWJhc2VgIGhvb2suXG4gICAqIEBwYXJhbSB7e2lkZW50aWZpZXI6IHN0cmluZywgdGVuYW50OiBvYmplY3QsIGNvbmZpZ3VyYXRpb24/OiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9fSBhcmdzXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGRyb3Aoe2lkZW50aWZpZXIsIHRlbmFudCwgY29uZmlndXJhdGlvbiA9IEN1cnJlbnQuY29uZmlndXJhdGlvbigpfSkge1xuICAgIGNvbnN0IHByb3ZpZGVyID0gY29uZmlndXJhdGlvbi5nZXRUZW5hbnREYXRhYmFzZVByb3ZpZGVyKGlkZW50aWZpZXIpXG5cbiAgICBpZiAodHlwZW9mIHByb3ZpZGVyLmRyb3BEYXRhYmFzZSAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRlbmFudCBkYXRhYmFzZSBwcm92aWRlciBmb3IgJHtpZGVudGlmaWVyfSBtdXN0IGRlZmluZSBkcm9wRGF0YWJhc2UgdG8gZHJvcCBhIHRlbmFudGApXG4gICAgfVxuXG4gICAgYXdhaXQgY29uZmlndXJhdGlvbi5ydW5XaXRoVGVuYW50KHRlbmFudCwgYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gR3VhcmQgYWdhaW5zdCBhbiB1bnJlc29sdmVkIHRlbmFudC4gcmVzb2x2ZURhdGFiYXNlQ29uZmlndXJhdGlvbiBmYWxscyBiYWNrIHRvIHRoZVxuICAgICAgLy8gYmFzZSAodGVtcGxhdGUvZGVmYXVsdCkgdGVuYW50IGRhdGFiYXNlIHdoZW4gdGhlIHJlc29sdmVyIHJldHVybnMgbm90aGluZyBmb3IgdGhpc1xuICAgICAgLy8gZGVzY3JpcHRvciwgc28gd2l0aG91dCB0aGlzIGNoZWNrIGEgcHJvdmlkZXIgdGhhdCBkcm9wcyBieSBkYXRhYmFzZUNvbmZpZ3VyYXRpb24ubmFtZVxuICAgICAgLy8gd291bGQgZHJvcCB0aGUgdGVtcGxhdGUgZGF0YWJhc2UgaW5zdGVhZCBvZiByZWplY3RpbmcgdGhlIGJhZCB0ZW5hbnQuXG4gICAgICBpZiAoIWNvbmZpZ3VyYXRpb24uaXNEYXRhYmFzZUlkZW50aWZpZXJBY3RpdmUoaWRlbnRpZmllcikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUZW5hbnQgZGF0YWJhc2UgaWRlbnRpZmllciAke2lkZW50aWZpZXJ9IGlzIGluYWN0aXZlIGZvciB0ZW5hbnQ6ICR7VGVuYW50SXRlcmF0b3IudGVuYW50TGFiZWwodGVuYW50KX1gKVxuICAgICAgfVxuXG4gICAgICBhd2FpdCBwcm92aWRlci5kcm9wRGF0YWJhc2U/Lih7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24sXG4gICAgICAgIGRhdGFiYXNlQ29uZmlndXJhdGlvbjogY29uZmlndXJhdGlvbi5yZXNvbHZlRGF0YWJhc2VDb25maWd1cmF0aW9uKGlkZW50aWZpZXIpLFxuICAgICAgICBpZGVudGlmaWVyLFxuICAgICAgICB0ZW5hbnRcbiAgICAgIH0pXG4gICAgfSlcbiAgfVxufVxuIl19
|
|
94
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVuYW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RlbmFudHMvdGVuYW50LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLE9BQU8sTUFBTSxlQUFlLENBQUE7QUFDbkMsT0FBTyxjQUFjLE1BQU0sc0JBQXNCLENBQUE7QUFFakQ7Ozs7Ozs7Ozs7R0FVRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sTUFBTTtJQUN6Qjs7Ozs7Ozs7Ozs7O09BWUc7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsUUFBUTtRQUNoQyxNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsYUFBYSxFQUFFLENBQUE7UUFFN0MsT0FBTyxNQUFNLE9BQU8sQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsTUFBTSxhQUFhLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQTtJQUN0RyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsTUFBTSxDQUFDLE9BQU87UUFDWixPQUFPLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQTtJQUN6QixDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFDLFVBQVUsRUFBRSxRQUFRLEVBQUUsUUFBUSxHQUFHLENBQUMsRUFBRSxNQUFNLEVBQUUsYUFBYSxHQUFHLE9BQU8sQ0FBQyxhQUFhLEVBQUUsRUFBQztRQUNyRyxNQUFNLFFBQVEsR0FBRyxhQUFhLENBQUMseUJBQXlCLENBQUMsVUFBVSxDQUFDLENBQUE7UUFDcEUsTUFBTSxhQUFhLEdBQUcsTUFBTSxhQUFhLENBQUMsaUJBQWlCLENBQUMsRUFBQyxJQUFJLEVBQUUsZ0JBQWdCLFVBQVUsRUFBRSxFQUFDLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDM0csT0FBTyxNQUFNLFFBQVEsQ0FBQyxXQUFXLENBQUMsRUFBQyxhQUFhLEVBQUUsVUFBVSxFQUFDLENBQUMsQ0FBQTtRQUNoRSxDQUFDLENBQUMsQ0FBQTtRQUVGLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUM7WUFDbEMsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQ0FBZ0MsVUFBVSx3Q0FBd0MsQ0FBQyxDQUFBO1FBQ3JHLENBQUM7UUFFRCxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQTtRQUNyRSxNQUFNLFFBQVEsR0FBRyxJQUFJLGNBQWMsQ0FBQyxFQUFDLGFBQWEsRUFBRSxVQUFVLEVBQUUsYUFBYSxFQUFFLFFBQVEsRUFBQyxDQUFDLENBQUE7UUFFekYsNEVBQTRFO1FBQzVFLHVGQUF1RjtRQUN2RixvRkFBb0Y7UUFDcEYsMEZBQTBGO1FBQzFGLE9BQU8sTUFBTSxRQUFRLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEVBQUU7WUFDeEQsTUFBTSxhQUFhLENBQUMsaUJBQWlCLENBQUMsRUFBQyxJQUFJLEVBQUUsZ0JBQWdCLFVBQVUsRUFBRSxFQUFDLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxNQUFNLFFBQVEsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFBO1FBQ3ZILENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsYUFBYSxHQUFHLE9BQU8sQ0FBQyxhQUFhLEVBQUUsRUFBQztRQUM3RSxNQUFNLFFBQVEsR0FBRyxhQUFhLENBQUMseUJBQXlCLENBQUMsVUFBVSxDQUFDLENBQUE7UUFFcEUsSUFBSSxPQUFPLFFBQVEsQ0FBQyxZQUFZLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDaEQsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQ0FBZ0MsVUFBVSw0Q0FBNEMsQ0FBQyxDQUFBO1FBQ3pHLENBQUM7UUFFRCxNQUFNLGFBQWEsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ25ELHFGQUFxRjtZQUNyRixxRkFBcUY7WUFDckYsd0ZBQXdGO1lBQ3hGLHdFQUF3RTtZQUN4RSxJQUFJLENBQUMsYUFBYSxDQUFDLDBCQUEwQixDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7Z0JBQzFELE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLFVBQVUsNEJBQTRCLGNBQWMsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFBO1lBQzNILENBQUM7WUFFRCxNQUFNLFFBQVEsQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDNUIsYUFBYTtnQkFDYixxQkFBcUIsRUFBRSxhQUFhLENBQUMsNEJBQTRCLENBQUMsVUFBVSxDQUFDO2dCQUM3RSxVQUFVO2dCQUNWLE1BQU07YUFDUCxDQUFDLENBQUE7UUFDSixDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgQ3VycmVudCBmcm9tIFwiLi4vY3VycmVudC5qc1wiXG5pbXBvcnQgVGVuYW50SXRlcmF0b3IgZnJvbSBcIi4vdGVuYW50LWl0ZXJhdG9yLmpzXCJcblxuLyoqXG4gKiBBcGFydG1lbnQtc3R5bGUgcnVudGltZSBmYcOnYWRlIGZvciBtdWx0aS10ZW5hbnQgYXBwcy4gQSBcInRlbmFudFwiIGlzIHdoYXRldmVyIGRlc2NyaXB0b3JcbiAqIG9iamVjdCB0aGUgYXBwJ3MgYHRlbmFudERhdGFiYXNlUmVzb2x2ZXJgIHVuZGVyc3RhbmRzIChhbiBhY2NvdW50LCBhIHByb2plY3QsIOKApik7IHRoaXNcbiAqIGNsYXNzIGlzIHRoZSBzaW5nbGUgZGlzY292ZXJhYmxlIGhvbWUgZm9yIHN3aXRjaGluZyBpbnRvIGEgdGVuYW50J3MgY29udGV4dCwgcmVhZGluZyB0aGVcbiAqIGN1cnJlbnQgb25lLCBpdGVyYXRpbmcgZXZlcnkgdGVuYW50IG9mIGEgZGF0YWJhc2UgaWRlbnRpZmllciwgYW5kIGRyb3BwaW5nIGEgdGVuYW50J3NcbiAqIGRhdGFiYXNlLiBTd2l0Y2hpbmcgZGVsZWdhdGVzIHRvIHtAbGluayBDdXJyZW50fSAod2hpY2ggb3ducyB0aGUgYXN5bmMtY29udGV4dCB0ZW5hbnRcbiAqIHN0YXRlKSBhbmQgYWRkaXRpb25hbGx5IHJ1bnMgdGhlIGNhbGxiYWNrIGluc2lkZSBgZW5zdXJlQ29ubmVjdGlvbnNgLCBzbyBlbnRlcmluZyBhIHRlbmFudFxuICogbWFrZXMgaXRzIGRhdGFiYXNlIGltbWVkaWF0ZWx5IHF1ZXJ5YWJsZSDigJQgdGhlIGFwYXJ0bWVudC1zdHlsZSBcInN3aXRjaFwiIHNlbWFudGljcyDigJQgd2l0aG91dFxuICogdGhlIGNhbGxlciBlc3RhYmxpc2hpbmcgY29ubmVjdGlvbnMgaXRzZWxmOyBpdGVyYXRpb24gYW5kIGRyb3AgZHJpdmUgdGhlIGFwcCdzIHRlbmFudFxuICogZGF0YWJhc2UgcHJvdmlkZXIgaG9va3MuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRlbmFudCB7XG4gIC8qKlxuICAgKiBSdW5zIGBjYWxsYmFja2Agd2l0aCBgdGVuYW50YCBhcyB0aGUgY3VycmVudCB0ZW5hbnQsIHJlc3RvcmluZyB0aGUgcHJldmlvdXMgdGVuYW50IGFmdGVyLlxuICAgKiBUaGUgY2FsbGJhY2sgcnVucyBpbnNpZGUgYGVuc3VyZUNvbm5lY3Rpb25zYCwgc28gZXZlcnkgZGF0YWJhc2UgaWRlbnRpZmllciB0aGUgdGVuYW50XG4gICAqIGFjdGl2YXRlcyAodGhlIGdsb2JhbCBkYXRhYmFzZSBwbHVzIHRoZSB0ZW5hbnQncyBkYXRhYmFzZSkgaGFzIGEgY2hlY2tlZC1vdXQgY29ubmVjdGlvblxuICAgKiBhdmFpbGFibGUgZm9yIHRoZSBjYWxsYmFjaydzIGR1cmF0aW9uOiBzd2l0Y2hpbmcgaW50byBhIHRlbmFudCBtYWtlcyBpdCBxdWVyeWFibGUgd2l0aG91dFxuICAgKiB0aGUgY2FsbGVyIHdpcmluZyB1cCBjb25uZWN0aW9ucy4gQWxyZWFkeS1jaGVja2VkLW91dCBjb25uZWN0aW9ucyBhcmUgcmV1c2VkLCBzbyBuZXN0aW5nXG4gICAqIGBUZW5hbnQud2l0aGAgY2FsbHMgZG9lcyBub3Qgb3BlbiByZWR1bmRhbnQgY29ubmVjdGlvbnMuIFRoZSBjYWxsYmFjayByZWNlaXZlcyB0aGUgYWN0aXZlXG4gICAqIGNvbm5lY3Rpb25zIGtleWVkIGJ5IGlkZW50aWZpZXIsIHRoZSBzYW1lIGFzIGBlbnN1cmVDb25uZWN0aW9uc2AuXG4gICAqIEB0ZW1wbGF0ZSBUXG4gICAqIEBwYXJhbSB7b2JqZWN0fSB0ZW5hbnQgRGVzY3JpcHRvciB1bmRlcnN0b29kIGJ5IHRoZSBhcHAncyB0ZW5hbnREYXRhYmFzZVJlc29sdmVyLlxuICAgKiBAcGFyYW0geyhjb25uZWN0aW9uczogUmVjb3JkPHN0cmluZywgaW1wb3J0KFwiLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHQ+KSA9PiBQcm9taXNlPFQ+fSBjYWxsYmFja1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxUPn1cbiAgICovXG4gIHN0YXRpYyBhc3luYyB3aXRoKHRlbmFudCwgY2FsbGJhY2spIHtcbiAgICBjb25zdCBjb25maWd1cmF0aW9uID0gQ3VycmVudC5jb25maWd1cmF0aW9uKClcblxuICAgIHJldHVybiBhd2FpdCBDdXJyZW50LndpdGhUZW5hbnQodGVuYW50LCBhc3luYyAoKSA9PiBhd2FpdCBjb25maWd1cmF0aW9uLmVuc3VyZUNvbm5lY3Rpb25zKGNhbGxiYWNrKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgY3VycmVudCB0ZW5hbnQgZGVzY3JpcHRvciwgb3IgdW5kZWZpbmVkIHdoZW4gcnVubmluZyBvdXRzaWRlIGFueSB0ZW5hbnQgY29udGV4dC5cbiAgICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkfVxuICAgKi9cbiAgc3RhdGljIGN1cnJlbnQoKSB7XG4gICAgcmV0dXJuIEN1cnJlbnQudGVuYW50KClcbiAgfVxuXG4gIC8qKlxuICAgKiBMaXN0cyB0aGUgdGVuYW50cyBmb3IgYSBkYXRhYmFzZSBpZGVudGlmaWVyIHRocm91Z2ggdGhlIHByb3ZpZGVyIGFuZCBydW5zIGBjYWxsYmFja2BcbiAgICogd2l0aGluIGVhY2ggdGVuYW50J3MgY29udGV4dCwgb3B0aW9uYWxseSBmaWx0ZXJlZCBhbmQgc2V2ZXJhbCBhdCBhIHRpbWUuIExpa2VcbiAgICoge0BsaW5rIFRlbmFudC53aXRofSwgdGhlIGNhbGxiYWNrIHJ1bnMgaW5zaWRlIGBlbnN1cmVDb25uZWN0aW9uc2Agc28gZWFjaCB0ZW5hbnQnc1xuICAgKiBkYXRhYmFzZSBpcyBxdWVyeWFibGUgd2l0aG91dCB0aGUgY2FsbGVyIHdpcmluZyB1cCBjb25uZWN0aW9ucy4gUmV0dXJucyBob3cgbWFueSB0ZW5hbnRzXG4gICAqIHRoZSBjYWxsYmFjayByYW4gZm9yIChhZnRlciBmaWx0ZXJpbmcpLlxuICAgKiBAcGFyYW0ge3tpZGVudGlmaWVyOiBzdHJpbmcsIGNhbGxiYWNrOiBmdW5jdGlvbih7ZGF0YWJhc2VDb25maWd1cmF0aW9uOiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLXR5cGVzLmpzXCIpLkRhdGFiYXNlQ29uZmlndXJhdGlvblR5cGUsIHRlbmFudDogP30pIDogUHJvbWlzZTx2b2lkPiwgcGFyYWxsZWw/OiBudW1iZXIsIGZpbHRlcj86ICh0ZW5hbnQ6ID8pID0+IGJvb2xlYW4sIGNvbmZpZ3VyYXRpb24/OiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9fSBhcmdzXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPG51bWJlcj59XG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZWFjaCh7aWRlbnRpZmllciwgY2FsbGJhY2ssIHBhcmFsbGVsID0gMSwgZmlsdGVyLCBjb25maWd1cmF0aW9uID0gQ3VycmVudC5jb25maWd1cmF0aW9uKCl9KSB7XG4gICAgY29uc3QgcHJvdmlkZXIgPSBjb25maWd1cmF0aW9uLmdldFRlbmFudERhdGFiYXNlUHJvdmlkZXIoaWRlbnRpZmllcilcbiAgICBjb25zdCBsaXN0ZWRUZW5hbnRzID0gYXdhaXQgY29uZmlndXJhdGlvbi5lbnN1cmVDb25uZWN0aW9ucyh7bmFtZTogYFRlbmFudC5lYWNoOiAke2lkZW50aWZpZXJ9YH0sIGFzeW5jICgpID0+IHtcbiAgICAgIHJldHVybiBhd2FpdCBwcm92aWRlci5saXN0VGVuYW50cyh7Y29uZmlndXJhdGlvbiwgaWRlbnRpZmllcn0pXG4gICAgfSlcblxuICAgIGlmICghQXJyYXkuaXNBcnJheShsaXN0ZWRUZW5hbnRzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUZW5hbnQgZGF0YWJhc2UgcHJvdmlkZXIgZm9yICR7aWRlbnRpZmllcn0gbXVzdCByZXR1cm4gYW4gYXJyYXkgZnJvbSBsaXN0VGVuYW50c2ApXG4gICAgfVxuXG4gICAgY29uc3QgdGVuYW50cyA9IGZpbHRlciA/IGxpc3RlZFRlbmFudHMuZmlsdGVyKGZpbHRlcikgOiBsaXN0ZWRUZW5hbnRzXG4gICAgY29uc3QgaXRlcmF0b3IgPSBuZXcgVGVuYW50SXRlcmF0b3Ioe2NvbmZpZ3VyYXRpb24sIGlkZW50aWZpZXIsIHBhcmFsbGVsQ291bnQ6IHBhcmFsbGVsfSlcblxuICAgIC8vIFJ1biBlYWNoIHRlbmFudCdzIGNhbGxiYWNrIGluc2lkZSBlbnN1cmVDb25uZWN0aW9ucyBzbyB0aGUgaXRlcmF0b3Igc3RheXNcbiAgICAvLyBjb25uZWN0aW9uLWFnbm9zdGljICh0aGUgZGI6dGVuYW50czoqIENMSSBjb21tYW5kcyBzaGFyZSBUZW5hbnRJdGVyYXRvciBhbmQgbXVzdCBydW5cbiAgICAvLyB0aGVpciBjYWxsYmFja3MsIHN1Y2ggYXMgY3JlYXRlLCBiZWZvcmUgdGhlIHRlbmFudCBkYXRhYmFzZSBleGlzdHMpIHdoaWxlIHJ1bnRpbWVcbiAgICAvLyBpdGVyYXRpb24gaGVyZSBnZXRzIHRoZSB0ZW5hbnQncyBjb25uZWN0aW9ucyBlc3RhYmxpc2hlZCB0aGUgc2FtZSB3YXkgVGVuYW50LndpdGggZG9lcy5cbiAgICByZXR1cm4gYXdhaXQgaXRlcmF0b3IucnVuKHRlbmFudHMsIGFzeW5jIChjYWxsYmFja0FyZ3MpID0+IHtcbiAgICAgIGF3YWl0IGNvbmZpZ3VyYXRpb24uZW5zdXJlQ29ubmVjdGlvbnMoe25hbWU6IGBUZW5hbnQuZWFjaDogJHtpZGVudGlmaWVyfWB9LCBhc3luYyAoKSA9PiBhd2FpdCBjYWxsYmFjayhjYWxsYmFja0FyZ3MpKVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogRHJvcHMgb25lIHRlbmFudCdzIGRhdGFiYXNlL3NjaGVtYSB0aHJvdWdoIHRoZSBwcm92aWRlcidzIGBkcm9wRGF0YWJhc2VgIGhvb2suXG4gICAqIEBwYXJhbSB7e2lkZW50aWZpZXI6IHN0cmluZywgdGVuYW50OiBvYmplY3QsIGNvbmZpZ3VyYXRpb24/OiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9fSBhcmdzXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGRyb3Aoe2lkZW50aWZpZXIsIHRlbmFudCwgY29uZmlndXJhdGlvbiA9IEN1cnJlbnQuY29uZmlndXJhdGlvbigpfSkge1xuICAgIGNvbnN0IHByb3ZpZGVyID0gY29uZmlndXJhdGlvbi5nZXRUZW5hbnREYXRhYmFzZVByb3ZpZGVyKGlkZW50aWZpZXIpXG5cbiAgICBpZiAodHlwZW9mIHByb3ZpZGVyLmRyb3BEYXRhYmFzZSAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRlbmFudCBkYXRhYmFzZSBwcm92aWRlciBmb3IgJHtpZGVudGlmaWVyfSBtdXN0IGRlZmluZSBkcm9wRGF0YWJhc2UgdG8gZHJvcCBhIHRlbmFudGApXG4gICAgfVxuXG4gICAgYXdhaXQgY29uZmlndXJhdGlvbi5ydW5XaXRoVGVuYW50KHRlbmFudCwgYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gR3VhcmQgYWdhaW5zdCBhbiB1bnJlc29sdmVkIHRlbmFudC4gcmVzb2x2ZURhdGFiYXNlQ29uZmlndXJhdGlvbiBmYWxscyBiYWNrIHRvIHRoZVxuICAgICAgLy8gYmFzZSAodGVtcGxhdGUvZGVmYXVsdCkgdGVuYW50IGRhdGFiYXNlIHdoZW4gdGhlIHJlc29sdmVyIHJldHVybnMgbm90aGluZyBmb3IgdGhpc1xuICAgICAgLy8gZGVzY3JpcHRvciwgc28gd2l0aG91dCB0aGlzIGNoZWNrIGEgcHJvdmlkZXIgdGhhdCBkcm9wcyBieSBkYXRhYmFzZUNvbmZpZ3VyYXRpb24ubmFtZVxuICAgICAgLy8gd291bGQgZHJvcCB0aGUgdGVtcGxhdGUgZGF0YWJhc2UgaW5zdGVhZCBvZiByZWplY3RpbmcgdGhlIGJhZCB0ZW5hbnQuXG4gICAgICBpZiAoIWNvbmZpZ3VyYXRpb24uaXNEYXRhYmFzZUlkZW50aWZpZXJBY3RpdmUoaWRlbnRpZmllcikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUZW5hbnQgZGF0YWJhc2UgaWRlbnRpZmllciAke2lkZW50aWZpZXJ9IGlzIGluYWN0aXZlIGZvciB0ZW5hbnQ6ICR7VGVuYW50SXRlcmF0b3IudGVuYW50TGFiZWwodGVuYW50KX1gKVxuICAgICAgfVxuXG4gICAgICBhd2FpdCBwcm92aWRlci5kcm9wRGF0YWJhc2U/Lih7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24sXG4gICAgICAgIGRhdGFiYXNlQ29uZmlndXJhdGlvbjogY29uZmlndXJhdGlvbi5yZXNvbHZlRGF0YWJhc2VDb25maWd1cmF0aW9uKGlkZW50aWZpZXIpLFxuICAgICAgICBpZGVudGlmaWVyLFxuICAgICAgICB0ZW5hbnRcbiAgICAgIH0pXG4gICAgfSlcbiAgfVxufVxuIl19
|
package/build/tenants/tenant.js
CHANGED
|
@@ -8,19 +8,30 @@ import TenantIterator from "./tenant-iterator.js"
|
|
|
8
8
|
* object the app's `tenantDatabaseResolver` understands (an account, a project, …); this
|
|
9
9
|
* class is the single discoverable home for switching into a tenant's context, reading the
|
|
10
10
|
* current one, iterating every tenant of a database identifier, and dropping a tenant's
|
|
11
|
-
* database. Switching
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* database. Switching delegates to {@link Current} (which owns the async-context tenant
|
|
12
|
+
* state) and additionally runs the callback inside `ensureConnections`, so entering a tenant
|
|
13
|
+
* makes its database immediately queryable — the apartment-style "switch" semantics — without
|
|
14
|
+
* the caller establishing connections itself; iteration and drop drive the app's tenant
|
|
15
|
+
* database provider hooks.
|
|
14
16
|
*/
|
|
15
17
|
export default class Tenant {
|
|
16
18
|
/**
|
|
17
19
|
* Runs `callback` with `tenant` as the current tenant, restoring the previous tenant after.
|
|
20
|
+
* The callback runs inside `ensureConnections`, so every database identifier the tenant
|
|
21
|
+
* activates (the global database plus the tenant's database) has a checked-out connection
|
|
22
|
+
* available for the callback's duration: switching into a tenant makes it queryable without
|
|
23
|
+
* the caller wiring up connections. Already-checked-out connections are reused, so nesting
|
|
24
|
+
* `Tenant.with` calls does not open redundant connections. The callback receives the active
|
|
25
|
+
* connections keyed by identifier, the same as `ensureConnections`.
|
|
26
|
+
* @template T
|
|
18
27
|
* @param {object} tenant Descriptor understood by the app's tenantDatabaseResolver.
|
|
19
|
-
* @param {() => Promise
|
|
20
|
-
* @returns {Promise
|
|
28
|
+
* @param {(connections: Record<string, import("../database/drivers/base.js").default>) => Promise<T>} callback
|
|
29
|
+
* @returns {Promise<T>}
|
|
21
30
|
*/
|
|
22
31
|
static async with(tenant, callback) {
|
|
23
|
-
|
|
32
|
+
const configuration = Current.configuration()
|
|
33
|
+
|
|
34
|
+
return await Current.withTenant(tenant, async () => await configuration.ensureConnections(callback))
|
|
24
35
|
}
|
|
25
36
|
|
|
26
37
|
/**
|
|
@@ -33,8 +44,10 @@ export default class Tenant {
|
|
|
33
44
|
|
|
34
45
|
/**
|
|
35
46
|
* Lists the tenants for a database identifier through the provider and runs `callback`
|
|
36
|
-
* within each tenant's context, optionally filtered and several at a time.
|
|
37
|
-
*
|
|
47
|
+
* within each tenant's context, optionally filtered and several at a time. Like
|
|
48
|
+
* {@link Tenant.with}, the callback runs inside `ensureConnections` so each tenant's
|
|
49
|
+
* database is queryable without the caller wiring up connections. Returns how many tenants
|
|
50
|
+
* the callback ran for (after filtering).
|
|
38
51
|
* @param {{identifier: string, callback: function({databaseConfiguration: import("../configuration-types.js").DatabaseConfigurationType, tenant: ?}) : Promise<void>, parallel?: number, filter?: (tenant: ?) => boolean, configuration?: import("../configuration.js").default}} args
|
|
39
52
|
* @returns {Promise<number>}
|
|
40
53
|
*/
|
|
@@ -51,7 +64,13 @@ export default class Tenant {
|
|
|
51
64
|
const tenants = filter ? listedTenants.filter(filter) : listedTenants
|
|
52
65
|
const iterator = new TenantIterator({configuration, identifier, parallelCount: parallel})
|
|
53
66
|
|
|
54
|
-
|
|
67
|
+
// Run each tenant's callback inside ensureConnections so the iterator stays
|
|
68
|
+
// connection-agnostic (the db:tenants:* CLI commands share TenantIterator and must run
|
|
69
|
+
// their callbacks, such as create, before the tenant database exists) while runtime
|
|
70
|
+
// iteration here gets the tenant's connections established the same way Tenant.with does.
|
|
71
|
+
return await iterator.run(tenants, async (callbackArgs) => {
|
|
72
|
+
await configuration.ensureConnections({name: `Tenant.each: ${identifier}`}, async () => await callback(callbackArgs))
|
|
73
|
+
})
|
|
55
74
|
}
|
|
56
75
|
|
|
57
76
|
/**
|
package/package.json
CHANGED
package/src/current.js
CHANGED
|
@@ -70,9 +70,10 @@ export default class Current {
|
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
72
|
* Runs with tenant.
|
|
73
|
+
* @template T
|
|
73
74
|
* @param {object} tenant - Tenant. Any caller-defined object shape; read back (and narrowed) via tenant().
|
|
74
|
-
* @param {() => Promise
|
|
75
|
-
* @returns {Promise
|
|
75
|
+
* @param {() => Promise<T>} callback - Callback.
|
|
76
|
+
* @returns {Promise<T>} - Callback result.
|
|
76
77
|
*/
|
|
77
78
|
static async withTenant(tenant, callback) {
|
|
78
79
|
return await this.configuration().runWithTenant(tenant, callback)
|
package/src/tenants/tenant.js
CHANGED
|
@@ -8,19 +8,30 @@ import TenantIterator from "./tenant-iterator.js"
|
|
|
8
8
|
* object the app's `tenantDatabaseResolver` understands (an account, a project, …); this
|
|
9
9
|
* class is the single discoverable home for switching into a tenant's context, reading the
|
|
10
10
|
* current one, iterating every tenant of a database identifier, and dropping a tenant's
|
|
11
|
-
* database. Switching
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* database. Switching delegates to {@link Current} (which owns the async-context tenant
|
|
12
|
+
* state) and additionally runs the callback inside `ensureConnections`, so entering a tenant
|
|
13
|
+
* makes its database immediately queryable — the apartment-style "switch" semantics — without
|
|
14
|
+
* the caller establishing connections itself; iteration and drop drive the app's tenant
|
|
15
|
+
* database provider hooks.
|
|
14
16
|
*/
|
|
15
17
|
export default class Tenant {
|
|
16
18
|
/**
|
|
17
19
|
* Runs `callback` with `tenant` as the current tenant, restoring the previous tenant after.
|
|
20
|
+
* The callback runs inside `ensureConnections`, so every database identifier the tenant
|
|
21
|
+
* activates (the global database plus the tenant's database) has a checked-out connection
|
|
22
|
+
* available for the callback's duration: switching into a tenant makes it queryable without
|
|
23
|
+
* the caller wiring up connections. Already-checked-out connections are reused, so nesting
|
|
24
|
+
* `Tenant.with` calls does not open redundant connections. The callback receives the active
|
|
25
|
+
* connections keyed by identifier, the same as `ensureConnections`.
|
|
26
|
+
* @template T
|
|
18
27
|
* @param {object} tenant Descriptor understood by the app's tenantDatabaseResolver.
|
|
19
|
-
* @param {() => Promise
|
|
20
|
-
* @returns {Promise
|
|
28
|
+
* @param {(connections: Record<string, import("../database/drivers/base.js").default>) => Promise<T>} callback
|
|
29
|
+
* @returns {Promise<T>}
|
|
21
30
|
*/
|
|
22
31
|
static async with(tenant, callback) {
|
|
23
|
-
|
|
32
|
+
const configuration = Current.configuration()
|
|
33
|
+
|
|
34
|
+
return await Current.withTenant(tenant, async () => await configuration.ensureConnections(callback))
|
|
24
35
|
}
|
|
25
36
|
|
|
26
37
|
/**
|
|
@@ -33,8 +44,10 @@ export default class Tenant {
|
|
|
33
44
|
|
|
34
45
|
/**
|
|
35
46
|
* Lists the tenants for a database identifier through the provider and runs `callback`
|
|
36
|
-
* within each tenant's context, optionally filtered and several at a time.
|
|
37
|
-
*
|
|
47
|
+
* within each tenant's context, optionally filtered and several at a time. Like
|
|
48
|
+
* {@link Tenant.with}, the callback runs inside `ensureConnections` so each tenant's
|
|
49
|
+
* database is queryable without the caller wiring up connections. Returns how many tenants
|
|
50
|
+
* the callback ran for (after filtering).
|
|
38
51
|
* @param {{identifier: string, callback: function({databaseConfiguration: import("../configuration-types.js").DatabaseConfigurationType, tenant: ?}) : Promise<void>, parallel?: number, filter?: (tenant: ?) => boolean, configuration?: import("../configuration.js").default}} args
|
|
39
52
|
* @returns {Promise<number>}
|
|
40
53
|
*/
|
|
@@ -51,7 +64,13 @@ export default class Tenant {
|
|
|
51
64
|
const tenants = filter ? listedTenants.filter(filter) : listedTenants
|
|
52
65
|
const iterator = new TenantIterator({configuration, identifier, parallelCount: parallel})
|
|
53
66
|
|
|
54
|
-
|
|
67
|
+
// Run each tenant's callback inside ensureConnections so the iterator stays
|
|
68
|
+
// connection-agnostic (the db:tenants:* CLI commands share TenantIterator and must run
|
|
69
|
+
// their callbacks, such as create, before the tenant database exists) while runtime
|
|
70
|
+
// iteration here gets the tenant's connections established the same way Tenant.with does.
|
|
71
|
+
return await iterator.run(tenants, async (callbackArgs) => {
|
|
72
|
+
await configuration.ensureConnections({name: `Tenant.each: ${identifier}`}, async () => await callback(callbackArgs))
|
|
73
|
+
})
|
|
55
74
|
}
|
|
56
75
|
|
|
57
76
|
/**
|