velocious 1.0.481 → 1.0.482

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.
@@ -0,0 +1,326 @@
1
+ // @ts-check
2
+ import MigrationsLedger from "../migrations-ledger.js";
3
+ import TableData from "../table-data/index.js";
4
+ import TableIndex from "../table-data/table-index.js";
5
+ const SIMPLE_DEFAULT_PATTERN = /^(?:-?\d+(?:\.\d+)?|[A-Za-z0-9 _.,:/@+-]*)$/;
6
+ /** @type {Record<string, number>} */
7
+ const TEXT_TYPE_RANKS = {
8
+ tinytext: 1,
9
+ text: 2,
10
+ mediumtext: 3,
11
+ longtext: 4
12
+ };
13
+ /**
14
+ * Clones table structure (columns, text-type widening, indexes) from a source database
15
+ * into a target database for a given set of tables, then baselines the target's
16
+ * `schema_migrations` ledger to the source via {@link MigrationsLedger}. This is the
17
+ * mechanism multi-tenant apps use to provision a tenant database from a template/global
18
+ * database without re-running migrations: the structure is copied and the ledger is
19
+ * recorded as already-applied, so a later `db:tenants:migrate` does not re-run an
20
+ * `addColumn` whose column already exists.
21
+ *
22
+ * The cloner is intentionally policy-free — the caller decides which tables to sync and
23
+ * which databases are source/target. It is idempotent: missing tables are created,
24
+ * missing columns added, too-narrow text columns widened, and missing indexes created;
25
+ * an index whose definition diverges from the source is treated as drift and throws.
26
+ */
27
+ export default class SchemaCloner {
28
+ /**
29
+ * Creates a cloner that copies table structure from `sourceDb` into `targetDb`.
30
+ * @param {{sourceDb: import("../drivers/base.js").default, targetDb: import("../drivers/base.js").default}} args
31
+ */
32
+ constructor({ sourceDb, targetDb }) {
33
+ this.sourceDb = sourceDb;
34
+ this.targetDb = targetDb;
35
+ }
36
+ /**
37
+ * Clones every given table from the source into the target, then baselines the
38
+ * target's ledger so the cloned schema is recorded as already-migrated.
39
+ * @param {string[]} tableNames
40
+ * @returns {Promise<void>}
41
+ */
42
+ async syncTables(tableNames) {
43
+ for (const tableName of tableNames) {
44
+ await this.syncTable(tableName);
45
+ }
46
+ await this.reconcileLedger();
47
+ }
48
+ /**
49
+ * Clones a single table from the source into the target, creating it or adding and
50
+ * widening columns and indexes as needed.
51
+ * @param {string} tableName
52
+ * @returns {Promise<void>}
53
+ */
54
+ async syncTable(tableName) {
55
+ const sourceTable = await this.sourceDb.getTableByName(tableName);
56
+ if (!sourceTable) {
57
+ throw new Error(`Expected source table to exist: ${tableName}`);
58
+ }
59
+ if (!await this.targetDb.tableExists(tableName)) {
60
+ await this.createTargetTable({ sourceTable, tableName });
61
+ return;
62
+ }
63
+ const changedColumns = await this.ensureTargetColumns({ sourceTable, tableName });
64
+ if (changedColumns) {
65
+ this.targetDb.clearSchemaCache();
66
+ }
67
+ await this.ensureTargetIndexes({ sourceTable, tableName });
68
+ }
69
+ /**
70
+ * Creates the table in the target from the source table's columns and its
71
+ * non-primary-key indexes.
72
+ * @param {{sourceTable: import("../drivers/base-table.js").default, tableName: string}} args
73
+ * @returns {Promise<void>}
74
+ */
75
+ async createTargetTable({ sourceTable, tableName }) {
76
+ const tableData = new TableData(tableName);
77
+ for (const sourceColumn of await sourceTable.getColumns()) {
78
+ tableData.addColumn(sourceColumn.getName(), this.columnArgsFromSourceColumn(sourceColumn, { isNewColumn: false }));
79
+ }
80
+ for (const sourceIndex of await sourceTable.getIndexes()) {
81
+ if (!sourceIndex.isPrimaryKey()) {
82
+ tableData.addIndex(this.tableDataIndexFromSourceIndex(sourceIndex));
83
+ }
84
+ }
85
+ await this.targetDb.createTable(tableData);
86
+ this.targetDb.clearSchemaCache();
87
+ }
88
+ /**
89
+ * Adds columns present on the source but missing from the target, and widens
90
+ * too-narrow target text columns.
91
+ * @param {{sourceTable: import("../drivers/base-table.js").default, tableName: string}} args
92
+ * @returns {Promise<boolean>} Whether any column was added or widened.
93
+ */
94
+ async ensureTargetColumns({ sourceTable, tableName }) {
95
+ const sourceColumns = await sourceTable.getColumns();
96
+ const targetTable = await this.targetDb.getTableByNameOrFail(tableName);
97
+ const targetColumnsByName = new Map();
98
+ const missingColumns = [];
99
+ const columnsNeedingWidening = [];
100
+ for (const targetColumn of await targetTable.getColumns()) {
101
+ targetColumnsByName.set(targetColumn.getName(), targetColumn);
102
+ }
103
+ for (const sourceColumn of sourceColumns) {
104
+ const targetColumn = targetColumnsByName.get(sourceColumn.getName());
105
+ if (!targetColumn) {
106
+ missingColumns.push(sourceColumn);
107
+ }
108
+ else if (this.columnNeedsWidening(sourceColumn, targetColumn)) {
109
+ columnsNeedingWidening.push(sourceColumn);
110
+ }
111
+ }
112
+ if (missingColumns.length <= 0 && columnsNeedingWidening.length <= 0) {
113
+ return false;
114
+ }
115
+ const tableData = new TableData(tableName);
116
+ for (const sourceColumn of missingColumns) {
117
+ tableData.addColumn(sourceColumn.getName(), this.columnArgsFromSourceColumn(sourceColumn, { isNewColumn: true }));
118
+ }
119
+ for (const sourceColumn of columnsNeedingWidening) {
120
+ tableData.addColumn(sourceColumn.getName(), this.columnArgsFromSourceColumn(sourceColumn, { isNewColumn: false }));
121
+ }
122
+ for (const alterSql of await this.targetDb.alterTableSQLs(tableData)) {
123
+ await this.targetDb.query(alterSql);
124
+ }
125
+ return true;
126
+ }
127
+ /**
128
+ * Creates non-primary-key indexes present on the source but missing from the target,
129
+ * and throws if an existing target index diverges from the source.
130
+ * @param {{sourceTable: import("../drivers/base-table.js").default, tableName: string}} args
131
+ * @returns {Promise<void>}
132
+ */
133
+ async ensureTargetIndexes({ sourceTable, tableName }) {
134
+ const targetTable = await this.targetDb.getTableByNameOrFail(tableName);
135
+ /** @type {Map<string, import("../drivers/base-columns-index.js").default>} */
136
+ const targetIndexesByName = new Map();
137
+ const targetIndexSignatures = new Set();
138
+ let createdIndex = false;
139
+ for (const targetIndex of await targetTable.getIndexes()) {
140
+ targetIndexesByName.set(targetIndex.getName(), targetIndex);
141
+ targetIndexSignatures.add(this.indexSignature(targetIndex));
142
+ }
143
+ for (const sourceIndex of await sourceTable.getIndexes()) {
144
+ if (sourceIndex.isPrimaryKey()) {
145
+ continue;
146
+ }
147
+ const sourceIndexSignature = this.indexSignature(sourceIndex);
148
+ // SQLite index names are unique per-database, not per-table, so match cloned
149
+ // indexes by their column/uniqueness signature rather than their name.
150
+ if (this.targetDb.getType() === "sqlite" && targetIndexSignatures.has(sourceIndexSignature)) {
151
+ continue;
152
+ }
153
+ const targetIndex = this.targetDb.getType() === "sqlite" ? undefined : targetIndexesByName.get(sourceIndex.getName());
154
+ if (!targetIndex) {
155
+ const createIndexSqls = await this.targetDb.createIndexSQLs(this.createIndexArgsFromSourceIndex({ sourceIndex, tableName }));
156
+ for (const createIndexSql of createIndexSqls) {
157
+ await this.targetDb.query(createIndexSql);
158
+ }
159
+ createdIndex = true;
160
+ targetIndexSignatures.add(sourceIndexSignature);
161
+ continue;
162
+ }
163
+ if (!this.indexesMatch(sourceIndex, targetIndex)) {
164
+ throw new Error(`Schema clone index drift for ${tableName}.${sourceIndex.getName()}`);
165
+ }
166
+ }
167
+ if (createdIndex) {
168
+ this.targetDb.clearSchemaCache();
169
+ }
170
+ }
171
+ /**
172
+ * Baselines the target ledger so the cloned schema is recorded as already-applied.
173
+ * @returns {Promise<string[]>} The versions newly recorded on the target.
174
+ */
175
+ async reconcileLedger() {
176
+ return await MigrationsLedger.baselineFromDatabase({ sourceDb: this.sourceDb, targetDb: this.targetDb });
177
+ }
178
+ /**
179
+ * Whether the target ledger is missing any version applied on the source — i.e. the
180
+ * target schema may have been advanced out of band without recording it.
181
+ * @returns {Promise<boolean>}
182
+ */
183
+ async ledgerDriftsFromSource() {
184
+ if (!await MigrationsLedger.tableExists(this.targetDb)) {
185
+ return true;
186
+ }
187
+ const sourceVersions = await MigrationsLedger.appliedVersions(this.sourceDb);
188
+ const targetVersionSet = new Set(await MigrationsLedger.appliedVersions(this.targetDb));
189
+ return sourceVersions.some((version) => !targetVersionSet.has(version));
190
+ }
191
+ /**
192
+ * Maps a source index into a TableData index for table creation (SQLite omits the
193
+ * index name so the driver can generate a unique one).
194
+ * @param {import("../drivers/base-columns-index.js").default} sourceIndex
195
+ * @returns {TableIndex}
196
+ */
197
+ tableDataIndexFromSourceIndex(sourceIndex) {
198
+ /** @type {{name?: string, unique: boolean}} */
199
+ const args = { unique: sourceIndex.isUnique() };
200
+ // SQLite index names are unique per-database, not per-table, so let the driver
201
+ // generate one; other drivers preserve the source index name. Build the TableIndex
202
+ // directly (rather than via the driver's getTableDataIndex, which only MySQL and
203
+ // SQLite implement) so cloning a PostgreSQL or MS-SQL source table works too.
204
+ if (this.targetDb.getType() !== "sqlite") {
205
+ args.name = sourceIndex.getName();
206
+ }
207
+ return new TableIndex(sourceIndex.getColumnNames(), args);
208
+ }
209
+ /**
210
+ * Builds driver create-index args from a source index (the index name is omitted on
211
+ * SQLite, where index names are unique per-database rather than per-table).
212
+ * @param {{sourceIndex: import("../drivers/base-columns-index.js").default, tableName: string}} args
213
+ * @returns {{columns: string[], name?: string, tableName: string, unique: boolean}}
214
+ */
215
+ createIndexArgsFromSourceIndex({ sourceIndex, tableName }) {
216
+ /** @type {{columns: string[], name?: string, tableName: string, unique: boolean}} */
217
+ const createIndexArgs = {
218
+ columns: sourceIndex.getColumnNames(),
219
+ tableName,
220
+ unique: sourceIndex.isUnique()
221
+ };
222
+ if (this.targetDb.getType() !== "sqlite") {
223
+ createIndexArgs.name = sourceIndex.getName();
224
+ }
225
+ return createIndexArgs;
226
+ }
227
+ /**
228
+ * Whether two indexes have the same uniqueness and ordered column list.
229
+ * @param {import("../drivers/base-columns-index.js").default} sourceIndex
230
+ * @param {import("../drivers/base-columns-index.js").default} targetIndex
231
+ * @returns {boolean}
232
+ */
233
+ indexesMatch(sourceIndex, targetIndex) {
234
+ const sourceColumnNames = sourceIndex.getColumnNames();
235
+ const targetColumnNames = targetIndex.getColumnNames();
236
+ if (sourceIndex.isUnique() !== targetIndex.isUnique()) {
237
+ return false;
238
+ }
239
+ if (sourceColumnNames.length !== targetColumnNames.length) {
240
+ return false;
241
+ }
242
+ for (let columnIndex = 0; columnIndex < sourceColumnNames.length; columnIndex++) {
243
+ if (sourceColumnNames[columnIndex] !== targetColumnNames[columnIndex]) {
244
+ return false;
245
+ }
246
+ }
247
+ return true;
248
+ }
249
+ /**
250
+ * A stable signature for an index, used to match cloned indexes by shape.
251
+ * @param {import("../drivers/base-columns-index.js").default} index
252
+ * @returns {string}
253
+ */
254
+ indexSignature(index) {
255
+ return `${index.isUnique() ? "unique" : "index"}:${index.getColumnNames().join(",")}`;
256
+ }
257
+ /**
258
+ * Normalizes a column type to its canonical lowercase form (`int` becomes `integer`).
259
+ * @param {string} columnType
260
+ * @returns {string}
261
+ */
262
+ normalizedColumnType(columnType) {
263
+ const normalizedType = columnType.toLowerCase();
264
+ if (normalizedType === "int") {
265
+ return "integer";
266
+ }
267
+ return normalizedType;
268
+ }
269
+ /**
270
+ * The widening rank of a text column type (0 when not a text type).
271
+ * @param {string} columnType
272
+ * @returns {number}
273
+ */
274
+ textTypeRank(columnType) {
275
+ return TEXT_TYPE_RANKS[this.normalizedColumnType(columnType)] || 0;
276
+ }
277
+ /**
278
+ * Whether the target's text column is narrower than the source's and must be widened.
279
+ * @param {import("../drivers/base-column.js").default} sourceColumn
280
+ * @param {import("../drivers/base-column.js").default} targetColumn
281
+ * @returns {boolean}
282
+ */
283
+ columnNeedsWidening(sourceColumn, targetColumn) {
284
+ const sourceRank = this.textTypeRank(sourceColumn.getType());
285
+ const targetRank = this.textTypeRank(targetColumn.getType());
286
+ return sourceRank > 0 && targetRank > 0 && sourceRank > targetRank;
287
+ }
288
+ /**
289
+ * Builds TableData column args from a source column, copying type, nullability,
290
+ * length, notes, simple defaults and (for full clones) primary-key flag.
291
+ * @param {import("../drivers/base-column.js").default} sourceColumn
292
+ * @param {{isNewColumn: boolean}} args
293
+ * @returns {Record<string, unknown>}
294
+ */
295
+ columnArgsFromSourceColumn(sourceColumn, { isNewColumn }) {
296
+ /** @type {{autoIncrement?: boolean, default?: unknown, isNewColumn: boolean, maxLength?: number, notes?: string, null: boolean, primaryKey?: boolean, type: string}} */
297
+ const columnArgs = {
298
+ isNewColumn,
299
+ null: sourceColumn.getNull(),
300
+ type: this.normalizedColumnType(sourceColumn.getType())
301
+ };
302
+ const defaultValue = sourceColumn.getDefault();
303
+ const maxLength = sourceColumn.getMaxLength();
304
+ const notes = sourceColumn.getNotes();
305
+ if (!isNewColumn && sourceColumn.getPrimaryKey()) {
306
+ columnArgs.primaryKey = true;
307
+ }
308
+ if (sourceColumn.getAutoIncrement()) {
309
+ columnArgs.autoIncrement = true;
310
+ }
311
+ // A maxLength of -1 is the MS-SQL "max" sentinel (NVARCHAR(MAX) / VARBINARY(MAX),
312
+ // backing Velocious text/json/blob columns); the column type drives the unbounded
313
+ // SQL, so don't forward -1 as an explicit length (it would emit NVARCHAR(-1)).
314
+ if (maxLength !== undefined && maxLength >= 0) {
315
+ columnArgs.maxLength = maxLength;
316
+ }
317
+ if (notes) {
318
+ columnArgs.notes = notes;
319
+ }
320
+ if (defaultValue !== null && defaultValue !== undefined && SIMPLE_DEFAULT_PATTERN.test(String(defaultValue))) {
321
+ columnArgs.default = defaultValue;
322
+ }
323
+ return columnArgs;
324
+ }
325
+ }
326
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hLWNsb25lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9kYXRhYmFzZS90ZW5hbnRzL3NjaGVtYS1jbG9uZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sZ0JBQWdCLE1BQU0seUJBQXlCLENBQUE7QUFDdEQsT0FBTyxTQUFTLE1BQU0sd0JBQXdCLENBQUE7QUFDOUMsT0FBTyxVQUFVLE1BQU0sOEJBQThCLENBQUE7QUFFckQsTUFBTSxzQkFBc0IsR0FBRyw2Q0FBNkMsQ0FBQTtBQUU1RSxxQ0FBcUM7QUFDckMsTUFBTSxlQUFlLEdBQUc7SUFDdEIsUUFBUSxFQUFFLENBQUM7SUFDWCxJQUFJLEVBQUUsQ0FBQztJQUNQLFVBQVUsRUFBRSxDQUFDO0lBQ2IsUUFBUSxFQUFFLENBQUM7Q0FDWixDQUFBO0FBRUQ7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sWUFBWTtJQUMvQjs7O09BR0c7SUFDSCxZQUFZLEVBQUMsUUFBUSxFQUFFLFFBQVEsRUFBQztRQUM5QixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQTtRQUN4QixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQTtJQUMxQixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMsVUFBVSxDQUFDLFVBQVU7UUFDekIsS0FBSyxNQUFNLFNBQVMsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNuQyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUE7UUFDakMsQ0FBQztRQUVELE1BQU0sSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFBO0lBQzlCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILEtBQUssQ0FBQyxTQUFTLENBQUMsU0FBUztRQUN2QixNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFBO1FB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VUFBVSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUE7UUFDakMsQ0FBQztRQUVELGtGQUFrRjtRQUNsRixrRkFBa0Y7UUFDbEYsK0VBQStFO1FBQy9FLElBQUksU0FBUyxLQUFLLFNBQVMsSUFBSSxTQUFTLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDOUMsVUFBVSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUE7UUFDbEMsQ0FBQztRQUVELElBQUksS0FBSyxFQUFFLENBQUM7WUFDVixVQUFVLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQTtRQUMxQixDQUFDO1FBRUQsSUFBSSxZQUFZLEtBQUssSUFBSSxJQUFJLFlBQVksS0FBSyxTQUFTLElBQUksc0JBQXNCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDN0csVUFBVSxDQUFDLE9BQU8sR0FBRyxZQUFZLENBQUE7UUFDbkMsQ0FBQztRQUVELE9BQU8sVUFBVSxDQUFBO0lBQ25CLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgTWlncmF0aW9uc0xlZGdlciBmcm9tIFwiLi4vbWlncmF0aW9ucy1sZWRnZXIuanNcIlxuaW1wb3J0IFRhYmxlRGF0YSBmcm9tIFwiLi4vdGFibGUtZGF0YS9pbmRleC5qc1wiXG5pbXBvcnQgVGFibGVJbmRleCBmcm9tIFwiLi4vdGFibGUtZGF0YS90YWJsZS1pbmRleC5qc1wiXG5cbmNvbnN0IFNJTVBMRV9ERUZBVUxUX1BBVFRFUk4gPSAvXig/Oi0/XFxkKyg/OlxcLlxcZCspP3xbQS1aYS16MC05IF8uLDovQCstXSopJC9cblxuLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBudW1iZXI+fSAqL1xuY29uc3QgVEVYVF9UWVBFX1JBTktTID0ge1xuICB0aW55dGV4dDogMSxcbiAgdGV4dDogMixcbiAgbWVkaXVtdGV4dDogMyxcbiAgbG9uZ3RleHQ6IDRcbn1cblxuLyoqXG4gKiBDbG9uZXMgdGFibGUgc3RydWN0dXJlIChjb2x1bW5zLCB0ZXh0LXR5cGUgd2lkZW5pbmcsIGluZGV4ZXMpIGZyb20gYSBzb3VyY2UgZGF0YWJhc2VcbiAqIGludG8gYSB0YXJnZXQgZGF0YWJhc2UgZm9yIGEgZ2l2ZW4gc2V0IG9mIHRhYmxlcywgdGhlbiBiYXNlbGluZXMgdGhlIHRhcmdldCdzXG4gKiBgc2NoZW1hX21pZ3JhdGlvbnNgIGxlZGdlciB0byB0aGUgc291cmNlIHZpYSB7QGxpbmsgTWlncmF0aW9uc0xlZGdlcn0uIFRoaXMgaXMgdGhlXG4gKiBtZWNoYW5pc20gbXVsdGktdGVuYW50IGFwcHMgdXNlIHRvIHByb3Zpc2lvbiBhIHRlbmFudCBkYXRhYmFzZSBmcm9tIGEgdGVtcGxhdGUvZ2xvYmFsXG4gKiBkYXRhYmFzZSB3aXRob3V0IHJlLXJ1bm5pbmcgbWlncmF0aW9uczogdGhlIHN0cnVjdHVyZSBpcyBjb3BpZWQgYW5kIHRoZSBsZWRnZXIgaXNcbiAqIHJlY29yZGVkIGFzIGFscmVhZHktYXBwbGllZCwgc28gYSBsYXRlciBgZGI6dGVuYW50czptaWdyYXRlYCBkb2VzIG5vdCByZS1ydW4gYW5cbiAqIGBhZGRDb2x1bW5gIHdob3NlIGNvbHVtbiBhbHJlYWR5IGV4aXN0cy5cbiAqXG4gKiBUaGUgY2xvbmVyIGlzIGludGVudGlvbmFsbHkgcG9saWN5LWZyZWUg4oCUIHRoZSBjYWxsZXIgZGVjaWRlcyB3aGljaCB0YWJsZXMgdG8gc3luYyBhbmRcbiAqIHdoaWNoIGRhdGFiYXNlcyBhcmUgc291cmNlL3RhcmdldC4gSXQgaXMgaWRlbXBvdGVudDogbWlzc2luZyB0YWJsZXMgYXJlIGNyZWF0ZWQsXG4gKiBtaXNzaW5nIGNvbHVtbnMgYWRkZWQsIHRvby1uYXJyb3cgdGV4dCBjb2x1bW5zIHdpZGVuZWQsIGFuZCBtaXNzaW5nIGluZGV4ZXMgY3JlYXRlZDtcbiAqIGFuIGluZGV4IHdob3NlIGRlZmluaXRpb24gZGl2ZXJnZXMgZnJvbSB0aGUgc291cmNlIGlzIHRyZWF0ZWQgYXMgZHJpZnQgYW5kIHRocm93cy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2NoZW1hQ2xvbmVyIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBjbG9uZXIgdGhhdCBjb3BpZXMgdGFibGUgc3RydWN0dXJlIGZyb20gYHNvdXJjZURiYCBpbnRvIGB0YXJnZXREYmAuXG4gICAqIEBwYXJhbSB7e3NvdXJjZURiOiBpbXBvcnQoXCIuLi9kcml2ZXJzL2Jhc2UuanNcIikuZGVmYXVsdCwgdGFyZ2V0RGI6IGltcG9ydChcIi4uL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0fX0gYXJnc1xuICAgKi9cbiAgY29uc3RydWN0b3Ioe3NvdXJjZURiLCB0YXJnZXREYn0pIHtcbiAgICB0aGlzLnNvdXJjZURiID0gc291cmNlRGJcbiAgICB0aGlzLnRhcmdldERiID0gdGFyZ2V0RGJcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9uZXMgZXZlcnkgZ2l2ZW4gdGFibGUgZnJvbSB0aGUgc291cmNlIGludG8gdGhlIHRhcmdldCwgdGhlbiBiYXNlbGluZXMgdGhlXG4gICAqIHRhcmdldCdzIGxlZGdlciBzbyB0aGUgY2xvbmVkIHNjaGVtYSBpcyByZWNvcmRlZCBhcyBhbHJlYWR5LW1pZ3JhdGVkLlxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSB0YWJsZU5hbWVzXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgc3luY1RhYmxlcyh0YWJsZU5hbWVzKSB7XG4gICAgZm9yIChjb25zdCB0YWJsZU5hbWUgb2YgdGFibGVOYW1lcykge1xuICAgICAgYXdhaXQgdGhpcy5zeW5jVGFibGUodGFibGVOYW1lKVxuICAgIH1cblxuICAgIGF3YWl0IHRoaXMucmVjb25jaWxlTGVkZ2VyKClcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9uZXMgYSBzaW5nbGUgdGFibGUgZnJvbSB0aGUgc291cmNlIGludG8gdGhlIHRhcmdldCwgY3JlYXRpbmcgaXQgb3IgYWRkaW5nIGFuZFxuICAgKiB3aWRlbmluZyBjb2x1bW5zIGFuZCBpbmRleGVzIGFzIG5lZWRlZC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIHN5bmNUYWJsZSh0YWJsZU5hbWUpIHtcbiAgICBjb25zdCBzb3VyY2VUYWJsZSA9IGF3YWl0IHRoaXMuc291cmNlRGIuZ2V0VGFibGVCeU5hbWUodGFibGVOYW1lKVxuXG4gICAgaWYgKCFzb3VyY2VUYWJsZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBzb3VyY2UgdGFibGUgdG8gZXhpc3Q6ICR7dGFibGVOYW1lfWApXG4gICAgfVxuXG4gICAgaWYgKCFhd2FpdCB0aGlzLnRhcmdldERiLnRhYmxlRXhpc3RzKHRhYmxlTmFtZSkpIHtcbiAgICAgIGF3YWl0IHRoaXMuY3JlYXRlVGFyZ2V0VGFibGUoe3NvdXJjZVRhYmxlLCB0YWJsZU5hbWV9KVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3QgY2hhbmdlZENvbHVtbnMgPSBhd2FpdCB0aGlzLmVuc3VyZVRhcmdldENvbHVtbnMoe3NvdXJjZVRhYmxlLCB0YWJsZU5hbWV9KVxuXG4gICAgaWYgKGNoYW5nZWRDb2x1bW5zKSB7XG4gICAgICB0aGlzLnRhcmdldERiLmNsZWFyU2NoZW1hQ2FjaGUoKVxuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuZW5zdXJlVGFyZ2V0SW5kZXhlcyh7c291cmNlVGFibGUsIHRhYmxlTmFtZX0pXG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyB0aGUgdGFibGUgaW4gdGhlIHRhcmdldCBmcm9tIHRoZSBzb3VyY2UgdGFibGUncyBjb2x1bW5zIGFuZCBpdHNcbiAgICogbm9uLXByaW1hcnkta2V5IGluZGV4ZXMuXG4gICAqIEBwYXJhbSB7e3NvdXJjZVRhYmxlOiBpbXBvcnQoXCIuLi9kcml2ZXJzL2Jhc2UtdGFibGUuanNcIikuZGVmYXVsdCwgdGFibGVOYW1lOiBzdHJpbmd9fSBhcmdzXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgY3JlYXRlVGFyZ2V0VGFibGUoe3NvdXJjZVRhYmxlLCB0YWJsZU5hbWV9KSB7XG4gICAgY29uc3QgdGFibGVEYXRhID0gbmV3IFRhYmxlRGF0YSh0YWJsZU5hbWUpXG5cbiAgICBmb3IgKGNvbnN0IHNvdXJjZUNvbHVtbiBvZiBhd2FpdCBzb3VyY2VUYWJsZS5nZXRDb2x1bW5zKCkpIHtcbiAgICAgIHRhYmxlRGF0YS5hZGRDb2x1bW4oc291cmNlQ29sdW1uLmdldE5hbWUoKSwgdGhpcy5jb2x1bW5BcmdzRnJvbVNvdXJjZUNvbHVtbihzb3VyY2VDb2x1bW4sIHtpc05ld0NvbHVtbjogZmFsc2V9KSlcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHNvdXJjZUluZGV4IG9mIGF3YWl0IHNvdXJjZVRhYmxlLmdldEluZGV4ZXMoKSkge1xuICAgICAgaWYgKCFzb3VyY2VJbmRleC5pc1ByaW1hcnlLZXkoKSkge1xuICAgICAgICB0YWJsZURhdGEuYWRkSW5kZXgodGhpcy50YWJsZURhdGFJbmRleEZyb21Tb3VyY2VJbmRleChzb3VyY2VJbmRleCkpXG4gICAgICB9XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy50YXJnZXREYi5jcmVhdGVUYWJsZSh0YWJsZURhdGEpXG4gICAgdGhpcy50YXJnZXREYi5jbGVhclNjaGVtYUNhY2hlKClcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGNvbHVtbnMgcHJlc2VudCBvbiB0aGUgc291cmNlIGJ1dCBtaXNzaW5nIGZyb20gdGhlIHRhcmdldCwgYW5kIHdpZGVuc1xuICAgKiB0b28tbmFycm93IHRhcmdldCB0ZXh0IGNvbHVtbnMuXG4gICAqIEBwYXJhbSB7e3NvdXJjZVRhYmxlOiBpbXBvcnQoXCIuLi9kcml2ZXJzL2Jhc2UtdGFibGUuanNcIikuZGVmYXVsdCwgdGFibGVOYW1lOiBzdHJpbmd9fSBhcmdzXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fSBXaGV0aGVyIGFueSBjb2x1bW4gd2FzIGFkZGVkIG9yIHdpZGVuZWQuXG4gICAqL1xuICBhc3luYyBlbnN1cmVUYXJnZXRDb2x1bW5zKHtzb3VyY2VUYWJsZSwgdGFibGVOYW1lfSkge1xuICAgIGNvbnN0IHNvdXJjZUNvbHVtbnMgPSBhd2FpdCBzb3VyY2VUYWJsZS5nZXRDb2x1bW5zKClcbiAgICBjb25zdCB0YXJnZXRUYWJsZSA9IGF3YWl0IHRoaXMudGFyZ2V0RGIuZ2V0VGFibGVCeU5hbWVPckZhaWwodGFibGVOYW1lKVxuICAgIGNvbnN0IHRhcmdldENvbHVtbnNCeU5hbWUgPSBuZXcgTWFwKClcbiAgICBjb25zdCBtaXNzaW5nQ29sdW1ucyA9IFtdXG4gICAgY29uc3QgY29sdW1uc05lZWRpbmdXaWRlbmluZyA9IFtdXG5cbiAgICBmb3IgKGNvbnN0IHRhcmdldENvbHVtbiBvZiBhd2FpdCB0YXJnZXRUYWJsZS5nZXRDb2x1bW5zKCkpIHtcbiAgICAgIHRhcmdldENvbHVtbnNCeU5hbWUuc2V0KHRhcmdldENvbHVtbi5nZXROYW1lKCksIHRhcmdldENvbHVtbilcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHNvdXJjZUNvbHVtbiBvZiBzb3VyY2VDb2x1bW5zKSB7XG4gICAgICBjb25zdCB0YXJnZXRDb2x1bW4gPSB0YXJnZXRDb2x1bW5zQnlOYW1lLmdldChzb3VyY2VDb2x1bW4uZ2V0TmFtZSgpKVxuXG4gICAgICBpZiAoIXRhcmdldENvbHVtbikge1xuICAgICAgICBtaXNzaW5nQ29sdW1ucy5wdXNoKHNvdXJjZUNvbHVtbilcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5jb2x1bW5OZWVkc1dpZGVuaW5nKHNvdXJjZUNvbHVtbiwgdGFyZ2V0Q29sdW1uKSkge1xuICAgICAgICBjb2x1bW5zTmVlZGluZ1dpZGVuaW5nLnB1c2goc291cmNlQ29sdW1uKVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChtaXNzaW5nQ29sdW1ucy5sZW5ndGggPD0gMCAmJiBjb2x1bW5zTmVlZGluZ1dpZGVuaW5nLmxlbmd0aCA8PSAwKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG5cbiAgICBjb25zdCB0YWJsZURhdGEgPSBuZXcgVGFibGVEYXRhKHRhYmxlTmFtZSlcblxuICAgIGZvciAoY29uc3Qgc291cmNlQ29sdW1uIG9mIG1pc3NpbmdDb2x1bW5zKSB7XG4gICAgICB0YWJsZURhdGEuYWRkQ29sdW1uKHNvdXJjZUNvbHVtbi5nZXROYW1lKCksIHRoaXMuY29sdW1uQXJnc0Zyb21Tb3VyY2VDb2x1bW4oc291cmNlQ29sdW1uLCB7aXNOZXdDb2x1bW46IHRydWV9KSlcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHNvdXJjZUNvbHVtbiBvZiBjb2x1bW5zTmVlZGluZ1dpZGVuaW5nKSB7XG4gICAgICB0YWJsZURhdGEuYWRkQ29sdW1uKHNvdXJjZUNvbHVtbi5nZXROYW1lKCksIHRoaXMuY29sdW1uQXJnc0Zyb21Tb3VyY2VDb2x1bW4oc291cmNlQ29sdW1uLCB7aXNOZXdDb2x1bW46IGZhbHNlfSkpXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBhbHRlclNxbCBvZiBhd2FpdCB0aGlzLnRhcmdldERiLmFsdGVyVGFibGVTUUxzKHRhYmxlRGF0YSkpIHtcbiAgICAgIGF3YWl0IHRoaXMudGFyZ2V0RGIucXVlcnkoYWx0ZXJTcWwpXG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIG5vbi1wcmltYXJ5LWtleSBpbmRleGVzIHByZXNlbnQgb24gdGhlIHNvdXJjZSBidXQgbWlzc2luZyBmcm9tIHRoZSB0YXJnZXQsXG4gICAqIGFuZCB0aHJvd3MgaWYgYW4gZXhpc3RpbmcgdGFyZ2V0IGluZGV4IGRpdmVyZ2VzIGZyb20gdGhlIHNvdXJjZS5cbiAgICogQHBhcmFtIHt7c291cmNlVGFibGU6IGltcG9ydChcIi4uL2RyaXZlcnMvYmFzZS10YWJsZS5qc1wiKS5kZWZhdWx0LCB0YWJsZU5hbWU6IHN0cmluZ319IGFyZ3NcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBlbnN1cmVUYXJnZXRJbmRleGVzKHtzb3VyY2VUYWJsZSwgdGFibGVOYW1lfSkge1xuICAgIGNvbnN0IHRhcmdldFRhYmxlID0gYXdhaXQgdGhpcy50YXJnZXREYi5nZXRUYWJsZUJ5TmFtZU9yRmFpbCh0YWJsZU5hbWUpXG4gICAgLyoqIEB0eXBlIHtNYXA8c3RyaW5nLCBpbXBvcnQoXCIuLi9kcml2ZXJzL2Jhc2UtY29sdW1ucy1pbmRleC5qc1wiKS5kZWZhdWx0Pn0gKi9cbiAgICBjb25zdCB0YXJnZXRJbmRleGVzQnlOYW1lID0gbmV3IE1hcCgpXG4gICAgY29uc3QgdGFyZ2V0SW5kZXhTaWduYXR1cmVzID0gbmV3IFNldCgpXG4gICAgbGV0IGNyZWF0ZWRJbmRleCA9IGZhbHNlXG5cbiAgICBmb3IgKGNvbnN0IHRhcmdldEluZGV4IG9mIGF3YWl0IHRhcmdldFRhYmxlLmdldEluZGV4ZXMoKSkge1xuICAgICAgdGFyZ2V0SW5kZXhlc0J5TmFtZS5zZXQodGFyZ2V0SW5kZXguZ2V0TmFtZSgpLCB0YXJnZXRJbmRleClcbiAgICAgIHRhcmdldEluZGV4U2lnbmF0dXJlcy5hZGQodGhpcy5pbmRleFNpZ25hdHVyZSh0YXJnZXRJbmRleCkpXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBzb3VyY2VJbmRleCBvZiBhd2FpdCBzb3VyY2VUYWJsZS5nZXRJbmRleGVzKCkpIHtcbiAgICAgIGlmIChzb3VyY2VJbmRleC5pc1ByaW1hcnlLZXkoKSkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICBjb25zdCBzb3VyY2VJbmRleFNpZ25hdHVyZSA9IHRoaXMuaW5kZXhTaWduYXR1cmUoc291cmNlSW5kZXgpXG5cbiAgICAgIC8vIFNRTGl0ZSBpbmRleCBuYW1lcyBhcmUgdW5pcXVlIHBlci1kYXRhYmFzZSwgbm90IHBlci10YWJsZSwgc28gbWF0Y2ggY2xvbmVkXG4gICAgICAvLyBpbmRleGVzIGJ5IHRoZWlyIGNvbHVtbi91bmlxdWVuZXNzIHNpZ25hdHVyZSByYXRoZXIgdGhhbiB0aGVpciBuYW1lLlxuICAgICAgaWYgKHRoaXMudGFyZ2V0RGIuZ2V0VHlwZSgpID09PSBcInNxbGl0ZVwiICYmIHRhcmdldEluZGV4U2lnbmF0dXJlcy5oYXMoc291cmNlSW5kZXhTaWduYXR1cmUpKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRhcmdldEluZGV4ID0gdGhpcy50YXJnZXREYi5nZXRUeXBlKCkgPT09IFwic3FsaXRlXCIgPyB1bmRlZmluZWQgOiB0YXJnZXRJbmRleGVzQnlOYW1lLmdldChzb3VyY2VJbmRleC5nZXROYW1lKCkpXG5cbiAgICAgIGlmICghdGFyZ2V0SW5kZXgpIHtcbiAgICAgICAgY29uc3QgY3JlYXRlSW5kZXhTcWxzID0gYXdhaXQgdGhpcy50YXJnZXREYi5jcmVhdGVJbmRleFNRTHModGhpcy5jcmVhdGVJbmRleEFyZ3NGcm9tU291cmNlSW5kZXgoe3NvdXJjZUluZGV4LCB0YWJsZU5hbWV9KSlcblxuICAgICAgICBmb3IgKGNvbnN0IGNyZWF0ZUluZGV4U3FsIG9mIGNyZWF0ZUluZGV4U3Fscykge1xuICAgICAgICAgIGF3YWl0IHRoaXMudGFyZ2V0RGIucXVlcnkoY3JlYXRlSW5kZXhTcWwpXG4gICAgICAgIH1cblxuICAgICAgICBjcmVhdGVkSW5kZXggPSB0cnVlXG4gICAgICAgIHRhcmdldEluZGV4U2lnbmF0dXJlcy5hZGQoc291cmNlSW5kZXhTaWduYXR1cmUpXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIGlmICghdGhpcy5pbmRleGVzTWF0Y2goc291cmNlSW5kZXgsIHRhcmdldEluZGV4KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFNjaGVtYSBjbG9uZSBpbmRleCBkcmlmdCBmb3IgJHt0YWJsZU5hbWV9LiR7c291cmNlSW5kZXguZ2V0TmFtZSgpfWApXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNyZWF0ZWRJbmRleCkge1xuICAgICAgdGhpcy50YXJnZXREYi5jbGVhclNjaGVtYUNhY2hlKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQmFzZWxpbmVzIHRoZSB0YXJnZXQgbGVkZ2VyIHNvIHRoZSBjbG9uZWQgc2NoZW1hIGlzIHJlY29yZGVkIGFzIGFscmVhZHktYXBwbGllZC5cbiAgICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nW10+fSBUaGUgdmVyc2lvbnMgbmV3bHkgcmVjb3JkZWQgb24gdGhlIHRhcmdldC5cbiAgICovXG4gIGFzeW5jIHJlY29uY2lsZUxlZGdlcigpIHtcbiAgICByZXR1cm4gYXdhaXQgTWlncmF0aW9uc0xlZGdlci5iYXNlbGluZUZyb21EYXRhYmFzZSh7c291cmNlRGI6IHRoaXMuc291cmNlRGIsIHRhcmdldERiOiB0aGlzLnRhcmdldERifSlcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSB0YXJnZXQgbGVkZ2VyIGlzIG1pc3NpbmcgYW55IHZlcnNpb24gYXBwbGllZCBvbiB0aGUgc291cmNlIOKAlCBpLmUuIHRoZVxuICAgKiB0YXJnZXQgc2NoZW1hIG1heSBoYXZlIGJlZW4gYWR2YW5jZWQgb3V0IG9mIGJhbmQgd2l0aG91dCByZWNvcmRpbmcgaXQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fVxuICAgKi9cbiAgYXN5bmMgbGVkZ2VyRHJpZnRzRnJvbVNvdXJjZSgpIHtcbiAgICBpZiAoIWF3YWl0IE1pZ3JhdGlvbnNMZWRnZXIudGFibGVFeGlzdHModGhpcy50YXJnZXREYikpIHtcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuXG4gICAgY29uc3Qgc291cmNlVmVyc2lvbnMgPSBhd2FpdCBNaWdyYXRpb25zTGVkZ2VyLmFwcGxpZWRWZXJzaW9ucyh0aGlzLnNvdXJjZURiKVxuICAgIGNvbnN0IHRhcmdldFZlcnNpb25TZXQgPSBuZXcgU2V0KGF3YWl0IE1pZ3JhdGlvbnNMZWRnZXIuYXBwbGllZFZlcnNpb25zKHRoaXMudGFyZ2V0RGIpKVxuXG4gICAgcmV0dXJuIHNvdXJjZVZlcnNpb25zLnNvbWUoKHZlcnNpb24pID0+ICF0YXJnZXRWZXJzaW9uU2V0Lmhhcyh2ZXJzaW9uKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBNYXBzIGEgc291cmNlIGluZGV4IGludG8gYSBUYWJsZURhdGEgaW5kZXggZm9yIHRhYmxlIGNyZWF0aW9uIChTUUxpdGUgb21pdHMgdGhlXG4gICAqIGluZGV4IG5hbWUgc28gdGhlIGRyaXZlciBjYW4gZ2VuZXJhdGUgYSB1bmlxdWUgb25lKS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9kcml2ZXJzL2Jhc2UtY29sdW1ucy1pbmRleC5qc1wiKS5kZWZhdWx0fSBzb3VyY2VJbmRleFxuICAgKiBAcmV0dXJucyB7VGFibGVJbmRleH1cbiAgICovXG4gIHRhYmxlRGF0YUluZGV4RnJvbVNvdXJjZUluZGV4KHNvdXJjZUluZGV4KSB7XG4gICAgLyoqIEB0eXBlIHt7bmFtZT86IHN0cmluZywgdW5pcXVlOiBib29sZWFufX0gKi9cbiAgICBjb25zdCBhcmdzID0ge3VuaXF1ZTogc291cmNlSW5kZXguaXNVbmlxdWUoKX1cblxuICAgIC8vIFNRTGl0ZSBpbmRleCBuYW1lcyBhcmUgdW5pcXVlIHBlci1kYXRhYmFzZSwgbm90IHBlci10YWJsZSwgc28gbGV0IHRoZSBkcml2ZXJcbiAgICAvLyBnZW5lcmF0ZSBvbmU7IG90aGVyIGRyaXZlcnMgcHJlc2VydmUgdGhlIHNvdXJjZSBpbmRleCBuYW1lLiBCdWlsZCB0aGUgVGFibGVJbmRleFxuICAgIC8vIGRpcmVjdGx5IChyYXRoZXIgdGhhbiB2aWEgdGhlIGRyaXZlcidzIGdldFRhYmxlRGF0YUluZGV4LCB3aGljaCBvbmx5IE15U1FMIGFuZFxuICAgIC8vIFNRTGl0ZSBpbXBsZW1lbnQpIHNvIGNsb25pbmcgYSBQb3N0Z3JlU1FMIG9yIE1TLVNRTCBzb3VyY2UgdGFibGUgd29ya3MgdG9vLlxuICAgIGlmICh0aGlzLnRhcmdldERiLmdldFR5cGUoKSAhPT0gXCJzcWxpdGVcIikge1xuICAgICAgYXJncy5uYW1lID0gc291cmNlSW5kZXguZ2V0TmFtZSgpXG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBUYWJsZUluZGV4KHNvdXJjZUluZGV4LmdldENvbHVtbk5hbWVzKCksIGFyZ3MpXG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIGRyaXZlciBjcmVhdGUtaW5kZXggYXJncyBmcm9tIGEgc291cmNlIGluZGV4ICh0aGUgaW5kZXggbmFtZSBpcyBvbWl0dGVkIG9uXG4gICAqIFNRTGl0ZSwgd2hlcmUgaW5kZXggbmFtZXMgYXJlIHVuaXF1ZSBwZXItZGF0YWJhc2UgcmF0aGVyIHRoYW4gcGVyLXRhYmxlKS5cbiAgICogQHBhcmFtIHt7c291cmNlSW5kZXg6IGltcG9ydChcIi4uL2RyaXZlcnMvYmFzZS1jb2x1bW5zLWluZGV4LmpzXCIpLmRlZmF1bHQsIHRhYmxlTmFtZTogc3RyaW5nfX0gYXJnc1xuICAgKiBAcmV0dXJucyB7e2NvbHVtbnM6IHN0cmluZ1tdLCBuYW1lPzogc3RyaW5nLCB0YWJsZU5hbWU6IHN0cmluZywgdW5pcXVlOiBib29sZWFufX1cbiAgICovXG4gIGNyZWF0ZUluZGV4QXJnc0Zyb21Tb3VyY2VJbmRleCh7c291cmNlSW5kZXgsIHRhYmxlTmFtZX0pIHtcbiAgICAvKiogQHR5cGUge3tjb2x1bW5zOiBzdHJpbmdbXSwgbmFtZT86IHN0cmluZywgdGFibGVOYW1lOiBzdHJpbmcsIHVuaXF1ZTogYm9vbGVhbn19ICovXG4gICAgY29uc3QgY3JlYXRlSW5kZXhBcmdzID0ge1xuICAgICAgY29sdW1uczogc291cmNlSW5kZXguZ2V0Q29sdW1uTmFtZXMoKSxcbiAgICAgIHRhYmxlTmFtZSxcbiAgICAgIHVuaXF1ZTogc291cmNlSW5kZXguaXNVbmlxdWUoKVxuICAgIH1cblxuICAgIGlmICh0aGlzLnRhcmdldERiLmdldFR5cGUoKSAhPT0gXCJzcWxpdGVcIikge1xuICAgICAgY3JlYXRlSW5kZXhBcmdzLm5hbWUgPSBzb3VyY2VJbmRleC5nZXROYW1lKClcbiAgICB9XG5cbiAgICByZXR1cm4gY3JlYXRlSW5kZXhBcmdzXG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0d28gaW5kZXhlcyBoYXZlIHRoZSBzYW1lIHVuaXF1ZW5lc3MgYW5kIG9yZGVyZWQgY29sdW1uIGxpc3QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZHJpdmVycy9iYXNlLWNvbHVtbnMtaW5kZXguanNcIikuZGVmYXVsdH0gc291cmNlSW5kZXhcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9kcml2ZXJzL2Jhc2UtY29sdW1ucy1pbmRleC5qc1wiKS5kZWZhdWx0fSB0YXJnZXRJbmRleFxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIGluZGV4ZXNNYXRjaChzb3VyY2VJbmRleCwgdGFyZ2V0SW5kZXgpIHtcbiAgICBjb25zdCBzb3VyY2VDb2x1bW5OYW1lcyA9IHNvdXJjZUluZGV4LmdldENvbHVtbk5hbWVzKClcbiAgICBjb25zdCB0YXJnZXRDb2x1bW5OYW1lcyA9IHRhcmdldEluZGV4LmdldENvbHVtbk5hbWVzKClcblxuICAgIGlmIChzb3VyY2VJbmRleC5pc1VuaXF1ZSgpICE9PSB0YXJnZXRJbmRleC5pc1VuaXF1ZSgpKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG5cbiAgICBpZiAoc291cmNlQ29sdW1uTmFtZXMubGVuZ3RoICE9PSB0YXJnZXRDb2x1bW5OYW1lcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cblxuICAgIGZvciAobGV0IGNvbHVtbkluZGV4ID0gMDsgY29sdW1uSW5kZXggPCBzb3VyY2VDb2x1bW5OYW1lcy5sZW5ndGg7IGNvbHVtbkluZGV4KyspIHtcbiAgICAgIGlmIChzb3VyY2VDb2x1bW5OYW1lc1tjb2x1bW5JbmRleF0gIT09IHRhcmdldENvbHVtbk5hbWVzW2NvbHVtbkluZGV4XSkge1xuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZVxuICB9XG5cbiAgLyoqXG4gICAqIEEgc3RhYmxlIHNpZ25hdHVyZSBmb3IgYW4gaW5kZXgsIHVzZWQgdG8gbWF0Y2ggY2xvbmVkIGluZGV4ZXMgYnkgc2hhcGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZHJpdmVycy9iYXNlLWNvbHVtbnMtaW5kZXguanNcIikuZGVmYXVsdH0gaW5kZXhcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIGluZGV4U2lnbmF0dXJlKGluZGV4KSB7XG4gICAgcmV0dXJuIGAke2luZGV4LmlzVW5pcXVlKCkgPyBcInVuaXF1ZVwiIDogXCJpbmRleFwifToke2luZGV4LmdldENvbHVtbk5hbWVzKCkuam9pbihcIixcIil9YFxuICB9XG5cbiAgLyoqXG4gICAqIE5vcm1hbGl6ZXMgYSBjb2x1bW4gdHlwZSB0byBpdHMgY2Fub25pY2FsIGxvd2VyY2FzZSBmb3JtIChgaW50YCBiZWNvbWVzIGBpbnRlZ2VyYCkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjb2x1bW5UeXBlXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAqL1xuICBub3JtYWxpemVkQ29sdW1uVHlwZShjb2x1bW5UeXBlKSB7XG4gICAgY29uc3Qgbm9ybWFsaXplZFR5cGUgPSBjb2x1bW5UeXBlLnRvTG93ZXJDYXNlKClcblxuICAgIGlmIChub3JtYWxpemVkVHlwZSA9PT0gXCJpbnRcIikge1xuICAgICAgcmV0dXJuIFwiaW50ZWdlclwiXG4gICAgfVxuXG4gICAgcmV0dXJuIG5vcm1hbGl6ZWRUeXBlXG4gIH1cblxuICAvKipcbiAgICogVGhlIHdpZGVuaW5nIHJhbmsgb2YgYSB0ZXh0IGNvbHVtbiB0eXBlICgwIHdoZW4gbm90IGEgdGV4dCB0eXBlKS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGNvbHVtblR5cGVcbiAgICogQHJldHVybnMge251bWJlcn1cbiAgICovXG4gIHRleHRUeXBlUmFuayhjb2x1bW5UeXBlKSB7XG4gICAgcmV0dXJuIFRFWFRfVFlQRV9SQU5LU1t0aGlzLm5vcm1hbGl6ZWRDb2x1bW5UeXBlKGNvbHVtblR5cGUpXSB8fCAwXG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGUgdGFyZ2V0J3MgdGV4dCBjb2x1bW4gaXMgbmFycm93ZXIgdGhhbiB0aGUgc291cmNlJ3MgYW5kIG11c3QgYmUgd2lkZW5lZC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9kcml2ZXJzL2Jhc2UtY29sdW1uLmpzXCIpLmRlZmF1bHR9IHNvdXJjZUNvbHVtblxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2RyaXZlcnMvYmFzZS1jb2x1bW4uanNcIikuZGVmYXVsdH0gdGFyZ2V0Q29sdW1uXG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKi9cbiAgY29sdW1uTmVlZHNXaWRlbmluZyhzb3VyY2VDb2x1bW4sIHRhcmdldENvbHVtbikge1xuICAgIGNvbnN0IHNvdXJjZVJhbmsgPSB0aGlzLnRleHRUeXBlUmFuayhzb3VyY2VDb2x1bW4uZ2V0VHlwZSgpKVxuICAgIGNvbnN0IHRhcmdldFJhbmsgPSB0aGlzLnRleHRUeXBlUmFuayh0YXJnZXRDb2x1bW4uZ2V0VHlwZSgpKVxuXG4gICAgcmV0dXJuIHNvdXJjZVJhbmsgPiAwICYmIHRhcmdldFJhbmsgPiAwICYmIHNvdXJjZVJhbmsgPiB0YXJnZXRSYW5rXG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIFRhYmxlRGF0YSBjb2x1bW4gYXJncyBmcm9tIGEgc291cmNlIGNvbHVtbiwgY29weWluZyB0eXBlLCBudWxsYWJpbGl0eSxcbiAgICogbGVuZ3RoLCBub3Rlcywgc2ltcGxlIGRlZmF1bHRzIGFuZCAoZm9yIGZ1bGwgY2xvbmVzKSBwcmltYXJ5LWtleSBmbGFnLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2RyaXZlcnMvYmFzZS1jb2x1bW4uanNcIikuZGVmYXVsdH0gc291cmNlQ29sdW1uXG4gICAqIEBwYXJhbSB7e2lzTmV3Q29sdW1uOiBib29sZWFufX0gYXJnc1xuICAgKiBAcmV0dXJucyB7UmVjb3JkPHN0cmluZywgdW5rbm93bj59XG4gICAqL1xuICBjb2x1bW5BcmdzRnJvbVNvdXJjZUNvbHVtbihzb3VyY2VDb2x1bW4sIHtpc05ld0NvbHVtbn0pIHtcbiAgICAvKiogQHR5cGUge3thdXRvSW5jcmVtZW50PzogYm9vbGVhbiwgZGVmYXVsdD86IHVua25vd24sIGlzTmV3Q29sdW1uOiBib29sZWFuLCBtYXhMZW5ndGg/OiBudW1iZXIsIG5vdGVzPzogc3RyaW5nLCBudWxsOiBib29sZWFuLCBwcmltYXJ5S2V5PzogYm9vbGVhbiwgdHlwZTogc3RyaW5nfX0gKi9cbiAgICBjb25zdCBjb2x1bW5BcmdzID0ge1xuICAgICAgaXNOZXdDb2x1bW4sXG4gICAgICBudWxsOiBzb3VyY2VDb2x1bW4uZ2V0TnVsbCgpLFxuICAgICAgdHlwZTogdGhpcy5ub3JtYWxpemVkQ29sdW1uVHlwZShzb3VyY2VDb2x1bW4uZ2V0VHlwZSgpKVxuICAgIH1cbiAgICBjb25zdCBkZWZhdWx0VmFsdWUgPSBzb3VyY2VDb2x1bW4uZ2V0RGVmYXVsdCgpXG4gICAgY29uc3QgbWF4TGVuZ3RoID0gc291cmNlQ29sdW1uLmdldE1heExlbmd0aCgpXG4gICAgY29uc3Qgbm90ZXMgPSBzb3VyY2VDb2x1bW4uZ2V0Tm90ZXMoKVxuXG4gICAgaWYgKCFpc05ld0NvbHVtbiAmJiBzb3VyY2VDb2x1bW4uZ2V0UHJpbWFyeUtleSgpKSB7XG4gICAgICBjb2x1bW5BcmdzLnByaW1hcnlLZXkgPSB0cnVlXG4gICAgfVxuXG4gICAgaWYgKHNvdXJjZUNvbHVtbi5nZXRBdXRvSW5jcmVtZW50KCkpIHtcbiAgICAgIGNvbHVtbkFyZ3MuYXV0b0luY3JlbWVudCA9IHRydWVcbiAgICB9XG5cbiAgICAvLyBBIG1heExlbmd0aCBvZiAtMSBpcyB0aGUgTVMtU1FMIFwibWF4XCIgc2VudGluZWwgKE5WQVJDSEFSKE1BWCkgLyBWQVJCSU5BUlkoTUFYKSxcbiAgICAvLyBiYWNraW5nIFZlbG9jaW91cyB0ZXh0L2pzb24vYmxvYiBjb2x1bW5zKTsgdGhlIGNvbHVtbiB0eXBlIGRyaXZlcyB0aGUgdW5ib3VuZGVkXG4gICAgLy8gU1FMLCBzbyBkb24ndCBmb3J3YXJkIC0xIGFzIGFuIGV4cGxpY2l0IGxlbmd0aCAoaXQgd291bGQgZW1pdCBOVkFSQ0hBUigtMSkpLlxuICAgIGlmIChtYXhMZW5ndGggIT09IHVuZGVmaW5lZCAmJiBtYXhMZW5ndGggPj0gMCkge1xuICAgICAgY29sdW1uQXJncy5tYXhMZW5ndGggPSBtYXhMZW5ndGhcbiAgICB9XG5cbiAgICBpZiAobm90ZXMpIHtcbiAgICAgIGNvbHVtbkFyZ3Mubm90ZXMgPSBub3Rlc1xuICAgIH1cblxuICAgIGlmIChkZWZhdWx0VmFsdWUgIT09IG51bGwgJiYgZGVmYXVsdFZhbHVlICE9PSB1bmRlZmluZWQgJiYgU0lNUExFX0RFRkFVTFRfUEFUVEVSTi50ZXN0KFN0cmluZyhkZWZhdWx0VmFsdWUpKSkge1xuICAgICAgY29sdW1uQXJncy5kZWZhdWx0ID0gZGVmYXVsdFZhbHVlXG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbHVtbkFyZ3NcbiAgfVxufVxuIl19
@@ -1 +1 @@
1
- {"root":["../index.js","../bin/velocious.js","../src/application.js","../src/configuration-resolver.js","../src/configuration-types.js","../src/configuration.js","../src/controller.js","../src/current-configuration.js","../src/current.js","../src/error-logger.js","../src/frontend-model-controller.js","../src/initializer.js","../src/logger.js","../src/mailer.js","../src/record-payload-values.js","../src/time-zone.js","../src/velocious-error.js","../src/authorization/ability.js","../src/authorization/base-resource.js","../src/background-jobs/client.js","../src/background-jobs/cron-expression.js","../src/background-jobs/forked-runner-child.js","../src/background-jobs/job-record.js","../src/background-jobs/job-registry.js","../src/background-jobs/job-runner.js","../src/background-jobs/job.js","../src/background-jobs/json-socket.js","../src/background-jobs/main.js","../src/background-jobs/normalize-error.js","../src/background-jobs/scheduler.js","../src/background-jobs/socket-request.js","../src/background-jobs/status-reporter.js","../src/background-jobs/store.js","../src/background-jobs/types.js","../src/background-jobs/worker.js","../src/background-jobs/web/authorization.js","../src/background-jobs/web/controller.js","../src/background-jobs/web/index.js","../src/background-jobs/web/path-matcher.js","../src/background-jobs/web/registry.js","../src/beacon/client.js","../src/beacon/in-process-broker.js","../src/beacon/in-process-client.js","../src/beacon/server.js","../src/beacon/types.js","../src/cli/base-command.js","../src/cli/browser-cli.js","../src/cli/index.js","../src/cli/tenant-database-command-helper.js","../src/cli/use-browser-cli.js","../src/cli/commands/background-jobs-main.js","../src/cli/commands/background-jobs-runner.js","../src/cli/commands/background-jobs-worker.js","../src/cli/commands/beacon.js","../src/cli/commands/console.js","../src/cli/commands/init.js","../src/cli/commands/routes.js","../src/cli/commands/run-script.js","../src/cli/commands/runner.js","../src/cli/commands/server.js","../src/cli/commands/test.js","../src/cli/commands/db/base-command.js","../src/cli/commands/db/create.js","../src/cli/commands/db/drop.js","../src/cli/commands/db/migrate.js","../src/cli/commands/db/reset.js","../src/cli/commands/db/rollback.js","../src/cli/commands/db/seed.js","../src/cli/commands/db/schema/dump.js","../src/cli/commands/db/schema/load.js","../src/cli/commands/db/tenants/check.js","../src/cli/commands/db/tenants/create.js","../src/cli/commands/db/tenants/migrate.js","../src/cli/commands/destroy/migration.js","../src/cli/commands/generate/base-models.js","../src/cli/commands/generate/frontend-models.js","../src/cli/commands/generate/migration.js","../src/cli/commands/generate/model.js","../src/cli/commands/lint/relationships.js","../src/database/annotations-async-hooks.js","../src/database/annotations.js","../src/database/datetime-storage.js","../src/database/handler.js","../src/database/initializer-from-require-context.js","../src/database/migrations-ledger.js","../src/database/migrator.js","../src/database/use-database.js","../src/database/drivers/base-column.js","../src/database/drivers/base-columns-index.js","../src/database/drivers/base-foreign-key.js","../src/database/drivers/base-table.js","../src/database/drivers/base.js","../src/database/drivers/mssql/column.js","../src/database/drivers/mssql/columns-index.js","../src/database/drivers/mssql/connect-connection.js","../src/database/drivers/mssql/foreign-key.js","../src/database/drivers/mssql/index.js","../src/database/drivers/mssql/options.js","../src/database/drivers/mssql/query-parser.js","../src/database/drivers/mssql/structure-sql.js","../src/database/drivers/mssql/table.js","../src/database/drivers/mssql/sql/alter-table.js","../src/database/drivers/mssql/sql/create-database.js","../src/database/drivers/mssql/sql/create-index.js","../src/database/drivers/mssql/sql/create-table.js","../src/database/drivers/mssql/sql/delete.js","../src/database/drivers/mssql/sql/drop-database.js","../src/database/drivers/mssql/sql/drop-table.js","../src/database/drivers/mssql/sql/insert.js","../src/database/drivers/mssql/sql/remove-index.js","../src/database/drivers/mssql/sql/update.js","../src/database/drivers/mssql/sql/upsert.js","../src/database/drivers/mysql/column.js","../src/database/drivers/mysql/columns-index.js","../src/database/drivers/mysql/foreign-key.js","../src/database/drivers/mysql/index.js","../src/database/drivers/mysql/options.js","../src/database/drivers/mysql/query-parser.js","../src/database/drivers/mysql/query.js","../src/database/drivers/mysql/structure-sql.js","../src/database/drivers/mysql/table.js","../src/database/drivers/mysql/sql/alter-table.js","../src/database/drivers/mysql/sql/create-database.js","../src/database/drivers/mysql/sql/create-index.js","../src/database/drivers/mysql/sql/create-table.js","../src/database/drivers/mysql/sql/delete.js","../src/database/drivers/mysql/sql/drop-database.js","../src/database/drivers/mysql/sql/drop-table.js","../src/database/drivers/mysql/sql/insert.js","../src/database/drivers/mysql/sql/remove-index.js","../src/database/drivers/mysql/sql/update.js","../src/database/drivers/mysql/sql/upsert.js","../src/database/drivers/pgsql/column.js","../src/database/drivers/pgsql/columns-index.js","../src/database/drivers/pgsql/foreign-key.js","../src/database/drivers/pgsql/index.js","../src/database/drivers/pgsql/options.js","../src/database/drivers/pgsql/query-parser.js","../src/database/drivers/pgsql/structure-sql.js","../src/database/drivers/pgsql/table.js","../src/database/drivers/pgsql/sql/alter-table.js","../src/database/drivers/pgsql/sql/create-database.js","../src/database/drivers/pgsql/sql/create-index.js","../src/database/drivers/pgsql/sql/create-table.js","../src/database/drivers/pgsql/sql/delete.js","../src/database/drivers/pgsql/sql/drop-database.js","../src/database/drivers/pgsql/sql/drop-table.js","../src/database/drivers/pgsql/sql/insert.js","../src/database/drivers/pgsql/sql/remove-index.js","../src/database/drivers/pgsql/sql/update.js","../src/database/drivers/pgsql/sql/upsert.js","../src/database/drivers/sqlite/base.js","../src/database/drivers/sqlite/column.js","../src/database/drivers/sqlite/columns-index.js","../src/database/drivers/sqlite/connection-sql-js.js","../src/database/drivers/sqlite/foreign-key.js","../src/database/drivers/sqlite/index.js","../src/database/drivers/sqlite/index.native.js","../src/database/drivers/sqlite/index.web.js","../src/database/drivers/sqlite/options.js","../src/database/drivers/sqlite/query-parser.js","../src/database/drivers/sqlite/query.js","../src/database/drivers/sqlite/query.native.js","../src/database/drivers/sqlite/query.web.js","../src/database/drivers/sqlite/structure-sql.js","../src/database/drivers/sqlite/table-rebuilder.js","../src/database/drivers/sqlite/table.js","../src/database/drivers/sqlite/web-persistence.js","../src/database/drivers/sqlite/sql/alter-table.js","../src/database/drivers/sqlite/sql/create-index.js","../src/database/drivers/sqlite/sql/create-table.js","../src/database/drivers/sqlite/sql/delete.js","../src/database/drivers/sqlite/sql/drop-table.js","../src/database/drivers/sqlite/sql/insert.js","../src/database/drivers/sqlite/sql/remove-index.js","../src/database/drivers/sqlite/sql/update.js","../src/database/drivers/sqlite/sql/upsert.js","../src/database/drivers/structure-sql/utils.js","../src/database/migration/index.js","../src/database/migrator/files-finder.js","../src/database/migrator/types.js","../src/database/pool/async-tracked-multi-connection.js","../src/database/pool/base-methods-forward.js","../src/database/pool/base.js","../src/database/pool/single-multi-use.js","../src/database/query/alter-table-base.js","../src/database/query/base.js","../src/database/query/create-database-base.js","../src/database/query/create-index-base.js","../src/database/query/create-table-base.js","../src/database/query/delete-base.js","../src/database/query/drop-database-base.js","../src/database/query/drop-table-base.js","../src/database/query/from-base.js","../src/database/query/from-plain.js","../src/database/query/from-table.js","../src/database/query/index.js","../src/database/query/insert-base.js","../src/database/query/join-base.js","../src/database/query/join-object.js","../src/database/query/join-plain.js","../src/database/query/join-tracker.js","../src/database/query/model-class-query.js","../src/database/query/order-base.js","../src/database/query/order-column.js","../src/database/query/order-plain.js","../src/database/query/preloader.js","../src/database/query/query-data.js","../src/database/query/remove-index-base.js","../src/database/query/select-base.js","../src/database/query/select-plain.js","../src/database/query/select-table-and-column.js","../src/database/query/update-base.js","../src/database/query/upsert-base.js","../src/database/query/where-base.js","../src/database/query/where-combinator.js","../src/database/query/where-hash.js","../src/database/query/where-model-class-hash.js","../src/database/query/where-not.js","../src/database/query/where-plain.js","../src/database/query/with-count.js","../src/database/query/preloader/belongs-to.js","../src/database/query/preloader/ensure-model-class-initialized.js","../src/database/query/preloader/has-many.js","../src/database/query/preloader/has-one.js","../src/database/query/preloader/selection.js","../src/database/query-parser/base-query-parser.js","../src/database/query-parser/from-parser.js","../src/database/query-parser/group-parser.js","../src/database/query-parser/joins-parser.js","../src/database/query-parser/limit-parser.js","../src/database/query-parser/options.js","../src/database/query-parser/order-parser.js","../src/database/query-parser/select-parser.js","../src/database/query-parser/where-parser.js","../src/database/record/acts-as-list.js","../src/database/record/index.js","../src/database/record/record-not-found-error.js","../src/database/record/state-machine.js","../src/database/record/user-module.js","../src/database/record/attachments/attachment-record.js","../src/database/record/attachments/download.js","../src/database/record/attachments/handle.js","../src/database/record/attachments/normalize-input.js","../src/database/record/attachments/store.js","../src/database/record/attachments/storage-drivers/filesystem.js","../src/database/record/attachments/storage-drivers/native.js","../src/database/record/attachments/storage-drivers/s3.js","../src/database/record/instance-relationships/base.js","../src/database/record/instance-relationships/belongs-to.js","../src/database/record/instance-relationships/has-many.js","../src/database/record/instance-relationships/has-one.js","../src/database/record/relationships/base.js","../src/database/record/relationships/belongs-to.js","../src/database/record/relationships/has-many.js","../src/database/record/relationships/has-one.js","../src/database/record/validators/base.js","../src/database/record/validators/format.js","../src/database/record/validators/presence.js","../src/database/record/validators/uniqueness.js","../src/database/table-data/index.js","../src/database/table-data/table-column.js","../src/database/table-data/table-foreign-key.js","../src/database/table-data/table-index.js","../src/database/table-data/table-reference.js","../src/environment-handlers/base.js","../src/environment-handlers/browser.js","../src/environment-handlers/node.js","../src/environment-handlers/node/cli/commands/background-jobs-main.js","../src/environment-handlers/node/cli/commands/background-jobs-runner.js","../src/environment-handlers/node/cli/commands/background-jobs-worker.js","../src/environment-handlers/node/cli/commands/beacon.js","../src/environment-handlers/node/cli/commands/cli-command-context.js","../src/environment-handlers/node/cli/commands/console.js","../src/environment-handlers/node/cli/commands/init.js","../src/environment-handlers/node/cli/commands/routes.js","../src/environment-handlers/node/cli/commands/run-script.js","../src/environment-handlers/node/cli/commands/runner.js","../src/environment-handlers/node/cli/commands/server.js","../src/environment-handlers/node/cli/commands/test.js","../src/environment-handlers/node/cli/commands/db/seed.js","../src/environment-handlers/node/cli/commands/db/schema/dump.js","../src/environment-handlers/node/cli/commands/db/schema/load.js","../src/environment-handlers/node/cli/commands/destroy/migration.js","../src/environment-handlers/node/cli/commands/generate/base-models.js","../src/environment-handlers/node/cli/commands/generate/frontend-models.js","../src/environment-handlers/node/cli/commands/generate/generated-file-banner.js","../src/environment-handlers/node/cli/commands/generate/migration.js","../src/environment-handlers/node/cli/commands/generate/model.js","../src/environment-handlers/node/cli/commands/lint/relationships.js","../src/error-reporting/request-details.js","../src/frontend-model-resource/base-resource.js","../src/frontend-model-resource/velocious-attachment-resource.js","../src/frontend-models/base.js","../src/frontend-models/built-in-resources.js","../src/frontend-models/clear-pending-debounced-callback.js","../src/frontend-models/event-hook-models.js","../src/frontend-models/model-registry.js","../src/frontend-models/outgoing-event-buffer.js","../src/frontend-models/preloader.js","../src/frontend-models/query.js","../src/frontend-models/resource-config-validation.js","../src/frontend-models/resource-definition.js","../src/frontend-models/transport-serialization.js","../src/frontend-models/use-created-event.js","../src/frontend-models/use-destroyed-event.js","../src/frontend-models/use-model-class-event.js","../src/frontend-models/use-updated-event.js","../src/frontend-models/websocket-channel.js","../src/frontend-models/websocket-publishers.js","../src/http-client/header.js","../src/http-client/index.js","../src/http-client/request.js","../src/http-client/response.js","../src/http-client/websocket-client.js","../src/http-server/cookie.js","../src/http-server/development-reloader.js","../src/http-server/index.js","../src/http-server/remote-address.js","../src/http-server/server-client.js","../src/http-server/server-lock.js","../src/http-server/websocket-channel-subscribers.js","../src/http-server/websocket-channel.js","../src/http-server/websocket-connection.js","../src/http-server/websocket-event-log-store.js","../src/http-server/websocket-events-host.js","../src/http-server/websocket-events.js","../src/http-server/client/index.js","../src/http-server/client/params-to-object.js","../src/http-server/client/request-parser.js","../src/http-server/client/request-runner.js","../src/http-server/client/request-timing.js","../src/http-server/client/request.js","../src/http-server/client/response.js","../src/http-server/client/websocket-request.js","../src/http-server/client/websocket-session.js","../src/http-server/client/request-buffer/form-data-part.js","../src/http-server/client/request-buffer/header.js","../src/http-server/client/request-buffer/index.js","../src/http-server/client/uploaded-file/memory-uploaded-file.js","../src/http-server/client/uploaded-file/temporary-uploaded-file.js","../src/http-server/client/uploaded-file/uploaded-file.js","../src/http-server/worker-handler/channel-subscriber-dispatch.js","../src/http-server/worker-handler/in-process.js","../src/http-server/worker-handler/index.js","../src/http-server/worker-handler/worker-script.js","../src/http-server/worker-handler/worker-thread.js","../src/jobs/mail-delivery.js","../src/logger/base-logger.js","../src/logger/console-logger.js","../src/logger/file-logger.js","../src/logger/outputs/array-output.js","../src/logger/outputs/console-output.js","../src/logger/outputs/file-output.js","../src/logger/outputs/stdout-output.js","../src/mailer/base.js","../src/mailer/delivery.js","../src/mailer/index.js","../src/mailer/backends/smtp.js","../src/plugins/sqljs-wasm-route-controller.js","../src/plugins/sqljs-wasm-route.js","../src/routes/app-routes.js","../src/routes/base-route.js","../src/routes/basic-route.js","../src/routes/get-route.js","../src/routes/index.js","../src/routes/namespace-route.js","../src/routes/plugin-routes.js","../src/routes/post-route.js","../src/routes/resolver.js","../src/routes/resource-route.js","../src/routes/root-route.js","../src/routes/built-in/debug/controller.js","../src/routes/built-in/errors/controller.js","../src/routes/hooks/frontend-model-command-route-hook.js","../src/sync/conflict-strategy.js","../src/sync/device-identity.js","../src/sync/local-mutation-log.js","../src/sync/offline-grant.js","../src/sync/peer-mutation-bundle.js","../src/sync/server-change-feed.js","../src/sync/sync-envelope-replay-service.js","../src/testing/base-expect.js","../src/testing/browser-frontend-model-event-hook-scenarios.js","../src/testing/browser-test-app.js","../src/testing/expect-to-change.js","../src/testing/expect-utils.js","../src/testing/expect.js","../src/testing/request-client.js","../src/testing/test-files-finder.js","../src/testing/test-filter-parser.js","../src/testing/test-runner.js","../src/testing/test-suite-splitter.js","../src/testing/test.js","../src/types/external-modules.d.ts","../src/utils/backtrace-cleaner-node.js","../src/utils/backtrace-cleaner.js","../src/utils/deburr-column-name.js","../src/utils/event-emitter.js","../src/utils/file-exists.js","../src/utils/format-value.js","../src/utils/is-date.js","../src/utils/model-scope.js","../src/utils/nest-callbacks.js","../src/utils/plain-object.js","../src/utils/ransack.js","../src/utils/rest-args-error.js","../src/utils/singularize-model-name.js","../src/utils/split-sql-statements.js","../src/utils/to-import-specifier.js","../src/utils/with-tracked-stack-async-hooks.js","../src/utils/with-tracked-stack.js"],"version":"6.0.3"}
1
+ {"root":["../index.js","../bin/velocious.js","../src/application.js","../src/configuration-resolver.js","../src/configuration-types.js","../src/configuration.js","../src/controller.js","../src/current-configuration.js","../src/current.js","../src/error-logger.js","../src/frontend-model-controller.js","../src/initializer.js","../src/logger.js","../src/mailer.js","../src/record-payload-values.js","../src/time-zone.js","../src/velocious-error.js","../src/authorization/ability.js","../src/authorization/base-resource.js","../src/background-jobs/client.js","../src/background-jobs/cron-expression.js","../src/background-jobs/forked-runner-child.js","../src/background-jobs/job-record.js","../src/background-jobs/job-registry.js","../src/background-jobs/job-runner.js","../src/background-jobs/job.js","../src/background-jobs/json-socket.js","../src/background-jobs/main.js","../src/background-jobs/normalize-error.js","../src/background-jobs/scheduler.js","../src/background-jobs/socket-request.js","../src/background-jobs/status-reporter.js","../src/background-jobs/store.js","../src/background-jobs/types.js","../src/background-jobs/worker.js","../src/background-jobs/web/authorization.js","../src/background-jobs/web/controller.js","../src/background-jobs/web/index.js","../src/background-jobs/web/path-matcher.js","../src/background-jobs/web/registry.js","../src/beacon/client.js","../src/beacon/in-process-broker.js","../src/beacon/in-process-client.js","../src/beacon/server.js","../src/beacon/types.js","../src/cli/base-command.js","../src/cli/browser-cli.js","../src/cli/index.js","../src/cli/tenant-database-command-helper.js","../src/cli/use-browser-cli.js","../src/cli/commands/background-jobs-main.js","../src/cli/commands/background-jobs-runner.js","../src/cli/commands/background-jobs-worker.js","../src/cli/commands/beacon.js","../src/cli/commands/console.js","../src/cli/commands/init.js","../src/cli/commands/routes.js","../src/cli/commands/run-script.js","../src/cli/commands/runner.js","../src/cli/commands/server.js","../src/cli/commands/test.js","../src/cli/commands/db/base-command.js","../src/cli/commands/db/create.js","../src/cli/commands/db/drop.js","../src/cli/commands/db/migrate.js","../src/cli/commands/db/reset.js","../src/cli/commands/db/rollback.js","../src/cli/commands/db/seed.js","../src/cli/commands/db/schema/dump.js","../src/cli/commands/db/schema/load.js","../src/cli/commands/db/tenants/check.js","../src/cli/commands/db/tenants/create.js","../src/cli/commands/db/tenants/migrate.js","../src/cli/commands/destroy/migration.js","../src/cli/commands/generate/base-models.js","../src/cli/commands/generate/frontend-models.js","../src/cli/commands/generate/migration.js","../src/cli/commands/generate/model.js","../src/cli/commands/lint/relationships.js","../src/database/annotations-async-hooks.js","../src/database/annotations.js","../src/database/datetime-storage.js","../src/database/handler.js","../src/database/initializer-from-require-context.js","../src/database/migrations-ledger.js","../src/database/migrator.js","../src/database/use-database.js","../src/database/drivers/base-column.js","../src/database/drivers/base-columns-index.js","../src/database/drivers/base-foreign-key.js","../src/database/drivers/base-table.js","../src/database/drivers/base.js","../src/database/drivers/mssql/column.js","../src/database/drivers/mssql/columns-index.js","../src/database/drivers/mssql/connect-connection.js","../src/database/drivers/mssql/foreign-key.js","../src/database/drivers/mssql/index.js","../src/database/drivers/mssql/options.js","../src/database/drivers/mssql/query-parser.js","../src/database/drivers/mssql/structure-sql.js","../src/database/drivers/mssql/table.js","../src/database/drivers/mssql/sql/alter-table.js","../src/database/drivers/mssql/sql/create-database.js","../src/database/drivers/mssql/sql/create-index.js","../src/database/drivers/mssql/sql/create-table.js","../src/database/drivers/mssql/sql/delete.js","../src/database/drivers/mssql/sql/drop-database.js","../src/database/drivers/mssql/sql/drop-table.js","../src/database/drivers/mssql/sql/insert.js","../src/database/drivers/mssql/sql/remove-index.js","../src/database/drivers/mssql/sql/update.js","../src/database/drivers/mssql/sql/upsert.js","../src/database/drivers/mysql/column.js","../src/database/drivers/mysql/columns-index.js","../src/database/drivers/mysql/foreign-key.js","../src/database/drivers/mysql/index.js","../src/database/drivers/mysql/options.js","../src/database/drivers/mysql/query-parser.js","../src/database/drivers/mysql/query.js","../src/database/drivers/mysql/structure-sql.js","../src/database/drivers/mysql/table.js","../src/database/drivers/mysql/sql/alter-table.js","../src/database/drivers/mysql/sql/create-database.js","../src/database/drivers/mysql/sql/create-index.js","../src/database/drivers/mysql/sql/create-table.js","../src/database/drivers/mysql/sql/delete.js","../src/database/drivers/mysql/sql/drop-database.js","../src/database/drivers/mysql/sql/drop-table.js","../src/database/drivers/mysql/sql/insert.js","../src/database/drivers/mysql/sql/remove-index.js","../src/database/drivers/mysql/sql/update.js","../src/database/drivers/mysql/sql/upsert.js","../src/database/drivers/pgsql/column.js","../src/database/drivers/pgsql/columns-index.js","../src/database/drivers/pgsql/foreign-key.js","../src/database/drivers/pgsql/index.js","../src/database/drivers/pgsql/options.js","../src/database/drivers/pgsql/query-parser.js","../src/database/drivers/pgsql/structure-sql.js","../src/database/drivers/pgsql/table.js","../src/database/drivers/pgsql/sql/alter-table.js","../src/database/drivers/pgsql/sql/create-database.js","../src/database/drivers/pgsql/sql/create-index.js","../src/database/drivers/pgsql/sql/create-table.js","../src/database/drivers/pgsql/sql/delete.js","../src/database/drivers/pgsql/sql/drop-database.js","../src/database/drivers/pgsql/sql/drop-table.js","../src/database/drivers/pgsql/sql/insert.js","../src/database/drivers/pgsql/sql/remove-index.js","../src/database/drivers/pgsql/sql/update.js","../src/database/drivers/pgsql/sql/upsert.js","../src/database/drivers/sqlite/base.js","../src/database/drivers/sqlite/column.js","../src/database/drivers/sqlite/columns-index.js","../src/database/drivers/sqlite/connection-sql-js.js","../src/database/drivers/sqlite/foreign-key.js","../src/database/drivers/sqlite/index.js","../src/database/drivers/sqlite/index.native.js","../src/database/drivers/sqlite/index.web.js","../src/database/drivers/sqlite/options.js","../src/database/drivers/sqlite/query-parser.js","../src/database/drivers/sqlite/query.js","../src/database/drivers/sqlite/query.native.js","../src/database/drivers/sqlite/query.web.js","../src/database/drivers/sqlite/structure-sql.js","../src/database/drivers/sqlite/table-rebuilder.js","../src/database/drivers/sqlite/table.js","../src/database/drivers/sqlite/web-persistence.js","../src/database/drivers/sqlite/sql/alter-table.js","../src/database/drivers/sqlite/sql/create-index.js","../src/database/drivers/sqlite/sql/create-table.js","../src/database/drivers/sqlite/sql/delete.js","../src/database/drivers/sqlite/sql/drop-table.js","../src/database/drivers/sqlite/sql/insert.js","../src/database/drivers/sqlite/sql/remove-index.js","../src/database/drivers/sqlite/sql/update.js","../src/database/drivers/sqlite/sql/upsert.js","../src/database/drivers/structure-sql/utils.js","../src/database/migration/index.js","../src/database/migrator/files-finder.js","../src/database/migrator/types.js","../src/database/pool/async-tracked-multi-connection.js","../src/database/pool/base-methods-forward.js","../src/database/pool/base.js","../src/database/pool/single-multi-use.js","../src/database/query/alter-table-base.js","../src/database/query/base.js","../src/database/query/create-database-base.js","../src/database/query/create-index-base.js","../src/database/query/create-table-base.js","../src/database/query/delete-base.js","../src/database/query/drop-database-base.js","../src/database/query/drop-table-base.js","../src/database/query/from-base.js","../src/database/query/from-plain.js","../src/database/query/from-table.js","../src/database/query/index.js","../src/database/query/insert-base.js","../src/database/query/join-base.js","../src/database/query/join-object.js","../src/database/query/join-plain.js","../src/database/query/join-tracker.js","../src/database/query/model-class-query.js","../src/database/query/order-base.js","../src/database/query/order-column.js","../src/database/query/order-plain.js","../src/database/query/preloader.js","../src/database/query/query-data.js","../src/database/query/remove-index-base.js","../src/database/query/select-base.js","../src/database/query/select-plain.js","../src/database/query/select-table-and-column.js","../src/database/query/update-base.js","../src/database/query/upsert-base.js","../src/database/query/where-base.js","../src/database/query/where-combinator.js","../src/database/query/where-hash.js","../src/database/query/where-model-class-hash.js","../src/database/query/where-not.js","../src/database/query/where-plain.js","../src/database/query/with-count.js","../src/database/query/preloader/belongs-to.js","../src/database/query/preloader/ensure-model-class-initialized.js","../src/database/query/preloader/has-many.js","../src/database/query/preloader/has-one.js","../src/database/query/preloader/selection.js","../src/database/query-parser/base-query-parser.js","../src/database/query-parser/from-parser.js","../src/database/query-parser/group-parser.js","../src/database/query-parser/joins-parser.js","../src/database/query-parser/limit-parser.js","../src/database/query-parser/options.js","../src/database/query-parser/order-parser.js","../src/database/query-parser/select-parser.js","../src/database/query-parser/where-parser.js","../src/database/record/acts-as-list.js","../src/database/record/index.js","../src/database/record/record-not-found-error.js","../src/database/record/state-machine.js","../src/database/record/user-module.js","../src/database/record/attachments/attachment-record.js","../src/database/record/attachments/download.js","../src/database/record/attachments/handle.js","../src/database/record/attachments/normalize-input.js","../src/database/record/attachments/store.js","../src/database/record/attachments/storage-drivers/filesystem.js","../src/database/record/attachments/storage-drivers/native.js","../src/database/record/attachments/storage-drivers/s3.js","../src/database/record/instance-relationships/base.js","../src/database/record/instance-relationships/belongs-to.js","../src/database/record/instance-relationships/has-many.js","../src/database/record/instance-relationships/has-one.js","../src/database/record/relationships/base.js","../src/database/record/relationships/belongs-to.js","../src/database/record/relationships/has-many.js","../src/database/record/relationships/has-one.js","../src/database/record/validators/base.js","../src/database/record/validators/format.js","../src/database/record/validators/presence.js","../src/database/record/validators/uniqueness.js","../src/database/table-data/index.js","../src/database/table-data/table-column.js","../src/database/table-data/table-foreign-key.js","../src/database/table-data/table-index.js","../src/database/table-data/table-reference.js","../src/database/tenants/schema-cloner.js","../src/environment-handlers/base.js","../src/environment-handlers/browser.js","../src/environment-handlers/node.js","../src/environment-handlers/node/cli/commands/background-jobs-main.js","../src/environment-handlers/node/cli/commands/background-jobs-runner.js","../src/environment-handlers/node/cli/commands/background-jobs-worker.js","../src/environment-handlers/node/cli/commands/beacon.js","../src/environment-handlers/node/cli/commands/cli-command-context.js","../src/environment-handlers/node/cli/commands/console.js","../src/environment-handlers/node/cli/commands/init.js","../src/environment-handlers/node/cli/commands/routes.js","../src/environment-handlers/node/cli/commands/run-script.js","../src/environment-handlers/node/cli/commands/runner.js","../src/environment-handlers/node/cli/commands/server.js","../src/environment-handlers/node/cli/commands/test.js","../src/environment-handlers/node/cli/commands/db/seed.js","../src/environment-handlers/node/cli/commands/db/schema/dump.js","../src/environment-handlers/node/cli/commands/db/schema/load.js","../src/environment-handlers/node/cli/commands/destroy/migration.js","../src/environment-handlers/node/cli/commands/generate/base-models.js","../src/environment-handlers/node/cli/commands/generate/frontend-models.js","../src/environment-handlers/node/cli/commands/generate/generated-file-banner.js","../src/environment-handlers/node/cli/commands/generate/migration.js","../src/environment-handlers/node/cli/commands/generate/model.js","../src/environment-handlers/node/cli/commands/lint/relationships.js","../src/error-reporting/request-details.js","../src/frontend-model-resource/base-resource.js","../src/frontend-model-resource/velocious-attachment-resource.js","../src/frontend-models/base.js","../src/frontend-models/built-in-resources.js","../src/frontend-models/clear-pending-debounced-callback.js","../src/frontend-models/event-hook-models.js","../src/frontend-models/model-registry.js","../src/frontend-models/outgoing-event-buffer.js","../src/frontend-models/preloader.js","../src/frontend-models/query.js","../src/frontend-models/resource-config-validation.js","../src/frontend-models/resource-definition.js","../src/frontend-models/transport-serialization.js","../src/frontend-models/use-created-event.js","../src/frontend-models/use-destroyed-event.js","../src/frontend-models/use-model-class-event.js","../src/frontend-models/use-updated-event.js","../src/frontend-models/websocket-channel.js","../src/frontend-models/websocket-publishers.js","../src/http-client/header.js","../src/http-client/index.js","../src/http-client/request.js","../src/http-client/response.js","../src/http-client/websocket-client.js","../src/http-server/cookie.js","../src/http-server/development-reloader.js","../src/http-server/index.js","../src/http-server/remote-address.js","../src/http-server/server-client.js","../src/http-server/server-lock.js","../src/http-server/websocket-channel-subscribers.js","../src/http-server/websocket-channel.js","../src/http-server/websocket-connection.js","../src/http-server/websocket-event-log-store.js","../src/http-server/websocket-events-host.js","../src/http-server/websocket-events.js","../src/http-server/client/index.js","../src/http-server/client/params-to-object.js","../src/http-server/client/request-parser.js","../src/http-server/client/request-runner.js","../src/http-server/client/request-timing.js","../src/http-server/client/request.js","../src/http-server/client/response.js","../src/http-server/client/websocket-request.js","../src/http-server/client/websocket-session.js","../src/http-server/client/request-buffer/form-data-part.js","../src/http-server/client/request-buffer/header.js","../src/http-server/client/request-buffer/index.js","../src/http-server/client/uploaded-file/memory-uploaded-file.js","../src/http-server/client/uploaded-file/temporary-uploaded-file.js","../src/http-server/client/uploaded-file/uploaded-file.js","../src/http-server/worker-handler/channel-subscriber-dispatch.js","../src/http-server/worker-handler/in-process.js","../src/http-server/worker-handler/index.js","../src/http-server/worker-handler/worker-script.js","../src/http-server/worker-handler/worker-thread.js","../src/jobs/mail-delivery.js","../src/logger/base-logger.js","../src/logger/console-logger.js","../src/logger/file-logger.js","../src/logger/outputs/array-output.js","../src/logger/outputs/console-output.js","../src/logger/outputs/file-output.js","../src/logger/outputs/stdout-output.js","../src/mailer/base.js","../src/mailer/delivery.js","../src/mailer/index.js","../src/mailer/backends/smtp.js","../src/plugins/sqljs-wasm-route-controller.js","../src/plugins/sqljs-wasm-route.js","../src/routes/app-routes.js","../src/routes/base-route.js","../src/routes/basic-route.js","../src/routes/get-route.js","../src/routes/index.js","../src/routes/namespace-route.js","../src/routes/plugin-routes.js","../src/routes/post-route.js","../src/routes/resolver.js","../src/routes/resource-route.js","../src/routes/root-route.js","../src/routes/built-in/debug/controller.js","../src/routes/built-in/errors/controller.js","../src/routes/hooks/frontend-model-command-route-hook.js","../src/sync/conflict-strategy.js","../src/sync/device-identity.js","../src/sync/local-mutation-log.js","../src/sync/offline-grant.js","../src/sync/peer-mutation-bundle.js","../src/sync/server-change-feed.js","../src/sync/sync-envelope-replay-service.js","../src/testing/base-expect.js","../src/testing/browser-frontend-model-event-hook-scenarios.js","../src/testing/browser-test-app.js","../src/testing/expect-to-change.js","../src/testing/expect-utils.js","../src/testing/expect.js","../src/testing/request-client.js","../src/testing/test-files-finder.js","../src/testing/test-filter-parser.js","../src/testing/test-runner.js","../src/testing/test-suite-splitter.js","../src/testing/test.js","../src/types/external-modules.d.ts","../src/utils/backtrace-cleaner-node.js","../src/utils/backtrace-cleaner.js","../src/utils/deburr-column-name.js","../src/utils/event-emitter.js","../src/utils/file-exists.js","../src/utils/format-value.js","../src/utils/is-date.js","../src/utils/model-scope.js","../src/utils/nest-callbacks.js","../src/utils/plain-object.js","../src/utils/ransack.js","../src/utils/rest-args-error.js","../src/utils/singularize-model-name.js","../src/utils/split-sql-statements.js","../src/utils/to-import-specifier.js","../src/utils/with-tracked-stack-async-hooks.js","../src/utils/with-tracked-stack.js"],"version":"6.0.3"}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "velocious": "build/bin/velocious.js"
4
4
  },
5
5
  "name": "velocious",
6
- "version": "1.0.481",
6
+ "version": "1.0.482",
7
7
  "main": "build/index.js",
8
8
  "types": "build/index.d.ts",
9
9
  "files": [