velocious 1.0.488 → 1.0.492
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/build/application.js +3 -0
- package/build/cli/commands/db/tenants/create.js +7 -5
- package/build/cli/commands/db/tenants/drop.js +6 -6
- package/build/configuration-types.js +9 -0
- package/build/configuration.js +58 -0
- package/build/database/query/index.js +30 -0
- package/build/database/query/model-class-query.js +17 -0
- package/build/database/record/index.js +16 -0
- package/build/environment-handlers/node.js +22 -6
- package/build/src/application.d.ts.map +1 -1
- package/build/src/application.js +3 -1
- package/build/src/cli/commands/db/tenants/create.d.ts.map +1 -1
- package/build/src/cli/commands/db/tenants/create.js +8 -5
- package/build/src/cli/commands/db/tenants/drop.d.ts +1 -1
- package/build/src/cli/commands/db/tenants/drop.d.ts.map +1 -1
- package/build/src/cli/commands/db/tenants/drop.js +7 -6
- package/build/src/configuration-types.d.ts +29 -0
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +9 -1
- package/build/src/configuration.d.ts +17 -0
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +52 -1
- package/build/src/database/query/index.d.ts +25 -0
- package/build/src/database/query/index.d.ts.map +1 -1
- package/build/src/database/query/index.js +26 -1
- package/build/src/database/query/model-class-query.d.ts +10 -0
- package/build/src/database/query/model-class-query.d.ts.map +1 -1
- package/build/src/database/query/model-class-query.js +16 -1
- package/build/src/database/record/index.d.ts +7 -0
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +15 -1
- package/build/src/environment-handlers/node.d.ts.map +1 -1
- package/build/src/environment-handlers/node.js +20 -8
- package/build/src/sync/query-scope.d.ts +18 -0
- package/build/src/sync/query-scope.d.ts.map +1 -0
- package/build/src/sync/query-scope.js +77 -0
- package/build/src/sync/server-change-feed.d.ts.map +1 -1
- package/build/src/sync/server-change-feed.js +2 -24
- package/build/src/sync/stable-json.d.ts +9 -0
- package/build/src/sync/stable-json.d.ts.map +1 -0
- package/build/src/sync/stable-json.js +27 -0
- package/build/src/sync/sync-api-client.d.ts +185 -5
- package/build/src/sync/sync-api-client.d.ts.map +1 -1
- package/build/src/sync/sync-api-client.js +309 -17
- package/build/src/sync/sync-api-controller.d.ts +8 -0
- package/build/src/sync/sync-api-controller.d.ts.map +1 -1
- package/build/src/sync/sync-api-controller.js +17 -1
- package/build/src/sync/sync-client-registry.d.ts +12 -0
- package/build/src/sync/sync-client-registry.d.ts.map +1 -0
- package/build/src/sync/sync-client-registry.js +27 -0
- package/build/src/sync/sync-client-types.d.ts +127 -0
- package/build/src/sync/sync-client-types.d.ts.map +1 -0
- package/build/src/sync/sync-client-types.js +3 -0
- package/build/src/sync/sync-client.d.ts +176 -0
- package/build/src/sync/sync-client.d.ts.map +1 -0
- package/build/src/sync/sync-client.js +380 -0
- package/build/src/sync/sync-envelope-replay-service.d.ts +38 -4
- package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
- package/build/src/sync/sync-envelope-replay-service.js +73 -6
- package/build/src/sync/sync-resource-base.d.ts +98 -0
- package/build/src/sync/sync-resource-base.d.ts.map +1 -0
- package/build/src/sync/sync-resource-base.js +122 -0
- package/build/src/sync/sync-scope-store.d.ts +128 -0
- package/build/src/sync/sync-scope-store.d.ts.map +1 -0
- package/build/src/sync/sync-scope-store.js +282 -0
- package/build/src/tenants/default-tenant-database-provisioning.d.ts +21 -0
- package/build/src/tenants/default-tenant-database-provisioning.d.ts.map +1 -0
- package/build/src/tenants/default-tenant-database-provisioning.js +106 -0
- package/build/src/tenants/tenant.d.ts.map +1 -1
- package/build/src/tenants/tenant.js +6 -5
- package/build/sync/query-scope.js +84 -0
- package/build/sync/server-change-feed.js +1 -25
- package/build/sync/stable-json.js +28 -0
- package/build/sync/sync-api-client.js +331 -17
- package/build/sync/sync-api-controller.js +20 -0
- package/build/sync/sync-client-registry.js +30 -0
- package/build/sync/sync-client-types.js +41 -0
- package/build/sync/sync-client.js +433 -0
- package/build/sync/sync-envelope-replay-service.js +77 -5
- package/build/sync/sync-resource-base.js +143 -0
- package/build/sync/sync-scope-store.js +327 -0
- package/build/tenants/default-tenant-database-provisioning.js +124 -0
- package/build/tenants/tenant.js +5 -5
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/application.js +3 -0
- package/src/cli/commands/db/tenants/create.js +7 -5
- package/src/cli/commands/db/tenants/drop.js +6 -6
- package/src/configuration-types.js +9 -0
- package/src/configuration.js +58 -0
- package/src/database/query/index.js +30 -0
- package/src/database/query/model-class-query.js +17 -0
- package/src/database/record/index.js +16 -0
- package/src/environment-handlers/node.js +22 -6
- package/src/sync/query-scope.js +84 -0
- package/src/sync/server-change-feed.js +1 -25
- package/src/sync/stable-json.js +28 -0
- package/src/sync/sync-api-client.js +331 -17
- package/src/sync/sync-api-controller.js +20 -0
- package/src/sync/sync-client-registry.js +30 -0
- package/src/sync/sync-client-types.js +41 -0
- package/src/sync/sync-client.js +433 -0
- package/src/sync/sync-envelope-replay-service.js +77 -5
- package/src/sync/sync-resource-base.js +143 -0
- package/src/sync/sync-scope-store.js +327 -0
- package/src/tenants/default-tenant-database-provisioning.js +124 -0
- package/src/tenants/tenant.js +5 -5
package/README.md
CHANGED
|
@@ -1661,6 +1661,8 @@ unsubscribe()
|
|
|
1661
1661
|
await client.close()
|
|
1662
1662
|
```
|
|
1663
1663
|
|
|
1664
|
+
For long-lived Node clients, the constructor also accepts opt-in liveness options (all default off, so browser/Expo usage is unchanged): `webSocketImplementation` (inject Node's `ws`, since the global/undici WebSocket exposes neither protocol ping nor an unref-able socket), `heartbeatIntervalMs` (a ping heartbeat that drops a socket whose peer stops ponging, so a client notices a vanished server), and `unref` (unref the underlying socket so an idle connection can't keep the process alive on its own). See [docs/websocket-channels.md](docs/websocket-channels.md).
|
|
1665
|
+
|
|
1664
1666
|
## Subscribe to events
|
|
1665
1667
|
|
|
1666
1668
|
```js
|
package/build/application.js
CHANGED
|
@@ -4,6 +4,7 @@ import AppRoutes from "./routes/app-routes.js"
|
|
|
4
4
|
import Logger from "./logger.js"
|
|
5
5
|
import HttpServer from "./http-server/index.js"
|
|
6
6
|
import HttpServerLock from "./http-server/server-lock.js"
|
|
7
|
+
import SyncApiController from "./sync/sync-api-controller.js"
|
|
7
8
|
import websocketEventsHost from "./http-server/websocket-events-host.js"
|
|
8
9
|
import restArgsError from "./utils/rest-args-error.js"
|
|
9
10
|
|
|
@@ -54,6 +55,8 @@ export default class VelociousApplication {
|
|
|
54
55
|
|
|
55
56
|
await this.configuration.initialize({type: this.getType()})
|
|
56
57
|
|
|
58
|
+
SyncApiController.mountFromConfiguration(this.configuration)
|
|
59
|
+
|
|
57
60
|
this.configuration.setRoutes(routes)
|
|
58
61
|
|
|
59
62
|
if (!this.configuration.isDatabasePoolInitialized()) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
import BaseCommand from "../../../base-command.js"
|
|
4
|
+
import {createTenantDatabase} from "../../../../tenants/default-tenant-database-provisioning.js"
|
|
4
5
|
import TenantDatabaseCommandHelper from "../../../tenant-database-command-helper.js"
|
|
5
6
|
|
|
6
7
|
export default class DbTenantsCreate extends BaseCommand {
|
|
@@ -14,13 +15,14 @@ export default class DbTenantsCreate extends BaseCommand {
|
|
|
14
15
|
identifier: this.processArgs?.[1]
|
|
15
16
|
})
|
|
16
17
|
const provider = helper.provider
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
// Providers may customize creation, but the generic driver-agnostic provisioning
|
|
19
|
+
// is the framework default so apps do not reimplement it.
|
|
20
|
+
const createDatabase = typeof provider.createDatabase === "function"
|
|
21
|
+
? provider.createDatabase.bind(provider)
|
|
22
|
+
: createTenantDatabase
|
|
21
23
|
|
|
22
24
|
const tenantCount = await helper.eachTenant(async ({databaseConfiguration, tenant}) => {
|
|
23
|
-
await
|
|
25
|
+
await createDatabase({
|
|
24
26
|
configuration: this.getConfiguration(),
|
|
25
27
|
databaseConfiguration,
|
|
26
28
|
identifier: helper.identifier,
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
import BaseCommand from "../../../base-command.js"
|
|
4
|
+
import {dropTenantDatabase} from "../../../../tenants/default-tenant-database-provisioning.js"
|
|
4
5
|
import TenantDatabaseCommandHelper from "../../../tenant-database-command-helper.js"
|
|
5
6
|
|
|
6
7
|
export default class DbTenantsDrop extends BaseCommand {
|
|
7
8
|
/**
|
|
8
9
|
* Drops the tenant database/schema for every listed tenant through the provider's
|
|
9
|
-
* `dropDatabase` hook.
|
|
10
|
+
* `dropDatabase` hook, or the framework default when the provider defines none.
|
|
10
11
|
* @returns {Promise<{identifier: string, tenantCount: number} | void>} - Result in test mode.
|
|
11
12
|
*/
|
|
12
13
|
async execute() {
|
|
@@ -15,13 +16,12 @@ export default class DbTenantsDrop extends BaseCommand {
|
|
|
15
16
|
identifier: this.processArgs?.[1]
|
|
16
17
|
})
|
|
17
18
|
const provider = helper.provider
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
19
|
+
const dropDatabase = typeof provider.dropDatabase === "function"
|
|
20
|
+
? provider.dropDatabase.bind(provider)
|
|
21
|
+
: dropTenantDatabase
|
|
22
22
|
|
|
23
23
|
const tenantCount = await helper.eachTenant(async ({databaseConfiguration, tenant}) => {
|
|
24
|
-
await
|
|
24
|
+
await dropDatabase({
|
|
25
25
|
configuration: this.getConfiguration(),
|
|
26
26
|
databaseConfiguration,
|
|
27
27
|
identifier: helper.identifier,
|
|
@@ -355,9 +355,17 @@
|
|
|
355
355
|
* @property {Record<string, FrontendModelSyncJsonValue>} [policy] - Deterministic non-secret policy inputs included in the policy hash only.
|
|
356
356
|
*/
|
|
357
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Velocious sync API endpoint configuration.
|
|
360
|
+
* @typedef {object} VelociousSyncApiConfiguration
|
|
361
|
+
* @property {string} [mountPath] - Mount path for the sync endpoints. Defaults to "/velocious/sync".
|
|
362
|
+
* @property {FrontendModelResourceClassType} resourceClass - App sync resource class served by the auto-mounted sync endpoints.
|
|
363
|
+
*/
|
|
364
|
+
|
|
358
365
|
/**
|
|
359
366
|
* Velocious sync configuration.
|
|
360
367
|
* @typedef {object} VelociousSyncConfiguration
|
|
368
|
+
* @property {VelociousSyncApiConfiguration} [api] - Auto-mounts the Velocious sync changes/replay endpoints for this resource class.
|
|
361
369
|
* @property {import("./sync/device-identity.js").SyncJsonWebKey | null} [deviceCertificateBackendPublicKey] - Public backend key used to verify offline device certificates for sync replay.
|
|
362
370
|
* @property {number} [changeFeedRetentionSize] - Number of accepted server changes retained before clients must refresh from snapshot.
|
|
363
371
|
* @property {Array<import("./sync/offline-grant.js").OfflineGrantSigningKey>} offlineGrantSigningKeys - Signing keys used to issue and verify offline grants. Secrets must never be exposed to clients.
|
|
@@ -421,6 +429,7 @@
|
|
|
421
429
|
* @property {string} [frontendModelsOutputPath] - Optional output project path where `src/frontend-models` should be generated.
|
|
422
430
|
* @property {string} [resourcesPath] - Optional override for the resources directory to auto-discover; defaults to `<path>/src/resources`. Set internally for package entries.
|
|
423
431
|
* @property {Record<string, FrontendModelResourceDefinition>} [frontendModels] - Auto-discovered frontend model definitions keyed by model class name. Set internally by the environment handler — do not set manually.
|
|
432
|
+
* @property {AbilityResourceClassType[]} [abilityResources] - Auto-discovered ability resource classes (frontend-model and authorization) from this project's resources directory. Set internally by the environment handler — do not set manually.
|
|
424
433
|
*/
|
|
425
434
|
|
|
426
435
|
/**
|
package/build/configuration.js
CHANGED
|
@@ -424,6 +424,7 @@ export default class VelociousConfiguration {
|
|
|
424
424
|
* @returns {import("./configuration-types.js").VelociousSyncConfiguration} - Normalized sync configuration.
|
|
425
425
|
*/
|
|
426
426
|
_normalizeSyncConfiguration(sync) {
|
|
427
|
+
const api = sync?.api
|
|
427
428
|
const deviceCertificateBackendPublicKey = sync?.deviceCertificateBackendPublicKey || null
|
|
428
429
|
const changeFeedRetentionSize = sync?.changeFeedRetentionSize
|
|
429
430
|
const offlineGrantSigningKeys = sync?.offlineGrantSigningKeys || []
|
|
@@ -441,6 +442,7 @@ export default class VelociousConfiguration {
|
|
|
441
442
|
}
|
|
442
443
|
|
|
443
444
|
return {
|
|
445
|
+
api: this._normalizeSyncApiConfiguration(api),
|
|
444
446
|
changeFeedRetentionSize: changeFeedRetentionSize || 10000,
|
|
445
447
|
deviceCertificateBackendPublicKey,
|
|
446
448
|
offlineGrantSigningKeys: offlineGrantSigningKeys.map((key) => normalizeOfflineGrantSigningKey(key)),
|
|
@@ -448,6 +450,33 @@ export default class VelociousConfiguration {
|
|
|
448
450
|
}
|
|
449
451
|
}
|
|
450
452
|
|
|
453
|
+
/**
|
|
454
|
+
* Normalizes sync API endpoint configuration.
|
|
455
|
+
* @param {import("./configuration-types.js").VelociousSyncApiConfiguration | undefined} api - Sync API configuration.
|
|
456
|
+
* @returns {import("./configuration-types.js").VelociousSyncApiConfiguration | undefined} - Normalized sync API configuration.
|
|
457
|
+
*/
|
|
458
|
+
_normalizeSyncApiConfiguration(api) {
|
|
459
|
+
if (api === undefined || api === null) return undefined
|
|
460
|
+
|
|
461
|
+
if (typeof api !== "object" || Array.isArray(api)) {
|
|
462
|
+
throw new Error("sync.api must be an object with a resourceClass")
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const {mountPath, resourceClass} = api
|
|
466
|
+
|
|
467
|
+
if (typeof resourceClass !== "function") {
|
|
468
|
+
throw new Error(`sync.api.resourceClass must be a resource class, got: ${String(resourceClass)}`)
|
|
469
|
+
}
|
|
470
|
+
if (!resourceClass.ModelClass) {
|
|
471
|
+
throw new Error(`sync.api.resourceClass ${resourceClass.name} must define static ModelClass`)
|
|
472
|
+
}
|
|
473
|
+
if (mountPath !== undefined && (typeof mountPath !== "string" || !mountPath.startsWith("/"))) {
|
|
474
|
+
throw new Error(`sync.api.mountPath must start with '/', got: ${String(mountPath)}`)
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return {mountPath, resourceClass}
|
|
478
|
+
}
|
|
479
|
+
|
|
451
480
|
/**
|
|
452
481
|
* Runs get database configuration.
|
|
453
482
|
* @returns {Record<string, import("./configuration-types.js").DatabaseConfigurationType>} - The database configuration.
|
|
@@ -875,6 +904,34 @@ export default class VelociousConfiguration {
|
|
|
875
904
|
*/
|
|
876
905
|
setAbilityResources(resources) { this._abilityResources = resources }
|
|
877
906
|
|
|
907
|
+
/**
|
|
908
|
+
* Merges resource classes discovered from the app and every registered package
|
|
909
|
+
* into the ability-resources list. `autoDiscoverResources` populates each backend
|
|
910
|
+
* project's `frontendModels` (including package projects), so this makes a
|
|
911
|
+
* package-contributed model's abilities reach subscription and per-record
|
|
912
|
+
* authorization automatically — consuming apps do not have to hand-register
|
|
913
|
+
* package resources. Already-present classes (e.g. an app's explicitly-set
|
|
914
|
+
* resources) are left untouched.
|
|
915
|
+
* @returns {void} - No return value.
|
|
916
|
+
*/
|
|
917
|
+
_mergeDiscoveredAbilityResources() {
|
|
918
|
+
const merged = [...this._abilityResources]
|
|
919
|
+
const seen = new Set(merged)
|
|
920
|
+
|
|
921
|
+
for (const backendProject of this._backendProjects) {
|
|
922
|
+
if (!backendProject.abilityResources) continue
|
|
923
|
+
|
|
924
|
+
for (const ResourceClass of backendProject.abilityResources) {
|
|
925
|
+
if (seen.has(ResourceClass)) continue
|
|
926
|
+
|
|
927
|
+
seen.add(ResourceClass)
|
|
928
|
+
merged.push(ResourceClass)
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
this._abilityResources = merged
|
|
933
|
+
}
|
|
934
|
+
|
|
878
935
|
/**
|
|
879
936
|
* Runs get ability resolver.
|
|
880
937
|
* @returns {import("./configuration-types.js").AbilityResolverType | undefined} - Ability resolver.
|
|
@@ -1723,6 +1780,7 @@ export default class VelociousConfiguration {
|
|
|
1723
1780
|
|
|
1724
1781
|
await this.initializeModels({type})
|
|
1725
1782
|
await this.getEnvironmentHandler().autoDiscoverResources(this)
|
|
1783
|
+
this._mergeDiscoveredAbilityResources()
|
|
1726
1784
|
this._validateResourceRelationshipsOnModels()
|
|
1727
1785
|
|
|
1728
1786
|
if (this._initializers) {
|
|
@@ -235,18 +235,48 @@ export default class VelociousDatabaseQuery {
|
|
|
235
235
|
return this._groups
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Runs get joins.
|
|
240
|
+
* @returns {Array<?>} - The joins.
|
|
241
|
+
*/
|
|
242
|
+
getJoins() { return this._joins }
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Runs get limit.
|
|
246
|
+
* @returns {number | null} - The limit.
|
|
247
|
+
*/
|
|
248
|
+
getLimit() { return this._limit }
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Runs get offset.
|
|
252
|
+
* @returns {number | null} - The offset.
|
|
253
|
+
*/
|
|
254
|
+
getOffset() { return this._offset }
|
|
255
|
+
|
|
238
256
|
/**
|
|
239
257
|
* Runs get options.
|
|
240
258
|
* @returns {import("../query-parser/options.js").default} - The options options.
|
|
241
259
|
*/
|
|
242
260
|
getOptions() { return this.driver.options() }
|
|
243
261
|
|
|
262
|
+
/**
|
|
263
|
+
* Runs get orders.
|
|
264
|
+
* @returns {Array<?>} - The orders.
|
|
265
|
+
*/
|
|
266
|
+
getOrders() { return this._orders }
|
|
267
|
+
|
|
244
268
|
/**
|
|
245
269
|
* Runs get selects.
|
|
246
270
|
* @returns {Array<import("./select-base.js").default>} - The selects.
|
|
247
271
|
*/
|
|
248
272
|
getSelects() { return this._selects }
|
|
249
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Runs get wheres.
|
|
276
|
+
* @returns {Array<import("./where-base.js").default>} - The wheres.
|
|
277
|
+
*/
|
|
278
|
+
getWheres() { return this._wheres }
|
|
279
|
+
|
|
250
280
|
/**
|
|
251
281
|
* Runs from.
|
|
252
282
|
* @param {string|import("./from-base.js").default} from - From.
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import {incorporate} from "incorporator"
|
|
4
4
|
import * as inflection from "inflection"
|
|
5
5
|
import {isPlainObject} from "is-plain-object"
|
|
6
|
+
import {currentSyncClient} from "../../sync/sync-client-registry.js"
|
|
6
7
|
import Logger from "../../logger.js"
|
|
7
8
|
import Preloader from "./preloader.js"
|
|
8
9
|
import {normalizeQueryDataSpec, runQueryData} from "./query-data.js"
|
|
@@ -1114,6 +1115,22 @@ export default class VelociousDatabaseQueryModelClassQuery extends DatabaseQuery
|
|
|
1114
1115
|
queryLogName(operation) {
|
|
1115
1116
|
return `${this.getModelClass().name} ${operation}`
|
|
1116
1117
|
}
|
|
1118
|
+
|
|
1119
|
+
/**
|
|
1120
|
+
* Declares this query as a sync scope on the current sync client.
|
|
1121
|
+
* @returns {Promise<?>} - Declared scope and pull result.
|
|
1122
|
+
*/
|
|
1123
|
+
async sync() {
|
|
1124
|
+
return await currentSyncClient().sync(this)
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
/**
|
|
1128
|
+
* Deactivates this query's sync scope on the current sync client.
|
|
1129
|
+
* @returns {Promise<void>} - Resolves when the scope is deactivated.
|
|
1130
|
+
*/
|
|
1131
|
+
async unsync() {
|
|
1132
|
+
await currentSyncClient().unsync(this)
|
|
1133
|
+
}
|
|
1117
1134
|
}
|
|
1118
1135
|
|
|
1119
1136
|
/**
|
|
@@ -535,6 +535,22 @@ class VelociousDatabaseRecord {
|
|
|
535
535
|
callbacks[callbackName].push(callback)
|
|
536
536
|
}
|
|
537
537
|
|
|
538
|
+
/**
|
|
539
|
+
* Runs unregister lifecycle callback.
|
|
540
|
+
* @param {"afterCreate" | "afterDestroy" | "afterSave" | "afterUpdate" | "beforeCreate" | "beforeDestroy" | "beforeSave" | "beforeUpdate" | "beforeValidation"} callbackName - Callback type.
|
|
541
|
+
* @param {LifecycleCallbackType} callback - Previously registered callback.
|
|
542
|
+
* @returns {void}
|
|
543
|
+
*/
|
|
544
|
+
static unregisterLifecycleCallback(callbackName, callback) {
|
|
545
|
+
const callbacks = this.getLifecycleCallbacksMap()[callbackName]
|
|
546
|
+
|
|
547
|
+
if (!callbacks) return
|
|
548
|
+
|
|
549
|
+
const callbackIndex = callbacks.indexOf(callback)
|
|
550
|
+
|
|
551
|
+
if (callbackIndex >= 0) callbacks.splice(callbackIndex, 1)
|
|
552
|
+
}
|
|
553
|
+
|
|
538
554
|
/**
|
|
539
555
|
* Runs before validation.
|
|
540
556
|
* @template R
|
|
@@ -100,10 +100,11 @@ export default class VelociousEnvironmentHandlerNode extends Base{
|
|
|
100
100
|
*/
|
|
101
101
|
async autoDiscoverResources(configuration) {
|
|
102
102
|
const {frontendModelResourceDefinitionIsClass} = await import("../frontend-models/resource-definition.js")
|
|
103
|
+
const {default: AuthorizationBaseResource} = await import("../authorization/base-resource.js")
|
|
103
104
|
const backendProjects = configuration.getBackendProjects()
|
|
104
105
|
|
|
105
106
|
for (const backendProject of backendProjects) {
|
|
106
|
-
if (backendProject.
|
|
107
|
+
if (backendProject.abilityResources) continue
|
|
107
108
|
|
|
108
109
|
const resourcesDir = backendProject.resourcesPath || path.join(backendProject.path, "src", "resources")
|
|
109
110
|
let files
|
|
@@ -115,9 +116,13 @@ export default class VelociousEnvironmentHandlerNode extends Base{
|
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
/**
|
|
118
|
-
* Discovered.
|
|
119
|
+
* Discovered frontend-model resources keyed by model name.
|
|
119
120
|
* @type {Record<string, ?>} */
|
|
120
121
|
const discovered = {}
|
|
122
|
+
/**
|
|
123
|
+
* Every discovered ability resource class (frontend-model and authorization).
|
|
124
|
+
* @type {Array<?>} */
|
|
125
|
+
const abilityResourceClasses = []
|
|
121
126
|
|
|
122
127
|
for (const file of files) {
|
|
123
128
|
if (!file.endsWith(".js") && !file.endsWith(".mjs")) continue
|
|
@@ -127,10 +132,17 @@ export default class VelociousEnvironmentHandlerNode extends Base{
|
|
|
127
132
|
const imported = await import(filePath)
|
|
128
133
|
const ResourceClass = imported.default
|
|
129
134
|
|
|
135
|
+
// Any authorization resource (frontend-model resources also extend it) that
|
|
136
|
+
// declares a `ModelClass`; skip abstract/common base resources without one.
|
|
137
|
+
const isAbilityResource = typeof ResourceClass === "function"
|
|
138
|
+
&& (ResourceClass === AuthorizationBaseResource || ResourceClass.prototype instanceof AuthorizationBaseResource)
|
|
139
|
+
|
|
140
|
+
if (!isAbilityResource || !ResourceClass.ModelClass) continue
|
|
141
|
+
|
|
142
|
+
abilityResourceClasses.push(ResourceClass)
|
|
143
|
+
|
|
144
|
+
// Only frontend-model resources drive routing/generation/publisher discovery.
|
|
130
145
|
if (!frontendModelResourceDefinitionIsClass(ResourceClass)) continue
|
|
131
|
-
// Skip abstract/common base resources that declare no `ModelClass` — they are
|
|
132
|
-
// not models, so they must not be recorded as discovered frontend models.
|
|
133
|
-
if (!ResourceClass.ModelClass) continue
|
|
134
146
|
|
|
135
147
|
const baseName = file.replace(/\.(js|mjs)$/, "")
|
|
136
148
|
const modelName = baseName.replace(/-resource$/, "")
|
|
@@ -141,9 +153,13 @@ export default class VelociousEnvironmentHandlerNode extends Base{
|
|
|
141
153
|
discovered[modelName] = ResourceClass
|
|
142
154
|
}
|
|
143
155
|
|
|
144
|
-
if (Object.keys(discovered).length > 0) {
|
|
156
|
+
if (!backendProject.frontendModels && Object.keys(discovered).length > 0) {
|
|
145
157
|
backendProject.frontendModels = discovered
|
|
146
158
|
}
|
|
159
|
+
|
|
160
|
+
if (abilityResourceClasses.length > 0) {
|
|
161
|
+
backendProject.abilityResources = abilityResourceClasses
|
|
162
|
+
}
|
|
147
163
|
}
|
|
148
164
|
}
|
|
149
165
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/application.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/application.js"],"names":[],"mappings":"AAUA;;mGAEmG;AAEnG;IACE;;;;;;OAMG;IACH,8DAJG;QAAmD,aAAa,EAAxD,OAAO,oBAAoB,EAAE,OAAO;QACL,UAAU;QAC5B,IAAI,EAAjB,MAAM;KAChB,EAmBA;IAbC,oDAAkC;IAElC;;yCAEqC;IACrC,yBADU,uBAAuB,CACc;IAE/C,eAA8B;IAC9B,cAAiB;IACjB;;4CAEwC;IACxC,gBADU,cAAc,GAAG,SAAS,CACL;IAGjC;;;OAGG;IACH,WAFa,MAAM,CAEY;IAE/B;;;OAGG;IACH,cAFa,OAAO,CAAC,IAAI,CAAC,CAezB;IAED;;;OAGG;IACH,YAFa,OAAO,CAQnB;IAED;;;;OAIG;IACH,cAHW,MAAa,IAAI,GACf,OAAO,CAAC,IAAI,CAAC,CAUzB;IAED;;;OAGG;IACH,mBAFa,OAAO,CAAC,IAAI,CAAC,CAczB;IAED;;;;;;;;OAQG;IACH,8EANG;QAAmD,aAAa,EAAxD,OAAO,oBAAoB,EAAE,OAAO;QACtB,IAAI;QACM,uBAAuB,EAA/C,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC;QACJ,IAAI,EAAjB,MAAM;KACd,GAAU,OAAO,CAAC,IAAI,CAAC,CA4BzB;IAlBG,mCAOE;IAaN;;;;;;;OAOG;IACH,qDALG;QAAmD,aAAa,EAAxD,OAAO,oBAAoB,EAAE,OAAO;QACvB,IAAI,EAAjB,MAAM;QACO,IAAI,EAAjB,MAAM;KACd,GAAU,OAAO,CAAC,IAAI,CAAC,CAQzB;IAED;;;;;;;;;;OAUG;IACH,gFARG;QAAmD,aAAa,EAAxD,OAAO,oBAAoB,EAAE,OAAO;QACtB,IAAI;QACH,SAAS;QACV,UAAU;QACX,IAAI,EAAjB,MAAM;QACQ,OAAO;KAC7B,GAAU,UAAU,CAItB;IAED;;;OAGG;IACH,QAFa,OAAO,CAAC,IAAI,CAAC,CAazB;IAED;;;OAGG;IACH,yBAFa,OAAO,CAAC,IAAI,CAAC,CAOzB;IAED;;;OAGG;IACH,yBAFa,IAAI,CAQhB;IAED;;;OAGG;IACH,QAFa,OAAO,CAAC,IAAI,CAAC,CAMzB;IAFG,qEAA0B;CAG/B;;;;sCAzNY,OAAO,0BAA0B,EAAE,uBAAuB;mBATpD,aAAa;2BAEL,8BAA8B;uBADlC,wBAAwB"}
|
package/build/src/application.js
CHANGED
|
@@ -3,6 +3,7 @@ import AppRoutes from "./routes/app-routes.js";
|
|
|
3
3
|
import Logger from "./logger.js";
|
|
4
4
|
import HttpServer from "./http-server/index.js";
|
|
5
5
|
import HttpServerLock from "./http-server/server-lock.js";
|
|
6
|
+
import SyncApiController from "./sync/sync-api-controller.js";
|
|
6
7
|
import websocketEventsHost from "./http-server/websocket-events-host.js";
|
|
7
8
|
import restArgsError from "./utils/rest-args-error.js";
|
|
8
9
|
/**
|
|
@@ -44,6 +45,7 @@ export default class VelociousApplication {
|
|
|
44
45
|
async initialize() {
|
|
45
46
|
const routes = await AppRoutes.getRoutes(this.configuration);
|
|
46
47
|
await this.configuration.initialize({ type: this.getType() });
|
|
48
|
+
SyncApiController.mountFromConfiguration(this.configuration);
|
|
47
49
|
this.configuration.setRoutes(routes);
|
|
48
50
|
if (!this.configuration.isDatabasePoolInitialized()) {
|
|
49
51
|
await this.configuration.initializeDatabasePool();
|
|
@@ -197,4 +199,4 @@ export default class VelociousApplication {
|
|
|
197
199
|
});
|
|
198
200
|
}
|
|
199
201
|
}
|
|
200
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbGljYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBwbGljYXRpb24uanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sU0FBUyxNQUFNLHdCQUF3QixDQUFBO0FBQzlDLE9BQU8sTUFBTSxNQUFNLGFBQWEsQ0FBQTtBQUNoQyxPQUFPLFVBQVUsTUFBTSx3QkFBd0IsQ0FBQTtBQUMvQyxPQUFPLGNBQWMsTUFBTSw4QkFBOEIsQ0FBQTtBQUN6RCxPQUFPLG1CQUFtQixNQUFNLHdDQUF3QyxDQUFBO0FBQ3hFLE9BQU8sYUFBYSxNQUFNLDRCQUE0QixDQUFBO0FBRXREOzttR0FFbUc7QUFFbkcsTUFBTSxDQUFDLE9BQU8sT0FBTyxvQkFBb0I7SUFDdkM7Ozs7OztPQU1HO0lBQ0gsWUFBWSxFQUFDLGFBQWEsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLEdBQUcsUUFBUSxFQUFDO1FBQ3hELGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUV2QixJQUFJLENBQUMsYUFBYTtZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLENBQUMsQ0FBQTtRQUVoRSxJQUFJLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQTtRQUVsQzs7NkNBRXFDO1FBQ3JDLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxVQUFVLElBQUksRUFBRSxDQUFBO1FBRS9DLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDOUIsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUE7UUFDakI7O2dEQUV3QztRQUN4QyxJQUFJLENBQUMsY0FBYyxHQUFHLFNBQVMsQ0FBQTtJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsT0FBTyxLQUFLLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQSxDQUFDLENBQUM7SUFFL0I7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLFVBQVU7UUFDZCxNQUFNLE1BQU0s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bUIsR0FBRyxTQUFTLENBQUE7WUFDbEQsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLGdCQUFnQixFQUFFLENBQUE7WUFDM0MsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLHdCQUF3QixFQUFFLENBQUE7UUFDckQsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsTUFBTSxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQTtRQUNwQyxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxxQkFBcUI7UUFDekIsTUFBTSxFQUFDLGNBQWMsRUFBQyxHQUFHLElBQUksQ0FBQTtRQUU3QixJQUFJLENBQUMsY0FBYyxHQUFHLFNBQVMsQ0FBQTtRQUMvQixJQUFJLGNBQWM7WUFBRSxNQUFNLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQTtJQUNwRCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsaUJBQWlCLEdBQUcsR0FBRyxFQUFFO1FBQ3ZCLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLG9CQUFvQixDQUFDLENBQUE7UUFFdkMsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFBO1FBQ3BCLENBQUM7SUFDSCxDQUFDLENBQUE7SUFFRDs7O09BR0c7SUFDSCxJQUFJO1FBQ0YsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQzdCLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFBO1FBQzVCLENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBBcHBSb3V0ZXMgZnJvbSBcIi4vcm91dGVzL2FwcC1yb3V0ZXMuanNcIlxuaW1wb3J0IExvZ2dlciBmcm9tIFwiLi9sb2dnZXIuanNcIlxuaW1wb3J0IEh0dHBTZXJ2ZXIgZnJvbSBcIi4vaHR0cC1zZXJ2ZXIvaW5kZXguanNcIlxuaW1wb3J0IEh0dHBTZXJ2ZXJMb2NrIGZyb20gXCIuL2h0dHAtc2VydmVyL3NlcnZlci1sb2NrLmpzXCJcbmltcG9ydCB3ZWJzb2NrZXRFdmVudHNIb3N0IGZyb20gXCIuL2h0dHAtc2VydmVyL3dlYnNvY2tldC1ldmVudHMtaG9zdC5qc1wiXG5pbXBvcnQgcmVzdEFyZ3NFcnJvciBmcm9tIFwiLi91dGlscy9yZXN0LWFyZ3MtZXJyb3IuanNcIlxuXG4vKipcbiAqIEh0dHBTZXJ2ZXJDb25maWd1cmF0aW9uIHR5cGUuXG4gKiBAdHlwZWRlZiB7aW1wb3J0KFwiLi9jb25maWd1cmF0aW9uLXR5cGVzLmpzXCIpLkh0dHBTZXJ2ZXJDb25maWd1cmF0aW9ufSBIdHRwU2VydmVyQ29uZmlndXJhdGlvbiAqL1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBWZWxvY2lvdXNBcHBsaWNhdGlvbiB7XG4gIC8qKlxuICAgKiBSdW5zIGNvbnN0cnVjdG9yLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMgb2JqZWN0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBhcmdzLmNvbmZpZ3VyYXRpb24gLSBDb25maWd1cmF0aW9uIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge0h0dHBTZXJ2ZXJDb25maWd1cmF0aW9ufSBbYXJncy5odHRwU2VydmVyXSAtIEh0dHAgc2VydmVyLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy50eXBlIC0gVHlwZSBpZGVudGlmaWVyLlxuICAgKi9cbiAgY29uc3RydWN0b3Ioe2NvbmZpZ3VyYXRpb24sIGh0dHBTZXJ2ZXIsIHR5cGUsIC4uLnJlc3RBcmdzfSkge1xuICAgIHJlc3RBcmdzRXJyb3IocmVzdEFyZ3MpXG5cbiAgICBpZiAoIWNvbmZpZ3VyYXRpb24pIHRocm93IG5ldyBFcnJvcihcImNvbmZpZ3VyYXRpb24gaXMgcmVxdWlyZWRcIilcblxuICAgIHRoaXMuY29uZmlndXJhdGlvbiA9IGNvbmZpZ3VyYXRpb25cblxuICAgIC8qKlxuICAgICAqIFN0b3JlcyB0aGUgaHR0cCBzZXJ2ZXIgY29uZmlndXJhdGlvbiB2YWx1ZS5cbiAgICAgKiBAdHlwZSB7SHR0cFNlcnZlckNvbmZpZ3VyYXRpb259ICovXG4gICAgdGhpcy5odHRwU2VydmVyQ29uZmlndXJhdGlvbiA9IGh0dHBTZXJ2ZXIgPz8ge31cblxuICAgIHRoaXMubG9nZ2VyID0gbmV3IExvZ2dlcih0aGlzKVxuICAgIHRoaXMuX3R5cGUgPSB0eXBlXG4gICAgLyoqXG4gICAgICogU3RvcmVzIHRoZSBodHRwIHNlcnZlciBsb2NrIHZhbHVlLlxuICAgICAqIEB0eXBlIHtIdHRwU2VydmVyTG9jayB8IHVuZGVmaW5lZH0gKi9cbiAgICB0aGlzLmh0dHBTZXJ2ZXJMb2NrID0gdW5kZWZpbmVkXG4gIH1cblxuICAvKipcbiAgICogUnVucyBnZXQgdHlwZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gLSBUaGUgdHlwZS5cbiAgICovXG4gIGdldFR5cGUoKSB7IHJldHVybiB0aGlzLl90eXBlIH1cblxuICAvKipcbiAgICogUnVucyBpbml0aWFsaXplLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLlxuICAgKi9cbiAgYXN5bmMgaW5pdGlhbGl6ZSgpIHtcbiAgICBjb25zdCByb3V0ZXMgPSBhd2FpdCBBcHBSb3V0ZXMuZ2V0Um91dGVzKHRoaXMuY29uZmlndXJhdGlvbilcblxuICAgIGF3YWl0IHRoaXMuY29uZmlndXJhdGlvbi5pbml0aWFsaXplKHt0eXBlOiB0aGlzLmdldFR5cGUoKX0pXG5cbiAgICB0aGlzLmNvbmZpZ3VyYXRpb24uc2V0Um91dGVzKHJvdXRlcylcblxuICAgIGlmICghdGhpcy5jb25maWd1cmF0aW9uLmlzRGF0YWJhc2VQb29sSW5pdGlhbGl6ZWQoKSkge1xuICAgICAgYXdhaXQgdGhpcy5jb25maWd1cmF0aW9uLmluaXRpYWxpemVEYXRhYmFzZVBvb2woKVxuICAgIH1cblxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgaXMgYWN0aXZlLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBXaGV0aGVyIGFjdGl2ZS5cbiAgICovXG4gIGlzQWN0aXZlKCkge1xuICAgIGlmICh0aGlzLmh0dHBTZXJ2ZXIpIHtcbiAgICAgIHJldHVybiB0aGlzLmh0dHBTZXJ2ZXI/LmlzQWN0aXZlKClcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHJ1bi5cbiAgICogQHBhcmFtIHtmdW5jdGlvbigpIDogdm9pZH0gY2FsbGJhY2sgLSBDYWxsYmFjayBmdW5jdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS5cbiAgICovXG4gIGFzeW5jIHJ1bihjYWxsYmFjaykge1xuICAgIGF3YWl0IHRoaXMuc3RhcnRIdHRwU2VydmVyKClcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBjYWxsYmFjaygpXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGF3YWl0IHRoaXMuc3RvcCgpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc3RhcnQgaHR0cCBzZXJ2ZXIuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuXG4gICAqL1xuICBhc3luYyBzdGFydEh0dHBTZXJ2ZXIoKSB7XG4gICAgY29uc3Qge2NvbmZpZ3VyYXRpb259ID0gdGhpc1xuICAgIGNvbnN0IGh0dHBTZXJ2ZXJDb25maWd1cmF0aW9uID0ge1xuICAgICAgLi4uY29uZmlndXJhdGlvbi5odHRwU2VydmVyLFxuICAgICAgLi4udGhpcy5odHRwU2VydmVyQ29uZmlndXJhdGlvblxuICAgIH1cbiAgICBjb25zdCBwb3J0ID0gaHR0cFNlcnZlckNvbmZpZ3VyYXRpb24ucG9ydCA/PyAzMDA2XG4gICAgY29uc3QgaG9zdCA9IGh0dHBTZXJ2ZXJDb25maWd1cmF0aW9uLmhvc3RcblxuICAgIGF3YWl0IHRoaXMubG9nZ2VyLmRlYnVnKGBTdGFydGluZyBzZXJ2ZXIgb24gcG9ydCAke3BvcnR9YClcbiAgICBhd2FpdCB0aGlzLmFjcXVpcmVIdHRwU2VydmVyTG9jayh7Y29uZmlndXJhdGlvbiwgaG9zdDogaG9zdCA/PyBcIjAuMC4wLjBcIiwgcG9ydH0pXG4gICAgYXdhaXQgdGhpcy5zdGFydExvY2tlZEh0dHBTZXJ2ZXIoe2NvbmZpZ3VyYXRpb24sIGhvc3QsIGh0dHBTZXJ2ZXJDb25maWd1cmF0aW9uLCBwb3J0fSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHN0YXJ0IGxvY2tlZCBodHRwIHNlcnZlci5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBIVFRQIHNlcnZlciBzdGFydHVwIGFyZ3VtZW50cy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2NvbmZpZ3VyYXRpb24uanNcIikuZGVmYXVsdH0gYXJncy5jb25maWd1cmF0aW9uIC0gQ29uZmlndXJhdGlvbiBpbnN0YW5jZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFthcmdzLmhvc3RdIC0gSFRUUCBzZXJ2ZXIgaG9zdC5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gYXJncy5odHRwU2VydmVyQ29uZmlndXJhdGlvbiAtIE1lcmdlZCBIVFRQIHNlcnZlciBjb25maWd1cmF0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcn0gYXJncy5wb3J0IC0gSFRUUCBzZXJ2ZXIgcG9ydC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgYWZ0ZXIgdGhlIEhUVFAgc2VydmVyIGhhcyBzdGFydGVkLlxuICAgKi9cbiAgYXN5bmMgc3RhcnRMb2NrZWRIdHRwU2VydmVyKHtjb25maWd1cmF0aW9uLCBob3N0LCBodHRwU2VydmVyQ29uZmlndXJhdGlvbiwgcG9ydH0pIHtcbiAgICB0cnkge1xuICAgICAgaWYgKCFjb25maWd1cmF0aW9uLmdldFdlYnNvY2tldEV2ZW50cygpKSB7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24uc2V0V2Vic29ja2V0RXZlbnRzKC8qKiBAdHlwZSB7P30gKi8gKHdlYnNvY2tldEV2ZW50c0hvc3QpKVxuICAgICAgfVxuXG4gICAgICBhd2FpdCBjb25maWd1cmF0aW9uLmNvbm5lY3RCZWFjb24oe3BlZXJUeXBlOiBcInNlcnZlclwifSlcblxuICAgICAgdGhpcy5odHRwU2VydmVyID0gdGhpcy5jcmVhdGVIdHRwU2VydmVyKHtcbiAgICAgICAgY29uZmlndXJhdGlvbixcbiAgICAgICAgaG9zdCxcbiAgICAgICAgaW5Qcm9jZXNzOiBodHRwU2VydmVyQ29uZmlndXJhdGlvbi5pblByb2Nlc3MsXG4gICAgICAgIG1heFdvcmtlcnM6IGh0dHBTZXJ2ZXJDb25maWd1cmF0aW9uLm1heFdvcmtlcnMsXG4gICAgICAgIHBvcnQsXG4gICAgICAgIHdvcmtlcnM6IGh0dHBTZXJ2ZXJDb25maWd1cmF0aW9uLndvcmtlcnNcbiAgICAgIH0pXG4gICAgICB0aGlzLmh0dHBTZXJ2ZXIuZXZlbnRzLm9uKFwiY2xvc2VcIiwgdGhpcy5vbkh0dHBTZXJ2ZXJDbG9zZSlcbiAgICAgIGNvbmZpZ3VyYXRpb24uX2h0dHBTZXJ2ZXJJbnN0YW5jZSA9IHRoaXMuaHR0cFNlcnZlclxuXG4gICAgICBhd2FpdCB0aGlzLmh0dHBTZXJ2ZXIuc3RhcnQoKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBhd2FpdCB0aGlzLnJlbGVhc2VIdHRwU2VydmVyTG9jaygpXG4gICAgICBjb25maWd1cmF0aW9uLl9odHRwU2VydmVySW5zdGFuY2UgPSB1bmRlZmluZWRcblxuICAgICAgdGhyb3cgZXJyb3JcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBhY3F1aXJlIGh0dHAgc2VydmVyIGxvY2suXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gTG9jayBhY3F1aXNpdGlvbiBhcmd1bWVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9IGFyZ3MuY29uZmlndXJhdGlvbiAtIENvbmZpZ3VyYXRpb24gaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmhvc3QgLSBIVFRQIHNlcnZlciBob3N0LlxuICAgKiBAcGFyYW0ge251bWJlcn0gYXJncy5wb3J0IC0gSFRUUCBzZXJ2ZXIgcG9ydC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgYWZ0ZXIgYWNxdWlyaW5nIHRoZSBzZXJ2ZXIgbG9jayB3aGVuIG5lZWRlZC5cbiAgICovXG4gIGFzeW5jIGFjcXVpcmVIdHRwU2VydmVyTG9jayh7Y29uZmlndXJhdGlvbiwgaG9zdCwgcG9ydH0pIHtcbiAgICBpZiAodGhpcy5nZXRUeXBlKCkgPT09IFwidGVzdC1ydW5uZXJcIikgcmV0dXJuXG5cbiAgICBjb25zdCBodHRwU2VydmVyTG9jayA9IG5ldyBIdHRwU2VydmVyTG9jayh7Y29uZmlndXJhdGlvbiwgaG9zdCwgcG9ydH0pXG4gICAgYXdhaXQgaHR0cFNlcnZlckxvY2suYWNxdWlyZSgpXG4gICAgdGhpcy5odHRwU2VydmVyTG9jayA9IGh0dHBTZXJ2ZXJMb2NrXG4gIH1cblxuICAvKipcbiAgICogUnVucyBjcmVhdGUgaHR0cCBzZXJ2ZXIuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gSFRUUCBzZXJ2ZXIgYXJndW1lbnRzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBhcmdzLmNvbmZpZ3VyYXRpb24gLSBDb25maWd1cmF0aW9uIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2FyZ3MuaG9zdF0gLSBIb3N0LlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFthcmdzLmluUHJvY2Vzc10gLSBSdW4gSFRUUCBoYW5kbGVycyBpbiB0aGUgbWFpbiB0aHJlYWQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJncy5tYXhXb3JrZXJzXSAtIE1heCB3b3JrZXJzLlxuICAgKiBAcGFyYW0ge251bWJlcn0gYXJncy5wb3J0IC0gUG9ydC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IFthcmdzLndvcmtlcnNdIC0gV29ya2VyIGNvdW50LlxuICAgKiBAcmV0dXJucyB7SHR0cFNlcnZlcn0gLSBIVFRQIHNlcnZlciBpbnN0YW5jZS5cbiAgICovXG4gIGNyZWF0ZUh0dHBTZXJ2ZXIoe2NvbmZpZ3VyYXRpb24sIGhvc3QsIGluUHJvY2VzcywgbWF4V29ya2VycywgcG9ydCwgd29ya2Vyc30pIHtcbiAgICByZXR1cm4gbmV3IEh0dHBTZXJ2ZXIoe2NvbmZpZ3VyYXRpb24sIGhvc3QsIGluUHJvY2VzcywgbWF4V29ya2VycywgcG9ydCwgd29ya2Vyc30pXG4gIH1cblxuICAvKipcbiAgICogUnVucyBzdG9wLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLlxuICAgKi9cbiAgYXN5bmMgc3RvcCgpIHtcbiAgICBhd2FpdCB0aGlzLmxvZ2dlci5kZWJ1ZyhcIlN0b3BwaW5nIHNlcnZlclwiKVxuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuaHR0cFNlcnZlcj8uc3RvcCgpXG4gICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uX2h0dHBTZXJ2ZXJJbnN0YW5jZSA9IHVuZGVmaW5lZFxuICAgICAgYXdhaXQgdGhpcy5jb25maWd1cmF0aW9uLmRpc2Nvbm5lY3RCZWFjb24oKVxuICAgICAgYXdhaXQgdGhpcy5jb25maWd1cmF0aW9uLmNsb3NlRGF0YWJhc2VDb25uZWN0aW9ucygpXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGF3YWl0IHRoaXMucmVsZWFzZUh0dHBTZXJ2ZXJMb2NrKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyByZWxlYXNlIGh0dHAgc2VydmVyIGxvY2suXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIHRoZSBIVFRQIHNlcnZlciBsb2NrIGhhcyBiZWVuIHJlbGVhc2VkLlxuICAgKi9cbiAgYXN5bmMgcmVsZWFzZUh0dHBTZXJ2ZXJMb2NrKCkge1xuICAgIGNvbnN0IHtodHRwU2VydmVyTG9ja30gPSB0aGlzXG5cbiAgICB0aGlzLmh0dHBTZXJ2ZXJMb2NrID0gdW5kZWZpbmVkXG4gICAgaWYgKGh0dHBTZXJ2ZXJMb2NrKSBhd2FpdCBodHRwU2VydmVyTG9jay5yZWxlYXNlKClcbiAgfVxuXG4gIC8qKlxuICAgKiBPbiBodHRwIHNlcnZlciBjbG9zZS5cbiAgICogQHJldHVybnMge3ZvaWR9IC0gTm8gcmV0dXJuIHZhbHVlLlxuICAgKi9cbiAgb25IdHRwU2VydmVyQ2xvc2UgPSAoKSA9PiB7XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoXCJIVFRQIHNlcnZlciBjbG9zZWRcIilcblxuICAgIGlmICh0aGlzLndhaXRSZXNvbHZlKSB7XG4gICAgICB0aGlzLndhaXRSZXNvbHZlKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyB3YWl0LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLlxuICAgKi9cbiAgd2FpdCgpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgIHRoaXMud2FpdFJlc29sdmUgPSByZXNvbHZlXG4gICAgfSlcbiAgfVxufVxuIl19
|
|
202
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbGljYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBwbGljYXRpb24uanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sU0FBUyxNQUFNLHdCQUF3QixDQUFBO0FBQzlDLE9BQU8sTUFBTSxNQUFNLGFBQWEsQ0FBQTtBQUNoQyxPQUFPLFVBQVUsTUFBTSx3QkFBd0IsQ0FBQTtBQUMvQyxPQUFPLGNBQWMsTUFBTSw4QkFBOEIsQ0FBQTtBQUN6RCxPQUFPLGlCQUFpQixNQUFNLCtCQUErQixDQUFBO0FBQzdELE9BQU8sbUJBQW1CLE1BQU0sd0NBQXdDLENBQUE7QUFDeEUsT0FBTyxhQUFhLE1BQU0sNEJBQTRCLENBQUE7QUFFdEQ7O21HQUVtRztBQUVuRyxNQUFNLENBQUMsT0FBTyxPQUFPLG9CQUFvQjtJQUN2Qzs7Ozs7O09BTUc7SUFDSCxZQUFZLEVBQUMsYUFBYSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsR0FBRyxRQUFRLEVBQUM7UUFDeEQsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBRXZCLElBQUksQ0FBQyxhQUFhO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQywyQkFBMkIsQ0FBQyxDQUFBO1FBRWhFLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFBO1FBRWxDOzs2Q0FFcUM7UUFDckMsSUFBSSxDQUFDLHVCQUF1QixHQUFHLFVBQVUsSUFBSSxFQUFFLENBQUE7UUFFL0MsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUM5QixJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQTtRQUNqQjs7Z0RBRXdDO1FBQ3hDLElBQUksQ0FBQyxjQUFjLEdBQUcsU0FBUyxDQUFBO0lBQ2pDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxPQUFPLEtBQUssT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFBLENBQUMsQ0FBQztJQUUvQjs7O09BR0c7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QUUxQyxJQUFJLENBQUM7WUFDSCxNQUFNLElBQUksQ0FBQyxVQUFVLEVBQUUsSUFBSSxFQUFFLENBQUE7WUFDN0IsSUFBSSxDQUFDLGFBQWEsQ0FBQyxtQkFBbUIsR0FBRyxTQUFTLENBQUE7WUFDbEQsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLGdCQUFnQixFQUFFLENBQUE7WUFDM0MsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLHdCQUF3QixFQUFFLENBQUE7UUFDckQsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsTUFBTSxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQTtRQUNwQyxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxxQkFBcUI7UUFDekIsTUFBTSxFQUFDLGNBQWMsRUFBQyxHQUFHLElBQUksQ0FBQTtRQUU3QixJQUFJLENBQUMsY0FBYyxHQUFHLFNBQVMsQ0FBQTtRQUMvQixJQUFJLGNBQWM7WUFBRSxNQUFNLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQTtJQUNwRCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsaUJBQWlCLEdBQUcsR0FBRyxFQUFFO1FBQ3ZCLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLG9CQUFvQixDQUFDLENBQUE7UUFFdkMsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFBO1FBQ3BCLENBQUM7SUFDSCxDQUFDLENBQUE7SUFFRDs7O09BR0c7SUFDSCxJQUFJO1FBQ0YsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQzdCLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFBO1FBQzVCLENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBBcHBSb3V0ZXMgZnJvbSBcIi4vcm91dGVzL2FwcC1yb3V0ZXMuanNcIlxuaW1wb3J0IExvZ2dlciBmcm9tIFwiLi9sb2dnZXIuanNcIlxuaW1wb3J0IEh0dHBTZXJ2ZXIgZnJvbSBcIi4vaHR0cC1zZXJ2ZXIvaW5kZXguanNcIlxuaW1wb3J0IEh0dHBTZXJ2ZXJMb2NrIGZyb20gXCIuL2h0dHAtc2VydmVyL3NlcnZlci1sb2NrLmpzXCJcbmltcG9ydCBTeW5jQXBpQ29udHJvbGxlciBmcm9tIFwiLi9zeW5jL3N5bmMtYXBpLWNvbnRyb2xsZXIuanNcIlxuaW1wb3J0IHdlYnNvY2tldEV2ZW50c0hvc3QgZnJvbSBcIi4vaHR0cC1zZXJ2ZXIvd2Vic29ja2V0LWV2ZW50cy1ob3N0LmpzXCJcbmltcG9ydCByZXN0QXJnc0Vycm9yIGZyb20gXCIuL3V0aWxzL3Jlc3QtYXJncy1lcnJvci5qc1wiXG5cbi8qKlxuICogSHR0cFNlcnZlckNvbmZpZ3VyYXRpb24gdHlwZS5cbiAqIEB0eXBlZGVmIHtpbXBvcnQoXCIuL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuSHR0cFNlcnZlckNvbmZpZ3VyYXRpb259IEh0dHBTZXJ2ZXJDb25maWd1cmF0aW9uICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFZlbG9jaW91c0FwcGxpY2F0aW9uIHtcbiAgLyoqXG4gICAqIFJ1bnMgY29uc3RydWN0b3IuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucyBvYmplY3QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9IGFyZ3MuY29uZmlndXJhdGlvbiAtIENvbmZpZ3VyYXRpb24gaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7SHR0cFNlcnZlckNvbmZpZ3VyYXRpb259IFthcmdzLmh0dHBTZXJ2ZXJdIC0gSHR0cCBzZXJ2ZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLnR5cGUgLSBUeXBlIGlkZW50aWZpZXIuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcih7Y29uZmlndXJhdGlvbiwgaHR0cFNlcnZlciwgdHlwZSwgLi4ucmVzdEFyZ3N9KSB7XG4gICAgcmVzdEFyZ3NFcnJvcihyZXN0QXJncylcblxuICAgIGlmICghY29uZmlndXJhdGlvbikgdGhyb3cgbmV3IEVycm9yKFwiY29uZmlndXJhdGlvbiBpcyByZXF1aXJlZFwiKVxuXG4gICAgdGhpcy5jb25maWd1cmF0aW9uID0gY29uZmlndXJhdGlvblxuXG4gICAgLyoqXG4gICAgICogU3RvcmVzIHRoZSBodHRwIHNlcnZlciBjb25maWd1cmF0aW9uIHZhbHVlLlxuICAgICAqIEB0eXBlIHtIdHRwU2VydmVyQ29uZmlndXJhdGlvbn0gKi9cbiAgICB0aGlzLmh0dHBTZXJ2ZXJDb25maWd1cmF0aW9uID0gaHR0cFNlcnZlciA/PyB7fVxuXG4gICAgdGhpcy5sb2dnZXIgPSBuZXcgTG9nZ2VyKHRoaXMpXG4gICAgdGhpcy5fdHlwZSA9IHR5cGVcbiAgICAvKipcbiAgICAgKiBTdG9yZXMgdGhlIGh0dHAgc2VydmVyIGxvY2sgdmFsdWUuXG4gICAgICogQHR5cGUge0h0dHBTZXJ2ZXJMb2NrIHwgdW5kZWZpbmVkfSAqL1xuICAgIHRoaXMuaHR0cFNlcnZlckxvY2sgPSB1bmRlZmluZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGdldCB0eXBlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIFRoZSB0eXBlLlxuICAgKi9cbiAgZ2V0VHlwZSgpIHsgcmV0dXJuIHRoaXMuX3R5cGUgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGluaXRpYWxpemUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuXG4gICAqL1xuICBhc3luYyBpbml0aWFsaXplKCkge1xuICAgIGNvbnN0IHJvdXRlcyA9IGF3YWl0IEFwcFJvdXRlcy5nZXRSb3V0ZXModGhpcy5jb25maWd1cmF0aW9uKVxuXG4gICAgYXdhaXQgdGhpcy5jb25maWd1cmF0aW9uLmluaXRpYWxpemUoe3R5cGU6IHRoaXMuZ2V0VHlwZSgpfSlcblxuICAgIFN5bmNBcGlDb250cm9sbGVyLm1vdW50RnJvbUNvbmZpZ3VyYXRpb24odGhpcy5jb25maWd1cmF0aW9uKVxuXG4gICAgdGhpcy5jb25maWd1cmF0aW9uLnNldFJvdXRlcyhyb3V0ZXMpXG5cbiAgICBpZiAoIXRoaXMuY29uZmlndXJhdGlvbi5pc0RhdGFiYXNlUG9vbEluaXRpYWxpemVkKCkpIHtcbiAgICAgIGF3YWl0IHRoaXMuY29uZmlndXJhdGlvbi5pbml0aWFsaXplRGF0YWJhc2VQb29sKClcbiAgICB9XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGlzIGFjdGl2ZS5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gV2hldGhlciBhY3RpdmUuXG4gICAqL1xuICBpc0FjdGl2ZSgpIHtcbiAgICBpZiAodGhpcy5odHRwU2VydmVyKSB7XG4gICAgICByZXR1cm4gdGhpcy5odHRwU2VydmVyPy5pc0FjdGl2ZSgpXG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogUnVucyBydW4uXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oKSA6IHZvaWR9IGNhbGxiYWNrIC0gQ2FsbGJhY2sgZnVuY3Rpb24uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuXG4gICAqL1xuICBhc3luYyBydW4oY2FsbGJhY2spIHtcbiAgICBhd2FpdCB0aGlzLnN0YXJ0SHR0cFNlcnZlcigpXG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgY2FsbGJhY2soKVxuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCB0aGlzLnN0b3AoKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHN0YXJ0IGh0dHAgc2VydmVyLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLlxuICAgKi9cbiAgYXN5bmMgc3RhcnRIdHRwU2VydmVyKCkge1xuICAgIGNvbnN0IHtjb25maWd1cmF0aW9ufSA9IHRoaXNcbiAgICBjb25zdCBodHRwU2VydmVyQ29uZmlndXJhdGlvbiA9IHtcbiAgICAgIC4uLmNvbmZpZ3VyYXRpb24uaHR0cFNlcnZlcixcbiAgICAgIC4uLnRoaXMuaHR0cFNlcnZlckNvbmZpZ3VyYXRpb25cbiAgICB9XG4gICAgY29uc3QgcG9ydCA9IGh0dHBTZXJ2ZXJDb25maWd1cmF0aW9uLnBvcnQgPz8gMzAwNlxuICAgIGNvbnN0IGhvc3QgPSBodHRwU2VydmVyQ29uZmlndXJhdGlvbi5ob3N0XG5cbiAgICBhd2FpdCB0aGlzLmxvZ2dlci5kZWJ1ZyhgU3RhcnRpbmcgc2VydmVyIG9uIHBvcnQgJHtwb3J0fWApXG4gICAgYXdhaXQgdGhpcy5hY3F1aXJlSHR0cFNlcnZlckxvY2soe2NvbmZpZ3VyYXRpb24sIGhvc3Q6IGhvc3QgPz8gXCIwLjAuMC4wXCIsIHBvcnR9KVxuICAgIGF3YWl0IHRoaXMuc3RhcnRMb2NrZWRIdHRwU2VydmVyKHtjb25maWd1cmF0aW9uLCBob3N0LCBodHRwU2VydmVyQ29uZmlndXJhdGlvbiwgcG9ydH0pXG4gIH1cblxuICAvKipcbiAgICogUnVucyBzdGFydCBsb2NrZWQgaHR0cCBzZXJ2ZXIuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gSFRUUCBzZXJ2ZXIgc3RhcnR1cCBhcmd1bWVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHR9IGFyZ3MuY29uZmlndXJhdGlvbiAtIENvbmZpZ3VyYXRpb24gaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYXJncy5ob3N0XSAtIEhUVFAgc2VydmVyIGhvc3QuXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgPz59IGFyZ3MuaHR0cFNlcnZlckNvbmZpZ3VyYXRpb24gLSBNZXJnZWQgSFRUUCBzZXJ2ZXIgY29uZmlndXJhdGlvbi5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGFyZ3MucG9ydCAtIEhUVFAgc2VydmVyIHBvcnQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIHRoZSBIVFRQIHNlcnZlciBoYXMgc3RhcnRlZC5cbiAgICovXG4gIGFzeW5jIHN0YXJ0TG9ja2VkSHR0cFNlcnZlcih7Y29uZmlndXJhdGlvbiwgaG9zdCwgaHR0cFNlcnZlckNvbmZpZ3VyYXRpb24sIHBvcnR9KSB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICghY29uZmlndXJhdGlvbi5nZXRXZWJzb2NrZXRFdmVudHMoKSkge1xuICAgICAgICBjb25maWd1cmF0aW9uLnNldFdlYnNvY2tldEV2ZW50cygvKiogQHR5cGUgez99ICovICh3ZWJzb2NrZXRFdmVudHNIb3N0KSlcbiAgICAgIH1cblxuICAgICAgYXdhaXQgY29uZmlndXJhdGlvbi5jb25uZWN0QmVhY29uKHtwZWVyVHlwZTogXCJzZXJ2ZXJcIn0pXG5cbiAgICAgIHRoaXMuaHR0cFNlcnZlciA9IHRoaXMuY3JlYXRlSHR0cFNlcnZlcih7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24sXG4gICAgICAgIGhvc3QsXG4gICAgICAgIGluUHJvY2VzczogaHR0cFNlcnZlckNvbmZpZ3VyYXRpb24uaW5Qcm9jZXNzLFxuICAgICAgICBtYXhXb3JrZXJzOiBodHRwU2VydmVyQ29uZmlndXJhdGlvbi5tYXhXb3JrZXJzLFxuICAgICAgICBwb3J0LFxuICAgICAgICB3b3JrZXJzOiBodHRwU2VydmVyQ29uZmlndXJhdGlvbi53b3JrZXJzXG4gICAgICB9KVxuICAgICAgdGhpcy5odHRwU2VydmVyLmV2ZW50cy5vbihcImNsb3NlXCIsIHRoaXMub25IdHRwU2VydmVyQ2xvc2UpXG4gICAgICBjb25maWd1cmF0aW9uLl9odHRwU2VydmVySW5zdGFuY2UgPSB0aGlzLmh0dHBTZXJ2ZXJcblxuICAgICAgYXdhaXQgdGhpcy5odHRwU2VydmVyLnN0YXJ0KClcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgYXdhaXQgdGhpcy5yZWxlYXNlSHR0cFNlcnZlckxvY2soKVxuICAgICAgY29uZmlndXJhdGlvbi5faHR0cFNlcnZlckluc3RhbmNlID0gdW5kZWZpbmVkXG5cbiAgICAgIHRocm93IGVycm9yXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgYWNxdWlyZSBodHRwIHNlcnZlciBsb2NrLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIExvY2sgYWNxdWlzaXRpb24gYXJndW1lbnRzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBhcmdzLmNvbmZpZ3VyYXRpb24gLSBDb25maWd1cmF0aW9uIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy5ob3N0IC0gSFRUUCBzZXJ2ZXIgaG9zdC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGFyZ3MucG9ydCAtIEhUVFAgc2VydmVyIHBvcnQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIGFjcXVpcmluZyB0aGUgc2VydmVyIGxvY2sgd2hlbiBuZWVkZWQuXG4gICAqL1xuICBhc3luYyBhY3F1aXJlSHR0cFNlcnZlckxvY2soe2NvbmZpZ3VyYXRpb24sIGhvc3QsIHBvcnR9KSB7XG4gICAgaWYgKHRoaXMuZ2V0VHlwZSgpID09PSBcInRlc3QtcnVubmVyXCIpIHJldHVyblxuXG4gICAgY29uc3QgaHR0cFNlcnZlckxvY2sgPSBuZXcgSHR0cFNlcnZlckxvY2soe2NvbmZpZ3VyYXRpb24sIGhvc3QsIHBvcnR9KVxuICAgIGF3YWl0IGh0dHBTZXJ2ZXJMb2NrLmFjcXVpcmUoKVxuICAgIHRoaXMuaHR0cFNlcnZlckxvY2sgPSBodHRwU2VydmVyTG9ja1xuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgY3JlYXRlIGh0dHAgc2VydmVyLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIEhUVFAgc2VydmVyIGFyZ3VtZW50cy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2NvbmZpZ3VyYXRpb24uanNcIikuZGVmYXVsdH0gYXJncy5jb25maWd1cmF0aW9uIC0gQ29uZmlndXJhdGlvbiBpbnN0YW5jZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFthcmdzLmhvc3RdIC0gSG9zdC5cbiAgICogQHBhcmFtIHtib29sZWFufSBbYXJncy5pblByb2Nlc3NdIC0gUnVuIEhUVFAgaGFuZGxlcnMgaW4gdGhlIG1haW4gdGhyZWFkLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW2FyZ3MubWF4V29ya2Vyc10gLSBNYXggd29ya2Vycy5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGFyZ3MucG9ydCAtIFBvcnQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJncy53b3JrZXJzXSAtIFdvcmtlciBjb3VudC5cbiAgICogQHJldHVybnMge0h0dHBTZXJ2ZXJ9IC0gSFRUUCBzZXJ2ZXIgaW5zdGFuY2UuXG4gICAqL1xuICBjcmVhdGVIdHRwU2VydmVyKHtjb25maWd1cmF0aW9uLCBob3N0LCBpblByb2Nlc3MsIG1heFdvcmtlcnMsIHBvcnQsIHdvcmtlcnN9KSB7XG4gICAgcmV0dXJuIG5ldyBIdHRwU2VydmVyKHtjb25maWd1cmF0aW9uLCBob3N0LCBpblByb2Nlc3MsIG1heFdvcmtlcnMsIHBvcnQsIHdvcmtlcnN9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc3RvcC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS5cbiAgICovXG4gIGFzeW5jIHN0b3AoKSB7XG4gICAgYXdhaXQgdGhpcy5sb2dnZXIuZGVidWcoXCJTdG9wcGluZyBzZXJ2ZXJcIilcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmh0dHBTZXJ2ZXI/LnN0b3AoKVxuICAgICAgdGhpcy5jb25maWd1cmF0aW9uLl9odHRwU2VydmVySW5zdGFuY2UgPSB1bmRlZmluZWRcbiAgICAgIGF3YWl0IHRoaXMuY29uZmlndXJhdGlvbi5kaXNjb25uZWN0QmVhY29uKClcbiAgICAgIGF3YWl0IHRoaXMuY29uZmlndXJhdGlvbi5jbG9zZURhdGFiYXNlQ29ubmVjdGlvbnMoKVxuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCB0aGlzLnJlbGVhc2VIdHRwU2VydmVyTG9jaygpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgcmVsZWFzZSBodHRwIHNlcnZlciBsb2NrLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyBhZnRlciB0aGUgSFRUUCBzZXJ2ZXIgbG9jayBoYXMgYmVlbiByZWxlYXNlZC5cbiAgICovXG4gIGFzeW5jIHJlbGVhc2VIdHRwU2VydmVyTG9jaygpIHtcbiAgICBjb25zdCB7aHR0cFNlcnZlckxvY2t9ID0gdGhpc1xuXG4gICAgdGhpcy5odHRwU2VydmVyTG9jayA9IHVuZGVmaW5lZFxuICAgIGlmIChodHRwU2VydmVyTG9jaykgYXdhaXQgaHR0cFNlcnZlckxvY2sucmVsZWFzZSgpXG4gIH1cblxuICAvKipcbiAgICogT24gaHR0cCBzZXJ2ZXIgY2xvc2UuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIG9uSHR0cFNlcnZlckNsb3NlID0gKCkgPT4ge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKFwiSFRUUCBzZXJ2ZXIgY2xvc2VkXCIpXG5cbiAgICBpZiAodGhpcy53YWl0UmVzb2x2ZSkge1xuICAgICAgdGhpcy53YWl0UmVzb2x2ZSgpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgd2FpdC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS5cbiAgICovXG4gIHdhaXQoKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICB0aGlzLndhaXRSZXNvbHZlID0gcmVzb2x2ZVxuICAgIH0pXG4gIH1cbn1cbiJdfQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../../../../src/cli/commands/db/tenants/create.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../../../../src/cli/commands/db/tenants/create.js"],"names":[],"mappings":"AAMA;IACE;;;OAGG;IACH,WAFa,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,GAAG,IAAI,CAAC,CAwBrE;CACF;wBAhCuB,0BAA0B"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import BaseCommand from "../../../base-command.js";
|
|
3
|
+
import { createTenantDatabase } from "../../../../tenants/default-tenant-database-provisioning.js";
|
|
3
4
|
import TenantDatabaseCommandHelper from "../../../tenant-database-command-helper.js";
|
|
4
5
|
export default class DbTenantsCreate extends BaseCommand {
|
|
5
6
|
/**
|
|
@@ -12,11 +13,13 @@ export default class DbTenantsCreate extends BaseCommand {
|
|
|
12
13
|
identifier: this.processArgs?.[1]
|
|
13
14
|
});
|
|
14
15
|
const provider = helper.provider;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
// Providers may customize creation, but the generic driver-agnostic provisioning
|
|
17
|
+
// is the framework default so apps do not reimplement it.
|
|
18
|
+
const createDatabase = typeof provider.createDatabase === "function"
|
|
19
|
+
? provider.createDatabase.bind(provider)
|
|
20
|
+
: createTenantDatabase;
|
|
18
21
|
const tenantCount = await helper.eachTenant(async ({ databaseConfiguration, tenant }) => {
|
|
19
|
-
await
|
|
22
|
+
await createDatabase({
|
|
20
23
|
configuration: this.getConfiguration(),
|
|
21
24
|
databaseConfiguration,
|
|
22
25
|
identifier: helper.identifier,
|
|
@@ -27,4 +30,4 @@ export default class DbTenantsCreate extends BaseCommand {
|
|
|
27
30
|
return { identifier: helper.identifier, tenantCount };
|
|
28
31
|
}
|
|
29
32
|
}
|
|
30
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
33
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2NsaS9jb21tYW5kcy9kYi90ZW5hbnRzL2NyZWF0ZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxXQUFXLE1BQU0sMEJBQTBCLENBQUE7QUFDbEQsT0FBTyxFQUFDLG9CQUFvQixFQUFDLE1BQU0sNkRBQTZELENBQUE7QUFDaEcsT0FBTywyQkFBMkIsTUFBTSw0Q0FBNEMsQ0FBQTtBQUVwRixNQUFNLENBQUMsT0FBTyxPQUFPLGVBQWdCLFNBQVEsV0FBVztJQUN0RDs7O09BR0c7SUFDSCxLQUFLLENBQUMsT0FBTztRQUNYLE1BQU0sTUFBTSxHQUFHLElBQUksMkJBQTJCLENBQUM7WUFDN0MsT0FBTyxFQUFFLElBQUk7WUFDYixVQUFVLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQztTQUNsQyxDQUFDLENBQUE7UUFDRixNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFBO1FBQ2hDLGlGQUFpRjtRQUNqRiwwREFBMEQ7UUFDMUQsTUFBTSxjQUFjLEdBQUcsT0FBTyxRQUFRLENBQUMsY0FBYyxLQUFLLFVBQVU7WUFDbEUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztZQUN4QyxDQUFDLENBQUMsb0JBQW9CLENBQUE7UUFFeEIsTUFBTSxXQUFXLEdBQUcsTUFBTSxNQUFNLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxFQUFDLHFCQUFxQixFQUFFLE1BQU0sRUFBQyxFQUFFLEVBQUU7WUFDcEYsTUFBTSxjQUFjLENBQUM7Z0JBQ25CLGFBQWEsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7Z0JBQ3RDLHFCQUFxQjtnQkFDckIsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVO2dCQUM3QixNQUFNO2FBQ1AsQ0FBQyxDQUFBO1FBQ0osQ0FBQyxDQUFDLENBQUE7UUFFRixJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTztZQUFFLE9BQU8sRUFBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVUsRUFBRSxXQUFXLEVBQUMsQ0FBQTtJQUM1RSxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IEJhc2VDb21tYW5kIGZyb20gXCIuLi8uLi8uLi9iYXNlLWNvbW1hbmQuanNcIlxuaW1wb3J0IHtjcmVhdGVUZW5hbnREYXRhYmFzZX0gZnJvbSBcIi4uLy4uLy4uLy4uL3RlbmFudHMvZGVmYXVsdC10ZW5hbnQtZGF0YWJhc2UtcHJvdmlzaW9uaW5nLmpzXCJcbmltcG9ydCBUZW5hbnREYXRhYmFzZUNvbW1hbmRIZWxwZXIgZnJvbSBcIi4uLy4uLy4uL3RlbmFudC1kYXRhYmFzZS1jb21tYW5kLWhlbHBlci5qc1wiXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIERiVGVuYW50c0NyZWF0ZSBleHRlbmRzIEJhc2VDb21tYW5kIHtcbiAgLyoqXG4gICAqIFJ1bnMgZXhlY3V0ZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8e2lkZW50aWZpZXI6IHN0cmluZywgdGVuYW50Q291bnQ6IG51bWJlcn0gfCB2b2lkPn0gLSBSZXN1bHQgaW4gdGVzdCBtb2RlLlxuICAgKi9cbiAgYXN5bmMgZXhlY3V0ZSgpIHtcbiAgICBjb25zdCBoZWxwZXIgPSBuZXcgVGVuYW50RGF0YWJhc2VDb21tYW5kSGVscGVyKHtcbiAgICAgIGNvbW1hbmQ6IHRoaXMsXG4gICAgICBpZGVudGlmaWVyOiB0aGlzLnByb2Nlc3NBcmdzPy5bMV1cbiAgICB9KVxuICAgIGNvbnN0IHByb3ZpZGVyID0gaGVscGVyLnByb3ZpZGVyXG4gICAgLy8gUHJvdmlkZXJzIG1heSBjdXN0b21pemUgY3JlYXRpb24sIGJ1dCB0aGUgZ2VuZXJpYyBkcml2ZXItYWdub3N0aWMgcHJvdmlzaW9uaW5nXG4gICAgLy8gaXMgdGhlIGZyYW1ld29yayBkZWZhdWx0IHNvIGFwcHMgZG8gbm90IHJlaW1wbGVtZW50IGl0LlxuICAgIGNvbnN0IGNyZWF0ZURhdGFiYXNlID0gdHlwZW9mIHByb3ZpZGVyLmNyZWF0ZURhdGFiYXNlID09PSBcImZ1bmN0aW9uXCJcbiAgICAgID8gcHJvdmlkZXIuY3JlYXRlRGF0YWJhc2UuYmluZChwcm92aWRlcilcbiAgICAgIDogY3JlYXRlVGVuYW50RGF0YWJhc2VcblxuICAgIGNvbnN0IHRlbmFudENvdW50ID0gYXdhaXQgaGVscGVyLmVhY2hUZW5hbnQoYXN5bmMgKHtkYXRhYmFzZUNvbmZpZ3VyYXRpb24sIHRlbmFudH0pID0+IHtcbiAgICAgIGF3YWl0IGNyZWF0ZURhdGFiYXNlKHtcbiAgICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5nZXRDb25maWd1cmF0aW9uKCksXG4gICAgICAgIGRhdGFiYXNlQ29uZmlndXJhdGlvbixcbiAgICAgICAgaWRlbnRpZmllcjogaGVscGVyLmlkZW50aWZpZXIsXG4gICAgICAgIHRlbmFudFxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgaWYgKHRoaXMuYXJncy50ZXN0aW5nKSByZXR1cm4ge2lkZW50aWZpZXI6IGhlbHBlci5pZGVudGlmaWVyLCB0ZW5hbnRDb3VudH1cbiAgfVxufVxuIl19
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default class DbTenantsDrop extends BaseCommand {
|
|
2
2
|
/**
|
|
3
3
|
* Drops the tenant database/schema for every listed tenant through the provider's
|
|
4
|
-
* `dropDatabase` hook.
|
|
4
|
+
* `dropDatabase` hook, or the framework default when the provider defines none.
|
|
5
5
|
* @returns {Promise<{identifier: string, tenantCount: number} | void>} - Result in test mode.
|
|
6
6
|
*/
|
|
7
7
|
execute(): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drop.d.ts","sourceRoot":"","sources":["../../../../../../src/cli/commands/db/tenants/drop.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"drop.d.ts","sourceRoot":"","sources":["../../../../../../src/cli/commands/db/tenants/drop.js"],"names":[],"mappings":"AAMA;IACE;;;;OAIG;IACH,WAFa,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,GAAG,IAAI,CAAC,CAsBrE;CACF;wBA/BuB,0BAA0B"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import BaseCommand from "../../../base-command.js";
|
|
3
|
+
import { dropTenantDatabase } from "../../../../tenants/default-tenant-database-provisioning.js";
|
|
3
4
|
import TenantDatabaseCommandHelper from "../../../tenant-database-command-helper.js";
|
|
4
5
|
export default class DbTenantsDrop extends BaseCommand {
|
|
5
6
|
/**
|
|
6
7
|
* Drops the tenant database/schema for every listed tenant through the provider's
|
|
7
|
-
* `dropDatabase` hook.
|
|
8
|
+
* `dropDatabase` hook, or the framework default when the provider defines none.
|
|
8
9
|
* @returns {Promise<{identifier: string, tenantCount: number} | void>} - Result in test mode.
|
|
9
10
|
*/
|
|
10
11
|
async execute() {
|
|
@@ -13,11 +14,11 @@ export default class DbTenantsDrop extends BaseCommand {
|
|
|
13
14
|
identifier: this.processArgs?.[1]
|
|
14
15
|
});
|
|
15
16
|
const provider = helper.provider;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
const dropDatabase = typeof provider.dropDatabase === "function"
|
|
18
|
+
? provider.dropDatabase.bind(provider)
|
|
19
|
+
: dropTenantDatabase;
|
|
19
20
|
const tenantCount = await helper.eachTenant(async ({ databaseConfiguration, tenant }) => {
|
|
20
|
-
await
|
|
21
|
+
await dropDatabase({
|
|
21
22
|
configuration: this.getConfiguration(),
|
|
22
23
|
databaseConfiguration,
|
|
23
24
|
identifier: helper.identifier,
|
|
@@ -28,4 +29,4 @@ export default class DbTenantsDrop extends BaseCommand {
|
|
|
28
29
|
return { identifier: helper.identifier, tenantCount };
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
32
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9jbGkvY29tbWFuZHMvZGIvdGVuYW50cy9kcm9wLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLFdBQVcsTUFBTSwwQkFBMEIsQ0FBQTtBQUNsRCxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSw2REFBNkQsQ0FBQTtBQUM5RixPQUFPLDJCQUEyQixNQUFNLDRDQUE0QyxDQUFBO0FBRXBGLE1BQU0sQ0FBQyxPQUFPLE9BQU8sYUFBYyxTQUFRLFdBQVc7SUFDcEQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxPQUFPO1FBQ1gsTUFBTSxNQUFNLEdBQUcsSUFBSSwyQkFBMkIsQ0FBQztZQUM3QyxPQUFPLEVBQUUsSUFBSTtZQUNiLFVBQVUsRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQ2xDLENBQUMsQ0FBQTtRQUNGLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUE7UUFDaEMsTUFBTSxZQUFZLEdBQUcsT0FBTyxRQUFRLENBQUMsWUFBWSxLQUFLLFVBQVU7WUFDOUQsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztZQUN0QyxDQUFDLENBQUMsa0JBQWtCLENBQUE7UUFFdEIsTUFBTSxXQUFXLEdBQUcsTUFBTSxNQUFNLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxFQUFDLHFCQUFxQixFQUFFLE1BQU0sRUFBQyxFQUFFLEVBQUU7WUFDcEYsTUFBTSxZQUFZLENBQUM7Z0JBQ2pCLGFBQWEsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7Z0JBQ3RDLHFCQUFxQjtnQkFDckIsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVO2dCQUM3QixNQUFNO2FBQ1AsQ0FBQyxDQUFBO1FBQ0osQ0FBQyxDQUFDLENBQUE7UUFFRixJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTztZQUFFLE9BQU8sRUFBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVUsRUFBRSxXQUFXLEVBQUMsQ0FBQTtJQUM1RSxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IEJhc2VDb21tYW5kIGZyb20gXCIuLi8uLi8uLi9iYXNlLWNvbW1hbmQuanNcIlxuaW1wb3J0IHtkcm9wVGVuYW50RGF0YWJhc2V9IGZyb20gXCIuLi8uLi8uLi8uLi90ZW5hbnRzL2RlZmF1bHQtdGVuYW50LWRhdGFiYXNlLXByb3Zpc2lvbmluZy5qc1wiXG5pbXBvcnQgVGVuYW50RGF0YWJhc2VDb21tYW5kSGVscGVyIGZyb20gXCIuLi8uLi8uLi90ZW5hbnQtZGF0YWJhc2UtY29tbWFuZC1oZWxwZXIuanNcIlxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBEYlRlbmFudHNEcm9wIGV4dGVuZHMgQmFzZUNvbW1hbmQge1xuICAvKipcbiAgICogRHJvcHMgdGhlIHRlbmFudCBkYXRhYmFzZS9zY2hlbWEgZm9yIGV2ZXJ5IGxpc3RlZCB0ZW5hbnQgdGhyb3VnaCB0aGUgcHJvdmlkZXInc1xuICAgKiBgZHJvcERhdGFiYXNlYCBob29rLCBvciB0aGUgZnJhbWV3b3JrIGRlZmF1bHQgd2hlbiB0aGUgcHJvdmlkZXIgZGVmaW5lcyBub25lLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx7aWRlbnRpZmllcjogc3RyaW5nLCB0ZW5hbnRDb3VudDogbnVtYmVyfSB8IHZvaWQ+fSAtIFJlc3VsdCBpbiB0ZXN0IG1vZGUuXG4gICAqL1xuICBhc3luYyBleGVjdXRlKCkge1xuICAgIGNvbnN0IGhlbHBlciA9IG5ldyBUZW5hbnREYXRhYmFzZUNvbW1hbmRIZWxwZXIoe1xuICAgICAgY29tbWFuZDogdGhpcyxcbiAgICAgIGlkZW50aWZpZXI6IHRoaXMucHJvY2Vzc0FyZ3M/LlsxXVxuICAgIH0pXG4gICAgY29uc3QgcHJvdmlkZXIgPSBoZWxwZXIucHJvdmlkZXJcbiAgICBjb25zdCBkcm9wRGF0YWJhc2UgPSB0eXBlb2YgcHJvdmlkZXIuZHJvcERhdGFiYXNlID09PSBcImZ1bmN0aW9uXCJcbiAgICAgID8gcHJvdmlkZXIuZHJvcERhdGFiYXNlLmJpbmQocHJvdmlkZXIpXG4gICAgICA6IGRyb3BUZW5hbnREYXRhYmFzZVxuXG4gICAgY29uc3QgdGVuYW50Q291bnQgPSBhd2FpdCBoZWxwZXIuZWFjaFRlbmFudChhc3luYyAoe2RhdGFiYXNlQ29uZmlndXJhdGlvbiwgdGVuYW50fSkgPT4ge1xuICAgICAgYXdhaXQgZHJvcERhdGFiYXNlKHtcbiAgICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5nZXRDb25maWd1cmF0aW9uKCksXG4gICAgICAgIGRhdGFiYXNlQ29uZmlndXJhdGlvbixcbiAgICAgICAgaWRlbnRpZmllcjogaGVscGVyLmlkZW50aWZpZXIsXG4gICAgICAgIHRlbmFudFxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgaWYgKHRoaXMuYXJncy50ZXN0aW5nKSByZXR1cm4ge2lkZW50aWZpZXI6IGhlbHBlci5pZGVudGlmaWVyLCB0ZW5hbnRDb3VudH1cbiAgfVxufVxuIl19
|