@objectstack/runtime 4.0.3 → 4.0.4

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @objectstack/runtime@4.0.3 build /home/runner/work/framework/framework/packages/runtime
2
+ > @objectstack/runtime@4.0.4 build /home/runner/work/framework/framework/packages/runtime
3
3
  > tsup --config ../../tsup.config.ts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -10,13 +10,13 @@
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
12
  CJS Build start
13
- ESM dist/index.js 98.02 KB
14
- ESM dist/index.js.map 212.66 KB
15
- ESM ⚡️ Build success in 153ms
16
- CJS dist/index.cjs 100.63 KB
17
- CJS dist/index.cjs.map 212.72 KB
18
- CJS ⚡️ Build success in 153ms
13
+ CJS dist/index.cjs 97.58 KB
14
+ CJS dist/index.cjs.map 206.05 KB
15
+ CJS ⚡️ Build success in 196ms
16
+ ESM dist/index.js 94.96 KB
17
+ ESM dist/index.js.map 205.98 KB
18
+ ESM ⚡️ Build success in 200ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 3771ms
21
- DTS dist/index.d.ts 26.00 KB
22
- DTS dist/index.d.cts 26.00 KB
20
+ DTS ⚡️ Build success in 3990ms
21
+ DTS dist/index.d.ts 25.96 KB
22
+ DTS dist/index.d.cts 25.96 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @objectstack/runtime
2
2
 
3
+ ## 4.0.4
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [326b66b]
8
+ - @objectstack/spec@4.0.4
9
+ - @objectstack/core@4.0.4
10
+ - @objectstack/rest@4.0.4
11
+ - @objectstack/types@4.0.4
12
+
3
13
  ## 4.0.3
4
14
 
5
15
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -665,6 +665,13 @@ var AppPlugin = class {
665
665
  return;
666
666
  }
667
667
  ctx.logger.debug("Retrieved ObjectQL engine service", { appId });
668
+ if (this.bundle.datasourceMapping && Array.isArray(this.bundle.datasourceMapping)) {
669
+ ctx.logger.info("Configuring datasource mapping rules", {
670
+ appId,
671
+ ruleCount: this.bundle.datasourceMapping.length
672
+ });
673
+ ql.setDatasourceMapping(this.bundle.datasourceMapping);
674
+ }
668
675
  const runtime = this.bundle.default || this.bundle;
669
676
  if (runtime && typeof runtime.onEnable === "function") {
670
677
  ctx.logger.info("Executing runtime.onEnable", {
@@ -840,7 +847,7 @@ function randomUUID() {
840
847
  });
841
848
  }
842
849
  var HttpDispatcher = class {
843
- // Casting to any to access dynamic props like broker, services, graphql
850
+ // Casting to any to access dynamic props like services, graphql
844
851
  constructor(kernel) {
845
852
  this.kernel = kernel;
846
853
  }
@@ -874,11 +881,73 @@ var HttpDispatcher = class {
874
881
  }
875
882
  };
876
883
  }
