@payloadcms/drizzle 3.89.0-internal.95c9cba → 3.90.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.
Files changed (55) hide show
  1. package/dist/find/buildPolymorphicJoinQuery.d.ts +37 -0
  2. package/dist/find/buildPolymorphicJoinQuery.d.ts.map +1 -0
  3. package/dist/find/buildPolymorphicJoinQuery.js +134 -0
  4. package/dist/find/buildPolymorphicJoinQuery.js.map +1 -0
  5. package/dist/find/buildPolymorphicJoinQuery.spec.js +384 -0
  6. package/dist/find/buildPolymorphicJoinQuery.spec.js.map +1 -0
  7. package/dist/find/buildPolymorphicJoinWhere.d.ts +19 -0
  8. package/dist/find/buildPolymorphicJoinWhere.d.ts.map +1 -0
  9. package/dist/find/buildPolymorphicJoinWhere.js +268 -0
  10. package/dist/find/buildPolymorphicJoinWhere.js.map +1 -0
  11. package/dist/find/buildPolymorphicJoinWhere.spec.js +762 -0
  12. package/dist/find/buildPolymorphicJoinWhere.spec.js.map +1 -0
  13. package/dist/find/createPolymorphicJoinWherePlan.d.ts +37 -0
  14. package/dist/find/createPolymorphicJoinWherePlan.d.ts.map +1 -0
  15. package/dist/find/createPolymorphicJoinWherePlan.js +190 -0
  16. package/dist/find/createPolymorphicJoinWherePlan.js.map +1 -0
  17. package/dist/find/createPolymorphicJoinWherePlan.spec.js +897 -0
  18. package/dist/find/createPolymorphicJoinWherePlan.spec.js.map +1 -0
  19. package/dist/find/traverseFields.d.ts.map +1 -1
  20. package/dist/find/traverseFields.js +18 -191
  21. package/dist/find/traverseFields.js.map +1 -1
  22. package/dist/postgres/createJSONQuery/index.js +3 -3
  23. package/dist/postgres/createJSONQuery/index.js.map +1 -1
  24. package/dist/queries/getTableColumnFromPath.d.ts.map +1 -1
  25. package/dist/queries/getTableColumnFromPath.js +9 -0
  26. package/dist/queries/getTableColumnFromPath.js.map +1 -1
  27. package/dist/queries/parseParams.d.ts.map +1 -1
  28. package/dist/queries/parseParams.js +65 -3
  29. package/dist/queries/parseParams.js.map +1 -1
  30. package/dist/sqlite/createJSONQuery/convertPathToJSONTraversal.js +3 -2
  31. package/dist/sqlite/createJSONQuery/convertPathToJSONTraversal.js.map +1 -1
  32. package/dist/sqlite/createJSONQuery/index.d.ts.map +1 -1
  33. package/dist/sqlite/createJSONQuery/index.js +6 -5
  34. package/dist/sqlite/createJSONQuery/index.js.map +1 -1
  35. package/dist/sqlite/createJSONQuery/index.spec.js +28 -0
  36. package/dist/sqlite/createJSONQuery/index.spec.js.map +1 -0
  37. package/dist/transform/write/traverseFields.d.ts.map +1 -1
  38. package/dist/transform/write/traverseFields.js +8 -14
  39. package/dist/transform/write/traverseFields.js.map +1 -1
  40. package/dist/updateOne.d.ts.map +1 -1
  41. package/dist/updateOne.js +41 -1
  42. package/dist/updateOne.js.map +1 -1
  43. package/dist/updateOne.spec.js +84 -0
  44. package/dist/updateOne.spec.js.map +1 -0
  45. package/dist/upsertRow/conditionalUpdate.spec.js +61 -0
  46. package/dist/upsertRow/conditionalUpdate.spec.js.map +1 -0
  47. package/dist/upsertRow/index.d.ts +1 -1
  48. package/dist/upsertRow/index.d.ts.map +1 -1
  49. package/dist/upsertRow/index.js +25 -5
  50. package/dist/upsertRow/index.js.map +1 -1
  51. package/dist/utilities/parseJSONPathSegment.d.ts +9 -0
  52. package/dist/utilities/parseJSONPathSegment.d.ts.map +1 -0
  53. package/dist/utilities/parseJSONPathSegment.js +17 -0
  54. package/dist/utilities/parseJSONPathSegment.js.map +1 -0
  55. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/sqlite/createJSONQuery/convertPathToJSONTraversal.ts"],"sourcesContent":["import { sanitizePathSegment } from '../../utilities/sanitizePathSegment.js'\n\nexport const convertPathToJSONTraversal = (incomingSegments: string[]): string => {\n const segments = [...incomingSegments]\n segments.shift()\n\n return segments.reduce((res, segment, i) => {\n const formattedSegment = Number.isNaN(parseInt(segment))\n ? `'${sanitizePathSegment(segment)}'`\n : segment\n const isLast = i === segments.length - 1\n return `${res}${isLast ? '->>' : '->'}${formattedSegment}`\n }, '')\n}\n"],"names":["sanitizePathSegment","convertPathToJSONTraversal","incomingSegments","segments","shift","reduce","res","segment","i","formattedSegment","Number","isNaN","parseInt","isLast","length"],"mappings":"AAAA,SAASA,mBAAmB,QAAQ,yCAAwC;AAE5E,OAAO,MAAMC,6BAA6B,CAACC;IACzC,MAAMC,WAAW;WAAID;KAAiB;IACtCC,SAASC,KAAK;IAEd,OAAOD,SAASE,MAAM,CAAC,CAACC,KAAKC,SAASC;QACpC,MAAMC,mBAAmBC,OAAOC,KAAK,CAACC,SAASL,YAC3C,CAAC,CAAC,EAAEP,oBAAoBO,SAAS,CAAC,CAAC,GACnCA;QACJ,MAAMM,SAASL,MAAML,SAASW,MAAM,GAAG;QACvC,OAAO,GAAGR,MAAMO,SAAS,QAAQ,OAAOJ,kBAAkB;IAC5D,GAAG;AACL,EAAC"}
1
+ {"version":3,"sources":["../../../src/sqlite/createJSONQuery/convertPathToJSONTraversal.ts"],"sourcesContent":["import { parseJSONPathSegment } from '../../utilities/parseJSONPathSegment.js'\n\nexport const convertPathToJSONTraversal = (incomingSegments: string[]): string => {\n const segments = [...incomingSegments]\n segments.shift()\n\n return segments.reduce((res, segment, i) => {\n const parsedSegment = parseJSONPathSegment(segment)\n const formattedSegment =\n parsedSegment.type === 'objectKey' ? `'${parsedSegment.value}'` : parsedSegment.value\n const isLast = i === segments.length - 1\n return `${res}${isLast ? '->>' : '->'}${formattedSegment}`\n }, '')\n}\n"],"names":["parseJSONPathSegment","convertPathToJSONTraversal","incomingSegments","segments","shift","reduce","res","segment","i","parsedSegment","formattedSegment","type","value","isLast","length"],"mappings":"AAAA,SAASA,oBAAoB,QAAQ,0CAAyC;AAE9E,OAAO,MAAMC,6BAA6B,CAACC;IACzC,MAAMC,WAAW;WAAID;KAAiB;IACtCC,SAASC,KAAK;IAEd,OAAOD,SAASE,MAAM,CAAC,CAACC,KAAKC,SAASC;QACpC,MAAMC,gBAAgBT,qBAAqBO;QAC3C,MAAMG,mBACJD,cAAcE,IAAI,KAAK,cAAc,CAAC,CAAC,EAAEF,cAAcG,KAAK,CAAC,CAAC,CAAC,GAAGH,cAAcG,KAAK;QACvF,MAAMC,SAASL,MAAML,SAASW,MAAM,GAAG;QACvC,OAAO,GAAGR,MAAMO,SAAS,QAAQ,OAAOH,kBAAkB;IAC5D,GAAG;AACL,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sqlite/createJSONQuery/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AA8GzD,eAAO,MAAM,eAAe,iGASzB,mBAAmB,KAAG,MA0BxB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sqlite/createJSONQuery/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAgHzD,eAAO,MAAM,eAAe,iGASzB,mBAAmB,KAAG,MA2BxB,CAAA"}
@@ -16,7 +16,7 @@ const fromArray = ({ isRoot, operator, pathSegments, table, treatAsArray, value
16
16
  })}
