@betterportal/config-manager 0.0.1

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 (154) hide show
  1. package/README.md +3 -0
  2. package/bsb-plugin.json +23 -0
  3. package/bsb-tests.json +14 -0
  4. package/lib/.bsb/clients/service-betterportal-config-manager.d.ts +37 -0
  5. package/lib/.bsb/clients/service-betterportal-config-manager.d.ts.map +1 -0
  6. package/lib/.bsb/clients/service-betterportal-config-manager.js +40 -0
  7. package/lib/.bsb/clients/service-betterportal-config-manager.js.map +1 -0
  8. package/lib/index.d.ts +2 -0
  9. package/lib/index.d.ts.map +1 -0
  10. package/lib/index.js +2 -0
  11. package/lib/index.js.map +1 -0
  12. package/lib/plugins/service-betterportal-config-manager/.bp-generated/registry.d.ts +3 -0
  13. package/lib/plugins/service-betterportal-config-manager/.bp-generated/registry.d.ts.map +1 -0
  14. package/lib/plugins/service-betterportal-config-manager/.bp-generated/registry.js +235 -0
  15. package/lib/plugins/service-betterportal-config-manager/.bp-generated/registry.js.map +1 -0
  16. package/lib/plugins/service-betterportal-config-manager/adminApi.d.ts +4 -0
  17. package/lib/plugins/service-betterportal-config-manager/adminApi.d.ts.map +1 -0
  18. package/lib/plugins/service-betterportal-config-manager/adminApi.js +2319 -0
  19. package/lib/plugins/service-betterportal-config-manager/adminApi.js.map +1 -0
  20. package/lib/plugins/service-betterportal-config-manager/bootstrapEndpoint.d.ts +21 -0
  21. package/lib/plugins/service-betterportal-config-manager/bootstrapEndpoint.d.ts.map +1 -0
  22. package/lib/plugins/service-betterportal-config-manager/bootstrapEndpoint.js +269 -0
  23. package/lib/plugins/service-betterportal-config-manager/bootstrapEndpoint.js.map +1 -0
  24. package/lib/plugins/service-betterportal-config-manager/bootstrapWizardHtml.d.ts +19 -0
  25. package/lib/plugins/service-betterportal-config-manager/bootstrapWizardHtml.d.ts.map +1 -0
  26. package/lib/plugins/service-betterportal-config-manager/bootstrapWizardHtml.js +329 -0
  27. package/lib/plugins/service-betterportal-config-manager/bootstrapWizardHtml.js.map +1 -0
  28. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.d.ts +4 -0
  29. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.d.ts.map +1 -0
  30. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.js +38 -0
  31. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.js.map +1 -0
  32. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/index.d.ts +96 -0
  33. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/index.d.ts.map +1 -0
  34. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/index.js +78 -0
  35. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/index.js.map +1 -0
  36. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.bootstrap1/index.d.ts +4 -0
  37. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.bootstrap1/index.d.ts.map +1 -0
  38. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.bootstrap1/index.js +62 -0
  39. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.bootstrap1/index.js.map +1 -0
  40. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.embedded.d.ts +5 -0
  41. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.embedded.d.ts.map +1 -0
  42. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.embedded.js +5 -0
  43. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.embedded.js.map +1 -0
  44. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/index.d.ts +43 -0
  45. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/index.d.ts.map +1 -0
  46. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/index.js +68 -0
  47. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/index.js.map +1 -0
  48. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/_theme.bootstrap1/index.d.ts +5 -0
  49. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/_theme.bootstrap1/index.d.ts.map +1 -0
  50. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/_theme.bootstrap1/index.js +11 -0
  51. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/_theme.bootstrap1/index.js.map +1 -0
  52. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/index.d.ts +32 -0
  53. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/index.d.ts.map +1 -0
  54. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/index.js +32 -0
  55. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/index.js.map +1 -0
  56. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/_theme.bootstrap1/index.d.ts +4 -0
  57. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/_theme.bootstrap1/index.d.ts.map +1 -0
  58. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/_theme.bootstrap1/index.js +170 -0
  59. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/_theme.bootstrap1/index.js.map +1 -0
  60. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/index.d.ts +60 -0
  61. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/index.d.ts.map +1 -0
  62. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/index.js +48 -0
  63. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/index.js.map +1 -0
  64. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/_theme.bootstrap1/index.d.ts +4 -0
  65. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/_theme.bootstrap1/index.d.ts.map +1 -0
  66. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/_theme.bootstrap1/index.js +28 -0
  67. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/_theme.bootstrap1/index.js.map +1 -0
  68. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/index.d.ts +48 -0
  69. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/index.d.ts.map +1 -0
  70. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/index.js +40 -0
  71. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/index.js.map +1 -0
  72. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_theme.bootstrap1/index.d.ts +5 -0
  73. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_theme.bootstrap1/index.d.ts.map +1 -0
  74. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_theme.bootstrap1/index.js +194 -0
  75. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_theme.bootstrap1/index.js.map +1 -0
  76. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/index.d.ts +80 -0
  77. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/index.d.ts.map +1 -0
  78. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/index.js +59 -0
  79. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/index.js.map +1 -0
  80. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/index.d.ts +5 -0
  81. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/index.d.ts.map +1 -0
  82. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/index.js +167 -0
  83. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/index.js.map +1 -0
  84. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/index.d.ts +128 -0
  85. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/index.d.ts.map +1 -0
  86. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/index.js +89 -0
  87. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/index.js.map +1 -0
  88. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/_theme.bootstrap1/index.d.ts +5 -0
  89. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/_theme.bootstrap1/index.d.ts.map +1 -0
  90. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/_theme.bootstrap1/index.js +8 -0
  91. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/_theme.bootstrap1/index.js.map +1 -0
  92. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/index.d.ts +89 -0
  93. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/index.d.ts.map +1 -0
  94. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/index.js +93 -0
  95. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/index.js.map +1 -0
  96. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/_theme.bootstrap1/index.d.ts +4 -0
  97. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/_theme.bootstrap1/index.d.ts.map +1 -0
  98. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/_theme.bootstrap1/index.js +61 -0
  99. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/_theme.bootstrap1/index.js.map +1 -0
  100. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/index.d.ts +180 -0
  101. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/index.d.ts.map +1 -0
  102. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/index.js +405 -0
  103. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/index.js.map +1 -0
  104. package/lib/plugins/service-betterportal-config-manager/cpBootstrap.d.ts +26 -0
  105. package/lib/plugins/service-betterportal-config-manager/cpBootstrap.d.ts.map +1 -0
  106. package/lib/plugins/service-betterportal-config-manager/cpBootstrap.js +58 -0
  107. package/lib/plugins/service-betterportal-config-manager/cpBootstrap.js.map +1 -0
  108. package/lib/plugins/service-betterportal-config-manager/fragmentsEditor.d.ts +3 -0
  109. package/lib/plugins/service-betterportal-config-manager/fragmentsEditor.d.ts.map +1 -0
  110. package/lib/plugins/service-betterportal-config-manager/fragmentsEditor.js +365 -0
  111. package/lib/plugins/service-betterportal-config-manager/fragmentsEditor.js.map +1 -0
  112. package/lib/plugins/service-betterportal-config-manager/index.d.ts +143 -0
  113. package/lib/plugins/service-betterportal-config-manager/index.d.ts.map +1 -0
  114. package/lib/plugins/service-betterportal-config-manager/index.js +696 -0
  115. package/lib/plugins/service-betterportal-config-manager/index.js.map +1 -0
  116. package/lib/plugins/service-betterportal-config-manager/menuEditor.d.ts +3 -0
  117. package/lib/plugins/service-betterportal-config-manager/menuEditor.d.ts.map +1 -0
  118. package/lib/plugins/service-betterportal-config-manager/menuEditor.js +823 -0
  119. package/lib/plugins/service-betterportal-config-manager/menuEditor.js.map +1 -0
  120. package/lib/plugins/service-betterportal-config-manager/routeContext.d.ts +10 -0
  121. package/lib/plugins/service-betterportal-config-manager/routeContext.d.ts.map +1 -0
  122. package/lib/plugins/service-betterportal-config-manager/routeContext.js +11 -0
  123. package/lib/plugins/service-betterportal-config-manager/routeContext.js.map +1 -0
  124. package/lib/plugins/service-betterportal-config-manager/setupTokens.d.ts +18 -0
  125. package/lib/plugins/service-betterportal-config-manager/setupTokens.d.ts.map +1 -0
  126. package/lib/plugins/service-betterportal-config-manager/setupTokens.js +245 -0
  127. package/lib/plugins/service-betterportal-config-manager/setupTokens.js.map +1 -0
  128. package/lib/plugins/service-betterportal-config-manager/storage/core.d.ts +41 -0
  129. package/lib/plugins/service-betterportal-config-manager/storage/core.d.ts.map +1 -0
  130. package/lib/plugins/service-betterportal-config-manager/storage/core.js +396 -0
  131. package/lib/plugins/service-betterportal-config-manager/storage/core.js.map +1 -0
  132. package/lib/plugins/service-betterportal-config-manager/storage/file.d.ts +10 -0
  133. package/lib/plugins/service-betterportal-config-manager/storage/file.d.ts.map +1 -0
  134. package/lib/plugins/service-betterportal-config-manager/storage/file.js +30 -0
  135. package/lib/plugins/service-betterportal-config-manager/storage/file.js.map +1 -0
  136. package/lib/plugins/service-betterportal-config-manager/storage/index.d.ts +36 -0
  137. package/lib/plugins/service-betterportal-config-manager/storage/index.d.ts.map +1 -0
  138. package/lib/plugins/service-betterportal-config-manager/storage/index.js +52 -0
  139. package/lib/plugins/service-betterportal-config-manager/storage/index.js.map +1 -0
  140. package/lib/plugins/service-betterportal-config-manager/storage/postgres.d.ts +15 -0
  141. package/lib/plugins/service-betterportal-config-manager/storage/postgres.d.ts.map +1 -0
  142. package/lib/plugins/service-betterportal-config-manager/storage/postgres.js +60 -0
  143. package/lib/plugins/service-betterportal-config-manager/storage/postgres.js.map +1 -0
  144. package/lib/plugins/service-betterportal-config-manager/syncApi.d.ts +44 -0
  145. package/lib/plugins/service-betterportal-config-manager/syncApi.d.ts.map +1 -0
  146. package/lib/plugins/service-betterportal-config-manager/syncApi.js +280 -0
  147. package/lib/plugins/service-betterportal-config-manager/syncApi.js.map +1 -0
  148. package/lib/plugins/service-betterportal-config-manager/webhooks.d.ts +6 -0
  149. package/lib/plugins/service-betterportal-config-manager/webhooks.d.ts.map +1 -0
  150. package/lib/plugins/service-betterportal-config-manager/webhooks.js +372 -0
  151. package/lib/plugins/service-betterportal-config-manager/webhooks.js.map +1 -0
  152. package/lib/schemas/service-betterportal-config-manager.json +157 -0
  153. package/lib/schemas/service-betterportal-config-manager.plugin.json +135 -0
  154. package/package.json +69 -0
