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