17
17
  )`;
18
18
  };
19
- const createConstraint = ({ alias, operator, pathSegments, value })=>{
19
+ const createConstraint = ({ alias, operator, pathSegments, rootColumn, value })=>{
20
20
  const newAlias = `${pathSegments[0]}_alias_${pathSegments.length - 1}`;
21
21
  if (operator === 'exists' && value === false) {
22
22
  operator = 'not_exists';
@@ -27,7 +27,7 @@ const createConstraint = ({ alias, operator, pathSegments, value })=>{
27
27
  }
28
28
  if (operator === 'exists') {
29
29
  if (pathSegments.length === 1) {
30
- return `EXISTS (SELECT 1 FROM json_each("${sanitizePathSegment(pathSegments[0])}") AS ${newAlias})`;
30
+ return `EXISTS (SELECT 1 FROM json_each(${rootColumn ?? `"${sanitizePathSegment(pathSegments[0])}"`}) AS ${newAlias})`;
31
31
  }
32
32
  return `EXISTS (
33
33
  SELECT 1
@@ -37,7 +37,7 @@ const createConstraint = ({ alias, operator, pathSegments, value })=>{
37
37
  }
38
38
  if (operator === 'not_exists') {
39
39
  if (pathSegments.length === 1) {
40
- return `NOT EXISTS (SELECT 1 FROM json_each("${sanitizePathSegment(pathSegments[0])}") AS ${newAlias})`;
40
+ return `NOT EXISTS (SELECT 1 FROM json_each(${rootColumn ?? `"${sanitizePathSegment(pathSegments[0])}"`}) AS ${newAlias})`;
41
41
  }
42
42
  return `NOT EXISTS (
43
43
  SELECT 1
@@ -63,7 +63,7 @@ const createConstraint = ({ alias, operator, pathSegments, value })=>{
63
63
  formattedOperator = '=';
64
64
  }
65
65
  if (pathSegments.length === 1) {
66
- return `EXISTS (SELECT 1 FROM json_each("${sanitizePathSegment(pathSegments[0])}") AS ${newAlias} WHERE ${newAlias}.value ${formattedOperator} '${formattedValue}')`;
66
+ return `EXISTS (SELECT 1 FROM json_each(${rootColumn ?? `"${sanitizePathSegment(pathSegments[0])}"`}) AS ${newAlias} WHERE ${newAlias}.value ${formattedOperator} '${formattedValue}')`;
67
67
  }
68
68
  return `EXISTS (
69
69
  SELECT 1
@@ -86,7 +86,7 @@ export const createJSONQuery = ({ column, operator, pathSegments, rawColumn, tab
86
86
  value: v
87
87
  })} ${i === value.length - 1 ? '' : ` ${operator === 'in' ? 'OR' : 'AND'} `}`;
88
88
  }
89
- return sql;
89
+ return `(${sql})`;
90
90
  }
91
91
  if (treatAsArray?.includes(pathSegments[1]) && table) {
92
92
  return fromArray({
@@ -101,6 +101,7 @@ export const createJSONQuery = ({ column, operator, pathSegments, rawColumn, tab
101
101
  alias: table,
102
102
  operator,
103
103
  pathSegments,
104
+ rootColumn: typeof column === 'string' ? column : column ? `"${column.name}"` : undefined,
104
105
  treatAsArray,
105
106
  value: value
106
107
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/sqlite/createJSONQuery/index.ts"],"sourcesContent":["import type { CreateJSONQueryArgs } from '../../types.js'\n\nimport { escapeSQLValue } from '../../utilities/escapeSQLValue.js'\nimport { sanitizePathSegment } from '../../utilities/sanitizePathSegment.js'\n\ntype FromArrayArgs = {\n isRoot?: true\n operator: string\n pathSegments: string[]\n table: string\n treatAsArray?: string[]\n value: boolean | number | string\n}\n\nconst fromArray = ({\n isRoot,\n operator,\n pathSegments,\n table,\n treatAsArray,\n value,\n}: FromArrayArgs) => {\n const newPathSegments = pathSegments.slice(1)\n const sanitizedSegment = sanitizePathSegment(pathSegments[isRoot ? 0 : 1])\n const alias = `${sanitizedSegment}_alias_${newPathSegments.length}`\n\n return `EXISTS (\n SELECT 1\n FROM json_each(${table}.${sanitizePathSegment(pathSegments[0])}) AS ${alias}\n WHERE ${createJSONQuery({\n operator,\n pathSegments: newPathSegments,\n table: alias,\n treatAsArray,\n value,\n })}\n )`\n}\n\ntype CreateConstraintArgs = {\n alias?: string\n operator: string\n pathSegments: string[]\n treatAsArray?: string[]\n value: boolean | number | string\n}\n\nconst createConstraint = ({\n alias,\n operator,\n pathSegments,\n value,\n}: CreateConstraintArgs): string => {\n const newAlias = `${pathSegments[0]}_alias_${pathSegments.length - 1}`\n\n if (operator === 'exists' && value === false) {\n operator = 'not_exists'\n value = true\n } else if (operator === 'not_exists' && value === false) {\n operator = 'exists'\n value = true\n }\n\n if (operator === 'exists') {\n if (pathSegments.length === 1) {\n return `EXISTS (SELECT 1 FROM json_each(\"${sanitizePathSegment(pathSegments[0])}\") AS ${newAlias})`\n }\n\n return `EXISTS (\n SELECT 1\n FROM json_each(${alias}.value -> '${sanitizePathSegment(pathSegments[0])}') AS ${newAlias}\n WHERE ${newAlias}.key = '${sanitizePathSegment(pathSegments[1])}'\n )`\n }\n\n if (operator === 'not_exists') {\n if (pathSegments.length === 1) {\n return `NOT EXISTS (SELECT 1 FROM json_each(\"${sanitizePathSegment(pathSegments[0])}\") AS ${newAlias})`\n }\n\n return `NOT EXISTS (\n SELECT 1\n FROM json_each(${alias}.value -> '${sanitizePathSegment(pathSegments[0])}') AS ${newAlias}\n WHERE ${newAlias}.key = '${sanitizePathSegment(pathSegments[1])}'\n )`\n }\n\n let formattedValue = escapeSQLValue(value)\n let formattedOperator = operator\n if (['contains', 'like'].includes(operator)) {\n formattedOperator = 'like'\n formattedValue = `%${value}%`\n } else if (['not_like', 'notlike'].includes(operator)) {\n formattedOperator = 'not like'\n formattedValue = `%${value}%`\n } else if (operator === 'equals') {\n formattedOperator = '='\n }\n\n if (pathSegments.length === 1) {\n return `EXISTS (SELECT 1 FROM json_each(\"${sanitizePathSegment(pathSegments[0])}\") AS ${newAlias} WHERE ${newAlias}.value ${formattedOperator} '${formattedValue}')`\n }\n\n return `EXISTS (\n SELECT 1\n FROM json_each(${alias}.value -> '${sanitizePathSegment(pathSegments[0])}') AS ${newAlias}\n WHERE COALESCE(${newAlias}.value ->> '${sanitizePathSegment(pathSegments[1])}', '') ${formattedOperator} '${formattedValue}'\n )`\n}\n\nexport const createJSONQuery = ({\n column,\n operator,\n pathSegments,\n rawColumn,\n table,\n treatAsArray,\n treatRootAsArray,\n value,\n}: CreateJSONQueryArgs): string => {\n if ((operator === 'in' || operator === 'not_in') && Array.isArray(value)) {\n let sql = ''\n for (const [i, v] of value.entries()) {\n sql = `${sql}${createJSONQuery({ column, operator: operator === 'in' ? 'equals' : 'not_equals', pathSegments, rawColumn, table, treatAsArray, treatRootAsArray, value: v })} ${i === value.length - 1 ? '' : ` ${operator === 'in' ? 'OR' : 'AND'} `}`\n }\n return sql\n }\n\n if (treatAsArray?.includes(pathSegments[1]) && table) {\n return fromArray({\n operator,\n pathSegments,\n table,\n treatAsArray,\n value: value as CreateConstraintArgs['value'],\n })\n }\n\n return createConstraint({\n alias: table,\n operator,\n pathSegments,\n treatAsArray,\n value: value as CreateConstraintArgs['value'],\n })\n}\n"],"names":["escapeSQLValue","sanitizePathSegment","fromArray","isRoot","operator","pathSegments","table","treatAsArray","value","newPathSegments","slice","sanitizedSegment","alias","length","createJSONQuery","createConstraint","newAlias","formattedValue","formattedOperator","includes","column","rawColumn","treatRootAsArray","Array","isArray","sql","i","v","entries"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/sqlite/createJSONQuery/index.ts"],"sourcesContent":["import type { CreateJSONQueryArgs } from '../../types.js'\n\nimport { escapeSQLValue } from '../../utilities/escapeSQLValue.js'\nimport { sanitizePathSegment } from '../../utilities/sanitizePathSegment.js'\n\ntype FromArrayArgs = {\n isRoot?: true\n operator: string\n pathSegments: string[]\n table: string\n treatAsArray?: string[]\n value: boolean | number | string\n}\n\nconst fromArray = ({\n isRoot,\n operator,\n pathSegments,\n table,\n treatAsArray,\n value,\n}: FromArrayArgs) => {\n const newPathSegments = pathSegments.slice(1)\n const sanitizedSegment = sanitizePathSegment(pathSegments[isRoot ? 0 : 1])\n const alias = `${sanitizedSegment}_alias_${newPathSegments.length}`\n\n return `EXISTS (\n SELECT 1\n FROM json_each(${table}.${sanitizePathSegment(pathSegments[0])}) AS ${alias}\n WHERE ${createJSONQuery({\n operator,\n pathSegments: newPathSegments,\n table: alias,\n treatAsArray,\n value,\n })}\n )`\n}\n\ntype CreateConstraintArgs = {\n alias?: string\n operator: string\n pathSegments: string[]\n rootColumn?: string\n treatAsArray?: string[]\n value: boolean | number | string\n}\n\nconst createConstraint = ({\n alias,\n operator,\n pathSegments,\n rootColumn,\n value,\n}: CreateConstraintArgs): string => {\n const newAlias = `${pathSegments[0]}_alias_${pathSegments.length - 1}`\n\n if (operator === 'exists' && value === false) {\n operator = 'not_exists'\n value = true\n } else if (operator === 'not_exists' && value === false) {\n operator = 'exists'\n value = true\n }\n\n if (operator === 'exists') {\n if (pathSegments.length === 1) {\n return `EXISTS (SELECT 1 FROM json_each(${rootColumn ?? `\"${sanitizePathSegment(pathSegments[0])}\"`}) AS ${newAlias})`\n }\n\n return `EXISTS (\n SELECT 1\n FROM json_each(${alias}.value -> '${sanitizePathSegment(pathSegments[0])}') AS ${newAlias}\n WHERE ${newAlias}.key = '${sanitizePathSegment(pathSegments[1])}'\n )`\n }\n\n if (operator === 'not_exists') {\n if (pathSegments.length === 1) {\n return `NOT EXISTS (SELECT 1 FROM json_each(${rootColumn ?? `\"${sanitizePathSegment(pathSegments[0])}\"`}) AS ${newAlias})`\n }\n\n return `NOT EXISTS (\n SELECT 1\n FROM json_each(${alias}.value -> '${sanitizePathSegment(pathSegments[0])}') AS ${newAlias}\n WHERE ${newAlias}.key = '${sanitizePathSegment(pathSegments[1])}'\n )`\n }\n\n let formattedValue = escapeSQLValue(value)\n let formattedOperator = operator\n if (['contains', 'like'].includes(operator)) {\n formattedOperator = 'like'\n formattedValue = `%${value}%`\n } else if (['not_like', 'notlike'].includes(operator)) {\n formattedOperator = 'not like'\n formattedValue = `%${value}%`\n } else if (operator === 'equals') {\n formattedOperator = '='\n }\n\n if (pathSegments.length === 1) {\n return `EXISTS (SELECT 1 FROM json_each(${rootColumn ?? `\"${sanitizePathSegment(pathSegments[0])}\"`}) AS ${newAlias} WHERE ${newAlias}.value ${formattedOperator} '${formattedValue}')`\n }\n\n return `EXISTS (\n SELECT 1\n FROM json_each(${alias}.value -> '${sanitizePathSegment(pathSegments[0])}') AS ${newAlias}\n WHERE COALESCE(${newAlias}.value ->> '${sanitizePathSegment(pathSegments[1])}', '') ${formattedOperator} '${formattedValue}'\n )`\n}\n\nexport const createJSONQuery = ({\n column,\n operator,\n pathSegments,\n rawColumn,\n table,\n treatAsArray,\n treatRootAsArray,\n value,\n}: CreateJSONQueryArgs): string => {\n if ((operator === 'in' || operator === 'not_in') && Array.isArray(value)) {\n let sql = ''\n for (const [i, v] of value.entries()) {\n sql = `${sql}${createJSONQuery({ column, operator: operator === 'in' ? 'equals' : 'not_equals', pathSegments, rawColumn, table, treatAsArray, treatRootAsArray, value: v })} ${i === value.length - 1 ? '' : ` ${operator === 'in' ? 'OR' : 'AND'} `}`\n }\n return `(${sql})`\n }\n\n if (treatAsArray?.includes(pathSegments[1]) && table) {\n return fromArray({\n operator,\n pathSegments,\n table,\n treatAsArray,\n value: value as CreateConstraintArgs['value'],\n })\n }\n\n return createConstraint({\n alias: table,\n operator,\n pathSegments,\n rootColumn: typeof column === 'string' ? column : column ? `\"${column.name}\"` : undefined,\n treatAsArray,\n value: value as CreateConstraintArgs['value'],\n })\n}\n"],"names":["escapeSQLValue","sanitizePathSegment","fromArray","isRoot","operator","pathSegments","table","treatAsArray","value","newPathSegments","slice","sanitizedSegment","alias","length","createJSONQuery","createConstraint","rootColumn","newAlias","formattedValue","formattedOperator","includes","column","rawColumn","treatRootAsArray","Array","isArray","sql","i","v","entries","name","undefined"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { createJSONQuery } from './index.js';
3
+ describe('createJSONQuery', ()=>{
4
+ it('uses a supplied root SQL expression for scalar array comparisons', ()=>{
5
+ const rootColumn = '(select json_group_array(tags.value) from article_tags as tags)';
6
+ expect(createJSONQuery({
7
+ column: rootColumn,
8
+ operator: 'equals',
9
+ pathSegments: [
10
+ 'tags'
11
+ ],
12
+ value: 'available'
13
+ })).toContain(`json_each(${rootColumn})`);
14
+ });
15
+ it('uses a supplied root SQL expression for array existence checks', ()=>{
16
+ const rootColumn = '(select json_group_array(tags.value) from article_tags as tags)';
17
+ expect(createJSONQuery({
18
+ column: rootColumn,
19
+ operator: 'exists',
20
+ pathSegments: [
21
+ 'tags'
22
+ ],
23
+ value: false
24
+ })).toContain(`NOT EXISTS (SELECT 1 FROM json_each(${rootColumn})`);
25
+ });
26
+ });
27
+
28
+ //# sourceMappingURL=index.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/sqlite/createJSONQuery/index.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { createJSONQuery } from './index.js'\n\ndescribe('createJSONQuery', () => {\n it('uses a supplied root SQL expression for scalar array comparisons', () => {\n const rootColumn = '(select json_group_array(tags.value) from article_tags as tags)'\n\n expect(\n createJSONQuery({\n column: rootColumn,\n operator: 'equals',\n pathSegments: ['tags'],\n value: 'available',\n }),\n ).toContain(`json_each(${rootColumn})`)\n })\n\n it('uses a supplied root SQL expression for array existence checks', () => {\n const rootColumn = '(select json_group_array(tags.value) from article_tags as tags)'\n\n expect(\n createJSONQuery({\n column: rootColumn,\n operator: 'exists',\n pathSegments: ['tags'],\n value: false,\n }),\n ).toContain(`NOT EXISTS (SELECT 1 FROM json_each(${rootColumn})`)\n })\n})\n"],"names":["describe","expect","it","createJSONQuery","rootColumn","column","operator","pathSegments","value","toContain"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,eAAe,QAAQ,aAAY;AAE5CH,SAAS,mBAAmB;IAC1BE,GAAG,oEAAoE;QACrE,MAAME,aAAa;QAEnBH,OACEE,gBAAgB;YACdE,QAAQD;YACRE,UAAU;YACVC,cAAc;gBAAC;aAAO;YACtBC,OAAO;QACT,IACAC,SAAS,CAAC,CAAC,UAAU,EAAEL,WAAW,CAAC,CAAC;IACxC;IAEAF,GAAG,kEAAkE;QACnE,MAAME,aAAa;QAEnBH,OACEE,gBAAgB;YACdE,QAAQD;YACRE,UAAU;YACVC,cAAc;gBAAC;aAAO;YACtBC,OAAO;QACT,IACAC,SAAS,CAAC,CAAC,oCAAoC,EAAEL,WAAW,CAAC,CAAC;IAClE;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"traverseFields.d.ts","sourceRoot":"","sources":["../../../src/transform/write/traverseFields.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,SAAS,CAAA;AAIvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,WAAW,EACX,YAAY,EACb,MAAM,YAAY,CAAA;AAWnB,KAAK,IAAI,GAAG;IACV,OAAO,EAAE,cAAc,CAAA;IACvB;;OAEG;IACH,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;IAC7B;;;OAGG;IACH,YAAY,EAAE,WAAW,CAAC,cAAc,CAAC,CAAA;IACzC;;OAEG;IACH,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;IAC7B,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC3B;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IAC3C;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,OAAO,EAAE;QACP,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAC1C,CAAA;IACD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IAClC,eAAe,EAAE,cAAc,EAAE,CAAA;IACjC,iBAAiB,EAAE,OAAO,CAAA;IAC1B;;OAEG;IACH,eAAe,EAAE,MAAM,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IACxC,qBAAqB,EAAE,oBAAoB,EAAE,CAAA;IAC7C,qBAAqB,EAAE,oBAAoB,EAAE,CAAA;IAC7C,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC5B,OAAO,EAAE;QACP,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;KAC/C,CAAA;IACD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IAChC,aAAa,EAAE,YAAY,EAAE,CAAA;IAC7B;;;OAGG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAA;CAClC,CAAA;AAED,eAAO,MAAM,cAAc,sYA6BxB,IAAI,SAmvBN,CAAA"}
1
+ {"version":3,"file":"traverseFields.d.ts","sourceRoot":"","sources":["../../../src/transform/write/traverseFields.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,SAAS,CAAA;AAIvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,WAAW,EACX,YAAY,EACb,MAAM,YAAY,CAAA;AAWnB,KAAK,IAAI,GAAG;IACV,OAAO,EAAE,cAAc,CAAA;IACvB;;OAEG;IACH,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;IAC7B;;;OAGG;IACH,YAAY,EAAE,WAAW,CAAC,cAAc,CAAC,CAAA;IACzC;;OAEG;IACH,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;IAC7B,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC3B;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IAC3C;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,OAAO,EAAE;QACP,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAC1C,CAAA;IACD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IAClC,eAAe,EAAE,cAAc,EAAE,CAAA;IACjC,iBAAiB,EAAE,OAAO,CAAA;IAC1B;;OAEG;IACH,eAAe,EAAE,MAAM,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IACxC,qBAAqB,EAAE,oBAAoB,EAAE,CAAA;IAC7C,qBAAqB,EAAE,oBAAoB,EAAE,CAAA;IAC7C,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC5B,OAAO,EAAE;QACP,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;KAC/C,CAAA;IACD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IAChC,aAAa,EAAE,YAAY,EAAE,CAAA;IAC7B;;;OAGG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAA;CAClC,CAAA;AAED,eAAO,MAAM,cAAc,sYA6BxB,IAAI,SAuuBN,CAAA"}
@@ -1,6 +1,6 @@
1
1
  import { sql } from 'drizzle-orm';
2
2
  import { APIError } from 'payload';
3
- import { fieldIsVirtual, fieldShouldBeLocalized } from 'payload/shared';
3
+ import { expandOwnDottedKey, fieldIsVirtual, fieldShouldBeLocalized } from 'payload/shared';
4
4
  import toSnakeCase from 'to-snake-case';
5
5
  import { isArrayOfRows } from '../../utilities/isArrayOfRows.js';
6
6
  import { resolveBlockTableName } from '../../utilities/validateExistingBlockIsIdentical.js';
@@ -510,6 +510,9 @@ export const traverseFields = ({ adapter, arrays, arraysToPush, baseTableName, b
510
510
  return;
511
511
  }
512
512
  if (field.type === 'select' && field.hasMany) {
513
+ if (fieldData === undefined) {
514
+ return;
515
+ }
513
516
  const selectTableName = adapter.tableNameMap.get(`${parentTableName}_${columnName}`);
514
517
  if (!selects[selectTableName]) {
515
518
  selects[selectTableName] = [];
@@ -608,19 +611,10 @@ export const traverseFields = ({ adapter, arrays, arraysToPush, baseTableName, b
608
611
  // Handle dot-notation paths when no fields matched
609
612
  if (!fieldsMatched) {
610
613
  Object.keys(data).forEach((key)=>{
611
- if (key.includes('.')) {
612
- // Split on first dot only
613
- const firstDotIndex = key.indexOf('.');
614
- const fieldName = key.substring(0, firstDotIndex);
615
- const remainingPath = key.substring(firstDotIndex + 1);
616
- // Create nested structure for this field
617
- if (!data[fieldName]) {
618
- data[fieldName] = {};
619
- }
620
- const nestedData = data[fieldName];
621
- // Move the value to the nested structure
622
- nestedData[remainingPath] = data[key];
623
- delete data[key];
614
+ if (expandOwnDottedKey({
615
+ key,
616
+ target: data
617
+ })) {
624
618
  // Recursively process the newly created nested structure
625
619
  // The field traversal will naturally handle it if the field exists in the schema
626
620
  traverseFields({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/transform/write/traverseFields.ts"],"sourcesContent":["import { sql } from 'drizzle-orm'\nimport { APIError, type FlattenedField } from 'payload'\nimport { fieldIsVirtual, fieldShouldBeLocalized } from 'payload/shared'\nimport toSnakeCase from 'to-snake-case'\n\nimport type { DrizzleAdapter } from '../../types.js'\nimport type {\n NumberToDelete,\n RelationshipToAppend,\n RelationshipToDelete,\n RowToInsert,\n TextToDelete,\n} from './types.js'\n\nimport { isArrayOfRows } from '../../utilities/isArrayOfRows.js'\nimport { resolveBlockTableName } from '../../utilities/validateExistingBlockIsIdentical.js'\nimport { transformArray } from './array.js'\nimport { transformBlocks } from './blocks.js'\nimport { transformNumbers } from './numbers.js'\nimport { transformRelationship } from './relationships.js'\nimport { transformSelects } from './selects.js'\nimport { transformTexts } from './texts.js'\n\ntype Args = {\n adapter: DrizzleAdapter\n /**\n * This will delete the array table and then re-insert all the new array rows.\n */\n arrays: RowToInsert['arrays']\n /**\n * Array rows to push to the existing array. This will simply create\n * a new row in the array table.\n */\n arraysToPush: RowToInsert['arraysToPush']\n /**\n * This is the name of the base table\n */\n baseTableName: string\n blocks: RowToInsert['blocks']\n blocksToDelete: Set<string>\n /**\n * A snake-case field prefix, representing prior fields\n * Ex: my_group_my_named_tab_\n */\n columnPrefix: string\n data: Record<string, unknown>\n enableAtomicWrites?: boolean\n existingLocales?: Record<string, unknown>[]\n /**\n * A prefix that will retain camel-case formatting, representing prior fields\n * Ex: myGroup_myNamedTab_\n */\n fieldPrefix: string\n fields: FlattenedField[]\n forcedLocale?: string\n /**\n * Tracks whether the current traversion context is from array or block.\n */\n insideArrayOrBlock?: boolean\n locales: {\n [locale: string]: Record<string, unknown>\n }\n numbers: Record<string, unknown>[]\n numbersToDelete: NumberToDelete[]\n parentIsLocalized: boolean\n /**\n * This is the name of the parent table\n */\n parentTableName: string\n path: string\n relationships: Record<string, unknown>[]\n relationshipsToAppend: RelationshipToAppend[]\n relationshipsToDelete: RelationshipToDelete[]\n row: Record<string, unknown>\n selects: {\n [tableName: string]: Record<string, unknown>[]\n }\n texts: Record<string, unknown>[]\n textsToDelete: TextToDelete[]\n /**\n * Set to a locale code if this set of fields is traversed within a\n * localized array or block field\n */\n withinArrayOrBlockLocale?: string\n}\n\nexport const traverseFields = ({\n adapter,\n arrays,\n arraysToPush,\n baseTableName,\n blocks,\n blocksToDelete,\n columnPrefix,\n data,\n enableAtomicWrites,\n existingLocales,\n fieldPrefix,\n fields,\n forcedLocale,\n insideArrayOrBlock = false,\n locales,\n numbers,\n numbersToDelete,\n parentIsLocalized,\n parentTableName,\n path,\n relationships,\n relationshipsToAppend,\n relationshipsToDelete,\n row,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale,\n}: Args) => {\n let fieldsMatched = false\n\n if (row._uuid) {\n data._uuid = row._uuid\n }\n\n fields.forEach((field) => {\n let columnName = ''\n let fieldName = ''\n let fieldData: unknown\n\n if (fieldIsVirtual(field)) {\n return\n }\n\n // Mark that we found a matching field\n if (data[field.name] !== undefined) {\n fieldsMatched = true\n }\n\n columnName = `${columnPrefix || ''}${toSnakeCase(field.name)}`\n fieldName = `${fieldPrefix || ''}${field.name}`\n fieldData = data[field.name]\n\n const isLocalized = fieldShouldBeLocalized({ field, parentIsLocalized })\n\n if (field.type === 'array') {\n const arrayTableName = adapter.tableNameMap.get(`${parentTableName}_${columnName}`)\n\n if (isLocalized) {\n const value = data[field.name]\n\n if (typeof value === 'object' && value !== null) {\n Object.entries(value).forEach(([localeKey, localeValue]) => {\n let localeData = localeValue\n let push = false\n\n if (localeValue && typeof localeValue === 'object' && '$push' in localeValue) {\n localeData = localeValue.$push\n push = true\n if (!Array.isArray(localeData)) {\n localeData = [localeData]\n }\n }\n\n if (Array.isArray(localeData)) {\n const newRows = transformArray({\n adapter,\n arrayTableName,\n baseTableName,\n blocks,\n blocksToDelete,\n data: localeData,\n field,\n locale: localeKey,\n numbers,\n numbersToDelete,\n parentIsLocalized: parentIsLocalized || field.localized,\n path,\n relationships,\n relationshipsToDelete,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale: localeKey,\n })\n\n if (push) {\n if (!arraysToPush[arrayTableName]) {\n arraysToPush[arrayTableName] = []\n }\n arraysToPush[arrayTableName] = arraysToPush[arrayTableName].concat(newRows)\n } else {\n if (!arrays[arrayTableName]) {\n arrays[arrayTableName] = []\n }\n arrays[arrayTableName] = arrays[arrayTableName].concat(newRows)\n }\n }\n })\n }\n } else {\n let value = data[field.name]\n let push = false\n if (typeof value === 'object' && '$push' in value) {\n value = Array.isArray(value.$push) ? value.$push : [value.$push]\n push = true\n }\n\n const newRows = transformArray({\n adapter,\n arrayTableName,\n baseTableName,\n blocks,\n blocksToDelete,\n data: value,\n field,\n numbers,\n numbersToDelete,\n parentIsLocalized: parentIsLocalized || field.localized,\n path,\n relationships,\n relationshipsToDelete,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale,\n })\n\n if (push) {\n if (!arraysToPush[arrayTableName]) {\n arraysToPush[arrayTableName] = []\n }\n arraysToPush[arrayTableName] = arraysToPush[arrayTableName].concat(newRows)\n } else {\n if (!arrays[arrayTableName]) {\n arrays[arrayTableName] = []\n }\n arrays[arrayTableName] = arrays[arrayTableName].concat(newRows)\n }\n }\n\n return\n }\n\n if (field.type === 'blocks' && !adapter.blocksAsJSON) {\n ;(field.blockReferences ?? field.blocks).forEach((block) => {\n const matchedBlock =\n typeof block === 'string'\n ? adapter.payload.config.blocks.find((each) => each.slug === block)\n : block\n\n blocksToDelete.add(\n resolveBlockTableName(\n matchedBlock,\n adapter.tableNameMap.get(`${baseTableName}_blocks_${toSnakeCase(matchedBlock.slug)}`),\n ),\n )\n })\n\n if (isLocalized) {\n if (typeof data[field.name] === 'object' && data[field.name] !== null) {\n Object.entries(data[field.name]).forEach(([localeKey, localeData]) => {\n if (Array.isArray(localeData)) {\n transformBlocks({\n adapter,\n baseTableName,\n blocks,\n blocksToDelete,\n data: localeData,\n field,\n locale: localeKey,\n numbers,\n numbersToDelete,\n parentIsLocalized: parentIsLocalized || field.localized,\n path,\n relationships,\n relationshipsToDelete,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale: localeKey,\n })\n }\n })\n }\n } else if (isArrayOfRows(fieldData)) {\n transformBlocks({\n adapter,\n baseTableName,\n blocks,\n blocksToDelete,\n data: fieldData,\n field,\n numbers,\n numbersToDelete,\n parentIsLocalized: parentIsLocalized || field.localized,\n path,\n relationships,\n relationshipsToDelete,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale,\n })\n }\n\n return\n }\n\n if (field.type === 'group' || field.type === 'tab') {\n if (typeof data[field.name] === 'object' && data[field.name] !== null) {\n if (isLocalized) {\n Object.entries(data[field.name]).forEach(([localeKey, localeData]) => {\n // preserve array ID if there is\n localeData._uuid = data.id || data._uuid\n\n traverseFields({\n adapter,\n arrays,\n arraysToPush,\n baseTableName,\n blocks,\n blocksToDelete,\n columnPrefix: `${columnName}_`,\n data: localeData as Record<string, unknown>,\n enableAtomicWrites,\n existingLocales,\n fieldPrefix: `${fieldName}_`,\n fields: field.flattenedFields,\n forcedLocale: localeKey,\n insideArrayOrBlock,\n locales,\n numbers,\n numbersToDelete,\n parentIsLocalized: parentIsLocalized || field.localized,\n parentTableName,\n path: `${path || ''}${field.name}.`,\n relationships,\n relationshipsToAppend,\n relationshipsToDelete,\n row,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale: localeKey,\n })\n })\n } else {\n // preserve array ID if there is\n const groupData = data[field.name] as Record<string, unknown>\n groupData._uuid = data.id || data._uuid\n\n traverseFields({\n adapter,\n arrays,\n arraysToPush,\n baseTableName,\n blocks,\n blocksToDelete,\n columnPrefix: `${columnName}_`,\n data: groupData,\n enableAtomicWrites,\n existingLocales,\n fieldPrefix: `${fieldName}_`,\n fields: field.flattenedFields,\n forcedLocale,\n insideArrayOrBlock,\n locales,\n numbers,\n numbersToDelete,\n parentIsLocalized: parentIsLocalized || field.localized,\n parentTableName,\n path: `${path || ''}${field.name}.`,\n relationships,\n relationshipsToAppend,\n relationshipsToDelete,\n row,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale,\n })\n }\n }\n\n return\n }\n\n if (field.type === 'relationship' || field.type === 'upload') {\n const relationshipPath = `${path || ''}${field.name}`\n\n // Handle $push operation for relationship fields\n if (\n fieldData &&\n typeof fieldData === 'object' &&\n 'hasMany' in field &&\n field.hasMany &&\n ('$push' in fieldData ||\n (field.localized &&\n Object.values(fieldData).some(\n (localeValue) =>\n localeValue &&\n typeof localeValue === 'object' &&\n '$push' in (localeValue as Record<string, unknown>),\n )))\n ) {\n let itemsToAppend: unknown[]\n\n if (field.localized) {\n let hasLocaleOperations = false\n Object.entries(fieldData).forEach(([localeKey, localeValue]) => {\n if (localeValue && typeof localeValue === 'object' && '$push' in localeValue) {\n hasLocaleOperations = true\n const push = localeValue.$push\n const localeItems = Array.isArray(push) ? push : [push]\n\n localeItems.forEach((item) => {\n const relationshipToAppend: RelationshipToAppend = {\n locale: localeKey,\n path: relationshipPath,\n value: item,\n }\n\n // Handle polymorphic relationships\n if (\n Array.isArray(field.relationTo) &&\n item &&\n typeof item === 'object' &&\n 'relationTo' in item\n ) {\n relationshipToAppend.relationTo = item.relationTo\n relationshipToAppend.value = item.value\n } else if (typeof field.relationTo === 'string') {\n // Simple relationship\n relationshipToAppend.relationTo = field.relationTo\n relationshipToAppend.value = item\n }\n\n relationshipsToAppend.push(relationshipToAppend)\n })\n }\n })\n\n if (hasLocaleOperations) {\n return\n }\n } else {\n // Handle non-localized fields: { field: { $push: data } }\n itemsToAppend = Array.isArray((fieldData as any).$push)\n ? (fieldData as any).$push\n : [(fieldData as any).$push]\n\n itemsToAppend.forEach((item) => {\n const relationshipToAppend: RelationshipToAppend = {\n locale: isLocalized ? withinArrayOrBlockLocale : undefined,\n path: relationshipPath,\n value: item,\n }\n\n // Handle polymorphic relationships\n if (\n Array.isArray(field.relationTo) &&\n item &&\n typeof item === 'object' &&\n 'relationTo' in item &&\n 'value' in item\n ) {\n relationshipToAppend.relationTo = item.relationTo as string\n relationshipToAppend.value = item.value as number | string\n } else if (typeof field.relationTo === 'string') {\n // Simple relationship\n relationshipToAppend.relationTo = field.relationTo\n relationshipToAppend.value = item\n }\n\n relationshipsToAppend.push(relationshipToAppend)\n })\n }\n return\n }\n\n // Handle $remove operation for relationship fields\n if (\n fieldData &&\n typeof fieldData === 'object' &&\n 'hasMany' in field &&\n field.hasMany &&\n ('$remove' in fieldData ||\n (field.localized &&\n Object.values(fieldData).some(\n (localeValue) =>\n localeValue &&\n typeof localeValue === 'object' &&\n '$remove' in (localeValue as Record<string, unknown>),\n )))\n ) {\n // Check for new locale-first syntax: { field: { locale: { $remove: data } } }\n if (field.localized) {\n let hasLocaleOperations = false\n Object.entries(fieldData).forEach(([localeKey, localeValue]) => {\n if (localeValue && typeof localeValue === 'object' && '$remove' in localeValue) {\n hasLocaleOperations = true\n const remove = localeValue.$remove\n const localeItems = Array.isArray(remove) ? remove : [remove]\n\n localeItems.forEach((item) => {\n const relationshipToDelete: RelationshipToDelete = {\n itemToRemove: item,\n locale: localeKey,\n path: relationshipPath,\n }\n\n // Store relationTo for simple relationships\n if (typeof field.relationTo === 'string') {\n relationshipToDelete.relationTo = field.relationTo\n }\n\n relationshipsToDelete.push(relationshipToDelete)\n })\n }\n })\n\n if (hasLocaleOperations) {\n return\n }\n } else {\n // Handle non-localized fields: { field: { $remove: data } }\n const itemsToRemove = Array.isArray((fieldData as any).$remove)\n ? (fieldData as any).$remove\n : [(fieldData as any).$remove]\n\n itemsToRemove.forEach((item) => {\n const relationshipToDelete: RelationshipToDelete = {\n itemToRemove: item,\n locale: isLocalized ? withinArrayOrBlockLocale : undefined,\n path: relationshipPath,\n }\n\n // Store relationTo for simple relationships\n if (typeof field.relationTo === 'string') {\n relationshipToDelete.relationTo = field.relationTo\n }\n\n relationshipsToDelete.push(relationshipToDelete)\n })\n }\n return\n }\n\n if (\n isLocalized &&\n (Array.isArray(field.relationTo) || ('hasMany' in field && field.hasMany))\n ) {\n if (typeof fieldData === 'object') {\n Object.entries(fieldData).forEach(([localeKey, localeData]) => {\n if (localeData === null) {\n relationshipsToDelete.push({\n locale: localeKey,\n path: relationshipPath,\n })\n return\n }\n\n transformRelationship({\n baseRow: {\n locale: localeKey,\n path: relationshipPath,\n },\n data: localeData,\n field,\n relationships,\n })\n })\n }\n return\n } else if (Array.isArray(field.relationTo) || ('hasMany' in field && field.hasMany)) {\n if (fieldData === null || (Array.isArray(fieldData) && fieldData.length === 0)) {\n relationshipsToDelete.push({ path: relationshipPath })\n return\n }\n\n transformRelationship({\n baseRow: {\n locale: withinArrayOrBlockLocale,\n path: relationshipPath,\n },\n data: fieldData,\n field,\n relationships,\n })\n return\n } else {\n if (\n !isLocalized &&\n fieldData &&\n typeof fieldData === 'object' &&\n 'id' in fieldData &&\n fieldData?.id\n ) {\n fieldData = fieldData.id\n } else if (isLocalized) {\n if (typeof fieldData === 'object') {\n Object.entries(fieldData).forEach(([localeKey, localeData]) => {\n if (typeof localeData === 'object') {\n if (localeData && 'id' in localeData && localeData?.id) {\n fieldData[localeKey] = localeData.id\n }\n } else {\n fieldData[localeKey] = localeData\n }\n })\n }\n }\n }\n }\n\n if (field.type === 'text' && field.hasMany) {\n const textPath = `${path || ''}${field.name}`\n\n if (isLocalized) {\n if (typeof fieldData === 'object') {\n Object.entries(fieldData).forEach(([localeKey, localeData]) => {\n if (Array.isArray(localeData)) {\n if (!localeData.length) {\n textsToDelete.push({ locale: localeKey, path: textPath })\n return\n }\n\n transformTexts({\n baseRow: {\n locale: localeKey,\n path: textPath,\n },\n data: localeData,\n texts,\n })\n }\n })\n }\n } else if (Array.isArray(fieldData)) {\n if (!fieldData.length) {\n textsToDelete.push({ locale: withinArrayOrBlockLocale, path: textPath })\n return\n }\n\n transformTexts({\n baseRow: {\n locale: withinArrayOrBlockLocale,\n path: textPath,\n },\n data: fieldData,\n texts,\n })\n }\n\n return\n }\n\n if (field.type === 'number' && field.hasMany) {\n const numberPath = `${path || ''}${field.name}`\n\n if (isLocalized) {\n if (typeof fieldData === 'object') {\n Object.entries(fieldData).forEach(([localeKey, localeData]) => {\n if (Array.isArray(localeData)) {\n if (!localeData.length) {\n numbersToDelete.push({ locale: localeKey, path: numberPath })\n return\n }\n\n transformNumbers({\n baseRow: {\n locale: localeKey,\n path: numberPath,\n },\n data: localeData,\n numbers,\n })\n }\n })\n }\n } else if (Array.isArray(fieldData)) {\n if (!fieldData.length) {\n numbersToDelete.push({ locale: withinArrayOrBlockLocale, path: numberPath })\n return\n }\n\n transformNumbers({\n baseRow: {\n locale: withinArrayOrBlockLocale,\n path: numberPath,\n },\n data: fieldData,\n numbers,\n })\n }\n\n return\n }\n\n if (field.type === 'select' && field.hasMany) {\n const selectTableName = adapter.tableNameMap.get(`${parentTableName}_${columnName}`)\n if (!selects[selectTableName]) {\n selects[selectTableName] = []\n }\n\n if (isLocalized) {\n if (typeof data[field.name] === 'object' && data[field.name] !== null) {\n Object.entries(data[field.name]).forEach(([localeKey, localeData]) => {\n if (Array.isArray(localeData)) {\n const newRows = transformSelects({\n id: insideArrayOrBlock ? data._uuid || data.id : undefined,\n data: localeData,\n locale: localeKey,\n })\n\n selects[selectTableName] = selects[selectTableName].concat(newRows)\n }\n })\n }\n } else if (Array.isArray(data[field.name])) {\n const newRows = transformSelects({\n id: insideArrayOrBlock ? data._uuid || data.id : undefined,\n data: data[field.name],\n locale: withinArrayOrBlockLocale,\n })\n\n selects[selectTableName] = selects[selectTableName].concat(newRows)\n }\n\n return\n }\n\n const valuesToTransform: { localeKey?: string; ref: unknown; value: unknown }[] = []\n\n if (isLocalized) {\n if (typeof fieldData === 'object' && fieldData !== null) {\n Object.entries(fieldData).forEach(([localeKey, localeData]) => {\n if (!locales[localeKey]) {\n locales[localeKey] = {}\n }\n\n valuesToTransform.push({\n localeKey,\n ref: locales,\n value: localeData,\n })\n })\n }\n } else {\n let ref = row\n\n if (forcedLocale) {\n if (!locales[forcedLocale]) {\n locales[forcedLocale] = {}\n }\n ref = locales[forcedLocale]\n }\n\n valuesToTransform.push({ ref, value: fieldData })\n }\n\n valuesToTransform.forEach(({ localeKey, ref, value }) => {\n let formattedValue = value\n\n if (field.type === 'date') {\n if (fieldName === 'updatedAt' && formattedValue === null) {\n // If updatedAt is explicitly set to null, skip it entirely - don't add to row\n // This prevents the timestamp from being updated for session-only operations\n return // Skip this iteration\n } else if (fieldName === 'updatedAt' && typeof formattedValue === 'undefined') {\n // If updatedAt is undefined, set it to current time (normal behavior)\n formattedValue = new Date().toISOString()\n } else {\n if (typeof value === 'number' && !Number.isNaN(value)) {\n formattedValue = new Date(value).toISOString()\n } else if (value instanceof Date) {\n formattedValue = value.toISOString()\n }\n }\n }\n\n if (typeof value !== 'undefined') {\n if (value && field.type === 'point' && adapter.name !== 'sqlite') {\n formattedValue = sql`ST_GeomFromGeoJSON(${JSON.stringify(value)})`\n }\n\n if (field.type === 'text' && value && typeof value !== 'string') {\n formattedValue = JSON.stringify(value)\n }\n\n if (\n field.type === 'number' &&\n value &&\n typeof value === 'object' &&\n '$inc' in value &&\n typeof value.$inc === 'number'\n ) {\n if (!enableAtomicWrites) {\n throw new APIError(\n 'The passed data must not contain any nested fields for atomic writes',\n )\n }\n\n formattedValue = sql.raw(`${columnName} + ${value.$inc}`)\n }\n }\n\n if (typeof formattedValue !== 'undefined') {\n if (localeKey) {\n ref[localeKey][fieldName] = formattedValue\n } else {\n ref[fieldName] = formattedValue\n }\n }\n })\n })\n\n // Handle dot-notation paths when no fields matched\n if (!fieldsMatched) {\n Object.keys(data).forEach((key) => {\n if (key.includes('.')) {\n // Split on first dot only\n const firstDotIndex = key.indexOf('.')\n const fieldName = key.substring(0, firstDotIndex)\n const remainingPath = key.substring(firstDotIndex + 1)\n\n // Create nested structure for this field\n if (!data[fieldName]) {\n data[fieldName] = {}\n }\n\n const nestedData = data[fieldName] as Record<string, unknown>\n\n // Move the value to the nested structure\n nestedData[remainingPath] = data[key]\n delete data[key]\n\n // Recursively process the newly created nested structure\n // The field traversal will naturally handle it if the field exists in the schema\n traverseFields({\n adapter,\n arrays,\n arraysToPush,\n baseTableName,\n blocks,\n blocksToDelete,\n columnPrefix,\n data,\n enableAtomicWrites,\n existingLocales,\n fieldPrefix,\n fields,\n forcedLocale,\n insideArrayOrBlock,\n locales,\n numbers,\n numbersToDelete,\n parentIsLocalized,\n parentTableName,\n path,\n relationships,\n relationshipsToAppend,\n relationshipsToDelete,\n row,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale,\n })\n }\n })\n }\n}\n"],"names":["sql","APIError","fieldIsVirtual","fieldShouldBeLocalized","toSnakeCase","isArrayOfRows","resolveBlockTableName","transformArray","transformBlocks","transformNumbers","transformRelationship","transformSelects","transformTexts","traverseFields","adapter","arrays","arraysToPush","baseTableName","blocks","blocksToDelete","columnPrefix","data","enableAtomicWrites","existingLocales","fieldPrefix","fields","forcedLocale","insideArrayOrBlock","locales","numbers","numbersToDelete","parentIsLocalized","parentTableName","path","relationships","relationshipsToAppend","relationshipsToDelete","row","selects","texts","textsToDelete","withinArrayOrBlockLocale","fieldsMatched","_uuid","forEach","field","columnName","fieldName","fieldData","name","undefined","isLocalized","type","arrayTableName","tableNameMap","get","value","Object","entries","localeKey","localeValue","localeData","push","$push","Array","isArray","newRows","locale","localized","concat","blocksAsJSON","blockReferences","block","matchedBlock","payload","config","find","each","slug","add","id","flattenedFields","groupData","relationshipPath","hasMany","values","some","itemsToAppend","hasLocaleOperations","localeItems","item","relationshipToAppend","relationTo","remove","$remove","relationshipToDelete","itemToRemove","itemsToRemove","baseRow","length","textPath","numberPath","selectTableName","valuesToTransform","ref","formattedValue","Date","toISOString","Number","isNaN","JSON","stringify","$inc","raw","keys","key","includes","firstDotIndex","indexOf","substring","remainingPath","nestedData"],"mappings":"AAAA,SAASA,GAAG,QAAQ,cAAa;AACjC,SAASC,QAAQ,QAA6B,UAAS;AACvD,SAASC,cAAc,EAAEC,sBAAsB,QAAQ,iBAAgB;AACvE,OAAOC,iBAAiB,gBAAe;AAWvC,SAASC,aAAa,QAAQ,mCAAkC;AAChE,SAASC,qBAAqB,QAAQ,sDAAqD;AAC3F,SAASC,cAAc,QAAQ,aAAY;AAC3C,SAASC,eAAe,QAAQ,cAAa;AAC7C,SAASC,gBAAgB,QAAQ,eAAc;AAC/C,SAASC,qBAAqB,QAAQ,qBAAoB;AAC1D,SAASC,gBAAgB,QAAQ,eAAc;AAC/C,SAASC,cAAc,QAAQ,aAAY;AAiE3C,OAAO,MAAMC,iBAAiB,CAAC,EAC7BC,OAAO,EACPC,MAAM,EACNC,YAAY,EACZC,aAAa,EACbC,MAAM,EACNC,cAAc,EACdC,YAAY,EACZC,IAAI,EACJC,kBAAkB,EAClBC,eAAe,EACfC,WAAW,EACXC,MAAM,EACNC,YAAY,EACZC,qBAAqB,KAAK,EAC1BC,OAAO,EACPC,OAAO,EACPC,eAAe,EACfC,iBAAiB,EACjBC,eAAe,EACfC,IAAI,EACJC,aAAa,EACbC,qBAAqB,EACrBC,qBAAqB,EACrBC,GAAG,EACHC,OAAO,EACPC,KAAK,EACLC,aAAa,EACbC,wBAAwB,EACnB;IACL,IAAIC,gBAAgB;IAEpB,IAAIL,IAAIM,KAAK,EAAE;QACbtB,KAAKsB,KAAK,GAAGN,IAAIM,KAAK;IACxB;IAEAlB,OAAOmB,OAAO,CAAC,CAACC;QACd,IAAIC,aAAa;QACjB,IAAIC,YAAY;QAChB,IAAIC;QAEJ,IAAI9C,eAAe2C,QAAQ;YACzB;QACF;QAEA,sCAAsC;QACtC,IAAIxB,IAAI,CAACwB,MAAMI,IAAI,CAAC,KAAKC,WAAW;YAClCR,gBAAgB;QAClB;QAEAI,aAAa,GAAG1B,gBAAgB,KAAKhB,YAAYyC,MAAMI,IAAI,GAAG;QAC9DF,YAAY,GAAGvB,eAAe,KAAKqB,MAAMI,IAAI,EAAE;QAC/CD,YAAY3B,IAAI,CAACwB,MAAMI,IAAI,CAAC;QAE5B,MAAME,cAAchD,uBAAuB;YAAE0C;YAAOd;QAAkB;QAEtE,IAAIc,MAAMO,IAAI,KAAK,SAAS;YAC1B,MAAMC,iBAAiBvC,QAAQwC,YAAY,CAACC,GAAG,CAAC,GAAGvB,gBAAgB,CAAC,EAAEc,YAAY;YAElF,IAAIK,aAAa;gBACf,MAAMK,QAAQnC,IAAI,CAACwB,MAAMI,IAAI,CAAC;gBAE9B,IAAI,OAAOO,UAAU,YAAYA,UAAU,MAAM;oBAC/CC,OAAOC,OAAO,CAACF,OAAOZ,OAAO,CAAC,CAAC,CAACe,WAAWC,YAAY;wBACrD,IAAIC,aAAaD;wBACjB,IAAIE,OAAO;wBAEX,IAAIF,eAAe,OAAOA,gBAAgB,YAAY,WAAWA,aAAa;4BAC5EC,aAAaD,YAAYG,KAAK;4BAC9BD,OAAO;4BACP,IAAI,CAACE,MAAMC,OAAO,CAACJ,aAAa;gCAC9BA,aAAa;oCAACA;iCAAW;4BAC3B;wBACF;wBAEA,IAAIG,MAAMC,OAAO,CAACJ,aAAa;4BAC7B,MAAMK,UAAU3D,eAAe;gCAC7BO;gCACAuC;gCACApC;gCACAC;gCACAC;gCACAE,MAAMwC;gCACNhB;gCACAsB,QAAQR;gCACR9B;gCACAC;gCACAC,mBAAmBA,qBAAqBc,MAAMuB,SAAS;gCACvDnC;gCACAC;gCACAE;gCACAE;gCACAC;gCACAC;gCACAC,0BAA0BkB;4BAC5B;4BAEA,IAAIG,MAAM;gCACR,IAAI,CAAC9C,YAAY,CAACqC,eAAe,EAAE;oCACjCrC,YAAY,CAACqC,eAAe,GAAG,EAAE;gCACnC;gCACArC,YAAY,CAACqC,eAAe,GAAGrC,YAAY,CAACqC,eAAe,CAACgB,MAAM,CAACH;4BACrE,OAAO;gCACL,IAAI,CAACnD,MAAM,CAACsC,eAAe,EAAE;oCAC3BtC,MAAM,CAACsC,eAAe,GAAG,EAAE;gCAC7B;gCACAtC,MAAM,CAACsC,eAAe,GAAGtC,MAAM,CAACsC,eAAe,CAACgB,MAAM,CAACH;4BACzD;wBACF;oBACF;gBACF;YACF,OAAO;gBACL,IAAIV,QAAQnC,IAAI,CAACwB,MAAMI,IAAI,CAAC;gBAC5B,IAAIa,OAAO;gBACX,IAAI,OAAON,UAAU,YAAY,WAAWA,OAAO;oBACjDA,QAAQQ,MAAMC,OAAO,CAACT,MAAMO,KAAK,IAAIP,MAAMO,KAAK,GAAG;wBAACP,MAAMO,KAAK;qBAAC;oBAChED,OAAO;gBACT;gBAEA,MAAMI,UAAU3D,eAAe;oBAC7BO;oBACAuC;oBACApC;oBACAC;oBACAC;oBACAE,MAAMmC;oBACNX;oBACAhB;oBACAC;oBACAC,mBAAmBA,qBAAqBc,MAAMuB,SAAS;oBACvDnC;oBACAC;oBACAE;oBACAE;oBACAC;oBACAC;oBACAC;gBACF;gBAEA,IAAIqB,MAAM;oBACR,IAAI,CAAC9C,YAAY,CAACqC,eAAe,EAAE;wBACjCrC,YAAY,CAACqC,eAAe,GAAG,EAAE;oBACnC;oBACArC,YAAY,CAACqC,eAAe,GAAGrC,YAAY,CAACqC,eAAe,CAACgB,MAAM,CAACH;gBACrE,OAAO;oBACL,IAAI,CAACnD,MAAM,CAACsC,eAAe,EAAE;wBAC3BtC,MAAM,CAACsC,eAAe,GAAG,EAAE;oBAC7B;oBACAtC,MAAM,CAACsC,eAAe,GAAGtC,MAAM,CAACsC,eAAe,CAACgB,MAAM,CAACH;gBACzD;YACF;YAEA;QACF;QAEA,IAAIrB,MAAMO,IAAI,KAAK,YAAY,CAACtC,QAAQwD,YAAY,EAAE;;YAClDzB,CAAAA,MAAM0B,eAAe,IAAI1B,MAAM3B,MAAM,AAAD,EAAG0B,OAAO,CAAC,CAAC4B;gBAChD,MAAMC,eACJ,OAAOD,UAAU,WACb1D,QAAQ4D,OAAO,CAACC,MAAM,CAACzD,MAAM,CAAC0D,IAAI,CAAC,CAACC,OAASA,KAAKC,IAAI,KAAKN,SAC3DA;gBAENrD,eAAe4D,GAAG,CAChBzE,sBACEmE,cACA3D,QAAQwC,YAAY,CAACC,GAAG,CAAC,GAAGtC,cAAc,QAAQ,EAAEb,YAAYqE,aAAaK,IAAI,GAAG;YAG1F;YAEA,IAAI3B,aAAa;gBACf,IAAI,OAAO9B,IAAI,CAACwB,MAAMI,IAAI,CAAC,KAAK,YAAY5B,IAAI,CAACwB,MAAMI,IAAI,CAAC,KAAK,MAAM;oBACrEQ,OAAOC,OAAO,CAACrC,IAAI,CAACwB,MAAMI,IAAI,CAAC,EAAEL,OAAO,CAAC,CAAC,CAACe,WAAWE,WAAW;wBAC/D,IAAIG,MAAMC,OAAO,CAACJ,aAAa;4BAC7BrD,gBAAgB;gCACdM;gCACAG;gCACAC;gCACAC;gCACAE,MAAMwC;gCACNhB;gCACAsB,QAAQR;gCACR9B;gCACAC;gCACAC,mBAAmBA,qBAAqBc,MAAMuB,SAAS;gCACvDnC;gCACAC;gCACAE;gCACAE;gCACAC;gCACAC;gCACAC,0BAA0BkB;4BAC5B;wBACF;oBACF;gBACF;YACF,OAAO,IAAItD,cAAc2C,YAAY;gBACnCxC,gBAAgB;oBACdM;oBACAG;oBACAC;oBACAC;oBACAE,MAAM2B;oBACNH;oBACAhB;oBACAC;oBACAC,mBAAmBA,qBAAqBc,MAAMuB,SAAS;oBACvDnC;oBACAC;oBACAE;oBACAE;oBACAC;oBACAC;oBACAC;gBACF;YACF;YAEA;QACF;QAEA,IAAII,MAAMO,IAAI,KAAK,WAAWP,MAAMO,IAAI,KAAK,OAAO;YAClD,IAAI,OAAO/B,IAAI,CAACwB,MAAMI,IAAI,CAAC,KAAK,YAAY5B,IAAI,CAACwB,MAAMI,IAAI,CAAC,KAAK,MAAM;gBACrE,IAAIE,aAAa;oBACfM,OAAOC,OAAO,CAACrC,IAAI,CAACwB,MAAMI,IAAI,CAAC,EAAEL,OAAO,CAAC,CAAC,CAACe,WAAWE,WAAW;wBAC/D,gCAAgC;wBAChCA,WAAWlB,KAAK,GAAGtB,KAAK2D,EAAE,IAAI3D,KAAKsB,KAAK;wBAExC9B,eAAe;4BACbC;4BACAC;4BACAC;4BACAC;4BACAC;4BACAC;4BACAC,cAAc,GAAG0B,WAAW,CAAC,CAAC;4BAC9BzB,MAAMwC;4BACNvC;4BACAC;4BACAC,aAAa,GAAGuB,UAAU,CAAC,CAAC;4BAC5BtB,QAAQoB,MAAMoC,eAAe;4BAC7BvD,cAAciC;4BACdhC;4BACAC;4BACAC;4BACAC;4BACAC,mBAAmBA,qBAAqBc,MAAMuB,SAAS;4BACvDpC;4BACAC,MAAM,GAAGA,QAAQ,KAAKY,MAAMI,IAAI,CAAC,CAAC,CAAC;4BACnCf;4BACAC;4BACAC;4BACAC;4BACAC;4BACAC;4BACAC;4BACAC,0BAA0BkB;wBAC5B;oBACF;gBACF,OAAO;oBACL,gCAAgC;oBAChC,MAAMuB,YAAY7D,IAAI,CAACwB,MAAMI,IAAI,CAAC;oBAClCiC,UAAUvC,KAAK,GAAGtB,KAAK2D,EAAE,IAAI3D,KAAKsB,KAAK;oBAEvC9B,eAAe;wBACbC;wBACAC;wBACAC;wBACAC;wBACAC;wBACAC;wBACAC,cAAc,GAAG0B,WAAW,CAAC,CAAC;wBAC9BzB,MAAM6D;wBACN5D;wBACAC;wBACAC,aAAa,GAAGuB,UAAU,CAAC,CAAC;wBAC5BtB,QAAQoB,MAAMoC,eAAe;wBAC7BvD;wBACAC;wBACAC;wBACAC;wBACAC;wBACAC,mBAAmBA,qBAAqBc,MAAMuB,SAAS;wBACvDpC;wBACAC,MAAM,GAAGA,QAAQ,KAAKY,MAAMI,IAAI,CAAC,CAAC,CAAC;wBACnCf;wBACAC;wBACAC;wBACAC;wBACAC;wBACAC;wBACAC;wBACAC;oBACF;gBACF;YACF;YAEA;QACF;QAEA,IAAII,MAAMO,IAAI,KAAK,kBAAkBP,MAAMO,IAAI,KAAK,UAAU;YAC5D,MAAM+B,mBAAmB,GAAGlD,QAAQ,KAAKY,MAAMI,IAAI,EAAE;YAErD,iDAAiD;YACjD,IACED,aACA,OAAOA,cAAc,YACrB,aAAaH,SACbA,MAAMuC,OAAO,IACZ,CAAA,WAAWpC,aACTH,MAAMuB,SAAS,IACdX,OAAO4B,MAAM,CAACrC,WAAWsC,IAAI,CAC3B,CAAC1B,cACCA,eACA,OAAOA,gBAAgB,YACvB,WAAYA,YACf,GACL;gBACA,IAAI2B;gBAEJ,IAAI1C,MAAMuB,SAAS,EAAE;oBACnB,IAAIoB,sBAAsB;oBAC1B/B,OAAOC,OAAO,CAACV,WAAWJ,OAAO,CAAC,CAAC,CAACe,WAAWC,YAAY;wBACzD,IAAIA,eAAe,OAAOA,gBAAgB,YAAY,WAAWA,aAAa;4BAC5E4B,sBAAsB;4BACtB,MAAM1B,OAAOF,YAAYG,KAAK;4BAC9B,MAAM0B,cAAczB,MAAMC,OAAO,CAACH,QAAQA,OAAO;gCAACA;6BAAK;4BAEvD2B,YAAY7C,OAAO,CAAC,CAAC8C;gCACnB,MAAMC,uBAA6C;oCACjDxB,QAAQR;oCACR1B,MAAMkD;oCACN3B,OAAOkC;gCACT;gCAEA,mCAAmC;gCACnC,IACE1B,MAAMC,OAAO,CAACpB,MAAM+C,UAAU,KAC9BF,QACA,OAAOA,SAAS,YAChB,gBAAgBA,MAChB;oCACAC,qBAAqBC,UAAU,GAAGF,KAAKE,UAAU;oCACjDD,qBAAqBnC,KAAK,GAAGkC,KAAKlC,KAAK;gCACzC,OAAO,IAAI,OAAOX,MAAM+C,UAAU,KAAK,UAAU;oCAC/C,sBAAsB;oCACtBD,qBAAqBC,UAAU,GAAG/C,MAAM+C,UAAU;oCAClDD,qBAAqBnC,KAAK,GAAGkC;gCAC/B;gCAEAvD,sBAAsB2B,IAAI,CAAC6B;4BAC7B;wBACF;oBACF;oBAEA,IAAIH,qBAAqB;wBACvB;oBACF;gBACF,OAAO;oBACL,0DAA0D;oBAC1DD,gBAAgBvB,MAAMC,OAAO,CAAC,AAACjB,UAAkBe,KAAK,IAClD,AAACf,UAAkBe,KAAK,GACxB;wBAAEf,UAAkBe,KAAK;qBAAC;oBAE9BwB,cAAc3C,OAAO,CAAC,CAAC8C;wBACrB,MAAMC,uBAA6C;4BACjDxB,QAAQhB,cAAcV,2BAA2BS;4BACjDjB,MAAMkD;4BACN3B,OAAOkC;wBACT;wBAEA,mCAAmC;wBACnC,IACE1B,MAAMC,OAAO,CAACpB,MAAM+C,UAAU,KAC9BF,QACA,OAAOA,SAAS,YAChB,gBAAgBA,QAChB,WAAWA,MACX;4BACAC,qBAAqBC,UAAU,GAAGF,KAAKE,UAAU;4BACjDD,qBAAqBnC,KAAK,GAAGkC,KAAKlC,KAAK;wBACzC,OAAO,IAAI,OAAOX,MAAM+C,UAAU,KAAK,UAAU;4BAC/C,sBAAsB;4BACtBD,qBAAqBC,UAAU,GAAG/C,MAAM+C,UAAU;4BAClDD,qBAAqBnC,KAAK,GAAGkC;wBAC/B;wBAEAvD,sBAAsB2B,IAAI,CAAC6B;oBAC7B;gBACF;gBACA;YACF;YAEA,mDAAmD;YACnD,IACE3C,aACA,OAAOA,cAAc,YACrB,aAAaH,SACbA,MAAMuC,OAAO,IACZ,CAAA,aAAapC,aACXH,MAAMuB,SAAS,IACdX,OAAO4B,MAAM,CAACrC,WAAWsC,IAAI,CAC3B,CAAC1B,cACCA,eACA,OAAOA,gBAAgB,YACvB,aAAcA,YACjB,GACL;gBACA,8EAA8E;gBAC9E,IAAIf,MAAMuB,SAAS,EAAE;oBACnB,IAAIoB,sBAAsB;oBAC1B/B,OAAOC,OAAO,CAACV,WAAWJ,OAAO,CAAC,CAAC,CAACe,WAAWC,YAAY;wBACzD,IAAIA,eAAe,OAAOA,gBAAgB,YAAY,aAAaA,aAAa;4BAC9E4B,sBAAsB;4BACtB,MAAMK,SAASjC,YAAYkC,OAAO;4BAClC,MAAML,cAAczB,MAAMC,OAAO,CAAC4B,UAAUA,SAAS;gCAACA;6BAAO;4BAE7DJ,YAAY7C,OAAO,CAAC,CAAC8C;gCACnB,MAAMK,uBAA6C;oCACjDC,cAAcN;oCACdvB,QAAQR;oCACR1B,MAAMkD;gCACR;gCAEA,4CAA4C;gCAC5C,IAAI,OAAOtC,MAAM+C,UAAU,KAAK,UAAU;oCACxCG,qBAAqBH,UAAU,GAAG/C,MAAM+C,UAAU;gCACpD;gCAEAxD,sBAAsB0B,IAAI,CAACiC;4BAC7B;wBACF;oBACF;oBAEA,IAAIP,qBAAqB;wBACvB;oBACF;gBACF,OAAO;oBACL,4DAA4D;oBAC5D,MAAMS,gBAAgBjC,MAAMC,OAAO,CAAC,AAACjB,UAAkB8C,OAAO,IAC1D,AAAC9C,UAAkB8C,OAAO,GAC1B;wBAAE9C,UAAkB8C,OAAO;qBAAC;oBAEhCG,cAAcrD,OAAO,CAAC,CAAC8C;wBACrB,MAAMK,uBAA6C;4BACjDC,cAAcN;4BACdvB,QAAQhB,cAAcV,2BAA2BS;4BACjDjB,MAAMkD;wBACR;wBAEA,4CAA4C;wBAC5C,IAAI,OAAOtC,MAAM+C,UAAU,KAAK,UAAU;4BACxCG,qBAAqBH,UAAU,GAAG/C,MAAM+C,UAAU;wBACpD;wBAEAxD,sBAAsB0B,IAAI,CAACiC;oBAC7B;gBACF;gBACA;YACF;YAEA,IACE5C,eACCa,CAAAA,MAAMC,OAAO,CAACpB,MAAM+C,UAAU,KAAM,aAAa/C,SAASA,MAAMuC,OAAO,GACxE;gBACA,IAAI,OAAOpC,cAAc,UAAU;oBACjCS,OAAOC,OAAO,CAACV,WAAWJ,OAAO,CAAC,CAAC,CAACe,WAAWE,WAAW;wBACxD,IAAIA,eAAe,MAAM;4BACvBzB,sBAAsB0B,IAAI,CAAC;gCACzBK,QAAQR;gCACR1B,MAAMkD;4BACR;4BACA;wBACF;wBAEAzE,sBAAsB;4BACpBwF,SAAS;gCACP/B,QAAQR;gCACR1B,MAAMkD;4BACR;4BACA9D,MAAMwC;4BACNhB;4BACAX;wBACF;oBACF;gBACF;gBACA;YACF,OAAO,IAAI8B,MAAMC,OAAO,CAACpB,MAAM+C,UAAU,KAAM,aAAa/C,SAASA,MAAMuC,OAAO,EAAG;gBACnF,IAAIpC,cAAc,QAASgB,MAAMC,OAAO,CAACjB,cAAcA,UAAUmD,MAAM,KAAK,GAAI;oBAC9E/D,sBAAsB0B,IAAI,CAAC;wBAAE7B,MAAMkD;oBAAiB;oBACpD;gBACF;gBAEAzE,sBAAsB;oBACpBwF,SAAS;wBACP/B,QAAQ1B;wBACRR,MAAMkD;oBACR;oBACA9D,MAAM2B;oBACNH;oBACAX;gBACF;gBACA;YACF,OAAO;gBACL,IACE,CAACiB,eACDH,aACA,OAAOA,cAAc,YACrB,QAAQA,aACRA,WAAWgC,IACX;oBACAhC,YAAYA,UAAUgC,EAAE;gBAC1B,OAAO,IAAI7B,aAAa;oBACtB,IAAI,OAAOH,cAAc,UAAU;wBACjCS,OAAOC,OAAO,CAACV,WAAWJ,OAAO,CAAC,CAAC,CAACe,WAAWE,WAAW;4BACxD,IAAI,OAAOA,eAAe,UAAU;gCAClC,IAAIA,cAAc,QAAQA,cAAcA,YAAYmB,IAAI;oCACtDhC,SAAS,CAACW,UAAU,GAAGE,WAAWmB,EAAE;gCACtC;4BACF,OAAO;gCACLhC,SAAS,CAACW,UAAU,GAAGE;4BACzB;wBACF;oBACF;gBACF;YACF;QACF;QAEA,IAAIhB,MAAMO,IAAI,KAAK,UAAUP,MAAMuC,OAAO,EAAE;YAC1C,MAAMgB,WAAW,GAAGnE,QAAQ,KAAKY,MAAMI,IAAI,EAAE;YAE7C,IAAIE,aAAa;gBACf,IAAI,OAAOH,cAAc,UAAU;oBACjCS,OAAOC,OAAO,CAACV,WAAWJ,OAAO,CAAC,CAAC,CAACe,WAAWE,WAAW;wBACxD,IAAIG,MAAMC,OAAO,CAACJ,aAAa;4BAC7B,IAAI,CAACA,WAAWsC,MAAM,EAAE;gCACtB3D,cAAcsB,IAAI,CAAC;oCAAEK,QAAQR;oCAAW1B,MAAMmE;gCAAS;gCACvD;4BACF;4BAEAxF,eAAe;gCACbsF,SAAS;oCACP/B,QAAQR;oCACR1B,MAAMmE;gCACR;gCACA/E,MAAMwC;gCACNtB;4BACF;wBACF;oBACF;gBACF;YACF,OAAO,IAAIyB,MAAMC,OAAO,CAACjB,YAAY;gBACnC,IAAI,CAACA,UAAUmD,MAAM,EAAE;oBACrB3D,cAAcsB,IAAI,CAAC;wBAAEK,QAAQ1B;wBAA0BR,MAAMmE;oBAAS;oBACtE;gBACF;gBAEAxF,eAAe;oBACbsF,SAAS;wBACP/B,QAAQ1B;wBACRR,MAAMmE;oBACR;oBACA/E,MAAM2B;oBACNT;gBACF;YACF;YAEA;QACF;QAEA,IAAIM,MAAMO,IAAI,KAAK,YAAYP,MAAMuC,OAAO,EAAE;YAC5C,MAAMiB,aAAa,GAAGpE,QAAQ,KAAKY,MAAMI,IAAI,EAAE;YAE/C,IAAIE,aAAa;gBACf,IAAI,OAAOH,cAAc,UAAU;oBACjCS,OAAOC,OAAO,CAACV,WAAWJ,OAAO,CAAC,CAAC,CAACe,WAAWE,WAAW;wBACxD,IAAIG,MAAMC,OAAO,CAACJ,aAAa;4BAC7B,IAAI,CAACA,WAAWsC,MAAM,EAAE;gCACtBrE,gBAAgBgC,IAAI,CAAC;oCAAEK,QAAQR;oCAAW1B,MAAMoE;gCAAW;gCAC3D;4BACF;4BAEA5F,iBAAiB;gCACfyF,SAAS;oCACP/B,QAAQR;oCACR1B,MAAMoE;gCACR;gCACAhF,MAAMwC;gCACNhC;4BACF;wBACF;oBACF;gBACF;YACF,OAAO,IAAImC,MAAMC,OAAO,CAACjB,YAAY;gBACnC,IAAI,CAACA,UAAUmD,MAAM,EAAE;oBACrBrE,gBAAgBgC,IAAI,CAAC;wBAAEK,QAAQ1B;wBAA0BR,MAAMoE;oBAAW;oBAC1E;gBACF;gBAEA5F,iBAAiB;oBACfyF,SAAS;wBACP/B,QAAQ1B;wBACRR,MAAMoE;oBACR;oBACAhF,MAAM2B;oBACNnB;gBACF;YACF;YAEA;QACF;QAEA,IAAIgB,MAAMO,IAAI,KAAK,YAAYP,MAAMuC,OAAO,EAAE;YAC5C,MAAMkB,kBAAkBxF,QAAQwC,YAAY,CAACC,GAAG,CAAC,GAAGvB,gBAAgB,CAAC,EAAEc,YAAY;YACnF,IAAI,CAACR,OAAO,CAACgE,gBAAgB,EAAE;gBAC7BhE,OAAO,CAACgE,gBAAgB,GAAG,EAAE;YAC/B;YAEA,IAAInD,aAAa;gBACf,IAAI,OAAO9B,IAAI,CAACwB,MAAMI,IAAI,CAAC,KAAK,YAAY5B,IAAI,CAACwB,MAAMI,IAAI,CAAC,KAAK,MAAM;oBACrEQ,OAAOC,OAAO,CAACrC,IAAI,CAACwB,MAAMI,IAAI,CAAC,EAAEL,OAAO,CAAC,CAAC,CAACe,WAAWE,WAAW;wBAC/D,IAAIG,MAAMC,OAAO,CAACJ,aAAa;4BAC7B,MAAMK,UAAUvD,iBAAiB;gCAC/BqE,IAAIrD,qBAAqBN,KAAKsB,KAAK,IAAItB,KAAK2D,EAAE,GAAG9B;gCACjD7B,MAAMwC;gCACNM,QAAQR;4BACV;4BAEArB,OAAO,CAACgE,gBAAgB,GAAGhE,OAAO,CAACgE,gBAAgB,CAACjC,MAAM,CAACH;wBAC7D;oBACF;gBACF;YACF,OAAO,IAAIF,MAAMC,OAAO,CAAC5C,IAAI,CAACwB,MAAMI,IAAI,CAAC,GAAG;gBAC1C,MAAMiB,UAAUvD,iBAAiB;oBAC/BqE,IAAIrD,qBAAqBN,KAAKsB,KAAK,IAAItB,KAAK2D,EAAE,GAAG9B;oBACjD7B,MAAMA,IAAI,CAACwB,MAAMI,IAAI,CAAC;oBACtBkB,QAAQ1B;gBACV;gBAEAH,OAAO,CAACgE,gBAAgB,GAAGhE,OAAO,CAACgE,gBAAgB,CAACjC,MAAM,CAACH;YAC7D;YAEA;QACF;QAEA,MAAMqC,oBAA4E,EAAE;QAEpF,IAAIpD,aAAa;YACf,IAAI,OAAOH,cAAc,YAAYA,cAAc,MAAM;gBACvDS,OAAOC,OAAO,CAACV,WAAWJ,OAAO,CAAC,CAAC,CAACe,WAAWE,WAAW;oBACxD,IAAI,CAACjC,OAAO,CAAC+B,UAAU,EAAE;wBACvB/B,OAAO,CAAC+B,UAAU,GAAG,CAAC;oBACxB;oBAEA4C,kBAAkBzC,IAAI,CAAC;wBACrBH;wBACA6C,KAAK5E;wBACL4B,OAAOK;oBACT;gBACF;YACF;QACF,OAAO;YACL,IAAI2C,MAAMnE;YAEV,IAAIX,cAAc;gBAChB,IAAI,CAACE,OAAO,CAACF,aAAa,EAAE;oBAC1BE,OAAO,CAACF,aAAa,GAAG,CAAC;gBAC3B;gBACA8E,MAAM5E,OAAO,CAACF,aAAa;YAC7B;YAEA6E,kBAAkBzC,IAAI,CAAC;gBAAE0C;gBAAKhD,OAAOR;YAAU;QACjD;QAEAuD,kBAAkB3D,OAAO,CAAC,CAAC,EAAEe,SAAS,EAAE6C,GAAG,EAAEhD,KAAK,EAAE;YAClD,IAAIiD,iBAAiBjD;YAErB,IAAIX,MAAMO,IAAI,KAAK,QAAQ;gBACzB,IAAIL,cAAc,eAAe0D,mBAAmB,MAAM;oBACxD,8EAA8E;oBAC9E,6EAA6E;oBAC7E,QAAO,sBAAsB;gBAC/B,OAAO,IAAI1D,cAAc,eAAe,OAAO0D,mBAAmB,aAAa;oBAC7E,sEAAsE;oBACtEA,iBAAiB,IAAIC,OAAOC,WAAW;gBACzC,OAAO;oBACL,IAAI,OAAOnD,UAAU,YAAY,CAACoD,OAAOC,KAAK,CAACrD,QAAQ;wBACrDiD,iBAAiB,IAAIC,KAAKlD,OAAOmD,WAAW;oBAC9C,OAAO,IAAInD,iBAAiBkD,MAAM;wBAChCD,iBAAiBjD,MAAMmD,WAAW;oBACpC;gBACF;YACF;YAEA,IAAI,OAAOnD,UAAU,aAAa;gBAChC,IAAIA,SAASX,MAAMO,IAAI,KAAK,WAAWtC,QAAQmC,IAAI,KAAK,UAAU;oBAChEwD,iBAAiBzG,GAAG,CAAC,mBAAmB,EAAE8G,KAAKC,SAAS,CAACvD,OAAO,CAAC,CAAC;gBACpE;gBAEA,IAAIX,MAAMO,IAAI,KAAK,UAAUI,SAAS,OAAOA,UAAU,UAAU;oBAC/DiD,iBAAiBK,KAAKC,SAAS,CAACvD;gBAClC;gBAEA,IACEX,MAAMO,IAAI,KAAK,YACfI,SACA,OAAOA,UAAU,YACjB,UAAUA,SACV,OAAOA,MAAMwD,IAAI,KAAK,UACtB;oBACA,IAAI,CAAC1F,oBAAoB;wBACvB,MAAM,IAAIrB,SACR;oBAEJ;oBAEAwG,iBAAiBzG,IAAIiH,GAAG,CAAC,GAAGnE,WAAW,GAAG,EAAEU,MAAMwD,IAAI,EAAE;gBAC1D;YACF;YAEA,IAAI,OAAOP,mBAAmB,aAAa;gBACzC,IAAI9C,WAAW;oBACb6C,GAAG,CAAC7C,UAAU,CAACZ,UAAU,GAAG0D;gBAC9B,OAAO;oBACLD,GAAG,CAACzD,UAAU,GAAG0D;gBACnB;YACF;QACF;IACF;IAEA,mDAAmD;IACnD,IAAI,CAAC/D,eAAe;QAClBe,OAAOyD,IAAI,CAAC7F,MAAMuB,OAAO,CAAC,CAACuE;YACzB,IAAIA,IAAIC,QAAQ,CAAC,MAAM;gBACrB,0BAA0B;gBAC1B,MAAMC,gBAAgBF,IAAIG,OAAO,CAAC;gBAClC,MAAMvE,YAAYoE,IAAII,SAAS,CAAC,GAAGF;gBACnC,MAAMG,gBAAgBL,IAAII,SAAS,CAACF,gBAAgB;gBAEpD,yCAAyC;gBACzC,IAAI,CAAChG,IAAI,CAAC0B,UAAU,EAAE;oBACpB1B,IAAI,CAAC0B,UAAU,GAAG,CAAC;gBACrB;gBAEA,MAAM0E,aAAapG,IAAI,CAAC0B,UAAU;gBAElC,yCAAyC;gBACzC0E,UAAU,CAACD,cAAc,GAAGnG,IAAI,CAAC8F,IAAI;gBACrC,OAAO9F,IAAI,CAAC8F,IAAI;gBAEhB,yDAAyD;gBACzD,iFAAiF;gBACjFtG,eAAe;oBACbC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;gBACF;YACF;QACF;IACF;AACF,EAAC"}
1
+ {"version":3,"sources":["../../../src/transform/write/traverseFields.ts"],"sourcesContent":["import { sql } from 'drizzle-orm'\nimport { APIError, type FlattenedField } from 'payload'\nimport { expandOwnDottedKey, fieldIsVirtual, fieldShouldBeLocalized } from 'payload/shared'\nimport toSnakeCase from 'to-snake-case'\n\nimport type { DrizzleAdapter } from '../../types.js'\nimport type {\n NumberToDelete,\n RelationshipToAppend,\n RelationshipToDelete,\n RowToInsert,\n TextToDelete,\n} from './types.js'\n\nimport { isArrayOfRows } from '../../utilities/isArrayOfRows.js'\nimport { resolveBlockTableName } from '../../utilities/validateExistingBlockIsIdentical.js'\nimport { transformArray } from './array.js'\nimport { transformBlocks } from './blocks.js'\nimport { transformNumbers } from './numbers.js'\nimport { transformRelationship } from './relationships.js'\nimport { transformSelects } from './selects.js'\nimport { transformTexts } from './texts.js'\n\ntype Args = {\n adapter: DrizzleAdapter\n /**\n * This will delete the array table and then re-insert all the new array rows.\n */\n arrays: RowToInsert['arrays']\n /**\n * Array rows to push to the existing array. This will simply create\n * a new row in the array table.\n */\n arraysToPush: RowToInsert['arraysToPush']\n /**\n * This is the name of the base table\n */\n baseTableName: string\n blocks: RowToInsert['blocks']\n blocksToDelete: Set<string>\n /**\n * A snake-case field prefix, representing prior fields\n * Ex: my_group_my_named_tab_\n */\n columnPrefix: string\n data: Record<string, unknown>\n enableAtomicWrites?: boolean\n existingLocales?: Record<string, unknown>[]\n /**\n * A prefix that will retain camel-case formatting, representing prior fields\n * Ex: myGroup_myNamedTab_\n */\n fieldPrefix: string\n fields: FlattenedField[]\n forcedLocale?: string\n /**\n * Tracks whether the current traversion context is from array or block.\n */\n insideArrayOrBlock?: boolean\n locales: {\n [locale: string]: Record<string, unknown>\n }\n numbers: Record<string, unknown>[]\n numbersToDelete: NumberToDelete[]\n parentIsLocalized: boolean\n /**\n * This is the name of the parent table\n */\n parentTableName: string\n path: string\n relationships: Record<string, unknown>[]\n relationshipsToAppend: RelationshipToAppend[]\n relationshipsToDelete: RelationshipToDelete[]\n row: Record<string, unknown>\n selects: {\n [tableName: string]: Record<string, unknown>[]\n }\n texts: Record<string, unknown>[]\n textsToDelete: TextToDelete[]\n /**\n * Set to a locale code if this set of fields is traversed within a\n * localized array or block field\n */\n withinArrayOrBlockLocale?: string\n}\n\nexport const traverseFields = ({\n adapter,\n arrays,\n arraysToPush,\n baseTableName,\n blocks,\n blocksToDelete,\n columnPrefix,\n data,\n enableAtomicWrites,\n existingLocales,\n fieldPrefix,\n fields,\n forcedLocale,\n insideArrayOrBlock = false,\n locales,\n numbers,\n numbersToDelete,\n parentIsLocalized,\n parentTableName,\n path,\n relationships,\n relationshipsToAppend,\n relationshipsToDelete,\n row,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale,\n}: Args) => {\n let fieldsMatched = false\n\n if (row._uuid) {\n data._uuid = row._uuid\n }\n\n fields.forEach((field) => {\n let columnName = ''\n let fieldName = ''\n let fieldData: unknown\n\n if (fieldIsVirtual(field)) {\n return\n }\n\n // Mark that we found a matching field\n if (data[field.name] !== undefined) {\n fieldsMatched = true\n }\n\n columnName = `${columnPrefix || ''}${toSnakeCase(field.name)}`\n fieldName = `${fieldPrefix || ''}${field.name}`\n fieldData = data[field.name]\n\n const isLocalized = fieldShouldBeLocalized({ field, parentIsLocalized })\n\n if (field.type === 'array') {\n const arrayTableName = adapter.tableNameMap.get(`${parentTableName}_${columnName}`)\n\n if (isLocalized) {\n const value = data[field.name]\n\n if (typeof value === 'object' && value !== null) {\n Object.entries(value).forEach(([localeKey, localeValue]) => {\n let localeData = localeValue\n let push = false\n\n if (localeValue && typeof localeValue === 'object' && '$push' in localeValue) {\n localeData = localeValue.$push\n push = true\n if (!Array.isArray(localeData)) {\n localeData = [localeData]\n }\n }\n\n if (Array.isArray(localeData)) {\n const newRows = transformArray({\n adapter,\n arrayTableName,\n baseTableName,\n blocks,\n blocksToDelete,\n data: localeData,\n field,\n locale: localeKey,\n numbers,\n numbersToDelete,\n parentIsLocalized: parentIsLocalized || field.localized,\n path,\n relationships,\n relationshipsToDelete,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale: localeKey,\n })\n\n if (push) {\n if (!arraysToPush[arrayTableName]) {\n arraysToPush[arrayTableName] = []\n }\n arraysToPush[arrayTableName] = arraysToPush[arrayTableName].concat(newRows)\n } else {\n if (!arrays[arrayTableName]) {\n arrays[arrayTableName] = []\n }\n arrays[arrayTableName] = arrays[arrayTableName].concat(newRows)\n }\n }\n })\n }\n } else {\n let value = data[field.name]\n let push = false\n if (typeof value === 'object' && '$push' in value) {\n value = Array.isArray(value.$push) ? value.$push : [value.$push]\n push = true\n }\n\n const newRows = transformArray({\n adapter,\n arrayTableName,\n baseTableName,\n blocks,\n blocksToDelete,\n data: value,\n field,\n numbers,\n numbersToDelete,\n parentIsLocalized: parentIsLocalized || field.localized,\n path,\n relationships,\n relationshipsToDelete,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale,\n })\n\n if (push) {\n if (!arraysToPush[arrayTableName]) {\n arraysToPush[arrayTableName] = []\n }\n arraysToPush[arrayTableName] = arraysToPush[arrayTableName].concat(newRows)\n } else {\n if (!arrays[arrayTableName]) {\n arrays[arrayTableName] = []\n }\n arrays[arrayTableName] = arrays[arrayTableName].concat(newRows)\n }\n }\n\n return\n }\n\n if (field.type === 'blocks' && !adapter.blocksAsJSON) {\n ;(field.blockReferences ?? field.blocks).forEach((block) => {\n const matchedBlock =\n typeof block === 'string'\n ? adapter.payload.config.blocks.find((each) => each.slug === block)\n : block\n\n blocksToDelete.add(\n resolveBlockTableName(\n matchedBlock,\n adapter.tableNameMap.get(`${baseTableName}_blocks_${toSnakeCase(matchedBlock.slug)}`),\n ),\n )\n })\n\n if (isLocalized) {\n if (typeof data[field.name] === 'object' && data[field.name] !== null) {\n Object.entries(data[field.name]).forEach(([localeKey, localeData]) => {\n if (Array.isArray(localeData)) {\n transformBlocks({\n adapter,\n baseTableName,\n blocks,\n blocksToDelete,\n data: localeData,\n field,\n locale: localeKey,\n numbers,\n numbersToDelete,\n parentIsLocalized: parentIsLocalized || field.localized,\n path,\n relationships,\n relationshipsToDelete,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale: localeKey,\n })\n }\n })\n }\n } else if (isArrayOfRows(fieldData)) {\n transformBlocks({\n adapter,\n baseTableName,\n blocks,\n blocksToDelete,\n data: fieldData,\n field,\n numbers,\n numbersToDelete,\n parentIsLocalized: parentIsLocalized || field.localized,\n path,\n relationships,\n relationshipsToDelete,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale,\n })\n }\n\n return\n }\n\n if (field.type === 'group' || field.type === 'tab') {\n if (typeof data[field.name] === 'object' && data[field.name] !== null) {\n if (isLocalized) {\n Object.entries(data[field.name]).forEach(([localeKey, localeData]) => {\n // preserve array ID if there is\n localeData._uuid = data.id || data._uuid\n\n traverseFields({\n adapter,\n arrays,\n arraysToPush,\n baseTableName,\n blocks,\n blocksToDelete,\n columnPrefix: `${columnName}_`,\n data: localeData as Record<string, unknown>,\n enableAtomicWrites,\n existingLocales,\n fieldPrefix: `${fieldName}_`,\n fields: field.flattenedFields,\n forcedLocale: localeKey,\n insideArrayOrBlock,\n locales,\n numbers,\n numbersToDelete,\n parentIsLocalized: parentIsLocalized || field.localized,\n parentTableName,\n path: `${path || ''}${field.name}.`,\n relationships,\n relationshipsToAppend,\n relationshipsToDelete,\n row,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale: localeKey,\n })\n })\n } else {\n // preserve array ID if there is\n const groupData = data[field.name] as Record<string, unknown>\n groupData._uuid = data.id || data._uuid\n\n traverseFields({\n adapter,\n arrays,\n arraysToPush,\n baseTableName,\n blocks,\n blocksToDelete,\n columnPrefix: `${columnName}_`,\n data: groupData,\n enableAtomicWrites,\n existingLocales,\n fieldPrefix: `${fieldName}_`,\n fields: field.flattenedFields,\n forcedLocale,\n insideArrayOrBlock,\n locales,\n numbers,\n numbersToDelete,\n parentIsLocalized: parentIsLocalized || field.localized,\n parentTableName,\n path: `${path || ''}${field.name}.`,\n relationships,\n relationshipsToAppend,\n relationshipsToDelete,\n row,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale,\n })\n }\n }\n\n return\n }\n\n if (field.type === 'relationship' || field.type === 'upload') {\n const relationshipPath = `${path || ''}${field.name}`\n\n // Handle $push operation for relationship fields\n if (\n fieldData &&\n typeof fieldData === 'object' &&\n 'hasMany' in field &&\n field.hasMany &&\n ('$push' in fieldData ||\n (field.localized &&\n Object.values(fieldData).some(\n (localeValue) =>\n localeValue &&\n typeof localeValue === 'object' &&\n '$push' in (localeValue as Record<string, unknown>),\n )))\n ) {\n let itemsToAppend: unknown[]\n\n if (field.localized) {\n let hasLocaleOperations = false\n Object.entries(fieldData).forEach(([localeKey, localeValue]) => {\n if (localeValue && typeof localeValue === 'object' && '$push' in localeValue) {\n hasLocaleOperations = true\n const push = localeValue.$push\n const localeItems = Array.isArray(push) ? push : [push]\n\n localeItems.forEach((item) => {\n const relationshipToAppend: RelationshipToAppend = {\n locale: localeKey,\n path: relationshipPath,\n value: item,\n }\n\n // Handle polymorphic relationships\n if (\n Array.isArray(field.relationTo) &&\n item &&\n typeof item === 'object' &&\n 'relationTo' in item\n ) {\n relationshipToAppend.relationTo = item.relationTo\n relationshipToAppend.value = item.value\n } else if (typeof field.relationTo === 'string') {\n // Simple relationship\n relationshipToAppend.relationTo = field.relationTo\n relationshipToAppend.value = item\n }\n\n relationshipsToAppend.push(relationshipToAppend)\n })\n }\n })\n\n if (hasLocaleOperations) {\n return\n }\n } else {\n // Handle non-localized fields: { field: { $push: data } }\n itemsToAppend = Array.isArray((fieldData as any).$push)\n ? (fieldData as any).$push\n : [(fieldData as any).$push]\n\n itemsToAppend.forEach((item) => {\n const relationshipToAppend: RelationshipToAppend = {\n locale: isLocalized ? withinArrayOrBlockLocale : undefined,\n path: relationshipPath,\n value: item,\n }\n\n // Handle polymorphic relationships\n if (\n Array.isArray(field.relationTo) &&\n item &&\n typeof item === 'object' &&\n 'relationTo' in item &&\n 'value' in item\n ) {\n relationshipToAppend.relationTo = item.relationTo as string\n relationshipToAppend.value = item.value as number | string\n } else if (typeof field.relationTo === 'string') {\n // Simple relationship\n relationshipToAppend.relationTo = field.relationTo\n relationshipToAppend.value = item\n }\n\n relationshipsToAppend.push(relationshipToAppend)\n })\n }\n return\n }\n\n // Handle $remove operation for relationship fields\n if (\n fieldData &&\n typeof fieldData === 'object' &&\n 'hasMany' in field &&\n field.hasMany &&\n ('$remove' in fieldData ||\n (field.localized &&\n Object.values(fieldData).some(\n (localeValue) =>\n localeValue &&\n typeof localeValue === 'object' &&\n '$remove' in (localeValue as Record<string, unknown>),\n )))\n ) {\n // Check for new locale-first syntax: { field: { locale: { $remove: data } } }\n if (field.localized) {\n let hasLocaleOperations = false\n Object.entries(fieldData).forEach(([localeKey, localeValue]) => {\n if (localeValue && typeof localeValue === 'object' && '$remove' in localeValue) {\n hasLocaleOperations = true\n const remove = localeValue.$remove\n const localeItems = Array.isArray(remove) ? remove : [remove]\n\n localeItems.forEach((item) => {\n const relationshipToDelete: RelationshipToDelete = {\n itemToRemove: item,\n locale: localeKey,\n path: relationshipPath,\n }\n\n // Store relationTo for simple relationships\n if (typeof field.relationTo === 'string') {\n relationshipToDelete.relationTo = field.relationTo\n }\n\n relationshipsToDelete.push(relationshipToDelete)\n })\n }\n })\n\n if (hasLocaleOperations) {\n return\n }\n } else {\n // Handle non-localized fields: { field: { $remove: data } }\n const itemsToRemove = Array.isArray((fieldData as any).$remove)\n ? (fieldData as any).$remove\n : [(fieldData as any).$remove]\n\n itemsToRemove.forEach((item) => {\n const relationshipToDelete: RelationshipToDelete = {\n itemToRemove: item,\n locale: isLocalized ? withinArrayOrBlockLocale : undefined,\n path: relationshipPath,\n }\n\n // Store relationTo for simple relationships\n if (typeof field.relationTo === 'string') {\n relationshipToDelete.relationTo = field.relationTo\n }\n\n relationshipsToDelete.push(relationshipToDelete)\n })\n }\n return\n }\n\n if (\n isLocalized &&\n (Array.isArray(field.relationTo) || ('hasMany' in field && field.hasMany))\n ) {\n if (typeof fieldData === 'object') {\n Object.entries(fieldData).forEach(([localeKey, localeData]) => {\n if (localeData === null) {\n relationshipsToDelete.push({\n locale: localeKey,\n path: relationshipPath,\n })\n return\n }\n\n transformRelationship({\n baseRow: {\n locale: localeKey,\n path: relationshipPath,\n },\n data: localeData,\n field,\n relationships,\n })\n })\n }\n return\n } else if (Array.isArray(field.relationTo) || ('hasMany' in field && field.hasMany)) {\n if (fieldData === null || (Array.isArray(fieldData) && fieldData.length === 0)) {\n relationshipsToDelete.push({ path: relationshipPath })\n return\n }\n\n transformRelationship({\n baseRow: {\n locale: withinArrayOrBlockLocale,\n path: relationshipPath,\n },\n data: fieldData,\n field,\n relationships,\n })\n return\n } else {\n if (\n !isLocalized &&\n fieldData &&\n typeof fieldData === 'object' &&\n 'id' in fieldData &&\n fieldData?.id\n ) {\n fieldData = fieldData.id\n } else if (isLocalized) {\n if (typeof fieldData === 'object') {\n Object.entries(fieldData).forEach(([localeKey, localeData]) => {\n if (typeof localeData === 'object') {\n if (localeData && 'id' in localeData && localeData?.id) {\n fieldData[localeKey] = localeData.id\n }\n } else {\n fieldData[localeKey] = localeData\n }\n })\n }\n }\n }\n }\n\n if (field.type === 'text' && field.hasMany) {\n const textPath = `${path || ''}${field.name}`\n\n if (isLocalized) {\n if (typeof fieldData === 'object') {\n Object.entries(fieldData).forEach(([localeKey, localeData]) => {\n if (Array.isArray(localeData)) {\n if (!localeData.length) {\n textsToDelete.push({ locale: localeKey, path: textPath })\n return\n }\n\n transformTexts({\n baseRow: {\n locale: localeKey,\n path: textPath,\n },\n data: localeData,\n texts,\n })\n }\n })\n }\n } else if (Array.isArray(fieldData)) {\n if (!fieldData.length) {\n textsToDelete.push({ locale: withinArrayOrBlockLocale, path: textPath })\n return\n }\n\n transformTexts({\n baseRow: {\n locale: withinArrayOrBlockLocale,\n path: textPath,\n },\n data: fieldData,\n texts,\n })\n }\n\n return\n }\n\n if (field.type === 'number' && field.hasMany) {\n const numberPath = `${path || ''}${field.name}`\n\n if (isLocalized) {\n if (typeof fieldData === 'object') {\n Object.entries(fieldData).forEach(([localeKey, localeData]) => {\n if (Array.isArray(localeData)) {\n if (!localeData.length) {\n numbersToDelete.push({ locale: localeKey, path: numberPath })\n return\n }\n\n transformNumbers({\n baseRow: {\n locale: localeKey,\n path: numberPath,\n },\n data: localeData,\n numbers,\n })\n }\n })\n }\n } else if (Array.isArray(fieldData)) {\n if (!fieldData.length) {\n numbersToDelete.push({ locale: withinArrayOrBlockLocale, path: numberPath })\n return\n }\n\n transformNumbers({\n baseRow: {\n locale: withinArrayOrBlockLocale,\n path: numberPath,\n },\n data: fieldData,\n numbers,\n })\n }\n\n return\n }\n\n if (field.type === 'select' && field.hasMany) {\n if (fieldData === undefined) {\n return\n }\n\n const selectTableName = adapter.tableNameMap.get(`${parentTableName}_${columnName}`)\n if (!selects[selectTableName]) {\n selects[selectTableName] = []\n }\n\n if (isLocalized) {\n if (typeof data[field.name] === 'object' && data[field.name] !== null) {\n Object.entries(data[field.name]).forEach(([localeKey, localeData]) => {\n if (Array.isArray(localeData)) {\n const newRows = transformSelects({\n id: insideArrayOrBlock ? data._uuid || data.id : undefined,\n data: localeData,\n locale: localeKey,\n })\n\n selects[selectTableName] = selects[selectTableName].concat(newRows)\n }\n })\n }\n } else if (Array.isArray(data[field.name])) {\n const newRows = transformSelects({\n id: insideArrayOrBlock ? data._uuid || data.id : undefined,\n data: data[field.name],\n locale: withinArrayOrBlockLocale,\n })\n\n selects[selectTableName] = selects[selectTableName].concat(newRows)\n }\n\n return\n }\n\n const valuesToTransform: { localeKey?: string; ref: unknown; value: unknown }[] = []\n\n if (isLocalized) {\n if (typeof fieldData === 'object' && fieldData !== null) {\n Object.entries(fieldData).forEach(([localeKey, localeData]) => {\n if (!locales[localeKey]) {\n locales[localeKey] = {}\n }\n\n valuesToTransform.push({\n localeKey,\n ref: locales,\n value: localeData,\n })\n })\n }\n } else {\n let ref = row\n\n if (forcedLocale) {\n if (!locales[forcedLocale]) {\n locales[forcedLocale] = {}\n }\n ref = locales[forcedLocale]\n }\n\n valuesToTransform.push({ ref, value: fieldData })\n }\n\n valuesToTransform.forEach(({ localeKey, ref, value }) => {\n let formattedValue = value\n\n if (field.type === 'date') {\n if (fieldName === 'updatedAt' && formattedValue === null) {\n // If updatedAt is explicitly set to null, skip it entirely - don't add to row\n // This prevents the timestamp from being updated for session-only operations\n return // Skip this iteration\n } else if (fieldName === 'updatedAt' && typeof formattedValue === 'undefined') {\n // If updatedAt is undefined, set it to current time (normal behavior)\n formattedValue = new Date().toISOString()\n } else {\n if (typeof value === 'number' && !Number.isNaN(value)) {\n formattedValue = new Date(value).toISOString()\n } else if (value instanceof Date) {\n formattedValue = value.toISOString()\n }\n }\n }\n\n if (typeof value !== 'undefined') {\n if (value && field.type === 'point' && adapter.name !== 'sqlite') {\n formattedValue = sql`ST_GeomFromGeoJSON(${JSON.stringify(value)})`\n }\n\n if (field.type === 'text' && value && typeof value !== 'string') {\n formattedValue = JSON.stringify(value)\n }\n\n if (\n field.type === 'number' &&\n value &&\n typeof value === 'object' &&\n '$inc' in value &&\n typeof value.$inc === 'number'\n ) {\n if (!enableAtomicWrites) {\n throw new APIError(\n 'The passed data must not contain any nested fields for atomic writes',\n )\n }\n\n formattedValue = sql.raw(`${columnName} + ${value.$inc}`)\n }\n }\n\n if (typeof formattedValue !== 'undefined') {\n if (localeKey) {\n ref[localeKey][fieldName] = formattedValue\n } else {\n ref[fieldName] = formattedValue\n }\n }\n })\n })\n\n // Handle dot-notation paths when no fields matched\n if (!fieldsMatched) {\n Object.keys(data).forEach((key) => {\n if (expandOwnDottedKey({ key, target: data })) {\n // Recursively process the newly created nested structure\n // The field traversal will naturally handle it if the field exists in the schema\n traverseFields({\n adapter,\n arrays,\n arraysToPush,\n baseTableName,\n blocks,\n blocksToDelete,\n columnPrefix,\n data,\n enableAtomicWrites,\n existingLocales,\n fieldPrefix,\n fields,\n forcedLocale,\n insideArrayOrBlock,\n locales,\n numbers,\n numbersToDelete,\n parentIsLocalized,\n parentTableName,\n path,\n relationships,\n relationshipsToAppend,\n relationshipsToDelete,\n row,\n selects,\n texts,\n textsToDelete,\n withinArrayOrBlockLocale,\n })\n }\n })\n }\n}\n"],"names":["sql","APIError","expandOwnDottedKey","fieldIsVirtual","fieldShouldBeLocalized","toSnakeCase","isArrayOfRows","resolveBlockTableName","transformArray","transformBlocks","transformNumbers","transformRelationship","transformSelects","transformTexts","traverseFields","adapter","arrays","arraysToPush","baseTableName","blocks","blocksToDelete","columnPrefix","data","enableAtomicWrites","existingLocales","fieldPrefix","fields","forcedLocale","insideArrayOrBlock","locales","numbers","numbersToDelete","parentIsLocalized","parentTableName","path","relationships","relationshipsToAppend","relationshipsToDelete","row","selects","texts","textsToDelete","withinArrayOrBlockLocale","fieldsMatched","_uuid","forEach","field","columnName","fieldName","fieldData","name","undefined","isLocalized","type","arrayTableName","tableNameMap","get","value","Object","entries","localeKey","localeValue","localeData","push","$push","Array","isArray","newRows","locale","localized","concat","blocksAsJSON","blockReferences","block","matchedBlock","payload","config","find","each","slug","add","id","flattenedFields","groupData","relationshipPath","hasMany","values","some","itemsToAppend","hasLocaleOperations","localeItems","item","relationshipToAppend","relationTo","remove","$remove","relationshipToDelete","itemToRemove","itemsToRemove","baseRow","length","textPath","numberPath","selectTableName","valuesToTransform","ref","formattedValue","Date","toISOString","Number","isNaN","JSON","stringify","$inc","raw","keys","key","target"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"updateOne.d.ts","sourceRoot":"","sources":["../src/updateOne.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAYxC,eAAO,MAAM,SAAS,EAAE,SAqFvB,CAAA"}
1
+ {"version":3,"file":"updateOne.d.ts","sourceRoot":"","sources":["../src/updateOne.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAgBxC,eAAO,MAAM,SAAS,EAAE,SAiIvB,CAAA"}
package/dist/updateOne.js CHANGED
@@ -1,15 +1,20 @@
1
1
  import toSnakeCase from 'to-snake-case';
2
2
  import { buildQuery } from './queries/buildQuery.js';
3
3
  import { selectDistinct } from './queries/selectDistinct.js';
4
+ import { transform } from './transform/read/index.js';
5
+ import { transformForWrite } from './transform/write/index.js';
4
6
  import { upsertRow } from './upsertRow/index.js';
7
+ import { shouldUseOptimizedUpsertRow } from './upsertRow/shouldUseOptimizedUpsertRow.js';
5
8
  import { getPrimaryDb } from './utilities/getPrimaryDb.js';
6
9
  import { getTransaction } from './utilities/getTransaction.js';
10
+ import { markWrite } from './utilities/readAfterWrite.js';
7
11
  export const updateOne = async function updateOne({ id, collection: collectionSlug, data, joins: joinQuery, locale, options = {
8
12
  upsert: false
9
13
  }, req, returning, select, where: whereArg }) {
10
14
  const collection = this.payload.collections[collectionSlug].config;
11
15
  const tableName = this.tableNameMap.get(toSnakeCase(collection.slug));
12
16
  let idToUpdate = id;
17
+ let whereToUpdate;
13
18
  const db = getPrimaryDb(this, await getTransaction(this, req));
14
19
  if (!idToUpdate) {
15
20
  const { joins, selectFields, where } = buildQuery({
@@ -19,6 +24,40 @@ export const updateOne = async function updateOne({ id, collection: collectionSl
19
24
  tableName,
20
25
  where: whereArg
21
26
  });
27
+ // A `where` that needs joins cannot be applied to the UPDATE statement itself, so those
28
+ // queries keep resolving a matching id first and then update that row unconditionally
29
+ whereToUpdate = joins.length === 0 ? where : undefined;
30
+ if (options.atomic === true) {
31
+ if (!shouldUseOptimizedUpsertRow({
32
+ data,
33
+ fields: collection.flattenedFields
34
+ })) {
35
+ throw new Error('Atomic where updates only support fields stored on the main table');
36
+ }
37
+ const { arraysToPush, row } = transformForWrite({
38
+ adapter: this,
39
+ data,
40
+ enableAtomicWrites: true,
41
+ fields: collection.flattenedFields,
42
+ tableName
43
+ });
44
+ if (arraysToPush && Object.keys(arraysToPush).length) {
45
+ throw new Error('Atomic where updates do not support array operations');
46
+ }
47
+ markWrite(this);
48
+ const docs = await db.update(this.tables[tableName]).set(row).where(where).returning();
49
+ if (!docs[0]) {
50
+ return null;
51
+ }
52
+ return transform({
53
+ adapter: this,
54
+ config: this.payload.config,
55
+ data: docs[0],
56
+ fields: collection.flattenedFields,
57
+ joinQuery: false,
58
+ tableName
59
+ });
60
+ }
22
61
  // selectDistinct will only return if there are joins
23
62
  const selectDistinctResult = await selectDistinct({
24
63
  adapter: this,
@@ -58,7 +97,8 @@ export const updateOne = async function updateOne({ id, collection: collectionSl
58
97
  operation: 'update',
59
98
  req,
60
99
  select,
61
- tableName
100
+ tableName,
101
+ where: whereToUpdate
62
102
  });
63
103
  if (returning === false) {
64
104
  return null;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/updateOne.ts"],"sourcesContent":["import type { LibSQLDatabase } from 'drizzle-orm/libsql'\nimport type { UpdateOne } from 'payload'\n\nimport toSnakeCase from 'to-snake-case'\n\nimport type { DrizzleAdapter } from './types.js'\n\nimport { buildQuery } from './queries/buildQuery.js'\nimport { selectDistinct } from './queries/selectDistinct.js'\nimport { upsertRow } from './upsertRow/index.js'\nimport { getPrimaryDb } from './utilities/getPrimaryDb.js'\nimport { getTransaction } from './utilities/getTransaction.js'\n\nexport const updateOne: UpdateOne = async function updateOne(\n this: DrizzleAdapter,\n {\n id,\n collection: collectionSlug,\n data,\n joins: joinQuery,\n locale,\n options = { upsert: false },\n req,\n returning,\n select,\n where: whereArg,\n },\n) {\n const collection = this.payload.collections[collectionSlug].config\n const tableName = this.tableNameMap.get(toSnakeCase(collection.slug))\n let idToUpdate = id\n\n const db = getPrimaryDb(this, await getTransaction(this, req))\n\n if (!idToUpdate) {\n const { joins, selectFields, where } = buildQuery({\n adapter: this,\n fields: collection.flattenedFields,\n locale,\n tableName,\n where: whereArg,\n })\n\n // selectDistinct will only return if there are joins\n const selectDistinctResult = await selectDistinct({\n adapter: this,\n db,\n joins,\n query: ({ query }) => query.limit(1),\n selectFields,\n tableName,\n where,\n })\n\n if (selectDistinctResult?.[0]?.id) {\n idToUpdate = selectDistinctResult?.[0]?.id\n // If id wasn't passed but `where` without any joins, retrieve it with findFirst\n } else if (whereArg && !joins.length) {\n const table = this.tables[tableName]\n\n const docsToUpdate = await (db as LibSQLDatabase)\n .select({\n id: table.id,\n })\n .from(table)\n .where(where)\n .limit(1)\n idToUpdate = docsToUpdate?.[0]?.id\n }\n }\n\n if (!idToUpdate && !options.upsert) {\n // TODO: In 4.0, if returning === false, we should differentiate between:\n // - No document found to update\n // - Document found, but returning === false\n return null\n }\n\n const result = await upsertRow({\n id: idToUpdate,\n adapter: this,\n collectionSlug,\n data,\n db,\n fields: collection.flattenedFields,\n ignoreResult: returning === false,\n joinQuery,\n operation: 'update',\n req,\n select,\n tableName,\n })\n\n if (returning === false) {\n return null\n }\n\n return result\n}\n"],"names":["toSnakeCase","buildQuery","selectDistinct","upsertRow","getPrimaryDb","getTransaction","updateOne","id","collection","collectionSlug","data","joins","joinQuery","locale","options","upsert","req","returning","select","where","whereArg","payload","collections","config","tableName","tableNameMap","get","slug","idToUpdate","db","selectFields","adapter","fields","flattenedFields","selectDistinctResult","query","limit","length","table","tables","docsToUpdate","from","result","ignoreResult","operation"],"mappings":"AAGA,OAAOA,iBAAiB,gBAAe;AAIvC,SAASC,UAAU,QAAQ,0BAAyB;AACpD,SAASC,cAAc,QAAQ,8BAA6B;AAC5D,SAASC,SAAS,QAAQ,uBAAsB;AAChD,SAASC,YAAY,QAAQ,8BAA6B;AAC1D,SAASC,cAAc,QAAQ,gCAA+B;AAE9D,OAAO,MAAMC,YAAuB,eAAeA,UAEjD,EACEC,EAAE,EACFC,YAAYC,cAAc,EAC1BC,IAAI,EACJC,OAAOC,SAAS,EAChBC,MAAM,EACNC,UAAU;IAAEC,QAAQ;AAAM,CAAC,EAC3BC,GAAG,EACHC,SAAS,EACTC,MAAM,EACNC,OAAOC,QAAQ,EAChB;IAED,MAAMZ,aAAa,IAAI,CAACa,OAAO,CAACC,WAAW,CAACb,eAAe,CAACc,MAAM;IAClE,MAAMC,YAAY,IAAI,CAACC,YAAY,CAACC,GAAG,CAAC1B,YAAYQ,WAAWmB,IAAI;IACnE,IAAIC,aAAarB;IAEjB,MAAMsB,KAAKzB,aAAa,IAAI,EAAE,MAAMC,eAAe,IAAI,EAAEW;IAEzD,IAAI,CAACY,YAAY;QACf,MAAM,EAAEjB,KAAK,EAAEmB,YAAY,EAAEX,KAAK,EAAE,GAAGlB,WAAW;YAChD8B,SAAS,IAAI;YACbC,QAAQxB,WAAWyB,eAAe;YAClCpB;YACAW;YACAL,OAAOC;QACT;QAEA,qDAAqD;QACrD,MAAMc,uBAAuB,MAAMhC,eAAe;YAChD6B,SAAS,IAAI;YACbF;YACAlB;YACAwB,OAAO,CAAC,EAAEA,KAAK,EAAE,GAAKA,MAAMC,KAAK,CAAC;YAClCN;YACAN;YACAL;QACF;QAEA,IAAIe,sBAAsB,CAAC,EAAE,EAAE3B,IAAI;YACjCqB,aAAaM,sBAAsB,CAAC,EAAE,EAAE3B;QACxC,gFAAgF;QAClF,OAAO,IAAIa,YAAY,CAACT,MAAM0B,MAAM,EAAE;YACpC,MAAMC,QAAQ,IAAI,CAACC,MAAM,CAACf,UAAU;YAEpC,MAAMgB,eAAe,MAAM,AAACX,GACzBX,MAAM,CAAC;gBACNX,IAAI+B,MAAM/B,EAAE;YACd,GACCkC,IAAI,CAACH,OACLnB,KAAK,CAACA,OACNiB,KAAK,CAAC;YACTR,aAAaY,cAAc,CAAC,EAAE,EAAEjC;QAClC;IACF;IAEA,IAAI,CAACqB,cAAc,CAACd,QAAQC,MAAM,EAAE;QAClC,yEAAyE;QACzE,gCAAgC;QAChC,4CAA4C;QAC5C,OAAO;IACT;IAEA,MAAM2B,SAAS,MAAMvC,UAAU;QAC7BI,IAAIqB;QACJG,SAAS,IAAI;QACbtB;QACAC;QACAmB;QACAG,QAAQxB,WAAWyB,eAAe;QAClCU,cAAc1B,cAAc;QAC5BL;QACAgC,WAAW;QACX5B;QACAE;QACAM;IACF;IAEA,IAAIP,cAAc,OAAO;QACvB,OAAO;IACT;IAEA,OAAOyB;AACT,EAAC"}
1
+ {"version":3,"sources":["../src/updateOne.ts"],"sourcesContent":["import type { SQL } from 'drizzle-orm'\nimport type { LibSQLDatabase } from 'drizzle-orm/libsql'\nimport type { UpdateOne } from 'payload'\n\nimport toSnakeCase from 'to-snake-case'\n\nimport type { DrizzleAdapter } from './types.js'\n\nimport { buildQuery } from './queries/buildQuery.js'\nimport { selectDistinct } from './queries/selectDistinct.js'\nimport { transform } from './transform/read/index.js'\nimport { transformForWrite } from './transform/write/index.js'\nimport { upsertRow } from './upsertRow/index.js'\nimport { shouldUseOptimizedUpsertRow } from './upsertRow/shouldUseOptimizedUpsertRow.js'\nimport { getPrimaryDb } from './utilities/getPrimaryDb.js'\nimport { getTransaction } from './utilities/getTransaction.js'\nimport { markWrite } from './utilities/readAfterWrite.js'\n\nexport const updateOne: UpdateOne = async function updateOne(\n this: DrizzleAdapter,\n {\n id,\n collection: collectionSlug,\n data,\n joins: joinQuery,\n locale,\n options = { upsert: false },\n req,\n returning,\n select,\n where: whereArg,\n },\n) {\n const collection = this.payload.collections[collectionSlug].config\n const tableName = this.tableNameMap.get(toSnakeCase(collection.slug))\n let idToUpdate = id\n let whereToUpdate: SQL<unknown> | undefined\n\n const db = getPrimaryDb(this, await getTransaction(this, req))\n\n if (!idToUpdate) {\n const { joins, selectFields, where } = buildQuery({\n adapter: this,\n fields: collection.flattenedFields,\n locale,\n tableName,\n where: whereArg,\n })\n // A `where` that needs joins cannot be applied to the UPDATE statement itself, so those\n // queries keep resolving a matching id first and then update that row unconditionally\n whereToUpdate = joins.length === 0 ? where : undefined\n\n if (options.atomic === true) {\n if (!shouldUseOptimizedUpsertRow({ data, fields: collection.flattenedFields })) {\n throw new Error('Atomic where updates only support fields stored on the main table')\n }\n\n const { arraysToPush, row } = transformForWrite({\n adapter: this,\n data,\n enableAtomicWrites: true,\n fields: collection.flattenedFields,\n tableName,\n })\n\n if (arraysToPush && Object.keys(arraysToPush).length) {\n throw new Error('Atomic where updates do not support array operations')\n }\n\n markWrite(this)\n\n const docs = await (db as LibSQLDatabase)\n .update(this.tables[tableName])\n .set(row)\n .where(where)\n .returning()\n\n if (!docs[0]) {\n return null\n }\n\n return transform({\n adapter: this,\n config: this.payload.config,\n data: docs[0],\n fields: collection.flattenedFields,\n joinQuery: false,\n tableName,\n })\n }\n\n // selectDistinct will only return if there are joins\n const selectDistinctResult = await selectDistinct({\n adapter: this,\n db,\n joins,\n query: ({ query }) => query.limit(1),\n selectFields,\n tableName,\n where,\n })\n\n if (selectDistinctResult?.[0]?.id) {\n idToUpdate = selectDistinctResult?.[0]?.id\n // If id wasn't passed but `where` without any joins, retrieve it with findFirst\n } else if (whereArg && !joins.length) {\n const table = this.tables[tableName]\n\n const docsToUpdate = await (db as LibSQLDatabase)\n .select({\n id: table.id,\n })\n .from(table)\n .where(where)\n .limit(1)\n idToUpdate = docsToUpdate?.[0]?.id\n }\n }\n\n if (!idToUpdate && !options.upsert) {\n // TODO: In 4.0, if returning === false, we should differentiate between:\n // - No document found to update\n // - Document found, but returning === false\n return null\n }\n\n const result = await upsertRow({\n id: idToUpdate,\n adapter: this,\n collectionSlug,\n data,\n db,\n fields: collection.flattenedFields,\n ignoreResult: returning === false,\n joinQuery,\n operation: 'update',\n req,\n select,\n tableName,\n where: whereToUpdate,\n })\n\n if (returning === false) {\n return null\n }\n\n return result\n}\n"],"names":["toSnakeCase","buildQuery","selectDistinct","transform","transformForWrite","upsertRow","shouldUseOptimizedUpsertRow","getPrimaryDb","getTransaction","markWrite","updateOne","id","collection","collectionSlug","data","joins","joinQuery","locale","options","upsert","req","returning","select","where","whereArg","payload","collections","config","tableName","tableNameMap","get","slug","idToUpdate","whereToUpdate","db","selectFields","adapter","fields","flattenedFields","length","undefined","atomic","Error","arraysToPush","row","enableAtomicWrites","Object","keys","docs","update","tables","set","selectDistinctResult","query","limit","table","docsToUpdate","from","result","ignoreResult","operation"],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { buildQuery } from './queries/buildQuery.js';
3
+ import { selectDistinct } from './queries/selectDistinct.js';
4
+ import { updateOne } from './updateOne.js';
5
+ import { upsertRow } from './upsertRow/index.js';
6
+ vi.mock('./queries/buildQuery.js', ()=>({
7
+ buildQuery: vi.fn()
8
+ }));
9
+ vi.mock('./queries/selectDistinct.js', ()=>({
10
+ selectDistinct: vi.fn()
11
+ }));
12
+ vi.mock('./upsertRow/index.js', ()=>({
13
+ upsertRow: vi.fn()
14
+ }));
15
+ const conditionalWhere = {
16
+ conditional: true
17
+ };
18
+ const adapter = {
19
+ drizzle: {},
20
+ payload: {
21
+ collections: {
22
+ users: {
23
+ config: {
24
+ flattenedFields: [],
25
+ slug: 'users'
26
+ }
27
+ }
28
+ }
29
+ },
30
+ sessions: {},
31
+ tableNameMap: new Map([
32
+ [
33
+ 'users',
34
+ 'users'
35
+ ]
36
+ ])
37
+ };
38
+ describe('updateOne', ()=>{
39
+ beforeEach(()=>{
40
+ vi.mocked(buildQuery).mockReturnValue({
41
+ joins: [],
42
+ selectFields: {},
43
+ where: conditionalWhere
44
+ });
45
+ vi.mocked(selectDistinct).mockResolvedValue([
46
+ {
47
+ id: 1
48
+ }
49
+ ]);
50
+ vi.mocked(upsertRow).mockResolvedValue({
51
+ id: 1
52
+ });
53
+ });
54
+ it('should apply the original condition to the selected update', async ()=>{
55
+ await updateOne.call(adapter, {
56
+ collection: 'users',
57
+ data: {
58
+ hash: 'updated-hash',
59
+ salt: 'updated-salt'
60
+ },
61
+ select: {
62
+ id: true
63
+ },
64
+ where: {
65
+ hash: {
66
+ equals: 'existing-hash'
67
+ },
68
+ id: {
69
+ equals: 1
70
+ },
71
+ salt: {
72
+ equals: 'existing-salt'
73
+ }
74
+ }
75
+ });
76
+ expect(selectDistinct).toHaveBeenCalledTimes(1);
77
+ expect(upsertRow).toHaveBeenCalledWith(expect.objectContaining({
78
+ id: 1,
79
+ where: conditionalWhere
80
+ }));
81
+ });
82
+ });
83
+
84
+ //# sourceMappingURL=updateOne.spec.js.map