@cadenza.io/service 2.17.9 → 2.17.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.
package/dist/index.d.mts CHANGED
@@ -23120,6 +23120,7 @@ declare class DatabaseController {
23120
23120
  private deleteFunction;
23121
23121
  private resolveSafetyPolicy;
23122
23122
  private buildOnConflictClause;
23123
+ private getFieldDefinitionForKey;
23123
23124
  /**
23124
23125
  * Validates database schema structure and content.
23125
23126
  */
package/dist/index.d.ts CHANGED
@@ -23120,6 +23120,7 @@ declare class DatabaseController {
23120
23120
  private deleteFunction;
23121
23121
  private resolveSafetyPolicy;
23122
23122
  private buildOnConflictClause;
23123
+ private getFieldDefinitionForKey;
23123
23124
  /**
23124
23125
  * Validates database schema structure and content.
23125
23126
  */
package/dist/index.js CHANGED
@@ -5830,6 +5830,13 @@ var GraphMetadataController = class _GraphMetadataController {
5830
5830
  };
5831
5831
  }).doOn("meta.task.layer_index_changed", "meta.task.destroyed").emits("global.meta.graph_metadata.task_updated");
5832
5832
  CadenzaService.createMetaTask("Handle task relationship creation", (ctx) => {
5833
+ const taskName = ctx.data?.taskName ?? ctx.data?.task_name;
5834
+ const predecessorTaskName = ctx.data?.predecessorTaskName ?? ctx.data?.predecessor_task_name;
5835
+ const task = taskName ? CadenzaService.get(taskName) : void 0;
5836
+ const predecessorTask = predecessorTaskName ? CadenzaService.get(predecessorTaskName) : void 0;
5837
+ if (!task?.registered || !predecessorTask?.registered) {
5838
+ return false;
5839
+ }
5833
5840
  return {
5834
5841
  data: {
5835
5842
  ...ctx.data,
@@ -6106,6 +6113,13 @@ function defaultOperationIntentDescription(operation, tableName) {
6106
6113
  function isExplicitSqlLiteral(value) {
6107
6114
  return /^'.*'::[a-z_][a-z0-9_]*(\[\])?$/i.test(value.trim());
6108
6115
  }
6116
+ function extractExplicitJsonLiteral(value) {
6117
+ const match = /^'(.*)'::jsonb$/i.exec(value.trim());
6118
+ if (!match) {
6119
+ return null;
6120
+ }
6121
+ return match[1].replace(/''/g, "'");
6122
+ }
6109
6123
  function isExplicitSqlExpression(value) {
6110
6124
  const trimmed = value.trim();
6111
6125
  if (!trimmed) {
@@ -6164,6 +6178,31 @@ function serializeInitialDataValueForSql(value, field) {
6164
6178
  }
6165
6179
  return `'${stringValue.replace(/'/g, "''")}'`;
6166
6180
  }
6181
+ function serializeFieldValueForQuery(value, field) {
6182
+ if (value === void 0 || value === null || field?.type !== "jsonb") {
6183
+ return value;
6184
+ }
6185
+ if (typeof value === "string") {
6186
+ const explicitJsonLiteral = extractExplicitJsonLiteral(value);
6187
+ if (explicitJsonLiteral !== null) {
6188
+ return explicitJsonLiteral;
6189
+ }
6190
+ try {
6191
+ JSON.parse(value);
6192
+ return value;
6193
+ } catch {
6194
+ return JSON.stringify(value);
6195
+ }
6196
+ }
6197
+ return JSON.stringify(value);
6198
+ }
6199
+ function isSubOperationPayload(value) {
6200
+ if (!value || typeof value !== "object") {
6201
+ return false;
6202
+ }
6203
+ const candidate = value;
6204
+ return typeof candidate.subOperation === "string" && typeof candidate.table === "string" && candidate.table.trim().length > 0;
6205
+ }
6167
6206
  function readCustomIntentConfig(customIntent) {
6168
6207
  if (typeof customIntent === "string") {
6169
6208
  return {
@@ -6845,18 +6884,28 @@ var DatabaseController = class _DatabaseController {
6845
6884
  throw new Error("No rows available for insert after resolving data");
6846
6885
  }
6847
6886
  const keys = Object.keys(rows[0]);
6887
+ const tableFields = registration.schema.tables[tableName]?.fields ?? {};
6848
6888
  const sqlPrefix = `INSERT INTO ${tableName} (${keys.map((key) => (0, import_lodash_es.snakeCase)(key)).join(", ")}) VALUES `;
6849
6889
  const params = [];
6850
6890
  const placeholders = rows.map((row) => {
6851
6891
  const tuple = keys.map((key) => {
6852
- params.push(row[key]);
6892
+ params.push(
6893
+ serializeFieldValueForQuery(
6894
+ row[key],
6895
+ this.getFieldDefinitionForKey(tableFields, key)
6896
+ )
6897
+ );
6853
6898
  return `$${params.length}`;
6854
6899
  }).join(", ");
6855
6900
  return `(${tuple})`;
6856
6901
  }).join(", ");
6857
6902
  let onConflictSql = "";
6858
6903
  if (onConflict) {
6859
- onConflictSql = this.buildOnConflictClause(onConflict, params);
6904
+ onConflictSql = this.buildOnConflictClause(
6905
+ onConflict,
6906
+ params,
6907
+ tableFields
6908
+ );
6860
6909
  }
6861
6910
  const sql = `${sqlPrefix}${placeholders}${onConflictSql} RETURNING ${fields.length ? fields.map(import_lodash_es.snakeCase).join(", ") : "*"}`;
6862
6911
  const result = await this.withTimeout(
@@ -6904,27 +6953,26 @@ var DatabaseController = class _DatabaseController {
6904
6953
  data,
6905
6954
  tableName
6906
6955
  );
6907
- const params = Object.values(resolvedData);
6908
- let offset = 0;
6909
- const setClause = Object.keys(resolvedData).map((key, index) => {
6956
+ const tableFields = registration.schema.tables[tableName]?.fields ?? {};
6957
+ const params = [];
6958
+ const setClause = Object.keys(resolvedData).map((key) => {
6910
6959
  const value = resolvedData[key];
6911
- const offsetIndex = index - offset;
6912
6960
  if (value?.__effect === "increment") {
6913
- params.splice(offsetIndex, 1);
6914
- offset += 1;
6915
6961
  return `${(0, import_lodash_es.snakeCase)(key)} = ${(0, import_lodash_es.snakeCase)(key)} + 1`;
6916
6962
  }
6917
6963
  if (value?.__effect === "decrement") {
6918
- params.splice(offsetIndex, 1);
6919
- offset += 1;
6920
6964
  return `${(0, import_lodash_es.snakeCase)(key)} = ${(0, import_lodash_es.snakeCase)(key)} - 1`;
6921
6965
  }
6922
6966
  if (value?.__effect === "set") {
6923
- params.splice(offsetIndex, 1);
6924
- offset += 1;
6925
6967
  return `${(0, import_lodash_es.snakeCase)(key)} = ${value.__value}`;
6926
6968
  }
6927
- return `${(0, import_lodash_es.snakeCase)(key)} = $${offsetIndex + 1}`;
6969
+ params.push(
6970
+ serializeFieldValueForQuery(
6971
+ value,
6972
+ this.getFieldDefinitionForKey(tableFields, key)
6973
+ )
6974
+ );
6975
+ return `${(0, import_lodash_es.snakeCase)(key)} = $${params.length}`;
6928
6976
  }).join(", ");
6929
6977
  const whereClause = this.buildWhereClause(filter, params);
6930
6978
  const sql = `UPDATE ${tableName} SET ${setClause} ${whereClause} RETURNING *`;
@@ -7013,7 +7061,7 @@ var DatabaseController = class _DatabaseController {
7013
7061
  retryDelayFactor: Number.isFinite(durableState.safetyPolicy?.retryDelayFactor) ? Math.max(1, Number(durableState.safetyPolicy?.retryDelayFactor)) : 1
7014
7062
  };
7015
7063
  }
7016
- buildOnConflictClause(onConflict, params) {
7064
+ buildOnConflictClause(onConflict, params, tableFields) {
7017
7065
  const { target, action } = onConflict;
7018
7066
  let sql = ` ON CONFLICT (${target.map(import_lodash_es.snakeCase).join(", ")})`;
7019
7067
  if (action.do === "update") {
@@ -7024,7 +7072,12 @@ var DatabaseController = class _DatabaseController {
7024
7072
  if (typeof value === "string" && value === "excluded") {
7025
7073
  return `${(0, import_lodash_es.snakeCase)(field)} = excluded.${(0, import_lodash_es.snakeCase)(field)}`;
7026
7074
  }
7027
- params.push(value);
7075
+ params.push(
7076
+ serializeFieldValueForQuery(
7077
+ value,
7078
+ this.getFieldDefinitionForKey(tableFields, field)
7079
+ )
7080
+ );
7028
7081
  return `${(0, import_lodash_es.snakeCase)(field)} = $${params.length}`;
7029
7082
  });
7030
7083
  sql += ` DO UPDATE SET ${assignments.join(", ")}`;
@@ -7036,6 +7089,9 @@ var DatabaseController = class _DatabaseController {
7036
7089
  sql += " DO NOTHING";
7037
7090
  return sql;
7038
7091
  }
7092
+ getFieldDefinitionForKey(fields, key) {
7093
+ return fields[key] ?? fields[(0, import_lodash_es.snakeCase)(key)];
7094
+ }
7039
7095
  /**
7040
7096
  * Validates database schema structure and content.
7041
7097
  */
@@ -7628,9 +7684,8 @@ var DatabaseController = class _DatabaseController {
7628
7684
  }
7629
7685
  const resolved = { ...data };
7630
7686
  for (const [key, value] of Object.entries(data)) {
7631
- if (typeof value === "object" && value !== null && "subOperation" in value) {
7632
- const subOperation = value;
7633
- resolved[key] = await this.executeSubOperation(registration, subOperation);
7687
+ if (isSubOperationPayload(value)) {
7688
+ resolved[key] = await this.executeSubOperation(registration, value);
7634
7689
  } else if (typeof value === "string" && ["increment", "decrement", "set"].includes(value)) {
7635
7690
  resolved[key] = { __effect: value };
7636
7691
  } else if (typeof value === "object" && value !== null) {
@@ -7657,7 +7712,13 @@ var DatabaseController = class _DatabaseController {
7657
7712
  );
7658
7713
  const row = ensurePlainObject(resolvedData, "sub-operation insert data");
7659
7714
  const keys = Object.keys(row);
7660
- const params = Object.values(row);
7715
+ const tableFields = registration.schema.tables[operation.table]?.fields ?? {};
7716
+ const params = keys.map(
7717
+ (key) => serializeFieldValueForQuery(
7718
+ row[key],
7719
+ this.getFieldDefinitionForKey(tableFields, key)
7720
+ )
7721
+ );
7661
7722
  const sql2 = `INSERT INTO ${operation.table} (${keys.map((key) => (0, import_lodash_es.snakeCase)(key)).join(", ")}) VALUES (${params.map((_, index) => `$${index + 1}`).join(", ")}) ON CONFLICT DO NOTHING RETURNING ${operation.return ?? "*"}`;
7662
7723
  const result2 = await this.withTimeout(
7663
7724
  () => client.query(sql2, params),