@betterportal/config-manager 10.1.62 → 10.1.63

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 (58) 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 +36 -3
  4. package/lib/plugins/service-betterportal-config-manager/adminApi.d.ts +96 -12
  5. package/lib/plugins/service-betterportal-config-manager/adminApi.d.ts.map +1 -1
  6. package/lib/plugins/service-betterportal-config-manager/adminApi.js +26 -22
  7. package/lib/plugins/service-betterportal-config-manager/adminApi.js.map +1 -1
  8. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/route.impl.d.ts.map +1 -1
  9. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/route.impl.js +13 -13
  10. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/route.impl.js.map +1 -1
  11. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/route.impl.d.ts.map +1 -1
  12. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/route.impl.js +5 -5
  13. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/route.impl.js.map +1 -1
  14. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/route.impl.d.ts.map +1 -1
  15. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/route.impl.js +2 -2
  16. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/route.impl.js.map +1 -1
  17. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/route.impl.d.ts.map +1 -1
  18. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/route.impl.js +4 -4
  19. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/route.impl.js.map +1 -1
  20. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/route.impl.d.ts.map +1 -1
  21. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/route.impl.js +4 -4
  22. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/route.impl.js.map +1 -1
  23. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/route.impl.d.ts +2 -2
  24. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/route.impl.d.ts.map +1 -1
  25. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/route.impl.js +7 -7
  26. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/route.impl.js.map +1 -1
  27. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/route.impl.d.ts.map +1 -1
  28. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/route.impl.js +7 -7
  29. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/route.impl.js.map +1 -1
  30. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/route.impl.d.ts.map +1 -1
  31. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/route.impl.js +5 -5
  32. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/route.impl.js.map +1 -1
  33. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/route.impl.d.ts +4 -4
  34. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/route.impl.d.ts.map +1 -1
  35. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/route.impl.js +10 -10
  36. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/route.impl.js.map +1 -1
  37. package/lib/plugins/service-betterportal-config-manager/cpBootstrap.d.ts +2 -1
  38. package/lib/plugins/service-betterportal-config-manager/cpBootstrap.d.ts.map +1 -1
  39. package/lib/plugins/service-betterportal-config-manager/cpBootstrap.js.map +1 -1
  40. package/lib/plugins/service-betterportal-config-manager/index.js +2 -2
  41. package/lib/plugins/service-betterportal-config-manager/index.js.map +1 -1
  42. package/lib/plugins/service-betterportal-config-manager/setupTokens.d.ts.map +1 -1
  43. package/lib/plugins/service-betterportal-config-manager/setupTokens.js +9 -2
  44. package/lib/plugins/service-betterportal-config-manager/setupTokens.js.map +1 -1
  45. package/lib/plugins/service-betterportal-config-manager/storage/core.d.ts +9 -0
  46. package/lib/plugins/service-betterportal-config-manager/storage/core.d.ts.map +1 -1
  47. package/lib/plugins/service-betterportal-config-manager/storage/core.js +15 -0
  48. package/lib/plugins/service-betterportal-config-manager/storage/core.js.map +1 -1
  49. package/lib/plugins/service-betterportal-config-manager/storage/index.d.ts.map +1 -1
  50. package/lib/plugins/service-betterportal-config-manager/storage/index.js +2 -2
  51. package/lib/plugins/service-betterportal-config-manager/storage/index.js.map +1 -1
  52. package/lib/plugins/service-betterportal-config-manager/syncApi.d.ts +7 -7
  53. package/lib/plugins/service-betterportal-config-manager/syncApi.d.ts.map +1 -1
  54. package/lib/plugins/service-betterportal-config-manager/syncApi.js +25 -12
  55. package/lib/plugins/service-betterportal-config-manager/syncApi.js.map +1 -1
  56. package/lib/schemas/service-betterportal-config-manager.json +1 -1
  57. package/lib/schemas/service-betterportal-config-manager.plugin.json +1 -1
  58. 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 10.1.62
4
+ * @version 10.1.63
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 10.1.62
4
+ * @version 10.1.63
5
5
  */
