@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.mjs CHANGED
@@ -5779,6 +5779,13 @@ var GraphMetadataController = class _GraphMetadataController {
5779
5779
  };
5780
5780
  }).doOn("meta.task.layer_index_changed", "meta.task.destroyed").emits("global.meta.graph_metadata.task_updated");
5781
5781
  CadenzaService.createMetaTask("Handle task relationship creation", (ctx) => {
5782
+ const taskName = ctx.data?.taskName ?? ctx.data?.task_name;
5783
+ const predecessorTaskName = ctx.data?.predecessorTaskName ?? ctx.data?.predecessor_task_name;
5784
+ const task = taskName ? CadenzaService.get(taskName) : void 0;
5785
+ const predecessorTask = predecessorTaskName ? CadenzaService.get(predecessorTaskName) : void 0;
5786
+ if (!task?.registered || !predecessorTask?.registered) {
5787
+ return false;
5788
+ }
5782
5789
  return {
5783
5790
  data: {
5784
5791
  ...ctx.data,
@@ -6055,6 +6062,13 @@ function defaultOperationIntentDescription(operation, tableName) {
6055
6062
  function isExplicitSqlLiteral(value) {
6056
6063
  return /^'.*'::[a-z_][a-z0-9_]*(\[\])?$/i.test(value.trim());
6057
6064
  }
6065
+ function extractExplicitJsonLiteral(value) {
6066
+ const match = /^'(.*)'::jsonb$/i.exec(value.trim());
6067
+ if (!match) {
6068
+ return null;
6069
+ }
6070
+ return match[1].replace(/''/g, "'");
6071
+ }
6058
6072
  function isExplicitSqlExpression(value) {
6059
6073
  const trimmed = value.trim();
6060
6074
  if (!trimmed) {
@@ -6113,6 +6127,31 @@ function serializeInitialDataValueForSql(value, field) {
6113
6127
  }
6114
6128
  return `'${stringValue.replace(/'/g, "''")}'`;
6115
6129
  }
6130
+ function serializeFieldValueForQuery(value, field) {
6131
+ if (value === void 0 || value === null || field?.type !== "jsonb") {
6132
+ return value;
6133
+ }
6134
+ if (typeof value === "string") {
6135
+ const explicitJsonLiteral = extractExplicitJsonLiteral(value);
6136
+ if (explicitJsonLiteral !== null) {
6137
+ return explicitJsonLiteral;
6138
+ }
6139
+ try {
6140
+ JSON.parse(value);
6141
+ return value;
6142
+ } catch {
6143
+ return JSON.stringify(value);
6144
+ }
6145
+ }
6146
+ return JSON.stringify(value);
6147
+ }
6148
+ function isSubOperationPayload(value) {
6149
+ if (!value || typeof value !== "object") {
6150
+ return false;
6151
+ }
6152
+ const candidate = value;
6153
+ return typeof candidate.subOperation === "string" && typeof candidate.table === "string" && candidate.table.trim().length > 0;
6154
+ }
6116
6155
  function readCustomIntentConfig(customIntent) {
6117
6156
  if (typeof customIntent === "string") {
6118
6157
  return {
@@ -6794,18 +6833,28 @@ var DatabaseController = class _DatabaseController {
6794
6833
  throw new Error("No rows available for insert after resolving data");
6795
6834
  }
6796
6835
  const keys = Object.keys(rows[0]);
6836
+ const tableFields = registration.schema.tables[tableName]?.fields ?? {};
6797
6837
  const sqlPrefix = `INSERT INTO ${tableName} (${keys.map((key) => snakeCase(key)).join(", ")}) VALUES `;
6798
6838
  const params = [];
6799
6839
  const placeholders = rows.map((row) => {
6800
6840
  const tuple = keys.map((key) => {
6801
- params.push(row[key]);
6841
+ params.push(
6842
+ serializeFieldValueForQuery(
6843
+ row[key],
6844
+ this.getFieldDefinitionForKey(tableFields, key)
6845
+ )
6846
+ );
6802
6847
  return `$${params.length}`;
6803
6848
  }).join(", ");
6804
6849
  return `(${tuple})`;
6805
6850
  }).join(", ");
6806
6851
  let onConflictSql = "";
6807
6852
  if (onConflict) {
6808
- onConflictSql = this.buildOnConflictClause(onConflict, params);
6853
+ onConflictSql = this.buildOnConflictClause(
6854
+ onConflict,
6855
+ params,
6856
+ tableFields
6857
+ );
6809
6858
  }
6810
6859
  const sql = `${sqlPrefix}${placeholders}${onConflictSql} RETURNING ${fields.length ? fields.map(snakeCase).join(", ") : "*"}`;
6811
6860
  const result = await this.withTimeout(
@@ -6853,27 +6902,26 @@ var DatabaseController = class _DatabaseController {
6853
6902
  data,
6854
6903
  tableName
6855
6904
  );
6856
- const params = Object.values(resolvedData);
6857
- let offset = 0;
6858
- const setClause = Object.keys(resolvedData).map((key, index) => {
6905
+ const tableFields = registration.schema.tables[tableName]?.fields ?? {};
6906
+ const params = [];
6907
+ const setClause = Object.keys(resolvedData).map((key) => {
6859
6908
  const value = resolvedData[key];
6860
- const offsetIndex = index - offset;
6861
6909
  if (value?.__effect === "increment") {
6862
- params.splice(offsetIndex, 1);
6863
- offset += 1;
6864
6910
  return `${snakeCase(key)} = ${snakeCase(key)} + 1`;
6865
6911
  }
6866
6912
  if (value?.__effect === "decrement") {
6867
- params.splice(offsetIndex, 1);
6868
- offset += 1;
6869
6913
  return `${snakeCase(key)} = ${snakeCase(key)} - 1`;
6870
6914
  }
6871
6915
  if (value?.__effect === "set") {
6872
- params.splice(offsetIndex, 1);
6873
- offset += 1;
6874
6916
  return `${snakeCase(key)} = ${value.__value}`;
6875
6917
  }
6876
- return `${snakeCase(key)} = $${offsetIndex + 1}`;
6918
+ params.push(
6919
+ serializeFieldValueForQuery(
6920
+ value,
6921
+ this.getFieldDefinitionForKey(tableFields, key)
6922
+ )
6923
+ );
6924
+ return `${snakeCase(key)} = $${params.length}`;
6877
6925
  }).join(", ");
6878
6926
  const whereClause = this.buildWhereClause(filter, params);
6879
6927
  const sql = `UPDATE ${tableName} SET ${setClause} ${whereClause} RETURNING *`;
@@ -6962,7 +7010,7 @@ var DatabaseController = class _DatabaseController {
6962
7010
  retryDelayFactor: Number.isFinite(durableState.safetyPolicy?.retryDelayFactor) ? Math.max(1, Number(durableState.safetyPolicy?.retryDelayFactor)) : 1
6963
7011
  };
6964
7012
  }
6965
- buildOnConflictClause(onConflict, params) {
7013
+ buildOnConflictClause(onConflict, params, tableFields) {
6966
7014
  const { target, action } = onConflict;
6967
7015
  let sql = ` ON CONFLICT (${target.map(snakeCase).join(", ")})`;
6968
7016
  if (action.do === "update") {
@@ -6973,7 +7021,12 @@ var DatabaseController = class _DatabaseController {
6973
7021
  if (typeof value === "string" && value === "excluded") {
6974
7022
  return `${snakeCase(field)} = excluded.${snakeCase(field)}`;
6975
7023
  }
6976
- params.push(value);
7024
+ params.push(
7025
+ serializeFieldValueForQuery(
7026
+ value,
7027
+ this.getFieldDefinitionForKey(tableFields, field)
7028
+ )
7029
+ );
6977
7030
  return `${snakeCase(field)} = $${params.length}`;
6978
7031
  });
6979
7032
  sql += ` DO UPDATE SET ${assignments.join(", ")}`;
@@ -6985,6 +7038,9 @@ var DatabaseController = class _DatabaseController {
6985
7038
  sql += " DO NOTHING";
6986
7039
  return sql;
6987
7040
  }
7041
+ getFieldDefinitionForKey(fields, key) {
7042
+ return fields[key] ?? fields[snakeCase(key)];
7043
+ }
6988
7044
  /**
6989
7045
  * Validates database schema structure and content.
6990
7046
  */
@@ -7577,9 +7633,8 @@ var DatabaseController = class _DatabaseController {
7577
7633
  }
7578
7634
  const resolved = { ...data };
7579
7635
  for (const [key, value] of Object.entries(data)) {
7580
- if (typeof value === "object" && value !== null && "subOperation" in value) {
7581
- const subOperation = value;
7582
- resolved[key] = await this.executeSubOperation(registration, subOperation);
7636
+ if (isSubOperationPayload(value)) {
7637
+ resolved[key] = await this.executeSubOperation(registration, value);
7583
7638
  } else if (typeof value === "string" && ["increment", "decrement", "set"].includes(value)) {
7584
7639
  resolved[key] = { __effect: value };
7585
7640
  } else if (typeof value === "object" && value !== null) {
@@ -7606,7 +7661,13 @@ var DatabaseController = class _DatabaseController {
7606
7661
  );
7607
7662
  const row = ensurePlainObject(resolvedData, "sub-operation insert data");
7608
7663
  const keys = Object.keys(row);
7609
- const params = Object.values(row);
7664
+ const tableFields = registration.schema.tables[operation.table]?.fields ?? {};
7665
+ const params = keys.map(
7666
+ (key) => serializeFieldValueForQuery(
7667
+ row[key],
7668
+ this.getFieldDefinitionForKey(tableFields, key)
7669
+ )
7670
+ );
7610
7671
  const sql2 = `INSERT INTO ${operation.table} (${keys.map((key) => snakeCase(key)).join(", ")}) VALUES (${params.map((_, index) => `$${index + 1}`).join(", ")}) ON CONFLICT DO NOTHING RETURNING ${operation.return ?? "*"}`;
7611
7672
  const result2 = await this.withTimeout(
7612
7673
  () => client.query(sql2, params),