@betterportal/config-manager 11.0.9 → 11.0.11

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 (27) hide show
  1. package/lib/.bsb/clients/service-betterportal-config-manager.d.ts +1 -1
  2. package/lib/.bsb/clients/service-betterportal-config-manager.js +1 -1
  3. package/lib/bp-contracts/org.betterportal.config-manager.json +1 -1
  4. package/lib/plugins/service-betterportal-config-manager/adminApi.d.ts.map +1 -1
  5. package/lib/plugins/service-betterportal-config-manager/adminApi.js +27 -9
  6. package/lib/plugins/service-betterportal-config-manager/adminApi.js.map +1 -1
  7. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_renderer.bootstrap5/GET.d.ts.map +1 -1
  8. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_renderer.bootstrap5/GET.js +2 -3
  9. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_renderer.bootstrap5/GET.js.map +1 -1
  10. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_renderer.bootstrap5/GET.d.ts.map +1 -1
  11. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_renderer.bootstrap5/GET.js +1 -2
  12. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_renderer.bootstrap5/GET.js.map +1 -1
  13. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_renderer.bootstrap5/GET.d.ts.map +1 -1
  14. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_renderer.bootstrap5/GET.js +2 -7
  15. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_renderer.bootstrap5/GET.js.map +1 -1
  16. package/lib/plugins/service-betterportal-config-manager/serviceConnections.d.ts +5 -0
  17. package/lib/plugins/service-betterportal-config-manager/serviceConnections.d.ts.map +1 -0
  18. package/lib/plugins/service-betterportal-config-manager/serviceConnections.js +11 -0
  19. package/lib/plugins/service-betterportal-config-manager/serviceConnections.js.map +1 -0
  20. package/lib/plugins/service-betterportal-config-manager/setupTokens.d.ts.map +1 -1
  21. package/lib/plugins/service-betterportal-config-manager/setupTokens.js +6 -7
  22. package/lib/plugins/service-betterportal-config-manager/setupTokens.js.map +1 -1
  23. package/lib/plugins/service-betterportal-config-manager/tenantManagement.js +20 -3
  24. package/lib/plugins/service-betterportal-config-manager/tenantManagement.js.map +1 -1
  25. package/lib/schemas/service-betterportal-config-manager.json +1 -1
  26. package/lib/schemas/service-betterportal-config-manager.plugin.json +1 -1
  27. package/package.json +3 -3
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Auto-generated BSB virtual client for service-betterportal-config-manager
3
3
  * DO NOT EDIT - Regenerated on every build
4
- * @version 11.0.9
4
+ * @version 11.0.11
5
5
  */
6
6
  import { ServiceClient, BSBService } from "@bsb/base";
7
7
  import type { Observable, BSBServiceClientDefinition, EventInputType } from "@bsb/base";
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Auto-generated BSB virtual client for service-betterportal-config-manager
3
3
  * DO NOT EDIT - Regenerated on every build
4
- * @version 11.0.9
4
+ * @version 11.0.11
5
5
  */
6
6
  import { ServiceClient, importPortableSchema, createFireAndForgetEvent, createBroadcastEvent, createEventSchemas } from "@bsb/base";
7
7
  const _webhookDeliveryAvailableSchema = importPortableSchema(JSON.parse("{\"anyvaliVersion\":\"1.0\",\"schemaVersion\":\"1.1\",\"root\":{\"kind\":\"object\",\"properties\":{},\"required\":[],\"unknownKeys\":\"strip\"},\"definitions\":{},\"extensions\":{}}"));
@@ -4,7 +4,7 @@
4
4
  "pluginId": "org.betterportal.config-manager",
5
5
  "title": "BetterPortal Config Manager",
6
6
  "description": "Admin-facing BetterPortal service for discovering and managing service config surfaces.",
7
- "version": "11.0.9",
7
+ "version": "11.0.11",
8
8
  "category": "service",
