velocious 1.0.502 → 1.0.504

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.
Files changed (81) hide show
  1. package/build/application.js +4 -0
  2. package/build/configuration-types.js +8 -8
  3. package/build/configuration.js +2 -2
  4. package/build/src/application.d.ts.map +1 -1
  5. package/build/src/application.js +5 -1
  6. package/build/src/configuration-types.d.ts +17 -17
  7. package/build/src/configuration-types.d.ts.map +1 -1
  8. package/build/src/configuration-types.js +9 -9
  9. package/build/src/configuration.d.ts +4 -4
  10. package/build/src/configuration.d.ts.map +1 -1
  11. package/build/src/configuration.js +3 -3
  12. package/build/src/sync/sync-change-fanout.d.ts +71 -0
  13. package/build/src/sync/sync-change-fanout.d.ts.map +1 -0
  14. package/build/src/sync/sync-change-fanout.js +54 -0
  15. package/build/src/sync/sync-channel-name.d.ts +9 -0
  16. package/build/src/sync/sync-channel-name.d.ts.map +1 -0
  17. package/build/src/sync/sync-channel-name.js +10 -0
  18. package/build/src/sync/sync-client-types.d.ts +13 -6
  19. package/build/src/sync/sync-client-types.d.ts.map +1 -1
  20. package/build/src/sync/sync-client-types.js +1 -1
  21. package/build/src/sync/sync-client.d.ts +1 -1
  22. package/build/src/sync/sync-client.d.ts.map +1 -1
  23. package/build/src/sync/sync-client.js +8 -4
  24. package/build/src/sync/sync-envelope-replay-service.d.ts +15 -4
  25. package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
  26. package/build/src/sync/sync-envelope-replay-service.js +60 -42
  27. package/build/src/sync/sync-model-change-feed-service.d.ts +6 -1
  28. package/build/src/sync/sync-model-change-feed-service.d.ts.map +1 -1
  29. package/build/src/sync/sync-model-change-feed-service.js +15 -4
  30. package/build/src/sync/sync-publish-suppression.d.ts +31 -0
  31. package/build/src/sync/sync-publish-suppression.d.ts.map +1 -0
  32. package/build/src/sync/sync-publish-suppression.js +54 -0
  33. package/build/src/sync/sync-publisher-types.d.ts +178 -0
  34. package/build/src/sync/sync-publisher-types.d.ts.map +1 -0
  35. package/build/src/sync/sync-publisher-types.js +3 -0
  36. package/build/src/sync/sync-publisher.d.ts +160 -0
  37. package/build/src/sync/sync-publisher.d.ts.map +1 -0
  38. package/build/src/sync/sync-publisher.js +438 -0
  39. package/build/src/sync/sync-realtime-bridge.d.ts +33 -10
  40. package/build/src/sync/sync-realtime-bridge.d.ts.map +1 -1
  41. package/build/src/sync/sync-realtime-bridge.js +51 -12
  42. package/build/src/sync/sync-scope-attributes.d.ts +15 -0
  43. package/build/src/sync/sync-scope-attributes.d.ts.map +1 -0
  44. package/build/src/sync/sync-scope-attributes.js +24 -0
  45. package/build/src/sync/sync-websocket-channel.d.ts +58 -0
  46. package/build/src/sync/sync-websocket-channel.d.ts.map +1 -0
  47. package/build/src/sync/sync-websocket-channel.js +131 -0
  48. package/build/src/testing/test-runner.d.ts +8 -0
  49. package/build/src/testing/test-runner.d.ts.map +1 -1
  50. package/build/src/testing/test-runner.js +64 -2
  51. package/build/sync/sync-change-fanout.js +58 -0
  52. package/build/sync/sync-channel-name.js +10 -0
  53. package/build/sync/sync-client-types.js +12 -5
  54. package/build/sync/sync-client.js +8 -3
  55. package/build/sync/sync-envelope-replay-service.js +60 -41
  56. package/build/sync/sync-model-change-feed-service.js +17 -3
  57. package/build/sync/sync-publish-suppression.js +59 -0
  58. package/build/sync/sync-publisher-types.js +84 -0
  59. package/build/sync/sync-publisher.js +502 -0
  60. package/build/sync/sync-realtime-bridge.js +56 -11
  61. package/build/sync/sync-scope-attributes.js +26 -0
  62. package/build/sync/sync-websocket-channel.js +146 -0
  63. package/build/testing/test-runner.js +69 -1
  64. package/build/tsconfig.tsbuildinfo +1 -1
  65. package/package.json +1 -1
  66. package/src/application.js +4 -0
  67. package/src/configuration-types.js +8 -8
  68. package/src/configuration.js +2 -2
  69. package/src/sync/sync-change-fanout.js +58 -0
  70. package/src/sync/sync-channel-name.js +10 -0
  71. package/src/sync/sync-client-types.js +12 -5
  72. package/src/sync/sync-client.js +8 -3
  73. package/src/sync/sync-envelope-replay-service.js +60 -41
  74. package/src/sync/sync-model-change-feed-service.js +17 -3
  75. package/src/sync/sync-publish-suppression.js +59 -0
  76. package/src/sync/sync-publisher-types.js +84 -0
  77. package/src/sync/sync-publisher.js +502 -0
  78. package/src/sync/sync-realtime-bridge.js +56 -11
  79. package/src/sync/sync-scope-attributes.js +26 -0
  80. package/src/sync/sync-websocket-channel.js +146 -0
  81. package/src/testing/test-runner.js +69 -1