6
6
  import { ServiceClient, bsb, createBroadcastEvent, createEventSchemas } from "@bsb/base";
7
7
  const _platformConfigChangedSchema = bsb.object({
@@ -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": "10.1.62",
7
+ "version": "10.1.63",
8
8
  "category": "service",
9
9
  "deploymentModes": [
10
10
  "self-hosted"
@@ -1402,7 +1402,8 @@
1402
1402
  "inner": {
1403
1403
  "kind": "record",
1404
1404
  "valueSchema": {
1405
- "kind": "any"
1405
+ "kind": "ref",
1406
+ "ref": "#/definitions/BetterPortalJsonValue"
1406
1407
  }
1407
1408
  }
1408
1409
  },
@@ -1468,7 +1469,39 @@
1468
1469
  ],
1469
1470
  "unknownKeys": "strip"
1470
1471
  },
1471
- "definitions": {},
1472
+ "definitions": {
1473
+ "BetterPortalJsonValue": {
1474
+ "kind": "union",
1475
+ "variants": [
1476
+ {
1477
+ "kind": "null"
1478
+ },
1479
+ {
1480
+ "kind": "bool"
1481
+ },
1482
+ {
1483
+ "kind": "string"
1484
+ },
1485
+ {
1486
+ "kind": "number"
1487
+ },
1488
+ {
1489
+ "kind": "array",
1490
+ "items": {
1491
+ "kind": "ref",
1492
+ "ref": "#/definitions/BetterPortalJsonValue"
1493
+ }
1494
+ },
1495
+ {
1496
+ "kind": "record",
1497
+ "valueSchema": {
1498
+ "kind": "ref",
1499
+ "ref": "#/definitions/BetterPortalJsonValue"
1500
+ }
1501
+ }
1502
+ ]
1503
+ }
1504
+ },
1472
1505
  "extensions": {}
1473
1506
  },
1474
1507
  "metadataResponseSchema": {},