877
- ensureBroker() {
878
- if (!this.kernel.broker) {
879
- throw { statusCode: 500, message: "Kernel Broker not available" };
880
- }
881
- return this.kernel.broker;
884
+ /**
885
+ * Direct data service dispatch — replaces broker.call('data.*').
886
+ * Tries protocol service first (supports expand/populate), falls back to ObjectQL.
887
+ */
888
+ async callData(action, params) {
889
+ const protocol = await this.resolveService("protocol");
890
+ const qlService = await this.getObjectQLService();
891
+ const ql = qlService ?? await this.resolveService("objectql");
892
+ if (action === "create") {
893
+ if (ql) {
894
+ const res = await ql.insert(params.object, params.data);
895
+ const record = { ...params.data, ...res };
896
+ return { object: params.object, id: record.id, record };
897
+ }
898
+ throw { statusCode: 503, message: "Data service not available" };
899
+ }
900
+ if (action === "get") {
901
+ if (protocol && typeof protocol.getData === "function") {
902
+ return await protocol.getData({ object: params.object, id: params.id, expand: params.expand, select: params.select });
903
+ }
904
+ if (ql) {
905
+ let all = await ql.find(params.object);
906
+ if (!all) all = [];
907
+ const match = all.find((i) => i.id === params.id);
908
+ return match ? { object: params.object, id: params.id, record: match } : null;
909
+ }
910
+ throw { statusCode: 503, message: "Data service not available" };
911
+ }
912
+ if (action === "update") {
913
+ if (ql && params.id) {
914
+ let all = await ql.find(params.object);
915
+ if (all && all.value) all = all.value;
916
+ if (!all) all = [];
917
+ const existing = all.find((i) => i.id === params.id);
918
+ if (!existing) throw new Error("[ObjectStack] Not Found");
919
+ await ql.update(params.object, params.data, { where: { id: params.id } });
920
+ return { object: params.object, id: params.id, record: { ...existing, ...params.data } };
921
+ }
922
+ throw { statusCode: 503, message: "Data service not available" };
923
+ }
924
+ if (action === "delete") {
925
+ if (ql) {
926
+ await ql.delete(params.object, { where: { id: params.id } });
927
+ return { object: params.object, id: params.id, deleted: true };
928
+ }
929
+ throw { statusCode: 503, message: "Data service not available" };
930
+ }
931
+ if (action === "query" || action === "find") {
932
+ if (protocol && typeof protocol.findData === "function") {
933
+ const query = params.query || (() => {
934
+ const { object, ...rest } = params;
935
+ return rest;
936
+ })();
937
+ return await protocol.findData({ object: params.object, query });
938
+ }
939
+ if (ql) {
940
+ let all = await ql.find(params.object);
941
+ if (!Array.isArray(all) && all && all.value) all = all.value;
942
+ if (!all) all = [];
943
+ return { object: params.object, records: all, total: all.length };
944
+ }
945
+ throw { statusCode: 503, message: "Data service not available" };
946
+ }
947
+ if (action === "batch") {
948
+ return { object: params.object, results: [] };
949
+ }
950
+ throw { statusCode: 400, message: `Unknown data action: ${action}` };
882
951
  }
883
952
  /**
884
953
  * Generates the discovery JSON response for the API root.
@@ -1042,18 +1111,6 @@ var HttpDispatcher = class {
1042
1111
  return { handled: true, result: response };
1043
1112
  }
1044
1113
  const normalizedPath = path.replace(/^\/+/, "");
1045
- if (normalizedPath === "login" && method.toUpperCase() === "POST") {
1046
- try {
1047
- const broker = this.ensureBroker();
1048
- const data = await broker.call("auth.login", body, { request: context.request });
1049
- return { handled: true, response: { status: 200, body: data } };
1050
- } catch (error) {
1051
- const statusCode = error?.statusCode ?? error?.status;
1052
- if (statusCode !== 500 || !error?.message?.includes("Broker not available")) {
1053
- throw error;
1054
- }
1055
- }
1056
- }
1057
1114
  return this.mockAuthFallback(normalizedPath, method, body);
1058
1115
  }
1059
1116
  /**
@@ -1109,70 +1166,23 @@ var HttpDispatcher = class {
1109
1166
  * Standard: /metadata/:type/:name
1110
1167
  * Fallback for backward compat: /metadata (all objects), /metadata/:objectName (get object)
1111
1168
  */
1112
- async handleMetadata(path, context, method, body, query) {
1113
- const broker = this.kernel.broker ?? null;
1169
+ async handleMetadata(path, _context, method, body, query) {
1114
1170
  const parts = path.replace(/^\/+/, "").split("/").filter(Boolean);
1115
1171
  if (parts[0] === "types") {
1116
- console.log("[HttpDispatcher] Attempting to resolve MetadataService...");
1117
- console.log("[HttpDispatcher] Available kernel methods:", {
1118
- hasGetServiceAsync: typeof this.kernel.getServiceAsync === "function",
1119
- hasGetService: typeof this.kernel.getService === "function",
1120
- hasContext: !!this.kernel.context,
1121
- hasContextGetService: typeof this.kernel.context?.getService === "function"
1122
- });
1123
- let metadataService = null;
1124
- if (typeof this.kernel.getServiceAsync === "function") {
1125
- try {
1126
- metadataService = await this.kernel.getServiceAsync("metadata");
1127
- console.log('[HttpDispatcher] kernel.getServiceAsync("metadata") returned:', !!metadataService);
1128
- } catch (e) {
1129
- console.log('[HttpDispatcher] kernel.getServiceAsync("metadata") failed:', e.message);
1130
- }
1131
- }
1132
- if (!metadataService && typeof this.kernel.getService === "function") {
1133
- try {
1134
- metadataService = await this.kernel.getService("metadata");
1135
- console.log('[HttpDispatcher] kernel.getService("metadata") returned:', !!metadataService);
1136
- } catch (e) {
1137
- console.log('[HttpDispatcher] kernel.getService("metadata") failed:', e.message);
1138
- }
1139
- }
1140
- if (!metadataService && this.kernel.context?.getService) {
1141
- try {
1142
- metadataService = await this.kernel.context.getService("metadata");
1143
- console.log('[HttpDispatcher] kernel.context.getService("metadata") returned:', !!metadataService);
1144
- } catch (e) {
1145
- console.log('[HttpDispatcher] kernel.context.getService("metadata") failed:', e.message);
1146
- }
1147
- }
1148
- console.log("[HttpDispatcher] Final metadataService:", !!metadataService, "has getRegisteredTypes:", typeof metadataService?.getRegisteredTypes);
1172
+ const metadataService = await this.resolveService("metadata");
1149
1173
  if (metadataService && typeof metadataService.getRegisteredTypes === "function") {
1150
1174
  try {
1151
1175
  const types = await metadataService.getRegisteredTypes();
1152
- console.log("[HttpDispatcher] MetadataService.getRegisteredTypes() returned:", types);
1153
1176
  return { handled: true, response: this.success({ types }) };
1154
1177
  } catch (e) {
1155
- console.warn("[HttpDispatcher] MetadataService.getRegisteredTypes() failed:", e.message, e.stack);
1178
+ console.warn("[HttpDispatcher] MetadataService.getRegisteredTypes() failed:", e.message);
1156
1179
  }
1157
- } else {
1158
- console.log("[HttpDispatcher] MetadataService not available or missing getRegisteredTypes, falling back to protocol service");
1159
1180
  }
1160
1181
  const protocol = await this.resolveService("protocol");
1161
1182
  if (protocol && typeof protocol.getMetaTypes === "function") {
1162
1183
  const result = await protocol.getMetaTypes({});
1163
- console.log("[HttpDispatcher] Protocol service returned types:", result);
1164
1184
  return { handled: true, response: this.success(result) };
1165
1185
  }
1166
- if (broker) {
1167
- try {
1168
- const data = await broker.call("metadata.types", {}, { request: context.request });
1169
- console.log("[HttpDispatcher] Broker returned types:", data);
1170
- return { handled: true, response: this.success(data) };
1171
- } catch (e) {
1172
- console.log("[HttpDispatcher] Broker call failed:", e);
1173
- }
1174
- }
1175
- console.warn("[HttpDispatcher] Falling back to hardcoded defaults for metadata types");
1176
1186
  return { handled: true, response: this.success({ types: ["object", "app", "plugin"] }) };
1177
1187
  }
1178
1188
  if (parts.length === 3 && parts[2] === "published" && (!method || method === "GET")) {
@@ -1183,12 +1193,12 @@ var HttpDispatcher = class {
1183
1193
  if (data === void 0) return { handled: true, response: this.error("Not found", 404) };
1184
1194
  return { handled: true, response: this.success(data) };
1185
1195
  }
1186
- if (broker) {
1196
+ const metaSvc = await this.resolveService("metadata");
1197
+ if (metaSvc && typeof metaSvc.getPublished === "function") {
1187
1198
  try {
1188
- const data = await broker.call("metadata.getPublished", { type, name }, { request: context.request });
1189
- return { handled: true, response: this.success(data) };
1190
- } catch (e) {
1191
- return { handled: true, response: this.error(e.message, 404) };
1199
+ const fallbackData = await metaSvc.getPublished(type, name);
1200
+ if (fallbackData !== void 0) return { handled: true, response: this.success(fallbackData) };
1201
+ } catch {
1192
1202
  }
1193
1203
  }
1194
1204
  return { handled: true, response: this.error("Not found", 404) };
@@ -1206,9 +1216,10 @@ var HttpDispatcher = class {
1206
1216
  return { handled: true, response: this.error(e.message, 400) };
1207
1217
  }
1208
1218
  }
1209
- if (broker) {
1219
+ const metaSvc = await this.resolveService("metadata");
1220
+ if (metaSvc && typeof metaSvc.saveItem === "function") {
1210
1221
  try {
1211
- const data = await broker.call("metadata.saveItem", { type, name, item: body }, { request: context.request });
1222
+ const data = await metaSvc.saveItem(type, name, body);
1212
1223
  return { handled: true, response: this.success(data) };
1213
1224
  } catch (e) {
1214
1225
  return { handled: true, response: this.error(e.message || "Save not supported", 501) };
@@ -1218,10 +1229,6 @@ var HttpDispatcher = class {
1218
1229
  }
1219
1230
  try {
1220
1231
  if (type === "objects" || type === "object") {
1221
- if (broker) {
1222
- const data = await broker.call("metadata.getObject", { objectName: name }, { request: context.request });
1223
- return { handled: true, response: this.success(data) };
1224
- }
1225
1232
  const qlService = await this.getObjectQLService();
1226
1233
  if (qlService?.registry) {
1227
1234
  const data = qlService.registry.getObject(name);
@@ -1238,10 +1245,13 @@ var HttpDispatcher = class {
1238
1245
  } catch (e) {
1239
1246
  }
1240
1247
  }
1241
- if (broker) {
1242
- const method2 = `metadata.get${this.capitalize(singularType)}`;
1243
- const data = await broker.call(method2, { name }, { request: context.request });
1244
- return { handled: true, response: this.success(data) };
1248
+ const metaSvc = await this.resolveService("metadata");
1249
+ if (metaSvc && typeof metaSvc.getItem === "function") {
1250
+ try {
1251
+ const data = await metaSvc.getItem(singularType, name);
1252
+ if (data) return { handled: true, response: this.success(data) };
1253
+ } catch {
1254
+ }
1245
1255
  }
1246
1256
  return { handled: true, response: this.error("Not found", 404) };
1247
1257
  } catch (e) {
@@ -1264,7 +1274,10 @@ var HttpDispatcher = class {
1264
1274
  const metadataService = await this.getService(import_system.CoreServiceName.enum.metadata);
1265
1275
  if (metadataService && typeof metadataService.list === "function") {
1266
1276
  try {
1267
- const items = await metadataService.list(typeOrName);
1277
+ let items = await metadataService.list(typeOrName);
1278
+ if (packageId && items && items.length > 0) {
1279
+ items = items.filter((item) => item?._packageId === packageId);
1280
+ }
1268
1281
  if (items && items.length > 0) {
1269
1282
  return { handled: true, response: this.success({ type: typeOrName, items }) };
1270
1283
  }
@@ -1273,25 +1286,6 @@ var HttpDispatcher = class {
1273
1286
  console.debug(`[HttpDispatcher] MetadataService.list() failed for type:`, sanitizedType, "error:", e.message);
1274
1287
  }
1275
1288
  }
1276
- if (broker) {
1277
- try {
1278
- if (typeOrName === "objects") {
1279
- const data2 = await broker.call("metadata.objects", { packageId }, { request: context.request });
1280
- return { handled: true, response: this.success(data2) };
1281
- }
1282
- const data = await broker.call(`metadata.${typeOrName}`, { packageId }, { request: context.request });
1283
- if (data !== null && data !== void 0) {
1284
- return { handled: true, response: this.success(data) };
1285
- }
1286
- } catch {
1287
- }
1288
- try {
1289
- const data = await broker.call("metadata.getObject", { objectName: typeOrName }, { request: context.request });
1290
- return { handled: true, response: this.success(data) };
1291
- } catch (e) {
1292
- return { handled: true, response: this.error(e.message, 404) };
1293
- }
1294
- }
1295
1289
  const qlService = await this.getObjectQLService();
1296
1290
  if (qlService?.registry) {
1297
1291
  if (typeOrName === "objects") {
@@ -1308,18 +1302,19 @@ var HttpDispatcher = class {
1308
1302
  return { handled: true, response: this.error("Not found", 404) };
1309
1303
  }
1310
1304
  if (parts.length === 0) {
1305
+ const metadataService = await this.resolveService("metadata");
1306
+ if (metadataService && typeof metadataService.getRegisteredTypes === "function") {
1307
+ try {
1308
+ const types = await metadataService.getRegisteredTypes();
1309
+ return { handled: true, response: this.success({ types }) };
1310
+ } catch {
1311
+ }
1312
+ }
1311
1313
  const protocol = await this.resolveService("protocol");
1312
1314
  if (protocol && typeof protocol.getMetaTypes === "function") {
1313
1315
  const result = await protocol.getMetaTypes({});
1314
1316
  return { handled: true, response: this.success(result) };
1315
1317
  }
1316
- if (broker) {
1317
- try {
1318
- const data = await broker.call("metadata.types", {}, { request: context.request });
1319
- return { handled: true, response: this.success(data) };
1320
- } catch {
1321
- }
1322
- }
1323
1318
  return { handled: true, response: this.success({ types: ["object", "app", "plugin"] }) };
1324
1319
  }
1325
1320
  return { handled: false };
@@ -1328,8 +1323,7 @@ var HttpDispatcher = class {
1328
1323
  * Handles Data requests
1329
1324
  * path: sub-path after /data/ (e.g. "contacts", "contacts/123", "contacts/query")
1330
1325
  */
1331
- async handleData(path, method, body, query, context) {
1332
- const broker = this.ensureBroker();
1326
+ async handleData(path, method, body, query, _context) {
1333
1327
  const parts = path.replace(/^\/+/, "").split("/");
1334
1328
  const objectName = parts[0];
1335
1329
  if (!objectName) {
@@ -1339,11 +1333,11 @@ var HttpDispatcher = class {
1339
1333
  if (parts.length > 1) {
1340
1334
  const action = parts[1];
1341
1335
  if (action === "query" && m === "POST") {
1342
- const result = await broker.call("data.query", { object: objectName, ...body }, { request: context.request });
1336
+ const result = await this.callData("query", { object: objectName, ...body });
1343
1337
  return { handled: true, response: this.success(result) };
1344
1338
  }
1345
1339
  if (action === "batch" && m === "POST") {
1346
- const result = await broker.call("data.batch", { object: objectName, ...body }, { request: context.request });
1340
+ const result = await this.callData("batch", { object: objectName, ...body });
1347
1341
  return { handled: true, response: this.success(result) };
1348
1342
  }
1349
1343
  if (parts.length === 2 && m === "GET") {
@@ -1352,17 +1346,17 @@ var HttpDispatcher = class {
1352
1346
  const allowedParams = {};
1353
1347
  if (select != null) allowedParams.select = select;
1354
1348
  if (expand != null) allowedParams.expand = expand;
1355
- const result = await broker.call("data.get", { object: objectName, id, ...allowedParams }, { request: context.request });
1349
+ const result = await this.callData("get", { object: objectName, id, ...allowedParams });
1356
1350
  return { handled: true, response: this.success(result) };
1357
1351
  }
1358
1352
  if (parts.length === 2 && m === "PATCH") {
1359
1353
  const id = parts[1];
1360
- const result = await broker.call("data.update", { object: objectName, id, data: body }, { request: context.request });
1354
+ const result = await this.callData("update", { object: objectName, id, data: body });
1361
1355
  return { handled: true, response: this.success(result) };
1362
1356
  }
1363
1357
  if (parts.length === 2 && m === "DELETE") {
1364
1358
  const id = parts[1];
1365
- const result = await broker.call("data.delete", { object: objectName, id }, { request: context.request });
1359
+ const result = await this.callData("delete", { object: objectName, id });
1366
1360
  return { handled: true, response: this.success(result) };
1367
1361
  }
1368
1362
  } else {
@@ -1389,11 +1383,11 @@ var HttpDispatcher = class {
1389
1383
  normalized.offset = normalized.skip;
1390
1384
  delete normalized.skip;
1391
1385
  }
1392
- const result = await broker.call("data.query", { object: objectName, query: normalized }, { request: context.request });
1386
+ const result = await this.callData("query", { object: objectName, query: normalized });
1393
1387
  return { handled: true, response: this.success(result) };
1394
1388
  }
1395
1389
  if (m === "POST") {
1396
- const result = await broker.call("data.create", { object: objectName, data: body }, { request: context.request });
1390
+ const result = await this.callData("create", { object: objectName, data: body });
1397
1391
  const res = this.success(result);
1398
1392
  res.status = 201;
1399
1393
  return { handled: true, response: res };
@@ -1495,18 +1489,14 @@ var HttpDispatcher = class {
1495
1489
  * - POST /packages/:id/publish → publish a package (metadata snapshot)
1496
1490
  * - POST /packages/:id/revert → revert a package to last published state
1497
1491
  *
1498
- * Uses ObjectQL SchemaRegistry directly (via the 'objectql' service)
1499
- * with broker fallback for backward compatibility.
1492
+ * Uses ObjectQL SchemaRegistry directly (via the 'objectql' service).
1500
1493
  */
1501
- async handlePackages(path, method, body, query, context) {
1494
+ async handlePackages(path, method, body, query, _context) {
1502
1495
  const m = method.toUpperCase();
1503
1496
  const parts = path.replace(/^\/+/, "").split("/").filter(Boolean);
1504
1497
  const qlService = await this.getObjectQLService();
1505
1498
  const registry = qlService?.registry;
1506
1499
  if (!registry) {
1507
- if (this.kernel.broker) {
1508
- return this.handlePackagesViaBroker(parts, m, body, query, context);
1509
- }
1510
1500
  return { handled: true, response: this.error("Package service not available", 503) };
1511
1501
  }
1512
1502
  try {
@@ -1545,10 +1535,6 @@ var HttpDispatcher = class {
1545
1535
  const result = await metadataService.publishPackage(id, body || {});
1546
1536
  return { handled: true, response: this.success(result) };
1547
1537
  }
1548
- if (this.kernel.broker) {
1549
- const result = await this.kernel.broker.call("metadata.publishPackage", { packageId: id, ...body }, { request: context.request });
1550
- return { handled: true, response: this.success(result) };
1551
- }
1552
1538
  return { handled: true, response: this.error("Metadata service not available", 503) };
1553
1539
  }
1554
1540
  if (parts.length === 2 && parts[1] === "revert" && m === "POST") {
@@ -1558,10 +1544,6 @@ var HttpDispatcher = class {
1558
1544
  await metadataService.revertPackage(id);
1559
1545
  return { handled: true, response: this.success({ success: true }) };
1560
1546
  }
1561
- if (this.kernel.broker) {
1562
- await this.kernel.broker.call("metadata.revertPackage", { packageId: id }, { request: context.request });
1563
- return { handled: true, response: this.success({ success: true }) };
1564
- }
1565
1547
  return { handled: true, response: this.error("Metadata service not available", 503) };
1566
1548
  }
1567
1549
  if (parts.length === 1 && m === "GET") {
@@ -1581,47 +1563,6 @@ var HttpDispatcher = class {
1581
1563
  }
1582
1564
  return { handled: false };
1583
1565
  }
1584
- /**
1585
- * Fallback: handle packages via broker (for backward compatibility)
1586
- */
1587
- async handlePackagesViaBroker(parts, m, body, query, context) {
1588
- const broker = this.kernel.broker;
1589
- try {
1590
- if (parts.length === 0 && m === "GET") {
1591
- const result = await broker.call("package.list", query || {}, { request: context.request });
1592
- return { handled: true, response: this.success(result) };
1593
- }
1594
- if (parts.length === 0 && m === "POST") {
1595
- const result = await broker.call("package.install", body, { request: context.request });
1596
- const res = this.success(result);
1597
- res.status = 201;
1598
- return { handled: true, response: res };
1599
- }
1600
- if (parts.length === 2 && parts[1] === "enable" && m === "PATCH") {
1601
- const id = decodeURIComponent(parts[0]);
1602
- const result = await broker.call("package.enable", { id }, { request: context.request });
1603
- return { handled: true, response: this.success(result) };
1604
- }
1605
- if (parts.length === 2 && parts[1] === "disable" && m === "PATCH") {
1606
- const id = decodeURIComponent(parts[0]);
1607
- const result = await broker.call("package.disable", { id }, { request: context.request });
1608
- return { handled: true, response: this.success(result) };
1609
- }
1610
- if (parts.length === 1 && m === "GET") {
1611
- const id = decodeURIComponent(parts[0]);
1612
- const result = await broker.call("package.get", { id }, { request: context.request });
1613
- return { handled: true, response: this.success(result) };
1614
- }
1615
- if (parts.length === 1 && m === "DELETE") {
1616
- const id = decodeURIComponent(parts[0]);
1617
- const result = await broker.call("package.uninstall", { id }, { request: context.request });
1618
- return { handled: true, response: this.success(result) };
1619
- }
1620
- } catch (e) {
1621
- return { handled: true, response: this.error(e.message, e.statusCode || 500) };
1622
- }
1623
- return { handled: false };
1624
- }
1625
1566
  /**
1626
1567
  * Handles Storage requests
1627
1568
  * path: sub-path after /storage/
@@ -1830,9 +1771,6 @@ var HttpDispatcher = class {
1830
1771
  }
1831
1772
  return null;
1832
1773
  }
1833
- capitalize(s) {
1834
- return s.charAt(0).toUpperCase() + s.slice(1);
1835
- }
1836
1774
  /**
1837
1775
  * Handle AI service routes (/ai/chat, /ai/models, /ai/conversations, etc.)
1838
1776
  * Resolves the AI service and its built-in route handlers, then dispatches.
@@ -1969,10 +1907,12 @@ var HttpDispatcher = class {
1969
1907
  return this.handleAI(cleanPath, method, body, query, context);
1970
1908
  }
1971
1909
  if (cleanPath === "/openapi.json" && method === "GET") {
1972
- const broker = this.ensureBroker();
1973
1910
  try {
1974
- const result2 = await broker.call("metadata.generateOpenApi", {}, { request: context.request });
1975
- return { handled: true, response: this.success(result2) };
1911
+ const metaSvc = await this.resolveService("metadata");
1912
+ if (metaSvc && typeof metaSvc.generateOpenApi === "function") {
1913
+ const result2 = await metaSvc.generateOpenApi({});
1914
+ return { handled: true, response: this.success(result2) };
1915
+ }
1976
1916
  } catch (e) {
1977
1917
  }
1978
1918
  }
@@ -1987,37 +1927,48 @@ var HttpDispatcher = class {
1987
1927
  * Handles Custom API Endpoints defined in metadata
1988
1928
  */
1989
1929
  async handleApiEndpoint(path, method, body, query, context) {
1990
- const broker = this.ensureBroker();
1991
1930
  try {
1992
- const endpoint = await broker.call("metadata.matchEndpoint", { path, method });
1931
+ const metaSvc = await this.resolveService("metadata");
1932
+ if (!metaSvc || typeof metaSvc.matchEndpoint !== "function") {
1933
+ return { handled: false };
1934
+ }
1935
+ const endpoint = await metaSvc.matchEndpoint({ path, method });
1993
1936
  if (endpoint) {
1994
1937
  if (endpoint.type === "flow") {
1995
- const result = await broker.call("automation.runFlow", {
1938
+ const automationSvc = await this.resolveService("automation");
1939
+ if (!automationSvc || typeof automationSvc.runFlow !== "function") {
1940
+ return { handled: true, response: this.error("Automation service not available", 503) };
1941
+ }
1942
+ const result = await automationSvc.runFlow({
1996
1943
  flowId: endpoint.target,
1997
1944
  inputs: { ...query, ...body, _request: context.request }
1998
1945
  });
1999
1946
  return { handled: true, response: this.success(result) };
2000
1947
  }
2001
1948
  if (endpoint.type === "script") {
2002
- const result = await broker.call("automation.runScript", {
1949
+ const automationSvc = await this.resolveService("automation");
1950
+ if (!automationSvc || typeof automationSvc.runScript !== "function") {
1951
+ return { handled: true, response: this.error("Automation service not available", 503) };
1952
+ }
1953
+ const result = await automationSvc.runScript({
2003
1954
  scriptName: endpoint.target,
2004
1955
  context: { ...query, ...body, request: context.request }
2005
- }, { request: context.request });
1956
+ });
2006
1957
  return { handled: true, response: this.success(result) };
2007
1958
  }
2008
1959
  if (endpoint.type === "object_operation") {
2009
1960
  if (endpoint.objectParams) {
2010
1961
  const { object, operation } = endpoint.objectParams;
2011
1962
  if (operation === "find") {
2012
- const result = await broker.call("data.query", { object, query }, { request: context.request });
1963
+ const result = await this.callData("query", { object, query });
2013
1964
  return { handled: true, response: this.success(result.records, { total: result.total }) };
2014
1965
  }
2015
1966
  if (operation === "get" && query.id) {
2016
- const result = await broker.call("data.get", { object, id: query.id }, { request: context.request });
1967
+ const result = await this.callData("get", { object, id: query.id });
2017
1968
  return { handled: true, response: this.success(result) };
2018
1969
  }
2019
1970
  if (operation === "create") {
2020
- const result = await broker.call("data.create", { object, data: body }, { request: context.request });
1971
+ const result = await this.callData("create", { object, data: body });
2021
1972
  return { handled: true, response: this.success(result) };
2022
1973
  }
2023
1974
  }