@@ -0,0 +1,438 @@
1
+ // @ts-check
2
+ import Configuration from "../configuration.js";
3
+ import Logger from "../logger.js";
4
+ import restArgsError from "../utils/rest-args-error.js";
5
+ import { declaredSyncScopeAttributes } from "./sync-scope-attributes.js";
6
+ import { deliverDeclaredBroadcasts, upsertSyncRow } from "./sync-change-fanout.js";
7
+ import { isPublishingSuppressed } from "./sync-publish-suppression.js";
8
+ import { VELOCIOUS_SYNC_CHANNEL } from "./sync-channel-name.js";
9
+ /** @type {{create: "afterCreate", update: "afterUpdate", destroy: "afterDestroy"}} */
10
+ const PUBLISHED_CALLBACK_NAMES = { create: "afterCreate", destroy: "afterDestroy", update: "afterUpdate" };
11
+ /**
12
+ * Operations published by default for models declaring `static sync` publish
13
+ * without an `operations` key: server-side creates and updates publish
14
+ * automatically. Destroys are not published by default because a server
15
+ * destroy is often cleanup rather than a synced delete; opt in with an
16
+ * operations list.
17
+ * @type {Array<"create" | "update" | "destroy">} */
18
+ const DEFAULT_PUBLISHED_OPERATIONS = ["create", "update"];
19
+ /** @type {WeakMap<Configuration, SyncPublisher>} */
20
+ const startedPublishersByConfiguration = new WeakMap();
21
+ /**
22
+ * Declarative server-side sync publisher — the server mirror of the client's
23
+ * track-by-default mutation tracking.
24
+ *
25
+ * Server models declare what to publish through `static sync`'s `publish`
26
+ * key, and Velocious writes every committed server-side change to the sync
27
+ * change feed (model-backed Sync-row upsert with server re-sequencing) and
28
+ * broadcasts the standard sync envelope (`{echoOrigin, syncs: [...]}`) on the
29
+ * framework sync channel ({@link VELOCIOUS_SYNC_CHANNEL}) scoped by the
30
+ * change's derived scope-partition values, so devices receive server-origin
31
+ * changes without app code declaring channels or calling manual
32
+ * upsert/broadcast helpers:
33
+ *
34
+ * static sync = {publish: true} // default payload (attributes) + default scope partition
35
+ * static sync = {publish: {serialize: (record) => ({id: record.id(), pin: record.pin()})}}
36
+ *
37
+ * The scope partition comes from the sync model's `static
38
+ * syncScopeAttributes` declaration (for example `["eventId"]` or
39
+ * `["accountId"]` — Velocious has no built-in partition name): each declared
40
+ * scope attribute reads the record's attribute of the same name when the
41
+ * model has one, else the record's own id (scope-root models), overridable
42
+ * per model through `publish: {scopeAttributes: {accountId: "ownerId"}}`.
43
+ * The pre-framework-channel `broadcasts` list and the `eventId`
44
+ * string/resolver-function declaration forms keep working but are deprecated.
45
+ *
46
+ * Replayed device mutations never double-publish: the framework's routed
47
+ * replay apply marks its written records through `markServerApply(record)`
48
+ * (see sync-publish-suppression.js), and app code applying already-synced
49
+ * data can use `markServerApply`/`withoutPublishing` the same way.
50
+ */
51
+ export default class SyncPublisher {
52
+ /**
53
+ * Builds the sync publisher by deriving published resources from the
54
+ * configuration's registered models: every model declaring `static sync`
55
+ * with a `publish` declaration becomes a published resource
56
+ * (`publish: false` opts out). The sync/change model is the registered
57
+ * "Sync" model and broadcasts default to the configuration's channel
58
+ * broadcast.
59
+ * @param {import("./sync-publisher-types.js").SyncPublisherOptions} [options] - Optional overrides.
60
+ */
61
+ constructor(options = {}) {
62
+ const { actorForeignKeyColumn = "authentication_token_id", broadcaster, configuration = Configuration.current(), onError, syncModel, ...restOptions } = options;
63
+ restArgsError(restOptions);
64
+ const modelClasses = configuration.getModelClasses();
65
+ const publishingModelClasses = Object.values(modelClasses).filter((modelClass) => publishDeclarationFor(modelClass));
66
+ if (publishingModelClasses.length === 0) {
67
+ throw new Error("SyncPublisher found no registered models declaring static sync publish - declare `static sync = {publish: {serialize}}` on the models whose server-side changes should publish to the sync feed");
68
+ }
69
+ const resolvedSyncModel = syncModel || modelClasses.Sync;
70
+ if (!resolvedSyncModel) {
71
+ throw new Error("SyncPublisher requires a registered \"Sync\" model for published sync change rows (or pass options.syncModel)");
72
+ }
73
+ const scopeAttributes = declaredSyncScopeAttributes(resolvedSyncModel);
74
+ /** @type {Record<string, import("./sync-publisher-types.js").SyncPublisherResourceConfig>} */
75
+ const resources = {};
76
+ for (const modelClass of publishingModelClasses) {
77
+ const publish = publishDeclarationFor(modelClass);
78
+ const resourceConfig = resourceConfigFromPublishDeclaration({ modelClass, publish, scopeAttributes, syncModel: resolvedSyncModel });
79
+ resources[resourceConfig.resourceType] = resourceConfig;
80
+ }
81
+ /** @type {{actorForeignKeyColumn: string, broadcaster: import("./sync-publisher-types.js").SyncPublisherOptions["broadcaster"], configuration: Configuration, onError: import("./sync-publisher-types.js").SyncPublisherOptions["onError"], resources: Record<string, import("./sync-publisher-types.js").SyncPublisherResourceConfig>, syncModel: ?}} */
82
+ this.config = { actorForeignKeyColumn, broadcaster, configuration, onError, resources, syncModel: resolvedSyncModel };
83
+ /** @type {Array<{callback: (record: ?) => Promise<void>, callbackName: "afterCreate" | "afterUpdate" | "afterDestroy", modelClass: ?}>} */
84
+ this._publishedCallbacks = [];
85
+ /** @type {Logger | null} */
86
+ this._logger = null;
87
+ this._started = false;
88
+ }
89
+ /**
90
+ * Builds a sync publisher derived from the given configuration. Alias for
91
+ * `new SyncPublisher({configuration, ...options})`.
92
+ * @param {Configuration} [configuration] - Configuration owning the registered models. Defaults to the current configuration.
93
+ * @param {Omit<import("./sync-publisher-types.js").SyncPublisherOptions, "configuration">} [options] - Optional overrides.
94
+ * @returns {SyncPublisher} Sync publisher derived from the configuration.
95
+ */
96
+ static fromConfiguration(configuration = Configuration.current(), options = {}) {
97
+ return new SyncPublisher({ ...options, configuration });
98
+ }
99
+ /**
100
+ * Starts (and memoizes per configuration) the sync publisher for a server
101
+ * boot: no-op when no registered model declares a publish config, guarded so
102
+ * repeated boots with the same configuration register the publish callbacks
103
+ * only once.
104
+ * @param {Configuration} configuration - Configuration owning the registered models.
105
+ * @returns {Promise<SyncPublisher | null>} Started publisher, or null when no models declare publish.
106
+ */
107
+ static async startFromConfiguration(configuration) {
108
+ const startedPublisher = startedPublishersByConfiguration.get(configuration);
109
+ if (startedPublisher)
110
+ return startedPublisher;
111
+ if (!Object.values(configuration.getModelClasses()).some((modelClass) => publishDeclarationFor(modelClass)))
112
+ return null;
113
+ const publisher = new SyncPublisher({ configuration });
114
+ startedPublishersByConfiguration.set(configuration, publisher);
115
+ await publisher.start();
116
+ return publisher;
117
+ }
118
+ /**
119
+ * Registers the publish callbacks for every published resource: server-side
120
+ * creates and updates (destroys when opted in) upsert a sync change row and
121
+ * fan out the declared broadcasts once their transaction commits.
122
+ * @returns {Promise<void>}
123
+ */
124
+ async start() {
125
+ if (this._started)
126
+ return;
127
+ this._started = true;
128
+ for (const resourceConfig of Object.values(this.config.resources)) {
129
+ for (const operation of resourceConfig.operations) {
130
+ const callbackName = PUBLISHED_CALLBACK_NAMES[operation];
131
+ const callback = this.publishedMutationCallback({ operation, resourceConfig });
132
+ resourceConfig.modelClass[callbackName](callback);
133
+ this._publishedCallbacks.push({ callback, callbackName, modelClass: resourceConfig.modelClass });
134
+ }
135
+ }
136
+ }
137
+ /**
138
+ * Unregisters all publish callbacks (tests, shutdown).
139
+ * @returns {void}
140
+ */
141
+ stop() {
142
+ for (const { callback, callbackName, modelClass } of this._publishedCallbacks) {
143
+ modelClass.unregisterLifecycleCallback(callbackName, callback);
144
+ }
145
+ this._publishedCallbacks = [];
146
+ this._started = false;
147
+ }
148
+ /**
149
+ * Builds the lifecycle callback publishing one server-side mutation. The
150
+ * published payload (declaration `serialize`), event scope, and sync type
151
+ * are snapshotted at mutation-callback time, so afterSave hooks assigning
152
+ * unsaved attributes (or any later drift on the record) cannot change what
153
+ * gets published vs what was committed. Persisting and broadcasting are
154
+ * deferred through the model connection's afterCommit hook so they only run
155
+ * once the mutation's transaction has committed (immediately when no
156
+ * transaction is open) - rolled-back mutations never publish. Post-commit
157
+ * publish failures are reported without rethrowing into the driver's
158
+ * afterCommit chain (see reportAfterCommitError).
159
+ * @param {{operation: "create" | "update" | "destroy", resourceConfig: import("./sync-publisher-types.js").SyncPublisherResourceConfig}} args - Operation and resource config.
160
+ * @returns {(record: ?) => Promise<void>} Lifecycle callback.
161
+ */
162
+ publishedMutationCallback({ operation, resourceConfig }) {
163
+ return async (record) => {
164
+ if (isPublishingSuppressed(record))
165
+ return;
166
+ const data = await resourceConfig.serialize(record);
167
+ const resourceId = String(record.id());
168
+ const syncType = operation === "destroy" ? "delete" : "update";
169
+ const scopeValues = await this.publishedScopeValues({ record, resourceConfig });
170
+ /** @type {Record<string, ?>} */
171
+ const attributes = {
172
+ [this.config.actorForeignKeyColumn]: null,
173
+ client_updated_at: new Date(),
174
+ data: JSON.stringify(data),
175
+ resource_id: resourceId,
176
+ resource_type: resourceConfig.resourceType,
177
+ sync_type: syncType,
178
+ ...scopeValues.columns
179
+ };
180
+ await resourceConfig.modelClass.connection().afterCommit(async () => {
181
+ try {
182
+ const syncRow = await this.upsertPublishedSyncRow(attributes);
183
+ await this.broadcaster()({
184
+ body: {
185
+ echoOrigin: null,
186
+ syncs: [{ data, resourceId, resourceType: resourceConfig.resourceType, syncType }]
187
+ },
188
+ channel: VELOCIOUS_SYNC_CHANNEL,
189
+ params: { ...scopeValues.params, resourceType: resourceConfig.resourceType }
190
+ });
191
+ if (resourceConfig.broadcasts) {
192
+ await deliverDeclaredBroadcasts({
193
+ args: { data, operation, record, resourceId, resourceType: resourceConfig.resourceType, syncRow, syncType },
194
+ broadcaster: this.broadcaster(),
195
+ broadcasts: resourceConfig.broadcasts
196
+ });
197
+ }
198
+ }
199
+ catch (error) {
200
+ await this.reportAfterCommitError(/** @type {Error} */ (error));
201
+ }
202
+ });
203
+ };
204
+ }
205
+ /**
206
+ * Resolves the scope-partition values for one published mutation from the
207
+ * resource's derived scope plan: each entry reads its record attribute (or
208
+ * the record's own id for scope-root models, or the deprecated resolver
209
+ * function). The values are persisted onto the sync row's partition columns
210
+ * and broadcast as the framework sync channel's scoping params.
211
+ * @param {{record: ?, resourceConfig: import("./sync-publisher-types.js").SyncPublisherResourceConfig}} args - Mutated record and resource config.
212
+ * @returns {Promise<{columns: Record<string, string | null>, params: Record<string, string | null>}>} Scope values keyed by sync-row column and by scope attribute.
213
+ */
214
+ async publishedScopeValues({ record, resourceConfig }) {
215
+ /** @type {Record<string, string | null>} */
216
+ const columns = {};
217
+ /** @type {Record<string, string | null>} */
218
+ const params = {};
219
+ for (const scopePlanEntry of resourceConfig.scopePlan) {
220
+ /** @type {?} */
221
+ let rawValue;
222
+ if (scopePlanEntry.resolver) {
223
+ rawValue = await scopePlanEntry.resolver(record);
224
+ }
225
+ else if (scopePlanEntry.recordAttribute) {
226
+ rawValue = record.readAttribute(scopePlanEntry.recordAttribute);
227
+ }
228
+ else {
229
+ rawValue = record.id();
230
+ }
231
+ const value = rawValue === undefined || rawValue === null ? null : String(rawValue);
232
+ columns[scopePlanEntry.columnName] = value;
233
+ params[scopePlanEntry.scopeAttribute] = value;
234
+ }
235
+ return { columns, params };
236
+ }
237
+ /**
238
+ * Upserts the published server-origin sync row for a resource identity:
239
+ * server-origin rows carry a null actor column (no device to echo the
240
+ * change back to), so repeated server changes to one resource reuse and
241
+ * re-sequence one feed row.
242
+ * @param {Record<string, ?>} attributes - Snapshotted sync row attributes.
243
+ * @returns {Promise<?>} Upserted sync row.
244
+ */
245
+ async upsertPublishedSyncRow(attributes) {
246
+ const existingSync = await this.config.syncModel
247
+ .where({
248
+ [this.config.actorForeignKeyColumn]: null,
249
+ resource_id: attributes.resource_id,
250
+ resource_type: attributes.resource_type
251
+ })
252
+ .first();
253
+ return await upsertSyncRow({ attributes, existingSync, syncModel: this.config.syncModel });
254
+ }
255
+ /**
256
+ * Returns the broadcaster delivering declared broadcasts: the injected one,
257
+ * or the configuration's channel broadcast awaited through the pending
258
+ * broadcast queue.
259
+ * @returns {NonNullable<import("./sync-publisher-types.js").SyncPublisherOptions["broadcaster"]>} Broadcast deliverer.
260
+ */
261
+ broadcaster() {
262
+ if (this.config.broadcaster)
263
+ return this.config.broadcaster;
264
+ return async ({ body, channel, params }) => {
265
+ this.config.configuration.broadcastToChannel(channel, params, body);
266
+ await this.config.configuration.awaitPendingBroadcasts();
267
+ };
268
+ }
269
+ /**
270
+ * Reports a post-commit publish failure. The transaction has already
271
+ * committed when afterCommit callbacks run, so rethrowing here would poison
272
+ * the driver's awaited afterCommit chain (breaking unrelated callbacks) -
273
+ * instead the failure goes to the configured onError hook, or is emitted on
274
+ * the configuration's framework-error/all-error channels (so production bug
275
+ * reporting via `configuration.getErrorEvents()` sees a broken publish
276
+ * path) and logged loudly through the publisher's logger when none is
277
+ * configured.
278
+ * @param {Error} error - Post-commit publish failure.
279
+ * @returns {Promise<void>}
280
+ */
281
+ async reportAfterCommitError(error) {
282
+ if (this.config.onError) {
283
+ this.config.onError(error);
284
+ return;
285
+ }
286
+ const errorEvents = this.config.configuration.getErrorEvents();
287
+ const payload = { context: { stage: "sync-publish-after-commit" }, error };
288
+ errorEvents.emit("framework-error", payload);
289
+ errorEvents.emit("all-error", { ...payload, errorType: "framework-error" });
290
+ await this.logger().error("SyncPublisher failed to publish a server-side sync change after commit", error);
291
+ }
292
+ /**
293
+ * Returns the lazily built publisher logger.
294
+ * @returns {Logger} Publisher logger.
295
+ */
296
+ logger() {
297
+ this._logger ||= new Logger("SyncPublisher", { configuration: this.config.configuration });
298
+ return this._logger;
299
+ }
300
+ }
301
+ /**
302
+ * Resolves a model class's active publish declaration from `static sync`.
303
+ * Opted-out (`publish: false`) and undeclared models resolve to null; every
304
+ * other declared value flows into loud declaration validation.
305
+ * @param {?} modelClass - Registered model class.
306
+ * @returns {import("./sync-publisher-types.js").SyncPublishDeclaration | null} Active publish declaration, or null.
307
+ */
308
+ function publishDeclarationFor(modelClass) {
309
+ const declaration = modelClass.sync;
310
+ if (!declaration || typeof declaration !== "object" || declaration.publish === undefined || declaration.publish === false)
311
+ return null;
312
+ return declaration.publish;
313
+ }
314
+ /**
315
+ * Builds one published resource config from a model's `static sync` publish
316
+ * declaration. `publish: true` opts in with all defaults (attribute payload,
317
+ * derived scope partition, created/updated operations).
318
+ * @param {{modelClass: ?, publish: import("./sync-publisher-types.js").SyncPublishDeclaration | null, scopeAttributes: string[] | null, syncModel: ?}} args - Declaration args plus the sync model's declared scope attributes.
319
+ * @returns {import("./sync-publisher-types.js").SyncPublisherResourceConfig} Derived resource config.
320
+ */
321
+ function resourceConfigFromPublishDeclaration({ modelClass, publish, scopeAttributes: syncScopeAttributes, syncModel }) {
322
+ const modelName = modelClass.getModelName();
323
+ const normalizedPublish = publish === true ? {} : publish;
324
+ if (!normalizedPublish || typeof normalizedPublish !== "object" || Array.isArray(normalizedPublish)) {
325
+ throw new Error(`${modelName} static sync publish must be true, false or a publish declaration object, got: ${String(publish)}`);
326
+ }
327
+ const { broadcasts, eventId, operations, resourceType, scopeAttributes, serialize, ...restDeclaration } = normalizedPublish;
328
+ const unknownKeys = Object.keys(restDeclaration);
329
+ if (unknownKeys.length > 0) {
330
+ throw new Error(`${modelName} static sync publish received unknown keys: ${unknownKeys.join(", ")} (supported: broadcasts, eventId (deprecated), operations, resourceType, scopeAttributes, serialize)`);
331
+ }
332
+ if (serialize !== undefined && typeof serialize !== "function") {
333
+ throw new Error(`${modelName} static sync publish serialize must be a function building the published payload, got: ${String(serialize)}`);
334
+ }
335
+ if (operations !== undefined) {
336
+ if (!Array.isArray(operations) || operations.length === 0) {
337
+ throw new Error(`${modelName} static sync publish operations must be a non-empty array of create/update/destroy`);
338
+ }
339
+ for (const operation of operations) {
340
+ if (!(operation in PUBLISHED_CALLBACK_NAMES)) {
341
+ throw new Error(`${modelName} static sync publish operations must be create/update/destroy, got: ${String(operation)}`);
342
+ }
343
+ }
344
+ }
345
+ return {
346
+ broadcasts,
347
+ modelClass,
348
+ operations: operations === undefined ? DEFAULT_PUBLISHED_OPERATIONS : operations,
349
+ resourceType: resourceType === undefined ? modelName : resourceType,
350
+ scopePlan: scopePlanFor({ eventId, modelClass, modelName, scopeAttributes, syncModel, syncScopeAttributes }),
351
+ serialize: serialize === undefined ? defaultSerializedAttributes : serialize
352
+ };
353
+ }
354
+ /**
355
+ * Derives the scope plan partitioning a published model's changes: one entry
356
+ * per scope attribute declared on the sync model (`static
357
+ * syncScopeAttributes`), each reading the record attribute named like the
358
+ * scope attribute (overridable through the declaration's `scopeAttributes`
359
+ * name map), or the record's own id when the model has no such attribute
360
+ * (scope-root models). The deprecated `eventId` declaration forms map to a
361
+ * fixed `eventId`/`event_id` plan for 1.0.503 compatibility.
362
+ * @param {{eventId: import("./sync-publisher-types.js").SyncPublishDeclarationConfig["eventId"], modelClass: ?, modelName: string, scopeAttributes: Record<string, string> | undefined, syncModel: ?, syncScopeAttributes: string[] | null}} args - Declaration and sync-model scope args.
363
+ * @returns {Array<import("./sync-publisher-types.js").SyncPublisherScopePlanEntry>} Derived scope plan.
364
+ */
365
+ function scopePlanFor({ eventId, modelClass, modelName, scopeAttributes, syncModel, syncScopeAttributes }) {
366
+ const attributeNames = Object.values(modelClass.getColumnNameToAttributeNameMap());
367
+ if (eventId !== undefined) {
368
+ if (scopeAttributes !== undefined) {
369
+ throw new Error(`${modelName} static sync publish can't declare both scopeAttributes and the deprecated eventId form`);
370
+ }
371
+ if (typeof eventId === "function") {
372
+ return [{ columnName: "event_id", recordAttribute: null, resolver: eventId, scopeAttribute: "eventId" }];
373
+ }
374
+ if (typeof eventId !== "string") {
375
+ throw new Error(`${modelName} static sync publish eventId must be an attribute-name string (or a deprecated resolver function), got: ${String(eventId)}`);
376
+ }
377
+ if (!attributeNames.includes(eventId)) {
378
+ throw new Error(`${modelName} static sync publish eventId attribute doesn't exist on the model: ${eventId}`);
379
+ }
380
+ return [{ columnName: "event_id", recordAttribute: eventId, resolver: undefined, scopeAttribute: "eventId" }];
381
+ }
382
+ if (scopeAttributes !== undefined && !syncScopeAttributes) {
383
+ throw new Error(`${modelName} static sync publish declares scopeAttributes but the sync model declares no static syncScopeAttributes`);
384
+ }
385
+ if (!syncScopeAttributes)
386
+ return [];
387
+ if (scopeAttributes !== undefined && (typeof scopeAttributes !== "object" || Array.isArray(scopeAttributes))) {
388
+ throw new Error(`${modelName} static sync publish scopeAttributes must be an object mapping scope attributes to record attribute names, got: ${String(scopeAttributes)}`);
389
+ }
390
+ for (const scopeAttribute of Object.keys(scopeAttributes || {})) {
391
+ if (!syncScopeAttributes.includes(scopeAttribute)) {
392
+ throw new Error(`${modelName} static sync publish scopeAttributes received unknown scope attribute: ${scopeAttribute} (the sync model declares: ${syncScopeAttributes.join(", ")})`);
393
+ }
394
+ }
395
+ return syncScopeAttributes.map((scopeAttribute) => {
396
+ const declaredRecordAttribute = scopeAttributes?.[scopeAttribute];
397
+ if (declaredRecordAttribute !== undefined) {
398
+ if (typeof declaredRecordAttribute !== "string" || !attributeNames.includes(declaredRecordAttribute)) {
399
+ throw new Error(`${modelName} static sync publish scopeAttributes.${scopeAttribute} must name an existing record attribute, got: ${String(declaredRecordAttribute)}`);
400
+ }
401
+ return { columnName: syncScopeColumnName({ scopeAttribute, syncModel }), recordAttribute: declaredRecordAttribute, resolver: undefined, scopeAttribute };
402
+ }
403
+ return {
404
+ columnName: syncScopeColumnName({ scopeAttribute, syncModel }),
405
+ recordAttribute: attributeNames.includes(scopeAttribute) ? scopeAttribute : null,
406
+ resolver: undefined,
407
+ scopeAttribute
408
+ };
409
+ });
410
+ }
411
+ /**
412
+ * Resolves the sync-row column persisting a declared scope attribute.
413
+ * @param {{scopeAttribute: string, syncModel: ?}} args - Scope attribute and sync model.
414
+ * @returns {string} Sync-row column name.
415
+ */
416
+ function syncScopeColumnName({ scopeAttribute, syncModel }) {
417
+ const columnName = syncModel.getAttributeNameToColumnNameMap()[scopeAttribute];
418
+ if (!columnName) {
419
+ throw new Error(`${syncModel.name} declares the sync scope attribute ${scopeAttribute} but has no matching column for it`);
420
+ }
421
+ return columnName;
422
+ }
423
+ /**
424
+ * Default publish serializer: the record's attributes with Date values
425
+ * serialized to ISO strings.
426
+ * @param {?} record - Mutated server model record.
427
+ * @returns {Record<string, ?>} Serialized attributes payload.
428
+ */
429
+ function defaultSerializedAttributes(record) {
430
+ /** @type {Record<string, ?>} */
431
+ const attributes = { ...record.attributes() };
432
+ for (const [attributeName, value] of Object.entries(attributes)) {
433
+ if (value instanceof Date)
434
+ attributes[attributeName] = value.toISOString();
435
+ }
436
+ return attributes;
437
+ }
438
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1wdWJsaXNoZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3luYy9zeW5jLXB1Ymxpc2hlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxhQUFhLE1BQU0scUJBQXFCLENBQUE7QUFDL0MsT0FBTyxNQUFNLE1BQU0sY0FBYyxDQUFBO0FBQ2pDLE9BQU8sYUFBYSxNQUFNLDZCQUE2QixDQUFBO0FBRXZELE9BQU8sRUFBQywyQkFBMkIsRUFBQyxNQUFNLDRCQUE0QixDQUFBO0FBQ3RFLE9BQU8sRUFBQyx5QkFBeUIsRUFBRSxhQUFhLEVBQUMsTUFBTSx5QkFBeUIsQ0FBQTtBQUNoRixPQUFPLEVBQUMsc0JBQXNCLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQTtBQUNwRSxPQUFPLEVBQUMsc0JBQXNCLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQTtBQUU3RCxzRkFBc0Y7QUFDdEYsTUFBTSx3QkFBd0IsR0FBRyxFQUFDLE1BQU0sRUFBRSxhQUFhLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFDLENBQUE7QUFFeEc7Ozs7OztvREFNb0Q7QUFDcEQsTUFBTSw0QkFBNEIsR0FBRyxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQTtBQUV6RCxvREFBb0Q7QUFDcEQsTUFBTSxnQ0FBZ0MsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFBO0FBRXREOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTZCRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sYUFBYTtJQUNoQzs7Ozs7Ozs7T0FRRztJQUNILFlBQVksT0FBTyxHQUFHLEVBQUU7UUFDdEIsTUFBTSxFQUFDLHFCQUFxQixHQUFHLHlCQUF5QixFQUFFLFdBQVcsRUFBRSxhQUFhLEdBQUcsYUFBYSxDQUFDLE9BQU8sRUFBRSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsR0FBRyxXQUFXLEVBQUMsR0FBRyxPQUFP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QUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUNoRSxJQUFJLEtBQUssWUFBWSxJQUFJO1lBQUUsVUFBVSxDQUFDLGFBQWEsQ0FBQyxHQUFHLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQTtJQUM1RSxDQUFDO0lBRUQsT0FBTyxVQUFVLENBQUE7QUFDbkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgQ29uZmlndXJhdGlvbiBmcm9tIFwiLi4vY29uZmlndXJhdGlvbi5qc1wiXG5pbXBvcnQgTG9nZ2VyIGZyb20gXCIuLi9sb2dnZXIuanNcIlxuaW1wb3J0IHJlc3RBcmdzRXJyb3IgZnJvbSBcIi4uL3V0aWxzL3Jlc3QtYXJncy1lcnJvci5qc1wiXG5cbmltcG9ydCB7ZGVjbGFyZWRTeW5jU2NvcGVBdHRyaWJ1dGVzfSBmcm9tIFwiLi9zeW5jLXNjb3BlLWF0dHJpYnV0ZXMuanNcIlxuaW1wb3J0IHtkZWxpdmVyRGVjbGFyZWRCcm9hZGNhc3RzLCB1cHNlcnRTeW5jUm93fSBmcm9tIFwiLi9zeW5jLWNoYW5nZS1mYW5vdXQuanNcIlxuaW1wb3J0IHtpc1B1Ymxpc2hpbmdTdXBwcmVzc2VkfSBmcm9tIFwiLi9zeW5jLXB1Ymxpc2gtc3VwcHJlc3Npb24uanNcIlxuaW1wb3J0IHtWRUxPQ0lPVVNfU1lOQ19DSEFOTkVMfSBmcm9tIFwiLi9zeW5jLWNoYW5uZWwtbmFtZS5qc1wiXG5cbi8qKiBAdHlwZSB7e2NyZWF0ZTogXCJhZnRlckNyZWF0ZVwiLCB1cGRhdGU6IFwiYWZ0ZXJVcGRhdGVcIiwgZGVzdHJveTogXCJhZnRlckRlc3Ryb3lcIn19ICovXG5jb25zdCBQVUJMSVNIRURfQ0FMTEJBQ0tfTkFNRVMgPSB7Y3JlYXRlOiBcImFmdGVyQ3JlYXRlXCIsIGRlc3Ryb3k6IFwiYWZ0ZXJEZXN0cm95XCIsIHVwZGF0ZTogXCJhZnRlclVwZGF0ZVwifVxuXG4vKipcbiAqIE9wZXJhdGlvbnMgcHVibGlzaGVkIGJ5IGRlZmF1bHQgZm9yIG1vZGVscyBkZWNsYXJpbmcgYHN0YXRpYyBzeW5jYCBwdWJsaXNoXG4gKiB3aXRob3V0IGFuIGBvcGVyYXRpb25zYCBrZXk6IHNlcnZlci1zaWRlIGNyZWF0ZXMgYW5kIHVwZGF0ZXMgcHVibGlzaFxuICogYXV0b21hdGljYWxseS4gRGVzdHJveXMgYXJlIG5vdCBwdWJsaXNoZWQgYnkgZGVmYXVsdCBiZWNhdXNlIGEgc2VydmVyXG4gKiBkZXN0cm95IGlzIG9mdGVuIGNsZWFudXAgcmF0aGVyIHRoYW4gYSBzeW5jZWQgZGVsZXRlOyBvcHQgaW4gd2l0aCBhblxuICogb3BlcmF0aW9ucyBsaXN0LlxuICogQHR5cGUge0FycmF5PFwiY3JlYXRlXCIgfCBcInVwZGF0ZVwiIHwgXCJkZXN0cm95XCI+fSAqL1xuY29uc3QgREVGQVVMVF9QVUJMSVNIRURfT1BFUkFUSU9OUyA9IFtcImNyZWF0ZVwiLCBcInVwZGF0ZVwiXVxuXG4vKiogQHR5cGUge1dlYWtNYXA8Q29uZmlndXJhdGlvbiwgU3luY1B1Ymxpc2hlcj59ICovXG5jb25zdCBzdGFydGVkUHVibGlzaGVyc0J5Q29uZmlndXJhdGlvbiA9IG5ldyBXZWFrTWFwKClcblxuLyoqXG4gKiBEZWNsYXJhdGl2ZSBzZXJ2ZXItc2lkZSBzeW5jIHB1Ymxpc2hlciDigJQgdGhlIHNlcnZlciBtaXJyb3Igb2YgdGhlIGNsaWVudCdzXG4gKiB0cmFjay1ieS1kZWZhdWx0IG11dGF0aW9uIHRyYWNraW5nLlxuICpcbiAqIFNlcnZlciBtb2RlbHMgZGVjbGFyZSB3aGF0IHRvIHB1Ymxpc2ggdGhyb3VnaCBgc3RhdGljIHN5bmNgJ3MgYHB1Ymxpc2hgXG4gKiBrZXksIGFuZCBWZWxvY2lvdXMgd3JpdGVzIGV2ZXJ5IGNvbW1pdHRlZCBzZXJ2ZXItc2lkZSBjaGFuZ2UgdG8gdGhlIHN5bmNcbiAqIGNoYW5nZSBmZWVkIChtb2RlbC1iYWNrZWQgU3luYy1yb3cgdXBzZXJ0IHdpdGggc2VydmVyIHJlLXNlcXVlbmNpbmcpIGFuZFxuICogYnJvYWRjYXN0cyB0aGUgc3RhbmRhcmQgc3luYyBlbnZlbG9wZSAoYHtlY2hvT3JpZ2luLCBzeW5jczogWy4uLl19YCkgb24gdGhlXG4gKiBmcmFtZXdvcmsgc3luYyBjaGFubmVsICh7QGxpbmsgVkVMT0NJT1VTX1NZTkNfQ0hBTk5FTH0pIHNjb3BlZCBieSB0aGVcbiAqIGNoYW5nZSdzIGRlcml2ZWQgc2NvcGUtcGFydGl0aW9uIHZhbHVlcywgc28gZGV2aWNlcyByZWNlaXZlIHNlcnZlci1vcmlnaW5cbiAqIGNoYW5nZXMgd2l0aG91dCBhcHAgY29kZSBkZWNsYXJpbmcgY2hhbm5lbHMgb3IgY2FsbGluZyBtYW51YWxcbiAqIHVwc2VydC9icm9hZGNhc3QgaGVscGVyczpcbiAqXG4gKiAgICAgc3RhdGljIHN5bmMgPSB7cHVibGlzaDogdHJ1ZX0gLy8gZGVmYXVsdCBwYXlsb2FkIChhdHRyaWJ1dGVzKSArIGRlZmF1bHQgc2NvcGUgcGFydGl0aW9uXG4gKiAgICAgc3RhdGljIHN5bmMgPSB7cHVibGlzaDoge3NlcmlhbGl6ZTogKHJlY29yZCkgPT4gKHtpZDogcmVjb3JkLmlkKCksIHBpbjogcmVjb3JkLnBpbigpfSl9fVxuICpcbiAqIFRoZSBzY29wZSBwYXJ0aXRpb24gY29tZXMgZnJvbSB0aGUgc3luYyBtb2RlbCdzIGBzdGF0aWNcbiAqIHN5bmNTY29wZUF0dHJpYnV0ZXNgIGRlY2xhcmF0aW9uIChmb3IgZXhhbXBsZSBgW1wiZXZlbnRJZFwiXWAgb3JcbiAqIGBbXCJhY2NvdW50SWRcIl1gIOKAlCBWZWxvY2lvdXMgaGFzIG5vIGJ1aWx0LWluIHBhcnRpdGlvbiBuYW1lKTogZWFjaCBkZWNsYXJlZFxuICogc2NvcGUgYXR0cmlidXRlIHJlYWRzIHRoZSByZWNvcmQncyBhdHRyaWJ1dGUgb2YgdGhlIHNhbWUgbmFtZSB3aGVuIHRoZVxuICogbW9kZWwgaGFzIG9uZSwgZWxzZSB0aGUgcmVjb3JkJ3Mgb3duIGlkIChzY29wZS1yb290IG1vZGVscyksIG92ZXJyaWRhYmxlXG4gKiBwZXIgbW9kZWwgdGhyb3VnaCBgcHVibGlzaDoge3Njb3BlQXR0cmlidXRlczoge2FjY291bnRJZDogXCJvd25lcklkXCJ9fWAuXG4gKiBUaGUgcHJlLWZyYW1ld29yay1jaGFubmVsIGBicm9hZGNhc3RzYCBsaXN0IGFuZCB0aGUgYGV2ZW50SWRgXG4gKiBzdHJpbmcvcmVzb2x2ZXItZnVuY3Rpb24gZGVjbGFyYXRpb24gZm9ybXMga2VlcCB3b3JraW5nIGJ1dCBhcmUgZGVwcmVjYXRlZC5cbiAqXG4gKiBSZXBsYXllZCBkZXZpY2UgbXV0YXRpb25zIG5ldmVyIGRvdWJsZS1wdWJsaXNoOiB0aGUgZnJhbWV3b3JrJ3Mgcm91dGVkXG4gKiByZXBsYXkgYXBwbHkgbWFya3MgaXRzIHdyaXR0ZW4gcmVjb3JkcyB0aHJvdWdoIGBtYXJrU2VydmVyQXBwbHkocmVjb3JkKWBcbiAqIChzZWUgc3luYy1wdWJsaXNoLXN1cHByZXNzaW9uLmpzKSwgYW5kIGFwcCBjb2RlIGFwcGx5aW5nIGFscmVhZHktc3luY2VkXG4gKiBkYXRhIGNhbiB1c2UgYG1hcmtTZXJ2ZXJBcHBseWAvYHdpdGhvdXRQdWJsaXNoaW5nYCB0aGUgc2FtZSB3YXkuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN5bmNQdWJsaXNoZXIge1xuICAvKipcbiAgICogQnVpbGRzIHRoZSBzeW5jIHB1Ymxpc2hlciBieSBkZXJpdmluZyBwdWJsaXNoZWQgcmVzb3VyY2VzIGZyb20gdGhlXG4gICAqIGNvbmZpZ3VyYXRpb24ncyByZWdpc3RlcmVkIG1vZGVsczogZXZlcnkgbW9kZWwgZGVjbGFyaW5nIGBzdGF0aWMgc3luY2BcbiAgICogd2l0aCBhIGBwdWJsaXNoYCBkZWNsYXJhdGlvbiBiZWNvbWVzIGEgcHVibGlzaGVkIHJlc291cmNlXG4gICAqIChgcHVibGlzaDogZmFsc2VgIG9wdHMgb3V0KS4gVGhlIHN5bmMvY2hhbmdlIG1vZGVsIGlzIHRoZSByZWdpc3RlcmVkXG4gICAqIFwiU3luY1wiIG1vZGVsIGFuZCBicm9hZGNhc3RzIGRlZmF1bHQgdG8gdGhlIGNvbmZpZ3VyYXRpb24ncyBjaGFubmVsXG4gICAqIGJyb2FkY2FzdC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJPcHRpb25zfSBbb3B0aW9uc10gLSBPcHRpb25hbCBvdmVycmlkZXMuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCB7YWN0b3JGb3JlaWduS2V5Q29sdW1uID0gXCJhdXRoZW50aWNhdGlvbl90b2tlbl9pZFwiLCBicm9hZGNhc3RlciwgY29uZmlndXJhdGlvbiA9IENvbmZpZ3VyYXRpb24uY3VycmVudCgpLCBvbkVycm9yLCBzeW5jTW9kZWwsIC4uLnJlc3RPcHRpb25zfSA9IG9wdGlvbnNcblxuICAgIHJlc3RBcmdzRXJyb3IocmVzdE9wdGlvbnMpXG5cbiAgICBjb25zdCBtb2RlbENsYXNzZXMgPSBjb25maWd1cmF0aW9uLmdldE1vZGVsQ2xhc3NlcygpXG4gICAgY29uc3QgcHVibGlzaGluZ01vZGVsQ2xhc3NlcyA9IE9iamVjdC52YWx1ZXMobW9kZWxDbGFzc2VzKS5maWx0ZXIoKG1vZGVsQ2xhc3MpID0+IHB1Ymxpc2hEZWNsYXJhdGlvbkZvcihtb2RlbENsYXNzKSlcblxuICAgIGlmIChwdWJsaXNoaW5nTW9kZWxDbGFzc2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU3luY1B1Ymxpc2hlciBmb3VuZCBubyByZWdpc3RlcmVkIG1vZGVscyBkZWNsYXJpbmcgc3RhdGljIHN5bmMgcHVibGlzaCAtIGRlY2xhcmUgYHN0YXRpYyBzeW5jID0ge3B1Ymxpc2g6IHtzZXJpYWxpemV9fWAgb24gdGhlIG1vZGVscyB3aG9zZSBzZXJ2ZXItc2lkZSBjaGFuZ2VzIHNob3VsZCBwdWJsaXNoIHRvIHRoZSBzeW5jIGZlZWRcIilcbiAgICB9XG5cbiAgICBjb25zdCByZXNvbHZlZFN5bmNNb2RlbCA9IHN5bmNNb2RlbCB8fCBtb2RlbENsYXNzZXMuU3luY1xuXG4gICAgaWYgKCFyZXNvbHZlZFN5bmNNb2RlbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU3luY1B1Ymxpc2hlciByZXF1aXJlcyBhIHJlZ2lzdGVyZWQgXFxcIlN5bmNcXFwiIG1vZGVsIGZvciBwdWJsaXNoZWQgc3luYyBjaGFuZ2Ugcm93cyAob3IgcGFzcyBvcHRpb25zLnN5bmNNb2RlbClcIilcbiAgICB9XG5cbiAgICBjb25zdCBzY29wZUF0dHJpYnV0ZXMgPSBkZWNsYXJlZFN5bmNTY29wZUF0dHJpYnV0ZXMocmVzb2x2ZWRTeW5jTW9kZWwpXG4gICAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJSZXNvdXJjZUNvbmZpZz59ICovXG4gICAgY29uc3QgcmVzb3VyY2VzID0ge31cblxuICAgIGZvciAoY29uc3QgbW9kZWxDbGFzcyBvZiBwdWJsaXNoaW5nTW9kZWxDbGFzc2VzKSB7XG4gICAgICBjb25zdCBwdWJsaXNoID0gcHVibGlzaERlY2xhcmF0aW9uRm9yKG1vZGVsQ2xhc3MpXG4gICAgICBjb25zdCByZXNvdXJjZUNvbmZpZyA9IHJlc291cmNlQ29uZmlnRnJvbVB1Ymxpc2hEZWNsYXJhdGlvbih7bW9kZWxDbGFzcywgcHVibGlzaCwgc2NvcGVBdHRyaWJ1dGVzLCBzeW5jTW9kZWw6IHJlc29sdmVkU3luY01vZGVsfSlcblxuICAgICAgcmVzb3VyY2VzW3Jlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZV0gPSByZXNvdXJjZUNvbmZpZ1xuICAgIH1cblxuICAgIC8qKiBAdHlwZSB7e2FjdG9yRm9yZWlnbktleUNvbHVtbjogc3RyaW5nLCBicm9hZGNhc3RlcjogaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyT3B0aW9uc1tcImJyb2FkY2FzdGVyXCJdLCBjb25maWd1cmF0aW9uOiBDb25maWd1cmF0aW9uLCBvbkVycm9yOiBpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJPcHRpb25zW1wib25FcnJvclwiXSwgcmVzb3VyY2VzOiBSZWNvcmQ8c3RyaW5nLCBpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJSZXNvdXJjZUNvbmZpZz4sIHN5bmNNb2RlbDogP319ICovXG4gICAgdGhpcy5jb25maWcgPSB7YWN0b3JGb3JlaWduS2V5Q29sdW1uLCBicm9hZGNhc3RlciwgY29uZmlndXJhdGlvbiwgb25FcnJvciwgcmVzb3VyY2VzLCBzeW5jTW9kZWw6IHJlc29sdmVkU3luY01vZGVsfVxuICAgIC8qKiBAdHlwZSB7QXJyYXk8e2NhbGxiYWNrOiAocmVjb3JkOiA/KSA9PiBQcm9taXNlPHZvaWQ+LCBjYWxsYmFja05hbWU6IFwiYWZ0ZXJDcmVhdGVcIiB8IFwiYWZ0ZXJVcGRhdGVcIiB8IFwiYWZ0ZXJEZXN0cm95XCIsIG1vZGVsQ2xhc3M6ID99Pn0gKi9cbiAgICB0aGlzLl9wdWJsaXNoZWRDYWxsYmFja3MgPSBbXVxuICAgIC8qKiBAdHlwZSB7TG9nZ2VyIHwgbnVsbH0gKi9cbiAgICB0aGlzLl9sb2dnZXIgPSBudWxsXG4gICAgdGhpcy5fc3RhcnRlZCA9IGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIGEgc3luYyBwdWJsaXNoZXIgZGVyaXZlZCBmcm9tIHRoZSBnaXZlbiBjb25maWd1cmF0aW9uLiBBbGlhcyBmb3JcbiAgICogYG5ldyBTeW5jUHVibGlzaGVyKHtjb25maWd1cmF0aW9uLCAuLi5vcHRpb25zfSlgLlxuICAgKiBAcGFyYW0ge0NvbmZpZ3VyYXRpb259IFtjb25maWd1cmF0aW9uXSAtIENvbmZpZ3VyYXRpb24gb3duaW5nIHRoZSByZWdpc3RlcmVkIG1vZGVscy4gRGVmYXVsdHMgdG8gdGhlIGN1cnJlbnQgY29uZmlndXJhdGlvbi5cbiAgICogQHBhcmFtIHtPbWl0PGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlck9wdGlvbnMsIFwiY29uZmlndXJhdGlvblwiPn0gW29wdGlvbnNdIC0gT3B0aW9uYWwgb3ZlcnJpZGVzLlxuICAgKiBAcmV0dXJucyB7U3luY1B1Ymxpc2hlcn0gU3luYyBwdWJsaXNoZXIgZGVyaXZlZCBmcm9tIHRoZSBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgc3RhdGljIGZyb21Db25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb24gPSBDb25maWd1cmF0aW9uLmN1cnJlbnQoKSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgcmV0dXJuIG5ldyBTeW5jUHVibGlzaGVyKHsuLi5vcHRpb25zLCBjb25maWd1cmF0aW9ufSlcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGFydHMgKGFuZCBtZW1vaXplcyBwZXIgY29uZmlndXJhdGlvbikgdGhlIHN5bmMgcHVibGlzaGVyIGZvciBhIHNlcnZlclxuICAgKiBib290OiBuby1vcCB3aGVuIG5vIHJlZ2lzdGVyZWQgbW9kZWwgZGVjbGFyZXMgYSBwdWJsaXNoIGNvbmZpZywgZ3VhcmRlZCBzb1xuICAgKiByZXBlYXRlZCBib290cyB3aXRoIHRoZSBzYW1lIGNvbmZpZ3VyYXRpb24gcmVnaXN0ZXIgdGhlIHB1Ymxpc2ggY2FsbGJhY2tzXG4gICAqIG9ubHkgb25jZS5cbiAgICogQHBhcmFtIHtDb25maWd1cmF0aW9ufSBjb25maWd1cmF0aW9uIC0gQ29uZmlndXJhdGlvbiBvd25pbmcgdGhlIHJlZ2lzdGVyZWQgbW9kZWxzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxTeW5jUHVibGlzaGVyIHwgbnVsbD59IFN0YXJ0ZWQgcHVibGlzaGVyLCBvciBudWxsIHdoZW4gbm8gbW9kZWxzIGRlY2xhcmUgcHVibGlzaC5cbiAgICovXG4gIHN0YXRpYyBhc3luYyBzdGFydEZyb21Db25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb24pIHtcbiAgICBjb25zdCBzdGFydGVkUHVibGlzaGVyID0gc3RhcnRlZFB1Ymxpc2hlcnNCeUNvbmZpZ3VyYXRpb24uZ2V0KGNvbmZpZ3VyYXRpb24pXG5cbiAgICBpZiAoc3RhcnRlZFB1Ymxpc2hlcikgcmV0dXJuIHN0YXJ0ZWRQdWJsaXNoZXJcblxuICAgIGlmICghT2JqZWN0LnZhbHVlcyhjb25maWd1cmF0aW9uLmdldE1vZGVsQ2xhc3NlcygpKS5zb21lKChtb2RlbENsYXNzKSA9PiBwdWJsaXNoRGVjbGFyYXRpb25Gb3IobW9kZWxDbGFzcykpKSByZXR1cm4gbnVsbFxuXG4gICAgY29uc3QgcHVibGlzaGVyID0gbmV3IFN5bmNQdWJsaXNoZXIoe2NvbmZpZ3VyYXRpb259KVxuXG4gICAgc3RhcnRlZFB1Ymxpc2hlcnNCeUNvbmZpZ3VyYXRpb24uc2V0KGNvbmZpZ3VyYXRpb24sIHB1Ymxpc2hlcilcbiAgICBhd2FpdCBwdWJsaXNoZXIuc3RhcnQoKVxuXG4gICAgcmV0dXJuIHB1Ymxpc2hlclxuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyB0aGUgcHVibGlzaCBjYWxsYmFja3MgZm9yIGV2ZXJ5IHB1Ymxpc2hlZCByZXNvdXJjZTogc2VydmVyLXNpZGVcbiAgICogY3JlYXRlcyBhbmQgdXBkYXRlcyAoZGVzdHJveXMgd2hlbiBvcHRlZCBpbikgdXBzZXJ0IGEgc3luYyBjaGFuZ2Ugcm93IGFuZFxuICAgKiBmYW4gb3V0IHRoZSBkZWNsYXJlZCBicm9hZGNhc3RzIG9uY2UgdGhlaXIgdHJhbnNhY3Rpb24gY29tbWl0cy5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBzdGFydCgpIHtcbiAgICBpZiAodGhpcy5fc3RhcnRlZCkgcmV0dXJuXG5cbiAgICB0aGlzLl9zdGFydGVkID0gdHJ1ZVxuXG4gICAgZm9yIChjb25zdCByZXNvdXJjZUNvbmZpZyBvZiBPYmplY3QudmFsdWVzKHRoaXMuY29uZmlnLnJlc291cmNlcykpIHtcbiAgICAgIGZvciAoY29uc3Qgb3BlcmF0aW9uIG9mIHJlc291cmNlQ29uZmlnLm9wZXJhdGlvbnMpIHtcbiAgICAgICAgY29uc3QgY2FsbGJhY2tOYW1lID0gUFVCTElTSEVEX0NBTExCQUNLX05BTUVTW29wZXJhdGlvbl1cbiAgICAgICAgY29uc3QgY2FsbGJhY2sgPSB0aGlzLnB1Ymxpc2hlZE11dGF0aW9uQ2FsbGJhY2soe29wZXJhdGlvbiwgcmVzb3VyY2VDb25maWd9KVxuXG4gICAgICAgIHJlc291cmNlQ29uZmlnLm1vZGVsQ2xhc3NbY2FsbGJhY2tOYW1lXShjYWxsYmFjaylcbiAgICAgICAgdGhpcy5fcHVibGlzaGVkQ2FsbGJhY2tzLnB1c2goe2NhbGxiYWNrLCBjYWxsYmFja05hbWUsIG1vZGVsQ2xhc3M6IHJlc291cmNlQ29uZmlnLm1vZGVsQ2xhc3N9KVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVbnJlZ2lzdGVycyBhbGwgcHVibGlzaCBjYWxsYmFja3MgKHRlc3RzLCBzaHV0ZG93bikuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgc3RvcCgpIHtcbiAgICBmb3IgKGNvbnN0IHtjYWxsYmFjaywgY2FsbGJhY2tOYW1lLCBtb2RlbENsYXNzfSBvZiB0aGlzLl9wdWJsaXNoZWRDYWxsYmFja3MpIHtcbiAgICAgIG1vZGVsQ2xhc3MudW5yZWdpc3RlckxpZmVjeWNsZUNhbGxiYWNrKGNhbGxiYWNrTmFtZSwgY2FsbGJhY2spXG4gICAgfVxuXG4gICAgdGhpcy5fcHVibGlzaGVkQ2FsbGJhY2tzID0gW11cbiAgICB0aGlzLl9zdGFydGVkID0gZmFsc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgdGhlIGxpZmVjeWNsZSBjYWxsYmFjayBwdWJsaXNoaW5nIG9uZSBzZXJ2ZXItc2lkZSBtdXRhdGlvbi4gVGhlXG4gICAqIHB1Ymxpc2hlZCBwYXlsb2FkIChkZWNsYXJhdGlvbiBgc2VyaWFsaXplYCksIGV2ZW50IHNjb3BlLCBhbmQgc3luYyB0eXBlXG4gICAqIGFyZSBzbmFwc2hvdHRlZCBhdCBtdXRhdGlvbi1jYWxsYmFjayB0aW1lLCBzbyBhZnRlclNhdmUgaG9va3MgYXNzaWduaW5nXG4gICAqIHVuc2F2ZWQgYXR0cmlidXRlcyAob3IgYW55IGxhdGVyIGRyaWZ0IG9uIHRoZSByZWNvcmQpIGNhbm5vdCBjaGFuZ2Ugd2hhdFxuICAgKiBnZXRzIHB1Ymxpc2hlZCB2cyB3aGF0IHdhcyBjb21taXR0ZWQuIFBlcnNpc3RpbmcgYW5kIGJyb2FkY2FzdGluZyBhcmVcbiAgICogZGVmZXJyZWQgdGhyb3VnaCB0aGUgbW9kZWwgY29ubmVjdGlvbidzIGFmdGVyQ29tbWl0IGhvb2sgc28gdGhleSBvbmx5IHJ1blxuICAgKiBvbmNlIHRoZSBtdXRhdGlvbidzIHRyYW5zYWN0aW9uIGhhcyBjb21taXR0ZWQgKGltbWVkaWF0ZWx5IHdoZW4gbm9cbiAgICogdHJhbnNhY3Rpb24gaXMgb3BlbikgLSByb2xsZWQtYmFjayBtdXRhdGlvbnMgbmV2ZXIgcHVibGlzaC4gUG9zdC1jb21taXRcbiAgICogcHVibGlzaCBmYWlsdXJlcyBhcmUgcmVwb3J0ZWQgd2l0aG91dCByZXRocm93aW5nIGludG8gdGhlIGRyaXZlcidzXG4gICAqIGFmdGVyQ29tbWl0IGNoYWluIChzZWUgcmVwb3J0QWZ0ZXJDb21taXRFcnJvcikuXG4gICAqIEBwYXJhbSB7e29wZXJhdGlvbjogXCJjcmVhdGVcIiB8IFwidXBkYXRlXCIgfCBcImRlc3Ryb3lcIiwgcmVzb3VyY2VDb25maWc6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlclJlc291cmNlQ29uZmlnfX0gYXJncyAtIE9wZXJhdGlvbiBhbmQgcmVzb3VyY2UgY29uZmlnLlxuICAgKiBAcmV0dXJucyB7KHJlY29yZDogPykgPT4gUHJvbWlzZTx2b2lkPn0gTGlmZWN5Y2xlIGNhbGxiYWNrLlxuICAgKi9cbiAgcHVibGlzaGVkTXV0YXRpb25DYWxsYmFjayh7b3BlcmF0aW9uLCByZXNvdXJjZUNvbmZpZ30pIHtcbiAgICByZXR1cm4gYXN5bmMgKHJlY29yZCkgPT4ge1xuICAgICAgaWYgKGlzUHVibGlzaGluZ1N1cHByZXNzZWQocmVjb3JkKSkgcmV0dXJuXG5cbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZXNvdXJjZUNvbmZpZy5zZXJpYWxpemUocmVjb3JkKVxuICAgICAgY29uc3QgcmVzb3VyY2VJZCA9IFN0cmluZyhyZWNvcmQuaWQoKSlcbiAgICAgIGNvbnN0IHN5bmNUeXBlID0gb3BlcmF0aW9uID09PSBcImRlc3Ryb3lcIiA/IFwiZGVsZXRlXCIgOiBcInVwZGF0ZVwiXG4gICAgICBjb25zdCBzY29wZVZhbHVlcyA9IGF3YWl0IHRoaXMucHVibGlzaGVkU2NvcGVWYWx1ZXMoe3JlY29yZCwgcmVzb3VyY2VDb25maWd9KVxuICAgICAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi9cbiAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSB7XG4gICAgICAgIFt0aGlzLmNvbmZpZy5hY3RvckZvcmVpZ25LZXlDb2x1bW5dOiBudWxsLFxuICAgICAgICBjbGllbnRfdXBkYXRlZF9hdDogbmV3IERhdGUoKSxcbiAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoZGF0YSksXG4gICAgICAgIHJlc291cmNlX2lkOiByZXNvdXJjZUlkLFxuICAgICAgICByZXNvdXJjZV90eXBlOiByZXNvdXJjZUNvbmZpZy5yZXNvdXJjZVR5cGUsXG4gICAgICAgIHN5bmNfdHlwZTogc3luY1R5cGUsXG4gICAgICAgIC4uLnNjb3BlVmFsdWVzLmNvbHVtbnNcbiAgICAgIH1cblxuICAgICAgYXdhaXQgcmVzb3VyY2VDb25maWcubW9kZWxDbGFzcy5jb25uZWN0aW9uKCkuYWZ0ZXJDb21taXQoYXN5bmMgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHN5bmNSb3cgPSBhd2FpdCB0aGlzLnVwc2VydFB1Ymxpc2hlZFN5bmNSb3coYXR0cmlidXRlcylcblxuICAgICAgICAgIGF3YWl0IHRoaXMuYnJvYWRjYXN0ZXIoKSh7XG4gICAgICAgICAgICBib2R5OiB7XG4gICAgICAgICAgICAgIGVjaG9PcmlnaW46IG51bGwsXG4gICAgICAgICAgICAgIHN5bmNzOiBbe2RhdGEsIHJlc291cmNlSWQsIHJlc291cmNlVHlwZTogcmVzb3VyY2VDb25maWcucmVzb3VyY2VUeXBlLCBzeW5jVHlwZX1dXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2hhbm5lbDogVkVMT0NJT1VTX1NZTkNfQ0hBTk5FTCxcbiAgICAgICAgICAgIHBhcmFtczogey4uLnNjb3BlVmFsdWVzLnBhcmFtcywgcmVzb3VyY2VUeXBlOiByZXNvdXJjZUNvbmZpZy5yZXNvdXJjZVR5cGV9XG4gICAgICAgICAgfSlcblxuICAgICAgICAgIGlmIChyZXNvdXJjZUNvbmZpZy5icm9hZGNhc3RzKSB7XG4gICAgICAgICAgICBhd2FpdCBkZWxpdmVyRGVjbGFyZWRCcm9hZGNhc3RzKHtcbiAgICAgICAgICAgICAgYXJnczoge2RhdGEsIG9wZXJhdGlvbiwgcmVjb3JkLCByZXNvdXJjZUlkLCByZXNvdXJjZVR5cGU6IHJlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZSwgc3luY1Jvdywgc3luY1R5cGV9LFxuICAgICAgICAgICAgICBicm9hZGNhc3RlcjogdGhpcy5icm9hZGNhc3RlcigpLFxuICAgICAgICAgICAgICBicm9hZGNhc3RzOiByZXNvdXJjZUNvbmZpZy5icm9hZGNhc3RzXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLnJlcG9ydEFmdGVyQ29tbWl0RXJyb3IoLyoqIEB0eXBlIHtFcnJvcn0gKi8gKGVycm9yKSlcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgdGhlIHNjb3BlLXBhcnRpdGlvbiB2YWx1ZXMgZm9yIG9uZSBwdWJsaXNoZWQgbXV0YXRpb24gZnJvbSB0aGVcbiAgICogcmVzb3VyY2UncyBkZXJpdmVkIHNjb3BlIHBsYW46IGVhY2ggZW50cnkgcmVhZHMgaXRzIHJlY29yZCBhdHRyaWJ1dGUgKG9yXG4gICAqIHRoZSByZWNvcmQncyBvd24gaWQgZm9yIHNjb3BlLXJvb3QgbW9kZWxzLCBvciB0aGUgZGVwcmVjYXRlZCByZXNvbHZlclxuICAgKiBmdW5jdGlvbikuIFRoZSB2YWx1ZXMgYXJlIHBlcnNpc3RlZCBvbnRvIHRoZSBzeW5jIHJvdydzIHBhcnRpdGlvbiBjb2x1bW5zXG4gICAqIGFuZCBicm9hZGNhc3QgYXMgdGhlIGZyYW1ld29yayBzeW5jIGNoYW5uZWwncyBzY29waW5nIHBhcmFtcy5cbiAgICogQHBhcmFtIHt7cmVjb3JkOiA/LCByZXNvdXJjZUNvbmZpZzogaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyUmVzb3VyY2VDb25maWd9fSBhcmdzIC0gTXV0YXRlZCByZWNvcmQgYW5kIHJlc291cmNlIGNvbmZpZy5cbiAgICogQHJldHVybnMge1Byb21pc2U8e2NvbHVtbnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bGw+LCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bGw+fT59IFNjb3BlIHZhbHVlcyBrZXllZCBieSBzeW5jLXJvdyBjb2x1bW4gYW5kIGJ5IHNjb3BlIGF0dHJpYnV0ZS5cbiAgICovXG4gIGFzeW5jIHB1Ymxpc2hlZFNjb3BlVmFsdWVzKHtyZWNvcmQsIHJlc291cmNlQ29uZmlnfSkge1xuICAgIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVsbD59ICovXG4gICAgY29uc3QgY29sdW1ucyA9IHt9XG4gICAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBudWxsPn0gKi9cbiAgICBjb25zdCBwYXJhbXMgPSB7fVxuXG4gICAgZm9yIChjb25zdCBzY29wZVBsYW5FbnRyeSBvZiByZXNvdXJjZUNvbmZpZy5zY29wZVBsYW4pIHtcbiAgICAgIC8qKiBAdHlwZSB7P30gKi9cbiAgICAgIGxldCByYXdWYWx1ZVxuXG4gICAgICBpZiAoc2NvcGVQbGFuRW50cnkucmVzb2x2ZXIpIHtcbiAgICAgICAgcmF3VmFsdWUgPSBhd2FpdCBzY29wZVBsYW5FbnRyeS5yZXNvbHZlcihyZWNvcmQpXG4gICAgICB9IGVsc2UgaWYgKHNjb3BlUGxhbkVudHJ5LnJlY29yZEF0dHJpYnV0ZSkge1xuICAgICAgICByYXdWYWx1ZSA9IHJlY29yZC5yZWFkQXR0cmlidXRlKHNjb3BlUGxhbkVudHJ5LnJlY29yZEF0dHJpYnV0ZSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJhd1ZhbHVlID0gcmVjb3JkLmlkKClcbiAgICAgIH1cblxuICAgICAgY29uc3QgdmFsdWUgPSByYXdWYWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHJhd1ZhbHVlID09PSBudWxsID8gbnVsbCA6IFN0cmluZyhyYXdWYWx1ZSlcblxuICAgICAgY29sdW1uc1tzY29wZVBsYW5FbnRyeS5jb2x1bW5OYW1lXSA9IHZhbHVlXG4gICAgICBwYXJhbXNbc2NvcGVQbGFuRW50cnkuc2NvcGVBdHRyaWJ1dGVdID0gdmFsdWVcbiAgICB9XG5cbiAgICByZXR1cm4ge2NvbHVtbnMsIHBhcmFtc31cbiAgfVxuXG4gIC8qKlxuICAgKiBVcHNlcnRzIHRoZSBwdWJsaXNoZWQgc2VydmVyLW9yaWdpbiBzeW5jIHJvdyBmb3IgYSByZXNvdXJjZSBpZGVudGl0eTpcbiAgICogc2VydmVyLW9yaWdpbiByb3dzIGNhcnJ5IGEgbnVsbCBhY3RvciBjb2x1bW4gKG5vIGRldmljZSB0byBlY2hvIHRoZVxuICAgKiBjaGFuZ2UgYmFjayB0byksIHNvIHJlcGVhdGVkIHNlcnZlciBjaGFuZ2VzIHRvIG9uZSByZXNvdXJjZSByZXVzZSBhbmRcbiAgICogcmUtc2VxdWVuY2Ugb25lIGZlZWQgcm93LlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsID8+fSBhdHRyaWJ1dGVzIC0gU25hcHNob3R0ZWQgc3luYyByb3cgYXR0cmlidXRlcy5cbiAgICogQHJldHVybnMge1Byb21pc2U8Pz59IFVwc2VydGVkIHN5bmMgcm93LlxuICAgKi9cbiAgYXN5bmMgdXBzZXJ0UHVibGlzaGVkU3luY1JvdyhhdHRyaWJ1dGVzKSB7XG4gICAgY29uc3QgZXhpc3RpbmdTeW5jID0gYXdhaXQgdGhpcy5jb25maWcuc3luY01vZGVsXG4gICAgICAud2hlcmUoe1xuICAgICAgICBbdGhpcy5jb25maWcuYWN0b3JGb3JlaWduS2V5Q29sdW1uXTogbnVsbCxcbiAgICAgICAgcmVzb3VyY2VfaWQ6IGF0dHJpYnV0ZXMucmVzb3VyY2VfaWQsXG4gICAgICAgIHJlc291cmNlX3R5cGU6IGF0dHJpYnV0ZXMucmVzb3VyY2VfdHlwZVxuICAgICAgfSlcbiAgICAgIC5maXJzdCgpXG5cbiAgICByZXR1cm4gYXdhaXQgdXBzZXJ0U3luY1Jvdyh7YXR0cmlidXRlcywgZXhpc3RpbmdTeW5jLCBzeW5jTW9kZWw6IHRoaXMuY29uZmlnLnN5bmNNb2RlbH0pXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYnJvYWRjYXN0ZXIgZGVsaXZlcmluZyBkZWNsYXJlZCBicm9hZGNhc3RzOiB0aGUgaW5qZWN0ZWQgb25lLFxuICAgKiBvciB0aGUgY29uZmlndXJhdGlvbidzIGNoYW5uZWwgYnJvYWRjYXN0IGF3YWl0ZWQgdGhyb3VnaCB0aGUgcGVuZGluZ1xuICAgKiBicm9hZGNhc3QgcXVldWUuXG4gICAqIEByZXR1cm5zIHtOb25OdWxsYWJsZTxpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJPcHRpb25zW1wiYnJvYWRjYXN0ZXJcIl0+fSBCcm9hZGNhc3QgZGVsaXZlcmVyLlxuICAgKi9cbiAgYnJvYWRjYXN0ZXIoKSB7XG4gICAgaWYgKHRoaXMuY29uZmlnLmJyb2FkY2FzdGVyKSByZXR1cm4gdGhpcy5jb25maWcuYnJvYWRjYXN0ZXJcblxuICAgIHJldHVybiBhc3luYyAoe2JvZHksIGNoYW5uZWwsIHBhcmFtc30pID0+IHtcbiAgICAgIHRoaXMuY29uZmlnLmNvbmZpZ3VyYXRpb24uYnJvYWRjYXN0VG9DaGFubmVsKGNoYW5uZWwsIHBhcmFtcywgYm9keSlcbiAgICAgIGF3YWl0IHRoaXMuY29uZmlnLmNvbmZpZ3VyYXRpb24uYXdhaXRQZW5kaW5nQnJvYWRjYXN0cygpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcG9ydHMgYSBwb3N0LWNvbW1pdCBwdWJsaXNoIGZhaWx1cmUuIFRoZSB0cmFuc2FjdGlvbiBoYXMgYWxyZWFkeVxuICAgKiBjb21taXR0ZWQgd2hlbiBhZnRlckNvbW1pdCBjYWxsYmFja3MgcnVuLCBzbyByZXRocm93aW5nIGhlcmUgd291bGQgcG9pc29uXG4gICAqIHRoZSBkcml2ZXIncyBhd2FpdGVkIGFmdGVyQ29tbWl0IGNoYWluIChicmVha2luZyB1bnJlbGF0ZWQgY2FsbGJhY2tzKSAtXG4gICAqIGluc3RlYWQgdGhlIGZhaWx1cmUgZ29lcyB0byB0aGUgY29uZmlndXJlZCBvbkVycm9yIGhvb2ssIG9yIGlzIGVtaXR0ZWQgb25cbiAgICogdGhlIGNvbmZpZ3VyYXRpb24ncyBmcmFtZXdvcmstZXJyb3IvYWxsLWVycm9yIGNoYW5uZWxzIChzbyBwcm9kdWN0aW9uIGJ1Z1xuICAgKiByZXBvcnRpbmcgdmlhIGBjb25maWd1cmF0aW9uLmdldEVycm9yRXZlbnRzKClgIHNlZXMgYSBicm9rZW4gcHVibGlzaFxuICAgKiBwYXRoKSBhbmQgbG9nZ2VkIGxvdWRseSB0aHJvdWdoIHRoZSBwdWJsaXNoZXIncyBsb2dnZXIgd2hlbiBub25lIGlzXG4gICAqIGNvbmZpZ3VyZWQuXG4gICAqIEBwYXJhbSB7RXJyb3J9IGVycm9yIC0gUG9zdC1jb21taXQgcHVibGlzaCBmYWlsdXJlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIHJlcG9ydEFmdGVyQ29tbWl0RXJyb3IoZXJyb3IpIHtcbiAgICBpZiAodGhpcy5jb25maWcub25FcnJvcikge1xuICAgICAgdGhpcy5jb25maWcub25FcnJvcihlcnJvcilcblxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3QgZXJyb3JFdmVudHMgPSB0aGlzLmNvbmZpZy5jb25maWd1cmF0aW9uLmdldEVycm9yRXZlbnRzKClcbiAgICBjb25zdCBwYXlsb2FkID0ge2NvbnRleHQ6IHtzdGFnZTogXCJzeW5jLXB1Ymxpc2gtYWZ0ZXItY29tbWl0XCJ9LCBlcnJvcn1cblxuICAgIGVycm9yRXZlbnRzLmVtaXQoXCJmcmFtZXdvcmstZXJyb3JcIiwgcGF5bG9hZClcbiAgICBlcnJvckV2ZW50cy5lbWl0KFwiYWxsLWVycm9yXCIsIHsuLi5wYXlsb2FkLCBlcnJvclR5cGU6IFwiZnJhbWV3b3JrLWVycm9yXCJ9KVxuXG4gICAgYXdhaXQgdGhpcy5sb2dnZXIoKS5lcnJvcihcIlN5bmNQdWJsaXNoZXIgZmFpbGVkIHRvIHB1Ymxpc2ggYSBzZXJ2ZXItc2lkZSBzeW5jIGNoYW5nZSBhZnRlciBjb21taXRcIiwgZXJyb3IpXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgbGF6aWx5IGJ1aWx0IHB1Ymxpc2hlciBsb2dnZXIuXG4gICAqIEByZXR1cm5zIHtMb2dnZXJ9IFB1Ymxpc2hlciBsb2dnZXIuXG4gICAqL1xuICBsb2dnZXIoKSB7XG4gICAgdGhpcy5fbG9nZ2VyIHx8PSBuZXcgTG9nZ2VyKFwiU3luY1B1Ymxpc2hlclwiLCB7Y29uZmlndXJhdGlvbjogdGhpcy5jb25maWcuY29uZmlndXJhdGlvbn0pXG5cbiAgICByZXR1cm4gdGhpcy5fbG9nZ2VyXG4gIH1cbn1cblxuLyoqXG4gKiBSZXNvbHZlcyBhIG1vZGVsIGNsYXNzJ3MgYWN0aXZlIHB1Ymxpc2ggZGVjbGFyYXRpb24gZnJvbSBgc3RhdGljIHN5bmNgLlxuICogT3B0ZWQtb3V0IChgcHVibGlzaDogZmFsc2VgKSBhbmQgdW5kZWNsYXJlZCBtb2RlbHMgcmVzb2x2ZSB0byBudWxsOyBldmVyeVxuICogb3RoZXIgZGVjbGFyZWQgdmFsdWUgZmxvd3MgaW50byBsb3VkIGRlY2xhcmF0aW9uIHZhbGlkYXRpb24uXG4gKiBAcGFyYW0gez99IG1vZGVsQ2xhc3MgLSBSZWdpc3RlcmVkIG1vZGVsIGNsYXNzLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hEZWNsYXJhdGlvbiB8IG51bGx9IEFjdGl2ZSBwdWJsaXNoIGRlY2xhcmF0aW9uLCBvciBudWxsLlxuICovXG5mdW5jdGlvbiBwdWJsaXNoRGVjbGFyYXRpb25Gb3IobW9kZWxDbGFzcykge1xuICBjb25zdCBkZWNsYXJhdGlvbiA9IG1vZGVsQ2xhc3Muc3luY1xuXG4gIGlmICghZGVjbGFyYXRpb24gfHwgdHlwZW9mIGRlY2xhcmF0aW9uICE9PSBcIm9iamVjdFwiIHx8IGRlY2xhcmF0aW9uLnB1Ymxpc2ggPT09IHVuZGVmaW5lZCB8fCBkZWNsYXJhdGlvbi5wdWJsaXNoID09PSBmYWxzZSkgcmV0dXJuIG51bGxcblxuICByZXR1cm4gZGVjbGFyYXRpb24ucHVibGlzaFxufVxuXG4vKipcbiAqIEJ1aWxkcyBvbmUgcHVibGlzaGVkIHJlc291cmNlIGNvbmZpZyBmcm9tIGEgbW9kZWwncyBgc3RhdGljIHN5bmNgIHB1Ymxpc2hcbiAqIGRlY2xhcmF0aW9uLiBgcHVibGlzaDogdHJ1ZWAgb3B0cyBpbiB3aXRoIGFsbCBkZWZhdWx0cyAoYXR0cmlidXRlIHBheWxvYWQsXG4gKiBkZXJpdmVkIHNjb3BlIHBhcnRpdGlvbiwgY3JlYXRlZC91cGRhdGVkIG9wZXJhdGlvbnMpLlxuICogQHBhcmFtIHt7bW9kZWxDbGFzczogPywgcHVibGlzaDogaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaERlY2xhcmF0aW9uIHwgbnVsbCwgc2NvcGVBdHRyaWJ1dGVzOiBzdHJpbmdbXSB8IG51bGwsIHN5bmNNb2RlbDogP319IGFyZ3MgLSBEZWNsYXJhdGlvbiBhcmdzIHBsdXMgdGhlIHN5bmMgbW9kZWwncyBkZWNsYXJlZCBzY29wZSBhdHRyaWJ1dGVzLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlclJlc291cmNlQ29uZmlnfSBEZXJpdmVkIHJlc291cmNlIGNvbmZpZy5cbiAqL1xuZnVuY3Rpb24gcmVzb3VyY2VDb25maWdGcm9tUHVibGlzaERlY2xhcmF0aW9uKHttb2RlbENsYXNzLCBwdWJsaXNoLCBzY29wZUF0dHJpYnV0ZXM6IHN5bmNTY29wZUF0dHJpYnV0ZXMsIHN5bmNNb2RlbH0pIHtcbiAgY29uc3QgbW9kZWxOYW1lID0gbW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKVxuICBjb25zdCBub3JtYWxpemVkUHVibGlzaCA9IHB1Ymxpc2ggPT09IHRydWUgPyB7fSA6IHB1Ymxpc2hcblxuICBpZiAoIW5vcm1hbGl6ZWRQdWJsaXNoIHx8IHR5cGVvZiBub3JtYWxpemVkUHVibGlzaCAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KG5vcm1hbGl6ZWRQdWJsaXNoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggbXVzdCBiZSB0cnVlLCBmYWxzZSBvciBhIHB1Ymxpc2ggZGVjbGFyYXRpb24gb2JqZWN0LCBnb3Q6ICR7U3RyaW5nKHB1Ymxpc2gpfWApXG4gIH1cblxuICBjb25zdCB7YnJvYWRjYXN0cywgZXZlbnRJZCwgb3BlcmF0aW9ucywgcmVzb3VyY2VUeXBlLCBzY29wZUF0dHJpYnV0ZXMsIHNlcmlhbGl6ZSwgLi4ucmVzdERlY2xhcmF0aW9ufSA9IG5vcm1hbGl6ZWRQdWJsaXNoXG4gIGNvbnN0IHVua25vd25LZXlzID0gT2JqZWN0LmtleXMocmVzdERlY2xhcmF0aW9uKVxuXG4gIGlmICh1bmtub3duS2V5cy5sZW5ndGggPiAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCByZWNlaXZlZCB1bmtub3duIGtleXM6ICR7dW5rbm93bktleXMuam9pbihcIiwgXCIpfSAoc3VwcG9ydGVkOiBicm9hZGNhc3RzLCBldmVudElkIChkZXByZWNhdGVkKSwgb3BlcmF0aW9ucywgcmVzb3VyY2VUeXBlLCBzY29wZUF0dHJpYnV0ZXMsIHNlcmlhbGl6ZSlgKVxuICB9XG4gIGlmIChzZXJpYWxpemUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2Ygc2VyaWFsaXplICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIHNlcmlhbGl6ZSBtdXN0IGJlIGEgZnVuY3Rpb24gYnVpbGRpbmcgdGhlIHB1Ymxpc2hlZCBwYXlsb2FkLCBnb3Q6ICR7U3RyaW5nKHNlcmlhbGl6ZSl9YClcbiAgfVxuICBpZiAob3BlcmF0aW9ucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KG9wZXJhdGlvbnMpIHx8IG9wZXJhdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIG9wZXJhdGlvbnMgbXVzdCBiZSBhIG5vbi1lbXB0eSBhcnJheSBvZiBjcmVhdGUvdXBkYXRlL2Rlc3Ryb3lgKVxuICAgIH1cblxuICAgIGZvciAoY29uc3Qgb3BlcmF0aW9uIG9mIG9wZXJhdGlvbnMpIHtcbiAgICAgIGlmICghKG9wZXJhdGlvbiBpbiBQVUJMSVNIRURfQ0FMTEJBQ0tfTkFNRVMpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggb3BlcmF0aW9ucyBtdXN0IGJlIGNyZWF0ZS91cGRhdGUvZGVzdHJveSwgZ290OiAke1N0cmluZyhvcGVyYXRpb24pfWApXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBicm9hZGNhc3RzLFxuICAgIG1vZGVsQ2xhc3MsXG4gICAgb3BlcmF0aW9uczogb3BlcmF0aW9ucyA9PT0gdW5kZWZpbmVkID8gREVGQVVMVF9QVUJMSVNIRURfT1BFUkFUSU9OUyA6IG9wZXJhdGlvbnMsXG4gICAgcmVzb3VyY2VUeXBlOiByZXNvdXJjZVR5cGUgPT09IHVuZGVmaW5lZCA/IG1vZGVsTmFtZSA6IHJlc291cmNlVHlwZSxcbiAgICBzY29wZVBsYW46IHNjb3BlUGxhbkZvcih7ZXZlbnRJZCwgbW9kZWxDbGFzcywgbW9kZWxOYW1lLCBzY29wZUF0dHJpYnV0ZXMsIHN5bmNNb2RlbCwgc3luY1Njb3BlQXR0cmlidXRlc30pLFxuICAgIHNlcmlhbGl6ZTogc2VyaWFsaXplID09PSB1bmRlZmluZWQgPyBkZWZhdWx0U2VyaWFsaXplZEF0dHJpYnV0ZXMgOiBzZXJpYWxpemVcbiAgfVxufVxuXG4vKipcbiAqIERlcml2ZXMgdGhlIHNjb3BlIHBsYW4gcGFydGl0aW9uaW5nIGEgcHVibGlzaGVkIG1vZGVsJ3MgY2hhbmdlczogb25lIGVudHJ5XG4gKiBwZXIgc2NvcGUgYXR0cmlidXRlIGRlY2xhcmVkIG9uIHRoZSBzeW5jIG1vZGVsIChgc3RhdGljXG4gKiBzeW5jU2NvcGVBdHRyaWJ1dGVzYCksIGVhY2ggcmVhZGluZyB0aGUgcmVjb3JkIGF0dHJpYnV0ZSBuYW1lZCBsaWtlIHRoZVxuICogc2NvcGUgYXR0cmlidXRlIChvdmVycmlkYWJsZSB0aHJvdWdoIHRoZSBkZWNsYXJhdGlvbidzIGBzY29wZUF0dHJpYnV0ZXNgXG4gKiBuYW1lIG1hcCksIG9yIHRoZSByZWNvcmQncyBvd24gaWQgd2hlbiB0aGUgbW9kZWwgaGFzIG5vIHN1Y2ggYXR0cmlidXRlXG4gKiAoc2NvcGUtcm9vdCBtb2RlbHMpLiBUaGUgZGVwcmVjYXRlZCBgZXZlbnRJZGAgZGVjbGFyYXRpb24gZm9ybXMgbWFwIHRvIGFcbiAqIGZpeGVkIGBldmVudElkYC9gZXZlbnRfaWRgIHBsYW4gZm9yIDEuMC41MDMgY29tcGF0aWJpbGl0eS5cbiAqIEBwYXJhbSB7e2V2ZW50SWQ6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hEZWNsYXJhdGlvbkNvbmZpZ1tcImV2ZW50SWRcIl0sIG1vZGVsQ2xhc3M6ID8sIG1vZGVsTmFtZTogc3RyaW5nLCBzY29wZUF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCB1bmRlZmluZWQsIHN5bmNNb2RlbDogPywgc3luY1Njb3BlQXR0cmlidXRlczogc3RyaW5nW10gfCBudWxsfX0gYXJncyAtIERlY2xhcmF0aW9uIGFuZCBzeW5jLW1vZGVsIHNjb3BlIGFyZ3MuXG4gKiBAcmV0dXJucyB7QXJyYXk8aW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyU2NvcGVQbGFuRW50cnk+fSBEZXJpdmVkIHNjb3BlIHBsYW4uXG4gKi9cbmZ1bmN0aW9uIHNjb3BlUGxhbkZvcih7ZXZlbnRJZCwgbW9kZWxDbGFzcywgbW9kZWxOYW1lLCBzY29wZUF0dHJpYnV0ZXMsIHN5bmNNb2RlbCwgc3luY1Njb3BlQXR0cmlidXRlc30pIHtcbiAgY29uc3QgYXR0cmlidXRlTmFtZXMgPSBPYmplY3QudmFsdWVzKG1vZGVsQ2xhc3MuZ2V0Q29sdW1uTmFtZVRvQXR0cmlidXRlTmFtZU1hcCgpKVxuXG4gIGlmIChldmVudElkICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoc2NvcGVBdHRyaWJ1dGVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggY2FuJ3QgZGVjbGFyZSBib3RoIHNjb3BlQXR0cmlidXRlcyBhbmQgdGhlIGRlcHJlY2F0ZWQgZXZlbnRJZCBmb3JtYClcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBldmVudElkID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHJldHVybiBbe2NvbHVtbk5hbWU6IFwiZXZlbnRfaWRcIiwgcmVjb3JkQXR0cmlidXRlOiBudWxsLCByZXNvbHZlcjogZXZlbnRJZCwgc2NvcGVBdHRyaWJ1dGU6IFwiZXZlbnRJZFwifV1cbiAgICB9XG4gICAgaWYgKHR5cGVvZiBldmVudElkICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIGV2ZW50SWQgbXVzdCBiZSBhbiBhdHRyaWJ1dGUtbmFtZSBzdHJpbmcgKG9yIGEgZGVwcmVjYXRlZCByZXNvbHZlciBmdW5jdGlvbiksIGdvdDogJHtTdHJpbmcoZXZlbnRJZCl9YClcbiAgICB9XG4gICAgaWYgKCFhdHRyaWJ1dGVOYW1lcy5pbmNsdWRlcyhldmVudElkKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCBldmVudElkIGF0dHJpYnV0ZSBkb2Vzbid0IGV4aXN0IG9uIHRoZSBtb2RlbDogJHtldmVudElkfWApXG4gICAgfVxuXG4gICAgcmV0dXJuIFt7Y29sdW1uTmFtZTogXCJldmVudF9pZFwiLCByZWNvcmRBdHRyaWJ1dGU6IGV2ZW50SWQsIHJlc29sdmVyOiB1bmRlZmluZWQsIHNjb3BlQXR0cmlidXRlOiBcImV2ZW50SWRcIn1dXG4gIH1cblxuICBpZiAoc2NvcGVBdHRyaWJ1dGVzICE9PSB1bmRlZmluZWQgJiYgIXN5bmNTY29wZUF0dHJpYnV0ZXMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIGRlY2xhcmVzIHNjb3BlQXR0cmlidXRlcyBidXQgdGhlIHN5bmMgbW9kZWwgZGVjbGFyZXMgbm8gc3RhdGljIHN5bmNTY29wZUF0dHJpYnV0ZXNgKVxuICB9XG5cbiAgaWYgKCFzeW5jU2NvcGVBdHRyaWJ1dGVzKSByZXR1cm4gW11cblxuICBpZiAoc2NvcGVBdHRyaWJ1dGVzICE9PSB1bmRlZmluZWQgJiYgKHR5cGVvZiBzY29wZUF0dHJpYnV0ZXMgIT09IFwib2JqZWN0XCIgfHwgQXJyYXkuaXNBcnJheShzY29wZUF0dHJpYnV0ZXMpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggc2NvcGVBdHRyaWJ1dGVzIG11c3QgYmUgYW4gb2JqZWN0IG1hcHBpbmcgc2NvcGUgYXR0cmlidXRlcyB0byByZWNvcmQgYXR0cmlidXRlIG5hbWVzLCBnb3Q6ICR7U3RyaW5nKHNjb3BlQXR0cmlidXRlcyl9YClcbiAgfVxuXG4gIGZvciAoY29uc3Qgc2NvcGVBdHRyaWJ1dGUgb2YgT2JqZWN0LmtleXMoc2NvcGVBdHRyaWJ1dGVzIHx8IHt9KSkge1xuICAgIGlmICghc3luY1Njb3BlQXR0cmlidXRlcy5pbmNsdWRlcyhzY29wZUF0dHJpYnV0ZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggc2NvcGVBdHRyaWJ1dGVzIHJlY2VpdmVkIHVua25vd24gc2NvcGUgYXR0cmlidXRlOiAke3Njb3BlQXR0cmlidXRlfSAodGhlIHN5bmMgbW9kZWwgZGVjbGFyZXM6ICR7c3luY1Njb3BlQXR0cmlidXRlcy5qb2luKFwiLCBcIil9KWApXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHN5bmNTY29wZUF0dHJpYnV0ZXMubWFwKChzY29wZUF0dHJpYnV0ZSkgPT4ge1xuICAgIGNvbnN0IGRlY2xhcmVkUmVjb3JkQXR0cmlidXRlID0gc2NvcGVBdHRyaWJ1dGVzPy5bc2NvcGVBdHRyaWJ1dGVdXG5cbiAgICBpZiAoZGVjbGFyZWRSZWNvcmRBdHRyaWJ1dGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKHR5cGVvZiBkZWNsYXJlZFJlY29yZEF0dHJpYnV0ZSAhPT0gXCJzdHJpbmdcIiB8fCAhYXR0cmlidXRlTmFtZXMuaW5jbHVkZXMoZGVjbGFyZWRSZWNvcmRBdHRyaWJ1dGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggc2NvcGVBdHRyaWJ1dGVzLiR7c2NvcGVBdHRyaWJ1dGV9IG11c3QgbmFtZSBhbiBleGlzdGluZyByZWNvcmQgYXR0cmlidXRlLCBnb3Q6ICR7U3RyaW5nKGRlY2xhcmVkUmVjb3JkQXR0cmlidXRlKX1gKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4ge2NvbHVtbk5hbWU6IHN5bmNTY29wZUNvbHVtbk5hbWUoe3Njb3BlQXR0cmlidXRlLCBzeW5jTW9kZWx9KSwgcmVjb3JkQXR0cmlidXRlOiBkZWNsYXJlZFJlY29yZEF0dHJpYnV0ZSwgcmVzb2x2ZXI6IHVuZGVmaW5lZCwgc2NvcGVBdHRyaWJ1dGV9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbHVtbk5hbWU6IHN5bmNTY29wZUNvbHVtbk5hbWUoe3Njb3BlQXR0cmlidXRlLCBzeW5jTW9kZWx9KSxcbiAgICAgIHJlY29yZEF0dHJpYnV0ZTogYXR0cmlidXRlTmFtZXMuaW5jbHVkZXMoc2NvcGVBdHRyaWJ1dGUpID8gc2NvcGVBdHRyaWJ1dGUgOiBudWxsLFxuICAgICAgcmVzb2x2ZXI6IHVuZGVmaW5lZCxcbiAgICAgIHNjb3BlQXR0cmlidXRlXG4gICAgfVxuICB9KVxufVxuXG4vKipcbiAqIFJlc29sdmVzIHRoZSBzeW5jLXJvdyBjb2x1bW4gcGVyc2lzdGluZyBhIGRlY2xhcmVkIHNjb3BlIGF0dHJpYnV0ZS5cbiAqIEBwYXJhbSB7e3Njb3BlQXR0cmlidXRlOiBzdHJpbmcsIHN5bmNNb2RlbDogP319IGFyZ3MgLSBTY29wZSBhdHRyaWJ1dGUgYW5kIHN5bmMgbW9kZWwuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTeW5jLXJvdyBjb2x1bW4gbmFtZS5cbiAqL1xuZnVuY3Rpb24gc3luY1Njb3BlQ29sdW1uTmFtZSh7c2NvcGVBdHRyaWJ1dGUsIHN5bmNNb2RlbH0pIHtcbiAgY29uc3QgY29sdW1uTmFtZSA9IHN5bmNNb2RlbC5nZXRBdHRyaWJ1dGVOYW1lVG9Db2x1bW5OYW1lTWFwKClbc2NvcGVBdHRyaWJ1dGVdXG5cbiAgaWYgKCFjb2x1bW5OYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke3N5bmNNb2RlbC5uYW1lfSBkZWNsYXJlcyB0aGUgc3luYyBzY29wZSBhdHRyaWJ1dGUgJHtzY29wZUF0dHJpYnV0ZX0gYnV0IGhhcyBubyBtYXRjaGluZyBjb2x1bW4gZm9yIGl0YClcbiAgfVxuXG4gIHJldHVybiBjb2x1bW5OYW1lXG59XG5cbi8qKlxuICogRGVmYXVsdCBwdWJsaXNoIHNlcmlhbGl6ZXI6IHRoZSByZWNvcmQncyBhdHRyaWJ1dGVzIHdpdGggRGF0ZSB2YWx1ZXNcbiAqIHNlcmlhbGl6ZWQgdG8gSVNPIHN0cmluZ3MuXG4gKiBAcGFyYW0gez99IHJlY29yZCAtIE11dGF0ZWQgc2VydmVyIG1vZGVsIHJlY29yZC5cbiAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gU2VyaWFsaXplZCBhdHRyaWJ1dGVzIHBheWxvYWQuXG4gKi9cbmZ1bmN0aW9uIGRlZmF1bHRTZXJpYWxpemVkQXR0cmlidXRlcyhyZWNvcmQpIHtcbiAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi9cbiAgY29uc3QgYXR0cmlidXRlcyA9IHsuLi5yZWNvcmQuYXR0cmlidXRlcygpfVxuXG4gIGZvciAoY29uc3QgW2F0dHJpYnV0ZU5hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhhdHRyaWJ1dGVzKSkge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIGF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV0gPSB2YWx1ZS50b0lTT1N0cmluZygpXG4gIH1cblxuICByZXR1cm4gYXR0cmlidXRlc1xufVxuIl19
@@ -1,12 +1,16 @@
1
1
  /** @typedef {import("../configuration-types.js").VelociousSyncRealtimeChannelDescriptor} VelociousSyncRealtimeChannelDescriptor */
