@webda/core 4.0.0-beta.7 → 4.0.0-beta.9
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/lib/application/application.d.ts +19 -0
- package/lib/application/application.d.ts.map +1 -1
- package/lib/application/application.js +52 -9
- package/lib/application/application.js.map +1 -1
- package/lib/application/model-types.d.ts +63 -0
- package/lib/application/model-types.d.ts.map +1 -0
- package/lib/application/model-types.js +59 -0
- package/lib/application/model-types.js.map +1 -0
- package/lib/application/unpackedapplication.d.ts.map +1 -1
- package/lib/application/unpackedapplication.js +5 -4
- package/lib/application/unpackedapplication.js.map +1 -1
- package/lib/bin/cli.d.ts +18 -0
- package/lib/bin/cli.d.ts.map +1 -1
- package/lib/bin/cli.js +38 -3
- package/lib/bin/cli.js.map +1 -1
- package/lib/core/operations.d.ts +17 -0
- package/lib/core/operations.d.ts.map +1 -1
- package/lib/core/operations.js +1 -1
- package/lib/core/operations.js.map +1 -1
- package/lib/index.d.ts +5 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -1
- package/lib/index.js.map +1 -1
- package/lib/models/decorator.d.ts +21 -0
- package/lib/models/decorator.d.ts.map +1 -1
- package/lib/models/decorator.js +18 -0
- package/lib/models/decorator.js.map +1 -1
- package/lib/rest/restoperationstransport.service.d.ts +6 -0
- package/lib/rest/restoperationstransport.service.d.ts.map +1 -1
- package/lib/rest/restoperationstransport.service.js +31 -2
- package/lib/rest/restoperationstransport.service.js.map +1 -1
- package/lib/rest/router.service.d.ts.map +1 -1
- package/lib/rest/router.service.js +5 -2
- package/lib/rest/router.service.js.map +1 -1
- package/lib/services/binary.service.d.ts +1 -1
- package/lib/services/binary.service.d.ts.map +1 -1
- package/lib/services/binary.service.js.map +1 -1
- package/lib/services/httpserver.service.d.ts.map +1 -1
- package/lib/services/httpserver.service.js +5 -0
- package/lib/services/httpserver.service.js.map +1 -1
- package/lib/services/service.d.ts.map +1 -1
- package/lib/services/service.js +4 -1
- package/lib/services/service.js.map +1 -1
- package/lib/services/servicecommands.d.ts.map +1 -1
- package/lib/services/servicecommands.js +14 -1
- package/lib/services/servicecommands.js.map +1 -1
- package/lib/stores/capability.d.ts +16 -0
- package/lib/stores/capability.d.ts.map +1 -0
- package/lib/stores/capability.js +5 -0
- package/lib/stores/capability.js.map +1 -0
- package/lib/stores/memory.service.d.ts +30 -1
- package/lib/stores/memory.service.d.ts.map +1 -1
- package/lib/stores/memory.service.js +47 -1
- package/lib/stores/memory.service.js.map +1 -1
- package/lib/stores/migration.d.ts +306 -0
- package/lib/stores/migration.d.ts.map +1 -0
- package/lib/stores/migration.js +280 -0
- package/lib/stores/migration.js.map +1 -0
- package/lib/stores/store.d.ts +151 -17
- package/lib/stores/store.d.ts.map +1 -1
- package/lib/stores/store.js +421 -21
- package/lib/stores/store.js.map +1 -1
- package/lib/test/index.d.ts +2 -0
- package/lib/test/index.d.ts.map +1 -1
- package/lib/test/index.js +3 -0
- package/lib/test/index.js.map +1 -1
- package/lib/test/legacy-types.d.ts +146 -0
- package/lib/test/legacy-types.d.ts.map +1 -0
- package/lib/test/legacy-types.fixture.model.d.ts +38 -0
- package/lib/test/legacy-types.fixture.model.d.ts.map +1 -0
- package/lib/test/legacy-types.fixture.model.js +38 -0
- package/lib/test/legacy-types.fixture.model.js.map +1 -0
- package/lib/test/legacy-types.js +481 -0
- package/lib/test/legacy-types.js.map +1 -0
- package/package.json +11 -11
- package/webda.module.json +48 -22
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { type ModelClass, type ModelTypeResolver } from "@webda/models";
|
|
2
|
+
import * as WebdaError from "../errors/errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* A row as the backend stores it, read without type filter nor hydration
|
|
5
|
+
*/
|
|
6
|
+
export interface RawRow {
|
|
7
|
+
/**
|
|
8
|
+
* Table (collection) holding the row: the store name for single-storage stores (Memory, File)
|
|
9
|
+
*/
|
|
10
|
+
table: string;
|
|
11
|
+
/**
|
|
12
|
+
* Storage key of the row
|
|
13
|
+
*/
|
|
14
|
+
key: string;
|
|
15
|
+
/**
|
|
16
|
+
* Stored data, `__type` as stored. Rows written by Webda 4 Memory and File stores are serializer envelopes
|
|
17
|
+
* `{ $serializer, value, __type }`; Webda 3 rows are plain objects.
|
|
18
|
+
*/
|
|
19
|
+
data: Record<string, any>;
|
|
20
|
+
/**
|
|
21
|
+
* Set when the stored value is not a JSON object: `data` is then empty and the row cannot be patched
|
|
22
|
+
*/
|
|
23
|
+
unreadable?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Top-level fields to set on a raw row
|
|
27
|
+
*/
|
|
28
|
+
export type RawPatch = Record<string, any>;
|
|
29
|
+
/**
|
|
30
|
+
* A page of raw rows
|
|
31
|
+
*/
|
|
32
|
+
export interface RawPage {
|
|
33
|
+
/**
|
|
34
|
+
* Rows of the page
|
|
35
|
+
*/
|
|
36
|
+
rows: RawRow[];
|
|
37
|
+
/**
|
|
38
|
+
* Token of the next page, undefined on the last one
|
|
39
|
+
*/
|
|
40
|
+
continuationToken?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A table managed by a store
|
|
44
|
+
*/
|
|
45
|
+
export interface RawTable {
|
|
46
|
+
/**
|
|
47
|
+
* Table name, as used in reports
|
|
48
|
+
*/
|
|
49
|
+
name: string;
|
|
50
|
+
/**
|
|
51
|
+
* Model owning the untyped rows of the table (the first model of the store or of the table)
|
|
52
|
+
*/
|
|
53
|
+
root?: ModelClass;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The store has no raw access yet: it cannot run migrations
|
|
57
|
+
*/
|
|
58
|
+
export declare class MigrationUnsupported extends WebdaError.CodeError {
|
|
59
|
+
/**
|
|
60
|
+
* @param store - the store name
|
|
61
|
+
*/
|
|
62
|
+
constructor(store: string);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Parse a value of a key/value storage as a raw row
|
|
66
|
+
* @param table - table name
|
|
67
|
+
* @param key - storage key
|
|
68
|
+
* @param value - stored JSON string (or object, for old persistence files)
|
|
69
|
+
* @returns the row, flagged unreadable when the value is not a JSON object
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseRawValue(table: string, key: string, value: unknown): RawRow;
|
|
72
|
+
/**
|
|
73
|
+
* Read a page of a key/value storage, in key order
|
|
74
|
+
*
|
|
75
|
+
* The token is the last key of the page, so rows added or removed meanwhile do not shift the next page.
|
|
76
|
+
* @param map - the storage
|
|
77
|
+
* @param table - table name of the rows
|
|
78
|
+
* @param batchSize - rows per page
|
|
79
|
+
* @param token - token of the previous page
|
|
80
|
+
* @returns the page
|
|
81
|
+
*/
|
|
82
|
+
export declare function mapRawPage(map: Map<string, any>, table: string, batchSize: number, token?: string): RawPage;
|
|
83
|
+
/**
|
|
84
|
+
* Set top-level fields of a row of a key/value storage
|
|
85
|
+
* @param map - the storage
|
|
86
|
+
* @param key - storage key
|
|
87
|
+
* @param patch - fields to set
|
|
88
|
+
*/
|
|
89
|
+
export declare function mapRawPatch(map: Map<string, any>, key: string, patch: RawPatch): void;
|
|
90
|
+
/**
|
|
91
|
+
* Counters a patcher fills for the report
|
|
92
|
+
*/
|
|
93
|
+
export interface MigrationContext {
|
|
94
|
+
/**
|
|
95
|
+
* Count a rewritten value under `"<from> → <to>"`
|
|
96
|
+
* @param from - the stored value
|
|
97
|
+
* @param to - the new value
|
|
98
|
+
*/
|
|
99
|
+
change(from: string, to: string): void;
|
|
100
|
+
/**
|
|
101
|
+
* Count a row left untouched because its value is unknown or ambiguous
|
|
102
|
+
* @param type - the stored value
|
|
103
|
+
*/
|
|
104
|
+
unknown(type: string): void;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Compute the patch of a raw row: undefined when the row is already migrated
|
|
108
|
+
*/
|
|
109
|
+
export type MigrationPatcher = (row: RawRow, context: MigrationContext) => Promise<RawPatch | undefined> | RawPatch | undefined;
|
|
110
|
+
/**
|
|
111
|
+
* Options of a migration run
|
|
112
|
+
*/
|
|
113
|
+
export interface MigrationOptions {
|
|
114
|
+
/**
|
|
115
|
+
* Rows per page
|
|
116
|
+
*
|
|
117
|
+
* @default 500
|
|
118
|
+
*/
|
|
119
|
+
batchSize?: number;
|
|
120
|
+
/**
|
|
121
|
+
* Run the patchers and count, write nothing: no row, no progress, no lease
|
|
122
|
+
*/
|
|
123
|
+
dryRun?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Lease duration in ms, renewed every page
|
|
126
|
+
*
|
|
127
|
+
* @default 300000
|
|
128
|
+
*/
|
|
129
|
+
leaseDuration?: number;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Report of one table
|
|
133
|
+
*/
|
|
134
|
+
export interface MigrationTableReport {
|
|
135
|
+
/** Rows read */
|
|
136
|
+
scanned: number;
|
|
137
|
+
/** Rows patched (to patch, in a dry run) */
|
|
138
|
+
updated: number;
|
|
139
|
+
/** Count by `"<from> → <to>"` */
|
|
140
|
+
byChange: Record<string, number>;
|
|
141
|
+
/** Untouched rows by stored value */
|
|
142
|
+
unknown: Record<string, number>;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Report of a migration run
|
|
146
|
+
*/
|
|
147
|
+
export interface MigrationReport {
|
|
148
|
+
/** Store name */
|
|
149
|
+
store: string;
|
|
150
|
+
/** Migration name */
|
|
151
|
+
name: string;
|
|
152
|
+
/** Report by table */
|
|
153
|
+
tables: Record<string, MigrationTableReport>;
|
|
154
|
+
/** The run continued an interrupted one */
|
|
155
|
+
resumed: boolean;
|
|
156
|
+
/** Nothing was written */
|
|
157
|
+
dryRun: boolean;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Progress of a migration, stored in the Registry entry `storeMigration.<store>.<name>`
|
|
161
|
+
*/
|
|
162
|
+
export interface MigrationProgress {
|
|
163
|
+
/** Token of the next page of `table` */
|
|
164
|
+
continuationToken?: string;
|
|
165
|
+
/** Table of the last saved page */
|
|
166
|
+
table?: string;
|
|
167
|
+
/** Rows read */
|
|
168
|
+
scanned: number;
|
|
169
|
+
/** Rows patched */
|
|
170
|
+
updated: number;
|
|
171
|
+
/** Rows left untouched (unknown or ambiguous) */
|
|
172
|
+
unknown: number;
|
|
173
|
+
/** The last run finished */
|
|
174
|
+
done: boolean;
|
|
175
|
+
/** Start of the run, epoch ms */
|
|
176
|
+
startedAt: number;
|
|
177
|
+
/** Last save, epoch ms */
|
|
178
|
+
updatedAt: number;
|
|
179
|
+
/** End of the lease, epoch ms; 0 when free */
|
|
180
|
+
leaseUntil: number;
|
|
181
|
+
/** Runner holding the lease */
|
|
182
|
+
owner?: string;
|
|
183
|
+
/** Report so far by table, so a resumed run ends with the same totals */
|
|
184
|
+
tables: Record<string, MigrationTableReport>;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* A lease held by a runner
|
|
188
|
+
*/
|
|
189
|
+
export interface MigrationLease {
|
|
190
|
+
/** Registry entry */
|
|
191
|
+
id: string;
|
|
192
|
+
/** Runner id */
|
|
193
|
+
owner: string;
|
|
194
|
+
/** End of the lease, epoch ms, as stored */
|
|
195
|
+
leaseUntil: number;
|
|
196
|
+
/** Lease duration, ms */
|
|
197
|
+
leaseDuration: number;
|
|
198
|
+
/** Progress as stored */
|
|
199
|
+
progress: MigrationProgress;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Default rows per page
|
|
203
|
+
*/
|
|
204
|
+
export declare const DEFAULT_MIGRATION_BATCH = 500;
|
|
205
|
+
/**
|
|
206
|
+
* Default lease duration: 5 minutes
|
|
207
|
+
*/
|
|
208
|
+
export declare const DEFAULT_MIGRATION_LEASE: number;
|
|
209
|
+
/**
|
|
210
|
+
* Another runner holds the lease of the migration
|
|
211
|
+
*/
|
|
212
|
+
export declare class MigrationAlreadyRunning extends WebdaError.CodeError {
|
|
213
|
+
/**
|
|
214
|
+
* @param id - registry entry
|
|
215
|
+
* @param owner - runner holding the lease
|
|
216
|
+
* @param until - end of its lease, epoch ms
|
|
217
|
+
*/
|
|
218
|
+
constructor(id: string, owner: string | undefined, until: number);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Increment a counter
|
|
222
|
+
* @param counts - the counters
|
|
223
|
+
* @param key - the counter
|
|
224
|
+
* @param n - the increment
|
|
225
|
+
*/
|
|
226
|
+
export declare function incrementCount(counts: Record<string, number>, key: string, n?: number): void;
|
|
227
|
+
/**
|
|
228
|
+
* @returns an empty table report
|
|
229
|
+
*/
|
|
230
|
+
export declare function emptyTableReport(): MigrationTableReport;
|
|
231
|
+
/**
|
|
232
|
+
* @returns the progress of a fresh run (the keys set to undefined clear a previous run when saved)
|
|
233
|
+
*/
|
|
234
|
+
export declare function emptyProgress(): MigrationProgress;
|
|
235
|
+
/**
|
|
236
|
+
* Read a Registry entry as a progress
|
|
237
|
+
* @param entry - the entry
|
|
238
|
+
* @returns the progress
|
|
239
|
+
*/
|
|
240
|
+
export declare function toMigrationProgress(entry: any): MigrationProgress;
|
|
241
|
+
/**
|
|
242
|
+
* Totals of a report, for the progress entry
|
|
243
|
+
* @param report - the report
|
|
244
|
+
* @returns the totals and the tables
|
|
245
|
+
*/
|
|
246
|
+
export declare function migrationTotals(report: MigrationReport): {
|
|
247
|
+
scanned: number;
|
|
248
|
+
updated: number;
|
|
249
|
+
unknown: number;
|
|
250
|
+
tables: Record<string, MigrationTableReport>;
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* Human-readable report, one line per table and per change
|
|
254
|
+
* @param report - the report
|
|
255
|
+
* @param resolver - resolver telling unknown from ambiguous types
|
|
256
|
+
* @returns the text
|
|
257
|
+
*/
|
|
258
|
+
export declare function formatMigrationReport(report: MigrationReport, resolver?: ModelTypeResolver): string;
|
|
259
|
+
/**
|
|
260
|
+
* Read the rows of raw tables page by page, in table order, stopping after `maxRows` rows
|
|
261
|
+
* @param pages - reads a page of a table (a store's `rawPages`)
|
|
262
|
+
* @param tables - the tables to read
|
|
263
|
+
* @param maxRows - the row limit
|
|
264
|
+
* @param onRow - called for each row
|
|
265
|
+
* @returns true when rows were left unread because of the limit
|
|
266
|
+
*/
|
|
267
|
+
export declare function scanRawRows(pages: (table: string, batchSize: number, token?: string) => Promise<RawPage>, tables: RawTable[], maxRows: number, onRow: (row: RawRow) => void): Promise<boolean>;
|
|
268
|
+
/**
|
|
269
|
+
* Default rows scanned by the startup type check of stores without a native count
|
|
270
|
+
*/
|
|
271
|
+
export declare const DEFAULT_TYPE_CHECK_ROWS = 10000;
|
|
272
|
+
/**
|
|
273
|
+
* Count of rows by stored type, by table
|
|
274
|
+
*/
|
|
275
|
+
export interface StoredTypeCounts {
|
|
276
|
+
/** Count by stored `__type` (`UNTYPED`, `UNREADABLE` included), by table */
|
|
277
|
+
tables: Record<string, Record<string, number>>;
|
|
278
|
+
/** The scan stopped at its row limit: counts are "at least" */
|
|
279
|
+
truncated: boolean;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Outcome of the startup type check
|
|
283
|
+
*/
|
|
284
|
+
export interface TypeCheckSummary {
|
|
285
|
+
/** Rows with a legacy type */
|
|
286
|
+
legacy: number;
|
|
287
|
+
/** Untyped rows that would be stamped */
|
|
288
|
+
untyped: number;
|
|
289
|
+
/** Rows with an unknown, ambiguous or unreadable type */
|
|
290
|
+
unknown: number;
|
|
291
|
+
/** Counts are "at least" */
|
|
292
|
+
truncated: boolean;
|
|
293
|
+
/** WARN message, undefined when every row is current */
|
|
294
|
+
message?: string;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Summarize stored type counts into the startup WARN
|
|
298
|
+
* @param store - store name
|
|
299
|
+
* @param counts - the counts
|
|
300
|
+
* @param roots - root model of each table
|
|
301
|
+
* @param maxRows - the scan limit, for the message
|
|
302
|
+
* @param resolver - the resolver
|
|
303
|
+
* @returns the summary
|
|
304
|
+
*/
|
|
305
|
+
export declare function summarizeStoredTypes(store: string, counts: StoredTypeCounts, roots: Map<string, ModelClass | undefined>, maxRows: number, resolver?: ModelTypeResolver): TypeCheckSummary;
|
|
306
|
+
//# sourceMappingURL=migration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../../src/stores/migration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { getTypeResolver } from "@webda/models";
|
|
2
|
+
import * as WebdaError from "../errors/errors.js";
|
|
3
|
+
import { classifyStoredType, UNTYPED } from "../application/model-types.js";
|
|
4
|
+
/**
|
|
5
|
+
* The store has no raw access yet: it cannot run migrations
|
|
6
|
+
*/
|
|
7
|
+
export class MigrationUnsupported extends WebdaError.CodeError {
|
|
8
|
+
/**
|
|
9
|
+
* @param store - the store name
|
|
10
|
+
*/
|
|
11
|
+
constructor(store) {
|
|
12
|
+
super("MIGRATION_UNSUPPORTED", `Store ${store} has no raw access: it cannot run migrations`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Parse a value of a key/value storage as a raw row
|
|
17
|
+
* @param table - table name
|
|
18
|
+
* @param key - storage key
|
|
19
|
+
* @param value - stored JSON string (or object, for old persistence files)
|
|
20
|
+
* @returns the row, flagged unreadable when the value is not a JSON object
|
|
21
|
+
*/
|
|
22
|
+
export function parseRawValue(table, key, value) {
|
|
23
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
24
|
+
return { table, key, data: { ...value } };
|
|
25
|
+
}
|
|
26
|
+
if (typeof value === "string") {
|
|
27
|
+
try {
|
|
28
|
+
const data = JSON.parse(value);
|
|
29
|
+
if (data !== null && typeof data === "object" && !Array.isArray(data)) {
|
|
30
|
+
return { table, key, data };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Not JSON: reported as unreadable below
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { table, key, data: {}, unreadable: true };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Read a page of a key/value storage, in key order
|
|
41
|
+
*
|
|
42
|
+
* The token is the last key of the page, so rows added or removed meanwhile do not shift the next page.
|
|
43
|
+
* @param map - the storage
|
|
44
|
+
* @param table - table name of the rows
|
|
45
|
+
* @param batchSize - rows per page
|
|
46
|
+
* @param token - token of the previous page
|
|
47
|
+
* @returns the page
|
|
48
|
+
*/
|
|
49
|
+
export function mapRawPage(map, table, batchSize, token) {
|
|
50
|
+
const keys = [...map.keys()].sort();
|
|
51
|
+
let start = 0;
|
|
52
|
+
if (token !== undefined) {
|
|
53
|
+
start = keys.findIndex(key => key > token);
|
|
54
|
+
if (start < 0)
|
|
55
|
+
start = keys.length;
|
|
56
|
+
}
|
|
57
|
+
const slice = keys.slice(start, start + batchSize);
|
|
58
|
+
const rows = [];
|
|
59
|
+
for (const key of slice) {
|
|
60
|
+
const value = map.get(key);
|
|
61
|
+
if (value !== undefined)
|
|
62
|
+
rows.push(parseRawValue(table, key, value));
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
rows,
|
|
66
|
+
continuationToken: start + batchSize < keys.length ? slice[slice.length - 1] : undefined
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Set top-level fields of a row of a key/value storage
|
|
71
|
+
* @param map - the storage
|
|
72
|
+
* @param key - storage key
|
|
73
|
+
* @param patch - fields to set
|
|
74
|
+
*/
|
|
75
|
+
export function mapRawPatch(map, key, patch) {
|
|
76
|
+
const value = map.get(key);
|
|
77
|
+
if (value === undefined) {
|
|
78
|
+
throw new Error(`Raw row not found: ${key}`);
|
|
79
|
+
}
|
|
80
|
+
const row = parseRawValue("", key, value);
|
|
81
|
+
if (row.unreadable) {
|
|
82
|
+
throw new Error(`Raw row ${key} is not a JSON object: it cannot be patched`);
|
|
83
|
+
}
|
|
84
|
+
map.set(key, JSON.stringify({ ...row.data, ...patch }));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Default rows per page
|
|
88
|
+
*/
|
|
89
|
+
export const DEFAULT_MIGRATION_BATCH = 500;
|
|
90
|
+
/**
|
|
91
|
+
* Default lease duration: 5 minutes
|
|
92
|
+
*/
|
|
93
|
+
export const DEFAULT_MIGRATION_LEASE = 5 * 60 * 1000;
|
|
94
|
+
/**
|
|
95
|
+
* Another runner holds the lease of the migration
|
|
96
|
+
*/
|
|
97
|
+
export class MigrationAlreadyRunning extends WebdaError.CodeError {
|
|
98
|
+
/**
|
|
99
|
+
* @param id - registry entry
|
|
100
|
+
* @param owner - runner holding the lease
|
|
101
|
+
* @param until - end of its lease, epoch ms
|
|
102
|
+
*/
|
|
103
|
+
constructor(id, owner, until) {
|
|
104
|
+
super("MIGRATION_ALREADY_RUNNING", `Migration ${id} is already running (runner ${owner ?? "unknown"}, lease until ${new Date(until).toISOString()})`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Increment a counter
|
|
109
|
+
* @param counts - the counters
|
|
110
|
+
* @param key - the counter
|
|
111
|
+
* @param n - the increment
|
|
112
|
+
*/
|
|
113
|
+
export function incrementCount(counts, key, n = 1) {
|
|
114
|
+
counts[key] = (counts[key] ?? 0) + n;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* @returns an empty table report
|
|
118
|
+
*/
|
|
119
|
+
export function emptyTableReport() {
|
|
120
|
+
return { scanned: 0, updated: 0, byChange: {}, unknown: {} };
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* @returns the progress of a fresh run (the keys set to undefined clear a previous run when saved)
|
|
124
|
+
*/
|
|
125
|
+
export function emptyProgress() {
|
|
126
|
+
const now = Date.now();
|
|
127
|
+
return {
|
|
128
|
+
table: undefined,
|
|
129
|
+
continuationToken: undefined,
|
|
130
|
+
scanned: 0,
|
|
131
|
+
updated: 0,
|
|
132
|
+
unknown: 0,
|
|
133
|
+
done: false,
|
|
134
|
+
startedAt: now,
|
|
135
|
+
updatedAt: now,
|
|
136
|
+
leaseUntil: 0,
|
|
137
|
+
owner: undefined,
|
|
138
|
+
tables: {}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Read a Registry entry as a progress
|
|
143
|
+
* @param entry - the entry
|
|
144
|
+
* @returns the progress
|
|
145
|
+
*/
|
|
146
|
+
export function toMigrationProgress(entry) {
|
|
147
|
+
return {
|
|
148
|
+
continuationToken: entry?.continuationToken,
|
|
149
|
+
table: entry?.table,
|
|
150
|
+
scanned: entry?.scanned ?? 0,
|
|
151
|
+
updated: entry?.updated ?? 0,
|
|
152
|
+
unknown: entry?.unknown ?? 0,
|
|
153
|
+
done: !!entry?.done,
|
|
154
|
+
startedAt: entry?.startedAt ?? 0,
|
|
155
|
+
updatedAt: entry?.updatedAt ?? 0,
|
|
156
|
+
leaseUntil: Number(entry?.leaseUntil ?? 0),
|
|
157
|
+
owner: entry?.owner,
|
|
158
|
+
tables: entry?.tables ?? {}
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Totals of a report, for the progress entry
|
|
163
|
+
* @param report - the report
|
|
164
|
+
* @returns the totals and the tables
|
|
165
|
+
*/
|
|
166
|
+
export function migrationTotals(report) {
|
|
167
|
+
let scanned = 0;
|
|
168
|
+
let updated = 0;
|
|
169
|
+
let unknown = 0;
|
|
170
|
+
for (const table of Object.values(report.tables)) {
|
|
171
|
+
scanned += table.scanned;
|
|
172
|
+
updated += table.updated;
|
|
173
|
+
unknown += Object.values(table.unknown).reduce((sum, n) => sum + n, 0);
|
|
174
|
+
}
|
|
175
|
+
return { scanned, updated, unknown, tables: report.tables };
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Entries of a record sorted by key, by UTF-16 code unit (the default sort order)
|
|
179
|
+
* @param record - the record
|
|
180
|
+
* @returns the entries
|
|
181
|
+
*/
|
|
182
|
+
function sortedEntries(record) {
|
|
183
|
+
return Object.keys(record)
|
|
184
|
+
.sort()
|
|
185
|
+
.map(key => [key, record[key]]);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Human-readable report, one line per table and per change
|
|
189
|
+
* @param report - the report
|
|
190
|
+
* @param resolver - resolver telling unknown from ambiguous types
|
|
191
|
+
* @returns the text
|
|
192
|
+
*/
|
|
193
|
+
export function formatMigrationReport(report, resolver = getTypeResolver()) {
|
|
194
|
+
const flags = [report.dryRun ? "dry run" : undefined, report.resumed ? "resumed" : undefined].filter(Boolean);
|
|
195
|
+
const lines = [`Store ${report.store}: migration ${report.name}${flags.length ? ` (${flags.join(", ")})` : ""}`];
|
|
196
|
+
for (const [table, tableReport] of Object.entries(report.tables)) {
|
|
197
|
+
lines.push(` ${table}: ${tableReport.scanned} scanned, ${tableReport.updated} ${report.dryRun ? "to update" : "updated"}`);
|
|
198
|
+
for (const [change, n] of sortedEntries(tableReport.byChange)) {
|
|
199
|
+
lines.push(` ${change}: ${n}`);
|
|
200
|
+
}
|
|
201
|
+
for (const [type, n] of sortedEntries(tableReport.unknown)) {
|
|
202
|
+
lines.push(` ${resolver.resolve(type).status === "ambiguous" ? "ambiguous" : "unknown"} ${type}: ${n}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return lines.join("\n");
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Read the rows of raw tables page by page, in table order, stopping after `maxRows` rows
|
|
209
|
+
* @param pages - reads a page of a table (a store's `rawPages`)
|
|
210
|
+
* @param tables - the tables to read
|
|
211
|
+
* @param maxRows - the row limit
|
|
212
|
+
* @param onRow - called for each row
|
|
213
|
+
* @returns true when rows were left unread because of the limit
|
|
214
|
+
*/
|
|
215
|
+
export async function scanRawRows(pages, tables, maxRows, onRow) {
|
|
216
|
+
let seen = 0;
|
|
217
|
+
for (const [index, table] of tables.entries()) {
|
|
218
|
+
let token;
|
|
219
|
+
do {
|
|
220
|
+
if (seen >= maxRows)
|
|
221
|
+
return true;
|
|
222
|
+
const page = await pages(table.name, Math.min(1000, maxRows - seen), token);
|
|
223
|
+
for (const row of page.rows) {
|
|
224
|
+
onRow(row);
|
|
225
|
+
seen++;
|
|
226
|
+
}
|
|
227
|
+
token = page.continuationToken;
|
|
228
|
+
} while (token);
|
|
229
|
+
if (seen >= maxRows && index < tables.length - 1)
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Default rows scanned by the startup type check of stores without a native count
|
|
236
|
+
*/
|
|
237
|
+
export const DEFAULT_TYPE_CHECK_ROWS = 10000;
|
|
238
|
+
/**
|
|
239
|
+
* Summarize stored type counts into the startup WARN
|
|
240
|
+
* @param store - store name
|
|
241
|
+
* @param counts - the counts
|
|
242
|
+
* @param roots - root model of each table
|
|
243
|
+
* @param maxRows - the scan limit, for the message
|
|
244
|
+
* @param resolver - the resolver
|
|
245
|
+
* @returns the summary
|
|
246
|
+
*/
|
|
247
|
+
export function summarizeStoredTypes(store, counts, roots, maxRows, resolver = getTypeResolver()) {
|
|
248
|
+
const summary = { legacy: 0, untyped: 0, unknown: 0, truncated: counts.truncated };
|
|
249
|
+
const parts = [];
|
|
250
|
+
for (const [table, types] of Object.entries(counts.tables)) {
|
|
251
|
+
const entries = [];
|
|
252
|
+
for (const [type, n] of sortedEntries(types)) {
|
|
253
|
+
const kind = classifyStoredType(type === UNTYPED ? undefined : type, roots.get(table), resolver);
|
|
254
|
+
if (kind.kind === "current" || (kind.kind === "untyped" && !kind.to))
|
|
255
|
+
continue;
|
|
256
|
+
if (kind.kind === "legacy") {
|
|
257
|
+
summary.legacy += n;
|
|
258
|
+
entries.push(`'${type}' → ${kind.to}: ${n}`);
|
|
259
|
+
}
|
|
260
|
+
else if (kind.kind === "untyped") {
|
|
261
|
+
summary.untyped += n;
|
|
262
|
+
entries.push(`untyped → ${kind.to}: ${n}`);
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
summary.unknown += n;
|
|
266
|
+
entries.push(`${kind.kind} '${type}': ${n}`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (entries.length)
|
|
270
|
+
parts.push(`${table} (${entries.join(", ")})`);
|
|
271
|
+
}
|
|
272
|
+
if (parts.length) {
|
|
273
|
+
summary.message =
|
|
274
|
+
`Store ${store} holds rows with legacy, untyped or unknown types: ${parts.join("; ")}` +
|
|
275
|
+
`${counts.truncated ? ` — at least: the check stopped after ${maxRows} rows` : ""}. ` +
|
|
276
|
+
"Run `webda migrate` to rewrite them.";
|
|
277
|
+
}
|
|
278
|
+
return summary;
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.js","sourceRoot":"","sources":["../../src/stores/migration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAA2C,MAAM,eAAe,CAAC;AACzF,OAAO,KAAK,UAAU,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AA0D5E;;GAEG;AACH,MAAM,OAAO,oBAAqB,SAAQ,UAAU,CAAC,SAAS;IAC5D;;OAEG;IACH,YAAY,KAAa;QACvB,KAAK,CAAC,uBAAuB,EAAE,SAAS,KAAK,8CAA8C,CAAC,CAAC;IAC/F,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,GAAW,EAAE,KAAc;IACtE,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,GAAI,KAA6B,EAAE,EAAE,CAAC;IACrE,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC/B,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;YAC9B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,yCAAyC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AACpD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAAC,GAAqB,EAAE,KAAa,EAAE,SAAiB,EAAE,KAAc;IAChG,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACpC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;QAC3C,IAAI,KAAK,GAAG,CAAC;YAAE,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;IACrC,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC,CAAC;IACnD,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IACvE,CAAC;IACD,OAAO;QACL,IAAI;QACJ,iBAAiB,EAAE,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;KACzF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,GAAqB,EAAE,GAAW,EAAE,KAAe;IAC7E,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,sBAAsB,GAAG,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,GAAG,GAAG,aAAa,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1C,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,WAAW,GAAG,6CAA6C,CAAC,CAAC;IAC/E,CAAC;IACD,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;AAC1D,CAAC;AA2HD;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAC3C;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAErD;;GAEG;AACH,MAAM,OAAO,uBAAwB,SAAQ,UAAU,CAAC,SAAS;IAC/D;;;;OAIG;IACH,YAAY,EAAU,EAAE,KAAyB,EAAE,KAAa;QAC9D,KAAK,CACH,2BAA2B,EAC3B,aAAa,EAAE,+BAA+B,KAAK,IAAI,SAAS,iBAAiB,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,GAAG,CAClH,CAAC;IACJ,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,MAA8B,EAAE,GAAW,EAAE,CAAC,GAAW,CAAC;IACvF,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,OAAO;QACL,KAAK,EAAE,SAAS;QAChB,iBAAiB,EAAE,SAAS;QAC5B,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;QACV,IAAI,EAAE,KAAK;QACX,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG;QACd,UAAU,EAAE,CAAC;QACb,KAAK,EAAE,SAAS;QAChB,MAAM,EAAE,EAAE;KACX,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAU;IAC5C,OAAO;QACL,iBAAiB,EAAE,KAAK,EAAE,iBAAiB;QAC3C,KAAK,EAAE,KAAK,EAAE,KAAK;QACnB,OAAO,EAAE,KAAK,EAAE,OAAO,IAAI,CAAC;QAC5B,OAAO,EAAE,KAAK,EAAE,OAAO,IAAI,CAAC;QAC5B,OAAO,EAAE,KAAK,EAAE,OAAO,IAAI,CAAC;QAC5B,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI;QACnB,SAAS,EAAE,KAAK,EAAE,SAAS,IAAI,CAAC;QAChC,SAAS,EAAE,KAAK,EAAE,SAAS,IAAI,CAAC;QAChC,UAAU,EAAE,MAAM,CAAC,KAAK,EAAE,UAAU,IAAI,CAAC,CAAC;QAC1C,KAAK,EAAE,KAAK,EAAE,KAAK;QACnB,MAAM,EAAE,KAAK,EAAE,MAAM,IAAI,EAAE;KAC5B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAAuB;IAMrD,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACjD,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC;QACzB,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC;QACzB,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AAC9D,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAI,MAAyB;IACjD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;SACvB,IAAI,EAAE;SACN,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAuB,EACvB,QAAQ,GAAsB,eAAe,EAAE;IAE/C,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9G,MAAM,KAAK,GAAG,CAAC,SAAS,MAAM,CAAC,KAAK,eAAe,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjH,KAAK,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACjE,KAAK,CAAC,IAAI,CACR,KAAK,KAAK,KAAK,WAAW,CAAC,OAAO,aAAa,WAAW,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,EAAE,CAChH,CAAC;QACF,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,aAAa,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9D,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;QACpC,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3D,KAAK,CAAC,IAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAA6E,EAC7E,MAAkB,EAClB,OAAe,EACf,KAA4B;IAE5B,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;QAC9C,IAAI,KAAyB,CAAC;QAC9B,GAAG,CAAC;YACF,IAAI,IAAI,IAAI,OAAO;gBAAE,OAAO,IAAI,CAAC;YACjC,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;YAC5E,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC5B,KAAK,CAAC,GAAG,CAAC,CAAC;gBACX,IAAI,EAAE,CAAC;YACT,CAAC;YACD,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC;QACjC,CAAC,QAAQ,KAAK,EAAE;QAChB,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IAChE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,CAAC;AA4B7C;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAa,EACb,MAAwB,EACxB,KAA0C,EAC1C,OAAe,EACf,QAAQ,GAAsB,eAAe,EAAE;IAE/C,MAAM,OAAO,GAAqB,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;IACrG,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3D,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAC;YACjG,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAAE,SAAS;YAC/E,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC3B,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;gBACpB,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;YAC/C,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACnC,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC;gBACrB,OAAO,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;YAC7C,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC;gBACrB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QACD,IAAI,OAAO,CAAC,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,OAAO,CAAC,OAAO;YACb,SAAS,KAAK,sDAAsD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACtF,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,wCAAwC,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI;gBACrF,sCAAsC,CAAC;IAC3C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|