velocious 1.0.492 → 1.0.494
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/build/database/drivers/base.js +6 -0
- package/build/database/query/insert-base.js +1 -1
- package/build/src/database/drivers/base.d.ts +5 -0
- package/build/src/database/drivers/base.d.ts.map +1 -1
- package/build/src/database/drivers/base.js +6 -1
- package/build/src/database/query/insert-base.js +2 -2
- package/build/src/sync/server-sequence-allocator.d.ts +106 -0
- package/build/src/sync/server-sequence-allocator.d.ts.map +1 -0
- package/build/src/sync/server-sequence-allocator.js +220 -0
- package/build/src/sync/sync-attribute-normalizer.d.ts +105 -0
- package/build/src/sync/sync-attribute-normalizer.d.ts.map +1 -0
- package/build/src/sync/sync-attribute-normalizer.js +172 -0
- package/build/src/sync/sync-envelope-replay-service.d.ts +116 -7
- package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
- package/build/src/sync/sync-envelope-replay-service.js +103 -10
- package/build/src/sync/sync-replay-upsert-applier.d.ts +102 -0
- package/build/src/sync/sync-replay-upsert-applier.d.ts.map +1 -0
- package/build/src/sync/sync-replay-upsert-applier.js +158 -0
- package/build/src/sync/sync-resource-base.d.ts +48 -0
- package/build/src/sync/sync-resource-base.d.ts.map +1 -1
- package/build/src/sync/sync-resource-base.js +89 -1
- package/build/sync/server-sequence-allocator.js +246 -0
- package/build/sync/sync-attribute-normalizer.js +186 -0
- package/build/sync/sync-envelope-replay-service.js +114 -9
- package/build/sync/sync-replay-upsert-applier.js +179 -0
- package/build/sync/sync-resource-base.js +103 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/database/drivers/base.js +6 -0
- package/src/database/query/insert-base.js +1 -1
- package/src/sync/server-sequence-allocator.js +246 -0
- package/src/sync/sync-attribute-normalizer.js +186 -0
- package/src/sync/sync-envelope-replay-service.js +114 -9
- package/src/sync/sync-replay-upsert-applier.js +179 -0
- package/src/sync/sync-resource-base.js +103 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { optionalFloat, optionalInteger, optionalString } from "typanic";
|
|
3
|
+
import SyncApiClient from "./sync-api-client.js";
|
|
4
|
+
/**
|
|
5
|
+
* Coercers for the declarative sync field types. All are present-key based:
|
|
6
|
+
* a field is only applied when its key exists in the mutation data.
|
|
7
|
+
* @type {Record<string, (value: ?, label: string) => ?>}
|
|
8
|
+
*/
|
|
9
|
+
const FIELD_TYPES = {
|
|
10
|
+
booleanOrNull: (value, label) => SyncApiClient.optionalBooleanSyncValue(value, label),
|
|
11
|
+
dateOrNull: (value, label) => optionalSyncDate(value, label),
|
|
12
|
+
floatOrNull: (value, label) => optionalFloat(value, label),
|
|
13
|
+
integerOrNull: (value, label) => optionalInteger(value, label),
|
|
14
|
+
raw: (value) => value,
|
|
15
|
+
stringOrNull: (value, label) => optionalString(value, label)
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Parses an optional date value, failing loudly on invalid input.
|
|
19
|
+
* @param {?} value - Date, parseable string, or epoch number.
|
|
20
|
+
* @param {string} label - Field label for error messages.
|
|
21
|
+
* @returns {Date | null} Parsed date or null when absent.
|
|
22
|
+
*/
|
|
23
|
+
function optionalSyncDate(value, label) {
|
|
24
|
+
if (value === null || value === undefined)
|
|
25
|
+
return null;
|
|
26
|
+
if (value instanceof Date && !Number.isNaN(value.getTime()))
|
|
27
|
+
return value;
|
|
28
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
29
|
+
const dateValue = new Date(value);
|
|
30
|
+
if (!Number.isNaN(dateValue.getTime()))
|
|
31
|
+
return dateValue;
|
|
32
|
+
}
|
|
33
|
+
throw new Error(`Expected ${label} to be a valid date or null`);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Declarative field-map upsert applier for sync replay mutations.
|
|
37
|
+
*
|
|
38
|
+
* Owns the generic mechanics every per-resource replay handler repeats:
|
|
39
|
+
* present-key filtering, per-field type coercion, unknown-key rejection, the
|
|
40
|
+
* find-or-create upsert, the delete branch, optional snapshot serialization,
|
|
41
|
+
* and the domain after-apply tail. Apps declare only the field map and hooks.
|
|
42
|
+
*/
|
|
43
|
+
export default class SyncReplayUpsertApplier {
|
|
44
|
+
/**
|
|
45
|
+
* Creates a declarative upsert applier.
|
|
46
|
+
* @param {object} args - Applier configuration.
|
|
47
|
+
* @param {?} args.modelClass - Model class receiving the mutations.
|
|
48
|
+
* @param {Record<string, string | {type: string, column?: string} | ((value: ?, label: string) => ?)>} args.fields - Data-key → field-type map: a named type, a {type, column} rename spec, "ignored" for accepted-but-dropped keys, or a custom coercer function.
|
|
49
|
+
* @param {(args: {data: Record<string, ?>, mutation: ?, context: Record<string, ?>}) => Promise<?>} [args.findRecord] - Custom record resolver. Defaults to findBy({id: mutation.resourceId}).
|
|
50
|
+
* @param {(args: {mutation: ?, context: Record<string, ?>}) => Promise<?>} [args.findRecordForDelete] - Custom delete resolver. Defaults to findRecord.
|
|
51
|
+
* @param {"error" | "ignore"} [args.restArgs] - Unknown data-key handling. Defaults to "error".
|
|
52
|
+
* @param {(args: {mappedAttributes: Record<string, ?>, mutation: ?, context: Record<string, ?>, record: ?}) => Promise<Record<string, ?> | void>} [args.afterApply] - Domain tail; its returned object merges into the apply result.
|
|
53
|
+
* @param {(args: {mutation: ?, context: Record<string, ?>, record: ?}) => Promise<Record<string, ?>> | Record<string, ?>} [args.serialize] - Snapshot serializer; result lands on applyResult.serializedData.
|
|
54
|
+
*/
|
|
55
|
+
constructor({ afterApply, fields, findRecord, findRecordForDelete, modelClass, restArgs = "error", serialize }) {
|
|
56
|
+
if (!modelClass)
|
|
57
|
+
throw new Error("SyncReplayUpsertApplier requires a modelClass");
|
|
58
|
+
if (!fields || typeof fields !== "object")
|
|
59
|
+
throw new Error("SyncReplayUpsertApplier requires a fields map");
|
|
60
|
+
if (restArgs !== "error" && restArgs !== "ignore") {
|
|
61
|
+
throw new Error(`SyncReplayUpsertApplier restArgs must be "error" or "ignore", got: ${String(restArgs)}`);
|
|
62
|
+
}
|
|
63
|
+
for (const [fieldName, fieldSpec] of Object.entries(fields)) {
|
|
64
|
+
if (typeof fieldSpec === "function")
|
|
65
|
+
continue;
|
|
66
|
+
const fieldType = typeof fieldSpec === "string" ? fieldSpec : fieldSpec.type;
|
|
67
|
+
if (fieldType !== "ignored" && !(fieldType in FIELD_TYPES)) {
|
|
68
|
+
throw new Error(`Unknown sync field type: ${fieldType} for: ${fieldName}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
this.afterApply = afterApply;
|
|
72
|
+
this.fields = fields;
|
|
73
|
+
this.findRecord = findRecord;
|
|
74
|
+
this.findRecordForDelete = findRecordForDelete;
|
|
75
|
+
this.modelClass = modelClass;
|
|
76
|
+
this.restArgs = restArgs;
|
|
77
|
+
this.serialize = serialize;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Applies one normalized replay mutation to the declared model.
|
|
81
|
+
* @param {{actor: ?, context: Record<string, ?>, existingSync: ?, mutation: ?}} args - Replay apply arguments.
|
|
82
|
+
* @returns {Promise<Record<string, ?>>} Apply result with the record, created/deleted flags, optional serializedData, and afterApply extras.
|
|
83
|
+
*/
|
|
84
|
+
async apply({ context, mutation }) {
|
|
85
|
+
if (mutation.syncType === "delete")
|
|
86
|
+
return await this.applyDelete({ context, mutation });
|
|
87
|
+
const mappedAttributes = this.mappedAttributes(mutation.data);
|
|
88
|
+
const record = this.findRecord
|
|
89
|
+
? await this.findRecord({ context, data: mutation.data, mutation })
|
|
90
|
+
: await this.modelClass.findBy({ id: mutation.resourceId });
|
|
91
|
+
/** @type {Record<string, ?>} */
|
|
92
|
+
const result = { created: false, deleted: false, record: null };
|
|
93
|
+
if (record) {
|
|
94
|
+
record.assign(mappedAttributes);
|
|
95
|
+
await record.save();
|
|
96
|
+
result.record = record;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
result.record = await this.modelClass.create({ id: mutation.resourceId, ...mappedAttributes });
|
|
100
|
+
result.created = true;
|
|
101
|
+
}
|
|
102
|
+
if (this.serialize)
|
|
103
|
+
result.serializedData = await this.serialize({ context, mutation, record: result.record });
|
|
104
|
+
if (this.afterApply) {
|
|
105
|
+
const afterApplyResult = await this.afterApply({ context, mappedAttributes, mutation, record: result.record });
|
|
106
|
+
if (afterApplyResult && typeof afterApplyResult === "object")
|
|
107
|
+
Object.assign(result, afterApplyResult);
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Applies a delete mutation to the declared model.
|
|
113
|
+
* @param {{context: Record<string, ?>, mutation: ?}} args - Delete arguments.
|
|
114
|
+
* @returns {Promise<Record<string, ?>>} Apply result with the deleted flag.
|
|
115
|
+
*/
|
|
116
|
+
async applyDelete({ context, mutation }) {
|
|
117
|
+
const resolveRecord = this.findRecordForDelete || this.findRecord;
|
|
118
|
+
const record = resolveRecord
|
|
119
|
+
? await resolveRecord({ context, data: mutation.data, mutation })
|
|
120
|
+
: await this.modelClass.findBy({ id: mutation.resourceId });
|
|
121
|
+
if (!record)
|
|
122
|
+
return { created: false, deleted: false, record: null };
|
|
123
|
+
await record.destroy();
|
|
124
|
+
return { created: false, deleted: true, record };
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Maps present data keys through the declared field types.
|
|
128
|
+
* @param {Record<string, ?>} data - Normalized mutation data.
|
|
129
|
+
* @returns {Record<string, ?>} Coerced attributes keyed by column name.
|
|
130
|
+
*/
|
|
131
|
+
mappedAttributes(data) {
|
|
132
|
+
/** @type {Record<string, ?>} */
|
|
133
|
+
const mappedAttributes = {};
|
|
134
|
+
/** @type {string[]} */
|
|
135
|
+
const unknownKeys = [];
|
|
136
|
+
for (const [dataKey, value] of Object.entries(data)) {
|
|
137
|
+
const fieldSpec = this.fields[dataKey];
|
|
138
|
+
if (!fieldSpec) {
|
|
139
|
+
unknownKeys.push(dataKey);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (typeof fieldSpec === "function") {
|
|
143
|
+
mappedAttributes[dataKey] = fieldSpec(value, dataKey);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
const fieldType = typeof fieldSpec === "string" ? fieldSpec : fieldSpec.type;
|
|
147
|
+
if (fieldType === "ignored")
|
|
148
|
+
continue;
|
|
149
|
+
const column = typeof fieldSpec === "string" ? dataKey : fieldSpec.column || dataKey;
|
|
150
|
+
mappedAttributes[column] = FIELD_TYPES[fieldType](value, dataKey);
|
|
151
|
+
}
|
|
152
|
+
if (unknownKeys.length > 0 && this.restArgs === "error") {
|
|
153
|
+
throw new Error(`Unknown sync data keys: ${unknownKeys.join(", ")}`);
|
|
154
|
+
}
|
|
155
|
+
return mappedAttributes;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1yZXBsYXktdXBzZXJ0LWFwcGxpZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3luYy9zeW5jLXJlcGxheS11cHNlcnQtYXBwbGllci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxFQUFDLGFBQWEsRUFBRSxlQUFlLEVBQUUsY0FBYyxFQUFDLE1BQU0sU0FBUyxDQUFBO0FBRXRFLE9BQU8sYUFBYSxNQUFNLHNCQUFzQixDQUFBO0FBRWhEOzs7O0dBSUc7QUFDSCxNQUFNLFdBQVcsR0FBRztJQUNsQixhQUFhLEVBQUUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxhQUFhLENBQUMsd0JBQXdCLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQztJQUNyRixVQUFVLEVBQUUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDO0lBQzVELFdBQVcsRUFBRSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDO0lBQzFELGFBQWEsRUFBRSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDO0lBQzlELEdBQUcsRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSztJQUNyQixZQUFZLEVBQUUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQztDQUM3RCxDQUFBO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFTLGdCQUFnQixDQUFDLEtBQUssRUFBRSxLQUFLO0lBQ3BDLElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLEtBQUssU0FBUztRQUFFLE9BQU8sSUFBSSxDQUFBO0lBRXRELElBQUksS0FBSyxZ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QU0sQ0FBQyxPQUFPLENBQUMsQ0FBQTtZQUV0QyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ2YsV0FBVyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQTtnQkFDekIsU0FBUTtZQUNWLENBQUM7WUFFRCxJQUFJLE9BQU8sU0FBUyxLQUFLLFVBQVUsRUFBRSxDQUFDO2dCQUNwQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsR0FBRyxTQUFTLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFBO2dCQUNyRCxTQUFRO1lBQ1YsQ0FBQztZQUVELE1BQU0sU0FBUyxHQUFHLE9BQU8sU0FBUyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFBO1lBRTVFLElBQUksU0FBUyxLQUFLLFNBQVM7Z0JBQUUsU0FBUTtZQUVyQyxNQUFNLE1BQU0sR0FBRyxPQUFPLFNBQVMsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sSUFBSSxPQUFPLENBQUE7WUFFcEYsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLEdBQUcsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQTtRQUNuRSxDQUFDO1FBRUQsSUFBSSxXQUFXLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQ3hELE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBQ3RFLENBQUM7UUFFRCxPQUFPLGdCQUFnQixDQUFBO0lBQ3pCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQge29wdGlvbmFsRmxvYXQsIG9wdGlvbmFsSW50ZWdlciwgb3B0aW9uYWxTdHJpbmd9IGZyb20gXCJ0eXBhbmljXCJcblxuaW1wb3J0IFN5bmNBcGlDbGllbnQgZnJvbSBcIi4vc3luYy1hcGktY2xpZW50LmpzXCJcblxuLyoqXG4gKiBDb2VyY2VycyBmb3IgdGhlIGRlY2xhcmF0aXZlIHN5bmMgZmllbGQgdHlwZXMuIEFsbCBhcmUgcHJlc2VudC1rZXkgYmFzZWQ6XG4gKiBhIGZpZWxkIGlzIG9ubHkgYXBwbGllZCB3aGVuIGl0cyBrZXkgZXhpc3RzIGluIHRoZSBtdXRhdGlvbiBkYXRhLlxuICogQHR5cGUge1JlY29yZDxzdHJpbmcsICh2YWx1ZTogPywgbGFiZWw6IHN0cmluZykgPT4gPz59XG4gKi9cbmNvbnN0IEZJRUxEX1RZUEVTID0ge1xuICBib29sZWFuT3JOdWxsOiAodmFsdWUsIGxhYmVsKSA9PiBTeW5jQXBpQ2xpZW50Lm9wdGlvbmFsQm9vbGVhblN5bmNWYWx1ZSh2YWx1ZSwgbGFiZWwpLFxuICBkYXRlT3JOdWxsOiAodmFsdWUsIGxhYmVsKSA9PiBvcHRpb25hbFN5bmNEYXRlKHZhbHVlLCBsYWJlbCksXG4gIGZsb2F0T3JOdWxsOiAodmFsdWUsIGxhYmVsKSA9PiBvcHRpb25hbEZsb2F0KHZhbHVlLCBsYWJlbCksXG4gIGludGVnZXJPck51bGw6ICh2YWx1ZSwgbGFiZWwpID0+IG9wdGlvbmFsSW50ZWdlcih2YWx1ZSwgbGFiZWwpLFxuICByYXc6ICh2YWx1ZSkgPT4gdmFsdWUsXG4gIHN0cmluZ09yTnVsbDogKHZhbHVlLCBsYWJlbCkgPT4gb3B0aW9uYWxTdHJpbmcodmFsdWUsIGxhYmVsKVxufVxuXG4vKipcbiAqIFBhcnNlcyBhbiBvcHRpb25hbCBkYXRlIHZhbHVlLCBmYWlsaW5nIGxvdWRseSBvbiBpbnZhbGlkIGlucHV0LlxuICogQHBhcmFtIHs/fSB2YWx1ZSAtIERhdGUsIHBhcnNlYWJsZSBzdHJpbmcsIG9yIGVwb2NoIG51bWJlci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBsYWJlbCAtIEZpZWxkIGxhYmVsIGZvciBlcnJvciBtZXNzYWdlcy5cbiAqIEByZXR1cm5zIHtEYXRlIHwgbnVsbH0gUGFyc2VkIGRhdGUgb3IgbnVsbCB3aGVuIGFic2VudC5cbiAqL1xuZnVuY3Rpb24gb3B0aW9uYWxTeW5jRGF0ZSh2YWx1ZSwgbGFiZWwpIHtcbiAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHJldHVybiBudWxsXG5cbiAgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSAmJiAhTnVtYmVyLmlzTmFOKHZhbHVlLmdldFRpbWUoKSkpIHJldHVybiB2YWx1ZVxuXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgfHwgdHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiKSB7XG4gICAgY29uc3QgZGF0ZVZhbHVlID0gbmV3IERhdGUodmFsdWUpXG5cbiAgICBpZiAoIU51bWJlci5pc05hTihkYXRlVmFsdWUuZ2V0VGltZSgpKSkgcmV0dXJuIGRhdGVWYWx1ZVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCAke2xhYmVsfSB0byBiZSBhIHZhbGlkIGRhdGUgb3IgbnVsbGApXG59XG5cbi8qKlxuICogRGVjbGFyYXRpdmUgZmllbGQtbWFwIHVwc2VydCBhcHBsaWVyIGZvciBzeW5jIHJlcGxheSBtdXRhdGlvbnMuXG4gKlxuICogT3ducyB0aGUgZ2VuZXJpYyBtZWNoYW5pY3MgZXZlcnkgcGVyLXJlc291cmNlIHJlcGxheSBoYW5kbGVyIHJlcGVhdHM6XG4gKiBwcmVzZW50LWtleSBmaWx0ZXJpbmcsIHBlci1maWVsZCB0eXBlIGNvZXJjaW9uLCB1bmtub3duLWtleSByZWplY3Rpb24sIHRoZVxuICogZmluZC1vci1jcmVhdGUgdXBzZXJ0LCB0aGUgZGVsZXRlIGJyYW5jaCwgb3B0aW9uYWwgc25hcHNob3Qgc2VyaWFsaXphdGlvbixcbiAqIGFuZCB0aGUgZG9tYWluIGFmdGVyLWFwcGx5IHRhaWwuIEFwcHMgZGVjbGFyZSBvbmx5IHRoZSBmaWVsZCBtYXAgYW5kIGhvb2tzLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTeW5jUmVwbGF5VXBzZXJ0QXBwbGllciB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgZGVjbGFyYXRpdmUgdXBzZXJ0IGFwcGxpZXIuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gQXBwbGllciBjb25maWd1cmF0aW9uLlxuICAgKiBAcGFyYW0gez99IGFyZ3MubW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzIHJlY2VpdmluZyB0aGUgbXV0YXRpb25zLlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIHN0cmluZyB8IHt0eXBlOiBzdHJpbmcsIGNvbHVtbj86IHN0cmluZ30gfCAoKHZhbHVlOiA/LCBsYWJlbDogc3RyaW5nKSA9PiA/KT59IGFyZ3MuZmllbGRzIC0gRGF0YS1rZXkg4oaSIGZpZWxkLXR5cGUgbWFwOiBhIG5hbWVkIHR5cGUsIGEge3R5cGUsIGNvbHVtbn0gcmVuYW1lIHNwZWMsIFwiaWdub3JlZFwiIGZvciBhY2NlcHRlZC1idXQtZHJvcHBlZCBrZXlzLCBvciBhIGN1c3RvbSBjb2VyY2VyIGZ1bmN0aW9uLlxuICAgKiBAcGFyYW0geyhhcmdzOiB7ZGF0YTogUmVjb3JkPHN0cmluZywgPz4sIG11dGF0aW9uOiA/LCBjb250ZXh0OiBSZWNvcmQ8c3RyaW5nLCA/Pn0pID0+IFByb21pc2U8Pz59IFthcmdzLmZpbmRSZWNvcmRdIC0gQ3VzdG9tIHJlY29yZCByZXNvbHZlci4gRGVmYXVsdHMgdG8gZmluZEJ5KHtpZDogbXV0YXRpb24ucmVzb3VyY2VJZH0pLlxuICAgKiBAcGFyYW0geyhhcmdzOiB7bXV0YXRpb246ID8sIGNvbnRleHQ6IFJlY29yZDxzdHJpbmcsID8+fSkgPT4gUHJvbWlzZTw/Pn0gW2FyZ3MuZmluZFJlY29yZEZvckRlbGV0ZV0gLSBDdXN0b20gZGVsZXRlIHJlc29sdmVyLiBEZWZhdWx0cyB0byBmaW5kUmVjb3JkLlxuICAgKiBAcGFyYW0ge1wiZXJyb3JcIiB8IFwiaWdub3JlXCJ9IFthcmdzLnJlc3RBcmdzXSAtIFVua25vd24gZGF0YS1rZXkgaGFuZGxpbmcuIERlZmF1bHRzIHRvIFwiZXJyb3JcIi5cbiAgICogQHBhcmFtIHsoYXJnczoge21hcHBlZEF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsID8+LCBtdXRhdGlvbjogPywgY29udGV4dDogUmVjb3JkPHN0cmluZywgPz4sIHJlY29yZDogP30pID0+IFByb21pc2U8UmVjb3JkPHN0cmluZywgPz4gfCB2b2lkPn0gW2FyZ3MuYWZ0ZXJBcHBseV0gLSBEb21haW4gdGFpbDsgaXRzIHJldHVybmVkIG9iamVjdCBtZXJnZXMgaW50byB0aGUgYXBwbHkgcmVzdWx0LlxuICAgKiBAcGFyYW0geyhhcmdzOiB7bXV0YXRpb246ID8sIGNvbnRleHQ6IFJlY29yZDxzdHJpbmcsID8+LCByZWNvcmQ6ID99KSA9PiBQcm9taXNlPFJlY29yZDxzdHJpbmcsID8+PiB8IFJlY29yZDxzdHJpbmcsID8+fSBbYXJncy5zZXJpYWxpemVdIC0gU25hcHNob3Qgc2VyaWFsaXplcjsgcmVzdWx0IGxhbmRzIG9uIGFwcGx5UmVzdWx0LnNlcmlhbGl6ZWREYXRhLlxuICAgKi9cbiAgY29uc3RydWN0b3Ioe2FmdGVyQXBwbHksIGZpZWxkcywgZmluZFJlY29yZCwgZmluZFJlY29yZEZvckRlbGV0ZSwgbW9kZWxDbGFzcywgcmVzdEFyZ3MgPSBcImVycm9yXCIsIHNlcmlhbGl6ZX0pIHtcbiAgICBpZiAoIW1vZGVsQ2xhc3MpIHRocm93IG5ldyBFcnJvcihcIlN5bmNSZXBsYXlVcHNlcnRBcHBsaWVyIHJlcXVpcmVzIGEgbW9kZWxDbGFzc1wiKVxuICAgIGlmICghZmllbGRzIHx8IHR5cGVvZiBmaWVsZHMgIT09IFwib2JqZWN0XCIpIHRocm93IG5ldyBFcnJvcihcIlN5bmNSZXBsYXlVcHNlcnRBcHBsaWVyIHJlcXVpcmVzIGEgZmllbGRzIG1hcFwiKVxuICAgIGlmIChyZXN0QXJncyAhPT0gXCJlcnJvclwiICYmIHJlc3RBcmdzICE9PSBcImlnbm9yZVwiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFN5bmNSZXBsYXlVcHNlcnRBcHBsaWVyIHJlc3RBcmdzIG11c3QgYmUgXCJlcnJvclwiIG9yIFwiaWdub3JlXCIsIGdvdDogJHtTdHJpbmcocmVzdEFyZ3MpfWApXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBbZmllbGROYW1lLCBmaWVsZFNwZWNdIG9mIE9iamVjdC5lbnRyaWVzKGZpZWxkcykpIHtcbiAgICAgIGlmICh0eXBlb2YgZmllbGRTcGVjID09PSBcImZ1bmN0aW9uXCIpIGNvbnRpbnVlXG5cbiAgICAgIGNvbnN0IGZpZWxkVHlwZSA9IHR5cGVvZiBmaWVsZFNwZWMgPT09IFwic3RyaW5nXCIgPyBmaWVsZFNwZWMgOiBmaWVsZFNwZWMudHlwZVxuXG4gICAgICBpZiAoZmllbGRUeXBlICE9PSBcImlnbm9yZWRcIiAmJiAhKGZpZWxkVHlwZSBpbiBGSUVMRF9UWVBFUykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHN5bmMgZmllbGQgdHlwZTogJHtmaWVsZFR5cGV9IGZvcjogJHtmaWVsZE5hbWV9YClcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmFmdGVyQXBwbHkgPSBhZnRlckFwcGx5XG4gICAgdGhpcy5maWVsZHMgPSBmaWVsZHNcbiAgICB0aGlzLmZpbmRSZWNvcmQgPSBmaW5kUmVjb3JkXG4gICAgdGhpcy5maW5kUmVjb3JkRm9yRGVsZXRlID0gZmluZFJlY29yZEZvckRlbGV0ZVxuICAgIHRoaXMubW9kZWxDbGFzcyA9IG1vZGVsQ2xhc3NcbiAgICB0aGlzLnJlc3RBcmdzID0gcmVzdEFyZ3NcbiAgICB0aGlzLnNlcmlhbGl6ZSA9IHNlcmlhbGl6ZVxuICB9XG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgb25lIG5vcm1hbGl6ZWQgcmVwbGF5IG11dGF0aW9uIHRvIHRoZSBkZWNsYXJlZCBtb2RlbC5cbiAgICogQHBhcmFtIHt7YWN0b3I6ID8sIGNvbnRleHQ6IFJlY29yZDxzdHJpbmcsID8+LCBleGlzdGluZ1N5bmM6ID8sIG11dGF0aW9uOiA/fX0gYXJncyAtIFJlcGxheSBhcHBseSBhcmd1bWVudHMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsID8+Pn0gQXBwbHkgcmVzdWx0IHdpdGggdGhlIHJlY29yZCwgY3JlYXRlZC9kZWxldGVkIGZsYWdzLCBvcHRpb25hbCBzZXJpYWxpemVkRGF0YSwgYW5kIGFmdGVyQXBwbHkgZXh0cmFzLlxuICAgKi9cbiAgYXN5bmMgYXBwbHkoe2NvbnRleHQsIG11dGF0aW9ufSkge1xuICAgIGlmIChtdXRhdGlvbi5zeW5jVHlwZSA9PT0gXCJkZWxldGVcIikgcmV0dXJuIGF3YWl0IHRoaXMuYXBwbHlEZWxldGUoe2NvbnRleHQsIG11dGF0aW9ufSlcblxuICAgIGNvbnN0IG1hcHBlZEF0dHJpYnV0ZXMgPSB0aGlzLm1hcHBlZEF0dHJpYnV0ZXMobXV0YXRpb24uZGF0YSlcbiAgICBjb25zdCByZWNvcmQgPSB0aGlzLmZpbmRSZWNvcmRcbiAgICAgID8gYXdhaXQgdGhpcy5maW5kUmVjb3JkKHtjb250ZXh0LCBkYXRhOiBtdXRhdGlvbi5kYXRhLCBtdXRhdGlvbn0pXG4gICAgICA6IGF3YWl0IHRoaXMubW9kZWxDbGFzcy5maW5kQnkoe2lkOiBtdXRhdGlvbi5yZXNvdXJjZUlkfSlcbiAgICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsID8+fSAqL1xuICAgIGNvbnN0IHJlc3VsdCA9IHtjcmVhdGVkOiBmYWxzZSwgZGVsZXRlZDogZmFsc2UsIHJlY29yZDogbnVsbH1cblxuICAgIGlmIChyZWNvcmQpIHtcbiAgICAgIHJlY29yZC5hc3NpZ24obWFwcGVkQXR0cmlidXRlcylcbiAgICAgIGF3YWl0IHJlY29yZC5zYXZlKClcbiAgICAgIHJlc3VsdC5yZWNvcmQgPSByZWNvcmRcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0LnJlY29yZCA9IGF3YWl0IHRoaXMubW9kZWxDbGFzcy5jcmVhdGUoe2lkOiBtdXRhdGlvbi5yZXNvdXJjZUlkLCAuLi5tYXBwZWRBdHRyaWJ1dGVzfSlcbiAgICAgIHJlc3VsdC5jcmVhdGVkID0gdHJ1ZVxuICAgIH1cblxuICAgIGlmICh0aGlzLnNlcmlhbGl6ZSkgcmVzdWx0LnNlcmlhbGl6ZWREYXRhID0gYXdhaXQgdGhpcy5zZXJpYWxpemUoe2NvbnRleHQsIG11dGF0aW9uLCByZWNvcmQ6IHJlc3VsdC5yZWNvcmR9KVxuXG4gICAgaWYgKHRoaXMuYWZ0ZXJBcHBseSkge1xuICAgICAgY29uc3QgYWZ0ZXJBcHBseVJlc3VsdCA9IGF3YWl0IHRoaXMuYWZ0ZXJBcHBseSh7Y29udGV4dCwgbWFwcGVkQXR0cmlidXRlcywgbXV0YXRpb24sIHJlY29yZDogcmVzdWx0LnJlY29yZH0pXG5cbiAgICAgIGlmIChhZnRlckFwcGx5UmVzdWx0ICYmIHR5cGVvZiBhZnRlckFwcGx5UmVzdWx0ID09PSBcIm9iamVjdFwiKSBPYmplY3QuYXNzaWduKHJlc3VsdCwgYWZ0ZXJBcHBseVJlc3VsdClcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyBhIGRlbGV0ZSBtdXRhdGlvbiB0byB0aGUgZGVjbGFyZWQgbW9kZWwuXG4gICAqIEBwYXJhbSB7e2NvbnRleHQ6IFJlY29yZDxzdHJpbmcsID8+LCBtdXRhdGlvbjogP319IGFyZ3MgLSBEZWxldGUgYXJndW1lbnRzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCA/Pj59IEFwcGx5IHJlc3VsdCB3aXRoIHRoZSBkZWxldGVkIGZsYWcuXG4gICAqL1xuICBhc3luYyBhcHBseURlbGV0ZSh7Y29udGV4dCwgbXV0YXRpb259KSB7XG4gICAgY29uc3QgcmVzb2x2ZVJlY29yZCA9IHRoaXMuZmluZFJlY29yZEZvckRlbGV0ZSB8fCB0aGlzLmZpbmRSZWNvcmRcbiAgICBjb25zdCByZWNvcmQgPSByZXNvbHZlUmVjb3JkXG4gICAgICA/IGF3YWl0IHJlc29sdmVSZWNvcmQoe2NvbnRleHQsIGRhdGE6IG11dGF0aW9uLmRhdGEsIG11dGF0aW9ufSlcbiAgICAgIDogYXdhaXQgdGhpcy5tb2RlbENsYXNzLmZpbmRCeSh7aWQ6IG11dGF0aW9uLnJlc291cmNlSWR9KVxuXG4gICAgaWYgKCFyZWNvcmQpIHJldHVybiB7Y3JlYXRlZDogZmFsc2UsIGRlbGV0ZWQ6IGZhbHNlLCByZWNvcmQ6IG51bGx9XG5cbiAgICBhd2FpdCByZWNvcmQuZGVzdHJveSgpXG5cbiAgICByZXR1cm4ge2NyZWF0ZWQ6IGZhbHNlLCBkZWxldGVkOiB0cnVlLCByZWNvcmR9XG4gIH1cblxuICAvKipcbiAgICogTWFwcyBwcmVzZW50IGRhdGEga2V5cyB0aHJvdWdoIHRoZSBkZWNsYXJlZCBmaWVsZCB0eXBlcy5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gZGF0YSAtIE5vcm1hbGl6ZWQgbXV0YXRpb24gZGF0YS5cbiAgICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsID8+fSBDb2VyY2VkIGF0dHJpYnV0ZXMga2V5ZWQgYnkgY29sdW1uIG5hbWUuXG4gICAqL1xuICBtYXBwZWRBdHRyaWJ1dGVzKGRhdGEpIHtcbiAgICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsID8+fSAqL1xuICAgIGNvbnN0IG1hcHBlZEF0dHJpYnV0ZXMgPSB7fVxuICAgIC8qKiBAdHlwZSB7c3RyaW5nW119ICovXG4gICAgY29uc3QgdW5rbm93bktleXMgPSBbXVxuXG4gICAgZm9yIChjb25zdCBbZGF0YUtleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGRhdGEpKSB7XG4gICAgICBjb25zdCBmaWVsZFNwZWMgPSB0aGlzLmZpZWxkc1tkYXRhS2V5XVxuXG4gICAgICBpZiAoIWZpZWxkU3BlYykge1xuICAgICAgICB1bmtub3duS2V5cy5wdXNoKGRhdGFLZXkpXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgZmllbGRTcGVjID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgbWFwcGVkQXR0cmlidXRlc1tkYXRhS2V5XSA9IGZpZWxkU3BlYyh2YWx1ZSwgZGF0YUtleSlcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgY29uc3QgZmllbGRUeXBlID0gdHlwZW9mIGZpZWxkU3BlYyA9PT0gXCJzdHJpbmdcIiA/IGZpZWxkU3BlYyA6IGZpZWxkU3BlYy50eXBlXG5cbiAgICAgIGlmIChmaWVsZFR5cGUgPT09IFwiaWdub3JlZFwiKSBjb250aW51ZVxuXG4gICAgICBjb25zdCBjb2x1bW4gPSB0eXBlb2YgZmllbGRTcGVjID09PSBcInN0cmluZ1wiID8gZGF0YUtleSA6IGZpZWxkU3BlYy5jb2x1bW4gfHwgZGF0YUtleVxuXG4gICAgICBtYXBwZWRBdHRyaWJ1dGVzW2NvbHVtbl0gPSBGSUVMRF9UWVBFU1tmaWVsZFR5cGVdKHZhbHVlLCBkYXRhS2V5KVxuICAgIH1cblxuICAgIGlmICh1bmtub3duS2V5cy5sZW5ndGggPiAwICYmIHRoaXMucmVzdEFyZ3MgPT09IFwiZXJyb3JcIikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHN5bmMgZGF0YSBrZXlzOiAke3Vua25vd25LZXlzLmpvaW4oXCIsIFwiKX1gKVxuICAgIH1cblxuICAgIHJldHVybiBtYXBwZWRBdHRyaWJ1dGVzXG4gIH1cbn1cbiJdfQ==
|
|
@@ -14,6 +14,54 @@
|
|
|
14
14
|
* @augments {FrontendModelBaseResource<TModelClass>}
|
|
15
15
|
*/
|
|
16
16
|
export default class SyncResourceBase<TModelClass extends typeof import("../database/record/index.js").default = typeof import("../database/record/index.js").default> extends FrontendModelBaseResource<TModelClass> {
|
|
17
|
+
/**
|
|
18
|
+
* Declarative quick-search text columns. When declared, an index search on
|
|
19
|
+
* the pseudo-column `quickSearch` expands to an OR of LIKE conditions over
|
|
20
|
+
* these root-table columns instead of hitting the controller default.
|
|
21
|
+
* @type {string[] | null} */
|
|
22
|
+
static quickSearchColumns: string[] | null;
|
|
23
|
+
/**
|
|
24
|
+
* Declarative writable-attribute schema consumed by
|
|
25
|
+
* {@link SyncResourceBase#normalizeWritableAttributes}, keyed by camelCase
|
|
26
|
+
* attribute name.
|
|
27
|
+
* @type {Record<string, import("./sync-attribute-normalizer.js").SyncAttributeSchemaEntry> | null} */
|
|
28
|
+
static writableAttributes: Record<string, import("./sync-attribute-normalizer.js").SyncAttributeSchemaEntry> | null;
|
|
29
|
+
/**
|
|
30
|
+
* Expands a `quickSearch` pseudo-column search into an OR of LIKE conditions
|
|
31
|
+
* over the declared {@link SyncResourceBase.quickSearchColumns}.
|
|
32
|
+
* @param {object} args - Search args.
|
|
33
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceAnyQuery} args.query - Query to filter.
|
|
34
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch} args.search - Search payload.
|
|
35
|
+
* @returns {boolean} Whether the search was handled as a quick search.
|
|
36
|
+
*/
|
|
37
|
+
applyQuickSearch({ query, search }: {
|
|
38
|
+
query: import("../frontend-model-resource/base-resource.js").FrontendModelResourceAnyQuery;
|
|
39
|
+
search: import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch;
|
|
40
|
+
}): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Normalizes incoming writable attributes through the declared
|
|
43
|
+
* {@link SyncResourceBase.writableAttributes} schema: camelCase and
|
|
44
|
+
* snake_case input keys are accepted, values are validated per type and the
|
|
45
|
+
* normalized values are written under snake_case column keys. Validation
|
|
46
|
+
* failures throw client-safe errors built by
|
|
47
|
+
* {@link SyncResourceBase#writableAttributeError}.
|
|
48
|
+
* @param {Record<string, ?>} attributes - Raw incoming attributes.
|
|
49
|
+
* @param {{unknownAttributes?: "error" | "ignore"}} [options] - Unknown input-key handling. Defaults to "error".
|
|
50
|
+
* @returns {Record<string, ?>} Normalized attributes keyed by column names.
|
|
51
|
+
*/
|
|
52
|
+
normalizeWritableAttributes(attributes: Record<string, unknown>, options?: {
|
|
53
|
+
unknownAttributes?: "error" | "ignore";
|
|
54
|
+
}): Record<string, unknown>;
|
|
55
|
+
/**
|
|
56
|
+
* Builds the client-safe error thrown for a failed writable-attribute validation.
|
|
57
|
+
* @param {string} message - Human-readable validation message.
|
|
58
|
+
* @param {{cause?: Error, code: string}} details - Stable machine-readable code and optional cause.
|
|
59
|
+
* @returns {Error} Client-safe error.
|
|
60
|
+
*/
|
|
61
|
+
writableAttributeError(message: string, { cause, code }: {
|
|
62
|
+
cause?: Error;
|
|
63
|
+
code: string;
|
|
64
|
+
}): Error;
|
|
17
65
|
/**
|
|
18
66
|
* Returns a stable change-feed page after app authorization.
|
|
19
67
|
* @returns {Promise<Record<string, ?>>} Change-feed page result.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-resource-base.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-resource-base.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sync-resource-base.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-resource-base.js"],"names":[],"mappings":"AAWA;;;;;GAKG;AAEH;;;;;;;;GAQG;AACH,sCAHqE,WAAW,SAAnE,cAAe,6BAA6B,EAAE,OAAQ;IAIjE;;;;iCAI6B;IAC7B,2BADU,MAAM,EAAE,GAAG,IAAI,CACO;IAEhC;;;;0GAIsG;IACtG,2BADU,MAAM,CAAC,MAAM,EAAE,OAAO,gCAAgC,EAAE,wBAAwB,CAAC,GAAG,IAAI,CAClE;IAgBhC;;;;;;;OAOG;IACH,oCAJG;QAAkG,KAAK,EAA/F,OAAO,6CAA6C,EAAE,6BAA6B;QACK,MAAM,EAA9F,OAAO,6CAA6C,EAAE,2BAA2B;KACzF,GAAU,OAAO,CA6BnB;IAED;;;;;;;;;;OAUG;IACH,wCAJW,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,YACjB;QAAC,iBAAiB,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;KAAC,GACtC,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAa7B;IAED;;;;;OAKG;IACH,gCAJW,MAAM,mBACN;QAAC,KAAK,CAAC,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,GAC3B,KAAK,CAIjB;IAED;;;OAGG;IACH,WAFa,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC,CAStC;IAED;;;OAGG;IACH,UAFa,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC,CAQtC;IAED;;;;OAIG;IACH,qBAHW,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,GACf,sBAAsB,GAAG,IAAI,CAoBzC;IAED;;;;OAIG;IACH,qCAHW;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC;QAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAAA;KAAC,GAC/D;QAAC,OAAO,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC,CAAA;KAAC,CAQvD;IAED;;;OAGG;IACH,sBAFa,OAAO,mCAAmC,EAAE,OAAO,CAM/D;IAED;;;OAGG;IACH,qBAFa,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAI7B;IAED;;;OAGG;IACH,kBAFa,cAAc,6BAA6B,EAAE,OAAO,CAQhE;IAED;;;;OAIG;IACH,wBAHW;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC;QAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAAA;KAAC,GAC/D,OAAO,CAAC,IAAI,CAAC,CAIzB;IAED;;;;OAIG;IACH,yBAHW;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC;QAAC,KAAK,EAAE,OAAO,wCAAwC,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAAA;KAAC,GAChI,IAAI,CAIhB;IAED;;;OAGG;IACH,sBAFa,cAAc,mCAAmC,EAAE,OAAO,CAItE;CACF;;;;;;;;gBAvOa,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC;;;;kBACjB,MAAM;;sCAXkB,6CAA6C"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { forcedNonBlankStringParam } from "typanic";
|
|
3
3
|
import FrontendModelBaseResource from "../frontend-model-resource/base-resource.js";
|
|
4
|
+
import normalizeAttributesWithSchema from "./sync-attribute-normalizer.js";
|
|
4
5
|
import SyncModelChangeFeedService from "./sync-model-change-feed-service.js";
|
|
6
|
+
import VelociousError from "../velocious-error.js";
|
|
7
|
+
const QUICK_SEARCH_COLUMN = "quickSearch";
|
|
5
8
|
/**
|
|
6
9
|
* Optional client-declared sync scope carried on a changes request.
|
|
7
10
|
* @typedef {object} SerializedChangesScope
|
|
@@ -18,6 +21,91 @@ import SyncModelChangeFeedService from "./sync-model-change-feed-service.js";
|
|
|
18
21
|
* @augments {FrontendModelBaseResource<TModelClass>}
|
|
19
22
|
*/
|
|
20
23
|
export default class SyncResourceBase extends FrontendModelBaseResource {
|
|
24
|
+
/**
|
|
25
|
+
* Declarative quick-search text columns. When declared, an index search on
|
|
26
|
+
* the pseudo-column `quickSearch` expands to an OR of LIKE conditions over
|
|
27
|
+
* these root-table columns instead of hitting the controller default.
|
|
28
|
+
* @type {string[] | null} */
|
|
29
|
+
static quickSearchColumns = null;
|
|
30
|
+
/**
|
|
31
|
+
* Declarative writable-attribute schema consumed by
|
|
32
|
+
* {@link SyncResourceBase#normalizeWritableAttributes}, keyed by camelCase
|
|
33
|
+
* attribute name.
|
|
34
|
+
* @type {Record<string, import("./sync-attribute-normalizer.js").SyncAttributeSchemaEntry> | null} */
|
|
35
|
+
static writableAttributes = null;
|
|
36
|
+
/**
|
|
37
|
+
* Applies frontend-model index searches, expanding declared quick searches.
|
|
38
|
+
* @param {object} args - Search args.
|
|
39
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceController} args.controller - Controller handling the query.
|
|
40
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceAnyQuery} args.query - Query instance.
|
|
41
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch} args.search - Search params.
|
|
42
|
+
* @returns {void}
|
|
43
|
+
*/
|
|
44
|
+
applyFrontendModelIndexSearch({ controller, query, search }) {
|
|
45
|
+
if (this.applyQuickSearch({ query, search }))
|
|
46
|
+
return;
|
|
47
|
+
super.applyFrontendModelIndexSearch({ controller, query, search });
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Expands a `quickSearch` pseudo-column search into an OR of LIKE conditions
|
|
51
|
+
* over the declared {@link SyncResourceBase.quickSearchColumns}.
|
|
52
|
+
* @param {object} args - Search args.
|
|
53
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceAnyQuery} args.query - Query to filter.
|
|
54
|
+
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch} args.search - Search payload.
|
|
55
|
+
* @returns {boolean} Whether the search was handled as a quick search.
|
|
56
|
+
*/
|
|
57
|
+
applyQuickSearch({ query, search }) {
|
|
58
|
+
const quickSearchColumns = /** @type {typeof SyncResourceBase} */ (this.constructor).quickSearchColumns;
|
|
59
|
+
if (!quickSearchColumns || quickSearchColumns.length === 0)
|
|
60
|
+
return false;
|
|
61
|
+
if (search.path.length > 0 || search.column !== QUICK_SEARCH_COLUMN)
|
|
62
|
+
return false;
|
|
63
|
+
if (search.operator !== "like") {
|
|
64
|
+
throw VelociousError.safe("Sync quick search must use the like operator.", { code: "sync-invalid-quick-search" });
|
|
65
|
+
}
|
|
66
|
+
if (typeof search.value !== "string") {
|
|
67
|
+
throw VelociousError.safe("Sync quick search must be a string.", { code: "sync-invalid-quick-search" });
|
|
68
|
+
}
|
|
69
|
+
const trimmedValue = search.value.trim();
|
|
70
|
+
if (!trimmedValue)
|
|
71
|
+
return true;
|
|
72
|
+
const tableSql = query.driver.quoteTable(query.getTableReferenceForJoin());
|
|
73
|
+
const likeValue = `%${trimmedValue}%`;
|
|
74
|
+
const conditions = quickSearchColumns.map((columnName) => (`${tableSql}.${query.driver.quoteColumn(columnName)} LIKE ${query.driver.quote(likeValue)}`));
|
|
75
|
+
query.where(`(${conditions.join(" OR ")})`);
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Normalizes incoming writable attributes through the declared
|
|
80
|
+
* {@link SyncResourceBase.writableAttributes} schema: camelCase and
|
|
81
|
+
* snake_case input keys are accepted, values are validated per type and the
|
|
82
|
+
* normalized values are written under snake_case column keys. Validation
|
|
83
|
+
* failures throw client-safe errors built by
|
|
84
|
+
* {@link SyncResourceBase#writableAttributeError}.
|
|
85
|
+
* @param {Record<string, ?>} attributes - Raw incoming attributes.
|
|
86
|
+
* @param {{unknownAttributes?: "error" | "ignore"}} [options] - Unknown input-key handling. Defaults to "error".
|
|
87
|
+
* @returns {Record<string, ?>} Normalized attributes keyed by column names.
|
|
88
|
+
*/
|
|
89
|
+
normalizeWritableAttributes(attributes, options = {}) {
|
|
90
|
+
const schema = /** @type {typeof SyncResourceBase} */ (this.constructor).writableAttributes;
|
|
91
|
+
if (!schema)
|
|
92
|
+
throw new Error(`${this.constructor.name} must define static writableAttributes to use normalizeWritableAttributes`);
|
|
93
|
+
return normalizeAttributesWithSchema({
|
|
94
|
+
attributes,
|
|
95
|
+
errorFactory: (message, details) => this.writableAttributeError(message, details),
|
|
96
|
+
schema,
|
|
97
|
+
unknownAttributes: options.unknownAttributes
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Builds the client-safe error thrown for a failed writable-attribute validation.
|
|
102
|
+
* @param {string} message - Human-readable validation message.
|
|
103
|
+
* @param {{cause?: Error, code: string}} details - Stable machine-readable code and optional cause.
|
|
104
|
+
* @returns {Error} Client-safe error.
|
|
105
|
+
*/
|
|
106
|
+
writableAttributeError(message, { cause, code }) {
|
|
107
|
+
return VelociousError.safe(message, cause ? { cause, code } : { code });
|
|
108
|
+
}
|
|
21
109
|
/**
|
|
22
110
|
* Returns a stable change-feed page after app authorization.
|
|
23
111
|
* @returns {Promise<Record<string, ?>>} Change-feed page result.
|
|
@@ -119,4 +207,4 @@ export default class SyncResourceBase extends FrontendModelBaseResource {
|
|
|
119
207
|
throw new Error("SyncResourceBase#replayServiceClass must be implemented");
|
|
120
208
|
}
|
|
121
209
|
}
|
|
122
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1yZXNvdXJjZS1iYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N5bmMvc3luYy1yZXNvdXJjZS1iYXNlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEVBQUMseUJBQXlCLEVBQUMsTUFBTSxTQUFTLENBQUE7QUFFakQsT0FBTyx5QkFBeUIsTUFBTSw2Q0FBNkMsQ0FBQTtBQUNuRixPQUFPLDBCQUEwQixNQUFNLHFDQUFxQyxDQUFBO0FBRTVFOzs7OztHQUtHO0FBRUg7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLGdCQUFpQixTQUFRLHlCQUF5QjtJQUNyRTs7O09BR0c7SUFDSCxLQUFLLENBQUMsT0FBTztRQUNYLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQTtRQUM1QixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBRXZDLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLEVBQUMsTUFBTSxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUE7UUFFNUMsT0FBTyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxFQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFBO0lBQ2hFLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsTUFBTTtRQUNWLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFBO1FBRXBFLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxPQUFPO1lBQUUsT0FBTyxNQUFNLENBQUE7UUFFNUMsT0FBTyxFQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLLEVBQUMsQ0FBQTtJQUNqRCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILFlBQVksQ0FBQyxNQUFNO1FBQ2pCLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUE7UUFFMUIsSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssS0FBSyxJQUFJO1lBQUUsT0FBTyxJQUFJLENBQUE7UUFFdEQsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3RELE1BQU0sSUFBSSxLQUFLLENBQUMsOENBQThDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDaEYsQ0FBQztRQUVELE1BQU0sV0FBVyxHQUFHLGdDQUFnQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDNUQsTUFBTSxZQUFZLEdBQUcseUJBQXlCLENBQUMsV0FBVyxFQUFFLGNBQWMsQ0FBQyxDQUFBO1FBQzNFLE1BQU0sVUFBVSxHQUFHLFdBQVcsQ0FBQyxVQUFVLENBQUE7UUFFekMsSUFBSSxDQUFDLFVBQVUsSUFBSSxPQUFPLFVBQVUsS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQy9FLE1BQU0sSUFBSSxLQUFLLENBQUMseURBQXlELE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDaEcsQ0FBQztRQUVELE9BQU8sRUFBQyxVQUFVLEVBQUUsZ0NBQWdDLENBQUMsQ0FBQyxVQUFVLENBQUMsRUFBRSxZQUFZLEVBQUMsQ0FBQTtJQUNsRixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGlCQUFpQixDQUFDLEVBQUMsTUFBTSxFQUFFLEtBQUssRUFBQztRQUMvQixPQUFPLElBQUksMEJBQTBCLENBQUM7WUFDcEMsVUFBVSxFQUFFLElBQUksQ0FBQyxjQUFjLEVBQUU7WUFDakMsTUFBTTtZQUNOLFVBQVUsRUFBRSxDQUFDLEVBQUMsS0FBSyxFQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxFQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFDLENBQUM7U0FDeEUsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOzs7T0FHRztJQUNILGtCQUFrQjtRQUNoQixNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFBO1FBRXBELE9BQU8sSUFBSSxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxDQUFBO0lBQ3pELENBQUM7SUFFRDs7O09BR0c7SUFDSCxpQkFBaUI7UUFDZixPQUFPLEVBQUUsQ0FBQTtJQUNYLENBQUM7SUFFRDs7O09BR0c7SUFDSCxjQUFjO1FBQ1osTUFBTSxVQUFVLEdBQUcsc0NBQXNDLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsVUFBVSxDQUFBO1FBRXZGLElBQUksQ0FBQyxVQUFVO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxnQ0FBZ0MsQ0FBQyxDQUFBO1FBRTFGLE9BQU8sVUFBVSxDQUFBO0lBQ25CLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLGdCQUFnQixDQUFDLEtBQUs7UUFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyx1REFBdUQsQ0FBQyxDQUFBO0lBQzFFLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsaUJBQWlCLENBQUMsS0FBSztRQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxDQUFDLENBQUE7SUFDM0UsQ0FBQztJQUVEOzs7T0FHRztJQUNILGtCQUFrQjtRQUNoQixNQUFNLElBQUksS0FBSyxDQUFDLHlEQUF5RCxDQUFDLENBQUE7SUFDNUUsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCB7Zm9yY2VkTm9uQmxhbmtTdHJpbmdQYXJhbX0gZnJvbSBcInR5cGFuaWNcIlxuXG5pbXBvcnQgRnJvbnRlbmRNb2RlbEJhc2VSZXNvdXJjZSBmcm9tIFwiLi4vZnJvbnRlbmQtbW9kZWwtcmVzb3VyY2UvYmFzZS1yZXNvdXJjZS5qc1wiXG5pbXBvcnQgU3luY01vZGVsQ2hhbmdlRmVlZFNlcnZpY2UgZnJvbSBcIi4vc3luYy1tb2RlbC1jaGFuZ2UtZmVlZC1zZXJ2aWNlLmpzXCJcblxuLyoqXG4gKiBPcHRpb25hbCBjbGllbnQtZGVjbGFyZWQgc3luYyBzY29wZSBjYXJyaWVkIG9uIGEgY2hhbmdlcyByZXF1ZXN0LlxuICogQHR5cGVkZWYge29iamVjdH0gU2VyaWFsaXplZENoYW5nZXNTY29wZVxuICogQHByb3BlcnR5IHtSZWNvcmQ8c3RyaW5nLCA/Pn0gY29uZGl0aW9ucyAtIFBsYWluIGF0dHJpYnV0ZSBjb25kaXRpb25zIGZyb20gdGhlIGNsaWVudCBxdWVyeS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSByZXNvdXJjZVR5cGUgLSBDbGllbnQgcmVzb3VyY2UvbW9kZWwgbmFtZSB0aGUgc2NvcGUgd2FzIGRlY2xhcmVkIGZvci5cbiAqL1xuXG4vKipcbiAqIEJhc2UgcmVzb3VyY2UgZm9yIFZlbG9jaW91cyBzeW5jIGVuZHBvaW50cy5cbiAqXG4gKiBWZWxvY2lvdXMgb3ducyB0aGUgY2hhbmdlcy9yZXBsYXkgb3JjaGVzdHJhdGlvbiAoc2NvcGUgcGFyc2luZywgZmVlZCBwYWdpbmcsXG4gKiByZXBsYXkgZGVsZWdhdGlvbiwgcmVzcG9uc2Ugc2hhcGUpIHdoaWxlIGFwcHMgc3ViY2xhc3MgYW5kIG9ubHkgZGVjbGFyZVxuICogYXV0aG9yaXphdGlvbiwgZmVlZCBzY29waW5nLCBhbmQgdGhlaXIgcmVwbGF5IHNlcnZpY2UuXG4gKiBAdGVtcGxhdGUge3R5cGVvZiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdH0gW1RNb2RlbENsYXNzPXR5cGVvZiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdF1cbiAqIEBhdWdtZW50cyB7RnJvbnRlbmRNb2RlbEJhc2VSZXNvdXJjZTxUTW9kZWxDbGFzcz59XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN5bmNSZXNvdXJjZUJhc2UgZXh0ZW5kcyBGcm9udGVuZE1vZGVsQmFzZVJlc291cmNlIHtcbiAgLyoqXG4gICAqIFJldHVybnMgYSBzdGFibGUgY2hhbmdlLWZlZWQgcGFnZSBhZnRlciBhcHAgYXV0aG9yaXphdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8UmVjb3JkPHN0cmluZywgPz4+fSBDaGFuZ2UtZmVlZCBwYWdlIHJlc3VsdC5cbiAgICovXG4gIGFzeW5jIGNoYW5nZXMoKSB7XG4gICAgY29uc3QgcGFyYW1zID0gdGhpcy5wYXJhbXMoKVxuICAgIGNvbnN0IHNjb3BlID0gdGhpcy5jaGFuZ2VzU2NvcGUocGFyYW1zKVxuXG4gICAgYXdhaXQgdGhpcy5hdXRob3JpemVDaGFuZ2VzKHtwYXJhbXMsIHNjb3BlfSlcblxuICAgIHJldHVybiBhd2FpdCB0aGlzLmNoYW5nZUZlZWRTZXJ2aWNlKHtwYXJhbXMsIHNjb3BlfSkuY2hhbmdlcygpXG4gIH1cblxuICAvKipcbiAgICogUmVwbGF5cyBjbGllbnQgc3luYyBlbnZlbG9wZXMgdGhyb3VnaCB0aGUgYXBwIHJlcGxheSBzZXJ2aWNlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCA/Pj59IFJlcGxheSByZXN1bHQgd2l0aCBwZXItc3luYyBzdGF0ZXMuXG4gICAqL1xuICBhc3luYyByZXBsYXkoKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5idWlsZFJlcGxheVNlcnZpY2UoKS5yZXBsYXkodGhpcy5wYXJhbXMoKSlcblxuICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSBcImVycm9yXCIpIHJldHVybiByZXN1bHRcblxuICAgIHJldHVybiB7c3RhdHVzOiBcInN1Y2Nlc3NcIiwgc3luY3M6IHJlc3VsdC5zeW5jc31cbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZXMgdGhlIG9wdGlvbmFsIGNsaWVudC1kZWNsYXJlZCBzY29wZSBmcm9tIHJlcXVlc3QgcGFyYW1zLlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsID8+fSBwYXJhbXMgLSBSZXF1ZXN0IHBhcmFtcy5cbiAgICogQHJldHVybnMge1NlcmlhbGl6ZWRDaGFuZ2VzU2NvcGUgfCBudWxsfSBQYXJzZWQgc2NvcGUsIG9yIG51bGwgd2hlbiB0aGUgY2xpZW50IHNlbnQgbm9uZS5cbiAgICovXG4gIGNoYW5nZXNTY29wZShwYXJhbXMpIHtcbiAgICBjb25zdCBzY29wZSA9IHBhcmFtcy5zY29wZVxuXG4gICAgaWYgKHNjb3BlID09PSB1bmRlZmluZWQgfHwgc2NvcGUgPT09IG51bGwpIHJldHVybiBudWxsXG5cbiAgICBpZiAodHlwZW9mIHNjb3BlICE9PSBcIm9iamVjdFwiIHx8IEFycmF5LmlzQXJyYXkoc2NvcGUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFN5bmMgY2hhbmdlcyBzY29wZSBtdXN0IGJlIGFuIG9iamVjdCwgZ290OiAke1N0cmluZyhzY29wZSl9YClcbiAgICB9XG5cbiAgICBjb25zdCBzY29wZVBhcmFtcyA9IC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgPz59ICovIChzY29wZSlcbiAgICBjb25zdCByZXNvdXJjZVR5cGUgPSBmb3JjZWROb25CbGFua1N0cmluZ1BhcmFtKHNjb3BlUGFyYW1zLCBcInJlc291cmNlVHlwZVwiKVxuICAgIGNvbnN0IGNvbmRpdGlvbnMgPSBzY29wZVBhcmFtcy5jb25kaXRpb25zXG5cbiAgICBpZiAoIWNvbmRpdGlvbnMgfHwgdHlwZW9mIGNvbmRpdGlvbnMgIT09IFwib2JqZWN0XCIgfHwgQXJyYXkuaXNBcnJheShjb25kaXRpb25zKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBTeW5jIGNoYW5nZXMgc2NvcGUuY29uZGl0aW9ucyBtdXN0IGJlIGFuIG9iamVjdCwgZ290OiAke1N0cmluZyhjb25kaXRpb25zKX1gKVxuICAgIH1cblxuICAgIHJldHVybiB7Y29uZGl0aW9uczogLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi8gKGNvbmRpdGlvbnMpLCByZXNvdXJjZVR5cGV9XG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIHRoZSBjaGFuZ2UtZmVlZCBzZXJ2aWNlIHNlcnZpbmcgdGhpcyBjaGFuZ2VzIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7e3BhcmFtczogUmVjb3JkPHN0cmluZywgPz4sIHNjb3BlOiBTZXJpYWxpemVkQ2hhbmdlc1Njb3BlIHwgbnVsbH19IGFyZ3MgLSBSZXF1ZXN0IHBhcmFtcyBhbmQgcGFyc2VkIHNjb3BlLlxuICAgKiBAcmV0dXJucyB7e2NoYW5nZXM6ICgpID0+IFByb21pc2U8UmVjb3JkPHN0cmluZywgPz4+fX0gQ2hhbmdlLWZlZWQgc2VydmljZS5cbiAgICovXG4gIGNoYW5nZUZlZWRTZXJ2aWNlKHtwYXJhbXMsIHNjb3BlfSkge1xuICAgIHJldHVybiBuZXcgU3luY01vZGVsQ2hhbmdlRmVlZFNlcnZpY2Uoe1xuICAgICAgbW9kZWxDbGFzczogdGhpcy5zeW5jTW9kZWxDbGFzcygpLFxuICAgICAgcGFyYW1zLFxuICAgICAgc2NvcGVRdWVyeTogKHtxdWVyeX0pID0+IHRoaXMuc2NvcGVDaGFuZ2VzUXVlcnkoe3BhcmFtcywgcXVlcnksIHNjb3BlfSlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgYXBwIHJlcGxheSBzZXJ2aWNlIGhhbmRsaW5nIHRoaXMgcmVwbGF5IHJlcXVlc3QuXG4gICAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3N5bmMtZW52ZWxvcGUtcmVwbGF5LXNlcnZpY2UuanNcIikuZGVmYXVsdH0gUmVwbGF5IHNlcnZpY2UgaW5zdGFuY2UuXG4gICAqL1xuICBidWlsZFJlcGxheVNlcnZpY2UoKSB7XG4gICAgY29uc3QgUmVwbGF5U2VydmljZUNsYXNzID0gdGhpcy5yZXBsYXlTZXJ2aWNlQ2xhc3MoKVxuXG4gICAgcmV0dXJuIG5ldyBSZXBsYXlTZXJ2aWNlQ2xhc3ModGhpcy5yZXBsYXlTZXJ2aWNlQXJncygpKVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgY29uc3RydWN0b3IgYXJncyBmb3IgdGhlIGFwcCByZXBsYXkgc2VydmljZS5cbiAgICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsID8+fSBSZXBsYXkgc2VydmljZSBjb25zdHJ1Y3RvciBhcmdzLlxuICAgKi9cbiAgcmVwbGF5U2VydmljZUFyZ3MoKSB7XG4gICAgcmV0dXJuIHt9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc3luYyBtb2RlbCBjbGFzcyBiYWNraW5nIHRoZSBjaGFuZ2UgZmVlZC5cbiAgICogQHJldHVybnMge3R5cGVvZiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdH0gU3luYyBtb2RlbCBjbGFzcy5cbiAgICovXG4gIHN5bmNNb2RlbENsYXNzKCkge1xuICAgIGNvbnN0IG1vZGVsQ2xhc3MgPSAvKiogQHR5cGUge3R5cGVvZiBTeW5jUmVzb3VyY2VCYXNlfSAqLyAodGhpcy5jb25zdHJ1Y3RvcikuTW9kZWxDbGFzc1xuXG4gICAgaWYgKCFtb2RlbENsYXNzKSB0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5jb25zdHJ1Y3Rvci5uYW1lfSBtdXN0IGRlZmluZSBzdGF0aWMgTW9kZWxDbGFzc2ApXG5cbiAgICByZXR1cm4gbW9kZWxDbGFzc1xuICB9XG5cbiAgLyoqXG4gICAqIEF1dGhvcml6ZXMgdGhlIGN1cnJlbnQgY29udGV4dCBmb3IgcmVhZGluZyB0aGUgcmVxdWVzdGVkIGNoYW5nZXMuXG4gICAqIEBwYXJhbSB7e3BhcmFtczogUmVjb3JkPHN0cmluZywgPz4sIHNjb3BlOiBTZXJpYWxpemVkQ2hhbmdlc1Njb3BlIHwgbnVsbH19IF9hcmdzIC0gUmVxdWVzdCBwYXJhbXMgYW5kIHBhcnNlZCBzY29wZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IFJlc29sdmVzIHdoZW4gYWNjZXNzIGlzIGFsbG93ZWQ7IHRocm93cyBvdGhlcndpc2UuXG4gICAqL1xuICBhc3luYyBhdXRob3JpemVDaGFuZ2VzKF9hcmdzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiU3luY1Jlc291cmNlQmFzZSNhdXRob3JpemVDaGFuZ2VzIG11c3QgYmUgaW1wbGVtZW50ZWRcIilcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBsaWVzIGFwcCB2aXNpYmlsaXR5IHNjb3Bpbmcgb250byB0aGUgY2hhbmdlLWZlZWQgcXVlcnkuXG4gICAqIEBwYXJhbSB7e3BhcmFtczogUmVjb3JkPHN0cmluZywgPz4sIHF1ZXJ5OiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9xdWVyeS9tb2RlbC1jbGFzcy1xdWVyeS5qc1wiKS5kZWZhdWx0LCBzY29wZTogU2VyaWFsaXplZENoYW5nZXNTY29wZSB8IG51bGx9fSBfYXJncyAtIFJlcXVlc3QgcGFyYW1zLCBmZWVkIHF1ZXJ5LCBhbmQgcGFyc2VkIHNjb3BlLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHNjb3BlQ2hhbmdlc1F1ZXJ5KF9hcmdzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiU3luY1Jlc291cmNlQmFzZSNzY29wZUNoYW5nZXNRdWVyeSBtdXN0IGJlIGltcGxlbWVudGVkXCIpXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYXBwIHJlcGxheSBzZXJ2aWNlIGNsYXNzIGhhbmRsaW5nIHJlcGxheSBtdXRhdGlvbnMuXG4gICAqIEByZXR1cm5zIHt0eXBlb2YgaW1wb3J0KFwiLi9zeW5jLWVudmVsb3BlLXJlcGxheS1zZXJ2aWNlLmpzXCIpLmRlZmF1bHR9IFJlcGxheSBzZXJ2aWNlIGNsYXNzLlxuICAgKi9cbiAgcmVwbGF5U2VydmljZUNsYXNzKCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlN5bmNSZXNvdXJjZUJhc2UjcmVwbGF5U2VydmljZUNsYXNzIG11c3QgYmUgaW1wbGVtZW50ZWRcIilcbiAgfVxufVxuIl19
|
|
210
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1yZXNvdXJjZS1iYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N5bmMvc3luYy1yZXNvdXJjZS1iYXNlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEVBQUMseUJBQXlCLEVBQUMsTUFBTSxTQUFTLENBQUE7QUFFakQsT0FBTyx5QkFBeUIsTUFBTSw2Q0FBNkMsQ0FBQTtBQUNuRixPQUFPLDZCQUE2QixNQUFNLGdDQUFnQyxDQUFBO0FBQzFFLE9BQU8sMEJBQTBCLE1BQU0scUNBQXFDLENBQUE7QUFDNUUsT0FBTyxjQUFjLE1BQU0sdUJBQXVCLENBQUE7QUFFbEQsTUFBTSxtQkFBbUIsR0FBRyxhQUFhLENBQUE7QUFFekM7Ozs7O0dBS0c7QUFFSDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sZ0JBQWlCLFNBQVEseUJBQXlCO0lBQ3JFOzs7O2lDQUk2QjtJQUM3QixNQUFNLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFBO0lBRWhDOzs7OzBHQUlzRztJQUN0RyxNQUFNLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFBO0lBRWhDOzs7Ozs7O09BT0c7SUFDSCw2QkFBNkIsQ0FBQyxFQUFDLFVBQVUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFDO1FBQ3ZELElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLEVBQUMsS0FBSyxFQUFFLE1BQU0sRUFBQyxDQUFDO1lBQUUsT0FBTTtRQUVsRCxLQUFLLENBQUMsNkJBQTZCLENBQUMsRUFBQyxVQUFVLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBQyxDQUFDLENBQUE7SUFDbEUsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxnQkFBZ0IsQ0FBQyxFQUFDLEtBQUssRUFBRSxNQUFNLEVBQUM7UUFDOUIsTUFBTSxrQkFBa0IsR0FBRyxzQ0FBc0MsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxrQkFBa0Is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QzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdURBQXVELENBQUMsQ0FBQTtJQUMxRSxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGlCQUFpQixDQUFDLEtBQUs7UUFDckIsTUFBTSxJQUFJLEtBQUssQ0FBQyx3REFBd0QsQ0FBQyxDQUFBO0lBQzNFLENBQUM7SUFFRDs7O09BR0c7SUFDSCxrQkFBa0I7UUFDaEIsTUFBTSxJQUFJLEtBQUssQ0FBQyx5REFBeUQsQ0FBQyxDQUFBO0lBQzVFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtmb3JjZWROb25CbGFua1N0cmluZ1BhcmFtfSBmcm9tIFwidHlwYW5pY1wiXG5cbmltcG9ydCBGcm9udGVuZE1vZGVsQmFzZVJlc291cmNlIGZyb20gXCIuLi9mcm9udGVuZC1tb2RlbC1yZXNvdXJjZS9iYXNlLXJlc291cmNlLmpzXCJcbmltcG9ydCBub3JtYWxpemVBdHRyaWJ1dGVzV2l0aFNjaGVtYSBmcm9tIFwiLi9zeW5jLWF0dHJpYnV0ZS1ub3JtYWxpemVyLmpzXCJcbmltcG9ydCBTeW5jTW9kZWxDaGFuZ2VGZWVkU2VydmljZSBmcm9tIFwiLi9zeW5jLW1vZGVsLWNoYW5nZS1mZWVkLXNlcnZpY2UuanNcIlxuaW1wb3J0IFZlbG9jaW91c0Vycm9yIGZyb20gXCIuLi92ZWxvY2lvdXMtZXJyb3IuanNcIlxuXG5jb25zdCBRVUlDS19TRUFSQ0hfQ09MVU1OID0gXCJxdWlja1NlYXJjaFwiXG5cbi8qKlxuICogT3B0aW9uYWwgY2xpZW50LWRlY2xhcmVkIHN5bmMgc2NvcGUgY2FycmllZCBvbiBhIGNoYW5nZXMgcmVxdWVzdC5cbiAqIEB0eXBlZGVmIHtvYmplY3R9IFNlcmlhbGl6ZWRDaGFuZ2VzU2NvcGVcbiAqIEBwcm9wZXJ0eSB7UmVjb3JkPHN0cmluZywgPz59IGNvbmRpdGlvbnMgLSBQbGFpbiBhdHRyaWJ1dGUgY29uZGl0aW9ucyBmcm9tIHRoZSBjbGllbnQgcXVlcnkuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gcmVzb3VyY2VUeXBlIC0gQ2xpZW50IHJlc291cmNlL21vZGVsIG5hbWUgdGhlIHNjb3BlIHdhcyBkZWNsYXJlZCBmb3IuXG4gKi9cblxuLyoqXG4gKiBCYXNlIHJlc291cmNlIGZvciBWZWxvY2lvdXMgc3luYyBlbmRwb2ludHMuXG4gKlxuICogVmVsb2Npb3VzIG93bnMgdGhlIGNoYW5nZXMvcmVwbGF5IG9yY2hlc3RyYXRpb24gKHNjb3BlIHBhcnNpbmcsIGZlZWQgcGFnaW5nLFxuICogcmVwbGF5IGRlbGVnYXRpb24sIHJlc3BvbnNlIHNoYXBlKSB3aGlsZSBhcHBzIHN1YmNsYXNzIGFuZCBvbmx5IGRlY2xhcmVcbiAqIGF1dGhvcml6YXRpb24sIGZlZWQgc2NvcGluZywgYW5kIHRoZWlyIHJlcGxheSBzZXJ2aWNlLlxuICogQHRlbXBsYXRlIHt0eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9IFtUTW9kZWxDbGFzcz10eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHRdXG4gKiBAYXVnbWVudHMge0Zyb250ZW5kTW9kZWxCYXNlUmVzb3VyY2U8VE1vZGVsQ2xhc3M+fVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTeW5jUmVzb3VyY2VCYXNlIGV4dGVuZHMgRnJvbnRlbmRNb2RlbEJhc2VSZXNvdXJjZSB7XG4gIC8qKlxuICAgKiBEZWNsYXJhdGl2ZSBxdWljay1zZWFyY2ggdGV4dCBjb2x1bW5zLiBXaGVuIGRlY2xhcmVkLCBhbiBpbmRleCBzZWFyY2ggb25cbiAgICogdGhlIHBzZXVkby1jb2x1bW4gYHF1aWNrU2VhcmNoYCBleHBhbmRzIHRvIGFuIE9SIG9mIExJS0UgY29uZGl0aW9ucyBvdmVyXG4gICAqIHRoZXNlIHJvb3QtdGFibGUgY29sdW1ucyBpbnN0ZWFkIG9mIGhpdHRpbmcgdGhlIGNvbnRyb2xsZXIgZGVmYXVsdC5cbiAgICogQHR5cGUge3N0cmluZ1tdIHwgbnVsbH0gKi9cbiAgc3RhdGljIHF1aWNrU2VhcmNoQ29sdW1ucyA9IG51bGxcblxuICAvKipcbiAgICogRGVjbGFyYXRpdmUgd3JpdGFibGUtYXR0cmlidXRlIHNjaGVtYSBjb25zdW1lZCBieVxuICAgKiB7QGxpbmsgU3luY1Jlc291cmNlQmFzZSNub3JtYWxpemVXcml0YWJsZUF0dHJpYnV0ZXN9LCBrZXllZCBieSBjYW1lbENhc2VcbiAgICogYXR0cmlidXRlIG5hbWUuXG4gICAqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBpbXBvcnQoXCIuL3N5bmMtYXR0cmlidXRlLW5vcm1hbGl6ZXIuanNcIikuU3luY0F0dHJpYnV0ZVNjaGVtYUVudHJ5PiB8IG51bGx9ICovXG4gIHN0YXRpYyB3cml0YWJsZUF0dHJpYnV0ZXMgPSBudWxsXG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgZnJvbnRlbmQtbW9kZWwgaW5kZXggc2VhcmNoZXMsIGV4cGFuZGluZyBkZWNsYXJlZCBxdWljayBzZWFyY2hlcy5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBTZWFyY2ggYXJncy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9mcm9udGVuZC1tb2RlbC1yZXNvdXJjZS9iYXNlLXJlc291cmNlLmpzXCIpLkZyb250ZW5kTW9kZWxSZXNvdXJjZUNvbnRyb2xsZXJ9IGFyZ3MuY29udHJvbGxlciAtIENvbnRyb2xsZXIgaGFuZGxpbmcgdGhlIHF1ZXJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Zyb250ZW5kLW1vZGVsLXJlc291cmNlL2Jhc2UtcmVzb3VyY2UuanNcIikuRnJvbnRlbmRNb2RlbFJlc291cmNlQW55UXVlcnl9IGFyZ3MucXVlcnkgLSBRdWVyeSBpbnN0YW5jZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9mcm9udGVuZC1tb2RlbC1yZXNvdXJjZS9iYXNlLXJlc291cmNlLmpzXCIpLkZyb250ZW5kTW9kZWxSZXNvdXJjZVNlYXJjaH0gYXJncy5zZWFyY2ggLSBTZWFyY2ggcGFyYW1zLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGFwcGx5RnJvbnRlbmRNb2RlbEluZGV4U2VhcmNoKHtjb250cm9sbGVyLCBxdWVyeSwgc2VhcmNofSkge1xuICAgIGlmICh0aGlzLmFwcGx5UXVpY2tTZWFyY2goe3F1ZXJ5LCBzZWFyY2h9KSkgcmV0dXJuXG5cbiAgICBzdXBlci5hcHBseUZyb250ZW5kTW9kZWxJbmRleFNlYXJjaCh7Y29udHJvbGxlciwgcXVlcnksIHNlYXJjaH0pXG4gIH1cblxuICAvKipcbiAgICogRXhwYW5kcyBhIGBxdWlja1NlYXJjaGAgcHNldWRvLWNvbHVtbiBzZWFyY2ggaW50byBhbiBPUiBvZiBMSUtFIGNvbmRpdGlvbnNcbiAgICogb3ZlciB0aGUgZGVjbGFyZWQge0BsaW5rIFN5bmNSZXNvdXJjZUJhc2UucXVpY2tTZWFyY2hDb2x1bW5zfS5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBTZWFyY2ggYXJncy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9mcm9udGVuZC1tb2RlbC1yZXNvdXJjZS9iYXNlLXJlc291cmNlLmpzXCIpLkZyb250ZW5kTW9kZWxSZXNvdXJjZUFueVF1ZXJ5fSBhcmdzLnF1ZXJ5IC0gUXVlcnkgdG8gZmlsdGVyLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Zyb250ZW5kLW1vZGVsLXJlc291cmNlL2Jhc2UtcmVzb3VyY2UuanNcIikuRnJvbnRlbmRNb2RlbFJlc291cmNlU2VhcmNofSBhcmdzLnNlYXJjaCAtIFNlYXJjaCBwYXlsb2FkLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgc2VhcmNoIHdhcyBoYW5kbGVkIGFzIGEgcXVpY2sgc2VhcmNoLlxuICAgKi9cbiAgYXBwbHlRdWlja1NlYXJjaCh7cXVlcnksIHNlYXJjaH0pIHtcbiAgICBjb25zdCBxdWlja1NlYXJjaENvbHVtbnMgPSAvKiogQHR5cGUge3R5cGVvZiBTeW5jUmVzb3VyY2VCYXNlfSAqLyAodGhpcy5jb25zdHJ1Y3RvcikucXVpY2tTZWFyY2hDb2x1bW5zXG5cbiAgICBpZiAoIXF1aWNrU2VhcmNoQ29sdW1ucyB8fCBxdWlja1NlYXJjaENvbHVtbnMubGVuZ3RoID09PSAwKSByZXR1cm4gZmFsc2VcbiAgICBpZiAoc2VhcmNoLnBhdGgubGVuZ3RoID4gMCB8fCBzZWFyY2guY29sdW1uICE9PSBRVUlDS19TRUFSQ0hfQ09MVU1OKSByZXR1cm4gZmFsc2VcblxuICAgIGlmIChzZWFyY2gub3BlcmF0b3IgIT09IFwibGlrZVwiKSB7XG4gICAgICB0aHJvdyBWZWxvY2lvdXNFcnJvci5zYWZlKFwiU3luYyBxdWljayBzZWFyY2ggbXVzdCB1c2UgdGhlIGxpa2Ugb3BlcmF0b3IuXCIsIHtjb2RlOiBcInN5bmMtaW52YWxpZC1xdWljay1zZWFyY2hcIn0pXG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBzZWFyY2gudmFsdWUgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgIHRocm93IFZlbG9jaW91c0Vycm9yLnNhZmUoXCJTeW5jIHF1aWNrIHNlYXJjaCBtdXN0IGJlIGEgc3RyaW5nLlwiLCB7Y29kZTogXCJzeW5jLWludmFsaWQtcXVpY2stc2VhcmNoXCJ9KVxuICAgIH1cblxuICAgIGNvbnN0IHRyaW1tZWRWYWx1ZSA9IHNlYXJjaC52YWx1ZS50cmltKClcblxuICAgIGlmICghdHJpbW1lZFZhbHVlKSByZXR1cm4gdHJ1ZVxuXG4gICAgY29uc3QgdGFibGVTcWwgPSBxdWVyeS5kcml2ZXIucXVvdGVUYWJsZShxdWVyeS5nZXRUYWJsZVJlZmVyZW5jZUZvckpvaW4oKSlcbiAgICBjb25zdCBsaWtlVmFsdWUgPSBgJSR7dHJpbW1lZFZhbHVlfSVgXG4gICAgY29uc3QgY29uZGl0aW9ucyA9IHF1aWNrU2VhcmNoQ29sdW1ucy5tYXAoKGNvbHVtbk5hbWUpID0+IChcbiAgICAgIGAke3RhYmxlU3FsfS4ke3F1ZXJ5LmRyaXZlci5xdW90ZUNvbHVtbihjb2x1bW5OYW1lKX0gTElLRSAke3F1ZXJ5LmRyaXZlci5xdW90ZShsaWtlVmFsdWUpfWBcbiAgICApKVxuXG4gICAgcXVlcnkud2hlcmUoYCgke2NvbmRpdGlvbnMuam9pbihcIiBPUiBcIil9KWApXG5cbiAgICByZXR1cm4gdHJ1ZVxuICB9XG5cbiAgLyoqXG4gICAqIE5vcm1hbGl6ZXMgaW5jb21pbmcgd3JpdGFibGUgYXR0cmlidXRlcyB0aHJvdWdoIHRoZSBkZWNsYXJlZFxuICAgKiB7QGxpbmsgU3luY1Jlc291cmNlQmFzZS53cml0YWJsZUF0dHJpYnV0ZXN9IHNjaGVtYTogY2FtZWxDYXNlIGFuZFxuICAgKiBzbmFrZV9jYXNlIGlucHV0IGtleXMgYXJlIGFjY2VwdGVkLCB2YWx1ZXMgYXJlIHZhbGlkYXRlZCBwZXIgdHlwZSBhbmQgdGhlXG4gICAqIG5vcm1hbGl6ZWQgdmFsdWVzIGFyZSB3cml0dGVuIHVuZGVyIHNuYWtlX2Nhc2UgY29sdW1uIGtleXMuIFZhbGlkYXRpb25cbiAgICogZmFpbHVyZXMgdGhyb3cgY2xpZW50LXNhZmUgZXJyb3JzIGJ1aWx0IGJ5XG4gICAqIHtAbGluayBTeW5jUmVzb3VyY2VCYXNlI3dyaXRhYmxlQXR0cmlidXRlRXJyb3J9LlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsID8+fSBhdHRyaWJ1dGVzIC0gUmF3IGluY29taW5nIGF0dHJpYnV0ZXMuXG4gICAqIEBwYXJhbSB7e3Vua25vd25BdHRyaWJ1dGVzPzogXCJlcnJvclwiIHwgXCJpZ25vcmVcIn19IFtvcHRpb25zXSAtIFVua25vd24gaW5wdXQta2V5IGhhbmRsaW5nLiBEZWZhdWx0cyB0byBcImVycm9yXCIuXG4gICAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gTm9ybWFsaXplZCBhdHRyaWJ1dGVzIGtleWVkIGJ5IGNvbHVtbiBuYW1lcy5cbiAgICovXG4gIG5vcm1hbGl6ZVdyaXRhYmxlQXR0cmlidXRlcyhhdHRyaWJ1dGVzLCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBzY2hlbWEgPSAvKiogQHR5cGUge3R5cGVvZiBTeW5jUmVzb3VyY2VCYXNlfSAqLyAodGhpcy5jb25zdHJ1Y3Rvcikud3JpdGFibGVBdHRyaWJ1dGVzXG5cbiAgICBpZiAoIXNjaGVtYSkgdGhyb3cgbmV3IEVycm9yKGAke3RoaXMuY29uc3RydWN0b3IubmFtZX0gbXVzdCBkZWZpbmUgc3RhdGljIHdyaXRhYmxlQXR0cmlidXRlcyB0byB1c2Ugbm9ybWFsaXplV3JpdGFibGVBdHRyaWJ1dGVzYClcblxuICAgIHJldHVybiBub3JtYWxpemVBdHRyaWJ1dGVzV2l0aFNjaGVtYSh7XG4gICAgICBhdHRyaWJ1dGVzLFxuICAgICAgZXJyb3JGYWN0b3J5OiAobWVzc2FnZSwgZGV0YWlscykgPT4gdGhpcy53cml0YWJsZUF0dHJpYnV0ZUVycm9yKG1lc3NhZ2UsIGRldGFpbHMpLFxuICAgICAgc2NoZW1hLFxuICAgICAgdW5rbm93bkF0dHJpYnV0ZXM6IG9wdGlvbnMudW5rbm93bkF0dHJpYnV0ZXNcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgY2xpZW50LXNhZmUgZXJyb3IgdGhyb3duIGZvciBhIGZhaWxlZCB3cml0YWJsZS1hdHRyaWJ1dGUgdmFsaWRhdGlvbi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBIdW1hbi1yZWFkYWJsZSB2YWxpZGF0aW9uIG1lc3NhZ2UuXG4gICAqIEBwYXJhbSB7e2NhdXNlPzogRXJyb3IsIGNvZGU6IHN0cmluZ319IGRldGFpbHMgLSBTdGFibGUgbWFjaGluZS1yZWFkYWJsZSBjb2RlIGFuZCBvcHRpb25hbCBjYXVzZS5cbiAgICogQHJldHVybnMge0Vycm9yfSBDbGllbnQtc2FmZSBlcnJvci5cbiAgICovXG4gIHdyaXRhYmxlQXR0cmlidXRlRXJyb3IobWVzc2FnZSwge2NhdXNlLCBjb2RlfSkge1xuICAgIHJldHVybiBWZWxvY2lvdXNFcnJvci5zYWZlKG1lc3NhZ2UsIGNhdXNlID8ge2NhdXNlLCBjb2RlfSA6IHtjb2RlfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc3RhYmxlIGNoYW5nZS1mZWVkIHBhZ2UgYWZ0ZXIgYXBwIGF1dGhvcml6YXRpb24uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsID8+Pn0gQ2hhbmdlLWZlZWQgcGFnZSByZXN1bHQuXG4gICAqL1xuICBhc3luYyBjaGFuZ2VzKCkge1xuICAgIGNvbnN0IHBhcmFtcyA9IHRoaXMucGFyYW1zKClcbiAgICBjb25zdCBzY29wZSA9IHRoaXMuY2hhbmdlc1Njb3BlKHBhcmFtcylcblxuICAgIGF3YWl0IHRoaXMuYXV0aG9yaXplQ2hhbmdlcyh7cGFyYW1zLCBzY29wZX0pXG5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5jaGFuZ2VGZWVkU2VydmljZSh7cGFyYW1zLCBzY29wZX0pLmNoYW5nZXMoKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxheXMgY2xpZW50IHN5bmMgZW52ZWxvcGVzIHRocm91Z2ggdGhlIGFwcCByZXBsYXkgc2VydmljZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8UmVjb3JkPHN0cmluZywgPz4+fSBSZXBsYXkgcmVzdWx0IHdpdGggcGVyLXN5bmMgc3RhdGVzLlxuICAgKi9cbiAgYXN5bmMgcmVwbGF5KCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuYnVpbGRSZXBsYXlTZXJ2aWNlKCkucmVwbGF5KHRoaXMucGFyYW1zKCkpXG5cbiAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gXCJlcnJvclwiKSByZXR1cm4gcmVzdWx0XG5cbiAgICByZXR1cm4ge3N0YXR1czogXCJzdWNjZXNzXCIsIHN5bmNzOiByZXN1bHQuc3luY3N9XG4gIH1cblxuICAvKipcbiAgICogUGFyc2VzIHRoZSBvcHRpb25hbCBjbGllbnQtZGVjbGFyZWQgc2NvcGUgZnJvbSByZXF1ZXN0IHBhcmFtcy5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gcGFyYW1zIC0gUmVxdWVzdCBwYXJhbXMuXG4gICAqIEByZXR1cm5zIHtTZXJpYWxpemVkQ2hhbmdlc1Njb3BlIHwgbnVsbH0gUGFyc2VkIHNjb3BlLCBvciBudWxsIHdoZW4gdGhlIGNsaWVudCBzZW50IG5vbmUuXG4gICAqL1xuICBjaGFuZ2VzU2NvcGUocGFyYW1zKSB7XG4gICAgY29uc3Qgc2NvcGUgPSBwYXJhbXMuc2NvcGVcblxuICAgIGlmIChzY29wZSA9PT0gdW5kZWZpbmVkIHx8IHNjb3BlID09PSBudWxsKSByZXR1cm4gbnVsbFxuXG4gICAgaWYgKHR5cGVvZiBzY29wZSAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KHNjb3BlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBTeW5jIGNoYW5nZXMgc2NvcGUgbXVzdCBiZSBhbiBvYmplY3QsIGdvdDogJHtTdHJpbmcoc2NvcGUpfWApXG4gICAgfVxuXG4gICAgY29uc3Qgc2NvcGVQYXJhbXMgPSAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsID8+fSAqLyAoc2NvcGUpXG4gICAgY29uc3QgcmVzb3VyY2VUeXBlID0gZm9yY2VkTm9uQmxhbmtTdHJpbmdQYXJhbShzY29wZVBhcmFtcywgXCJyZXNvdXJjZVR5cGVcIilcbiAgICBjb25zdCBjb25kaXRpb25zID0gc2NvcGVQYXJhbXMuY29uZGl0aW9uc1xuXG4gICAgaWYgKCFjb25kaXRpb25zIHx8IHR5cGVvZiBjb25kaXRpb25zICE9PSBcIm9iamVjdFwiIHx8IEFycmF5LmlzQXJyYXkoY29uZGl0aW9ucykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgU3luYyBjaGFuZ2VzIHNjb3BlLmNvbmRpdGlvbnMgbXVzdCBiZSBhbiBvYmplY3QsIGdvdDogJHtTdHJpbmcoY29uZGl0aW9ucyl9YClcbiAgICB9XG5cbiAgICByZXR1cm4ge2NvbmRpdGlvbnM6IC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgPz59ICovIChjb25kaXRpb25zKSwgcmVzb3VyY2VUeXBlfVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgY2hhbmdlLWZlZWQgc2VydmljZSBzZXJ2aW5nIHRoaXMgY2hhbmdlcyByZXF1ZXN0LlxuICAgKiBAcGFyYW0ge3twYXJhbXM6IFJlY29yZDxzdHJpbmcsID8+LCBzY29wZTogU2VyaWFsaXplZENoYW5nZXNTY29wZSB8IG51bGx9fSBhcmdzIC0gUmVxdWVzdCBwYXJhbXMgYW5kIHBhcnNlZCBzY29wZS5cbiAgICogQHJldHVybnMge3tjaGFuZ2VzOiAoKSA9PiBQcm9taXNlPFJlY29yZDxzdHJpbmcsID8+Pn19IENoYW5nZS1mZWVkIHNlcnZpY2UuXG4gICAqL1xuICBjaGFuZ2VGZWVkU2VydmljZSh7cGFyYW1zLCBzY29wZX0pIHtcbiAgICByZXR1cm4gbmV3IFN5bmNNb2RlbENoYW5nZUZlZWRTZXJ2aWNlKHtcbiAgICAgIG1vZGVsQ2xhc3M6IHRoaXMuc3luY01vZGVsQ2xhc3MoKSxcbiAgICAgIHBhcmFtcyxcbiAgICAgIHNjb3BlUXVlcnk6ICh7cXVlcnl9KSA9PiB0aGlzLnNjb3BlQ2hhbmdlc1F1ZXJ5KHtwYXJhbXMsIHF1ZXJ5LCBzY29wZX0pXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgdGhlIGFwcCByZXBsYXkgc2VydmljZSBoYW5kbGluZyB0aGlzIHJlcGxheSByZXF1ZXN0LlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi9zeW5jLWVudmVsb3BlLXJlcGxheS1zZXJ2aWNlLmpzXCIpLmRlZmF1bHR9IFJlcGxheSBzZXJ2aWNlIGluc3RhbmNlLlxuICAgKi9cbiAgYnVpbGRSZXBsYXlTZXJ2aWNlKCkge1xuICAgIGNvbnN0IFJlcGxheVNlcnZpY2VDbGFzcyA9IHRoaXMucmVwbGF5U2VydmljZUNsYXNzKClcblxuICAgIHJldHVybiBuZXcgUmVwbGF5U2VydmljZUNsYXNzKHRoaXMucmVwbGF5U2VydmljZUFyZ3MoKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGNvbnN0cnVjdG9yIGFyZ3MgZm9yIHRoZSBhcHAgcmVwbGF5IHNlcnZpY2UuXG4gICAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gUmVwbGF5IHNlcnZpY2UgY29uc3RydWN0b3IgYXJncy5cbiAgICovXG4gIHJlcGxheVNlcnZpY2VBcmdzKCkge1xuICAgIHJldHVybiB7fVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHN5bmMgbW9kZWwgY2xhc3MgYmFja2luZyB0aGUgY2hhbmdlIGZlZWQuXG4gICAqIEByZXR1cm5zIHt0eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9IFN5bmMgbW9kZWwgY2xhc3MuXG4gICAqL1xuICBzeW5jTW9kZWxDbGFzcygpIHtcbiAgICBjb25zdCBtb2RlbENsYXNzID0gLyoqIEB0eXBlIHt0eXBlb2YgU3luY1Jlc291cmNlQmFzZX0gKi8gKHRoaXMuY29uc3RydWN0b3IpLk1vZGVsQ2xhc3NcblxuICAgIGlmICghbW9kZWxDbGFzcykgdGhyb3cgbmV3IEVycm9yKGAke3RoaXMuY29uc3RydWN0b3IubmFtZX0gbXVzdCBkZWZpbmUgc3RhdGljIE1vZGVsQ2xhc3NgKVxuXG4gICAgcmV0dXJuIG1vZGVsQ2xhc3NcbiAgfVxuXG4gIC8qKlxuICAgKiBBdXRob3JpemVzIHRoZSBjdXJyZW50IGNvbnRleHQgZm9yIHJlYWRpbmcgdGhlIHJlcXVlc3RlZCBjaGFuZ2VzLlxuICAgKiBAcGFyYW0ge3twYXJhbXM6IFJlY29yZDxzdHJpbmcsID8+LCBzY29wZTogU2VyaWFsaXplZENoYW5nZXNTY29wZSB8IG51bGx9fSBfYXJncyAtIFJlcXVlc3QgcGFyYW1zIGFuZCBwYXJzZWQgc2NvcGUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBSZXNvbHZlcyB3aGVuIGFjY2VzcyBpcyBhbGxvd2VkOyB0aHJvd3Mgb3RoZXJ3aXNlLlxuICAgKi9cbiAgYXN5bmMgYXV0aG9yaXplQ2hhbmdlcyhfYXJncykge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlN5bmNSZXNvdXJjZUJhc2UjYXV0aG9yaXplQ2hhbmdlcyBtdXN0IGJlIGltcGxlbWVudGVkXCIpXG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyBhcHAgdmlzaWJpbGl0eSBzY29waW5nIG9udG8gdGhlIGNoYW5nZS1mZWVkIHF1ZXJ5LlxuICAgKiBAcGFyYW0ge3twYXJhbXM6IFJlY29yZDxzdHJpbmcsID8+LCBxdWVyeTogaW1wb3J0KFwiLi4vZGF0YWJhc2UvcXVlcnkvbW9kZWwtY2xhc3MtcXVlcnkuanNcIikuZGVmYXVsdCwgc2NvcGU6IFNlcmlhbGl6ZWRDaGFuZ2VzU2NvcGUgfCBudWxsfX0gX2FyZ3MgLSBSZXF1ZXN0IHBhcmFtcywgZmVlZCBxdWVyeSwgYW5kIHBhcnNlZCBzY29wZS5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBzY29wZUNoYW5nZXNRdWVyeShfYXJncykge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlN5bmNSZXNvdXJjZUJhc2Ujc2NvcGVDaGFuZ2VzUXVlcnkgbXVzdCBiZSBpbXBsZW1lbnRlZFwiKVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGFwcCByZXBsYXkgc2VydmljZSBjbGFzcyBoYW5kbGluZyByZXBsYXkgbXV0YXRpb25zLlxuICAgKiBAcmV0dXJucyB7dHlwZW9mIGltcG9ydChcIi4vc3luYy1lbnZlbG9wZS1yZXBsYXktc2VydmljZS5qc1wiKS5kZWZhdWx0fSBSZXBsYXkgc2VydmljZSBjbGFzcy5cbiAgICovXG4gIHJlcGxheVNlcnZpY2VDbGFzcygpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJTeW5jUmVzb3VyY2VCYXNlI3JlcGxheVNlcnZpY2VDbGFzcyBtdXN0IGJlIGltcGxlbWVudGVkXCIpXG4gIH1cbn1cbiJdfQ==
|