9
9
  "deploymentModes": [
10
10
  "self-hosted"
@@ -1 +1 @@
1
- {"version":3,"file":"adminApi.d.ts","sourceRoot":"","sources":["../../../src/plugins/service-betterportal-config-manager/adminApi.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adminApi.d.ts","sourceRoot":"","sources":["../../../src/plugins/service-betterportal-config-manager/adminApi.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,7 @@ import { getCachedManifestForService, getManifestCache, reconcileCachedServiceRo
9
9
  import { apiRoutePath, appRoutePatternKey, isApiRoute, pageRoutePath } from "./routeMounts.js";
10
10
  import { M2MConnectionError, approveM2MConnections, buildM2MConnectionModel, revokeM2MConnection } from "./m2mConnections.js";
11
11
  import { isPreviewApp } from "./previewEnvironments.js";
12
+ import { renderServiceConnection } from "./serviceConnections.js";
12
13
  const API_BASE = "/.well-known/bp/admin";
13
14
  const CONFIG_TICKET_TTL_SECONDS = 5 * 60;
14
15
  // Parse-only base for relative request URLs. Never emit this origin.
@@ -178,7 +179,9 @@ function fixedParamsFromBody(body) {
178
179
  export function validateFixedParamValue(name, value, paramsSchema) {
179
180
  if (value.length > 100)
180
181
  return `${name} must be at most 100 characters.`;
181
- if (!paramsSchema)
182
+ // The SDK publishes {} when no parameter schema was declared. This is
183
+ // different from an explicitly declared AnyVali object with no such field.
184
+ if (!paramsSchema || Object.keys(paramsSchema).length === 0)
182
185
  return undefined;
183
186
  try {
184
187
  const document = paramsSchema;
@@ -2011,12 +2014,19 @@ export function registerAdminApiRoutes(app, store, cpState, database) {
2011
2014
  const appDef = config.apps.find((candidate) => candidate.id === appId);
2012
2015
  if (!appDef)
2013
2016
  return jsonResponse({ error: "App not found" }, 404);
2017
+ if (wantsHtmx(event) && selections.length !== 1)
2018
+ return htmxError("Choose one service connection to update", 400);
2014
2019
  try {
2015
2020
  const result = approveM2MConnections(config, appId, selections);
2016
2021
  if (result.created.length > 0)
2017
2022
  await store.saveConfig(config);
2018
- if (wantsHtmx(event))
2019
- return htmxReload(`/services?tenantId=${encodeURIComponent(appDef.tenantId)}&appId=${encodeURIComponent(appId)}`);
2023
+ if (wantsHtmx(event)) {
2024
+ const connections = buildM2MConnectionModel(config, appId);
2025
+ const selected = selections.length === 1 ? connections.find(connection => connection.sourceServiceId === selections[0].sourceServiceId && connection.requestId === selections[0].requestId) : undefined;
2026
+ return selected
2027
+ ? htmlResponse(String(renderServiceConnection(selected, appId, API_BASE)), 200, "text/html; mode=fragment")
2028
+ : htmxError("Service connection is no longer available", 404);
2029
+ }
2020
2030
  return jsonResponse(result, result.created.length > 0 ? 201 : 200);
2021
2031
  }
2022
2032
  catch (error) {
@@ -2032,12 +2042,15 @@ export function registerAdminApiRoutes(app, store, cpState, database) {
2032
2042
  return jsonResponse({ error: "appId and bindingId required" }, 400);
2033
2043
  const config = await store.loadConfig();
2034
2044
  const appDef = config.apps.find((candidate) => candidate.id === appId);
2045
+ const previous = buildM2MConnectionModel(config, appId).find(connection => connection.bindingId === bindingId);
2035
2046
  if (!appDef || !revokeM2MConnection(config, appId, bindingId)) {
2036
2047
  return wantsHtmx(event) ? htmxError("Service connection not found", 404) : jsonResponse({ error: "Service connection not found" }, 404);
2037
2048
  }
2038
2049
  await store.saveConfig(config);
2039
- if (wantsHtmx(event))
2040
- return htmxReload(`/services?tenantId=${encodeURIComponent(appDef.tenantId)}&appId=${encodeURIComponent(appId)}`);
2050
+ if (wantsHtmx(event)) {
2051
+ const selected = previous && buildM2MConnectionModel(config, appId).find(connection => connection.sourceServiceId === previous.sourceServiceId && connection.requestId === previous.requestId);
2052
+ return htmlResponse(selected ? String(renderServiceConnection(selected, appId, API_BASE)) : '<div class="list-group-item bp-service-connection">Service connection revoked.</div>', 200, "text/html; mode=fragment");
2053
+ }
2041
2054
  return jsonResponse({ ok: true });
2042
2055
  });
2043
2056
  // Routes (per app)
@@ -2148,7 +2161,10 @@ export function registerAdminApiRoutes(app, store, cpState, database) {
2148
2161
  const servicePathError = validateCanonicalRoutePath(requestedServicePath, "Service path");
2149
2162
  if (servicePathError)
2150
2163
  return validationError(event, servicePathError);
2151
- const submittedFixed = fixedParamsFromBody(body);
2164
+ const hasFixedParams = Object.keys(body).some(key => key.startsWith("fixedParam."));
2165
+ const submittedFixed = !hasFixedParams && !routeIdentityChanged && body.servicePathVariant === undefined
2166
+ ? route.fixedParams ?? {}
2167
+ : fixedParamsFromBody(body);
2152
2168
  const pageRenderable = isPageOperation(manifestOperation);
2153
2169
  const mappedAppPath = !pageRenderable
2154
2170
  ? apiRoutePath(manifest?.serviceId ?? route.serviceId, requestedServicePath)
@@ -2948,7 +2964,7 @@ export function renderConfigClientShell(d) {
2948
2964
  if (control === "multiselect") return Array.from(input.selectedOptions || []).map((option) => option.value).join(",");
2949
2965
  return input.value;
2950
2966
  };
2951
- const schemaLayout = (schema) => {
2967
+ const schemaLayout = (schema, scope) => {
2952
2968
  const byKey = new Map();
2953
2969
  const groupsById = new Map();
2954
2970
  for (const entry of schema.configSchemas || []) {
@@ -2957,6 +2973,8 @@ export function renderConfigClientShell(d) {
2957
2973
  }
2958
2974
  for (const field of entry.fields || []) {
2959
2975
  if (!field || typeof field.key !== "string" || byKey.has(field.key)) continue;
2976
+ // App settings may inherit tenant defaults; tenant-only settings cannot be overridden.
2977
+ if (scope === "app" && (field.scope || entry.scope) === "tenant") continue;
2960
2978
  const property = entry.jsonSchema?.properties?.[field.key] ?? entry.jsonSchema?.[field.key];
2961
2979
  const type = typeof property === "string" ? property : property?.type;
2962
2980
  const boolean = type === "boolean" || (!type && typeof field.defaultValue === "boolean");
@@ -2995,9 +3013,9 @@ export function renderConfigClientShell(d) {
2995
3013
  return { fields, sections };
2996
3014
  };
2997
3015
  const renderForm = async (schema, token, selectedScope, appId) => {
2998
- const layout = schemaLayout(schema);
2999
- const fields = layout.fields;
3000
3016
  const scope = selectedScope === "app" ? "app" : "tenant";
3017
+ const layout = schemaLayout(schema, scope);
3018
+ const fields = layout.fields;
3001
3019
  const apps = cfg.tenantApps || [];
3002
3020
  const selectedAppId = scope === "app"
3003
3021
  ? (apps.some((app) => app.id === appId) ? appId : apps[0]?.id || "")