@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.
- package/README.md +3 -0
- package/bsb-plugin.json +23 -0
- package/bsb-tests.json +14 -0
- package/lib/.bsb/clients/service-betterportal-config-manager.d.ts +37 -0
- package/lib/.bsb/clients/service-betterportal-config-manager.d.ts.map +1 -0
- package/lib/.bsb/clients/service-betterportal-config-manager.js +40 -0
- package/lib/.bsb/clients/service-betterportal-config-manager.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/.bp-generated/registry.d.ts +3 -0
- package/lib/plugins/service-betterportal-config-manager/.bp-generated/registry.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/.bp-generated/registry.js +235 -0
- package/lib/plugins/service-betterportal-config-manager/.bp-generated/registry.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/adminApi.d.ts +4 -0
- package/lib/plugins/service-betterportal-config-manager/adminApi.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/adminApi.js +2319 -0
- package/lib/plugins/service-betterportal-config-manager/adminApi.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bootstrapEndpoint.d.ts +21 -0
- package/lib/plugins/service-betterportal-config-manager/bootstrapEndpoint.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bootstrapEndpoint.js +269 -0
- package/lib/plugins/service-betterportal-config-manager/bootstrapEndpoint.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bootstrapWizardHtml.d.ts +19 -0
- package/lib/plugins/service-betterportal-config-manager/bootstrapWizardHtml.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bootstrapWizardHtml.js +329 -0
- package/lib/plugins/service-betterportal-config-manager/bootstrapWizardHtml.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.d.ts +4 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.js +38 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/index.d.ts +96 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/index.js +78 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.bootstrap1/index.d.ts +4 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.bootstrap1/index.js +62 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.embedded.d.ts +5 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.embedded.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.embedded.js +5 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.embedded.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/config/index.d.ts +43 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/config/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/config/index.js +68 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/config/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/_theme.bootstrap1/index.d.ts +5 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/_theme.bootstrap1/index.js +11 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/index.d.ts +32 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/index.js +32 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/_theme.bootstrap1/index.d.ts +4 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/_theme.bootstrap1/index.js +170 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/index.d.ts +60 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/index.js +48 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/_theme.bootstrap1/index.d.ts +4 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/_theme.bootstrap1/index.js +28 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/index.d.ts +48 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/index.js +40 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_theme.bootstrap1/index.d.ts +5 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_theme.bootstrap1/index.js +194 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/index.d.ts +80 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/index.js +59 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/index.d.ts +5 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/index.js +167 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/services/index.d.ts +128 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/services/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/services/index.js +89 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/services/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/_theme.bootstrap1/index.d.ts +5 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/_theme.bootstrap1/index.js +8 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/index.d.ts +89 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/index.js +93 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/_theme.bootstrap1/index.d.ts +4 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/_theme.bootstrap1/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/_theme.bootstrap1/index.js +61 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/_theme.bootstrap1/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/index.d.ts +180 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/index.js +405 -0
- package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/cpBootstrap.d.ts +26 -0
- package/lib/plugins/service-betterportal-config-manager/cpBootstrap.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/cpBootstrap.js +58 -0
- package/lib/plugins/service-betterportal-config-manager/cpBootstrap.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/fragmentsEditor.d.ts +3 -0
- package/lib/plugins/service-betterportal-config-manager/fragmentsEditor.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/fragmentsEditor.js +365 -0
- package/lib/plugins/service-betterportal-config-manager/fragmentsEditor.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/index.d.ts +143 -0
- package/lib/plugins/service-betterportal-config-manager/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/index.js +696 -0
- package/lib/plugins/service-betterportal-config-manager/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/menuEditor.d.ts +3 -0
- package/lib/plugins/service-betterportal-config-manager/menuEditor.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/menuEditor.js +823 -0
- package/lib/plugins/service-betterportal-config-manager/menuEditor.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/routeContext.d.ts +10 -0
- package/lib/plugins/service-betterportal-config-manager/routeContext.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/routeContext.js +11 -0
- package/lib/plugins/service-betterportal-config-manager/routeContext.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/setupTokens.d.ts +18 -0
- package/lib/plugins/service-betterportal-config-manager/setupTokens.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/setupTokens.js +245 -0
- package/lib/plugins/service-betterportal-config-manager/setupTokens.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/storage/core.d.ts +41 -0
- package/lib/plugins/service-betterportal-config-manager/storage/core.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/storage/core.js +396 -0
- package/lib/plugins/service-betterportal-config-manager/storage/core.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/storage/file.d.ts +10 -0
- package/lib/plugins/service-betterportal-config-manager/storage/file.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/storage/file.js +30 -0
- package/lib/plugins/service-betterportal-config-manager/storage/file.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/storage/index.d.ts +36 -0
- package/lib/plugins/service-betterportal-config-manager/storage/index.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/storage/index.js +52 -0
- package/lib/plugins/service-betterportal-config-manager/storage/index.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/storage/postgres.d.ts +15 -0
- package/lib/plugins/service-betterportal-config-manager/storage/postgres.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/storage/postgres.js +60 -0
- package/lib/plugins/service-betterportal-config-manager/storage/postgres.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/syncApi.d.ts +44 -0
- package/lib/plugins/service-betterportal-config-manager/syncApi.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/syncApi.js +280 -0
- package/lib/plugins/service-betterportal-config-manager/syncApi.js.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/webhooks.d.ts +6 -0
- package/lib/plugins/service-betterportal-config-manager/webhooks.d.ts.map +1 -0
- package/lib/plugins/service-betterportal-config-manager/webhooks.js +372 -0
- package/lib/plugins/service-betterportal-config-manager/webhooks.js.map +1 -0
- package/lib/schemas/service-betterportal-config-manager.json +157 -0
- package/lib/schemas/service-betterportal-config-manager.plugin.json +135 -0
- package/package.json +69 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { htmlResponse, jsonResponse } from "@betterportal/framework";
|
|
2
|
+
const API_BASE = "/.well-known/bp/admin";
|
|
3
|
+
async function readFormBody(event) {
|
|
4
|
+
const fd = await event.req.formData().catch(() => null);
|
|
5
|
+
if (!fd)
|
|
6
|
+
return {};
|
|
7
|
+
const out = {};
|
|
8
|
+
fd.forEach((v, k) => { if (typeof v === "string")
|
|
9
|
+
out[k] = v; });
|
|
10
|
+
return out;
|
|
11
|
+
}
|
|
12
|
+
function escapeHtml(s) {
|
|
13
|
+
return s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c]));
|
|
14
|
+
}
|
|
15
|
+
function getApp(config, appId) {
|
|
16
|
+
return config.apps.find((a) => a.id === appId) ?? null;
|
|
17
|
+
}
|
|
18
|
+
function getServicesForApp(config, appDef) {
|
|
19
|
+
const tenant = (config.tenants ?? []).find((t) => t.id === appDef.tenantId);
|
|
20
|
+
if (!tenant)
|
|
21
|
+
return [];
|
|
22
|
+
const tenantSvcs = (tenant.services ?? []).filter((s) => s.enabled).map((s) => ({
|
|
23
|
+
id: s.id, title: s.title || s.serviceId || s.id, hostname: s.hostname
|
|
24
|
+
}));
|
|
25
|
+
const platformSvcs = (tenant.activatedPlatformServices ?? [])
|
|
26
|
+
.map((psId) => (config.platformServices ?? []).find((p) => p.id === psId && p.enabled))
|
|
27
|
+
.filter(Boolean)
|
|
28
|
+
.map((p) => ({ id: p.id, title: `${p.title || p.id} (platform)`, hostname: p.hostname }));
|
|
29
|
+
const sharedSvcs = (config.sharedServiceActivations ?? [])
|
|
30
|
+
.filter((activation) => activation.enabled
|
|
31
|
+
&& activation.tenantId === appDef.tenantId
|
|
32
|
+
&& (!activation.appId || activation.appId === appDef.id))
|
|
33
|
+
.map((activation) => {
|
|
34
|
+
const shared = (config.sharedServiceCatalog ?? []).find((s) => s.id === activation.sharedServiceId && s.enabled);
|
|
35
|
+
return shared ? {
|
|
36
|
+
id: activation.id,
|
|
37
|
+
title: `${shared.title || shared.id} (shared)`,
|
|
38
|
+
hostname: shared.baseUrl
|
|
39
|
+
} : null;
|
|
40
|
+
})
|
|
41
|
+
.filter(Boolean);
|
|
42
|
+
return [...tenantSvcs, ...platformSvcs, ...sharedSvcs];
|
|
43
|
+
}
|
|
44
|
+
function getServiceTitle(config, serviceId) {
|
|
45
|
+
for (const t of config.tenants ?? []) {
|
|
46
|
+
const s = (t.services ?? []).find((x) => x.id === serviceId);
|
|
47
|
+
if (s)
|
|
48
|
+
return s.title || s.serviceId || s.id;
|
|
49
|
+
}
|
|
50
|
+
const activation = (config.sharedServiceActivations ?? []).find((x) => x.id === serviceId);
|
|
51
|
+
if (activation) {
|
|
52
|
+
const shared = (config.sharedServiceCatalog ?? []).find((x) => x.id === activation.sharedServiceId);
|
|
53
|
+
if (shared)
|
|
54
|
+
return `${shared.title || shared.id} (shared)`;
|
|
55
|
+
}
|
|
56
|
+
const ps = (config.platformServices ?? []).find((x) => x.id === serviceId);
|
|
57
|
+
return ps ? (ps.title || ps.id) : serviceId;
|
|
58
|
+
}
|
|
59
|
+
function getServiceHostname(config, serviceId) {
|
|
60
|
+
for (const t of config.tenants ?? []) {
|
|
61
|
+
const s = (t.services ?? []).find((x) => x.id === serviceId);
|
|
62
|
+
if (s)
|
|
63
|
+
return s.hostname ?? null;
|
|
64
|
+
}
|
|
65
|
+
const activation = (config.sharedServiceActivations ?? []).find((x) => x.id === serviceId);
|
|
66
|
+
if (activation) {
|
|
67
|
+
const shared = (config.sharedServiceCatalog ?? []).find((x) => x.id === activation.sharedServiceId);
|
|
68
|
+
if (shared)
|
|
69
|
+
return shared.baseUrl ?? null;
|
|
70
|
+
}
|
|
71
|
+
const ps = (config.platformServices ?? []).find((x) => x.id === serviceId);
|
|
72
|
+
return ps?.hostname ?? null;
|
|
73
|
+
}
|
|
74
|
+
function getFragments(appDef, location) {
|
|
75
|
+
const all = (appDef.fragments ?? {});
|
|
76
|
+
return all[location] ?? [];
|
|
77
|
+
}
|
|
78
|
+
function setFragments(appDef, location, frags) {
|
|
79
|
+
appDef.fragments = appDef.fragments ?? {};
|
|
80
|
+
appDef.fragments[location] = frags;
|
|
81
|
+
}
|
|
82
|
+
const LOCATIONS = [
|
|
83
|
+
{ id: "nav", label: "Topbar (right side)" },
|
|
84
|
+
{ id: "footer", label: "Footer" }
|
|
85
|
+
];
|
|
86
|
+
function renderFragmentRow(frag, idx, location, appId, config) {
|
|
87
|
+
const serviceTitle = getServiceTitle(config, frag.serviceId);
|
|
88
|
+
const btn = (action, label, btnClass, title) => `<form hx-post="${API_BASE}/fragments-editor/${action}" hx-target="#bp-fragments-editor" hx-swap="outerHTML" class="d-inline m-0">
|
|
89
|
+
<input type="hidden" name="appId" value="${escapeHtml(appId)}" />
|
|
90
|
+
<input type="hidden" name="location" value="${escapeHtml(location)}" />
|
|
91
|
+
<input type="hidden" name="index" value="${idx}" />
|
|
92
|
+
<button type="submit" class="btn btn-sm ${btnClass}" title="${escapeHtml(title)}">${label}</button>
|
|
93
|
+
</form>`;
|
|
94
|
+
return `<li class="list-group-item d-flex justify-content-between align-items-center">
|
|
95
|
+
<div class="d-flex flex-column gap-1 flex-grow-1 min-width-0">
|
|
96
|
+
<div class="d-flex align-items-center gap-2">
|
|
97
|
+
<span class="badge text-bg-secondary">${escapeHtml(serviceTitle)}</span>
|
|
98
|
+
<span class="font-monospace">${escapeHtml(frag.fragmentId)}</span>
|
|
99
|
+
<span class="text-secondary">-></span>
|
|
100
|
+
<span class="font-monospace text-secondary small">${escapeHtml(frag.targetPath)}</span>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
<div class="btn-group btn-group-sm" role="group">
|
|
104
|
+
${btn("move-up", "^", "btn-outline-secondary", "Move up")}
|
|
105
|
+
${btn("move-down", "v", "btn-outline-secondary", "Move down")}
|
|
106
|
+
${btn("toggle", frag.enabled ? "on" : "off", frag.enabled ? "btn-success" : "btn-outline-secondary", frag.enabled ? "Disable" : "Enable")}
|
|
107
|
+
${btn("remove", "x", "btn-outline-danger", "Remove")}
|
|
108
|
+
</div>
|
|
109
|
+
</li>`;
|
|
110
|
+
}
|
|
111
|
+
function renderLocationSection(location, label, frags, appId, config, appDef) {
|
|
112
|
+
const services = getServicesForApp(config, appDef);
|
|
113
|
+
const serviceOpts = ["<option value=\"\">Select service...</option>",
|
|
114
|
+
...services.map((s) => {
|
|
115
|
+
const schemaUrl = `${s.hostname.replace(/\/+$/, "")}/.well-known/bp/schema.json`;
|
|
116
|
+
return `<option value="${escapeHtml(s.id)}" data-schema-url="${escapeHtml(schemaUrl)}">${escapeHtml(s.title)}</option>`;
|
|
117
|
+
})
|
|
118
|
+
].join("");
|
|
119
|
+
const rows = frags.length === 0
|
|
120
|
+
? `<li class="list-group-item text-secondary">No fragments in this location.</li>`
|
|
121
|
+
: frags.map((f, i) => renderFragmentRow(f, i, location, appId, config)).join("");
|
|
122
|
+
return `<div class="card mb-3">
|
|
123
|
+
<div class="card-header"><strong>${escapeHtml(label)}</strong> <span class="small text-secondary">(${frags.length})</span></div>
|
|
124
|
+
<ul class="list-group list-group-flush">${rows}</ul>
|
|
125
|
+
<div class="card-body">
|
|
126
|
+
<form hx-post="${API_BASE}/fragments-editor/add" hx-target="#bp-fragments-editor" hx-swap="outerHTML"
|
|
127
|
+
class="row g-2 align-items-end">
|
|
128
|
+
<input type="hidden" name="appId" value="${escapeHtml(appId)}" />
|
|
129
|
+
<input type="hidden" name="location" value="${escapeHtml(location)}" />
|
|
130
|
+
<div class="col-md-3">
|
|
131
|
+
<label class="form-label small mb-0">Service</label>
|
|
132
|
+
<select name="serviceId" class="form-select form-select-sm" required
|
|
133
|
+
hx-get="${API_BASE}/fragments-editor/fragments"
|
|
134
|
+
hx-target="#bp-frag-select-${location}"
|
|
135
|
+
hx-swap="outerHTML"
|
|
136
|
+
hx-trigger="change"
|
|
137
|
+
hx-include="closest form">${serviceOpts}</select>
|
|
138
|
+
</div>
|
|
139
|
+
<div class="col-md-3">
|
|
140
|
+
<label class="form-label small mb-0">Fragment</label>
|
|
141
|
+
<select id="bp-frag-select-${location}" name="fragmentId" class="form-select form-select-sm" required
|
|
142
|
+
data-bp-frag-select
|
|
143
|
+
data-location="${escapeHtml(location)}">
|
|
144
|
+
<option value="">Pick service first...</option>
|
|
145
|
+
</select>
|
|
146
|
+
<div id="bp-frag-status-${location}" class="form-text small text-secondary"></div>
|
|
147
|
+
</div>
|
|
148
|
+
<div class="col-md-4">
|
|
149
|
+
<label class="form-label small mb-0">Target Path</label>
|
|
150
|
+
<input id="bp-frag-target-${location}" type="text" name="targetPath" class="form-control form-control-sm font-monospace" placeholder="auto-filled" required />
|
|
151
|
+
</div>
|
|
152
|
+
<div class="col-md-2">
|
|
153
|
+
<button type="submit" class="btn btn-primary btn-sm w-100">Add</button>
|
|
154
|
+
</div>
|
|
155
|
+
</form>
|
|
156
|
+
</div>
|
|
157
|
+
</div>`;
|
|
158
|
+
}
|
|
159
|
+
function renderFragmentEditorScript() {
|
|
160
|
+
return `<script>
|
|
161
|
+
(() => {
|
|
162
|
+
const root = document.getElementById("bp-fragments-editor");
|
|
163
|
+
if (!root) return;
|
|
164
|
+
|
|
165
|
+
const escapeHtml = (value) => String(value).replace(/[&<>"']/g, (ch) => ({
|
|
166
|
+
"&": "&", "<": "<", ">": ">", '"': """, "'": "'"
|
|
167
|
+
})[ch]);
|
|
168
|
+
|
|
169
|
+
const loadFragments = async (fragmentSelect) => {
|
|
170
|
+
const location = fragmentSelect.dataset.location || "";
|
|
171
|
+
const schemaUrl = fragmentSelect.dataset.schemaUrl || "";
|
|
172
|
+
const targetInput = root.querySelector("#bp-frag-target-" + CSS.escape(location));
|
|
173
|
+
const status = root.querySelector("#bp-frag-status-" + CSS.escape(location));
|
|
174
|
+
if (targetInput) targetInput.value = "";
|
|
175
|
+
try {
|
|
176
|
+
if (status) status.textContent = "Loading service schema from " + schemaUrl;
|
|
177
|
+
const response = await fetch(schemaUrl, {
|
|
178
|
+
method: "GET",
|
|
179
|
+
headers: { Accept: "application/json" },
|
|
180
|
+
cache: "no-store"
|
|
181
|
+
});
|
|
182
|
+
if (!response.ok) throw new Error(String(response.status));
|
|
183
|
+
const schema = (response.headers.get("content-type") || "").includes("application/json") ? await response.json() : null;
|
|
184
|
+
if (!schema) throw new Error("service schema returned non-JSON");
|
|
185
|
+
const fragments = [];
|
|
186
|
+
for (const route of schema.routes || []) {
|
|
187
|
+
for (const fragment of route.fragments || []) {
|
|
188
|
+
if (location && fragment.fragmentLocation !== location) continue;
|
|
189
|
+
fragments.push({
|
|
190
|
+
fragmentId: fragment.fragmentId,
|
|
191
|
+
viewPath: route.path || ""
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (fragments.length === 0) {
|
|
197
|
+
fragmentSelect.innerHTML = '<option value="">No fragments at "' + escapeHtml(location) + '"</option>';
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
fragmentSelect.innerHTML = '<option value="">Select fragment...</option>' + fragments
|
|
202
|
+
.map((fragment) => '<option value="' + escapeHtml(fragment.fragmentId) + '" data-view-path="' + escapeHtml(fragment.viewPath) + '">' + escapeHtml(fragment.fragmentId) + ' (' + escapeHtml(fragment.viewPath) + ')</option>')
|
|
203
|
+
.join("");
|
|
204
|
+
if (status) status.textContent = "Loaded " + fragments.length + " fragment" + (fragments.length === 1 ? "" : "s") + " from service.";
|
|
205
|
+
} catch {
|
|
206
|
+
fragmentSelect.innerHTML = '<option value="">Unable to load fragments from browser</option>';
|
|
207
|
+
if (status) status.textContent = "Failed to load service schema from " + schemaUrl;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
if (root.dataset.bpFragmentsBound !== "1") {
|
|
212
|
+
root.dataset.bpFragmentsBound = "1";
|
|
213
|
+
root.addEventListener("change", (event) => {
|
|
214
|
+
const target = event.target;
|
|
215
|
+
if (!(target instanceof HTMLSelectElement)) return;
|
|
216
|
+
|
|
217
|
+
if (target.matches("[data-bp-frag-select]")) {
|
|
218
|
+
const location = target.dataset.location || "";
|
|
219
|
+
const targetInput = root.querySelector("#bp-frag-target-" + CSS.escape(location));
|
|
220
|
+
const selected = target.selectedOptions && target.selectedOptions[0];
|
|
221
|
+
if (targetInput) targetInput.value = selected ? (selected.dataset.viewPath || "") : "";
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
root.querySelectorAll("[data-bp-frag-select][data-schema-url]").forEach((select) => {
|
|
227
|
+
if (select.dataset.loaded === "1") return;
|
|
228
|
+
select.dataset.loaded = "1";
|
|
229
|
+
loadFragments(select);
|
|
230
|
+
});
|
|
231
|
+
})();
|
|
232
|
+
</script>`;
|
|
233
|
+
}
|
|
234
|
+
function renderFragmentSelect(location, schemaUrl) {
|
|
235
|
+
return `<select id="bp-frag-select-${escapeHtml(location)}" name="fragmentId" class="form-select form-select-sm" required
|
|
236
|
+
data-bp-frag-select
|
|
237
|
+
data-location="${escapeHtml(location)}"
|
|
238
|
+
data-schema-url="${escapeHtml(schemaUrl)}">
|
|
239
|
+
<option value="">Loading fragments...</option>
|
|
240
|
+
</select>
|
|
241
|
+
${renderFragmentEditorScript()}`;
|
|
242
|
+
}
|
|
243
|
+
function renderEditor(config, appDef, appId) {
|
|
244
|
+
const sections = LOCATIONS.map((loc) => renderLocationSection(loc.id, loc.label, getFragments(appDef, loc.id), appId, config, appDef)).join("");
|
|
245
|
+
return `<div id="bp-fragments-editor">${sections}${renderFragmentEditorScript()}</div>`;
|
|
246
|
+
}
|
|
247
|
+
export function registerFragmentsEditorRoutes(app, store) {
|
|
248
|
+
const respondEditor = async (appId) => {
|
|
249
|
+
const config = await store.loadConfig();
|
|
250
|
+
const appDef = getApp(config, appId);
|
|
251
|
+
if (!appDef)
|
|
252
|
+
return htmlResponse(`<div class="alert alert-danger">App not found</div>`, 200, "text/html; mode=fragment");
|
|
253
|
+
return htmlResponse(renderEditor(config, appDef, appId), 200, "text/html; mode=fragment", {
|
|
254
|
+
"HX-Trigger": "bp:fragments-changed"
|
|
255
|
+
});
|
|
256
|
+
};
|
|
257
|
+
app.get(`${API_BASE}/fragments-editor`, async (event) => {
|
|
258
|
+
const url = new URL(event.req.url ?? "", `http://${event.req.headers.get("host") ?? "localhost"}`);
|
|
259
|
+
const appId = url.searchParams.get("appId") ?? "";
|
|
260
|
+
if (!appId)
|
|
261
|
+
return htmlResponse(`<div class="alert alert-secondary">Select an app</div>`, 200, "text/html; mode=fragment");
|
|
262
|
+
return respondEditor(appId);
|
|
263
|
+
});
|
|
264
|
+
app.post(`${API_BASE}/fragments-editor/add`, async (event) => {
|
|
265
|
+
const f = await readFormBody(event);
|
|
266
|
+
const config = await store.loadConfig();
|
|
267
|
+
const appDef = getApp(config, f.appId);
|
|
268
|
+
if (!appDef)
|
|
269
|
+
return jsonResponse({ error: "App not found" }, 404);
|
|
270
|
+
if (!f.serviceId || !f.fragmentId || !f.targetPath)
|
|
271
|
+
return respondEditor(f.appId);
|
|
272
|
+
const frags = getFragments(appDef, f.location);
|
|
273
|
+
frags.push({
|
|
274
|
+
serviceId: f.serviceId,
|
|
275
|
+
fragmentId: f.fragmentId,
|
|
276
|
+
targetPath: f.targetPath,
|
|
277
|
+
enabled: true
|
|
278
|
+
});
|
|
279
|
+
setFragments(appDef, f.location, frags);
|
|
280
|
+
await store.saveConfig(config);
|
|
281
|
+
return respondEditor(f.appId);
|
|
282
|
+
});
|
|
283
|
+
app.post(`${API_BASE}/fragments-editor/remove`, async (event) => {
|
|
284
|
+
const f = await readFormBody(event);
|
|
285
|
+
const config = await store.loadConfig();
|
|
286
|
+
const appDef = getApp(config, f.appId);
|
|
287
|
+
if (!appDef)
|
|
288
|
+
return jsonResponse({ error: "App not found" }, 404);
|
|
289
|
+
const idx = parseInt(f.index, 10);
|
|
290
|
+
const frags = getFragments(appDef, f.location);
|
|
291
|
+
if (idx >= 0 && idx < frags.length)
|
|
292
|
+
frags.splice(idx, 1);
|
|
293
|
+
setFragments(appDef, f.location, frags);
|
|
294
|
+
await store.saveConfig(config);
|
|
295
|
+
return respondEditor(f.appId);
|
|
296
|
+
});
|
|
297
|
+
app.post(`${API_BASE}/fragments-editor/toggle`, async (event) => {
|
|
298
|
+
const f = await readFormBody(event);
|
|
299
|
+
const config = await store.loadConfig();
|
|
300
|
+
const appDef = getApp(config, f.appId);
|
|
301
|
+
if (!appDef)
|
|
302
|
+
return jsonResponse({ error: "App not found" }, 404);
|
|
303
|
+
const idx = parseInt(f.index, 10);
|
|
304
|
+
const frags = getFragments(appDef, f.location);
|
|
305
|
+
if (idx >= 0 && idx < frags.length)
|
|
306
|
+
frags[idx].enabled = !frags[idx].enabled;
|
|
307
|
+
setFragments(appDef, f.location, frags);
|
|
308
|
+
await store.saveConfig(config);
|
|
309
|
+
return respondEditor(f.appId);
|
|
310
|
+
});
|
|
311
|
+
app.post(`${API_BASE}/fragments-editor/move-up`, async (event) => {
|
|
312
|
+
const f = await readFormBody(event);
|
|
313
|
+
const config = await store.loadConfig();
|
|
314
|
+
const appDef = getApp(config, f.appId);
|
|
315
|
+
if (!appDef)
|
|
316
|
+
return jsonResponse({ error: "App not found" }, 404);
|
|
317
|
+
const idx = parseInt(f.index, 10);
|
|
318
|
+
const frags = getFragments(appDef, f.location);
|
|
319
|
+
if (idx > 0 && idx < frags.length) {
|
|
320
|
+
const [it] = frags.splice(idx, 1);
|
|
321
|
+
frags.splice(idx - 1, 0, it);
|
|
322
|
+
}
|
|
323
|
+
setFragments(appDef, f.location, frags);
|
|
324
|
+
await store.saveConfig(config);
|
|
325
|
+
return respondEditor(f.appId);
|
|
326
|
+
});
|
|
327
|
+
app.get(`${API_BASE}/fragments-editor/fragments`, async (event) => {
|
|
328
|
+
const url = new URL(event.req.url ?? "", `http://${event.req.headers.get("host") ?? "localhost"}`);
|
|
329
|
+
const serviceId = url.searchParams.get("serviceId") ?? "";
|
|
330
|
+
const location = url.searchParams.get("location") ?? "";
|
|
331
|
+
if (!serviceId)
|
|
332
|
+
return htmlResponse(`<option value="">Pick service first...</option>`, 200, "text/html; mode=fragment");
|
|
333
|
+
const config = await store.loadConfig();
|
|
334
|
+
const hostname = getServiceHostname(config, serviceId);
|
|
335
|
+
if (!hostname) {
|
|
336
|
+
return htmlResponse(`<select id="bp-frag-select-${escapeHtml(location)}" name="fragmentId" class="form-select form-select-sm" required><option value="">No service</option></select>`, 200, "text/html; mode=fragment");
|
|
337
|
+
}
|
|
338
|
+
return htmlResponse(renderFragmentSelect(location, `${hostname.replace(/\/+$/, "")}/.well-known/bp/schema.json`), 200, "text/html; mode=fragment");
|
|
339
|
+
});
|
|
340
|
+
app.get(`${API_BASE}/fragments-editor/fragment-target`, async (event) => {
|
|
341
|
+
const url = new URL(event.req.url ?? "", `http://${event.req.headers.get("host") ?? "localhost"}`);
|
|
342
|
+
const serviceId = url.searchParams.get("serviceId") ?? "";
|
|
343
|
+
const fragmentId = url.searchParams.get("fragmentId") ?? "";
|
|
344
|
+
const location = url.searchParams.get("location") ?? "";
|
|
345
|
+
const targetPath = url.searchParams.get("targetPath") ?? "";
|
|
346
|
+
return htmlResponse(`<input id="bp-frag-target-${escapeHtml(location)}" type="text" name="targetPath" class="form-control form-control-sm font-monospace" value="${escapeHtml(targetPath)}" placeholder="auto-filled" required />`, 200, "text/html; mode=fragment");
|
|
347
|
+
});
|
|
348
|
+
app.post(`${API_BASE}/fragments-editor/move-down`, async (event) => {
|
|
349
|
+
const f = await readFormBody(event);
|
|
350
|
+
const config = await store.loadConfig();
|
|
351
|
+
const appDef = getApp(config, f.appId);
|
|
352
|
+
if (!appDef)
|
|
353
|
+
return jsonResponse({ error: "App not found" }, 404);
|
|
354
|
+
const idx = parseInt(f.index, 10);
|
|
355
|
+
const frags = getFragments(appDef, f.location);
|
|
356
|
+
if (idx >= 0 && idx < frags.length - 1) {
|
|
357
|
+
const [it] = frags.splice(idx, 1);
|
|
358
|
+
frags.splice(idx + 1, 0, it);
|
|
359
|
+
}
|
|
360
|
+
setFragments(appDef, f.location, frags);
|
|
361
|
+
await store.saveConfig(config);
|
|
362
|
+
return respondEditor(f.appId);
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
//# sourceMappingURL=fragmentsEditor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fragmentsEditor.js","sourceRoot":"","sources":["../../../src/plugins/service-betterportal-config-manager/fragmentsEditor.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,YAAY,EACZ,YAAY,EACb,MAAM,yBAAyB,CAAC;AAEjC,MAAM,QAAQ,GAAG,uBAAuB,CAAC;AASzC,KAAK,UAAU,YAAY,CAAC,KAAwB;IAClD,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACxD,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,CAAC;IACnB,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;AACrH,CAAC;AAED,SAAS,MAAM,CAAC,MAAW,EAAE,KAAa;IACxC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC;AAC9D,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAW,EAAE,MAAW;IACjD,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjF,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;QACxF,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ;KACtE,CAAC,CAAC,CAAC;IACJ,MAAM,YAAY,GAAG,CAAC,MAAM,CAAC,yBAAyB,IAAI,EAAE,CAAC;SAC1D,GAAG,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;SACnG,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACjG,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,wBAAwB,IAAI,EAAE,CAAC;SACvD,MAAM,CAAC,CAAC,UAAe,EAAE,EAAE,CAC1B,UAAU,CAAC,OAAO;WACf,UAAU,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ;WACvC,CAAC,CAAC,UAAU,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,KAAK,MAAM,CAAC,EAAE,CAAC,CACzD;SACA,GAAG,CAAC,CAAC,UAAe,EAAE,EAAE;QACvB,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,eAAe,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;QACtH,OAAO,MAAM,CAAC,CAAC,CAAC;YACd,EAAE,EAAE,UAAU,CAAC,EAAE;YACjB,KAAK,EAAE,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,EAAE,WAAW;YAC9C,QAAQ,EAAE,MAAM,CAAC,OAAO;SACzB,CAAC,CAAC,CAAC,IAAI,CAAC;IACX,CAAC,CAAC;SACD,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,OAAO,CAAC,GAAG,UAAU,EAAE,GAAG,YAAY,EAAE,GAAG,UAAU,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,eAAe,CAAC,MAAW,EAAE,SAAiB;IACrD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QAClE,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC;IAC/C,CAAC;IACD,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;IAChG,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,eAAe,CAAC,CAAC;QACzG,IAAI,MAAM;YAAE,OAAO,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,EAAE,WAAW,CAAC;IAC7D,CAAC;IACD,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;IAChF,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9C,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAW,EAAE,SAAiB;IACxD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QAClE,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC;IACnC,CAAC;IACD,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;IAChG,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,eAAe,CAAC,CAAC;QACzG,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC;IAC5C,CAAC;IACD,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;IAChF,OAAO,EAAE,EAAE,QAAQ,IAAI,IAAI,CAAC;AAC9B,CAAC;AAQD,SAAS,YAAY,CAAC,MAAW,EAAE,QAAgB;IACjD,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAA+B,CAAC;IACnE,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,YAAY,CAAC,MAAW,EAAE,QAAgB,EAAE,KAAiB;IACpE,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;IACzC,MAAM,CAAC,SAAwC,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC;AACrE,CAAC;AAED,MAAM,SAAS,GAAG;IAChB,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,qBAAqB,EAAE;IAC3C,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;CAClC,CAAC;AAEF,SAAS,iBAAiB,CAAC,IAAc,EAAE,GAAW,EAAE,QAAgB,EAAE,KAAa,EAAE,MAAW;IAClG,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7D,MAAM,GAAG,GAAG,CAAC,MAAc,EAAE,KAAa,EAAE,QAAgB,EAAE,KAAa,EAAE,EAAE,CAC7E,kBAAkB,QAAQ,qBAAqB,MAAM;iDACR,UAAU,CAAC,KAAK,CAAC;oDACd,UAAU,CAAC,QAAQ,CAAC;iDACvB,GAAG;gDACJ,QAAQ,YAAY,UAAU,CAAC,KAAK,CAAC,KAAK,KAAK;YACnF,CAAC;IAEX,OAAO;;;gDAGuC,UAAU,CAAC,YAAY,CAAC;uCACjC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC;;4DAEN,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC;;;;QAI/E,GAAG,CAAC,SAAS,EAAE,GAAG,EAAE,uBAAuB,EAAE,SAAS,CAAC;QACvD,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE,uBAAuB,EAAE,WAAW,CAAC;QAC3D,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,uBAAuB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;QACvI,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,oBAAoB,EAAE,QAAQ,CAAC;;QAElD,CAAC;AACT,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAgB,EAAE,KAAa,EAAE,KAAiB,EAAE,KAAa,EAAE,MAAW,EAAE,MAAW;IACxH,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,MAAM,WAAW,GAAG,CAAC,+CAA+C;QAClE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACpB,MAAM,SAAS,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,6BAA6B,CAAC;YACjF,OAAO,kBAAkB,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,sBAAsB,UAAU,CAAC,SAAS,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC;QAC1H,CAAC,CAAC;KACH,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEX,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC;QAC7B,CAAC,CAAC,gFAAgF;QAClF,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEnF,OAAO;uCAC8B,UAAU,CAAC,KAAK,CAAC,iDAAiD,KAAK,CAAC,MAAM;8CACvE,IAAI;;uBAE3B,QAAQ;;mDAEoB,UAAU,CAAC,KAAK,CAAC;sDACd,UAAU,CAAC,QAAQ,CAAC;;;;sBAIpD,QAAQ;yCACW,QAAQ;;;wCAGT,WAAW;;;;uCAIZ,QAAQ;;6BAElB,UAAU,CAAC,QAAQ,CAAC;;;oCAGb,QAAQ;;;;sCAIN,QAAQ;;;;;;;SAOrC,CAAC;AACV,CAAC;AAED,SAAS,0BAA0B;IACjC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAwEC,CAAC;AACX,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAgB,EAAE,SAAiB;IAC/D,OAAO,8BAA8B,UAAU,CAAC,QAAQ,CAAC;;qBAEtC,UAAU,CAAC,QAAQ,CAAC;uBAClB,UAAU,CAAC,SAAS,CAAC;;;IAGxC,0BAA0B,EAAE,EAAE,CAAC;AACnC,CAAC;AAED,SAAS,YAAY,CAAC,MAAW,EAAE,MAAW,EAAE,KAAa;IAC3D,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACrC,qBAAqB,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAC9F,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEX,OAAO,iCAAiC,QAAQ,GAAG,0BAA0B,EAAE,QAAQ,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,GAAsB,EAAE,KAA0B;IAE9F,MAAM,aAAa,GAAG,KAAK,EAAE,KAAa,EAAqB,EAAE;QAC/D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC,qDAAqD,EAAE,GAAG,EAAE,0BAA0B,CAAC,CAAC;QACzH,OAAO,YAAY,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,0BAA0B,EAAE;YACxF,YAAY,EAAE,sBAAsB;SACrC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,mBAAmB,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QACtD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,UAAU,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC;QACnG,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAClD,IAAI,CAAC,KAAK;YAAE,OAAO,YAAY,CAAC,wDAAwD,EAAE,GAAG,EAAE,0BAA0B,CAAC,CAAC;QAC3H,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,uBAAuB,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC3D,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,GAAG,CAAC,CAAC;QAClE,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,UAAU;YAAE,OAAO,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAClF,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC;YACT,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACxC,MAAM,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,0BAA0B,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC9D,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,GAAG,CAAC,CAAC;QAClE,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM;YAAE,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACzD,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACxC,MAAM,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,0BAA0B,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC9D,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,GAAG,CAAC,CAAC;QAClE,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;QAC7E,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACxC,MAAM,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,2BAA2B,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC/D,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,GAAG,CAAC,CAAC;QAClE,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAClC,MAAM,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAClC,KAAK,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/B,CAAC;QACD,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACxC,MAAM,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,6BAA6B,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAChE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,UAAU,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC;QACnG,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAC1D,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACxD,IAAI,CAAC,SAAS;YAAE,OAAO,YAAY,CAAC,iDAAiD,EAAE,GAAG,EAAE,0BAA0B,CAAC,CAAC;QACxH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,YAAY,CACjB,8BAA8B,UAAU,CAAC,QAAQ,CAAC,+GAA+G,EACjK,GAAG,EACH,0BAA0B,CAC3B,CAAC;QACJ,CAAC;QACD,OAAO,YAAY,CACjB,oBAAoB,CAAC,QAAQ,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,6BAA6B,CAAC,EAC5F,GAAG,EACH,0BAA0B,CAC3B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,mCAAmC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QACtE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,UAAU,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC;QACnG,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAC1D,MAAM,UAAU,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QAC5D,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACxD,MAAM,UAAU,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QAC5D,OAAO,YAAY,CACjB,6BAA6B,UAAU,CAAC,QAAQ,CAAC,8FAA8F,UAAU,CAAC,UAAU,CAAC,yCAAyC,EAC9M,GAAG,EACH,0BAA0B,CAC3B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,6BAA6B,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QACjE,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM;YAAE,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,GAAG,CAAC,CAAC;QAClE,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvC,MAAM,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAClC,KAAK,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/B,CAAC;QACD,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACxC,MAAM,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { type BSBServiceConstructor, type Observable } from "@bsb/base";
|
|
2
|
+
import * as av from "anyvali";
|
|
3
|
+
import { BPService } from "@betterportal/plugin-bsb";
|
|
4
|
+
import type { JwtVerifier, AppAuthConfig } from "@betterportal/framework";
|
|
5
|
+
import { type BetterPortalEvent, type BetterPortalResolvedRequestContext, type BetterPortalRegistry } from "@betterportal/framework";
|
|
6
|
+
declare const Config: import("@bsb/base").BSBPluginConfigClass<av.ObjectSchema<{
|
|
7
|
+
host: av.StringSchema;
|
|
8
|
+
port: av.IntSchema;
|
|
9
|
+
storage: av.UnionSchema<[av.ObjectSchema<{
|
|
10
|
+
backend: av.LiteralSchema<"file">;
|
|
11
|
+
configPath: av.StringSchema;
|
|
12
|
+
}>, av.ObjectSchema<{
|
|
13
|
+
backend: av.LiteralSchema<"postgres">;
|
|
14
|
+
connectionString: av.StringSchema;
|
|
15
|
+
tableName: av.OptionalSchema<av.StringSchema>;
|
|
16
|
+
rowId: av.OptionalSchema<av.StringSchema>;
|
|
17
|
+
}>]>;
|
|
18
|
+
requestTimeoutMs: av.IntSchema;
|
|
19
|
+
/** Path to RSA keypair JSON used to sign envelope/setup tokens. Auto-generated on first boot. */
|
|
20
|
+
cpKeyStorePath: av.StringSchema;
|
|
21
|
+
/** Public issuer URL (matches token `iss` claim). Default: derived from host:port. */
|
|
22
|
+
cpIssuer: av.OptionalSchema<av.StringSchema>;
|
|
23
|
+
/** Required audience for tokens issued by this CP. */
|
|
24
|
+
cpAudience: av.StringSchema;
|
|
25
|
+
}>>;
|
|
26
|
+
declare const EventSchemas: {
|
|
27
|
+
readonly emitEvents: {};
|
|
28
|
+
readonly onEvents: {};
|
|
29
|
+
readonly emitReturnableEvents: {};
|
|
30
|
+
readonly onReturnableEvents: {};
|
|
31
|
+
readonly emitBroadcast: {
|
|
32
|
+
readonly "platform-config.changed": {
|
|
33
|
+
input: av.ObjectSchema<{
|
|
34
|
+
sourceId: av.StringSchema;
|
|
35
|
+
backend: av.EnumSchema<readonly ["file", "postgres"]>;
|
|
36
|
+
}>;
|
|
37
|
+
description?: string;
|
|
38
|
+
readonly __brand: "broadcast";
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
readonly onBroadcast: {};
|
|
42
|
+
};
|
|
43
|
+
export declare class Plugin extends BPService<InstanceType<typeof Config>, typeof EventSchemas> {
|
|
44
|
+
static Config: import("@bsb/base").BSBPluginConfigClass<av.ObjectSchema<{
|
|
45
|
+
host: av.StringSchema;
|
|
46
|
+
port: av.IntSchema;
|
|
47
|
+
storage: av.UnionSchema<[av.ObjectSchema<{
|
|
48
|
+
backend: av.LiteralSchema<"file">;
|
|
49
|
+
configPath: av.StringSchema;
|
|
50
|
+
}>, av.ObjectSchema<{
|
|
51
|
+
backend: av.LiteralSchema<"postgres">;
|
|
52
|
+
connectionString: av.StringSchema;
|
|
53
|
+
tableName: av.OptionalSchema<av.StringSchema>;
|
|
54
|
+
rowId: av.OptionalSchema<av.StringSchema>;
|
|
55
|
+
}>]>;
|
|
56
|
+
requestTimeoutMs: av.IntSchema;
|
|
57
|
+
/** Path to RSA keypair JSON used to sign envelope/setup tokens. Auto-generated on first boot. */
|
|
58
|
+
cpKeyStorePath: av.StringSchema;
|
|
59
|
+
/** Public issuer URL (matches token `iss` claim). Default: derived from host:port. */
|
|
60
|
+
cpIssuer: av.OptionalSchema<av.StringSchema>;
|
|
61
|
+
/** Required audience for tokens issued by this CP. */
|
|
62
|
+
cpAudience: av.StringSchema;
|
|
63
|
+
}>>;
|
|
64
|
+
static EventSchemas: {
|
|
65
|
+
readonly emitEvents: {};
|
|
66
|
+
readonly onEvents: {};
|
|
67
|
+
readonly emitReturnableEvents: {};
|
|
68
|
+
readonly onReturnableEvents: {};
|
|
69
|
+
readonly emitBroadcast: {
|
|
70
|
+
readonly "platform-config.changed": {
|
|
71
|
+
input: av.ObjectSchema<{
|
|
72
|
+
sourceId: av.StringSchema;
|
|
73
|
+
backend: av.EnumSchema<readonly ["file", "postgres"]>;
|
|
74
|
+
}>;
|
|
75
|
+
description?: string;
|
|
76
|
+
readonly __brand: "broadcast";
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
readonly onBroadcast: {};
|
|
80
|
+
};
|
|
81
|
+
protected readonly requireBetterPortalConfigSource = false;
|
|
82
|
+
private storage;
|
|
83
|
+
private webhookRuntime?;
|
|
84
|
+
private readonly changeSourceId;
|
|
85
|
+
private readonly selfClient;
|
|
86
|
+
/** CP-side signing keypair + issuer/audience info. Built on first init. */
|
|
87
|
+
private cpState;
|
|
88
|
+
/** Cache of (tenantId, appId) -> app.auth config + JWT verifier from synced storage. */
|
|
89
|
+
private readonly authConfigCache;
|
|
90
|
+
private readonly authCacheTtlMs;
|
|
91
|
+
constructor(cfg: BSBServiceConstructor<InstanceType<typeof Config>, typeof EventSchemas>);
|
|
92
|
+
protected definition(): {
|
|
93
|
+
manifest: {
|
|
94
|
+
pluginId: string;
|
|
95
|
+
title: string;
|
|
96
|
+
description: string;
|
|
97
|
+
cacheHints: {
|
|
98
|
+
metadataTtlSeconds: number;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
registry: BetterPortalRegistry;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* CM uses its own storage as the source of app.auth config (it IS the CP).
|
|
105
|
+
* Loads sync - async load via cached promise to keep getJwtVerifier signature simple.
|
|
106
|
+
*/
|
|
107
|
+
protected getAppAuthConfig(tenantId: string, appId: string): AppAuthConfig | undefined;
|
|
108
|
+
protected getJwtVerifier(tenantId: string, appId: string): JwtVerifier | undefined;
|
|
109
|
+
protected getServiceIdAliases(tenantId: string): Record<string, string> | undefined;
|
|
110
|
+
/**
|
|
111
|
+
* Stale-while-revalidate read of the auth cache. Returns any cached entry
|
|
112
|
+
* (even past its TTL) and kicks off a background refresh when stale, so an
|
|
113
|
+
* expired entry never causes a transient "Auth context unavailable" 401. The
|
|
114
|
+
* cache is warmed at startup and on every config change (see warmAuthCache),
|
|
115
|
+
* so a missing entry means the app genuinely has no auth configured.
|
|
116
|
+
*/
|
|
117
|
+
private readAuthCacheEntry;
|
|
118
|
+
/**
|
|
119
|
+
* Eagerly build verifiers for every app that already has pushed JWKS in
|
|
120
|
+
* persisted config. Called at startup (publicKeys survive restarts) and after
|
|
121
|
+
* each config change (e.g. an auth service installing and pushing its JWKS),
|
|
122
|
+
* so the first authenticated request never races an empty cache.
|
|
123
|
+
*/
|
|
124
|
+
private warmAuthCache;
|
|
125
|
+
private refreshAuthCache;
|
|
126
|
+
protected resolveCorsContext(event: BetterPortalEvent): Promise<BetterPortalResolvedRequestContext | null>;
|
|
127
|
+
protected describeCorsContextFailure(event: BetterPortalEvent): Promise<{
|
|
128
|
+
candidateHosts: string;
|
|
129
|
+
configuredAppHosts: string;
|
|
130
|
+
} | undefined>;
|
|
131
|
+
protected onRegistered(_registry: BetterPortalRegistry, _obs: Observable): Promise<void>;
|
|
132
|
+
private withChangeBroadcasts;
|
|
133
|
+
private populateConfigAdminContext;
|
|
134
|
+
private populateServicesContext;
|
|
135
|
+
private populateRoutesContext;
|
|
136
|
+
private populateMenuContext;
|
|
137
|
+
private populateFragmentsContext;
|
|
138
|
+
private populatePreviewContext;
|
|
139
|
+
private populateAdminAuthContext;
|
|
140
|
+
private populateSettingsContext;
|
|
141
|
+
}
|
|
142
|
+
export { Config, EventSchemas };
|
|
143
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/service-betterportal-config-manager/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,EAI1B,KAAK,UAAU,EAChB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAGrD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAc1E,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,kCAAkC,EACvC,KAAK,oBAAoB,EAG1B,MAAM,yBAAyB,CAAC;AA8CjC,QAAA,MAAM,MAAM;;;;;;;;;;;;;IAbV,iGAAiG;;IAEjG,sFAAsF;;IAEtF,sDAAsD;;GAiBvD,CAAC;AAEF,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;CAYhB,CAAC;AAEH,qBAAa,MAAO,SAAQ,SAAS,CAAC,YAAY,CAAC,OAAO,MAAM,CAAC,EAAE,OAAO,YAAY,CAAC;IACrF,MAAM,CAAC,MAAM;;;;;;;;;;;;;QAtCb,iGAAiG;;QAEjG,sFAAsF;;QAEtF,sDAAsD;;QAkC/B;IACvB,MAAM,CAAC,YAAY;;;;;;;;;;;;;;;;MAAgB;IACnC,SAAS,CAAC,QAAQ,CAAC,+BAA+B,SAAS;IAC3D,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,cAAc,CAAC,CAAkC;IACzD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAY;IAC3C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkC;IAC7D,2EAA2E;IAC3E,OAAO,CAAC,OAAO,CAAoB;IACnC,wFAAwF;IACxF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAwH;IACxJ,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAa;gBAEhC,GAAG,EAAE,qBAAqB,CAAC,YAAY,CAAC,OAAO,MAAM,CAAC,EAAE,OAAO,YAAY,CAAC;IAKxF,SAAS,CAAC,UAAU;;;;;;;;;;;IAYpB;;;OAGG;IACH,SAAS,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAItF,SAAS,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAIlF,SAAS,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS;IAOnF;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;;;;OAKG;YACW,aAAa;YA4Bb,gBAAgB;cAuBd,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kCAAkC,GAAG,IAAI,CAAC;cAehG,0BAA0B,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;cASjI,YAAY,CAAC,SAAS,EAAE,oBAAoB,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAqE9F,OAAO,CAAC,oBAAoB;YAqBd,0BAA0B;YA4D1B,uBAAuB;YAmGvB,qBAAqB;YAyErB,mBAAmB;YAsBnB,wBAAwB;YAcxB,sBAAsB;YAuCtB,wBAAwB;YAiGxB,uBAAuB;CAwDtC;AAED,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC"}
|