@cadenza.io/service 2.3.16 → 2.4.0

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/dist/index.js CHANGED
@@ -329,12 +329,11 @@ var ServiceRegistry = class _ServiceRegistry {
329
329
  deleted
330
330
  } = serviceInstance;
331
331
  if (uuid4 === this.serviceInstanceId) return;
332
- console.log("service instance", serviceName, uuid4, address);
333
332
  if (deleted) {
334
- this.instances.get(serviceName)?.splice(
335
- this.instances.get(serviceName)?.findIndex((i) => i.uuid === uuid4) ?? -1,
336
- 1
337
- );
333
+ const indexToDelete = this.instances.get(serviceName)?.findIndex((i) => i.uuid === uuid4) ?? -1;
334
+ if (indexToDelete >= 0) {
335
+ this.instances.get(serviceName)?.splice(indexToDelete, 1);
336
+ }
338
337
  if (this.instances.get(serviceName)?.length === 0) {
339
338
  this.instances.delete(serviceName);
340
339
  } else if (this.instances.get(serviceName)?.filter((i) => i.address === address && i.port === port).length === 0) {
@@ -377,7 +376,7 @@ var ServiceRegistry = class _ServiceRegistry {
377
376
  communicationTypes
378
377
  });
379
378
  instances?.filter(
380
- (i) => i.address === address && i.port === port && i.clientCreated && i.isActive
379
+ (i) => i.address === address && i.port === port && i.isActive
381
380
  ).forEach((i) => {
382
381
  i.clientCreated = true;
383
382
  });
@@ -409,7 +408,6 @@ var ServiceRegistry = class _ServiceRegistry {
409
408
  this.handleGlobalSignalRegistrationTask = CadenzaService.createMetaTask(
410
409
  "Handle global Signal Registration",
411
410
  (ctx) => {
412
- console.log("Handling global signal registration...");
413
411
  const { signalToTaskMaps } = ctx;
414
412
  const sortedSignalToTaskMap = signalToTaskMaps.sort(
415
413
  (a, b) => {
@@ -418,9 +416,7 @@ var ServiceRegistry = class _ServiceRegistry {
418
416
  return 0;
419
417
  }
420
418
  );
421
- console.log(sortedSignalToTaskMap);
422
419
  const locallyEmittedSignals = CadenzaService.signalBroker.listEmittedSignals().filter((s) => s.startsWith("global."));
423
- console.log(locallyEmittedSignals);
424
420
  for (const map of sortedSignalToTaskMap) {
425
421
  if (map.deleted) {
426
422
  this.remoteSignals.get(map.serviceName)?.delete(map.signalName);
@@ -437,9 +433,6 @@ var ServiceRegistry = class _ServiceRegistry {
437
433
  this.remoteSignals.set(map.serviceName, /* @__PURE__ */ new Set());
438
434
  }
439
435
  if (!this.remoteSignals.get(map.serviceName)?.has(map.signalName)) {
440
- console.log(
441
- `Creating signal transmission task for: ${map.signalName} to ${map.serviceName}`
442
- );
443
436
  CadenzaService.createSignalTransmissionTask(
444
437
  map.signalName,
445
438
  map.serviceName
@@ -487,7 +480,12 @@ var ServiceRegistry = class _ServiceRegistry {
487
480
  return true;
488
481
  },
489
482
  "Handles service not responding"
490
- ).doOn("meta.fetch.handshake_failed", "meta.socket_client.disconnected").attachSignal("global.meta.service_registry.service_not_responding");
483
+ ).doOn(
484
+ "meta.fetch.handshake_failed",
485
+ "meta.fetch.handshake_failed.*",
486
+ "meta.socket_client.disconnected",
487
+ "meta.socket_client.disconnected.*"
488
+ ).attachSignal("global.meta.service_registry.service_not_responding");
491
489
  this.handleServiceHandshakeTask = CadenzaService.createMetaTask(
492
490
  "Handle service handshake",
493
491
  (ctx, emit) => {
@@ -514,7 +512,10 @@ var ServiceRegistry = class _ServiceRegistry {
514
512
  (i) => i.uuid !== serviceInstanceId && i.address === serviceAddress && i.port === servicePort
515
513
  );
516
514
  for (const i of instancesToDelete ?? []) {
517
- this.instances.get(serviceName)?.splice(this.instances.get(serviceName)?.indexOf(i) ?? -1, 1);
515
+ const indexToDelete = this.instances.get(serviceName)?.indexOf(i) ?? -1;
516
+ if (indexToDelete >= 0) {
517
+ this.instances.get(serviceName)?.splice(indexToDelete, 1);
518
+ }
518
519
  emit("global.meta.service_registry.deleted", {
519
520
  data: {
520
521
  isActive: false,
@@ -551,23 +552,14 @@ var ServiceRegistry = class _ServiceRegistry {
551
552
  const mergeSyncDataTask = CadenzaService.createUniqueMetaTask(
552
553
  "Merge sync data",
553
554
  (ctx) => {
554
- try {
555
- let joinedContext = {};
556
- ctx.joinedContexts.forEach((ctx2) => {
557
- joinedContext = { ...joinedContext, ...ctx2 };
558
- });
559
- console.log("merging contexts of full sync...", joinedContext);
560
- return joinedContext;
561
- } catch (e) {
562
- console.log("Error", e.message, ctx);
563
- return false;
564
- }
555
+ let joinedContext = {};
556
+ ctx.joinedContexts.forEach((ctx2) => {
557
+ joinedContext = { ...joinedContext, ...ctx2 };
558
+ });
559
+ return joinedContext;
565
560
  }
566
561
  ).emits("meta.service_registry.initial_sync_complete").then(this.handleGlobalSignalRegistrationTask);
567
562
  this.fullSyncTask = CadenzaService.createMetaRoutine("Full sync", [
568
- CadenzaService.createTask("Confirm full sync", () => {
569
- console.log("Confirming full sync...");
570
- }),
571
563
  CadenzaService.createCadenzaDBQueryTask("signal_to_task_map", {
572
564
  filter: {
573
565
  isGlobal: true
@@ -683,8 +675,9 @@ var ServiceRegistry = class _ServiceRegistry {
683
675
  }
684
676
  if (__broadcast || instances[0].isFrontend) {
685
677
  for (const instance of instances) {
678
+ const socketKey = instance.isFrontend ? instance.address : `${instance.address}_${instance.port}`;
686
679
  emit(
687
- `meta.service_registry.selected_instance_for_socket:${instance.address}`,
680
+ `meta.service_registry.selected_instance_for_socket:${socketKey}`,
688
681
  context
689
682
  );
690
683
  }
@@ -1675,6 +1668,46 @@ var RestController = class _RestController {
1675
1668
  var import_socket = require("socket.io");
1676
1669
  var import_rate_limiter_flexible2 = require("rate-limiter-flexible");
1677
1670
  var import_socket2 = require("socket.io-client");
1671
+
1672
+ // src/network/socketClientUtils.ts
1673
+ var waitForSocketConnection = async (socket, timeoutMs, createError) => {
1674
+ if (!socket) {
1675
+ return { ok: false, error: createError("disconnected") };
1676
+ }
1677
+ if (socket.connected) {
1678
+ return { ok: true };
1679
+ }
1680
+ return new Promise((resolve) => {
1681
+ let timer = null;
1682
+ let settled = false;
1683
+ const cleanup = () => {
1684
+ if (timer) {
1685
+ clearTimeout(timer);
1686
+ timer = null;
1687
+ }
1688
+ socket.off("connect", onConnect);
1689
+ socket.off("connect_error", onConnectError);
1690
+ socket.off("disconnect", onDisconnect);
1691
+ };
1692
+ const settle = (outcome) => {
1693
+ if (settled) return;
1694
+ settled = true;
1695
+ cleanup();
1696
+ resolve(outcome);
1697
+ };
1698
+ const onConnect = () => settle({ ok: true });
1699
+ const onConnectError = (error) => settle({ ok: false, error: createError("connect_error", error) });
1700
+ const onDisconnect = () => settle({ ok: false, error: createError("disconnected") });
1701
+ socket.once("connect", onConnect);
1702
+ socket.once("connect_error", onConnectError);
1703
+ socket.once("disconnect", onDisconnect);
1704
+ timer = setTimeout(() => {
1705
+ settle({ ok: false, error: createError("connect_timeout") });
1706
+ }, timeoutMs);
1707
+ });
1708
+ };
1709
+
1710
+ // src/network/SocketController.ts
1678
1711
  var SocketController = class _SocketController {
1679
1712
  static get instance() {
1680
1713
  if (!this._instance) this._instance = new _SocketController();
@@ -1811,10 +1844,6 @@ var SocketController = class _SocketController {
1811
1844
  "delegation",
1812
1845
  (ctx2, callback) => {
1813
1846
  const deputyExecId = ctx2.__metadata.__deputyExecId;
1814
- console.log(
1815
- "Delegation request received:",
1816
- ctx2.__localTaskName
1817
- );
1818
1847
  CadenzaService.createEphemeralMetaTask(
1819
1848
  "Resolve delegation",
1820
1849
  (ctx3) => {
@@ -1849,7 +1878,6 @@ var SocketController = class _SocketController {
1849
1878
  "signal",
1850
1879
  (ctx2, callback) => {
1851
1880
  if (CadenzaService.signalBroker.listObservedSignals().includes(ctx2.__signalName)) {
1852
- console.log("Signal received:", ctx2.__signalName);
1853
1881
  callback({
1854
1882
  __status: "success",
1855
1883
  __signalName: ctx2.__signalName
@@ -1955,35 +1983,71 @@ var SocketController = class _SocketController {
1955
1983
  });
1956
1984
  emitWhenReady = (event, data, timeoutMs = 6e4, ack) => {
1957
1985
  return new Promise((resolve) => {
1958
- const tryEmit = () => {
1959
- if (!socket?.connected) {
1960
- socket?.once("connect", tryEmit);
1986
+ const resolveWithError = (errorMessage, fallbackError) => {
1987
+ resolve({
1988
+ ...data,
1989
+ errored: true,
1990
+ __error: errorMessage,
1991
+ error: fallbackError instanceof Error ? fallbackError.message : errorMessage,
1992
+ socketId: socket?.id,
1993
+ serviceName,
1994
+ URL
1995
+ });
1996
+ };
1997
+ const tryEmit = async () => {
1998
+ const waitTimeoutMs = timeoutMs > 0 ? timeoutMs + 10 : 1e4;
1999
+ const waitResult = await waitForSocketConnection(
2000
+ socket,
2001
+ waitTimeoutMs,
2002
+ (reason, error) => {
2003
+ if (reason === "connect_timeout") {
2004
+ return `Socket connect timed out before '${event}'`;
2005
+ }
2006
+ if (reason === "connect_error") {
2007
+ const errMessage = error instanceof Error ? error.message : String(error);
2008
+ return `Socket connect error before '${event}': ${errMessage}`;
2009
+ }
2010
+ return `Socket disconnected before '${event}'`;
2011
+ }
2012
+ );
2013
+ if (!waitResult.ok) {
2014
+ CadenzaService.log(
2015
+ waitResult.error,
2016
+ { socketId: socket?.id, serviceName, URL, event },
2017
+ "error"
2018
+ );
2019
+ resolveWithError(waitResult.error);
1961
2020
  return;
1962
2021
  }
1963
- let timer;
2022
+ let timer = null;
1964
2023
  if (timeoutMs !== 0) {
1965
2024
  timer = setTimeout(() => {
2025
+ if (timer) {
2026
+ pendingTimers.delete(timer);
2027
+ timer = null;
2028
+ }
1966
2029
  CadenzaService.log(
1967
2030
  `Socket event '${event}' timed out`,
1968
2031
  { socketId: socket?.id, serviceName, URL },
1969
2032
  "error"
1970
2033
  );
1971
- resolve({
1972
- ...data,
1973
- errored: true,
1974
- __error: `Socket event '${event}' timed out`,
1975
- error: `Socket event '${event}' timed out`,
1976
- socketId: socket?.id,
1977
- serviceName,
1978
- URL
1979
- });
2034
+ resolveWithError(`Socket event '${event}' timed out`);
1980
2035
  }, timeoutMs + 10);
1981
2036
  pendingTimers.add(timer);
1982
2037
  }
1983
- socket.timeout(timeoutMs).emit(event, data, (err, response) => {
1984
- if (timer) clearTimeout(timer);
1985
- pendingTimers.delete(timer);
1986
- timer = null;
2038
+ const connectedSocket = socket;
2039
+ if (!connectedSocket) {
2040
+ resolveWithError(
2041
+ `Socket unavailable before emitting '${event}'`
2042
+ );
2043
+ return;
2044
+ }
2045
+ connectedSocket.timeout(timeoutMs).emit(event, data, (err, response) => {
2046
+ if (timer) {
2047
+ clearTimeout(timer);
2048
+ pendingTimers.delete(timer);
2049
+ timer = null;
2050
+ }
1987
2051
  if (err) {
1988
2052
  CadenzaService.log(
1989
2053
  "Socket timeout.",
@@ -2006,11 +2070,7 @@ var SocketController = class _SocketController {
2006
2070
  resolve(response);
2007
2071
  });
2008
2072
  };
2009
- if (socket?.connected) {
2010
- tryEmit();
2011
- } else {
2012
- socket?.once("connect", tryEmit);
2013
- }
2073
+ void tryEmit();
2014
2074
  });
2015
2075
  };
2016
2076
  socket.on("connect", () => {
@@ -2126,7 +2186,6 @@ var SocketController = class _SocketController {
2126
2186
  delete ctx2.__broadcast;
2127
2187
  const requestSentAt = Date.now();
2128
2188
  pendingDelegationIds.add(ctx2.__metadata.__deputyExecId);
2129
- console.log("Delegating task:", ctx2.__remoteRoutineName);
2130
2189
  emitWhenReady?.(
2131
2190
  "delegation",
2132
2191
  ctx2,
@@ -2135,12 +2194,6 @@ var SocketController = class _SocketController {
2135
2194
  const requestDuration = Date.now() - requestSentAt;
2136
2195
  const metadata = resultContext.__metadata;
2137
2196
  delete resultContext.__metadata;
2138
- console.log(
2139
- "Delegation response received:",
2140
- ctx2.__remoteRoutineName,
2141
- "Duration:",
2142
- requestDuration
2143
- );
2144
2197
  emit(
2145
2198
  `meta.socket_client.delegated:${ctx2.__metadata.__deputyExecId}`,
2146
2199
  {
@@ -2168,7 +2221,6 @@ var SocketController = class _SocketController {
2168
2221
  }
2169
2222
  return new Promise((resolve) => {
2170
2223
  delete ctx2.__broadcast;
2171
- console.log("Transmitting signal:", ctx2.__signalName);
2172
2224
  emitWhenReady?.("signal", ctx2, 5e3, (response) => {
2173
2225
  if (ctx2.__routineExecId) {
2174
2226
  emit(
@@ -2335,14 +2387,25 @@ var GraphMetadataController = class _GraphMetadataController {
2335
2387
  return {
2336
2388
  data: {
2337
2389
  ...ctx.data,
2338
- serviceName: CadenzaService.serviceRegistry.serviceName
2339
- // input_context_schema_id: ctx.data.inputContextSchema ? { // TODO
2340
- //
2341
- // } : null,
2342
- // output_context_schema_id: ctx.data.outputContextSchema ? {
2343
- //
2344
- // } : null,
2345
- }
2390
+ serviceName: CadenzaService.serviceRegistry.serviceName,
2391
+ inputContextSchemaId: ctx.data.inputContextSchemaId ? {
2392
+ subOperation: "insert",
2393
+ table: "context_schema",
2394
+ data: {
2395
+ ...ctx.data.inputContextSchemaId
2396
+ },
2397
+ return: "uuid"
2398
+ } : null,
2399
+ outputContextSchemaId: ctx.data.outputContextSchemaId ? {
2400
+ subOperation: "insert",
2401
+ table: "context_schema",
2402
+ data: {
2403
+ ...ctx.data.outputContextSchemaId
2404
+ },
2405
+ return: "uuid"
2406
+ } : null
2407
+ },
2408
+ transaction: true
2346
2409
  };
2347
2410
  }).doOn("meta.task.created").emits("global.meta.graph_metadata.task_created");
2348
2411
  CadenzaService.createMetaTask("Handle task update", (ctx) => {
@@ -2474,7 +2537,7 @@ var GraphMetadataController = class _GraphMetadataController {
2474
2537
  data: {
2475
2538
  ...ctx.data,
2476
2539
  serviceName: CadenzaService.serviceRegistry.serviceName,
2477
- serviceInstance_id: CadenzaService.serviceRegistry.serviceInstanceId
2540
+ serviceInstanceId: CadenzaService.serviceRegistry.serviceInstanceId
2478
2541
  },
2479
2542
  filter: {
2480
2543
  ...ctx.filter
@@ -3002,7 +3065,6 @@ var DatabaseController = class _DatabaseController {
3002
3065
  if (ddl && ddl.length > 0) {
3003
3066
  for (const sql of ddl) {
3004
3067
  try {
3005
- console.log("Executing DDL", sql);
3006
3068
  await this.dbClient.query(sql);
3007
3069
  } catch (error) {
3008
3070
  console.error(
@@ -3651,9 +3713,9 @@ var DatabaseController = class _DatabaseController {
3651
3713
  createDatabaseTask(op, tableName, table, queryFunction, options) {
3652
3714
  const opAction = op === "query" ? "queried" : op === "insert" ? "inserted" : op === "update" ? "updated" : op === "delete" ? "deleted" : "";
3653
3715
  const defaultSignal = `global.${options.isMeta ? "meta." : ""}${tableName}.${opAction}`;
3654
- const tableNameFormatted = tableName.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
3655
- const taskName = `db${op.charAt(0).toUpperCase() + op.slice(1)}${tableNameFormatted}`;
3656
- CadenzaService.createThrottledTask(
3716
+ const taskName = `${op.charAt(0).toUpperCase() + op.slice(1)} ${tableName}`;
3717
+ const schema = this.getInputSchema(op, tableName, table);
3718
+ const task = CadenzaService.createThrottledTask(
3657
3719
  taskName,
3658
3720
  async (context, emit) => {
3659
3721
  for (const action of Object.keys(table.customSignals?.triggers ?? {})) {
@@ -3748,17 +3810,8 @@ var DatabaseController = class _DatabaseController {
3748
3810
  {
3749
3811
  isMeta: options.isMeta,
3750
3812
  isSubMeta: options.isMeta,
3751
- validateInputContext: false,
3752
- // TODO
3753
- inputSchema: {
3754
- // TODO
3755
- type: "object",
3756
- properties: {
3757
- filter: {
3758
- type: "object"
3759
- }
3760
- }
3761
- }
3813
+ validateInputContext: options.securityProfile !== "low",
3814
+ inputSchema: schema
3762
3815
  }
3763
3816
  ).doOn(
3764
3817
  ...table.customSignals?.triggers?.[op]?.map((signal) => {
@@ -3769,8 +3822,382 @@ var DatabaseController = class _DatabaseController {
3769
3822
  return typeof signal === "string" ? signal : signal.signal;
3770
3823
  }) ?? []
3771
3824
  );
3825
+ if (op === "query") {
3826
+ const intentName = `query-${CadenzaService.serviceRegistry.serviceName}-${tableName}`;
3827
+ CadenzaService.defineIntent({
3828
+ name: intentName,
3829
+ description: `Perform a query operation on the ${tableName} table`,
3830
+ input: schema
3831
+ });
3832
+ task.respondsTo(intentName);
3833
+ }
3834
+ }
3835
+ getInputSchema(op, tableName, table) {
3836
+ const inputSchema = {
3837
+ type: "object",
3838
+ properties: {
3839
+ queryData: {
3840
+ type: "object",
3841
+ properties: {},
3842
+ strict: true
3843
+ }
3844
+ },
3845
+ strict: true
3846
+ };
3847
+ if (!inputSchema.properties) {
3848
+ return inputSchema;
3849
+ }
3850
+ inputSchema.properties.transaction = getTransactionSchema();
3851
+ inputSchema.properties.queryData.properties.transaction = inputSchema.properties.transaction;
3852
+ switch (op) {
3853
+ case "insert":
3854
+ inputSchema.properties.data = getInsertDataSchemaFromTable(
3855
+ table,
3856
+ tableName
3857
+ );
3858
+ inputSchema.properties.queryData.properties.data = inputSchema.properties.data;
3859
+ inputSchema.properties.batch = getQueryBatchSchemaFromTable();
3860
+ inputSchema.properties.queryData.properties.batch = inputSchema.properties.batch;
3861
+ inputSchema.properties.onConflict = getQueryOnConflictSchemaFromTable(
3862
+ table,
3863
+ tableName
3864
+ );
3865
+ inputSchema.properties.queryData.properties.onConflict = inputSchema.properties.onConflict;
3866
+ break;
3867
+ case "query":
3868
+ inputSchema.properties.filter = getQueryFilterSchemaFromTable(
3869
+ table,
3870
+ tableName
3871
+ );
3872
+ inputSchema.properties.queryData.properties.filter = inputSchema.properties.filter;
3873
+ inputSchema.properties.fields = getQueryFieldsSchemaFromTable(
3874
+ table,
3875
+ tableName
3876
+ );
3877
+ inputSchema.properties.queryData.properties.fields = inputSchema.properties.fields;
3878
+ inputSchema.properties.joins = getQueryJoinsSchemaFromTable(
3879
+ table,
3880
+ tableName
3881
+ );
3882
+ inputSchema.properties.queryData.properties.joins = inputSchema.properties.joins;
3883
+ inputSchema.properties.sort = getQuerySortSchemaFromTable(
3884
+ table,
3885
+ tableName
3886
+ );
3887
+ inputSchema.properties.queryData.properties.sort = inputSchema.properties.sort;
3888
+ inputSchema.properties.limit = getQueryLimitSchemaFromTable();
3889
+ inputSchema.properties.queryData.properties.limit = inputSchema.properties.limit;
3890
+ inputSchema.properties.offset = getQueryOffsetSchemaFromTable();
3891
+ inputSchema.properties.queryData.properties.offset = inputSchema.properties.offset;
3892
+ break;
3893
+ case "update":
3894
+ inputSchema.properties.filter = getQueryFilterSchemaFromTable(
3895
+ table,
3896
+ tableName
3897
+ );
3898
+ inputSchema.properties.queryData.properties.filter = inputSchema.properties.filter;
3899
+ inputSchema.properties.fields = getQueryFieldsSchemaFromTable(
3900
+ table,
3901
+ tableName
3902
+ );
3903
+ inputSchema.properties.queryData.properties.fields = inputSchema.properties.fields;
3904
+ break;
3905
+ case "delete":
3906
+ inputSchema.properties.filter = getQueryFilterSchemaFromTable(
3907
+ table,
3908
+ tableName
3909
+ );
3910
+ inputSchema.properties.queryData.properties.filter = inputSchema.properties.filter;
3911
+ break;
3912
+ }
3913
+ return inputSchema;
3772
3914
  }
3773
3915
  };
3916
+ function getInsertDataSchemaFromTable(table, tableName) {
3917
+ const dataSchema = {
3918
+ type: "object",
3919
+ properties: {
3920
+ ...Object.fromEntries(
3921
+ Object.entries(table.fields).map((field) => {
3922
+ return [
3923
+ field[0],
3924
+ [
3925
+ {
3926
+ type: tableFieldTypeToSchemaType(field[1].type),
3927
+ description: `Inferred from field '${field[0]}' of type [${field[1].type}] on table ${tableName}.`
3928
+ },
3929
+ {
3930
+ type: "string",
3931
+ constraints: {
3932
+ oneOf: ["increment", "decrement", "set"]
3933
+ }
3934
+ },
3935
+ {
3936
+ type: "object",
3937
+ properties: {
3938
+ subOperation: {
3939
+ type: "string",
3940
+ enum: ["insert", "query"]
3941
+ },
3942
+ table: {
3943
+ type: "string"
3944
+ },
3945
+ data: [
3946
+ {
3947
+ type: "object"
3948
+ },
3949
+ {
3950
+ type: "array",
3951
+ items: {
3952
+ type: "object"
3953
+ }
3954
+ }
3955
+ ],
3956
+ filter: {
3957
+ type: "object"
3958
+ },
3959
+ fields: {
3960
+ type: "array",
3961
+ items: {
3962
+ type: "string"
3963
+ }
3964
+ },
3965
+ return: {
3966
+ type: "string"
3967
+ }
3968
+ },
3969
+ required: ["subOperation", "table"]
3970
+ }
3971
+ ]
3972
+ ];
3973
+ })
3974
+ )
3975
+ },
3976
+ required: Object.entries(table.fields).filter((field) => field[1].required || field[1].primary).map((field) => field[0]),
3977
+ strict: true
3978
+ };
3979
+ return [
3980
+ dataSchema,
3981
+ {
3982
+ type: "array",
3983
+ items: dataSchema
3984
+ }
3985
+ ];
3986
+ }
3987
+ function getQueryFilterSchemaFromTable(table, tableName) {
3988
+ return {
3989
+ type: "object",
3990
+ properties: {
3991
+ ...Object.fromEntries(
3992
+ Object.entries(table.fields).map((field) => {
3993
+ return [
3994
+ field[0],
3995
+ [
3996
+ {
3997
+ type: tableFieldTypeToSchemaType(field[1].type),
3998
+ description: `Inferred from field '${field[0]}' of type [${field[1].type}] on table ${tableName}.`
3999
+ },
4000
+ {
4001
+ type: "array",
4002
+ items: {
4003
+ type: tableFieldTypeToSchemaType(field[1].type)
4004
+ }
4005
+ }
4006
+ ]
4007
+ ];
4008
+ })
4009
+ )
4010
+ },
4011
+ strict: true,
4012
+ description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry.serviceName}.`
4013
+ };
4014
+ }
4015
+ function getQueryFieldsSchemaFromTable(table, tableName) {
4016
+ return {
4017
+ type: "array",
4018
+ items: {
4019
+ type: "string",
4020
+ constraints: {
4021
+ oneOf: Object.keys(table.fields)
4022
+ }
4023
+ },
4024
+ description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry.serviceName}.`
4025
+ };
4026
+ }
4027
+ function getQueryJoinsSchemaFromTable(table, tableName) {
4028
+ return {
4029
+ type: "object",
4030
+ properties: {
4031
+ ...Object.fromEntries(
4032
+ Object.entries(table.fields).map((field) => {
4033
+ return [
4034
+ field[0],
4035
+ {
4036
+ type: "object",
4037
+ properties: {
4038
+ on: {
4039
+ type: "string"
4040
+ },
4041
+ fields: {
4042
+ type: "array",
4043
+ items: {
4044
+ type: "string"
4045
+ }
4046
+ },
4047
+ filter: {
4048
+ type: "object"
4049
+ },
4050
+ returnAs: {
4051
+ type: "string",
4052
+ constraints: {
4053
+ oneOf: ["array", "object"]
4054
+ }
4055
+ },
4056
+ alias: {
4057
+ type: "string"
4058
+ },
4059
+ joins: {
4060
+ type: "object"
4061
+ }
4062
+ },
4063
+ required: ["on", "fields"],
4064
+ strict: true
4065
+ }
4066
+ ];
4067
+ })
4068
+ )
4069
+ },
4070
+ strict: true,
4071
+ description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry.serviceName}.`
4072
+ };
4073
+ }
4074
+ function getQuerySortSchemaFromTable(table, tableName) {
4075
+ return {
4076
+ type: "object",
4077
+ properties: {
4078
+ ...Object.fromEntries(
4079
+ Object.entries(table.fields).map((field) => {
4080
+ return [
4081
+ field[0],
4082
+ {
4083
+ type: "string",
4084
+ constraints: {
4085
+ oneOf: ["asc", "desc"]
4086
+ }
4087
+ }
4088
+ ];
4089
+ })
4090
+ )
4091
+ },
4092
+ strict: true,
4093
+ description: `Inferred from table '${tableName}' on database service ${CadenzaService.serviceRegistry.serviceName}.`
4094
+ };
4095
+ }
4096
+ function getQueryLimitSchemaFromTable() {
4097
+ return {
4098
+ type: "number",
4099
+ constraints: {
4100
+ min: 1
4101
+ },
4102
+ description: "Limit for query results"
4103
+ };
4104
+ }
4105
+ function getQueryOffsetSchemaFromTable() {
4106
+ return {
4107
+ type: "number",
4108
+ constraints: {
4109
+ min: 0
4110
+ },
4111
+ description: "Offset for query results"
4112
+ };
4113
+ }
4114
+ function getTransactionSchema() {
4115
+ return {
4116
+ type: "boolean",
4117
+ description: "Whether to run the query in a transaction"
4118
+ };
4119
+ }
4120
+ function getQueryBatchSchemaFromTable() {
4121
+ return {
4122
+ type: "boolean",
4123
+ description: "Whether to run the query in batch mode"
4124
+ };
4125
+ }
4126
+ function getQueryOnConflictSchemaFromTable(table, tableName) {
4127
+ return {
4128
+ type: "object",
4129
+ properties: {
4130
+ target: {
4131
+ type: "array",
4132
+ items: {
4133
+ type: "string",
4134
+ constraints: {
4135
+ oneOf: Object.keys(table.fields)
4136
+ }
4137
+ }
4138
+ },
4139
+ action: {
4140
+ type: "object",
4141
+ properties: {
4142
+ do: {
4143
+ type: "string",
4144
+ constraints: {
4145
+ oneOf: ["nothing", "update"]
4146
+ }
4147
+ },
4148
+ set: {
4149
+ type: "object",
4150
+ properties: {
4151
+ ...Object.fromEntries(
4152
+ Object.entries(table.fields).map((field) => {
4153
+ return [
4154
+ field[0],
4155
+ [
4156
+ {
4157
+ type: tableFieldTypeToSchemaType(field[1].type),
4158
+ description: `Inferred from field '${field[0]}' of type [${field[1].type}] on table ${tableName}.`
4159
+ }
4160
+ ]
4161
+ ];
4162
+ })
4163
+ )
4164
+ }
4165
+ },
4166
+ where: {
4167
+ type: "string"
4168
+ }
4169
+ },
4170
+ required: ["do"]
4171
+ }
4172
+ },
4173
+ required: ["target", "action"],
4174
+ strict: true
4175
+ };
4176
+ }
4177
+ function tableFieldTypeToSchemaType(type) {
4178
+ switch (type) {
4179
+ case "varchar":
4180
+ case "text":
4181
+ case "jsonb":
4182
+ case "uuid":
4183
+ case "date":
4184
+ case "geo_point":
4185
+ case "bytea":
4186
+ return "string";
4187
+ case "int":
4188
+ case "bigint":
4189
+ case "decimal":
4190
+ case "timestamp":
4191
+ return "number";
4192
+ case "boolean":
4193
+ return "boolean";
4194
+ case "array":
4195
+ return "array";
4196
+ case "object":
4197
+ return "object";
4198
+ }
4199
+ return "any";
4200
+ }
3774
4201
 
3775
4202
  // src/Cadenza.ts
3776
4203
  var import_uuid3 = require("uuid");
@@ -4242,7 +4669,6 @@ var GraphSyncController = class _GraphSyncController {
4242
4669
  );
4243
4670
  CadenzaService.schedule("meta.sync_requested", { __syncing: true }, 2e3);
4244
4671
  }
4245
- console.log("Syncing initiated", this.isCadenzaDBReady);
4246
4672
  }
4247
4673
  };
4248
4674
 
@@ -4645,10 +5071,9 @@ var CadenzaService = class {
4645
5071
  this.bootstrap();
4646
5072
  this.validateName(tableName);
4647
5073
  this.validateName(operation);
4648
- const tableNameFormatted = tableName.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
4649
5074
  const name = `${operation.charAt(0).toUpperCase() + operation.slice(1)} ${tableName} in ${databaseServiceName ?? "default database service"}`;
4650
5075
  const description = `Executes a ${operation} on table ${tableName} in ${databaseServiceName ?? "default database service"}`;
4651
- const taskName = `db${operation.charAt(0).toUpperCase() + operation.slice(1)}${tableNameFormatted}`;
5076
+ const taskName = `${operation.charAt(0).toUpperCase() + operation.slice(1)} ${tableName}`;
4652
5077
  options = {
4653
5078
  concurrency: 100,
4654
5079
  timeout: 0,
@@ -4910,7 +5335,7 @@ var CadenzaService = class {
4910
5335
  * This method is not supported in a browser environment and will log a warning if called in such an environment.
4911
5336
  *
4912
5337
  * @param {string} name - The name of the database service to be created.
4913
- * @param {SchemaDefinition} schema - The schema definition for the database service.
5338
+ * @param {DatabaseSchemaDefinition} schema - The schema definition for the database service.
4914
5339
  * @param {string} [description=""] - An optional description of the database service.
4915
5340
  * @param {ServerOptions & DatabaseOptions} [options={}] - Optional configuration settings for the database and server.
4916
5341
  * @return {void} This method does not return a value.
@@ -4974,7 +5399,7 @@ var CadenzaService = class {
4974
5399
  * Creates a meta database service with the specified configuration.
4975
5400
  *
4976
5401
  * @param {string} name - The name of the database service to be created.
4977
- * @param {SchemaDefinition} schema - The schema definition for the database.
5402
+ * @param {DatabaseSchemaDefinition} schema - The schema definition for the database.
4978
5403
  * @param {string} [description=""] - An optional description of the database service.
4979
5404
  * @param {ServerOptions & DatabaseOptions} [options={}] - Optional server and database configuration options. The `isMeta` flag will be automatically set to true.
4980
5405
  * @return {void} - This method does not return a value.