@hartl-services/medusa-base 0.3.0 → 0.4.0

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 (94) hide show
  1. package/.medusa/server/src/admin/index.js +741 -36
  2. package/.medusa/server/src/admin/index.mjs +743 -38
  3. package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/actions/[action_key]/route.js +31 -0
  4. package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/actions/[action_key]/runs/route.js +16 -0
  5. package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/route.js +14 -0
  6. package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/settings/route.js +22 -0
  7. package/.medusa/server/src/api/admin/plugin-features/route.js +6 -4
  8. package/.medusa/server/src/api/middlewares.js +22 -8
  9. package/.medusa/server/src/api/plugin-actions.js +221 -0
  10. package/.medusa/server/src/api/plugin-features-http.js +67 -8
  11. package/.medusa/server/src/modules/plugin-features/domain/plugin-action-runs.js +92 -0
  12. package/.medusa/server/src/modules/plugin-features/domain/plugin-settings.js +213 -0
  13. package/.medusa/server/src/modules/plugin-features/domain/secret-box.js +56 -0
  14. package/.medusa/server/src/modules/plugin-features/migrations/Migration20260928205031.js +16 -0
  15. package/.medusa/server/src/modules/plugin-features/migrations/Migration20260928215428.js +17 -0
  16. package/.medusa/server/src/modules/plugin-features/models/plugin-action-run.js +43 -0
  17. package/.medusa/server/src/modules/plugin-features/models/plugin-setting-state.js +32 -0
  18. package/.medusa/server/src/modules/plugin-features/service.js +419 -17
  19. package/.medusa/server/src/public/action-progress.js +67 -0
  20. package/.medusa/server/src/public/descriptor.js +199 -2
  21. package/.medusa/server/src/public/effective-features.js +9 -5
  22. package/.medusa/server/src/public/enforcement.js +18 -8
  23. package/.medusa/server/src/public/index.js +10 -2
  24. package/.medusa/server/src/public/module-access.js +14 -0
  25. package/.medusa/server/src/public/settings.js +17 -0
  26. package/.medusa/server/src/public/shop-master-data.js +95 -0
  27. package/.medusa/server/src/utils/discover-complete-cart-participants.js +9 -2
  28. package/.medusa/server/src/utils/discover-plugin-features.js +47 -9
  29. package/.medusa/server/src/workflows/hooks/complete-cart-participants.js +28 -16
  30. package/README.md +393 -12
  31. package/dist/admin-components/features/plugin-features/components/PluginActionsSection.d.ts +6 -0
  32. package/dist/admin-components/features/plugin-features/components/PluginActionsSection.js +66 -0
  33. package/dist/admin-components/features/plugin-features/components/PluginDetailPage.d.ts +2 -0
  34. package/dist/admin-components/features/plugin-features/components/PluginDetailPage.js +9 -0
  35. package/dist/admin-components/features/plugin-features/components/PluginFeatureGate.d.ts +22 -0
  36. package/dist/admin-components/features/plugin-features/components/PluginFeatureGate.js +18 -0
  37. package/dist/admin-components/features/plugin-features/components/PluginFeatureSections.d.ts +11 -0
  38. package/dist/admin-components/features/plugin-features/components/PluginFeatureSections.js +19 -0
  39. package/dist/admin-components/features/plugin-features/components/PluginFeaturesCard.d.ts +12 -0
  40. package/dist/admin-components/features/plugin-features/components/PluginFeaturesCard.js +34 -0
  41. package/dist/admin-components/features/plugin-features/components/PluginFeaturesSettingsPage.d.ts +5 -0
  42. package/dist/admin-components/features/plugin-features/components/PluginFeaturesSettingsPage.js +16 -0
  43. package/dist/admin-components/features/plugin-features/components/PluginHubCard.d.ts +7 -0
  44. package/dist/admin-components/features/plugin-features/components/PluginHubCard.js +21 -0
  45. package/dist/admin-components/features/plugin-features/components/PluginPageShell.d.ts +13 -0
  46. package/dist/admin-components/features/plugin-features/components/PluginPageShell.js +20 -0
  47. package/dist/admin-components/features/plugin-features/components/PluginSettingsForm.d.ts +7 -0
  48. package/dist/admin-components/features/plugin-features/components/PluginSettingsForm.js +39 -0
  49. package/dist/admin-components/features/plugin-features/components/PluginStatusChips.d.ts +5 -0
  50. package/dist/admin-components/features/plugin-features/components/PluginStatusChips.js +8 -0
  51. package/dist/admin-components/features/plugin-features/hooks/usePluginFeatureEnabled.d.ts +114 -0
  52. package/dist/admin-components/features/plugin-features/hooks/usePluginFeatureEnabled.js +40 -0
  53. package/dist/admin-components/features/plugin-features/hooks/usePluginFeatures.d.ts +392 -0
  54. package/dist/admin-components/features/plugin-features/hooks/usePluginFeatures.js +128 -0
  55. package/dist/admin-components/features/plugin-features/hooks/usePluginSettingsForm.d.ts +93 -0
  56. package/dist/admin-components/features/plugin-features/hooks/usePluginSettingsForm.js +44 -0
  57. package/dist/admin-components/features/plugin-features/lib/action-runs.d.ts +19 -0
  58. package/dist/admin-components/features/plugin-features/lib/action-runs.js +74 -0
  59. package/dist/admin-components/features/plugin-features/lib/plugin-features-admin-client.d.ts +363 -0
  60. package/dist/admin-components/features/plugin-features/lib/plugin-features-admin-client.js +9 -0
  61. package/dist/admin-components/features/plugin-features/lib/plugin-paths.d.ts +4 -0
  62. package/dist/admin-components/features/plugin-features/lib/plugin-paths.js +4 -0
  63. package/dist/admin-components/features/plugin-features/lib/settings-draft.d.ts +28 -0
  64. package/dist/admin-components/features/plugin-features/lib/settings-draft.js +86 -0
  65. package/dist/admin-components/features/plugin-features/queries/pluginFeatureKeys.d.ts +7 -0
  66. package/dist/admin-components/features/plugin-features/queries/pluginFeatureKeys.js +7 -0
  67. package/dist/admin-components/i18n/texts.d.ts +90 -0
  68. package/dist/admin-components/i18n/texts.js +90 -0
  69. package/dist/admin-components/index.d.ts +14 -0
  70. package/dist/admin-components/index.js +14 -0
  71. package/dist/admin-components/lib/errors.d.ts +6 -0
  72. package/dist/admin-components/lib/errors.js +27 -0
  73. package/dist/admin-components/lib/sdk.d.ts +2 -0
  74. package/dist/admin-components/lib/sdk.js +13 -0
  75. package/dist/public/action-progress.d.ts +25 -0
  76. package/dist/public/action-progress.js +66 -0
  77. package/dist/public/descriptor.d.ts +3 -2
  78. package/dist/public/descriptor.js +198 -1
  79. package/dist/public/effective-features.d.ts +2 -1
  80. package/dist/public/effective-features.js +8 -4
  81. package/dist/public/enforcement.d.ts +7 -0
  82. package/dist/public/enforcement.js +17 -7
  83. package/dist/public/index.d.ts +5 -2
  84. package/dist/public/index.js +9 -1
  85. package/dist/public/module-access.d.ts +3 -0
  86. package/dist/public/module-access.js +13 -0
  87. package/dist/public/settings.d.ts +11 -0
  88. package/dist/public/settings.js +16 -0
  89. package/dist/public/shop-master-data.d.ts +25 -0
  90. package/dist/public/shop-master-data.js +94 -0
  91. package/dist/public/types.d.ts +97 -1
  92. package/dist/utils/discover-plugin-features.d.ts +28 -0
  93. package/dist/utils/discover-plugin-features.js +96 -0
  94. package/package.json +7 -3