@@ -28,7 +28,7 @@ declare function automationServiceCatalog(config: BetterPortalConfig, appDef: Be
28
28
  title: string;
29
29
  description: string;
30
30
  scope: "tenant" | "app";
31
- visibility: "secret" | "public" | "protected";
31
+ visibility: "public" | "protected" | "secret";
32
32
  ownership: "bp" | "plugin" | "mixed";
33
33
  sourceOfTruth: "bp" | "plugin" | "external";
34
34
  required: boolean;
@@ -36,7 +36,7 @@ declare function automationServiceCatalog(config: BetterPortalConfig, appDef: Be
36
36
  order?: number | undefined;
37
37
  defaultValue?: JsonValue | undefined;
38
38
  ui?: {
39
- control?: "number" | "email" | "text" | "url" | "date" | "checkbox" | "password" | "textarea" | "select" | "multiselect" | "color" | "time" | "datetime-local" | undefined;
39
+ control?: "number" | "email" | "text" | "url" | "date" | "textarea" | "password" | "checkbox" | "select" | "multiselect" | "color" | "time" | "datetime-local" | undefined;
40
40
  placeholder?: string | undefined;
41
41
  options?: {
42
42
  value: string;
@@ -63,8 +63,29 @@ declare function automationServiceCatalog(config: BetterPortalConfig, appDef: Be
63
63
  payloadSchema: import("@betterportal/framework").JsonObject;
64
64
  description?: string | undefined;
65
65
  }[];
66
- apiContracts: JsonValue[];
67
- m2mRequests: JsonValue[];
66
+ apiContracts: {
67
+ id: string;
68
+ title: string;
69
+ version: string;
70
+ viewId: string;
71
+ methods: ("GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS")[];
72
+ capabilities: string[];
73
+ permissions: string[];
74
+ modes: ("service" | "delegated")[];
75
+ description?: string | undefined;
76
+ }[];
77
+ m2mRequests: {
78
+ id: string;
79
+ title: string;
80
+ contractId: string;
81
+ requiredCapabilities: string[];
82
+ methods: ("GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS")[];
83
+ permissions: string[];
84
+ mode: "service" | "delegated";
85
+ optional: boolean;
86
+ description?: string | undefined;
87
+ version?: string | undefined;
88
+ }[];
68
89
  developerResources: {
69
90
  url: string;
70
91
  id: string;
@@ -97,8 +118,29 @@ declare function automationServiceCatalog(config: BetterPortalConfig, appDef: Be
97
118
  dependencies: string[];
98
119
  schemas: Record<string, JsonValue> | undefined;
99
120
  raw: boolean;
100
- apiContracts: JsonValue[];
101
- demoScenarios: JsonValue[];
121
+ apiContracts: {
122
+ id: string;
123
+ title: string;
124
+ version: string;
125
+ viewId: string;
126
+ methods: ("GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS")[];
127
+ capabilities: string[];
128
+ permissions: string[];
129
+ modes: ("service" | "delegated")[];
130
+ description?: string | undefined;
131
+ }[];
132
+ demoScenarios: {
133
+ id: string;
134
+ title: string;
135
+ response: JsonValue;
136
+ description?: string | undefined;
137
+ match?: {
138
+ query?: import("@betterportal/framework").JsonObject | undefined;
139
+ params?: import("@betterportal/framework").JsonObject | undefined;
140
+ headers?: Record<string, string> | undefined;
141
+ request?: import("@betterportal/framework").JsonObject | undefined;
142
+ } | undefined;
143
+ }[];
102
144
  }[];
103
145
  id: string;
104
146
  serviceId: string;
@@ -119,7 +161,7 @@ declare function automationServiceCatalog(config: BetterPortalConfig, appDef: Be
119
161
  title: string;
120
162
  description: string;
121
163
  scope: "tenant" | "app";
122
- visibility: "secret" | "public" | "protected";
164
+ visibility: "public" | "protected" | "secret";
123
165
  ownership: "bp" | "plugin" | "mixed";
124
166
  sourceOfTruth: "bp" | "plugin" | "external";
125
167
  required: boolean;
@@ -127,7 +169,7 @@ declare function automationServiceCatalog(config: BetterPortalConfig, appDef: Be
127
169
  order?: number | undefined;
128
170
  defaultValue?: JsonValue | undefined;
129
171
  ui?: {
130
- control?: "number" | "email" | "text" | "url" | "date" | "checkbox" | "password" | "textarea" | "select" | "multiselect" | "color" | "time" | "datetime-local" | undefined;
172
+ control?: "number" | "email" | "text" | "url" | "date" | "textarea" | "password" | "checkbox" | "select" | "multiselect" | "color" | "time" | "datetime-local" | undefined;
131
173
  placeholder?: string | undefined;
132
174
  options?: {
133
175
  value: string;
@@ -154,8 +196,29 @@ declare function automationServiceCatalog(config: BetterPortalConfig, appDef: Be
154
196
  payloadSchema: import("@betterportal/framework").JsonObject;
155
197
  description?: string | undefined;
156
198
  }[];
157
- apiContracts: JsonValue[];
158
- m2mRequests: JsonValue[];
199
+ apiContracts: {
200
+ id: string;
201
+ title: string;
202
+ version: string;
203
+ viewId: string;
204
+ methods: ("GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS")[];
205
+ capabilities: string[];
206
+ permissions: string[];
207
+ modes: ("service" | "delegated")[];
208
+ description?: string | undefined;
209
+ }[];
210
+ m2mRequests: {
211
+ id: string;
212
+ title: string;
213
+ contractId: string;
214
+ requiredCapabilities: string[];
215
+ methods: ("GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS")[];
216
+ permissions: string[];
217
+ mode: "service" | "delegated";
218
+ optional: boolean;
219
+ description?: string | undefined;
220
+ version?: string | undefined;
221
+ }[];
159
222
  developerResources: {
160
223
  url: string;
161
224
  id: string;
@@ -188,8 +251,29 @@ declare function automationServiceCatalog(config: BetterPortalConfig, appDef: Be
188
251
  dependencies: string[];
189
252
  schemas: Record<string, JsonValue> | undefined;
190
253
  raw: boolean;
191
- apiContracts: JsonValue[];
192
- demoScenarios: JsonValue[];
254
+ apiContracts: {
255
+ id: string;
256
+ title: string;
257
+ version: string;
258
+ viewId: string;
259
+ methods: ("GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS")[];
260
+ capabilities: string[];
261
+ permissions: string[];
262
+ modes: ("service" | "delegated")[];
263
+ description?: string | undefined;
264
+ }[];
265
+ demoScenarios: {
266
+ id: string;
267
+ title: string;
268
+ response: JsonValue;
269
+ description?: string | undefined;
270
+ match?: {
271
+ query?: import("@betterportal/framework").JsonObject | undefined;
272
+ params?: import("@betterportal/framework").JsonObject | undefined;
273
+ headers?: Record<string, string> | undefined;
274
+ request?: import("@betterportal/framework").JsonObject | undefined;
275
+ } | undefined;
276
+ }[];
193
277
  }[];
194
278
  id: string;
195
279
  serviceId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"adminApi.d.ts","sourceRoot":"","sources":["../../../src/plugins/service-betterportal-config-manager/adminApi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAEjB,mBAAmB,EACnB,SAAS,EACV,MAAM,yBAAyB,CAAC;AAYjC,OAAO,KAAK,EAAuE,kBAAkB,EAAE,eAAe,EAA0C,MAAM,yBAAyB,CAAC;AAChM,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAqQzD,iBAAS,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkEpF;AAGD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,wBAAwB,CAAC,GAAG,MAAM,CA4CpG;AAwVD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG;IACvG,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CACzB,CAwEA;AAiPD,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE,gBAAgB,GACxB,IAAI,CAyhDN;AA8VD,wBAAgB,uBAAuB,CAAC,CAAC,EAAE;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD,GAAG,MAAM,CA0aT"}
1
+ {"version":3,"file":"adminApi.d.ts","sourceRoot":"","sources":["../../../src/plugins/service-betterportal-config-manager/adminApi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAEjB,mBAAmB,EACnB,SAAS,EACV,MAAM,yBAAyB,CAAC;AAajC,OAAO,KAAK,EAAuE,kBAAkB,EAAE,eAAe,EAAgE,MAAM,yBAAyB,CAAC;AACtN,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAmRzD,iBAAS,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkEpF;AAGD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,wBAAwB,CAAC,GAAG,MAAM,CA4CpG;AAwVD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG;IACvG,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CACzB,CAwEA;AAiPD,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE,gBAAgB,GACxB,IAAI,CAghDN;AA8VD,wBAAgB,uBAAuB,CAAC,CAAC,EAAE;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD,GAAG,MAAM,CA0aT"}
@@ -1,5 +1,5 @@
1
1
  import * as av from "anyvali";
2
- import { AppAuthRoleSchema, eventHeaders, htmlResponse, jsonResponse, resolveEmbeddedRequestContext, signServiceConfigTicket, uuidv7, BetterPortalThemeConfigSchema } from "@betterportal/framework";
2
+ import { AppAuthRoleSchema, eventHeaders, htmlResponse, jsonResponse, resolveEmbeddedRequestContext, signServiceConfigTicket, uuidv7, BetterPortalMenuItemSchema, BetterPortalThemeConfigSchema } from "@betterportal/framework";
3
3
  import { generateApiKey, hashApiKey } from "./storage/index.js";
4
4
  import { getManifestCache } from "./syncApi.js";
5
5
  import { apiRoutePath, appRoutePatternKey, isApiRoute, pageRoutePath } from "./routeMounts.js";
@@ -90,6 +90,19 @@ function requiredRouteString(body, key, label) {
90
90
  return { error: `${label} is required.` };
91
91
  return { value };
92
92
  }
93
+ function normalizeMenuItem(raw) {
94
+ const item = raw && typeof raw === "object" ? raw : {};
95
+ return BetterPortalMenuItemSchema.parse({
96
+ id: typeof item.id === "string" ? item.id : uuidv7(),
97
+ type: item.type === "group" ? "group" : "link",
98
+ title: typeof item.title === "string" ? item.title : undefined,
99
+ icon: typeof item.icon === "string" ? item.icon : undefined,
100
+ routeId: typeof item.routeId === "string" ? item.routeId : undefined,
101
+ href: typeof item.href === "string" ? item.href : undefined,
102
+ enabled: item.enabled !== false,
103
+ children: Array.isArray(item.children) ? item.children.map(normalizeMenuItem) : []
104
+ });
105
+ }
93
106
  function routesReloadPath(appId, apiServiceId) {
94
107
  return `/routes?appId=${encodeURIComponent(appId)}${apiServiceId ? `&apiServiceId=${encodeURIComponent(apiServiceId)}` : ""}`;
95
108
  }
@@ -1536,16 +1549,16 @@ export function registerAdminApiRoutes(app, store, cpState) {
1536
1549
  type: av.literal("auth"),
1537
1550
  mutation: av.object({
1538
1551
  roles: av.array(AppAuthRoleSchema)
1539
- }, { unknownKeys: "strip" })
1540
- }, { unknownKeys: "strip" }),
1552
+ })
1553
+ }),
1541
1554
  av.object({
1542
1555
  tenantId: av.string().minLength(1),
1543
1556
  appId: av.string().minLength(1),
1544
1557
  type: av.literal("theme"),
1545
1558
  mutation: av.object({
1546
1559
  themeConfig: BetterPortalThemeConfigSchema
1547
- }, { unknownKeys: "strip" })
1548
- }, { unknownKeys: "strip" })
1560
+ })
1561
+ })
1549
1562
  ]);
