velocious 1.0.497 → 1.0.499

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.
@@ -46,6 +46,8 @@ export type StateMachineDefinition = {
46
46
  export type StateDefinition = {
47
47
  beforeEnter?: (model: import("./index.js").default) => void | Promise<void>;
48
48
  afterEnter?: (model: import("./index.js").default) => void | Promise<void>;
49
+ beforeExit?: (model: import("./index.js").default) => void | Promise<void>;
50
+ afterExit?: (model: import("./index.js").default) => void | Promise<void>;
49
51
  };
50
52
  /**
51
53
  * Defines this typedef.
@@ -1 +1 @@
1
- {"version":3,"file":"state-machine.d.ts","sourceRoot":"","sources":["../../../../src/database/record/state-machine.js"],"names":[],"mappings":"AA4BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,yCAJW,cAAc,YAAY,EAAE,OAAO,cACnC,sBAAsB,GACpB,IAAI,CAkNhB;;;;qCAxQY;IACR,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACxC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CACxC;;;;8BACS;IACR,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3E;;;;8BACS;IACR,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5E,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACtE"}
1
+ {"version":3,"file":"state-machine.d.ts","sourceRoot":"","sources":["../../../../src/database/record/state-machine.js"],"names":[],"mappings":"AA8BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,yCAJW,cAAc,YAAY,EAAE,OAAO,cACnC,sBAAsB,GACpB,IAAI,CAsOhB;;;;qCA9RY;IACR,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACxC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CACxC;;;;8BACS;IACR,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;;;;8BACS;IACR,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5E,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACtE"}
@@ -9,7 +9,9 @@
9
9
  * }} StateMachineDefinition
10
10
  * @typedef {{
11
11
  * beforeEnter?: (model: import("./index.js").default) => void | Promise<void>,
12
- * afterEnter?: (model: import("./index.js").default) => void | Promise<void>
12
+ * afterEnter?: (model: import("./index.js").default) => void | Promise<void>,
13
+ * beforeExit?: (model: import("./index.js").default) => void | Promise<void>,
14
+ * afterExit?: (model: import("./index.js").default) => void | Promise<void>
13
15
  * }} StateDefinition
14
16
  * @typedef {{
15
17
  * from: string | string[],
@@ -63,6 +65,13 @@ export function stateMachine(ModelClass, definition) {
63
65
  * Dynamic class.
64
66
  * @type {?} */
65
67
  const dynamicClass = ModelClass;
68
+ // Idempotent: re-declaring on the same class (or a re-evaluated module) must not
69
+ // register the before/after-save transition hooks twice. Guard on an own property
70
+ // so a subclass declaring its own machine is unaffected by the parent's flag.
71
+ if (Object.prototype.hasOwnProperty.call(dynamicClass, "_stateMachineRegistered") && dynamicClass._stateMachineRegistered) {
72
+ return;
73
+ }
74
+ dynamicClass._stateMachineRegistered = true;
66
75
  dynamicClass._stateMachineDefinition = definition;
67
76
  dynamicClass._stateMachineColumn = column;
68
77
  /**
@@ -185,7 +194,11 @@ export function stateMachine(ModelClass, definition) {
185
194
  if (eventDef?.before) {
186
195
  await eventDef.before(model);
187
196
  }
188
- // Run state-level beforeEnter callback
197
+ // Run the exited state's beforeExit, then the entered state's beforeEnter
198
+ const fromStateDefinition = definition.states[pending.from];
199
+ if (fromStateDefinition?.beforeExit) {
200
+ await fromStateDefinition.beforeExit(model);
201
+ }
189
202
  const stateDefinition = definition.states[pending.to];
190
203
  if (stateDefinition?.beforeEnter) {
191
204
  await stateDefinition.beforeEnter(model);
@@ -203,11 +216,15 @@ export function stateMachine(ModelClass, definition) {
203
216
  }
204
217
  // Clear the pending transition now that save is complete
205
218
  dynamicModel[PENDING_TRANSITION_KEY] = null;
206
- // Run state-level afterEnter callback
219
+ // Run the entered state's afterEnter, then the exited state's afterExit
207
220
  const stateDefinition = definition.states[pending.to];
208
221
  if (stateDefinition?.afterEnter) {
209
222
  await stateDefinition.afterEnter(model);
210
223
  }
224
+ const fromStateDefinition = definition.states[pending.from];
225
+ if (fromStateDefinition?.afterExit) {
226
+ await fromStateDefinition.afterExit(model);
227
+ }
211
228
  // Run event-level after callback
212
229
  const eventDef = definition.events[pending.eventName];
213
230
  if (eventDef?.after) {
@@ -223,4 +240,4 @@ export function stateMachine(ModelClass, definition) {
223
240
  function columnSetterName(column) {
224
241
  return `set${column.charAt(0).toUpperCase()}${column.slice(1)}`;
225
242
  }
226
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGUtbWFjaGluZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9kYXRhYmFzZS9yZWNvcmQvc3RhdGUtbWFjaGluZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVo7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQkc7QUFFSDs7b0JBRW9CO0FBQ3BCLE1BQU0sc0JBQXNCLEdBQUcsZ0NBQWdDLENBQUE7QUFFL0Q7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0ErQkc7QUFDSCxNQUFNLFVBQVUsWUFBWSxDQUFDLFVBQVUsRUFBRSxVQUFVO0lBQ2pELE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNLElBQUksT0FBTyxDQUFBO0lBQzNDLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBRWpELHdEQUF3RDtJQUN4RDs7bUJBRWU7SUFDZixNQUFNLFlBQVksR0FBRyxVQUFVLENBQUE7SUFFL0IsWUFBWSxDQUFDLHVCQUF1QixHQUFHLFVBQVUsQ0FBQTtJQUNqRCxZQUFZLENBQUMsbUJBQW1CLEdBQUcsTUFBTSxDQUFBO0lBRXpDOzs7T0FHRztJQUNILFlBQVksQ0FBQyx5QkFBeUIsR0FBRztRQUN2QyxPQUFPLFlBQVksQ0FBQyx1QkFBdUIsQ0FBQTtJQUM3QyxDQUFDLENBQUE7SUFFRDs7O09BR0c7SUFDSCxZQUFZLENBQUMscUJBQXFCLEdBQUc7UUFDbkMsT0FBTyxZQUFZLENBQUMsbUJBQW1CLENBQUE7SUFDekMsQ0FBQyxDQUFBO0lBRUQ7OztPQUdHO0lBQ0gsWUFBWSxDQUFDLHlCQUF5QixHQUFHO1FBQ3ZDLE9BQU8sVUFBVSxDQUFBO0lBQ25CLENBQUMsQ0FBQTtJQUVELDREQUE0RDtJQUM1RDs7bUJBRWU7SUFDZixNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsU0FBUyxDQUFBO0lBRWxDLEtBQUssTUFBTSxDQUFDLFNB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QUVlO1FBQ2YsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFBO1FBQzFCLE1BQU0sT0FBTyxHQUFHLFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFBO1FBRXBELElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNiLE9BQU07UUFDUixDQUFDO1FBRUQseURBQXlEO1FBQ3pELFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyxHQUFHLElBQUksQ0FBQTtRQUUzQyxzQ0FBc0M7UUFDdEMsTUFBTSxlQUFlLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUE7UUFFckQsSUFBSSxlQUFlLEVBQUUsVUFBVSxFQUFFLENBQUM7WUFDaEMsTUFBTSxlQUFlLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ3pDLENBQUM7UUFFRCxpQ0FBaUM7UUFDakMsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUE7UUFFckQsSUFBSSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUM7WUFDcEIsTUFBTSxRQUFRLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQzdCLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQTtBQUNKLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxnQkFBZ0IsQ0FBQyxNQUFNO0lBQzlCLE9BQU8sTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtBQUNqRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbi8qKlxuICogRGVmaW5lcyB0aGlzIHR5cGVkZWYuXG4gKiBAdHlwZWRlZiB7e1xuICogICBjb2x1bW4/OiBzdHJpbmcsXG4gKiAgIGluaXRpYWw6IHN0cmluZyxcbiAqICAgc3RhdGVzOiBSZWNvcmQ8c3RyaW5nLCBTdGF0ZURlZmluaXRpb24+LFxuICogICBldmVudHM6IFJlY29yZDxzdHJpbmcsIEV2ZW50RGVmaW5pdGlvbj5cbiAqIH19IFN0YXRlTWFjaGluZURlZmluaXRpb25cbiAqIEB0eXBlZGVmIHt7XG4gKiAgIGJlZm9yZUVudGVyPzogKG1vZGVsOiBpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHQpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+LFxuICogICBhZnRlckVudGVyPzogKG1vZGVsOiBpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHQpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+XG4gKiB9fSBTdGF0ZURlZmluaXRpb25cbiAqIEB0eXBlZGVmIHt7XG4gKiAgIGZyb206IHN0cmluZyB8IHN0cmluZ1tdLFxuICogICB0bzogc3RyaW5nLFxuICogICBndWFyZD86IChtb2RlbDogaW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0KSA9PiBib29sZWFuIHwgUHJvbWlzZTxib29sZWFuPixcbiAqICAgYmVmb3JlPzogKG1vZGVsOiBpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHQpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+LFxuICogICBhZnRlcj86IChtb2RlbDogaW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0KSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPlxuICogfX0gRXZlbnREZWZpbml0aW9uXG4gKi9cblxuLyoqXG4gKiBQZW5kaW5nIHRyYW5zaXRpb24ga2V5LlxuICogQHR5cGUge3N0cmluZ30gKi9cbmNvbnN0IFBFTkRJTkdfVFJBTlNJVElPTl9LRVkgPSBcIl9zdGF0ZU1hY2hpbmVQZW5kaW5nVHJhbnNpdGlvblwiXG5cbi8qKlxuICogUmVnaXN0ZXJzIGEgc3RhdGUgbWFjaGluZSBvbiBhIFZlbG9jaW91cyBtb2RlbCBjbGFzcy5cbiAqXG4gKiBVc2FnZTpcbiAqIGBgYGpzXG4gKiBpbXBvcnQge3N0YXRlTWFjaGluZX0gZnJvbSBcInZlbG9jaW91cy9idWlsZC9zcmMvZGF0YWJhc2UvcmVjb3JkL3N0YXRlLW1hY2hpbmUuanNcIlxuICpcbiAqIGNsYXNzIEJ1aWxkIGV4dGVuZHMgQnVpbGRCYXNlIHt9XG4gKlxuICogc3RhdGVNYWNoaW5lKEJ1aWxkLCB7XG4gKiAgIGNvbHVtbjogXCJzdGF0dXNcIixcbiAqICAgaW5pdGlhbDogXCJuZXdcIixcbiAqICAgc3RhdGVzOiB7XG4gKiAgICAgbmV3OiB7fSxcbiAqICAgICBxdWV1ZWQ6IHtiZWZvcmVFbnRlcjogKGJ1aWxkKSA9PiB7IGJ1aWxkLnNldFF1ZXVlZEF0KG5ldyBEYXRlKCkpIH19LFxuICogICAgIHJ1bm5pbmc6IHtiZWZvcmVFbnRlcjogKGJ1aWxkKSA9PiB7IGJ1aWxkLnNldFN0YXJ0ZWRBdChuZXcgRGF0ZSgpKSB9fSxcbiAqICAgICBmYWlsZWQ6IHtiZWZvcmVFbnRlcjogKGJ1aWxkKSA9PiB7IGJ1aWxkLnNldEVuZGVkQXQobmV3IERhdGUoKSkgfX0sXG4gKiAgICAgc3VjY2VlZGVkOiB7YmVmb3JlRW50ZXI6IChidWlsZCkgPT4geyBidWlsZC5zZXRFbmRlZEF0KG5ldyBEYXRlKCkpIH19XG4gKiAgIH0sXG4gKiAgIGV2ZW50czoge1xuICogICAgIHF1ZXVlOiB7ZnJvbTogXCJuZXdcIiwgdG86IFwicXVldWVkXCJ9LFxuICogICAgIHJ1bjoge2Zyb206IFtcIm5ld1wiLCBcInF1ZXVlZFwiLCBcImNyYXNoZWRcIl0sIHRvOiBcInJ1bm5pbmdcIn0sXG4gKiAgICAgZmFpbDoge2Zyb206IFtcIm5ld1wiLCBcInF1ZXVlZFwiLCBcInJ1bm5pbmdcIl0sIHRvOiBcImZhaWxlZFwifSxcbiAqICAgICBzdWNjZWVkOiB7ZnJvbTogXCJydW5uaW5nXCIsIHRvOiBcInN1Y2NlZWRlZFwifSxcbiAqICAgICBjYW5jZWw6IHtmcm9tOiBbXCJuZXdcIiwgXCJxdWV1ZWRcIiwgXCJydW5uaW5nXCJdLCB0bzogXCJjYW5jZWxsZWRcIiwgZ3VhcmQ6IChidWlsZCkgPT4gIWJ1aWxkLmlzTmV3UmVjb3JkKCl9XG4gKiAgIH1cbiAqIH0pXG4gKiBgYGBcbiAqIEBwYXJhbSB7dHlwZW9mIGltcG9ydChcIi4vaW5kZXguanNcIikuZGVmYXVsdH0gTW9kZWxDbGFzcyAtIFRoZSBtb2RlbCBjbGFzcyB0byBhZGQgc3RhdGUgbWFjaGluZSBiZWhhdmlvciB0by5cbiAqIEBwYXJhbSB7U3RhdGVNYWNoaW5lRGVmaW5pdGlvbn0gZGVmaW5pdGlvbiAtIFRoZSBzdGF0ZSBtYWNoaW5lIGRlZmluaXRpb24uXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0YXRlTWFjaGluZShNb2RlbENsYXNzLCBkZWZpbml0aW9uKSB7XG4gIGNvbnN0IGNvbHVtbiA9IGRlZmluaXRpb24uY29sdW1uIHx8IFwic3RhdGVcIlxuICBjb25zdCBzdGF0ZU5hbWVzID0gT2JqZWN0LmtleXMoZGVmaW5pdGlvbi5zdGF0ZXMpXG5cbiAgLy8gU3RvcmUgZGVmaW5pdGlvbiBvbiB0aGUgbW9kZWwgY2xhc3MgZm9yIGludHJvc3BlY3Rpb25cbiAgLyoqXG4gICAqIER5bmFtaWMgY2xhc3MuXG4gICAqIEB0eXBlIHs/fSAqL1xuICBjb25zdCBkeW5hbWljQ2xhc3MgPSBNb2RlbENsYXNzXG5cbiAgZHluYW1pY0NsYXNzLl9zdGF0ZU1hY2hpbmVEZWZpbml0aW9uID0gZGVmaW5pdGlvblxuICBkeW5hbWljQ2xhc3MuX3N0YXRlTWFjaGluZUNvbHVtbiA9IGNvbHVtblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSByZWdpc3RlcmVkIHN0YXRlIG1hY2hpbmUgZGVmaW5pdGlvbi5cbiAgICogQHJldHVybnMge1N0YXRlTWFjaGluZURlZmluaXRpb259IC0gVGhlIHJlZ2lzdGVyZWQgc3RhdGUgbWFjaGluZSBkZWZpbml0aW9uLlxuICAgKi9cbiAgZHluYW1pY0NsYXNzLmdldFN0YXRlTWFjaGluZURlZmluaXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGR5bmFtaWNDbGFzcy5fc3RhdGVNYWNoaW5lRGVmaW5pdGlvblxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHN0YXRlIGNvbHVtbiBuYW1lLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIFRoZSBjb2x1bW4gbmFtZSB1c2VkIGZvciBzdGF0ZSBzdG9yYWdlLlxuICAgKi9cbiAgZHluYW1pY0NsYXNzLmdldFN0YXRlTWFjaGluZUNvbHVtbiA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZHluYW1pY0NsYXNzLl9zdGF0ZU1hY2hpbmVDb2x1bW5cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFsbCBkZWNsYXJlZCBzdGF0ZSBuYW1lcy5cbiAgICogQHJldHVybnMge3N0cmluZ1tdfSAtIEFsbCBkZWNsYXJlZCBzdGF0ZSBuYW1lcy5cbiAgICovXG4gIGR5bmFtaWNDbGFzcy5nZXRTdGF0ZU1hY2hpbmVTdGF0ZU5hbWVzID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBzdGF0ZU5hbWVzXG4gIH1cblxuICAvLyBSZWdpc3RlciBldmVudCBtZXRob2RzIGFuZCBndWFyZCBtZXRob2RzIG9uIHRoZSBwcm90b3R5cGVcbiAgLyoqXG4gICAqIFByb3RvLlxuICAgKiBAdHlwZSB7P30gKi9cbiAgY29uc3QgcHJvdG8gPSBNb2RlbENsYXNzLnByb3RvdHlwZVxuXG4gIGZvciAoY29uc3QgW2V2ZW50TmFtZSwgZXZlbnREZWZdIG9mIE9iamVjdC5lbnRyaWVzKGRlZmluaXRpb24uZXZlbnRzKSkge1xuICAgIGNvbnN0IGZyb21TdGF0ZXMgPSBBcnJheS5pc0FycmF5KGV2ZW50RGVmLmZyb20pID8gZXZlbnREZWYuZnJvbSA6IFtldmVudERlZi5mcm9tXVxuICAgIGNvbnN0IGNhcGl0YWxpemVkRXZlbnQgPSBldmVudE5hbWUuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBldmVudE5hbWUuc2xpY2UoMSlcbiAgICBjb25zdCBjYW5NZXRob2ROYW1lID0gYGNhbiR7Y2FwaXRhbGl6ZWRFdmVudH1gXG4gICAgY29uc3Qgc2V0dGVyTmFtZSA9IGNvbHVtblNldHRlck5hbWUoY29sdW1uKVxuXG4gICAgLy8gR3VhcmQgbWV0aG9kOiBjYW5RdWV1ZSgpLCBjYW5SdW4oKSwgZXRjLlxuICAgIHByb3RvW2Nhbk1ldGhvZE5hbWVdID0gZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY3VycmVudFN0YXRlID0gdGhpcy5yZWFkQXR0cmlidXRlKGNvbHVtbilcblxuICAgICAgaWYgKCFmcm9tU3RhdGVzLmluY2x1ZGVzKGN1cnJlbnRTdGF0ZSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICB9XG5cbiAgICAgIGlmIChldmVudERlZi5ndWFyZCkge1xuICAgICAgICBjb25zdCBndWFyZFJlc3VsdCA9IGV2ZW50RGVmLmd1YXJkKHRoaXMpXG5cbiAgICAgICAgaWYgKGd1YXJkUmVzdWx0IGluc3RhbmNlb2YgUHJvbWlzZSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgR3VhcmQgZm9yIGV2ZW50IFwiJHtldmVudE5hbWV9XCIgcmV0dXJuZWQgYSBQcm9taXNlLiBVc2UgYXdhaXQgbW9kZWwuY2FuJHtjYXBpdGFsaXplZEV2ZW50fUFzeW5jKCkgaW5zdGVhZC5gKVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGd1YXJkUmVzdWx0XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuXG4gICAgLy8gQXN5bmMgZ3VhcmQgbWV0aG9kOiBjYW5RdWV1ZUFzeW5jKCksIGNhblJ1bkFzeW5jKCksIGV0Yy5cbiAgICBwcm90b1tgJHtjYW5NZXRob2ROYW1lfUFzeW5jYF0gPSBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjdXJyZW50U3RhdGUgPSB0aGlzLnJlYWRBdHRyaWJ1dGUoY29sdW1uKVxuXG4gICAgICBpZiAoIWZyb21TdGF0ZXMuaW5jbHVkZXMoY3VycmVudFN0YXRlKSkge1xuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIH1cblxuICAgICAgaWYgKGV2ZW50RGVmLmd1YXJkKSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBldmVudERlZi5ndWFyZCh0aGlzKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cblxuICAgIC8vIFRyYW5zaXRpb24gbWV0aG9kOiBxdWV1ZSgpLCBydW4oKSwgZXRjLiDigJQgY2hlY2tzIGd1YXJkLCBzZXRzIHRoZSBzdGF0ZSwgc3Rhc2hlcyBldmVudCBuYW1lXG4gICAgcHJvdG9bZXZlbnROYW1lXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIC8qKlxuICAgICAgICogU2VsZi5cbiAgICAgICAqIEB0eXBlIHs/fSAqL1xuICAgICAgY29uc3Qgc2VsZiA9IHRoaXNcbiAgICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IHNlbGYucmVhZEF0dHJpYnV0ZShjb2x1bW4pXG5cbiAgICAgIGlmICghZnJvbVN0YXRlcy5pbmNsdWRlcyhjdXJyZW50U3RhdGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgQ2Fubm90IHRyYW5zaXRpb24gXCIke2V2ZW50TmFtZX1cIiBmcm9tIFwiJHtjdXJyZW50U3RhdGV9XCIgb24gJHtzZWxmLmdldE1vZGVsQ2xhc3MoKS5uYW1lfS4gYCArXG4gICAgICAgICAgYEFsbG93ZWQgc291cmNlIHN0YXRlczogJHtmcm9tU3RhdGVzLmpvaW4oXCIsIFwiKX1gXG4gICAgICAgIClcbiAgICAgIH1cblxuICAgICAgLy8gRW5mb3JjZSBzeW5jaHJvbm91cyBndWFyZCBiZWZvcmUgbXV0YXRpbmcgc3RhdGVcbiAgICAgIGlmIChldmVudERlZi5ndWFyZCkge1xuICAgICAgICBjb25zdCBndWFyZFJlc3VsdCA9IGV2ZW50RGVmLmd1YXJkKHNlbGYpXG5cbiAgICAgICAgaWYgKGd1YXJkUmVzdWx0IGluc3RhbmNlb2YgUHJvbWlzZSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgR3VhcmQgZm9yIGV2ZW50IFwiJHtldmVudE5hbWV9XCIgcmV0dXJuZWQgYSBQcm9taXNlLiBVc2UgYXdhaXQgbW9kZWwuJHtldmVudE5hbWV9QW5kU2F2ZSgpIGZvciBhc3luYyBndWFyZHMuYClcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghZ3VhcmRSZXN1bHQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgR3VhcmQgcmVqZWN0ZWQgdHJhbnNpdGlvbiBcIiR7ZXZlbnROYW1lfVwiIGZyb20gXCIke2N1cnJlbnRTdGF0ZX1cIiBvbiAke3NlbGYuZ2V0TW9kZWxDbGFzcygpLm5hbWV9LmBcbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gU3Rhc2ggdGhlIHRyYW5zaXRpb24gc28gYmVmb3JlU2F2ZS9hZnRlclNhdmUga25vdyB3aGljaCBldmVudCB3YXMgaW52b2tlZFxuICAgICAgc2VsZltQRU5ESU5HX1RSQU5TSVRJT05fS0VZXSA9IHtldmVudE5hbWUsIGZyb206IGN1cnJlbnRTdGF0ZSwgdG86IGV2ZW50RGVmLnRvfVxuICAgICAgc2VsZltzZXR0ZXJOYW1lXShldmVudERlZi50bylcbiAgICB9XG5cbiAgICAvLyBCYW5nIG1ldGhvZDogcXVldWVBbmRTYXZlKCksIHJ1bkFuZFNhdmUoKSwgZXRjLiDigJQgdHJhbnNpdGlvbnMgQU5EIHNhdmVzIChzdXBwb3J0cyBhc3luYyBndWFyZHMpXG4gICAgcHJvdG9bYCR7ZXZlbnROYW1lfUFuZFNhdmVgXSA9IGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8qKlxuICAgICAgICogU2VsZi5cbiAgICAgICAqIEB0eXBlIHs/fSAqL1xuICAgICAgY29uc3Qgc2VsZiA9IHRoaXNcbiAgICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IHNlbGYucmVhZEF0dHJpYnV0ZShjb2x1bW4pXG5cbiAgICAgIGlmICghZnJvbVN0YXRlcy5pbmNsdWRlcyhjdXJyZW50U3RhdGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgQ2Fubm90IHRyYW5zaXRpb24gXCIke2V2ZW50TmFtZX1cIiBmcm9tIFwiJHtjdXJyZW50U3RhdGV9XCIgb24gJHtzZWxmLmdldE1vZGVsQ2xhc3MoKS5uYW1lfS4gYCArXG4gICAgICAgICAgYEFsbG93ZWQgc291cmNlIHN0YXRlczogJHtmcm9tU3RhdGVzLmpvaW4oXCIsIFwiKX1gXG4gICAgICAgIClcbiAgICAgIH1cblxuICAgICAgLy8gRW5mb3JjZSBhc3luYyBndWFyZCBiZWZvcmUgbXV0YXRpbmcgc3RhdGVcbiAgICAgIGlmIChldmVudERlZi5ndWFyZCkge1xuICAgICAgICBjb25zdCBhbGxvd2VkID0gYXdhaXQgZXZlbnREZWYuZ3VhcmQoc2VsZilcblxuICAgICAgICBpZiAoIWFsbG93ZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgR3VhcmQgcmVqZWN0ZWQgdHJhbnNpdGlvbiBcIiR7ZXZlbnROYW1lfVwiIGZyb20gXCIke2N1cnJlbnRTdGF0ZX1cIiBvbiAke3NlbGYuZ2V0TW9kZWxDbGFzcygpLm5hbWV9LmBcbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgc2VsZltQRU5ESU5HX1RSQU5TSVRJT05fS0VZXSA9IHtldmVudE5hbWUsIGZyb206IGN1cnJlbnRTdGF0ZSwgdG86IGV2ZW50RGVmLnRvfVxuICAgICAgc2VsZltzZXR0ZXJOYW1lXShldmVudERlZi50bylcbiAgICAgIGF3YWl0IHNlbGYuc2F2ZSgpXG4gICAgfVxuICB9XG5cbiAgLy8gUmVnaXN0ZXIgYSBiZWZvcmVTYXZlIGNhbGxiYWNrIHRoYXQgZmlyZXMgc3RhdGUtZW50ZXIgaG9va3NcbiAgTW9kZWxDbGFzcy5iZWZvcmVTYXZlKGFzeW5jIGZ1bmN0aW9uIChtb2RlbCkge1xuICAgIC8qKlxuICAgICAqIER5bmFtaWMgbW9kZWwuXG4gICAgICogQHR5cGUgez99ICovXG4gICAgY29uc3QgZHluYW1pY01vZGVsID0gbW9kZWxcbiAgICBjb25zdCBwZW5kaW5nID0gZHluYW1pY01vZGVsW1BFTkRJTkdfVFJBTlNJVElPTl9LRVldXG5cbiAgICBpZiAoIXBlbmRpbmcpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IGV2ZW50RGVmID0gZGVmaW5pdGlvbi5ldmVudHNbcGVuZGluZy5ldmVudE5hbWVdXG5cbiAgICAvLyBSdW4gZXZlbnQtbGV2ZWwgYmVmb3JlIGNhbGxiYWNrXG4gICAgaWYgKGV2ZW50RGVmPy5iZWZvcmUpIHtcbiAgICAgIGF3YWl0IGV2ZW50RGVmLmJlZm9yZShtb2RlbClcbiAgICB9XG5cbiAgICAvLyBSdW4gc3RhdGUtbGV2ZWwgYmVmb3JlRW50ZXIgY2FsbGJhY2tcbiAgICBjb25zdCBzdGF0ZURlZmluaXRpb24gPSBkZWZpbml0aW9uLnN0YXRlc1twZW5kaW5nLnRvXVxuXG4gICAgaWYgKHN0YXRlRGVmaW5pdGlvbj8uYmVmb3JlRW50ZXIpIHtcbiAgICAgIGF3YWl0IHN0YXRlRGVmaW5pdGlvbi5iZWZvcmVFbnRlcihtb2RlbClcbiAgICB9XG4gIH0pXG5cbiAgLy8gUmVnaXN0ZXIgYW4gYWZ0ZXJTYXZlIGNhbGxiYWNrIGZvciBhZnRlckVudGVyIGhvb2tzXG4gIE1vZGVsQ2xhc3MuYWZ0ZXJTYXZlKGFzeW5jIGZ1bmN0aW9uIChtb2RlbCkge1xuICAgIC8qKlxuICAgICAqIER5bmFtaWMgbW9kZWwuXG4gICAgICogQHR5cGUgez99ICovXG4gICAgY29uc3QgZHluYW1pY01vZGVsID0gbW9kZWxcbiAgICBjb25zdCBwZW5kaW5nID0gZHluYW1pY01vZGVsW1BFTkRJTkdfVFJBTlNJVElPTl9LRVldXG5cbiAgICBpZiAoIXBlbmRpbmcpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIC8vIENsZWFyIHRoZSBwZW5kaW5nIHRyYW5zaXRpb24gbm93IHRoYXQgc2F2ZSBpcyBjb21wbGV0ZVxuICAgIGR5bmFtaWNNb2RlbFtQRU5ESU5HX1RSQU5TSVRJT05fS0VZXSA9IG51bGxcblxuICAgIC8vIFJ1biBzdGF0ZS1sZXZlbCBhZnRlckVudGVyIGNhbGxiYWNrXG4gICAgY29uc3Qgc3RhdGVEZWZpbml0aW9uID0gZGVmaW5pdGlvbi5zdGF0ZXNbcGVuZGluZy50b11cblxuICAgIGlmIChzdGF0ZURlZmluaXRpb24/LmFmdGVyRW50ZXIpIHtcbiAgICAgIGF3YWl0IHN0YXRlRGVmaW5pdGlvbi5hZnRlckVudGVyKG1vZGVsKVxuICAgIH1cblxuICAgIC8vIFJ1biBldmVudC1sZXZlbCBhZnRlciBjYWxsYmFja1xuICAgIGNvbnN0IGV2ZW50RGVmID0gZGVmaW5pdGlvbi5ldmVudHNbcGVuZGluZy5ldmVudE5hbWVdXG5cbiAgICBpZiAoZXZlbnREZWY/LmFmdGVyKSB7XG4gICAgICBhd2FpdCBldmVudERlZi5hZnRlcihtb2RlbClcbiAgICB9XG4gIH0pXG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc2V0dGVyIG1ldGhvZCBuYW1lIGZvciBhIGNvbHVtbiAoZS5nLiwgXCJzdGF0dXNcIiDihpIgXCJzZXRTdGF0dXNcIiwgXCJzdGF0ZVwiIOKGkiBcInNldFN0YXRlXCIpLlxuICogQHBhcmFtIHtzdHJpbmd9IGNvbHVtbiAtIFRoZSBjb2x1bW4gbmFtZS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IC0gVGhlIHNldHRlciBtZXRob2QgbmFtZS5cbiAqL1xuZnVuY3Rpb24gY29sdW1uU2V0dGVyTmFtZShjb2x1bW4pIHtcbiAgcmV0dXJuIGBzZXQke2NvbHVtbi5jaGFyQXQoMCkudG9VcHBlckNhc2UoKX0ke2NvbHVtbi5zbGljZSgxKX1gXG59XG4iXX0=
243
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGUtbWFjaGluZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9kYXRhYmFzZS9yZWNvcmQvc3RhdGUtbWFjaGluZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVo7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFCRztBQUVIOztvQkFFb0I7QUFDcEIsTUFBTSxzQkFBc0IsR0FBRyxnQ0FBZ0MsQ0FBQTtBQUUvRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQStCRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQUMsVUFBVSxFQUFFLFVBQVU7SUFDakQsTUFBTSxNQUFNLEdBQUcsVUFBVSxDQUFDLE1BQU0sSUFBSSxPQUFPLENBQUE7SUFDM0MsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUE7SUFFakQsd0RBQXdEO0lBQ3hEOzttQkFFZTtJQUNmLE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQTtJQUUvQixpRkFBaUY7SUFDakYsa0ZBQWtGO0lBQ2xGLDhFQUE4RTtJQUM5RSxJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUseUJBQXlCLENBQUMsSUFBSSxZQUFZLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztRQUMxSCxPQUFNO0lBQ1IsQ0FBQztJQUVELFlBQVksQ0FBQyx1QkFBdUIsR0FBRyxJQUFJLENBQUE7SUFDM0MsWUFBWSxDQUFDLHVCQUF1QixHQUFHLFVBQVUsQ0FBQTtJQUNqRCxZQUFZLENBQUMsbUJBQW1CLEdBQUcsTUFBTSxDQUFBO0lBRXpDOzs7T0FHRztJQUNILFlBQVksQ0FBQyx5QkFBeUIsR0FBRztRQUN2QyxPQUFPLFlBQVksQ0FBQyx1QkFBdUIsQ0FBQTtJQUM3QyxDQUFDLENBQUE7SUFFRDs7O09BR0c7SUFDSCxZQUFZLENBQUMscUJBQXFCLEdBQUc7UUFDbkMsT0FB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QWlDO1FBQ2pDLE1BQU0sUUFBUSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFBO1FBRXJELElBQUksUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDO1lBQ3BCLE1BQU0sUUFBUSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUM3QixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsZ0JBQWdCLENBQUMsTUFBTTtJQUM5QixPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUE7QUFDakUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG4vKipcbiAqIERlZmluZXMgdGhpcyB0eXBlZGVmLlxuICogQHR5cGVkZWYge3tcbiAqICAgY29sdW1uPzogc3RyaW5nLFxuICogICBpbml0aWFsOiBzdHJpbmcsXG4gKiAgIHN0YXRlczogUmVjb3JkPHN0cmluZywgU3RhdGVEZWZpbml0aW9uPixcbiAqICAgZXZlbnRzOiBSZWNvcmQ8c3RyaW5nLCBFdmVudERlZmluaXRpb24+XG4gKiB9fSBTdGF0ZU1hY2hpbmVEZWZpbml0aW9uXG4gKiBAdHlwZWRlZiB7e1xuICogICBiZWZvcmVFbnRlcj86IChtb2RlbDogaW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0KSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPixcbiAqICAgYWZ0ZXJFbnRlcj86IChtb2RlbDogaW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0KSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPixcbiAqICAgYmVmb3JlRXhpdD86IChtb2RlbDogaW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0KSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPixcbiAqICAgYWZ0ZXJFeGl0PzogKG1vZGVsOiBpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHQpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+XG4gKiB9fSBTdGF0ZURlZmluaXRpb25cbiAqIEB0eXBlZGVmIHt7XG4gKiAgIGZyb206IHN0cmluZyB8IHN0cmluZ1tdLFxuICogICB0bzogc3RyaW5nLFxuICogICBndWFyZD86IChtb2RlbDogaW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0KSA9PiBib29sZWFuIHwgUHJvbWlzZTxib29sZWFuPixcbiAqICAgYmVmb3JlPzogKG1vZGVsOiBpbXBvcnQoXCIuL2luZGV4LmpzXCIpLmRlZmF1bHQpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+LFxuICogICBhZnRlcj86IChtb2RlbDogaW1wb3J0KFwiLi9pbmRleC5qc1wiKS5kZWZhdWx0KSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPlxuICogfX0gRXZlbnREZWZpbml0aW9uXG4gKi9cblxuLyoqXG4gKiBQZW5kaW5nIHRyYW5zaXRpb24ga2V5LlxuICogQHR5cGUge3N0cmluZ30gKi9cbmNvbnN0IFBFTkRJTkdfVFJBTlNJVElPTl9LRVkgPSBcIl9zdGF0ZU1hY2hpbmVQZW5kaW5nVHJhbnNpdGlvblwiXG5cbi8qKlxuICogUmVnaXN0ZXJzIGEgc3RhdGUgbWFjaGluZSBvbiBhIFZlbG9jaW91cyBtb2RlbCBjbGFzcy5cbiAqXG4gKiBVc2FnZTpcbiAqIGBgYGpzXG4gKiBpbXBvcnQge3N0YXRlTWFjaGluZX0gZnJvbSBcInZlbG9jaW91cy9idWlsZC9zcmMvZGF0YWJhc2UvcmVjb3JkL3N0YXRlLW1hY2hpbmUuanNcIlxuICpcbiAqIGNsYXNzIEJ1aWxkIGV4dGVuZHMgQnVpbGRCYXNlIHt9XG4gKlxuICogc3RhdGVNYWNoaW5lKEJ1aWxkLCB7XG4gKiAgIGNvbHVtbjogXCJzdGF0dXNcIixcbiAqICAgaW5pdGlhbDogXCJuZXdcIixcbiAqICAgc3RhdGVzOiB7XG4gKiAgICAgbmV3OiB7fSxcbiAqICAgICBxdWV1ZWQ6IHtiZWZvcmVFbnRlcjogKGJ1aWxkKSA9PiB7IGJ1aWxkLnNldFF1ZXVlZEF0KG5ldyBEYXRlKCkpIH19LFxuICogICAgIHJ1bm5pbmc6IHtiZWZvcmVFbnRlcjogKGJ1aWxkKSA9PiB7IGJ1aWxkLnNldFN0YXJ0ZWRBdChuZXcgRGF0ZSgpKSB9fSxcbiAqICAgICBmYWlsZWQ6IHtiZWZvcmVFbnRlcjogKGJ1aWxkKSA9PiB7IGJ1aWxkLnNldEVuZGVkQXQobmV3IERhdGUoKSkgfX0sXG4gKiAgICAgc3VjY2VlZGVkOiB7YmVmb3JlRW50ZXI6IChidWlsZCkgPT4geyBidWlsZC5zZXRFbmRlZEF0KG5ldyBEYXRlKCkpIH19XG4gKiAgIH0sXG4gKiAgIGV2ZW50czoge1xuICogICAgIHF1ZXVlOiB7ZnJvbTogXCJuZXdcIiwgdG86IFwicXVldWVkXCJ9LFxuICogICAgIHJ1bjoge2Zyb206IFtcIm5ld1wiLCBcInF1ZXVlZFwiLCBcImNyYXNoZWRcIl0sIHRvOiBcInJ1bm5pbmdcIn0sXG4gKiAgICAgZmFpbDoge2Zyb206IFtcIm5ld1wiLCBcInF1ZXVlZFwiLCBcInJ1bm5pbmdcIl0sIHRvOiBcImZhaWxlZFwifSxcbiAqICAgICBzdWNjZWVkOiB7ZnJvbTogXCJydW5uaW5nXCIsIHRvOiBcInN1Y2NlZWRlZFwifSxcbiAqICAgICBjYW5jZWw6IHtmcm9tOiBbXCJuZXdcIiwgXCJxdWV1ZWRcIiwgXCJydW5uaW5nXCJdLCB0bzogXCJjYW5jZWxsZWRcIiwgZ3VhcmQ6IChidWlsZCkgPT4gIWJ1aWxkLmlzTmV3UmVjb3JkKCl9XG4gKiAgIH1cbiAqIH0pXG4gKiBgYGBcbiAqIEBwYXJhbSB7dHlwZW9mIGltcG9ydChcIi4vaW5kZXguanNcIikuZGVmYXVsdH0gTW9kZWxDbGFzcyAtIFRoZSBtb2RlbCBjbGFzcyB0byBhZGQgc3RhdGUgbWFjaGluZSBiZWhhdmlvciB0by5cbiAqIEBwYXJhbSB7U3RhdGVNYWNoaW5lRGVmaW5pdGlvbn0gZGVmaW5pdGlvbiAtIFRoZSBzdGF0ZSBtYWNoaW5lIGRlZmluaXRpb24uXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0YXRlTWFjaGluZShNb2RlbENsYXNzLCBkZWZpbml0aW9uKSB7XG4gIGNvbnN0IGNvbHVtbiA9IGRlZmluaXRpb24uY29sdW1uIHx8IFwic3RhdGVcIlxuICBjb25zdCBzdGF0ZU5hbWVzID0gT2JqZWN0LmtleXMoZGVmaW5pdGlvbi5zdGF0ZXMpXG5cbiAgLy8gU3RvcmUgZGVmaW5pdGlvbiBvbiB0aGUgbW9kZWwgY2xhc3MgZm9yIGludHJvc3BlY3Rpb25cbiAgLyoqXG4gICAqIER5bmFtaWMgY2xhc3MuXG4gICAqIEB0eXBlIHs/fSAqL1xuICBjb25zdCBkeW5hbWljQ2xhc3MgPSBNb2RlbENsYXNzXG5cbiAgLy8gSWRlbXBvdGVudDogcmUtZGVjbGFyaW5nIG9uIHRoZSBzYW1lIGNsYXNzIChvciBhIHJlLWV2YWx1YXRlZCBtb2R1bGUpIG11c3Qgbm90XG4gIC8vIHJlZ2lzdGVyIHRoZSBiZWZvcmUvYWZ0ZXItc2F2ZSB0cmFuc2l0aW9uIGhvb2tzIHR3aWNlLiBHdWFyZCBvbiBhbiBvd24gcHJvcGVydHlcbiAgLy8gc28gYSBzdWJjbGFzcyBkZWNsYXJpbmcgaXRzIG93biBtYWNoaW5lIGlzIHVuYWZmZWN0ZWQgYnkgdGhlIHBhcmVudCdzIGZsYWcuXG4gIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZHluYW1pY0NsYXNzLCBcIl9zdGF0ZU1hY2hpbmVSZWdpc3RlcmVkXCIpICYmIGR5bmFtaWNDbGFzcy5fc3RhdGVNYWNoaW5lUmVnaXN0ZXJlZCkge1xuICAgIHJldHVyblxuICB9XG5cbiAgZHluYW1pY0NsYXNzLl9zdGF0ZU1hY2hpbmVSZWdpc3RlcmVkID0gdHJ1ZVxuICBkeW5hbWljQ2xhc3MuX3N0YXRlTWFjaGluZURlZmluaXRpb24gPSBkZWZpbml0aW9uXG4gIGR5bmFtaWNDbGFzcy5fc3RhdGVNYWNoaW5lQ29sdW1uID0gY29sdW1uXG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHJlZ2lzdGVyZWQgc3RhdGUgbWFjaGluZSBkZWZpbml0aW9uLlxuICAgKiBAcmV0dXJucyB7U3RhdGVNYWNoaW5lRGVmaW5pdGlvbn0gLSBUaGUgcmVnaXN0ZXJlZCBzdGF0ZSBtYWNoaW5lIGRlZmluaXRpb24uXG4gICAqL1xuICBkeW5hbWljQ2xhc3MuZ2V0U3RhdGVNYWNoaW5lRGVmaW5pdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZHluYW1pY0NsYXNzLl9zdGF0ZU1hY2hpbmVEZWZpbml0aW9uXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc3RhdGUgY29sdW1uIG5hbWUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IC0gVGhlIGNvbHVtbiBuYW1lIHVzZWQgZm9yIHN0YXRlIHN0b3JhZ2UuXG4gICAqL1xuICBkeW5hbWljQ2xhc3MuZ2V0U3RhdGVNYWNoaW5lQ29sdW1uID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBkeW5hbWljQ2xhc3MuX3N0YXRlTWFjaGluZUNvbHVtblxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYWxsIGRlY2xhcmVkIHN0YXRlIG5hbWVzLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nW119IC0gQWxsIGRlY2xhcmVkIHN0YXRlIG5hbWVzLlxuICAgKi9cbiAgZHluYW1pY0NsYXNzLmdldFN0YXRlTWFjaGluZVN0YXRlTmFtZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHN0YXRlTmFtZXNcbiAgfVxuXG4gIC8vIFJlZ2lzdGVyIGV2ZW50IG1ldGhvZHMgYW5kIGd1YXJkIG1ldGhvZHMgb24gdGhlIHByb3RvdHlwZVxuICAvKipcbiAgICogUHJvdG8uXG4gICAqIEB0eXBlIHs/fSAqL1xuICBjb25zdCBwcm90byA9IE1vZGVsQ2xhc3MucHJvdG90eXBlXG5cbiAgZm9yIChjb25zdCBbZXZlbnROYW1lLCBldmVudERlZl0gb2YgT2JqZWN0LmVudHJpZXMoZGVmaW5pdGlvbi5ldmVudHMpKSB7XG4gICAgY29uc3QgZnJvbVN0YXRlcyA9IEFycmF5LmlzQXJyYXkoZXZlbnREZWYuZnJvbSkgPyBldmVudERlZi5mcm9tIDogW2V2ZW50RGVmLmZyb21dXG4gICAgY29uc3QgY2FwaXRhbGl6ZWRFdmVudCA9IGV2ZW50TmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIGV2ZW50TmFtZS5zbGljZSgxKVxuICAgIGNvbnN0IGNhbk1ldGhvZE5hbWUgPSBgY2FuJHtjYXBpdGFsaXplZEV2ZW50fWBcbiAgICBjb25zdCBzZXR0ZXJOYW1lID0gY29sdW1uU2V0dGVyTmFtZShjb2x1bW4pXG5cbiAgICAvLyBHdWFyZCBtZXRob2Q6IGNhblF1ZXVlKCksIGNhblJ1bigpLCBldGMuXG4gICAgcHJvdG9bY2FuTWV0aG9kTmFtZV0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjdXJyZW50U3RhdGUgPSB0aGlzLnJlYWRBdHRyaWJ1dGUoY29sdW1uKVxuXG4gICAgICBpZiAoIWZyb21TdGF0ZXMuaW5jbHVkZXMoY3VycmVudFN0YXRlKSkge1xuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIH1cblxuICAgICAgaWYgKGV2ZW50RGVmLmd1YXJkKSB7XG4gICAgICAgIGNvbnN0IGd1YXJkUmVzdWx0ID0gZXZlbnREZWYuZ3VhcmQodGhpcylcblxuICAgICAgICBpZiAoZ3VhcmRSZXN1bHQgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBHdWFyZCBmb3IgZXZlbnQgXCIke2V2ZW50TmFtZX1cIiByZXR1cm5lZCBhIFByb21pc2UuIFVzZSBhd2FpdCBtb2RlbC5jYW4ke2NhcGl0YWxpemVkRXZlbnR9QXN5bmMoKSBpbnN0ZWFkLmApXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZ3VhcmRSZXN1bHRcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG5cbiAgICAvLyBBc3luYyBndWFyZCBtZXRob2Q6IGNhblF1ZXVlQXN5bmMoKSwgY2FuUnVuQXN5bmMoKSwgZXRjLlxuICAgIHByb3RvW2Ake2Nhbk1ldGhvZE5hbWV9QXN5bmNgXSA9IGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IHRoaXMucmVhZEF0dHJpYnV0ZShjb2x1bW4pXG5cbiAgICAgIGlmICghZnJvbVN0YXRlcy5pbmNsdWRlcyhjdXJyZW50U3RhdGUpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgfVxuXG4gICAgICBpZiAoZXZlbnREZWYuZ3VhcmQpIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGV2ZW50RGVmLmd1YXJkKHRoaXMpXG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuXG4gICAgLy8gVHJhbnNpdGlvbiBtZXRob2Q6IHF1ZXVlKCksIHJ1bigpLCBldGMuIOKAlCBjaGVja3MgZ3VhcmQsIHNldHMgdGhlIHN0YXRlLCBzdGFzaGVzIGV2ZW50IG5hbWVcbiAgICBwcm90b1tldmVudE5hbWVdID0gZnVuY3Rpb24gKCkge1xuICAgICAgLyoqXG4gICAgICAgKiBTZWxmLlxuICAgICAgICogQHR5cGUgez99ICovXG4gICAgICBjb25zdCBzZWxmID0gdGhpc1xuICAgICAgY29uc3QgY3VycmVudFN0YXRlID0gc2VsZi5yZWFkQXR0cmlidXRlKGNvbHVtbilcblxuICAgICAgaWYgKCFmcm9tU3RhdGVzLmluY2x1ZGVzKGN1cnJlbnRTdGF0ZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBDYW5ub3QgdHJhbnNpdGlvbiBcIiR7ZXZlbnROYW1lfVwiIGZyb20gXCIke2N1cnJlbnRTdGF0ZX1cIiBvbiAke3NlbGYuZ2V0TW9kZWxDbGFzcygpLm5hbWV9LiBgICtcbiAgICAgICAgICBgQWxsb3dlZCBzb3VyY2Ugc3RhdGVzOiAke2Zyb21TdGF0ZXMuam9pbihcIiwgXCIpfWBcbiAgICAgICAgKVxuICAgICAgfVxuXG4gICAgICAvLyBFbmZvcmNlIHN5bmNocm9ub3VzIGd1YXJkIGJlZm9yZSBtdXRhdGluZyBzdGF0ZVxuICAgICAgaWYgKGV2ZW50RGVmLmd1YXJkKSB7XG4gICAgICAgIGNvbnN0IGd1YXJkUmVzdWx0ID0gZXZlbnREZWYuZ3VhcmQoc2VsZilcblxuICAgICAgICBpZiAoZ3VhcmRSZXN1bHQgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBHdWFyZCBmb3IgZXZlbnQgXCIke2V2ZW50TmFtZX1cIiByZXR1cm5lZCBhIFByb21pc2UuIFVzZSBhd2FpdCBtb2RlbC4ke2V2ZW50TmFtZX1BbmRTYXZlKCkgZm9yIGFzeW5jIGd1YXJkcy5gKVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFndWFyZFJlc3VsdCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBHdWFyZCByZWplY3RlZCB0cmFuc2l0aW9uIFwiJHtldmVudE5hbWV9XCIgZnJvbSBcIiR7Y3VycmVudFN0YXRlfVwiIG9uICR7c2VsZi5nZXRNb2RlbENsYXNzKCkubmFtZX0uYFxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBTdGFzaCB0aGUgdHJhbnNpdGlvbiBzbyBiZWZvcmVTYXZlL2FmdGVyU2F2ZSBrbm93IHdoaWNoIGV2ZW50IHdhcyBpbnZva2VkXG4gICAgICBzZWxmW1BFTkRJTkdfVFJBTlNJVElPTl9LRVldID0ge2V2ZW50TmFtZSwgZnJvbTogY3VycmVudFN0YXRlLCB0bzogZXZlbnREZWYudG99XG4gICAgICBzZWxmW3NldHRlck5hbWVdKGV2ZW50RGVmLnRvKVxuICAgIH1cblxuICAgIC8vIEJhbmcgbWV0aG9kOiBxdWV1ZUFuZFNhdmUoKSwgcnVuQW5kU2F2ZSgpLCBldGMuIOKAlCB0cmFuc2l0aW9ucyBBTkQgc2F2ZXMgKHN1cHBvcnRzIGFzeW5jIGd1YXJkcylcbiAgICBwcm90b1tgJHtldmVudE5hbWV9QW5kU2F2ZWBdID0gYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLyoqXG4gICAgICAgKiBTZWxmLlxuICAgICAgICogQHR5cGUgez99ICovXG4gICAgICBjb25zdCBzZWxmID0gdGhpc1xuICAgICAgY29uc3QgY3VycmVudFN0YXRlID0gc2VsZi5yZWFkQXR0cmlidXRlKGNvbHVtbilcblxuICAgICAgaWYgKCFmcm9tU3RhdGVzLmluY2x1ZGVzKGN1cnJlbnRTdGF0ZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBDYW5ub3QgdHJhbnNpdGlvbiBcIiR7ZXZlbnROYW1lfVwiIGZyb20gXCIke2N1cnJlbnRTdGF0ZX1cIiBvbiAke3NlbGYuZ2V0TW9kZWxDbGFzcygpLm5hbWV9LiBgICtcbiAgICAgICAgICBgQWxsb3dlZCBzb3VyY2Ugc3RhdGVzOiAke2Zyb21TdGF0ZXMuam9pbihcIiwgXCIpfWBcbiAgICAgICAgKVxuICAgICAgfVxuXG4gICAgICAvLyBFbmZvcmNlIGFzeW5jIGd1YXJkIGJlZm9yZSBtdXRhdGluZyBzdGF0ZVxuICAgICAgaWYgKGV2ZW50RGVmLmd1YXJkKSB7XG4gICAgICAgIGNvbnN0IGFsbG93ZWQgPSBhd2FpdCBldmVudERlZi5ndWFyZChzZWxmKVxuXG4gICAgICAgIGlmICghYWxsb3dlZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBHdWFyZCByZWplY3RlZCB0cmFuc2l0aW9uIFwiJHtldmVudE5hbWV9XCIgZnJvbSBcIiR7Y3VycmVudFN0YXRlfVwiIG9uICR7c2VsZi5nZXRNb2RlbENsYXNzKCkubmFtZX0uYFxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBzZWxmW1BFTkRJTkdfVFJBTlNJVElPTl9LRVldID0ge2V2ZW50TmFtZSwgZnJvbTogY3VycmVudFN0YXRlLCB0bzogZXZlbnREZWYudG99XG4gICAgICBzZWxmW3NldHRlck5hbWVdKGV2ZW50RGVmLnRvKVxuICAgICAgYXdhaXQgc2VsZi5zYXZlKClcbiAgICB9XG4gIH1cblxuICAvLyBSZWdpc3RlciBhIGJlZm9yZVNhdmUgY2FsbGJhY2sgdGhhdCBmaXJlcyBzdGF0ZS1lbnRlciBob29rc1xuICBNb2RlbENsYXNzLmJlZm9yZVNhdmUoYXN5bmMgZnVuY3Rpb24gKG1vZGVsKSB7XG4gICAgLyoqXG4gICAgICogRHluYW1pYyBtb2RlbC5cbiAgICAgKiBAdHlwZSB7P30gKi9cbiAgICBjb25zdCBkeW5hbWljTW9kZWwgPSBtb2RlbFxuICAgIGNvbnN0IHBlbmRpbmcgPSBkeW5hbWljTW9kZWxbUEVORElOR19UUkFOU0lUSU9OX0tFWV1cblxuICAgIGlmICghcGVuZGluZykge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3QgZXZlbnREZWYgPSBkZWZpbml0aW9uLmV2ZW50c1twZW5kaW5nLmV2ZW50TmFtZV1cblxuICAgIC8vIFJ1biBldmVudC1sZXZlbCBiZWZvcmUgY2FsbGJhY2tcbiAgICBpZiAoZXZlbnREZWY/LmJlZm9yZSkge1xuICAgICAgYXdhaXQgZXZlbnREZWYuYmVmb3JlKG1vZGVsKVxuICAgIH1cblxuICAgIC8vIFJ1biB0aGUgZXhpdGVkIHN0YXRlJ3MgYmVmb3JlRXhpdCwgdGhlbiB0aGUgZW50ZXJlZCBzdGF0ZSdzIGJlZm9yZUVudGVyXG4gICAgY29uc3QgZnJvbVN0YXRlRGVmaW5pdGlvbiA9IGRlZmluaXRpb24uc3RhdGVzW3BlbmRpbmcuZnJvbV1cblxuICAgIGlmIChmcm9tU3RhdGVEZWZpbml0aW9uPy5iZWZvcmVFeGl0KSB7XG4gICAgICBhd2FpdCBmcm9tU3RhdGVEZWZpbml0aW9uLmJlZm9yZUV4aXQobW9kZWwpXG4gICAgfVxuXG4gICAgY29uc3Qgc3RhdGVEZWZpbml0aW9uID0gZGVmaW5pdGlvbi5zdGF0ZXNbcGVuZGluZy50b11cblxuICAgIGlmIChzdGF0ZURlZmluaXRpb24/LmJlZm9yZUVudGVyKSB7XG4gICAgICBhd2FpdCBzdGF0ZURlZmluaXRpb24uYmVmb3JlRW50ZXIobW9kZWwpXG4gICAgfVxuICB9KVxuXG4gIC8vIFJlZ2lzdGVyIGFuIGFmdGVyU2F2ZSBjYWxsYmFjayBmb3IgYWZ0ZXJFbnRlciBob29rc1xuICBNb2RlbENsYXNzLmFmdGVyU2F2ZShhc3luYyBmdW5jdGlvbiAobW9kZWwpIHtcbiAgICAvKipcbiAgICAgKiBEeW5hbWljIG1vZGVsLlxuICAgICAqIEB0eXBlIHs/fSAqL1xuICAgIGNvbnN0IGR5bmFtaWNNb2RlbCA9IG1vZGVsXG4gICAgY29uc3QgcGVuZGluZyA9IGR5bmFtaWNNb2RlbFtQRU5ESU5HX1RSQU5TSVRJT05fS0VZXVxuXG4gICAgaWYgKCFwZW5kaW5nKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBDbGVhciB0aGUgcGVuZGluZyB0cmFuc2l0aW9uIG5vdyB0aGF0IHNhdmUgaXMgY29tcGxldGVcbiAgICBkeW5hbWljTW9kZWxbUEVORElOR19UUkFOU0lUSU9OX0tFWV0gPSBudWxsXG5cbiAgICAvLyBSdW4gdGhlIGVudGVyZWQgc3RhdGUncyBhZnRlckVudGVyLCB0aGVuIHRoZSBleGl0ZWQgc3RhdGUncyBhZnRlckV4aXRcbiAgICBjb25zdCBzdGF0ZURlZmluaXRpb24gPSBkZWZpbml0aW9uLnN0YXRlc1twZW5kaW5nLnRvXVxuXG4gICAgaWYgKHN0YXRlRGVmaW5pdGlvbj8uYWZ0ZXJFbnRlcikge1xuICAgICAgYXdhaXQgc3RhdGVEZWZpbml0aW9uLmFmdGVyRW50ZXIobW9kZWwpXG4gICAgfVxuXG4gICAgY29uc3QgZnJvbVN0YXRlRGVmaW5pdGlvbiA9IGRlZmluaXRpb24uc3RhdGVzW3BlbmRpbmcuZnJvbV1cblxuICAgIGlmIChmcm9tU3RhdGVEZWZpbml0aW9uPy5hZnRlckV4aXQpIHtcbiAgICAgIGF3YWl0IGZyb21TdGF0ZURlZmluaXRpb24uYWZ0ZXJFeGl0KG1vZGVsKVxuICAgIH1cblxuICAgIC8vIFJ1biBldmVudC1sZXZlbCBhZnRlciBjYWxsYmFja1xuICAgIGNvbnN0IGV2ZW50RGVmID0gZGVmaW5pdGlvbi5ldmVudHNbcGVuZGluZy5ldmVudE5hbWVdXG5cbiAgICBpZiAoZXZlbnREZWY/LmFmdGVyKSB7XG4gICAgICBhd2FpdCBldmVudERlZi5hZnRlcihtb2RlbClcbiAgICB9XG4gIH0pXG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc2V0dGVyIG1ldGhvZCBuYW1lIGZvciBhIGNvbHVtbiAoZS5nLiwgXCJzdGF0dXNcIiDihpIgXCJzZXRTdGF0dXNcIiwgXCJzdGF0ZVwiIOKGkiBcInNldFN0YXRlXCIpLlxuICogQHBhcmFtIHtzdHJpbmd9IGNvbHVtbiAtIFRoZSBjb2x1bW4gbmFtZS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IC0gVGhlIHNldHRlciBtZXRob2QgbmFtZS5cbiAqL1xuZnVuY3Rpb24gY29sdW1uU2V0dGVyTmFtZShjb2x1bW4pIHtcbiAgcmV0dXJuIGBzZXQke2NvbHVtbi5jaGFyQXQoMCkudG9VcHBlckNhc2UoKX0ke2NvbHVtbi5zbGljZSgxKX1gXG59XG4iXX0=
@@ -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/drop.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/column-types.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/auditing.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/validation-messages.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/length.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/data-copier.js","../src/database/tenants/schema-cloner.js","../src/database/tenants/tenant-table-plan.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/packages/velocious-package.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/query-scope.js","../src/sync/server-change-feed.js","../src/sync/server-sequence-allocator.js","../src/sync/stable-json.js","../src/sync/sync-api-client-types.js","../src/sync/sync-api-client.js","../src/sync/sync-api-controller.js","../src/sync/sync-client-registry.js","../src/sync/sync-client-types.js","../src/sync/sync-client.js","../src/sync/sync-envelope-replay-service.js","../src/sync/sync-model-change-feed-service.js","../src/sync/sync-replay-upsert-applier.js","../src/sync/sync-resource-base.js","../src/sync/sync-scope-store.js","../src/tenants/default-tenant-database-provisioning.js","../src/tenants/tenant-iterator.js","../src/tenants/tenant.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/drop.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/column-types.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/auditing.js","../src/database/record/counter-cache-magnitude.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/validation-messages.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/length.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/data-copier.js","../src/database/tenants/schema-cloner.js","../src/database/tenants/tenant-table-plan.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/packages/velocious-package.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/query-scope.js","../src/sync/server-change-feed.js","../src/sync/server-sequence-allocator.js","../src/sync/stable-json.js","../src/sync/sync-api-client-types.js","../src/sync/sync-api-client.js","../src/sync/sync-api-controller.js","../src/sync/sync-client-registry.js","../src/sync/sync-client-types.js","../src/sync/sync-client.js","../src/sync/sync-envelope-replay-service.js","../src/sync/sync-model-change-feed-service.js","../src/sync/sync-replay-upsert-applier.js","../src/sync/sync-resource-base.js","../src/sync/sync-scope-store.js","../src/tenants/default-tenant-database-provisioning.js","../src/tenants/tenant-iterator.js","../src/tenants/tenant.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.497",
6
+ "version": "1.0.499",
7
7
  "main": "build/index.js",
8
8
  "types": "build/index.d.ts",
9
9
  "files": [
@@ -7,9 +7,19 @@ import query from "./query"
7
7
  // @ts-expect-error
8
8
  import * as SQLite from "expo-sqlite"
9
9
 
10
+ import Mutex from "epic-locks/build/mutex.js"
11
+
10
12
  import Base from "./base.js"
11
13
 
12
14
  export default class VelociousDatabaseDriversSqliteNative extends Base {
15
+ /**
16
+ * Serializes native queries so concurrent `getAllAsync` calls never race
17
+ * `expo-sqlite`'s shared `NativeStatement` objects (a single connection
18
+ * prepares/executes/finalizes one statement at a time).
19
+ * @type {Mutex}
20
+ */
21
+ _queryMutex = new Mutex()
22
+
13
23
  async connect() {
14
24
  const {isBrowser, isNative, isServer} = envSense()
15
25
 
@@ -65,8 +75,10 @@ export default class VelociousDatabaseDriversSqliteNative extends Base {
65
75
  * @returns {Promise<Record<string, ?>[]>} - Query result rows.
66
76
  */
67
77
  async _queryActual(sql) {
68
- if (!this.connection) throw new Error("Not connected yet")
78
+ return await this._queryMutex.sync(() => {
79
+ if (!this.connection) throw new Error("Not connected yet")
69
80
 
70
- return await query(this.connection, sql)
81
+ return query(this.connection, sql)
82
+ })
71
83
  }
72
84
  }
@@ -0,0 +1,240 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * Reactive counter-cache driven by a per-record magnitude.
5
+ *
6
+ * Maintains a counter column on a `belongsTo` parent as the running sum of each
7
+ * child's magnitude — a small number derived from one source attribute (e.g.
8
+ * `1` while a build's `status` is `running`, else `0`). On every create, update
9
+ * and destroy the change in magnitude is applied to the parent as a single
10
+ * atomic increment (`SET col = col + delta`), and when the foreign key changes
11
+ * the magnitude is moved from the old parent to the new one.
12
+ *
13
+ * Because the counter is derived from the source attribute and diffed on every
14
+ * write, it follows that attribute automatically no matter which code path wrote
15
+ * it — there is no per-transition increment/decrement to forget. The old value is
16
+ * captured in `beforeSave` (Velocious clears `changes()` during the post-update
17
+ * reload) and consumed in `afterSave`, so the increment commits atomically with
18
+ * the row it reflects.
19
+ * @typedef {{
20
+ * belongsTo: string,
21
+ * counterColumn: string,
22
+ * sourceAttribute: string,
23
+ * magnitude: (sourceValue: ?) => number
24
+ * }} MagnitudeCounterCacheDefinition
25
+ */
26
+
27
+ /**
28
+ * Captured pending magnitude change stashed on a record between beforeSave and afterSave.
29
+ * @typedef {{newMagnitude: number, oldMagnitude: number, newParentId: ?, oldParentId: ?}} PendingMagnitudeDelta
30
+ */
31
+
32
+ /**
33
+ * Registers a reactive magnitude counter-cache on a model class.
34
+ * @param {typeof import("./index.js").default} modelClass - Model class to add the counter cache to.
35
+ * @param {MagnitudeCounterCacheDefinition} definition - Counter cache definition.
36
+ * @returns {void}
37
+ */
38
+ export function registerMagnitudeCounterCache(modelClass, definition) {
39
+ /**
40
+ * Dynamic class.
41
+ * @type {?} */
42
+ const dynamicClass = modelClass
43
+ const registeredFlag = `_magnitudeCounterCacheRegistered_${definition.counterColumn}`
44
+
45
+ // Idempotent per counter column: re-declaring (or subclassing) must not double-register.
46
+ if (Object.prototype.hasOwnProperty.call(dynamicClass, registeredFlag) && dynamicClass[registeredFlag]) {
47
+ return
48
+ }
49
+
50
+ dynamicClass[registeredFlag] = true
51
+
52
+ const pendingKey = `_magnitudeCounterCachePending_${definition.counterColumn}`
53
+
54
+ modelClass.beforeSave(async function (record) {
55
+ /**
56
+ * Dynamic record.
57
+ * @type {?} */
58
+ const dynamicRecord = record
59
+
60
+ dynamicRecord[pendingKey] = computePendingMagnitudeDelta(record, definition)
61
+ })
62
+
63
+ modelClass.afterSave(async function (record) {
64
+ /**
65
+ * Dynamic record.
66
+ * @type {?} */
67
+ const dynamicRecord = record
68
+ const pending = /** @type {PendingMagnitudeDelta | null} */ (dynamicRecord[pendingKey])
69
+
70
+ dynamicRecord[pendingKey] = null
71
+
72
+ if (pending) {
73
+ await applyPendingMagnitudeDelta(record, definition, pending)
74
+ }
75
+ })
76
+
77
+ modelClass.afterDestroy(async function (record) {
78
+ const magnitude = definition.magnitude(record.readAttribute(definition.sourceAttribute))
79
+ const parentId = currentParentId(record, definition)
80
+
81
+ if (parentId && magnitude !== 0) {
82
+ await incrementParentCounter(record, definition, parentId, -magnitude)
83
+ }
84
+ })
85
+ }
86
+
87
+ /**
88
+ * Diffs the source attribute (and foreign key) across the pending save to capture
89
+ * how the parent counter should move. Runs in beforeSave, where `changes()` still
90
+ * holds the pre-save values.
91
+ * @param {import("./index.js").default} record - Record being saved.
92
+ * @param {MagnitudeCounterCacheDefinition} definition - Counter cache definition.
93
+ * @returns {PendingMagnitudeDelta} The captured magnitude change.
94
+ */
95
+ function computePendingMagnitudeDelta(record, definition) {
96
+ const changes = record.changes()
97
+ const sourceColumn = columnNameForAttribute(record, definition.sourceAttribute)
98
+ const foreignKeyColumn = record.getModelClass().getRelationshipByName(definition.belongsTo).getForeignKey()
99
+
100
+ const newSource = record.readAttribute(definition.sourceAttribute)
101
+ const oldSource = oldSourceValueThroughReadCast(record, definition.sourceAttribute, sourceColumn, changes, newSource)
102
+
103
+ const newParentId = currentParentId(record, definition)
104
+ const oldParentId = foreignKeyColumn in changes ? changes[foreignKeyColumn][0] : newParentId
105
+
106
+ return {
107
+ newMagnitude: definition.magnitude(newSource),
108
+ oldMagnitude: definition.magnitude(oldSource),
109
+ newParentId,
110
+ oldParentId
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Applies a captured magnitude change to the parent counter(s) as atomic increments.
116
+ * @param {import("./index.js").default} record - Record that was saved.
117
+ * @param {MagnitudeCounterCacheDefinition} definition - Counter cache definition.
118
+ * @param {PendingMagnitudeDelta} pending - The captured magnitude change.
119
+ * @returns {Promise<void>}
120
+ */
121
+ async function applyPendingMagnitudeDelta(record, definition, pending) {
122
+ const {newMagnitude, oldMagnitude, newParentId, oldParentId} = pending
123
+
124
+ if (oldParentId === newParentId) {
125
+ const delta = newMagnitude - oldMagnitude
126
+
127
+ if (newParentId && delta !== 0) {
128
+ await incrementParentCounter(record, definition, newParentId, delta)
129
+ }
130
+
131
+ return
132
+ }
133
+
134
+ // The foreign key moved: take the old magnitude off the old parent and put the
135
+ // new magnitude on the new parent.
136
+ if (oldParentId && oldMagnitude !== 0) {
137
+ await incrementParentCounter(record, definition, oldParentId, -oldMagnitude)
138
+ }
139
+
140
+ if (newParentId && newMagnitude !== 0) {
141
+ await incrementParentCounter(record, definition, newParentId, newMagnitude)
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Reads the pre-save value of the source attribute through the normal read/cast
147
+ * path, so `magnitude` receives the old value in the same shape as the new one
148
+ * (e.g. a declared boolean as `true`/`false`, not the raw stored `1`/`0`). Drops
149
+ * the pending change so `readAttribute` falls back to the committed value and
150
+ * applies the same cast a fresh read would, then restores the pending change.
151
+ * @param {import("./index.js").default} record - Record being saved.
152
+ * @param {string} sourceAttribute - Source attribute name.
153
+ * @param {string} sourceColumn - Source column name.
154
+ * @param {Record<string, ?>} changes - The record's pre-save changes (column-keyed).
155
+ * @param {?} currentValue - The current (new) read value, returned when the source did not change.
156
+ * @returns {?} The read-cast pre-save value.
157
+ */
158
+ function oldSourceValueThroughReadCast(record, sourceAttribute, sourceColumn, changes, currentValue) {
159
+ if (!(sourceColumn in changes)) {
160
+ return currentValue
161
+ }
162
+
163
+ /**
164
+ * Dynamic record.
165
+ * @type {?} */
166
+ const dynamicRecord = record
167
+ const pendingChange = dynamicRecord._changes[sourceColumn]
168
+
169
+ delete dynamicRecord._changes[sourceColumn]
170
+
171
+ try {
172
+ return record.readAttribute(sourceAttribute)
173
+ } finally {
174
+ dynamicRecord._changes[sourceColumn] = pendingChange
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Reads the record's current foreign-key value for the counter-cache parent.
180
+ * @param {import("./index.js").default} record - Record whose parent is targeted.
181
+ * @param {MagnitudeCounterCacheDefinition} definition - Counter cache definition.
182
+ * @returns {?} The current foreign-key value.
183
+ */
184
+ function currentParentId(record, definition) {
185
+ const foreignKeyColumn = record.getModelClass().getRelationshipByName(definition.belongsTo).getForeignKey()
186
+
187
+ return record.readAttribute(attributeNameForColumn(record, foreignKeyColumn))
188
+ }
189
+
190
+ /**
191
+ * Atomically adds `amount` to the parent's counter column for one parent row.
192
+ * @param {import("./index.js").default} record - Child record (for connection + relationship metadata).
193
+ * @param {MagnitudeCounterCacheDefinition} definition - Counter cache definition.
194
+ * @param {?} parentId - Parent primary-key value.
195
+ * @param {number} amount - Signed integer to add.
196
+ * @returns {Promise<void>}
197
+ */
198
+ async function incrementParentCounter(record, definition, parentId, amount) {
199
+ const modelClass = record.getModelClass()
200
+ const relationship = modelClass.getRelationshipByName(definition.belongsTo)
201
+ const parentModelClass = relationship.getTargetModelClass()
202
+
203
+ if (!parentModelClass) {
204
+ throw new Error(`magnitudeCounterCache on ${modelClass.getModelName()} could not resolve the "${definition.belongsTo}" parent model class`)
205
+ }
206
+
207
+ // Update through the PARENT model's connection: the row being modified belongs
208
+ // to the parent, which may live on a different database/tenant than the child.
209
+ const db = parentModelClass.connection()
210
+ const counterColumnSql = db.quoteColumn(definition.counterColumn)
211
+ const truncatedAmount = Math.trunc(amount)
212
+
213
+ await db.query(
214
+ `UPDATE ${db.quoteTable(parentModelClass.tableName())} ` +
215
+ `SET ${counterColumnSql} = COALESCE(${counterColumnSql}, 0) + ${truncatedAmount} ` +
216
+ `WHERE ${db.quoteColumn(relationship.getPrimaryKey())} = ${db.quote(parentId)}`
217
+ )
218
+ }
219
+
220
+ /**
221
+ * Resolves the column name backing an attribute name.
222
+ * @param {import("./index.js").default} record - Record.
223
+ * @param {string} attributeName - Attribute name.
224
+ * @returns {string} The column name for the attribute (falls back to the attribute name).
225
+ */
226
+ function columnNameForAttribute(record, attributeName) {
227
+ return record.getModelClass().getAttributeNameToColumnNameMap()[attributeName] || attributeName
228
+ }
229
+
230
+ /**
231
+ * Resolves the attribute name backing a column name.
232
+ * @param {import("./index.js").default} record - Record.
233
+ * @param {string} columnName - Column name.
234
+ * @returns {string} The attribute name for the column (falls back to the column name).
235
+ */
236
+ function attributeNameForColumn(record, columnName) {
237
+ const map = record.getModelClass().getAttributeNameToColumnNameMap()
238
+
239
+ return Object.keys(map).find((attributeName) => map[attributeName] === columnName) || columnName
240
+ }
@@ -47,6 +47,8 @@ import {defineModelScope} from "../../utils/model-scope.js"
47
47
  import { normalizeDateStringForWrite, normalizeDateValueForRead, normalizeDateValueForWrite } from "../datetime-storage.js"
48
48
  import {formatValue} from "../../utils/format-value.js"
49
49
  import {captureCreateAuditChanges, captureUpdateAuditChanges, createAudit, createCreateAudit, createDestroyAudit, createUpdateAudit, registerAuditCallback, registerAuditing, withoutAudit} from "./auditing.js"
50
+ import {registerMagnitudeCounterCache} from "./counter-cache-magnitude.js"
51
+ import {stateMachine} from "./state-machine.js"
50
52
  import ValidatorsFormat from "./validators/format.js"
51
53
  import ValidatorsLength from "./validators/length.js"
52
54
  import ValidatorsPresence from "./validators/presence.js"
@@ -668,6 +670,30 @@ class VelociousDatabaseRecord {
668
670
  registerAuditing(this)
669
671
  }
670
672
 
673
+ /**
674
+ * Declares an aasm-style state machine on this model: named states, events
675
+ * (guarded transitions), and enter/exit + before/after transition hooks. See
676
+ * `state-machine.js`. Generates `event()` / `eventAndSave()` / `canEvent()`
677
+ * transition methods per declared event.
678
+ * @param {import("./state-machine.js").StateMachineDefinition} definition - State machine definition.
679
+ * @returns {void}
680
+ */
681
+ static stateMachine(definition) {
682
+ stateMachine(this, definition)
683
+ }
684
+
685
+ /**
686
+ * Maintains a counter column on a `belongsTo` parent as the sum of a per-record
687
+ * magnitude, kept current by atomic increments diffed on every create/update/
688
+ * destroy (and moved between parents when the foreign key changes). See
689
+ * `counter-cache-magnitude.js`.
690
+ * @param {import("./counter-cache-magnitude.js").MagnitudeCounterCacheDefinition} definition - Counter cache definition.
691
+ * @returns {void}
692
+ */
693
+ static magnitudeCounterCache(definition) {
694
+ registerMagnitudeCounterCache(this, definition)
695
+ }
696
+
671
697
  /**
672
698
  * Registers a callback invoked after this model writes an audit row for the action.
673
699
  * @template {typeof VelociousDatabaseRecord} MC