2
2
  /** @typedef {import("../configuration-types.js").VelociousSyncRealtimeWebsocketClient} VelociousSyncRealtimeWebsocketClient */
3
3
  /**
4
- * Derived realtime push bridge for the sync client. Subscribes the declared
5
- * websocket channels (config `sync.client.realtime.channels` callback plus
6
- * model-level `static sync = {realtime: {channel}}` declarations), applies
7
- * pushed changes through the same derived resource applier as pulls (with echo
8
- * suppression against tracked re-queueing), drops own-device messages by echo
9
- * origin, and fires a coalesced `pull()` when subscriptions become ready or
4
+ * Derived realtime push bridge for the sync client. Subscribes every declared
5
+ * pull scope to the framework sync channel ({@link VELOCIOUS_SYNC_CHANNEL})
6
+ * automatically the subscribe params mirror the scope's
7
+ * `{resourceType, conditions}` so the server authorizes them through the same
8
+ * sync resource authorization as pulls plus any deprecated legacy channels
9
+ * (config `sync.client.realtime.channels` callback and model-level
10
+ * `static sync = {realtime: {channel}}` declarations). Pushed changes apply
11
+ * through the same derived resource applier as pulls (with echo suppression
12
+ * against tracked re-queueing), own-device messages are dropped by echo
13
+ * origin, and a coalesced `pull()` fires when subscriptions become ready or
10
14
  * resume so offline gaps close.
11
15
  */