@@ -0,0 +1,372 @@
1
+ import { createHmac, randomBytes } from "node:crypto";
2
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ import { jsonResponse, uuidv7 } from "@betterportal/framework";
5
+ import { eventObservability } from "@betterportal/framework";
6
+ import { getManifestCache } from "./syncApi.js";
7
+ const API_BASE = "/.well-known/bp";
8
+ class WebhookDeliveryStore {
9
+ filePath;
10
+ constructor(filePath = "./.bp-webhook-deliveries.json") {
11
+ this.filePath = resolve(filePath);
12
+ }
13
+ list() {
14
+ if (!existsSync(this.filePath))
15
+ return [];
16
+ try {
17
+ const parsed = JSON.parse(readFileSync(this.filePath, "utf8"));
18
+ return Array.isArray(parsed) ? parsed : [];
19
+ }
20
+ catch {
21
+ return [];
22
+ }
23
+ }
24
+ save(records) {
25
+ const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1000;
26
+ const kept = records.filter((record) => record.status === "pending" || Date.parse(record.createdAt) >= cutoff);
27
+ writeFileSync(this.filePath, JSON.stringify(kept, null, 2), "utf8");
28
+ }
29
+ add(records) {
30
+ this.save([...this.list(), ...records]);
31
+ }
32
+ }
33
+ function readBearer(event) {
34
+ const auth = event.req.headers.get("authorization");
35
+ return auth?.startsWith("Bearer ") ? auth.slice(7) : null;
36
+ }
37
+ async function readJson(event) {
38
+ const parsed = await event.req.json().catch(() => null);
39
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
40
+ }
41
+ function stringValue(body, key) {
42
+ const value = body[key];
43
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
44
+ }
45
+ function appMatchesTenantUrl(app, tenantUrl) {
46
+ let host = "";
47
+ try {
48
+ host = new URL(tenantUrl).host.toLowerCase();
49
+ }
50
+ catch {
51
+ host = tenantUrl.toLowerCase().replace(/^https?:\/\//, "").replace(/\/.*$/, "");
52
+ }
53
+ return app.hostnames.some((hostname) => {
54
+ const value = hostname.toLowerCase();
55
+ if (value === host)
56
+ return true;
57
+ try {
58
+ return new URL(value).host.toLowerCase() === host;
59
+ }
60
+ catch {
61
+ return false;
62
+ }
63
+ });
64
+ }
65
+ function currentAppFromRequest(config, event) {
66
+ const url = new URL(event.req.url, `http://${event.req.headers.get("host") ?? "localhost"}`);
67
+ const appId = url.searchParams.get("appId") ?? event.req.headers.get("x-bp-app-id") ?? "";
68
+ const tenantUrl = url.searchParams.get("tenantUrl") ?? event.req.headers.get("referer") ?? event.req.headers.get("origin") ?? "";
69
+ return appId
70
+ ? config.apps.find((entry) => entry.id === appId)
71
+ : config.apps.find((entry) => tenantUrl && appMatchesTenantUrl(entry, tenantUrl));
72
+ }
73
+ function matchingTargets(config, serviceId, eventId, tenantId, appId) {
74
+ const tenant = config.tenants.find((entry) => entry.id === tenantId && entry.active);
75
+ if (!tenant)
76
+ return [];
77
+ return config.webhooks.targets.filter((target) => target.enabled
78
+ && target.serviceId === serviceId
79
+ && target.eventId === eventId
80
+ && target.tenantId === tenantId
81
+ && (!target.appId || target.appId === appId));
82
+ }
83
+ function sign(target, record, timestamp) {
84
+ const body = `${timestamp}.${record.id}.${record.eventId}.${JSON.stringify(record.payload)}`;
85
+ return `sha256=${createHmac("sha256", target.secret).update(body).digest("hex")}`;
86
+ }
87
+ function backoff(attempts) {
88
+ return Math.min(60 * 60, 2 ** Math.max(0, attempts - 1) * 30);
89
+ }
90
+ async function deliver(target, record) {
91
+ const timestamp = new Date().toISOString();
92
+ try {
93
+ const response = await fetch(target.url, {
94
+ method: "POST",
95
+ headers: {
96
+ "content-type": "application/json",
97
+ "x-bp-webhook-id": record.id,
98
+ "x-bp-webhook-event": record.eventId,
99
+ "x-bp-webhook-timestamp": timestamp,
100
+ "x-bp-webhook-signature": sign(target, record, timestamp)
101
+ },
102
+ body: JSON.stringify({
103
+ id: record.id,
104
+ serviceId: record.serviceId,
105
+ eventId: record.eventId,
106
+ tenantId: record.tenantId,
107
+ appId: record.appId,
108
+ payload: record.payload
109
+ })
110
+ });
111
+ return { ok: response.ok, status: response.status, error: response.ok ? undefined : await response.text().catch(() => response.statusText) };
112
+ }
113
+ catch (error) {
114
+ return { ok: false, error: error instanceof Error ? error.message : String(error) };
115
+ }
116
+ }
117
+ async function processDeliveries(store, deliveryStore) {
118
+ const config = await store.loadConfig();
119
+ const targets = new Map(config.webhooks.targets.map((target) => [target.id, target]));
120
+ const now = Date.now();
121
+ const records = deliveryStore.list();
122
+ let changed = false;
123
+ for (const record of records) {
124
+ if (record.status !== "pending" || Date.parse(record.nextAttemptAt) > now)
125
+ continue;
126
+ const target = targets.get(record.targetId);
127
+ if (!target?.enabled || !config.tenants.some((tenant) => tenant.id === target.tenantId && tenant.active)) {
128
+ record.status = "failed";
129
+ record.lastError = "target disabled or tenant inactive";
130
+ changed = true;
131
+ continue;
132
+ }
133
+ record.attempts += 1;
134
+ const result = await deliver(target, record);
135
+ record.lastStatus = result.status;
136
+ record.lastError = result.error;
137
+ record.status = result.ok ? "delivered" : record.attempts >= record.maxAttempts ? "failed" : "pending";
138
+ record.nextAttemptAt = new Date(Date.now() + backoff(record.attempts) * 1000).toISOString();
139
+ changed = true;
140
+ }
141
+ if (changed)
142
+ deliveryStore.save(records);
143
+ }
144
+ export function registerWebhookRoutes(app, store) {
145
+ const deliveryStore = new WebhookDeliveryStore();
146
+ let timer;
147
+ app.get(`${API_BASE}/admin/webhooks/events`, async () => {
148
+ const manifests = [...getManifestCache().entries()].map(([serviceId, manifest]) => ({
149
+ serviceId,
150
+ title: manifest.title,
151
+ webhooks: manifest.webhooks
152
+ }));
153
+ return jsonResponse(manifests);
154
+ });
155
+ app.get(`${API_BASE}/admin/webhooks/targets`, async () => {
156
+ const config = await store.loadConfig();
157
+ return jsonResponse(config.webhooks.targets.map(({ secret: _secret, ...target }) => target));
158
+ });
159
+ app.get(`${API_BASE}/manage/webhooks/events`, async (event) => {
160
+ const config = await store.loadConfig();
161
+ const appDef = currentAppFromRequest(config, event);
162
+ if (!appDef)
163
+ return jsonResponse({ error: "Unable to resolve current BetterPortal app" }, 404);
164
+ const services = new Set([
165
+ ...(config.tenants.find((tenant) => tenant.id === appDef.tenantId)?.services.map((service) => service.id) ?? []),
166
+ ...config.sharedServiceActivations
167
+ .filter((activation) => activation.enabled && activation.tenantId === appDef.tenantId && (!activation.appId || activation.appId === appDef.id))
168
+ .map((activation) => activation.id)
169
+ ]);
170
+ return jsonResponse([...getManifestCache().entries()]
171
+ .filter(([serviceId]) => services.has(serviceId))
172
+ .map(([serviceId, manifest]) => ({ serviceId, title: manifest.title, webhooks: manifest.webhooks })));
173
+ });
174
+ app.get(`${API_BASE}/manage/webhooks/targets`, async (event) => {
175
+ const config = await store.loadConfig();
176
+ const appDef = currentAppFromRequest(config, event);
177
+ if (!appDef)
178
+ return jsonResponse({ error: "Unable to resolve current BetterPortal app" }, 404);
179
+ return jsonResponse(config.webhooks.targets
180
+ .filter((target) => target.tenantId === appDef.tenantId && (!target.appId || target.appId === appDef.id))
181
+ .map(({ secret: _secret, ...target }) => target));
182
+ });
183
+ app.post(`${API_BASE}/manage/webhooks/targets`, async (event) => {
184
+ const config = await store.loadConfig();
185
+ const appDef = currentAppFromRequest(config, event);
186
+ if (!appDef)
187
+ return jsonResponse({ error: "Unable to resolve current BetterPortal app" }, 404);
188
+ const body = await readJson(event);
189
+ const serviceId = stringValue(body, "serviceId");
190
+ const eventId = stringValue(body, "eventId");
191
+ const url = stringValue(body, "url");
192
+ if (!serviceId || !eventId || !url)
193
+ return jsonResponse({ error: "serviceId, eventId and url are required" }, 400);
194
+ const manifest = getManifestCache().get(serviceId);
195
+ if (!manifest?.webhooks.some((entry) => entry.id === eventId))
196
+ return jsonResponse({ error: "Webhook event is not declared by service manifest" }, 400);
197
+ const target = {
198
+ id: uuidv7(),
199
+ tenantId: appDef.tenantId,
200
+ appId: appDef.id,
201
+ serviceId,
202
+ eventId,
203
+ url,
204
+ secret: randomBytes(32).toString("hex"),
205
+ createdAt: new Date().toISOString(),
206
+ enabled: true,
207
+ maxAttempts: typeof body.maxAttempts === "number" ? body.maxAttempts : 10
208
+ };
209
+ config.webhooks.targets.push(target);
210
+ await store.saveConfig(config);
211
+ return jsonResponse(target, 201);
212
+ });
213
+ app.delete(`${API_BASE}/manage/webhooks/targets/:targetId`, async (event) => {
214
+ const targetId = event.context.params?.targetId;
215
+ const config = await store.loadConfig();
216
+ const appDef = currentAppFromRequest(config, event);
217
+ if (!appDef)
218
+ return jsonResponse({ error: "Unable to resolve current BetterPortal app" }, 404);
219
+ const target = config.webhooks.targets.find((entry) => entry.id === targetId);
220
+ if (!target || target.tenantId !== appDef.tenantId || (target.appId && target.appId !== appDef.id)) {
221
+ return jsonResponse({ error: "Webhook target not found" }, 404);
222
+ }
223
+ config.webhooks.targets = config.webhooks.targets.filter((entry) => entry.id !== targetId);
224
+ await store.saveConfig(config);
225
+ return jsonResponse({ ok: true });
226
+ });
227
+ app.post(`${API_BASE}/manage/webhooks/targets/:targetId/test`, async (event) => {
228
+ const targetId = event.context.params?.targetId;
229
+ const config = await store.loadConfig();
230
+ const appDef = currentAppFromRequest(config, event);
231
+ if (!appDef)
232
+ return jsonResponse({ error: "Unable to resolve current BetterPortal app" }, 404);
233
+ const target = config.webhooks.targets.find((entry) => entry.id === targetId);
234
+ if (!target || target.tenantId !== appDef.tenantId || (target.appId && target.appId !== appDef.id)) {
235
+ return jsonResponse({ error: "Webhook target not found" }, 404);
236
+ }
237
+ const record = {
238
+ id: uuidv7(),
239
+ targetId: target.id,
240
+ serviceId: target.serviceId,
241
+ eventId: target.eventId,
242
+ tenantId: target.tenantId,
243
+ appId: target.appId,
244
+ payload: { test: true },
245
+ attempts: 0,
246
+ maxAttempts: 1,
247
+ nextAttemptAt: new Date().toISOString(),
248
+ createdAt: new Date().toISOString(),
249
+ status: "pending"
250
+ };
251
+ const result = await deliver(target, record);
252
+ return jsonResponse({ ok: result.ok, status: result.status, error: result.error }, result.ok ? 202 : 502);
253
+ });
254
+ app.post(`${API_BASE}/admin/webhooks/targets`, async (event) => {
255
+ const body = await readJson(event);
256
+ const tenantId = stringValue(body, "tenantId");
257
+ const serviceId = stringValue(body, "serviceId");
258
+ const eventId = stringValue(body, "eventId");
259
+ const url = stringValue(body, "url");
260
+ if (!tenantId || !serviceId || !eventId || !url)
261
+ return jsonResponse({ error: "tenantId, serviceId, eventId and url are required" }, 400);
262
+ const manifest = getManifestCache().get(serviceId);
263
+ if (!manifest?.webhooks.some((entry) => entry.id === eventId))
264
+ return jsonResponse({ error: "Webhook event is not declared by service manifest" }, 400);
265
+ const config = await store.loadConfig();
266
+ if (!config.tenants.some((tenant) => tenant.id === tenantId && tenant.active))
267
+ return jsonResponse({ error: "Tenant not found or disabled" }, 404);
268
+ const target = {
269
+ id: uuidv7(),
270
+ tenantId,
271
+ appId: stringValue(body, "appId"),
272
+ serviceId,
273
+ eventId,
274
+ url,
275
+ secret: randomBytes(32).toString("hex"),
276
+ createdAt: new Date().toISOString(),
277
+ enabled: true,
278
+ maxAttempts: typeof body.maxAttempts === "number" ? body.maxAttempts : 10
279
+ };
280
+ config.webhooks.targets.push(target);
281
+ await store.saveConfig(config);
282
+ return jsonResponse(target, 201);
283
+ });
284
+ app.delete(`${API_BASE}/admin/webhooks/targets/:targetId`, async (event) => {
285
+ const targetId = event.context.params?.targetId;
286
+ const config = await store.loadConfig();
287
+ config.webhooks.targets = config.webhooks.targets.filter((target) => target.id !== targetId);
288
+ await store.saveConfig(config);
289
+ return jsonResponse({ ok: true });
290
+ });
291
+ app.post(`${API_BASE}/admin/webhooks/targets/:targetId/test`, async (event) => {
292
+ const targetId = event.context.params?.targetId;
293
+ const config = await store.loadConfig();
294
+ const target = config.webhooks.targets.find((entry) => entry.id === targetId);
295
+ if (!target)
296
+ return jsonResponse({ error: "Webhook target not found" }, 404);
297
+ const record = {
298
+ id: uuidv7(),
299
+ targetId: target.id,
300
+ serviceId: target.serviceId,
301
+ eventId: target.eventId,
302
+ tenantId: target.tenantId,
303
+ appId: target.appId,
304
+ payload: { test: true },
305
+ attempts: 0,
306
+ maxAttempts: 1,
307
+ nextAttemptAt: new Date().toISOString(),
308
+ createdAt: new Date().toISOString(),
309
+ status: "pending"
310
+ };
311
+ const result = await deliver(target, record);
312
+ return jsonResponse({ ok: result.ok, status: result.status, error: result.error }, result.ok ? 202 : 502);
313
+ });
314
+ app.post(`${API_BASE}/webhooks/events`, async (event) => {
315
+ const obs = eventObservability(event);
316
+ const apiKey = readBearer(event);
317
+ if (!apiKey)
318
+ return jsonResponse({ error: "Bearer token required" }, 401);
319
+ const validated = await store.validateApiKey(apiKey);
320
+ if (!validated?.serviceId)
321
+ return jsonResponse({ error: "Invalid service token" }, 403);
322
+ const body = await readJson(event);
323
+ const eventId = stringValue(body, "eventId");
324
+ const tenantId = stringValue(body, "tenantId") ?? validated.tenantId;
325
+ const appId = stringValue(body, "appId");
326
+ if (!eventId || !tenantId)
327
+ return jsonResponse({ error: "eventId and tenantId are required" }, 400);
328
+ const manifest = getManifestCache().get(validated.serviceId);
329
+ if (!manifest?.webhooks.some((entry) => entry.id === eventId))
330
+ return jsonResponse({ error: "Webhook event is not declared by service manifest" }, 400);
331
+ const config = await store.loadConfig();
332
+ const targets = matchingTargets(config, validated.serviceId, eventId, tenantId, appId);
333
+ const createdAt = new Date().toISOString();
334
+ const records = targets.map((target) => ({
335
+ id: uuidv7(),
336
+ targetId: target.id,
337
+ serviceId: validated.serviceId,
338
+ eventId,
339
+ tenantId,
340
+ appId,
341
+ payload: (body.payload ?? null),
342
+ attempts: 0,
343
+ maxAttempts: target.maxAttempts,
344
+ nextAttemptAt: createdAt,
345
+ createdAt,
346
+ status: "pending"
347
+ }));
348
+ deliveryStore.add(records);
349
+ obs?.logger.info("BP WEBHOOK: queued service={serviceId} event={eventId} tenant={tenantId} app={appId} targets={targets}", {
350
+ serviceId: validated.serviceId,
351
+ eventId,
352
+ tenantId,
353
+ appId: appId ?? "",
354
+ targets: records.length
355
+ });
356
+ await processDeliveries(store, deliveryStore);
357
+ return jsonResponse({ queued: records.length }, 202);
358
+ });
359
+ return {
360
+ start() {
361
+ timer ??= setInterval(() => {
362
+ processDeliveries(store, deliveryStore).catch(() => undefined);
363
+ }, 30_000);
364
+ },
365
+ stop() {
366
+ if (timer)
367
+ clearInterval(timer);
368
+ timer = undefined;
369
+ }
370
+ };
371
+ }
372
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../../src/plugins/service-betterportal-config-manager/webhooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,YAAY,EACZ,MAAM,EAQP,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,QAAQ,GAAG,iBAAiB,CAAC;AAqBnC,MAAM,oBAAoB;IACP,QAAQ,CAAS;IAElC,YAAY,QAAQ,GAAG,+BAA+B;QACpD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,IAAI;QACF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;YAC/D,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAA0B,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAyB;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QACpD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CACrC,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,MAAM,CACtE,CAAC;QACF,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACtE,CAAC;IAED,GAAG,CAAC,OAAyB;QAC3B,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;IAC1C,CAAC;CACF;AAED,SAAS,UAAU,CAAC,KAAwB;IAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACpD,OAAO,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5D,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,KAAwB;IAC9C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACxD,OAAO,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAiC,CAAC,CAAC,CAAC,EAAE,CAAC;AACjH,CAAC;AAED,SAAS,WAAW,CAAC,IAA6B,EAAE,GAAW;IAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9E,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAoB,EAAE,SAAiB;IAClE,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;QACrC,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAChC,IAAI,CAAC;YACH,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,qBAAqB,CAAC,MAA0B,EAAE,KAAwB;IACjF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC;IAC7F,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;IAC1F,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACjI,OAAO,KAAK;QACV,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC;QACjD,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,IAAI,mBAAmB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;AACtF,CAAC;AAED,SAAS,eAAe,CAAC,MAA0B,EAAE,SAAiB,EAAE,OAAe,EAAE,QAAgB,EAAE,KAAc;IACvH,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;IACrF,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAC/C,MAAM,CAAC,OAAO;WACX,MAAM,CAAC,SAAS,KAAK,SAAS;WAC9B,MAAM,CAAC,OAAO,KAAK,OAAO;WAC1B,MAAM,CAAC,QAAQ,KAAK,QAAQ;WAC5B,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC,CAC7C,CAAC;AACJ,CAAC;AAED,SAAS,IAAI,CAAC,MAAqB,EAAE,MAAsB,EAAE,SAAiB;IAC5E,MAAM,IAAI,GAAG,GAAG,SAAS,IAAI,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7F,OAAO,UAAU,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACpF,CAAC;AAED,SAAS,OAAO,CAAC,QAAgB;IAC/B,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,MAAqB,EAAE,MAAsB;IAClE,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE;YACvC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,iBAAiB,EAAE,MAAM,CAAC,EAAE;gBAC5B,oBAAoB,EAAE,MAAM,CAAC,OAAO;gBACpC,wBAAwB,EAAE,SAAS;gBACnC,wBAAwB,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;aAC1D;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,EAAE,EAAE,MAAM,CAAC,EAAE;gBACb,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,OAAO,EAAE,MAAM,CAAC,OAAO;aACxB,CAAC;SACH,CAAC,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;IAC/I,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACtF,CAAC;AACH,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,KAA0B,EAAE,aAAmC;IAC9F,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACtF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC;IACrC,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,GAAG;YAAE,SAAS;QACpF,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YACzG,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC;YACzB,MAAM,CAAC,SAAS,GAAG,oCAAoC,CAAC;YACxD,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QAED,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;QACrB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7C,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;QAClC,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC;QAChC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QACvG,MAAM,CAAC,aAAa,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAC5F,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IAED,IAAI,OAAO;QAAE,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAsB,EAAE,KAA0B;IACtF,MAAM,aAAa,GAAG,IAAI,oBAAoB,EAAE,CAAC;IACjD,IAAI,KAAiD,CAAC;IAEtD,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,wBAAwB,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,SAAS,GAAG,CAAC,GAAG,gBAAgB,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;YAClF,SAAS;YACT,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;SAC5B,CAAC,CAAC,CAAC;QACJ,OAAO,YAAY,CAAC,SAAiC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,yBAAyB,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,OAAO,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAyB,CAAC,CAAC;IACvH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,yBAAyB,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC5D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,4CAA4C,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/F,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC;YACvB,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;YAChH,GAAG,MAAM,CAAC,wBAAwB;iBAC/B,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC;iBAC9I,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;SACtC,CAAC,CAAC;QACH,OAAO,YAAY,CAAC,CAAC,GAAG,gBAAgB,EAAE,CAAC,OAAO,EAAE,CAAC;aAClD,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;aAChD,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAyB,CAAC,CAAC;IAClI,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,0BAA0B,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC7D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,4CAA4C,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/F,OAAO,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO;aACxC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC;aACxG,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAyB,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,0BAA0B,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC9D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,4CAA4C,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/F,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,yCAAyC,EAAE,EAAE,GAAG,CAAC,CAAC;QACnH,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,mDAAmD,EAAE,EAAE,GAAG,CAAC,CAAC;QACxJ,MAAM,MAAM,GAAkB;YAC5B,EAAE,EAAE,MAAM,EAAE;YACZ,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,KAAK,EAAE,MAAM,CAAC,EAAE;YAChB,SAAS;YACT,OAAO;YACP,GAAG;YACH,MAAM,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;SAC1E,CAAC;QACF,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,YAAY,CAAC,MAA8B,EAAE,GAAG,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,MAAM,CAAC,GAAG,QAAQ,oCAAoC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC1E,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,4CAA4C,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/F,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC9E,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;YACnG,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,EAAE,GAAG,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,CAAC,QAAQ,CAAC,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC3F,MAAM,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,YAAY,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,yCAAyC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC7E,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,4CAA4C,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/F,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC9E,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;YACnG,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,EAAE,GAAG,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,MAAM,GAAmB;YAC7B,EAAE,EAAE,MAAM,EAAE;YACZ,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;YACvB,QAAQ,EAAE,CAAC;YACX,WAAW,EAAE,CAAC;YACd,aAAa,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACvC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,MAAM,EAAE,SAAS;SAClB,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7C,OAAO,YAAY,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAe,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACzH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,yBAAyB,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC7D,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC/C,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,mDAAmD,EAAE,EAAE,GAAG,CAAC,CAAC;QAE1I,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,mDAAmD,EAAE,EAAE,GAAG,CAAC,CAAC;QAExJ,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,8BAA8B,EAAE,EAAE,GAAG,CAAC,CAAC;QAEnJ,MAAM,MAAM,GAAkB;YAC5B,EAAE,EAAE,MAAM,EAAE;YACZ,QAAQ;YACR,KAAK,EAAE,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC;YACjC,SAAS;YACT,OAAO;YACP,GAAG;YACH,MAAM,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;SAC1E,CAAC;QACF,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,YAAY,CAAC,MAA8B,EAAE,GAAG,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,MAAM,CAAC,GAAG,QAAQ,mCAAmC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QACzE,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,CAAC,QAAQ,CAAC,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC7F,MAAM,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,YAAY,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,wCAAwC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC5E,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC9E,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,EAAE,GAAG,CAAC,CAAC;QAC7E,MAAM,MAAM,GAAmB;YAC7B,EAAE,EAAE,MAAM,EAAE;YACZ,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;YACvB,QAAQ,EAAE,CAAC;YACX,WAAW,EAAE,CAAC;YACd,aAAa,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACvC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,MAAM,EAAE,SAAS;SAClB,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7C,OAAO,YAAY,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAe,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACzH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,kBAAkB,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QACtD,MAAM,GAAG,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,EAAE,GAAG,CAAC,CAAC;QAC1E,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QACrD,IAAI,CAAC,SAAS,EAAE,SAAS;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,EAAE,GAAG,CAAC,CAAC;QAExF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC;QACrE,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,mCAAmC,EAAE,EAAE,GAAG,CAAC,CAAC;QAEpG,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC7D,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,mDAAmD,EAAE,EAAE,GAAG,CAAC,CAAC;QAExJ,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;QACvF,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAkB,EAAE,CAAC,CAAC;YACvD,EAAE,EAAE,MAAM,EAAE;YACZ,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,SAAS,EAAE,SAAS,CAAC,SAAU;YAC/B,OAAO;YACP,QAAQ;YACR,KAAK;YACL,OAAO,EAAE,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAc;YAC5C,QAAQ,EAAE,CAAC;YACX,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,aAAa,EAAE,SAAS;YACxB,SAAS;YACT,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC,CAAC;QACJ,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3B,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,wGAAwG,EAAE;YACzH,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,OAAO;YACP,QAAQ;YACR,KAAK,EAAE,KAAK,IAAI,EAAE;YAClB,OAAO,EAAE,OAAO,CAAC,MAAM;SACxB,CAAC,CAAC;QACH,MAAM,iBAAiB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QAC9C,OAAO,YAAY,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAe,EAAE,GAAG,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,KAAK;YACH,KAAK,KAAK,WAAW,CAAC,GAAG,EAAE;gBACzB,iBAAiB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACjE,CAAC,EAAE,MAAM,CAAC,CAAC;QACb,CAAC;QACD,IAAI;YACF,IAAI,KAAK;gBAAE,aAAa,CAAC,KAAK,CAAC,CAAC;YAChC,KAAK,GAAG,SAAS,CAAC;QACpB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,157 @@
1
+ {
2
+ "pluginName": "service-betterportal-config-manager",
3
+ "events": {
4
+ "platform-config.changed": {
5
+ "type": "broadcast",
6
+ "category": "emitBroadcast",
7
+ "description": "Emitted after platform config is saved by this config-manager instance.",
8
+ "inputSchema": {
9
+ "anyvaliVersion": "1.0",
10
+ "schemaVersion": "1.1",
11
+ "root": {
12
+ "kind": "object",
13
+ "properties": {
14
+ "sourceId": {
15
+ "kind": "string",
16
+ "minLength": 1
17
+ },
18
+ "backend": {
19
+ "kind": "enum",
20
+ "values": [
21
+ "file",
22
+ "postgres"
23
+ ]
24
+ }
25
+ },
26
+ "required": [
27
+ "sourceId",
28
+ "backend"
29
+ ],
30
+ "unknownKeys": "strip"
31
+ },
32
+ "definitions": {},
33
+ "extensions": {}
34
+ },
35
+ "outputSchema": null
36
+ }
37
+ },
38
+ "version": "0.0.1",
39
+ "configSchema": {
40
+ "anyvaliVersion": "1.0",
41
+ "schemaVersion": "1.1",
42
+ "root": {
43
+ "kind": "object",
44
+ "properties": {
45
+ "host": {
46
+ "kind": "string",
47
+ "minLength": 1,
48
+ "default": "0.0.0.0"
49
+ },
50
+ "port": {
51
+ "kind": "int",
52
+ "min": 1,
53
+ "default": 3300
54
+ },
55
+ "storage": {
56
+ "kind": "union",
57
+ "variants": [
58
+ {
59
+ "kind": "object",
60
+ "properties": {
61
+ "backend": {
62
+ "kind": "literal",
63
+ "value": "file"
64
+ },
65
+ "configPath": {
66
+ "kind": "string",
67
+ "minLength": 1
68
+ }
69
+ },
70
+ "required": [
71
+ "backend",
72
+ "configPath"
73
+ ],
74
+ "unknownKeys": "strip"
75
+ },
76
+ {
77
+ "kind": "object",
78
+ "properties": {
79
+ "backend": {
80
+ "kind": "literal",
81
+ "value": "postgres"
82
+ },
83
+ "connectionString": {
84
+ "kind": "string",
85
+ "minLength": 1
86
+ },
87
+ "tableName": {
88
+ "kind": "optional",
89
+ "inner": {
90
+ "kind": "string",
91
+ "minLength": 1
92
+ }
93
+ },
94
+ "rowId": {
95
+ "kind": "optional",
96
+ "inner": {
97
+ "kind": "string",
98
+ "minLength": 1
99
+ }
100
+ }
101
+ },
102
+ "required": [
103
+ "backend",
104
+ "connectionString"
105
+ ],
106
+ "unknownKeys": "strip"
107
+ }
108
+ ],
109
+ "default": {
110
+ "backend": "file",
111
+ "configPath": "./bp-config.yaml"
112
+ }
113
+ },
114
+ "requestTimeoutMs": {
115
+ "kind": "int",
116
+ "min": 1,
117
+ "default": 2000
118
+ },
119
+ "cpKeyStorePath": {
120
+ "kind": "string",
121
+ "minLength": 1,
122
+ "default": "./.bp-cp-state/keys.json"
123
+ },
124
+ "cpIssuer": {
125
+ "kind": "optional",
126
+ "inner": {
127
+ "kind": "string",
128
+ "minLength": 1
129
+ }
130
+ },
131
+ "cpAudience": {
132
+ "kind": "string",
133
+ "minLength": 1,
134
+ "default": "betterportal-control-plane"
135
+ }
136
+ },
137
+ "required": [
138
+ "host",
139
+ "port",
140
+ "storage",
141
+ "requestTimeoutMs",
142
+ "cpKeyStorePath",
143
+ "cpAudience"
144
+ ],
145
+ "unknownKeys": "strip"
146
+ },
147
+ "definitions": {},
148
+ "extensions": {}
149
+ },
150
+ "pluginType": "service",
151
+ "dependencies": [
152
+ {
153
+ "id": "_/service-betterportal-config-manager.js",
154
+ "version": "1.0.0"
155
+ }
156
+ ]
157
+ }