1550
1563
  const getAppOr404 = async (appId) => {
1551
1564
  const config = await store.loadConfig();
@@ -2131,19 +2144,7 @@ export function registerAdminApiRoutes(app, store, cpState) {
2131
2144
  const appDef = config.apps.find((a) => a.id === appId);
2132
2145
  if (!appDef)
2133
2146
  return jsonResponse({ error: "App not found" }, 404);
2134
- appDef.menu = items.map((raw) => {
2135
- const item = raw && typeof raw === "object" ? raw : {};
2136
- return {
2137
- id: typeof item.id === "string" ? item.id : uuidv7(),
2138
- type: item.type === "group" ? "group" : "link",
2139
- title: typeof item.title === "string" ? item.title : undefined,
2140
- icon: typeof item.icon === "string" ? item.icon : undefined,
2141
- routeId: typeof item.routeId === "string" ? item.routeId : undefined,
2142
- href: typeof item.href === "string" ? item.href : undefined,
2143
- enabled: item.enabled !== false,
2144
- children: Array.isArray(item.children) ? item.children : []
2145
- };
2146
- });
2147
+ appDef.menu = items.map(normalizeMenuItem);
2147
2148
  await store.saveConfig(config);
2148
2149
  return jsonResponse({ ok: true });
2149
2150
  });
@@ -2294,20 +2295,23 @@ export function registerAdminApiRoutes(app, store, cpState) {
2294
2295
  type: "link",
2295
2296
  title: routeTitle,
2296
2297
  routeId,
2297
- enabled: true
2298
+ enabled: true,
2299
+ serviceStatus: "show",
2300
+ authStatus: "show",
2301
+ children: []
2298
2302
  });
2299
2303
  }
2300
2304
  }
2301
2305
  if (groupChildren.length > 0) {
2302
- const menu = (appDef.menu ?? []);
2303
- menu.push({
2306
+ appDef.menu.push({
2304
2307
  id: groupId,
2305
2308
  type: "group",
2306
2309
  title,
2307
2310
  enabled: true,
2311
+ serviceStatus: "show",
2312
+ authStatus: "show",
2308
2313
  children: groupChildren
2309
2314
  });
2310
- appDef.menu = menu;
2311
2315
  }
2312
2316
  }
2313
2317
  }