12
16
  export default class SyncRealtimeBridge {
@@ -40,7 +44,7 @@ export default class SyncRealtimeBridge {
40
44
  * Subscribes the derived realtime channels (idempotent and single-flighted):
41
45
  * an active subscription is kept as-is and a concurrent subscribe awaits the
42
46
  * in-flight attempt. Call `unsubscribe()` first to change the context.
43
- * @param {?} [context] - App context passed to the `sync.client.realtime.channels` callback (runtime values like eventId).
47
+ * @param {?} [context] - App context passed to the deprecated `sync.client.realtime.channels` callback (runtime scope values).
44
48
  * @returns {Promise<void>}
45
49
  */
46
50
  subscribe(context?: unknown): Promise<void>;
@@ -85,12 +89,31 @@ export default class SyncRealtimeBridge {
85
89
  */
86
90
  realtimeConfiguration(): import("../configuration-types.js").VelociousSyncClientRealtimeConfiguration;
87
91
  /**
88
- * Derives the channel descriptors to subscribe: model-level static realtime
89
- * declarations plus the config channels callback, failing loudly when none exist.
90
- * @param {?} context - App context passed to the channels callback.
92
+ * Derives the channel descriptors to subscribe: one framework sync channel
93
+ * subscription per declared pull scope (the params mirror the scope's
94
+ * `{resourceType, conditions}`), plus the deprecated legacy paths
95
+ * model-level static realtime declarations and the config channels callback.
96
+ * Fails loudly when nothing is subscribable.
97
+ * @param {?} context - App context passed to the deprecated channels callback.
91
98
  * @returns {Promise<Array<VelociousSyncRealtimeChannelDescriptor>>} Channel descriptors.
92
99
  */
93
100
  channelDescriptors(context: unknown): Promise<Array<VelociousSyncRealtimeChannelDescriptor>>;
101
+ /**
102
+ * Translates a persisted scope's condition keys to the model's attribute
103
+ * names so the framework channel subscription matches the publisher's
104
+ * attribute-named scoping params: `serializedScopeFromQuery` persists the
105
+ * query's model-normalized column names (for example `project_id`), while
106
+ * scope-partition broadcasts carry attribute names (`projectId`). Keys
107
+ * without a column mapping are already attribute names and pass through;
108
+ * scopes on models without a declared sync resource fail loudly because no
109
+ * attribute mapping exists for them.
110
+ * @param {{conditions: Record<string, ?>, resourceType: string}} scopeRow - Active scope row.
111
+ * @returns {Record<string, ?>} Attribute-named scope conditions.
112
+ */
113
+ attributeNamedConditions(scopeRow: {
114
+ conditions: Record<string, unknown>;
115
+ resourceType: string;
116
+ }): Record<string, unknown>;
94
117
  /**
95
118
  * Chains one pushed message onto the serialized apply queue so changes apply
96
119
  * in arrival order; failures go to the sync client's error reporting.
@@ -1 +1 @@
1
- {"version":3,"file":"sync-realtime-bridge.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-realtime-bridge.js"],"names":[],"mappings":"AAIA,mIAAmI;AACnI,+HAA+H;AAE/H;;;;;;;;GAQG;AACH;IACE;;;OAGG;IACH,4BAFW;QAAC,UAAU,EAAE,OAAO,kBAAkB,EAAE,OAAO,CAAA;KAAC,EAkB1D;IAfC,+CAA4B;IAC5B,yJAAyJ;IACzJ,WADW,KAAK,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,OAAO,2BAA2B,EAAE,iCAAiC,CAAA;KAAC,CAAC,CAClI;IACnB,0DAA0D;IAC1D,SADW,oCAAoC,GAAG,IAAI,CACnC;IACnB,4BAA4B;IAC5B,eADW,OAAO,CAAC,IAAI,CAAC,CACc;IACtC,uHAAuH;IACvH,aADW,MAAM,CACG;IACpB,mCAAmC;IACnC,gBADW,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CACL;IAC1B,mCAAmC;IACnC,mBADW,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CACF;IAC7B,4DAA4D;IAC5D,QADW,YAAY,GAAG,aAAa,GAAG,cAAc,CAC5B;IAG9B;;;;;;OAMG;IACH,oBAHW,OAAC,GACC,OAAO,CAAC,IAAI,CAAC,CAYzB;IAED;;;;;;;;;OASG;IACH,oBAHW,OAAC,GACC,OAAO,CAAC,IAAI,CAAC,CAgFzB;IAED;;;;;OAKG;IACH,eAFa,OAAO,CAAC,IAAI,CAAC,CAiBzB;IAED;;;OAGG;IACH,UAFa;QAAC,QAAQ,EAAE,KAAK,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,OAAO,CAAC;YAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;SAAC,CAAC,CAAC;QAAC,KAAK,EAAE,YAAY,GAAG,aAAa,GAAG,cAAc,CAAA;KAAC,CAOnJ;IAED;;;OAGG;IACH,kBAFa,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;OAGG;IACH,yBAFa,OAAO,2BAA2B,EAAE,wCAAwC,CAUxF;IAED;;;;;OAKG;IACH,4BAHW,OAAC,GACC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC,CAsBlE;IAED;;;;;OAKG;IACH,qCAHW;QAAC,IAAI,EAAE,OAAC,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,GACpC,IAAI,CAUhB;IAED;;;;;;OAMG;IACH,qCAHW;QAAC,IAAI,EAAE,OAAC,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,GACpC,OAAO,CAAC,IAAI,CAAC,CAuBzB;IAED;;;;;OAKG;IACH,gBAFa,IAAI,CAchB;CACF;qDAtSa,OAAO,2BAA2B,EAAE,sCAAsC;mDAC1E,OAAO,2BAA2B,EAAE,oCAAoC"}
1
+ {"version":3,"file":"sync-realtime-bridge.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-realtime-bridge.js"],"names":[],"mappings":"AAKA,mIAAmI;AACnI,+HAA+H;AAE/H;;;;;;;;;;;;GAYG;AACH;IACE;;;OAGG;IACH,4BAFW;QAAC,UAAU,EAAE,OAAO,kBAAkB,EAAE,OAAO,CAAA;KAAC,EAkB1D;IAfC,+CAA4B;IAC5B,yJAAyJ;IACzJ,WADW,KAAK,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,OAAO,2BAA2B,EAAE,iCAAiC,CAAA;KAAC,CAAC,CAClI;IACnB,0DAA0D;IAC1D,SADW,oCAAoC,GAAG,IAAI,CACnC;IACnB,4BAA4B;IAC5B,eADW,OAAO,CAAC,IAAI,CAAC,CACc;IACtC,uHAAuH;IACvH,aADW,MAAM,CACG;IACpB,mCAAmC;IACnC,gBADW,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CACL;IAC1B,mCAAmC;IACnC,mBADW,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CACF;IAC7B,4DAA4D;IAC5D,QADW,YAAY,GAAG,aAAa,GAAG,cAAc,CAC5B;IAG9B;;;;;;OAMG;IACH,oBAHW,OAAC,GACC,OAAO,CAAC,IAAI,CAAC,CAYzB;IAED;;;;;;;;;OASG;IACH,oBAHW,OAAC,GACC,OAAO,CAAC,IAAI,CAAC,CAgFzB;IAED;;;;;OAKG;IACH,eAFa,OAAO,CAAC,IAAI,CAAC,CAiBzB;IAED;;;OAGG;IACH,UAFa;QAAC,QAAQ,EAAE,KAAK,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,OAAO,CAAC;YAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;SAAC,CAAC,CAAC;QAAC,KAAK,EAAE,YAAY,GAAG,aAAa,GAAG,cAAc,CAAA;KAAC,CAOnJ;IAED;;;OAGG;IACH,kBAFa,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;OAGG;IACH,yBAFa,OAAO,2BAA2B,EAAE,wCAAwC,CAUxF;IAED;;;;;;;;OAQG;IACH,4BAHW,OAAC,GACC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC,CA6BlE;IAED;;;;;;;;;;;OAWG;IACH,mCAHW;QAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAC,GACnD,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAkB7B;IAED;;;;;OAKG;IACH,qCAHW;QAAC,IAAI,EAAE,OAAC,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,GACpC,IAAI,CAUhB;IAED;;;;;;OAMG;IACH,qCAHW;QAAC,IAAI,EAAE,OAAC,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,GACpC,OAAO,CAAC,IAAI,CAAC,CAuBzB;IAED;;;;;OAKG;IACH,gBAFa,IAAI,CAchB;CACF;qDAlVa,OAAO,2BAA2B,EAAE,sCAAsC;mDAC1E,OAAO,2BAA2B,EAAE,oCAAoC"}