@cadenza.io/service 2.17.9 → 2.17.10

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,24 @@ 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
+ }
6116
6148
  function readCustomIntentConfig(customIntent) {
6117
6149
  if (typeof customIntent === "string") {
6118
6150
  return {
@@ -6794,18 +6826,28 @@ var DatabaseController = class _DatabaseController {
6794
6826
  throw new Error("No rows available for insert after resolving data");
6795
6827
  }
6796
6828
  const keys = Object.keys(rows[0]);
6829
+ const tableFields = registration.schema.tables[tableName]?.fields ?? {};
6797
6830
  const sqlPrefix = `INSERT INTO ${tableName} (${keys.map((key) => snakeCase(key)).join(", ")}) VALUES `;
6798
6831
  const params = [];
6799
6832
  const placeholders = rows.map((row) => {
6800
6833
  const tuple = keys.map((key) => {
6801
- params.push(row[key]);
6834
+ params.push(
6835
+ serializeFieldValueForQuery(
6836
+ row[key],
6837
+ this.getFieldDefinitionForKey(tableFields, key)
6838
+ )
6839
+ );
6802
6840
  return `$${params.length}`;
6803
6841
  }).join(", ");
6804
6842
  return `(${tuple})`;
6805
6843
  }).join(", ");
6806
6844
  let onConflictSql = "";
6807
6845
  if (onConflict) {
6808
- onConflictSql = this.buildOnConflictClause(onConflict, params);
6846
+ onConflictSql = this.buildOnConflictClause(
6847
+ onConflict,
6848
+ params,
6849
+ tableFields
6850
+ );
6809
6851
  }
6810
6852
  const sql = `${sqlPrefix}${placeholders}${onConflictSql} RETURNING ${fields.length ? fields.map(snakeCase).join(", ") : "*"}`;
6811
6853
  const result = await this.withTimeout(
@@ -6853,27 +6895,26 @@ var DatabaseController = class _DatabaseController {
6853
6895
  data,
6854
6896
  tableName
6855
6897
  );
6856
- const params = Object.values(resolvedData);
6857
- let offset = 0;
6858
- const setClause = Object.keys(resolvedData).map((key, index) => {
6898
+ const tableFields = registration.schema.tables[tableName]?.fields ?? {};
6899
+ const params = [];
6900
+ const setClause = Object.keys(resolvedData).map((key) => {
6859
6901
  const value = resolvedData[key];
6860
- const offsetIndex = index - offset;
6861
6902
  if (value?.__effect === "increment") {
6862
- params.splice(offsetIndex, 1);
6863
- offset += 1;
6864
6903
  return `${snakeCase(key)} = ${snakeCase(key)} + 1`;
6865
6904
  }
6866
6905
  if (value?.__effect === "decrement") {
6867
- params.splice(offsetIndex, 1);
6868
- offset += 1;
6869
6906
  return `${snakeCase(key)} = ${snakeCase(key)} - 1`;
6870
6907
  }
6871
6908
  if (value?.__effect === "set") {
6872
- params.splice(offsetIndex, 1);
6873
- offset += 1;
6874
6909
  return `${snakeCase(key)} = ${value.__value}`;
6875
6910
  }
6876
- return `${snakeCase(key)} = $${offsetIndex + 1}`;
6911
+ params.push(
6912
+ serializeFieldValueForQuery(
6913
+ value,
6914
+ this.getFieldDefinitionForKey(tableFields, key)
6915
+ )
6916
+ );
6917
+ return `${snakeCase(key)} = $${params.length}`;
6877
6918
  }).join(", ");
6878
6919
  const whereClause = this.buildWhereClause(filter, params);
6879
6920
  const sql = `UPDATE ${tableName} SET ${setClause} ${whereClause} RETURNING *`;
@@ -6962,7 +7003,7 @@ var DatabaseController = class _DatabaseController {
6962
7003
  retryDelayFactor: Number.isFinite(durableState.safetyPolicy?.retryDelayFactor) ? Math.max(1, Number(durableState.safetyPolicy?.retryDelayFactor)) : 1
6963
7004
  };
6964
7005
  }
6965
- buildOnConflictClause(onConflict, params) {
7006
+ buildOnConflictClause(onConflict, params, tableFields) {
6966
7007
  const { target, action } = onConflict;
6967
7008
  let sql = ` ON CONFLICT (${target.map(snakeCase).join(", ")})`;
6968
7009
  if (action.do === "update") {
@@ -6973,7 +7014,12 @@ var DatabaseController = class _DatabaseController {
6973
7014
  if (typeof value === "string" && value === "excluded") {
6974
7015
  return `${snakeCase(field)} = excluded.${snakeCase(field)}`;
6975
7016
  }
6976
- params.push(value);
7017
+ params.push(
7018
+ serializeFieldValueForQuery(
7019
+ value,
7020
+ this.getFieldDefinitionForKey(tableFields, field)
7021
+ )
7022
+ );
6977
7023
  return `${snakeCase(field)} = $${params.length}`;
6978
7024
  });
6979
7025
  sql += ` DO UPDATE SET ${assignments.join(", ")}`;
@@ -6985,6 +7031,9 @@ var DatabaseController = class _DatabaseController {
6985
7031
  sql += " DO NOTHING";
6986
7032
  return sql;
6987
7033
  }
7034
+ getFieldDefinitionForKey(fields, key) {
7035
+ return fields[key] ?? fields[snakeCase(key)];
7036
+ }
6988
7037
  /**
6989
7038
  * Validates database schema structure and content.
6990
7039
  */
@@ -7606,7 +7655,13 @@ var DatabaseController = class _DatabaseController {
7606
7655
  );
7607
7656
  const row = ensurePlainObject(resolvedData, "sub-operation insert data");
7608
7657
  const keys = Object.keys(row);
7609
- const params = Object.values(row);
7658
+ const tableFields = registration.schema.tables[operation.table]?.fields ?? {};
7659
+ const params = keys.map(
7660
+ (key) => serializeFieldValueForQuery(
7661
+ row[key],
7662
+ this.getFieldDefinitionForKey(tableFields, key)
7663
+ )
7664
+ );
7610
7665
  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
7666
  const result2 = await this.withTimeout(
7612
7667
  () => client.query(sql2, params),