@@ -17,7 +17,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  const utils_1 = require("@medusajs/framework/utils");
19
19
  const effective_features_1 = require("../../public/effective-features");
20
+ const shop_master_data_1 = require("../../public/shop-master-data");
21
+ const plugin_settings_1 = require("./domain/plugin-settings");
22
+ const plugin_action_runs_1 = require("./domain/plugin-action-runs");
23
+ const secret_box_1 = require("./domain/secret-box");
24
+ const plugin_action_run_1 = __importDefault(require("./models/plugin-action-run"));
20
25
  const plugin_feature_state_1 = __importDefault(require("./models/plugin-feature-state"));
26
+ const plugin_setting_state_1 = __importDefault(require("./models/plugin-setting-state"));
27
+ /** `undefined` when unset or empty; any other non-string fails closed. */
28
+ const readSettingsSecret = (options) => {
29
+ const value = options?.settingsSecret;
30
+ if (value === undefined || value === null || value === "") {
31
+ return undefined;
32
+ }
33
+ if (typeof value !== "string") {
34
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Die Option settingsSecret des Base-Plugins muss ein String sein.");
35
+ }
36
+ return value;
37
+ };
38
+ // One warning per undecryptable stored secret per process, not per read.
39
+ const reportedUndecryptable = new Set();
21
40
  const toStored = (row) => {
22
41
  const features = {};
23
42
  if (row.features && typeof row.features === "object") {
@@ -29,13 +48,71 @@ const toStored = (row) => {
29
48
  }
30
49
  return { enabled: row.enabled, features, version: Number(row.version) };
31
50
  };
32
- const describe = (descriptor, stored) => {
51
+ const toStoredSettings = (row) => ({
52
+ values: (0, plugin_settings_1.toStoredSettingValues)(row.values),
53
+ version: Number(row.version),
54
+ });
55
+ const describeSetting = (setting) => {
56
+ const { definition, source } = setting;
57
+ const base = {
58
+ key: definition.key,
59
+ label: definition.label,
60
+ description: definition.description ?? null,
61
+ required: definition.required === true,
62
+ is_set: source !== "none",
63
+ source,
64
+ invalidates: [...(definition.invalidates ?? [])],
65
+ };
66
+ switch (definition.type) {
67
+ case "secret":
68
+ return { ...base, type: "secret" };
69
+ case "select":
70
+ return {
71
+ ...base,
72
+ type: "select",
73
+ options: (definition.options ?? []).map((option) => ({
74
+ value: option.value,
75
+ label: option.label,
76
+ })),
77
+ default: typeof definition.default === "string" ? definition.default : null,
78
+ value: typeof setting.value === "string" ? setting.value : null,
79
+ };
80
+ case "number":
81
+ return {
82
+ ...base,
83
+ type: "number",
84
+ min: definition.min ?? null,
85
+ max: definition.max ?? null,
86
+ default: typeof definition.default === "number" ? definition.default : null,
87
+ value: typeof setting.value === "number" ? setting.value : null,
88
+ };
89
+ default:
90
+ return {
91
+ ...base,
92
+ type: definition.type,
93
+ default: definition.default ?? null,
94
+ value: setting.value ?? null,
95
+ };
96
+ }
97
+ };
98
+ const describeSettings = (descriptor, resolved, version) => {
99
+ const missing = (0, plugin_settings_1.missingSettingKeys)(resolved);
100
+ return {
101
+ plugin_key: descriptor.plugin_key,
102
+ version,
103
+ configured: missing.length === 0,
104
+ missing,
105
+ settings: resolved.map(describeSetting),
106
+ };
107
+ };
108
+ const describe = (descriptor, stored, settings) => {
33
109
  const states = (0, effective_features_1.resolvePluginFeatureStates)(descriptor, stored);
34
110
  return {
35
111
  plugin_key: descriptor.plugin_key,
36
112
  label: descriptor.label,
37
113
  description: descriptor.description ?? null,
38
114
  default_enabled: descriptor.default_enabled ?? true,
115
+ switchable: descriptor.switchable ?? true,
39
116
  enabled: states.enabled,
40
117
  version: stored?.version ?? 0,
41
118
  features: states.features.map((state) => ({
@@ -47,15 +124,50 @@ const describe = (descriptor, stored) => {
47
124
  enabled: state.enabled,
48
125
  effective_enabled: state.effective_enabled,
49
126
  })),
127
+ settings: settings.settings,
128
+ configured: settings.configured,
129
+ missing: settings.missing,
130
+ settings_version: settings.version,
131
+ actions: (descriptor.actions ?? []).map((action) => ({
132
+ key: action.key,
133
+ label: action.label,
134
+ description: action.description ?? null,
135
+ mode: action.mode,
136
+ confirm: action.confirm ?? null,
137
+ })),
138
+ admin_page: descriptor.admin_page ?? null,
50
139
  };
51
140
  };
141
+ const requireTransaction = (sharedContext, what) => {
142
+ const manager = sharedContext.transactionManager;
143
+ if (!manager) {
144
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Für die Aktualisierung ${what} fehlt die Transaktion.`);
145
+ }
146
+ return manager;
147
+ };
148
+ const assertExpectedVersion = (expectedVersion) => {
149
+ if (!Number.isInteger(expectedVersion) || expectedVersion < 0) {
150
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "expected_version muss eine nicht-negative ganze Zahl sein.");
151
+ }
152
+ };
52
153
  /**
53
- * Persists configured toggle values per plugin. The descriptor (declared by
54
- * the owning plugin) is always passed in; this module never imports plugins.
154
+ * Persists configured toggle values and runtime settings per plugin. The
155
+ * descriptor (declared by the owning plugin) is always passed in; this module
156
+ * never imports plugins.
55
157
  */
56
158
  class PluginFeaturesModuleService extends (0, utils_1.MedusaService)({
57
159
  PluginFeatureState: plugin_feature_state_1.default,
160
+ PluginSettingState: plugin_setting_state_1.default,
161
+ PluginActionRun: plugin_action_run_1.default,
58
162
  }) {
163
+ /** Medusa passes the plugin's options to its modules as `options`. */
164
+ constructor(cradle, options, ...rest) {
165
+ super(cradle, options, ...rest);
166
+ /** The base's own settings: the shop master data. */
167
+ this.pluginFeatures = shop_master_data_1.shopMasterDataDescriptor;
168
+ this.cradle_ = cradle;
169
+ this.settingsSecret_ = readSettingsSecret(options);
170
+ }
59
171
  async retrieveEffectiveFeatures(descriptor, sharedContext = {}) {
60
172
  const stored = await this.retrieveStored(descriptor.plugin_key, sharedContext);
61
173
  return (0, effective_features_1.resolveEffectivePluginFeatures)(descriptor, stored);
@@ -69,23 +181,23 @@ class PluginFeaturesModuleService extends (0, utils_1.MedusaService)({
69
181
  const storedByKey = new Map(rows.map((row) => [row.plugin_key, toStored(row)]));
70
182
  return descriptors.map((descriptor) => (0, effective_features_1.resolveEffectivePluginFeatures)(descriptor, storedByKey.get(descriptor.plugin_key) ?? null));
71
183
  }
72
- async describePluginFeatures(descriptor, sharedContext = {}) {
184
+ /** Toggles plus settings (no secret values), actions and the Admin page. */
185
+ async describePluginFeatures(descriptor, fallback, sharedContext = {}) {
73
186
  const stored = await this.retrieveStored(descriptor.plugin_key, sharedContext);
74
- return describe(descriptor, stored);
187
+ const settings = await this.retrieveStoredSettings(descriptor.plugin_key, sharedContext);
188
+ return describe(descriptor, stored, this.describeStoredSettings(descriptor, settings, fallback));
75
189
  }
76
190
  /**
77
191
  * Optimistic concurrency: `expected_version` 0 inserts the first row, any
78
192
  * other value updates exactly that version. A lost race is `CONFLICT`.
79
193
  */
80
- async updatePluginFeatures(descriptor, input, sharedContext = {}) {
194
+ async updatePluginFeatures(descriptor, input, fallback, sharedContext = {}) {
81
195
  const features = (0, effective_features_1.validateFeatureUpdate)(descriptor, input.features);
82
- if (!Number.isInteger(input.expected_version) || input.expected_version < 0) {
83
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "expected_version muss eine nicht-negative ganze Zahl sein.");
84
- }
85
- const manager = sharedContext.transactionManager;
86
- if (!manager) {
87
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Für die Aktualisierung der Funktionsschalter fehlt die Transaktion.");
196
+ assertExpectedVersion(input.expected_version);
197
+ if (descriptor.switchable === false && input.enabled !== true) {
198
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Plugin "${descriptor.plugin_key}" kann nicht ausgeschaltet werden.`);
88
199
  }
200
+ const manager = requireTransaction(sharedContext, "der Funktionsschalter");
89
201
  const featuresJson = JSON.stringify(features);
90
202
  const rows = input.expected_version === 0
91
203
  ? await manager.execute(`insert into "plugin_feature_state"
@@ -118,12 +230,253 @@ class PluginFeaturesModuleService extends (0, utils_1.MedusaService)({
118
230
  if (!saved) {
119
231
  throw new utils_1.MedusaError(utils_1.MedusaError.Types.CONFLICT, `Die Funktionsschalter für Plugin "${descriptor.plugin_key}" wurden zwischenzeitlich geändert.`);
120
232
  }
121
- return describe(descriptor, toStored(saved));
233
+ const settings = await this.retrieveStoredSettings(descriptor.plugin_key, sharedContext);
234
+ return describe(descriptor, toStored(saved), this.describeStoredSettings(descriptor, settings, fallback));
235
+ }
236
+ /** Settings with value source; secret values are never included. */
237
+ async describePluginSettings(descriptor, fallback, sharedContext = {}) {
238
+ const stored = await this.retrieveStoredSettings(descriptor.plugin_key, sharedContext);
239
+ return this.describeStoredSettings(descriptor, stored, fallback);
240
+ }
241
+ /**
242
+ * Resolved settings for server-side consumers, secrets DECRYPTED. Never
243
+ * return this to an HTTP client.
244
+ */
245
+ async resolvePluginSettings(descriptor, fallback, sharedContext = {}) {
246
+ const stored = await this.retrieveStoredSettings(descriptor.plugin_key, sharedContext);
247
+ const resolved = this.resolveStoredSettings(descriptor, stored, fallback);
248
+ const values = {};
249
+ for (const setting of resolved) {
250
+ if (setting.value !== undefined) {
251
+ values[setting.definition.key] = setting.value;
252
+ }
253
+ }
254
+ const missing = (0, plugin_settings_1.missingSettingKeys)(resolved);
255
+ return { values, configured: missing.length === 0, missing };
256
+ }
257
+ /**
258
+ * Merges `values` into the stored settings in one transaction: `null`
259
+ * deletes a key, secrets are sealed, secrets not sent stay, keys the
260
+ * descriptor no longer declares are dropped. Optimistic concurrency like
261
+ * the toggles: a stale `expected_version` is `CONFLICT`.
262
+ */
263
+ async updatePluginSettings(descriptor, input, fallback, sharedContext = {}) {
264
+ const update = (0, plugin_settings_1.validateSettingsUpdate)(descriptor, input.values ?? {});
265
+ assertExpectedVersion(input.expected_version);
266
+ const manager = requireTransaction(sharedContext, "der Einstellungen");
267
+ const conflict = () => new utils_1.MedusaError(utils_1.MedusaError.Types.CONFLICT, `Die Einstellungen für Plugin "${descriptor.plugin_key}" wurden zwischenzeitlich geändert.`);
268
+ const [currentRow] = await manager.execute(`select "values", "version" from "plugin_setting_state"
269
+ where "plugin_key" = ? and "deleted_at" is null
270
+ for update`, [descriptor.plugin_key], "all");
271
+ const current = currentRow ? toStoredSettings(currentRow) : null;
272
+ if ((current?.version ?? 0) !== input.expected_version) {
273
+ throw conflict();
274
+ }
275
+ const keyMaterial = Object.keys(update).some((key) => update[key] !== null &&
276
+ descriptor.settings?.find((setting) => setting.key === key)?.type ===
277
+ "secret")
278
+ ? this.requireKeyMaterial()
279
+ : "";
280
+ const merged = (0, plugin_settings_1.mergeStoredSettings)(descriptor, current?.values ?? {}, update, (plaintext, key) => (0, secret_box_1.sealSecret)(plaintext, keyMaterial, (0, secret_box_1.secretBinding)(descriptor.plugin_key, key)));
281
+ const valuesJson = JSON.stringify(merged.values);
282
+ const rows = input.expected_version === 0
283
+ ? await manager.execute(`insert into "plugin_setting_state"
284
+ ("id", "plugin_key", "values", "version",
285
+ "created_at", "updated_at")
286
+ values (?, ?, ?::jsonb, 1, now(), now())
287
+ on conflict do nothing
288
+ returning "values", "version"`, [
289
+ (0, utils_1.generateEntityId)(undefined, "plgset"),
290
+ descriptor.plugin_key,
291
+ valuesJson,
292
+ ], "all")
293
+ : await manager.execute(`update "plugin_setting_state"
294
+ set "values" = ?::jsonb,
295
+ "version" = ?,
296
+ "updated_at" = now()
297
+ where "plugin_key" = ?
298
+ and "version" = ?
299
+ and "deleted_at" is null
300
+ returning "values", "version"`, [
301
+ valuesJson,
302
+ input.expected_version + 1,
303
+ descriptor.plugin_key,
304
+ input.expected_version,
305
+ ], "all");
306
+ const saved = rows[0];
307
+ if (!saved) {
308
+ throw conflict();
309
+ }
310
+ const toggles = await this.retrieveStored(descriptor.plugin_key, sharedContext);
311
+ return {
312
+ plugin: describe(descriptor, toggles, this.describeStoredSettings(descriptor, toStoredSettings(saved), fallback)),
313
+ changed_keys: merged.changed_keys,
314
+ };
315
+ }
316
+ /**
317
+ * Records a new `running` run unless the same action is already running
318
+ * (then `started: false` with that run). First persists runs that the
319
+ * stale rule declares dead as failed, so a lost run never blocks forever;
320
+ * this is the only place that writes the stale state.
321
+ */
322
+ async startPluginActionRun(input, sharedContext = {}) {
323
+ const manager = requireTransaction(sharedContext, "des Aktionslaufs");
324
+ await this.abortStaleRuns(manager, input.plugin_key, input.action_key);
325
+ const [inserted] = await manager.execute(`insert into "plugin_action_run"
326
+ ("id", "plugin_key", "action_key", "status", "started_at",
327
+ "triggered_by", "created_at", "updated_at")
328
+ values (?, ?, ?, 'running', now(), ?, now(), now())
329
+ on conflict do nothing
330
+ returning *`, [
331
+ (0, utils_1.generateEntityId)(undefined, "plgrun"),
332
+ input.plugin_key,
333
+ input.action_key,
334
+ input.triggered_by,
335
+ ], "all");
336
+ if (inserted) {
337
+ return { started: true, run: (0, plugin_action_runs_1.toRunRecord)(inserted) };
338
+ }
339
+ const [running] = await manager.execute(`select * from "plugin_action_run"
340
+ where "plugin_key" = ? and "action_key" = ?
341
+ and "status" = 'running' and "deleted_at" is null
342
+ limit 1`, [input.plugin_key, input.action_key], "all");
343
+ if (!running) {
344
+ // The running run finished between insert and select; rare, retryable.
345
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.CONFLICT, "Diese Aktion läuft bereits.");
346
+ }
347
+ return { started: false, run: (0, plugin_action_runs_1.toRunRecord)(running) };
348
+ }
349
+ /**
350
+ * Records the outcome of a run. Returns `null` for an unknown run. Records
351
+ * the real outcome also when the stale rule had marked the run failed.
352
+ */
353
+ async finishPluginActionRun(runId, outcome, sharedContext = {}) {
354
+ const manager = requireTransaction(sharedContext, "des Aktionslaufs");
355
+ const columns = (0, plugin_action_runs_1.finishedRunColumns)(outcome);
356
+ const [row] = await manager.execute(`update "plugin_action_run"
357
+ set "status" = ?,
358
+ "message" = ?,
359
+ "result" = ?::jsonb,
360
+ "finished_at" = now(),
361
+ "updated_at" = now()
362
+ where "id" = ? and "deleted_at" is null
363
+ returning *`, [
364
+ columns.status,
365
+ columns.message,
366
+ columns.result === null ? null : JSON.stringify(columns.result),
367
+ runId,
368
+ ], "all");
369
+ return row ? (0, plugin_action_runs_1.toRunRecord)(row) : null;
370
+ }
371
+ /** Stores progress of a `running` run; `false` for an unknown or finished run. */
372
+ async reportPluginActionRunProgress(runId, progress, sharedContext = {}) {
373
+ const manager = requireTransaction(sharedContext, "des Aktionslaufs");
374
+ const rows = await manager.execute(`update "plugin_action_run"
375
+ set "progress" = ?::jsonb, "updated_at" = now()
376
+ where "id" = ? and "status" = 'running' and "deleted_at" is null
377
+ returning "id"`, [JSON.stringify(progress), runId], "all");
378
+ return rows.length > 0;
379
+ }
380
+ /**
381
+ * Latest runs of one action, newest first. Read-only: a run the stale rule
382
+ * declares dead is reported `failed` with "Abgebrochen (Neustart)" (and its
383
+ * last sign of life as `finished_at`), but only persisted as such by the
384
+ * next start attempt (`startPluginActionRun`).
385
+ */
386
+ async listRecentPluginActionRuns(pluginKey, actionKey, limit, sharedContext = {}) {
387
+ const manager = sharedContext.manager;
388
+ if (!manager) {
389
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Für das Lesen der Aktionsläufe fehlt der EntityManager.");
390
+ }
391
+ const rows = await manager.execute(`with "runs" as (
392
+ select *,
393
+ ("status" = 'running'
394
+ and "updated_at" < now() - make_interval(secs => ?)) as "stale"
395
+ from "plugin_action_run"
396
+ where "plugin_key" = ? and "action_key" = ? and "deleted_at" is null
397
+ order by "started_at" desc, "id" desc
398
+ limit ?
399
+ )
400
+ select "id", "plugin_key", "action_key",
401
+ case when "stale" then 'failed' else "status" end as "status",
402
+ "started_at",
403
+ case when "stale" then "updated_at" else "finished_at" end
404
+ as "finished_at",
405
+ "triggered_by",
406
+ case when "stale" then ? else "message" end as "message",
407
+ "progress", "result"
408
+ from "runs"
409
+ order by "started_at" desc, "id" desc`, [
410
+ plugin_action_runs_1.PLUGIN_ACTION_RUN_STALE_AFTER_MS / 1000,
411
+ pluginKey,
412
+ actionKey,
413
+ limit,
414
+ plugin_action_runs_1.PLUGIN_ACTION_RUN_ABORTED_MESSAGE,
415
+ ], "all");
416
+ return rows.map(plugin_action_runs_1.toRunRecord);
417
+ }
418
+ /**
419
+ * The lazy restart rule (see `isStaleRun`): a `running` run without start
420
+ * or progress for an hour will never finish and is marked failed.
421
+ */
422
+ async abortStaleRuns(manager, pluginKey, actionKey) {
423
+ await manager.execute(`update "plugin_action_run"
424
+ set "status" = 'failed',
425
+ "message" = ?,
426
+ "finished_at" = now(),
427
+ "updated_at" = now()
428
+ where "plugin_key" = ? and "action_key" = ?
429
+ and "status" = 'running' and "deleted_at" is null
430
+ and "updated_at" < now() - make_interval(secs => ?)`, [
431
+ plugin_action_runs_1.PLUGIN_ACTION_RUN_ABORTED_MESSAGE,
432
+ pluginKey,
433
+ actionKey,
434
+ plugin_action_runs_1.PLUGIN_ACTION_RUN_STALE_AFTER_MS / 1000,
435
+ ], "run");
436
+ }
437
+ describeStoredSettings(descriptor, stored, fallback) {
438
+ return describeSettings(descriptor, this.resolveStoredSettings(descriptor, stored, fallback), stored?.version ?? 0);
439
+ }
440
+ resolveStoredSettings(descriptor, stored, fallback) {
441
+ return (0, plugin_settings_1.resolveSettingValues)(descriptor, stored?.values ?? {}, fallback, (key, sealed) => this.tryOpen(descriptor.plugin_key, key, sealed));
442
+ }
443
+ /** `undefined` (logged once) when the secret cannot be decrypted. */
444
+ tryOpen(pluginKey, key, sealed) {
445
+ try {
446
+ return (0, secret_box_1.openSecret)(sealed, this.requireKeyMaterial(), (0, secret_box_1.secretBinding)(pluginKey, key));
447
+ }
448
+ catch (error) {
449
+ const marker = `${pluginKey}:${key}:${sealed}`;
450
+ if (!reportedUndecryptable.has(marker)) {
451
+ reportedUndecryptable.add(marker);
452
+ this.cradle_.logger?.warn(`Geheime Einstellung "${key}" von Plugin "${pluginKey}" kann nicht entschlüsselt werden und gilt als nicht gesetzt (wurde settingsSecret bzw. COOKIE_SECRET geändert?): ${error instanceof Error ? error.message : String(error)}`);
453
+ }
454
+ return undefined;
455
+ }
456
+ }
457
+ /**
458
+ * The plugin option `settingsSecret`, else `http.cookieSecret` from the
459
+ * project config (Medusa 2.19.0 always sets it, "supersecret" outside
460
+ * production when unset).
461
+ */
462
+ requireKeyMaterial() {
463
+ if (this.settingsSecret_) {
464
+ return this.settingsSecret_;
465
+ }
466
+ const cookieSecret = this.cradle_.configModule?.projectConfig?.http?.cookieSecret;
467
+ if (typeof cookieSecret === "string" && cookieSecret) {
468
+ return cookieSecret;
469
+ }
470
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Für geheime Einstellungen fehlt die Plugin-Option settingsSecret bzw. projectConfig.http.cookieSecret.");
122
471
  }
123
472
  async retrieveStored(pluginKey, sharedContext) {
124
473
  const [row] = await this.listPluginFeatureStates({ plugin_key: pluginKey }, { take: 1 }, sharedContext);
125
474
  return row ? toStored(row) : null;
126
475
  }
476
+ async retrieveStoredSettings(pluginKey, sharedContext) {
477
+ const [row] = await this.listPluginSettingStates({ plugin_key: pluginKey }, { take: 1 }, sharedContext);
478
+ return row ? toStoredSettings(row) : null;
479
+ }
127
480
  }
128
481
  __decorate([
129
482
  (0, utils_1.InjectManager)(),
@@ -141,17 +494,66 @@ __decorate([
141
494
  ], PluginFeaturesModuleService.prototype, "listEffectiveFeatures", null);
142
495
  __decorate([
143
496
  (0, utils_1.InjectManager)(),
144
- __param(1, (0, utils_1.MedusaContext)()),
497
+ __param(2, (0, utils_1.MedusaContext)()),
145
498
  __metadata("design:type", Function),
146
- __metadata("design:paramtypes", [Object, Object]),
499
+ __metadata("design:paramtypes", [Object, Object, Object]),
147
500
  __metadata("design:returntype", Promise)
148
501
  ], PluginFeaturesModuleService.prototype, "describePluginFeatures", null);
149
502
  __decorate([
150
503
  (0, utils_1.InjectTransactionManager)(),
504
+ __param(3, (0, utils_1.MedusaContext)()),
505
+ __metadata("design:type", Function),
506
+ __metadata("design:paramtypes", [Object, Object, Object, Object]),
507
+ __metadata("design:returntype", Promise)
508
+ ], PluginFeaturesModuleService.prototype, "updatePluginFeatures", null);
509
+ __decorate([
510
+ (0, utils_1.InjectManager)(),
151
511
  __param(2, (0, utils_1.MedusaContext)()),
152
512
  __metadata("design:type", Function),
153
513
  __metadata("design:paramtypes", [Object, Object, Object]),
154
514
  __metadata("design:returntype", Promise)
155
- ], PluginFeaturesModuleService.prototype, "updatePluginFeatures", null);
515
+ ], PluginFeaturesModuleService.prototype, "describePluginSettings", null);
516
+ __decorate([
517
+ (0, utils_1.InjectManager)(),
518
+ __param(2, (0, utils_1.MedusaContext)()),
519
+ __metadata("design:type", Function),
520
+ __metadata("design:paramtypes", [Object, Object, Object]),
521
+ __metadata("design:returntype", Promise)
522
+ ], PluginFeaturesModuleService.prototype, "resolvePluginSettings", null);
523
+ __decorate([
524
+ (0, utils_1.InjectTransactionManager)(),
525
+ __param(3, (0, utils_1.MedusaContext)()),
526
+ __metadata("design:type", Function),
527
+ __metadata("design:paramtypes", [Object, Object, Object, Object]),
528
+ __metadata("design:returntype", Promise)
529
+ ], PluginFeaturesModuleService.prototype, "updatePluginSettings", null);
530
+ __decorate([
531
+ (0, utils_1.InjectTransactionManager)(),
532
+ __param(1, (0, utils_1.MedusaContext)()),
533
+ __metadata("design:type", Function),
534
+ __metadata("design:paramtypes", [Object, Object]),
535
+ __metadata("design:returntype", Promise)
536
+ ], PluginFeaturesModuleService.prototype, "startPluginActionRun", null);
537
+ __decorate([
538
+ (0, utils_1.InjectTransactionManager)(),
539
+ __param(2, (0, utils_1.MedusaContext)()),
540
+ __metadata("design:type", Function),
541
+ __metadata("design:paramtypes", [String, Object, Object]),
542
+ __metadata("design:returntype", Promise)
543
+ ], PluginFeaturesModuleService.prototype, "finishPluginActionRun", null);
544
+ __decorate([
545
+ (0, utils_1.InjectTransactionManager)(),
546
+ __param(2, (0, utils_1.MedusaContext)()),
547
+ __metadata("design:type", Function),
548
+ __metadata("design:paramtypes", [String, Object, Object]),
549
+ __metadata("design:returntype", Promise)
550
+ ], PluginFeaturesModuleService.prototype, "reportPluginActionRunProgress", null);
551
+ __decorate([
552
+ (0, utils_1.InjectManager)(),
553
+ __param(3, (0, utils_1.MedusaContext)()),
554
+ __metadata("design:type", Function),
555
+ __metadata("design:paramtypes", [String, String, Number, Object]),
556
+ __metadata("design:returntype", Promise)
557
+ ], PluginFeaturesModuleService.prototype, "listRecentPluginActionRuns", null);
156
558
  exports.default = PluginFeaturesModuleService;
157
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL3BsdWdpbi1mZWF0dXJlcy9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUEscURBT2tDO0FBRWxDLHdFQUl3QztBQU14Qyx5RkFBOEQ7QUFzQjlELE1BQU0sUUFBUSxHQUFHLENBQ2YsR0FBMkIsRUFDaUIsRUFBRTtJQUM5QyxNQUFNLFFBQVEsR0FBNEIsRUFBRSxDQUFBO0lBQzVDLElBQUksR0FBRyxDQUFDLFFBQVEsSUFBSSxPQUFPLEdBQUcsQ0FBQyxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDckQsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDeEQsSUFBSSxPQUFPLEtBQUssS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDL0IsUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQTtZQUN2QixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLEVBQUUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUE7QUFDekUsQ0FBQyxDQUFBO0FBRUQsTUFBTSxRQUFRLEdBQUcsQ0FDZixVQUFtQyxFQUNuQyxNQUEyRCxFQUN0QyxFQUFFO0lBQ3ZCLE1BQU0sTUFBTSxHQUFHLElBQUEsK0NBQTBCLEVBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFBO0lBRTdELE9BQU87UUFDTCxVQUFVLEVBQUUsVUFBVSxDQUFDLFVBQVU7UUFDakMsS0FBSyxFQUFFLFVBQVUsQ0FBQyxLQUFLO1FBQ3ZCLFdBQVcsRUFBRSxVQUFVLENBQUMsV0FBVyxJQUFJLElB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
559
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL3BsdWdpbi1mZWF0dXJlcy9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBTUEscURBT2tDO0FBRWxDLHdFQUl3QztBQUN4QyxvRUFBd0U7QUFVeEUsOERBUWlDO0FBRWpDLG9FQU9vQztBQUNwQyxvREFBMkU7QUFDM0UsbUZBQXdEO0FBQ3hELHlGQUE4RDtBQUM5RCx5RkFBOEQ7QUFnRTlELDBFQUEwRTtBQUMxRSxNQUFNLGtCQUFrQixHQUFHLENBQ3pCLE9BQXNDLEVBQ2xCLEVBQUU7SUFDdEIsTUFBTSxLQUFLLEdBQVksT0FBTyxFQUFFLGNBQWMsQ0FBQTtJQUM5QyxJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLEtBQUssRUFBRSxFQUFFLENBQUM7UUFDMUQsT0FBTyxTQUFTLENBQUE7SUFDbEIsQ0FBQztJQUNELElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDOUIsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsa0VBQWtFLENBQ25FLENBQUE7SUFDSCxDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUE7QUFDZCxDQUFDLENBQUE7QUFFRCx5RUFBeUU7QUFDekUsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFBO0FBRS9DLE1BQU0sUUFBUSxHQUFHLENBQ2YsR0FBMkIsRUFDaUIsRUFBRTtJQUM5QyxNQUFNLFFBQVEsR0FBNEIsRUFBRSxDQUFBO0lBQzVDLElBQUksR0FBRyxDQUFDLFFBQVEsSUFBSSxPQUFPLEdBQUcsQ0FBQyxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDckQsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FB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
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PLUGIN_ACTION_PROGRESS_LABEL_MAX_LENGTH = void 0;
4
+ exports.normalizeActionProgress = normalizeActionProgress;
5
+ exports.reportPluginActionProgress = reportPluginActionProgress;
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ const module_access_1 = require("./module-access");
8
+ /** Longest stored progress label; longer labels are cut. */
9
+ exports.PLUGIN_ACTION_PROGRESS_LABEL_MAX_LENGTH = 200;
10
+ const isCount = (value) => typeof value === "number" && Number.isInteger(value) && value >= 0;
11
+ /**
12
+ * Validates and normalizes reported progress: `current` and `total` are
13
+ * non-negative integers (`total` may be unknown), a blank label is `null`
14
+ * and a long one is cut. Throws `INVALID_DATA`.
15
+ */
16
+ function normalizeActionProgress(progress) {
17
+ if (!isCount(progress?.current)) {
18
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Fortschritt: current muss eine nicht-negative ganze Zahl sein.");
19
+ }
20
+ const total = progress.total ?? null;
21
+ if (total !== null && !isCount(total)) {
22
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Fortschritt: total muss eine nicht-negative ganze Zahl oder null sein.");
23
+ }
24
+ const label = typeof progress.label === "string" && progress.label.trim()
25
+ ? progress.label.trim().slice(0, exports.PLUGIN_ACTION_PROGRESS_LABEL_MAX_LENGTH)
26
+ : null;
27
+ return { current: progress.current, total, label };
28
+ }
29
+ const warn = (container, message) => {
30
+ try {
31
+ container.resolve(utils_1.ContainerRegistrationKeys.LOGGER).warn(message);
32
+ }
33
+ catch {
34
+ // Progress is informational; logging must not fail the action.
35
+ }
36
+ };
37
+ /**
38
+ * Stores the progress of a running action (shown in the Admin while it
39
+ * runs). Call it from the action's workflow with `input.run_id`. Without a
40
+ * `run_id` (e.g. the same workflow run from a script) it does nothing. An
41
+ * unknown or finished run, a failed write and invalid progress (negative
42
+ * or non-integer numbers) are logged as a warning and dropped; progress
43
+ * never fails the action.
44
+ */
45
+ async function reportPluginActionProgress(container, runId, progress) {
46
+ let normalized;
47
+ try {
48
+ normalized = normalizeActionProgress(progress);
49
+ }
50
+ catch (error) {
51
+ warn(container, `Ungültiger Fortschritt${runId ? ` für Aktionslauf "${runId}"` : ""} verworfen: ${error instanceof Error ? error.message : String(error)}`);
52
+ return;
53
+ }
54
+ if (!runId) {
55
+ return;
56
+ }
57
+ try {
58
+ const updated = await (0, module_access_1.resolveBaseModule)(container).reportPluginActionRunProgress(runId, normalized);
59
+ if (!updated) {
60
+ warn(container, `Fortschritt für Aktionslauf "${runId}" verworfen: Lauf unbekannt oder nicht mehr aktiv.`);
61
+ }
62
+ }
63
+ catch (error) {
64
+ warn(container, `Fortschritt für Aktionslauf "${runId}" konnte nicht gespeichert werden: ${error instanceof Error ? error.message : String(error)}`);
65
+ }
66
+ }
67
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWN0aW9uLXByb2dyZXNzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3B1YmxpYy9hY3Rpb24tcHJvZ3Jlc3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBd0JBLDBEQXFCQztBQTBCRCxnRUFzQ0M7QUE1R0QscURBQWtGO0FBRWxGLG1EQUFtRDtBQVVuRCw0REFBNEQ7QUFDL0MsUUFBQSx1Q0FBdUMsR0FBRyxHQUFHLENBQUE7QUFFMUQsTUFBTSxPQUFPLEdBQUcsQ0FBQyxLQUFjLEVBQW1CLEVBQUUsQ0FDbEQsT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQTtBQUVwRTs7OztHQUlHO0FBQ0gsU0FBZ0IsdUJBQXVCLENBQ3JDLFFBQW1DO0lBRW5DLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDaEMsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsZ0VBQWdFLENBQ2pFLENBQUE7SUFDSCxDQUFDO0lBQ0QsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUE7SUFDcEMsSUFBSSxLQUFLLEtBQUssSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDdEMsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsd0VBQXdFLENBQ3pFLENBQUE7SUFDSCxDQUFDO0lBQ0QsTUFBTSxLQUFLLEdBQ1QsT0FBTyxRQUFRLENBQUMsS0FBSyxLQUFLLFFBQVEsSUFBSSxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRTtRQUN6RCxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLCtDQUF1QyxDQUFDO1FBQ3pFLENBQUMsQ0FBQyxJQUFJLENBQUE7SUFDVixPQUFPLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFBO0FBQ3BELENBQUM7QUFVRCxNQUFNLElBQUksR0FBRyxDQUFDLFNBQTBCLEVBQUUsT0FBZSxFQUFRLEVBQUU7SUFDakUsSUFBSSxDQUFDO1FBQ0gsU0FBUyxDQUFDLE9BQU8sQ0FBUyxpQ0FBeUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDM0UsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLCtEQUErRDtJQUNqRSxDQUFDO0FBQ0gsQ0FBQyxDQUFBO0FBRUQ7Ozs7Ozs7R0FPRztBQUNJLEtBQUssVUFBVSwwQkFBMEIsQ0FDOUMsU0FBMEIsRUFDMUIsS0FBZ0MsRUFDaEMsUUFBbUM7SUFFbkMsSUFBSSxVQUFnQyxDQUFBO0lBQ3BDLElBQUksQ0FBQztRQUNILFVBQVUsR0FBRyx1QkFBdUIsQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUNoRCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLElBQUksQ0FDRixTQUFTLEVBQ1QseUJBQXlCLEtBQUssQ0FBQyxDQUFDLENBQUMscUJBQXFCLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLGVBQ2pFLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ3ZELEVBQUUsQ0FDSCxDQUFBO1FBQ0QsT0FBTTtJQUNSLENBQUM7SUFDRCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDWCxPQUFNO0lBQ1IsQ0FBQztJQUNELElBQUksQ0FBQztRQUNILE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBQSxpQ0FBaUIsRUFDckMsU0FBUyxDQUNWLENBQUMsNkJBQTZCLENBQUMsS0FBSyxFQUFFLFVBQVUsQ0FBQyxDQUFBO1FBQ2xELElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNiLElBQUksQ0FDRixTQUFTLEVBQ1QsZ0NBQWdDLEtBQUssb0RBQW9ELENBQzFGLENBQUE7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixJQUFJLENBQ0YsU0FBUyxFQUNULGdDQUFnQyxLQUFLLHNDQUNuQyxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUN2RCxFQUFFLENBQ0gsQ0FBQTtJQUNILENBQUM7QUFDSCxDQUFDIn0=