@payloadcms/drizzle 3.0.0-canary.ff8c8fd → 3.0.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 (291) hide show
  1. package/dist/count.d.ts.map +1 -1
  2. package/dist/count.js +1 -1
  3. package/dist/count.js.map +1 -1
  4. package/dist/countGlobalVersions.d.ts +3 -0
  5. package/dist/countGlobalVersions.d.ts.map +1 -0
  6. package/dist/countGlobalVersions.js +27 -0
  7. package/dist/countGlobalVersions.js.map +1 -0
  8. package/dist/countVersions.d.ts +3 -0
  9. package/dist/countVersions.d.ts.map +1 -0
  10. package/dist/countVersions.js +27 -0
  11. package/dist/countVersions.js.map +1 -0
  12. package/dist/create.d.ts.map +1 -1
  13. package/dist/create.js +2 -1
  14. package/dist/create.js.map +1 -1
  15. package/dist/createGlobalVersion.d.ts +1 -1
  16. package/dist/createGlobalVersion.d.ts.map +1 -1
  17. package/dist/createGlobalVersion.js +7 -2
  18. package/dist/createGlobalVersion.js.map +1 -1
  19. package/dist/createTableName.d.ts.map +1 -1
  20. package/dist/createTableName.js +6 -2
  21. package/dist/createTableName.js.map +1 -1
  22. package/dist/createVersion.d.ts +1 -1
  23. package/dist/createVersion.d.ts.map +1 -1
  24. package/dist/createVersion.js +22 -14
  25. package/dist/createVersion.js.map +1 -1
  26. package/dist/deleteOne.d.ts.map +1 -1
  27. package/dist/deleteOne.js +6 -3
  28. package/dist/deleteOne.js.map +1 -1
  29. package/dist/deleteVersions.js +1 -1
  30. package/dist/deleteVersions.js.map +1 -1
  31. package/dist/destroy.d.ts.map +1 -1
  32. package/dist/destroy.js +3 -1
  33. package/dist/destroy.js.map +1 -1
  34. package/dist/exports/postgres.d.ts +2 -1
  35. package/dist/exports/postgres.d.ts.map +1 -1
  36. package/dist/exports/postgres.js +2 -1
  37. package/dist/exports/postgres.js.map +1 -1
  38. package/dist/find/buildFindManyArgs.d.ts +15 -7
  39. package/dist/find/buildFindManyArgs.d.ts.map +1 -1
  40. package/dist/find/buildFindManyArgs.js +40 -17
  41. package/dist/find/buildFindManyArgs.js.map +1 -1
  42. package/dist/find/findMany.d.ts +2 -1
  43. package/dist/find/findMany.d.ts.map +1 -1
  44. package/dist/find/findMany.js +12 -7
  45. package/dist/find/findMany.js.map +1 -1
  46. package/dist/find/traverseFields.d.ts +18 -4
  47. package/dist/find/traverseFields.d.ts.map +1 -1
  48. package/dist/find/traverseFields.js +358 -68
  49. package/dist/find/traverseFields.js.map +1 -1
  50. package/dist/find.d.ts.map +1 -1
  51. package/dist/find.js +4 -2
  52. package/dist/find.js.map +1 -1
  53. package/dist/findGlobal.d.ts.map +1 -1
  54. package/dist/findGlobal.js +2 -1
  55. package/dist/findGlobal.js.map +1 -1
  56. package/dist/findGlobalVersions.d.ts.map +1 -1
  57. package/dist/findGlobalVersions.js +4 -3
  58. package/dist/findGlobalVersions.js.map +1 -1
  59. package/dist/findMigrationDir.d.ts.map +1 -1
  60. package/dist/findMigrationDir.js +3 -1
  61. package/dist/findMigrationDir.js.map +1 -1
  62. package/dist/findOne.d.ts +1 -1
  63. package/dist/findOne.d.ts.map +1 -1
  64. package/dist/findOne.js +3 -1
  65. package/dist/findOne.js.map +1 -1
  66. package/dist/findVersions.d.ts.map +1 -1
  67. package/dist/findVersions.js +4 -3
  68. package/dist/findVersions.js.map +1 -1
  69. package/dist/index.d.ts +5 -0
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +5 -0
  72. package/dist/index.js.map +1 -1
  73. package/dist/migrate.d.ts.map +1 -1
  74. package/dist/migrate.js +4 -0
  75. package/dist/migrate.js.map +1 -1
  76. package/dist/migrateDown.d.ts.map +1 -1
  77. package/dist/migrateDown.js +1 -1
  78. package/dist/migrateDown.js.map +1 -1
  79. package/dist/migrateFresh.d.ts.map +1 -1
  80. package/dist/migrateFresh.js +4 -0
  81. package/dist/migrateFresh.js.map +1 -1
  82. package/dist/migrateRefresh.d.ts.map +1 -1
  83. package/dist/migrateRefresh.js +2 -1
  84. package/dist/migrateRefresh.js.map +1 -1
  85. package/dist/migrateReset.d.ts.map +1 -1
  86. package/dist/migrateReset.js +5 -3
  87. package/dist/migrateReset.js.map +1 -1
  88. package/dist/migrateStatus.js +0 -1
  89. package/dist/migrateStatus.js.map +1 -1
  90. package/dist/postgres/countDistinct.d.ts.map +1 -1
  91. package/dist/postgres/countDistinct.js +2 -3
  92. package/dist/postgres/countDistinct.js.map +1 -1
  93. package/dist/postgres/createDatabase.d.ts +14 -0
  94. package/dist/postgres/createDatabase.d.ts.map +1 -0
  95. package/dist/postgres/createDatabase.js +76 -0
  96. package/dist/postgres/createDatabase.js.map +1 -0
  97. package/dist/postgres/createExtensions.d.ts +3 -0
  98. package/dist/postgres/createExtensions.d.ts.map +1 -0
  99. package/dist/postgres/createExtensions.js +16 -0
  100. package/dist/postgres/createExtensions.js.map +1 -0
  101. package/dist/postgres/createJSONQuery/convertPathToJSONTraversal.d.ts.map +1 -1
  102. package/dist/postgres/createJSONQuery/convertPathToJSONTraversal.js +3 -1
  103. package/dist/postgres/createJSONQuery/convertPathToJSONTraversal.js.map +1 -1
  104. package/dist/postgres/createJSONQuery/index.d.ts +2 -9
  105. package/dist/postgres/createJSONQuery/index.d.ts.map +1 -1
  106. package/dist/postgres/createJSONQuery/index.js +34 -46
  107. package/dist/postgres/createJSONQuery/index.js.map +1 -1
  108. package/dist/postgres/createMigration.d.ts.map +1 -1
  109. package/dist/postgres/createMigration.js +1 -5
  110. package/dist/postgres/createMigration.js.map +1 -1
  111. package/dist/postgres/defaultSnapshot.d.ts.map +1 -1
  112. package/dist/postgres/defaultSnapshot.js +4 -1
  113. package/dist/postgres/defaultSnapshot.js.map +1 -1
  114. package/dist/postgres/init.d.ts.map +1 -1
  115. package/dist/postgres/init.js +12 -3
  116. package/dist/postgres/init.js.map +1 -1
  117. package/dist/postgres/schema/build.d.ts +12 -2
  118. package/dist/postgres/schema/build.d.ts.map +1 -1
  119. package/dist/postgres/schema/build.js +45 -10
  120. package/dist/postgres/schema/build.js.map +1 -1
  121. package/dist/postgres/schema/createIndex.d.ts +2 -3
  122. package/dist/postgres/schema/createIndex.d.ts.map +1 -1
  123. package/dist/postgres/schema/createIndex.js +5 -3
  124. package/dist/postgres/schema/createIndex.js.map +1 -1
  125. package/dist/postgres/schema/geometryColumn.d.ts +12 -0
  126. package/dist/postgres/schema/geometryColumn.d.ts.map +1 -0
  127. package/dist/postgres/schema/geometryColumn.js +18 -0
  128. package/dist/postgres/schema/geometryColumn.js.map +1 -0
  129. package/dist/postgres/schema/traverseFields.d.ts +9 -2
  130. package/dist/postgres/schema/traverseFields.d.ts.map +1 -1
  131. package/dist/postgres/schema/traverseFields.js +393 -265
  132. package/dist/postgres/schema/traverseFields.js.map +1 -1
  133. package/dist/postgres/schema/withDefault.d.ts.map +1 -1
  134. package/dist/postgres/schema/withDefault.js +6 -1
  135. package/dist/postgres/schema/withDefault.js.map +1 -1
  136. package/dist/postgres/types.d.ts +37 -7
  137. package/dist/postgres/types.d.ts.map +1 -1
  138. package/dist/postgres/types.js.map +1 -1
  139. package/dist/queries/addJoinTable.d.ts +11 -0
  140. package/dist/queries/addJoinTable.d.ts.map +1 -0
  141. package/dist/queries/addJoinTable.js +13 -0
  142. package/dist/queries/addJoinTable.js.map +1 -0
  143. package/dist/queries/buildAndOrConditions.d.ts +1 -1
  144. package/dist/queries/buildAndOrConditions.d.ts.map +1 -1
  145. package/dist/queries/buildAndOrConditions.js +2 -4
  146. package/dist/queries/buildAndOrConditions.js.map +1 -1
  147. package/dist/queries/buildOrderBy.d.ts +18 -0
  148. package/dist/queries/buildOrderBy.d.ts.map +1 -0
  149. package/dist/queries/buildOrderBy.js +56 -0
  150. package/dist/queries/buildOrderBy.js.map +1 -0
  151. package/dist/queries/buildQuery.d.ts +8 -7
  152. package/dist/queries/buildQuery.d.ts.map +1 -1
  153. package/dist/queries/buildQuery.js +12 -47
  154. package/dist/queries/buildQuery.js.map +1 -1
  155. package/dist/queries/getTableColumnFromPath.d.ts +6 -2
  156. package/dist/queries/getTableColumnFromPath.d.ts.map +1 -1
  157. package/dist/queries/getTableColumnFromPath.js +270 -223
  158. package/dist/queries/getTableColumnFromPath.js.map +1 -1
  159. package/dist/queries/operatorMap.d.ts.map +1 -1
  160. package/dist/queries/operatorMap.js +0 -4
  161. package/dist/queries/operatorMap.js.map +1 -1
  162. package/dist/queries/parseParams.d.ts +1 -1
  163. package/dist/queries/parseParams.d.ts.map +1 -1
  164. package/dist/queries/parseParams.js +85 -6
  165. package/dist/queries/parseParams.js.map +1 -1
  166. package/dist/queries/sanitizeQueryValue.d.ts +12 -1
  167. package/dist/queries/sanitizeQueryValue.d.ts.map +1 -1
  168. package/dist/queries/sanitizeQueryValue.js +89 -25
  169. package/dist/queries/sanitizeQueryValue.js.map +1 -1
  170. package/dist/queries/selectDistinct.d.ts +3 -4
  171. package/dist/queries/selectDistinct.d.ts.map +1 -1
  172. package/dist/queries/selectDistinct.js.map +1 -1
  173. package/dist/queryDrafts.d.ts.map +1 -1
  174. package/dist/queryDrafts.js +6 -6
  175. package/dist/queryDrafts.js.map +1 -1
  176. package/dist/transactions/beginTransaction.d.ts.map +1 -1
  177. package/dist/transactions/beginTransaction.js +5 -1
  178. package/dist/transactions/beginTransaction.js.map +1 -1
  179. package/dist/transactions/commitTransaction.d.ts.map +1 -1
  180. package/dist/transactions/commitTransaction.js +3 -1
  181. package/dist/transactions/commitTransaction.js.map +1 -1
  182. package/dist/transform/read/hasManyNumber.d.ts +2 -1
  183. package/dist/transform/read/hasManyNumber.d.ts.map +1 -1
  184. package/dist/transform/read/hasManyNumber.js +12 -2
  185. package/dist/transform/read/hasManyNumber.js.map +1 -1
  186. package/dist/transform/read/hasManyText.d.ts +2 -1
  187. package/dist/transform/read/hasManyText.d.ts.map +1 -1
  188. package/dist/transform/read/hasManyText.js +12 -2
  189. package/dist/transform/read/hasManyText.js.map +1 -1
  190. package/dist/transform/read/index.d.ts +3 -2
  191. package/dist/transform/read/index.d.ts.map +1 -1
  192. package/dist/transform/read/index.js +3 -2
  193. package/dist/transform/read/index.js.map +1 -1
  194. package/dist/transform/read/relationship.d.ts +2 -1
  195. package/dist/transform/read/relationship.d.ts.map +1 -1
  196. package/dist/transform/read/relationship.js +15 -6
  197. package/dist/transform/read/relationship.js.map +1 -1
  198. package/dist/transform/read/traverseFields.d.ts +10 -2
  199. package/dist/transform/read/traverseFields.d.ts.map +1 -1
  200. package/dist/transform/read/traverseFields.js +185 -71
  201. package/dist/transform/read/traverseFields.js.map +1 -1
  202. package/dist/transform/write/array.d.ts +6 -1
  203. package/dist/transform/write/array.d.ts.map +1 -1
  204. package/dist/transform/write/array.js +7 -3
  205. package/dist/transform/write/array.js.map +1 -1
  206. package/dist/transform/write/blocks.d.ts +8 -3
  207. package/dist/transform/write/blocks.d.ts.map +1 -1
  208. package/dist/transform/write/blocks.js +19 -7
  209. package/dist/transform/write/blocks.js.map +1 -1
  210. package/dist/transform/write/index.d.ts.map +1 -1
  211. package/dist/transform/write/index.js +1 -1
  212. package/dist/transform/write/index.js.map +1 -1
  213. package/dist/transform/write/relationships.d.ts.map +1 -1
  214. package/dist/transform/write/relationships.js +6 -2
  215. package/dist/transform/write/relationships.js.map +1 -1
  216. package/dist/transform/write/selects.d.ts.map +1 -1
  217. package/dist/transform/write/selects.js +1 -1
  218. package/dist/transform/write/selects.js.map +1 -1
  219. package/dist/transform/write/traverseFields.d.ts +6 -1
  220. package/dist/transform/write/traverseFields.d.ts.map +1 -1
  221. package/dist/transform/write/traverseFields.js +62 -19
  222. package/dist/transform/write/traverseFields.js.map +1 -1
  223. package/dist/types.d.ts +6 -4
  224. package/dist/types.d.ts.map +1 -1
  225. package/dist/types.js.map +1 -1
  226. package/dist/update.d.ts.map +1 -1
  227. package/dist/update.js +4 -2
  228. package/dist/update.js.map +1 -1
  229. package/dist/updateGlobal.d.ts +1 -1
  230. package/dist/updateGlobal.d.ts.map +1 -1
  231. package/dist/updateGlobal.js +2 -1
  232. package/dist/updateGlobal.js.map +1 -1
  233. package/dist/updateGlobalVersion.d.ts +1 -1
  234. package/dist/updateGlobalVersion.d.ts.map +1 -1
  235. package/dist/updateGlobalVersion.js +4 -3
  236. package/dist/updateGlobalVersion.js.map +1 -1
  237. package/dist/updateVersion.d.ts +1 -1
  238. package/dist/updateVersion.d.ts.map +1 -1
  239. package/dist/updateVersion.js +4 -3
  240. package/dist/updateVersion.js.map +1 -1
  241. package/dist/upsertRow/deleteExistingRowsByPath.d.ts.map +1 -1
  242. package/dist/upsertRow/deleteExistingRowsByPath.js +6 -2
  243. package/dist/upsertRow/deleteExistingRowsByPath.js.map +1 -1
  244. package/dist/upsertRow/index.d.ts +1 -1
  245. package/dist/upsertRow/index.d.ts.map +1 -1
  246. package/dist/upsertRow/index.js +51 -13
  247. package/dist/upsertRow/index.js.map +1 -1
  248. package/dist/upsertRow/insertArrays.d.ts.map +1 -1
  249. package/dist/upsertRow/insertArrays.js +5 -2
  250. package/dist/upsertRow/insertArrays.js.map +1 -1
  251. package/dist/upsertRow/types.d.ts +10 -5
  252. package/dist/upsertRow/types.d.ts.map +1 -1
  253. package/dist/upsertRow/types.js.map +1 -1
  254. package/dist/utilities/buildIndexName.d.ts +7 -0
  255. package/dist/utilities/buildIndexName.d.ts.map +1 -0
  256. package/dist/utilities/buildIndexName.js +14 -0
  257. package/dist/utilities/buildIndexName.js.map +1 -0
  258. package/dist/utilities/createBlocksMap.d.ts.map +1 -1
  259. package/dist/utilities/createBlocksMap.js +4 -2
  260. package/dist/utilities/createBlocksMap.js.map +1 -1
  261. package/dist/utilities/createRelationshipMap.d.ts.map +1 -1
  262. package/dist/utilities/createRelationshipMap.js +3 -1
  263. package/dist/utilities/createRelationshipMap.js.map +1 -1
  264. package/dist/utilities/executeSchemaHooks.d.ts +24 -0
  265. package/dist/utilities/executeSchemaHooks.d.ts.map +1 -0
  266. package/dist/utilities/executeSchemaHooks.js +21 -0
  267. package/dist/utilities/executeSchemaHooks.js.map +1 -0
  268. package/dist/utilities/extendDrizzleTable.d.ts +19 -0
  269. package/dist/utilities/extendDrizzleTable.d.ts.map +1 -0
  270. package/dist/utilities/extendDrizzleTable.js +38 -0
  271. package/dist/utilities/extendDrizzleTable.js.map +1 -0
  272. package/dist/utilities/getCollectionIdType.d.ts +7 -0
  273. package/dist/utilities/getCollectionIdType.d.ts.map +1 -0
  274. package/dist/utilities/getCollectionIdType.js +11 -0
  275. package/dist/utilities/getCollectionIdType.js.map +1 -0
  276. package/dist/utilities/getNameFromDrizzleTable.d.ts +3 -0
  277. package/dist/utilities/getNameFromDrizzleTable.d.ts.map +1 -0
  278. package/dist/utilities/getNameFromDrizzleTable.js +6 -0
  279. package/dist/utilities/getNameFromDrizzleTable.js.map +1 -0
  280. package/dist/utilities/hasLocalesTable.d.ts.map +1 -1
  281. package/dist/utilities/hasLocalesTable.js +12 -4
  282. package/dist/utilities/hasLocalesTable.js.map +1 -1
  283. package/dist/utilities/isPolymorphicRelationship.d.ts +6 -0
  284. package/dist/utilities/isPolymorphicRelationship.d.ts.map +1 -0
  285. package/dist/utilities/isPolymorphicRelationship.js +5 -0
  286. package/dist/utilities/isPolymorphicRelationship.js.map +1 -0
  287. package/dist/utilities/pushDevSchema.d.ts.map +1 -1
  288. package/dist/utilities/pushDevSchema.js +5 -0
  289. package/dist/utilities/pushDevSchema.js.map +1 -1
  290. package/license.md +22 -0
  291. package/package.json +17 -8
@@ -1,17 +1,19 @@
1
1
  import { relations } from 'drizzle-orm';
2
- import { PgNumericBuilder, PgUUIDBuilder, PgVarcharBuilder, boolean, foreignKey, index, integer, jsonb, numeric, text, timestamp, varchar } from 'drizzle-orm/pg-core';
2
+ import { boolean, foreignKey, index, integer, jsonb, numeric, PgNumericBuilder, PgUUIDBuilder, PgVarcharBuilder, text, timestamp, varchar } from 'drizzle-orm/pg-core';
3
3
  import { InvalidConfiguration } from 'payload';
4
- import { fieldAffectsData, optionIsObject } from 'payload/shared';
4
+ import { fieldAffectsData, fieldIsVirtual, optionIsObject } from 'payload/shared';
5
5
  import toSnakeCase from 'to-snake-case';
6
6
  import { createTableName } from '../../createTableName.js';
7
+ import { buildIndexName } from '../../utilities/buildIndexName.js';
7
8
  import { hasLocalesTable } from '../../utilities/hasLocalesTable.js';
8
9
  import { validateExistingBlockIsIdentical } from '../../utilities/validateExistingBlockIsIdentical.js';
9
10
  import { buildTable } from './build.js';
10
11
  import { createIndex } from './createIndex.js';
12
+ import { geometryColumn } from './geometryColumn.js';
11
13
  import { idToUUID } from './idToUUID.js';
12
14
  import { parentIDColumnMap } from './parentIDColumnMap.js';
13
15
  import { withDefault } from './withDefault.js';
14
- export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull, disableUnique = false, fieldPrefix, fields, forceLocalized, indexes, localesColumns, localesIndexes, newTableName, parentTableName, relationsToBuild, relationships, rootRelationsToBuild, rootTableIDColType, rootTableName, versions })=>{
16
+ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull, disableRelsTableUnique, disableUnique = false, fieldPrefix, fields, forceLocalized, indexes, localesColumns, localesIndexes, newTableName, parentTableName, relationships, relationsToBuild, rootRelationsToBuild, rootTableIDColType, rootTableName, uniqueRelationships, versions, withinLocalizedArrayOrBlock })=>{
15
17
  const throwValidationError = true;
16
18
  let hasLocalizedField = false;
17
19
  let hasLocalizedRelationshipField = false;
@@ -20,11 +22,22 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
20
22
  let hasManyNumberField = false;
21
23
  let hasLocalizedManyNumberField = false;
22
24
  let parentIDColType = 'integer';
23
- if (columns.id instanceof PgUUIDBuilder) parentIDColType = 'uuid';
24
- if (columns.id instanceof PgNumericBuilder) parentIDColType = 'numeric';
25
- if (columns.id instanceof PgVarcharBuilder) parentIDColType = 'varchar';
25
+ if (columns.id instanceof PgUUIDBuilder) {
26
+ parentIDColType = 'uuid';
27
+ }
28
+ if (columns.id instanceof PgNumericBuilder) {
29
+ parentIDColType = 'numeric';
30
+ }
31
+ if (columns.id instanceof PgVarcharBuilder) {
32
+ parentIDColType = 'varchar';
33
+ }
26
34
  fields.forEach((field)=>{
27
- if ('name' in field && field.name === 'id') return;
35
+ if ('name' in field && field.name === 'id') {
36
+ return;
37
+ }
38
+ if (fieldIsVirtual(field)) {
39
+ return;
40
+ }
28
41
  let columnName;
29
42
  let fieldName;
30
43
  let targetTable = columns;
@@ -39,14 +52,14 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
39
52
  targetTable = localesColumns;
40
53
  targetIndexes = localesIndexes;
41
54
  }
42
- if ((field.unique || field.index) && ![
43
- 'array',
44
- 'blocks',
45
- 'group',
46
- 'point',
55
+ if ((field.unique || field.index || [
47
56
  'relationship',
48
57
  'upload'
49
- ].includes(field.type) && !('hasMany' in field && field.hasMany === true)) {
58
+ ].includes(field.type)) && ![
59
+ 'array',
60
+ 'blocks',
61
+ 'group'
62
+ ].includes(field.type) && !('hasMany' in field && field.hasMany === true) && !('relationTo' in field && Array.isArray(field.relationTo))) {
50
63
  const unique = disableUnique !== true && field.unique;
51
64
  if (unique) {
52
65
  const constraintValue = `${fieldPrefix || ''}${field.name}`;
@@ -55,168 +68,21 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
55
68
  }
56
69
  adapter.fieldConstraints[rootTableName][`${columnName}_idx`] = constraintValue;
57
70
  }
58
- targetIndexes[`${newTableName}_${field.name}Idx`] = createIndex({
59
- name: fieldName,
60
- columnName,
61
- tableName: newTableName,
71
+ const indexName = buildIndexName({
72
+ name: `${newTableName}_${columnName}`,
73
+ adapter
74
+ });
75
+ targetIndexes[indexName] = createIndex({
76
+ name: field.localized ? [
77
+ fieldName,
78
+ '_locale'
79
+ ] : fieldName,
80
+ indexName,
62
81
  unique
63
82
  });
64
83
  }
65
84
  }
66
85
  switch(field.type){
67
- case 'text':
68
- {
69
- if (field.hasMany) {
70
- if (field.localized) {
71
- hasLocalizedManyTextField = true;
72
- }
73
- if (field.index) {
74
- hasManyTextField = 'index';
75
- } else if (!hasManyTextField) {
76
- hasManyTextField = true;
77
- }
78
- if (field.unique) {
79
- throw new InvalidConfiguration('Unique is not supported in Postgres for hasMany text fields.');
80
- }
81
- } else {
82
- targetTable[fieldName] = withDefault(varchar(columnName), field);
83
- }
84
- break;
85
- }
86
- case 'email':
87
- case 'code':
88
- case 'textarea':
89
- {
90
- targetTable[fieldName] = withDefault(varchar(columnName), field);
91
- break;
92
- }
93
- case 'number':
94
- {
95
- if (field.hasMany) {
96
- if (field.localized) {
97
- hasLocalizedManyNumberField = true;
98
- }
99
- if (field.index) {
100
- hasManyNumberField = 'index';
101
- } else if (!hasManyNumberField) {
102
- hasManyNumberField = true;
103
- }
104
- if (field.unique) {
105
- throw new InvalidConfiguration('Unique is not supported in Postgres for hasMany number fields.');
106
- }
107
- } else {
108
- targetTable[fieldName] = withDefault(numeric(columnName), field);
109
- }
110
- break;
111
- }
112
- case 'richText':
113
- case 'json':
114
- {
115
- targetTable[fieldName] = withDefault(jsonb(columnName), field);
116
- break;
117
- }
118
- case 'date':
119
- {
120
- targetTable[fieldName] = withDefault(timestamp(columnName, {
121
- mode: 'string',
122
- precision: 3,
123
- withTimezone: true
124
- }), field);
125
- break;
126
- }
127
- case 'point':
128
- {
129
- break;
130
- }
131
- case 'radio':
132
- case 'select':
133
- {
134
- const enumName = createTableName({
135
- adapter,
136
- config: field,
137
- parentTableName: newTableName,
138
- prefix: `enum_${newTableName}_`,
139
- target: 'enumName',
140
- throwValidationError
141
- });
142
- adapter.enums[enumName] = adapter.pgSchema.enum(enumName, field.options.map((option)=>{
143
- if (optionIsObject(option)) {
144
- return option.value;
145
- }
146
- return option;
147
- }));
148
- if (field.type === 'select' && field.hasMany) {
149
- const selectTableName = createTableName({
150
- adapter,
151
- config: field,
152
- parentTableName: newTableName,
153
- prefix: `${newTableName}_`,
154
- throwValidationError,
155
- versionsCustomName: versions
156
- });
157
- const baseColumns = {
158
- order: integer('order').notNull(),
159
- parent: parentIDColumnMap[parentIDColType]('parent_id').notNull(),
160
- value: adapter.enums[enumName]('value')
161
- };
162
- const baseExtraConfig = {
163
- orderIdx: (cols)=>index(`${selectTableName}_order_idx`).on(cols.order),
164
- parentFk: (cols)=>foreignKey({
165
- name: `${selectTableName}_parent_fk`,
166
- columns: [
167
- cols.parent
168
- ],
169
- foreignColumns: [
170
- adapter.tables[parentTableName].id
171
- ]
172
- }).onDelete('cascade'),
173
- parentIdx: (cols)=>index(`${selectTableName}_parent_idx`).on(cols.parent)
174
- };
175
- if (field.localized) {
176
- baseColumns.locale = adapter.enums.enum__locales('locale').notNull();
177
- baseExtraConfig.localeIdx = (cols)=>index(`${selectTableName}_locale_idx`).on(cols.locale);
178
- }
179
- if (field.index) {
180
- baseExtraConfig.value = (cols)=>index(`${selectTableName}_value_idx`).on(cols.value);
181
- }
182
- buildTable({
183
- adapter,
184
- baseColumns,
185
- baseExtraConfig,
186
- disableNotNull,
187
- disableUnique,
188
- fields: [],
189
- rootTableName,
190
- tableName: selectTableName,
191
- versions
192
- });
193
- relationsToBuild.set(fieldName, {
194
- type: 'many',
195
- // selects have their own localized table, independent of the base table.
196
- localized: false,
197
- target: selectTableName
198
- });
199
- adapter.relations[`relations_${selectTableName}`] = relations(adapter.tables[selectTableName], ({ one })=>({
200
- parent: one(adapter.tables[parentTableName], {
201
- fields: [
202
- adapter.tables[selectTableName].parent
203
- ],
204
- references: [
205
- adapter.tables[parentTableName].id
206
- ],
207
- relationName: fieldName
208
- })
209
- }));
210
- } else {
211
- targetTable[fieldName] = withDefault(adapter.enums[enumName](fieldName), field);
212
- }
213
- break;
214
- }
215
- case 'checkbox':
216
- {
217
- targetTable[fieldName] = withDefault(boolean(columnName), field);
218
- break;
219
- }
220
86
  case 'array':
221
87
  {
222
88
  const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull;
@@ -245,29 +111,46 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
245
111
  }).onDelete('cascade'),
246
112
  _parentIDIdx: (cols)=>index(`${arrayTableName}_parent_id_idx`).on(cols._parentID)
247
113
  };
248
- if (field.localized && adapter.payload.config.localization) {
114
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
115
+ if (isLocalized) {
249
116
  baseColumns._locale = adapter.enums.enum__locales('_locale').notNull();
250
117
  baseExtraConfig._localeIdx = (cols)=>index(`${arrayTableName}_locale_idx`).on(cols._locale);
251
118
  }
252
- const { hasManyNumberField: subHasManyNumberField, hasManyTextField: subHasManyTextField, relationsToBuild: subRelationsToBuild } = buildTable({
119
+ const { hasLocalizedManyNumberField: subHasLocalizedManyNumberField, hasLocalizedManyTextField: subHasLocalizedManyTextField, hasLocalizedRelationshipField: subHasLocalizedRelationshipField, hasManyNumberField: subHasManyNumberField, hasManyTextField: subHasManyTextField, relationsToBuild: subRelationsToBuild } = buildTable({
253
120
  adapter,
254
121
  baseColumns,
255
122
  baseExtraConfig,
256
123
  disableNotNull: disableNotNullFromHere,
124
+ disableRelsTableUnique: true,
257
125
  disableUnique,
258
126
  fields: disableUnique ? idToUUID(field.fields) : field.fields,
259
- rootRelationsToBuild,
260
127
  rootRelationships: relationships,
128
+ rootRelationsToBuild,
261
129
  rootTableIDColType,
262
130
  rootTableName,
131
+ rootUniqueRelationships: uniqueRelationships,
263
132
  tableName: arrayTableName,
264
- versions
133
+ versions,
134
+ withinLocalizedArrayOrBlock: isLocalized
265
135
  });
136
+ if (subHasLocalizedManyNumberField) {
137
+ hasLocalizedManyNumberField = subHasLocalizedManyNumberField;
138
+ }
139
+ if (subHasLocalizedRelationshipField) {
140
+ hasLocalizedRelationshipField = subHasLocalizedRelationshipField;
141
+ }
142
+ if (subHasLocalizedManyTextField) {
143
+ hasLocalizedManyTextField = subHasLocalizedManyTextField;
144
+ }
266
145
  if (subHasManyTextField) {
267
- if (!hasManyTextField || subHasManyTextField === 'index') hasManyTextField = subHasManyTextField;
146
+ if (!hasManyTextField || subHasManyTextField === 'index') {
147
+ hasManyTextField = subHasManyTextField;
148
+ }
268
149
  }
269
150
  if (subHasManyNumberField) {
270
- if (!hasManyNumberField || subHasManyNumberField === 'index') hasManyNumberField = subHasManyNumberField;
151
+ if (!hasManyNumberField || subHasManyNumberField === 'index') {
152
+ hasManyNumberField = subHasManyNumberField;
153
+ }
271
154
  }
272
155
  relationsToBuild.set(fieldName, {
273
156
  type: 'many',
@@ -335,7 +218,6 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
335
218
  };
336
219
  const baseExtraConfig = {
337
220
  _orderIdx: (cols)=>index(`${blockTableName}_order_idx`).on(cols._order),
338
- _parentIDIdx: (cols)=>index(`${blockTableName}_parent_id_idx`).on(cols._parentID),
339
221
  _parentIdFk: (cols)=>foreignKey({
340
222
  name: `${blockTableName}_parent_id_fk`,
341
223
  columns: [
@@ -345,31 +227,49 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
345
227
  adapter.tables[rootTableName].id
346
228
  ]
347
229
  }).onDelete('cascade'),
230
+ _parentIDIdx: (cols)=>index(`${blockTableName}_parent_id_idx`).on(cols._parentID),
348
231
  _pathIdx: (cols)=>index(`${blockTableName}_path_idx`).on(cols._path)
349
232
  };
350
- if (field.localized && adapter.payload.config.localization) {
233
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
234
+ if (isLocalized) {
351
235
  baseColumns._locale = adapter.enums.enum__locales('_locale').notNull();
352
236
  baseExtraConfig._localeIdx = (cols)=>index(`${blockTableName}_locale_idx`).on(cols._locale);
353
237
  }
354
- const { hasManyNumberField: subHasManyNumberField, hasManyTextField: subHasManyTextField, relationsToBuild: subRelationsToBuild } = buildTable({
238
+ const { hasLocalizedManyNumberField: subHasLocalizedManyNumberField, hasLocalizedManyTextField: subHasLocalizedManyTextField, hasLocalizedRelationshipField: subHasLocalizedRelationshipField, hasManyNumberField: subHasManyNumberField, hasManyTextField: subHasManyTextField, relationsToBuild: subRelationsToBuild } = buildTable({
355
239
  adapter,
356
240
  baseColumns,
357
241
  baseExtraConfig,
358
242
  disableNotNull: disableNotNullFromHere,
243
+ disableRelsTableUnique: true,
359
244
  disableUnique,
360
245
  fields: disableUnique ? idToUUID(block.fields) : block.fields,
361
- rootRelationsToBuild,
362
246
  rootRelationships: relationships,
247
+ rootRelationsToBuild,
363
248
  rootTableIDColType,
364
249
  rootTableName,
250
+ rootUniqueRelationships: uniqueRelationships,
365
251
  tableName: blockTableName,
366
- versions
252
+ versions,
253
+ withinLocalizedArrayOrBlock: isLocalized
367
254
  });
255
+ if (subHasLocalizedManyNumberField) {
256
+ hasLocalizedManyNumberField = subHasLocalizedManyNumberField;
257
+ }
258
+ if (subHasLocalizedRelationshipField) {
259
+ hasLocalizedRelationshipField = subHasLocalizedRelationshipField;
260
+ }
261
+ if (subHasLocalizedManyTextField) {
262
+ hasLocalizedManyTextField = subHasLocalizedManyTextField;
263
+ }
368
264
  if (subHasManyTextField) {
369
- if (!hasManyTextField || subHasManyTextField === 'index') hasManyTextField = subHasManyTextField;
265
+ if (!hasManyTextField || subHasManyTextField === 'index') {
266
+ hasManyTextField = subHasManyTextField;
267
+ }
370
268
  }
371
269
  if (subHasManyNumberField) {
372
- if (!hasManyNumberField || subHasManyNumberField === 'index') hasManyNumberField = subHasManyNumberField;
270
+ if (!hasManyNumberField || subHasManyNumberField === 'index') {
271
+ hasManyNumberField = subHasManyNumberField;
272
+ }
373
273
  }
374
274
  adapter.relations[`relations_${blockTableName}`] = relations(adapter.tables[blockTableName], ({ many, one })=>{
375
275
  const result = {
@@ -428,8 +328,76 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
428
328
  });
429
329
  break;
430
330
  }
431
- case 'tab':
331
+ case 'checkbox':
332
+ {
333
+ targetTable[fieldName] = withDefault(boolean(columnName), field);
334
+ break;
335
+ }
336
+ case 'code':
337
+ case 'email':
338
+ case 'textarea':
339
+ {
340
+ targetTable[fieldName] = withDefault(varchar(columnName), field);
341
+ break;
342
+ }
343
+ case 'collapsible':
344
+ case 'row':
345
+ {
346
+ const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull;
347
+ const { hasLocalizedField: rowHasLocalizedField, hasLocalizedManyNumberField: rowHasLocalizedManyNumberField, hasLocalizedManyTextField: rowHasLocalizedManyTextField, hasLocalizedRelationshipField: rowHasLocalizedRelationshipField, hasManyNumberField: rowHasManyNumberField, hasManyTextField: rowHasManyTextField } = traverseFields({
348
+ adapter,
349
+ columnPrefix,
350
+ columns,
351
+ disableNotNull: disableNotNullFromHere,
352
+ disableUnique,
353
+ fieldPrefix,
354
+ fields: field.fields,
355
+ forceLocalized,
356
+ indexes,
357
+ localesColumns,
358
+ localesIndexes,
359
+ newTableName,
360
+ parentTableName,
361
+ relationships,
362
+ relationsToBuild,
363
+ rootRelationsToBuild,
364
+ rootTableIDColType,
365
+ rootTableName,
366
+ uniqueRelationships,
367
+ versions,
368
+ withinLocalizedArrayOrBlock
369
+ });
370
+ if (rowHasLocalizedField) {
371
+ hasLocalizedField = true;
372
+ }
373
+ if (rowHasLocalizedRelationshipField) {
374
+ hasLocalizedRelationshipField = true;
375
+ }
376
+ if (rowHasManyTextField) {
377
+ hasManyTextField = true;
378
+ }
379
+ if (rowHasLocalizedManyTextField) {
380
+ hasLocalizedManyTextField = true;
381
+ }
382
+ if (rowHasManyNumberField) {
383
+ hasManyNumberField = true;
384
+ }
385
+ if (rowHasLocalizedManyNumberField) {
386
+ hasLocalizedManyNumberField = true;
387
+ }
388
+ break;
389
+ }
390
+ case 'date':
391
+ {
392
+ targetTable[fieldName] = withDefault(timestamp(columnName, {
393
+ mode: 'string',
394
+ precision: 3,
395
+ withTimezone: true
396
+ }), field);
397
+ break;
398
+ }
432
399
  case 'group':
400
+ case 'tab':
433
401
  {
434
402
  if (!('name' in field)) {
435
403
  const { hasLocalizedField: groupHasLocalizedField, hasLocalizedManyNumberField: groupHasLocalizedManyNumberField, hasLocalizedManyTextField: groupHasLocalizedManyTextField, hasLocalizedRelationshipField: groupHasLocalizedRelationshipField, hasManyNumberField: groupHasManyNumberField, hasManyTextField: groupHasManyTextField } = traverseFields({
@@ -446,19 +414,33 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
446
414
  localesIndexes,
447
415
  newTableName,
448
416
  parentTableName,
449
- relationsToBuild,
450
417
  relationships,
418
+ relationsToBuild,
451
419
  rootRelationsToBuild,
452
420
  rootTableIDColType,
453
421
  rootTableName,
454
- versions
422
+ uniqueRelationships,
423
+ versions,
424
+ withinLocalizedArrayOrBlock
455
425
  });
456
- if (groupHasLocalizedField) hasLocalizedField = true;
457
- if (groupHasLocalizedRelationshipField) hasLocalizedRelationshipField = true;
458
- if (groupHasManyTextField) hasManyTextField = true;
459
- if (groupHasLocalizedManyTextField) hasLocalizedManyTextField = true;
460
- if (groupHasManyNumberField) hasManyNumberField = true;
461
- if (groupHasLocalizedManyNumberField) hasLocalizedManyNumberField = true;
426
+ if (groupHasLocalizedField) {
427
+ hasLocalizedField = true;
428
+ }
429
+ if (groupHasLocalizedRelationshipField) {
430
+ hasLocalizedRelationshipField = true;
431
+ }
432
+ if (groupHasManyTextField) {
433
+ hasManyTextField = true;
434
+ }
435
+ if (groupHasLocalizedManyTextField) {
436
+ hasLocalizedManyTextField = true;
437
+ }
438
+ if (groupHasManyNumberField) {
439
+ hasManyNumberField = true;
440
+ }
441
+ if (groupHasLocalizedManyNumberField) {
442
+ hasLocalizedManyNumberField = true;
443
+ }
462
444
  break;
463
445
  }
464
446
  const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull;
@@ -476,95 +458,168 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
476
458
  localesIndexes,
477
459
  newTableName: `${parentTableName}_${columnName}`,
478
460
  parentTableName,
479
- relationsToBuild,
480
461
  relationships,
462
+ relationsToBuild,
481
463
  rootRelationsToBuild,
482
464
  rootTableIDColType,
483
465
  rootTableName,
484
- versions
466
+ uniqueRelationships,
467
+ versions,
468
+ withinLocalizedArrayOrBlock: withinLocalizedArrayOrBlock || field.localized
485
469
  });
486
- if (groupHasLocalizedField) hasLocalizedField = true;
487
- if (groupHasLocalizedRelationshipField) hasLocalizedRelationshipField = true;
488
- if (groupHasManyTextField) hasManyTextField = true;
489
- if (groupHasLocalizedManyTextField) hasLocalizedManyTextField = true;
490
- if (groupHasManyNumberField) hasManyNumberField = true;
491
- if (groupHasLocalizedManyNumberField) hasLocalizedManyNumberField = true;
470
+ if (groupHasLocalizedField) {
471
+ hasLocalizedField = true;
472
+ }
473
+ if (groupHasLocalizedRelationshipField) {
474
+ hasLocalizedRelationshipField = true;
475
+ }
476
+ if (groupHasManyTextField) {
477
+ hasManyTextField = true;
478
+ }
479
+ if (groupHasLocalizedManyTextField) {
480
+ hasLocalizedManyTextField = true;
481
+ }
482
+ if (groupHasManyNumberField) {
483
+ hasManyNumberField = true;
484
+ }
485
+ if (groupHasLocalizedManyNumberField) {
486
+ hasLocalizedManyNumberField = true;
487
+ }
492
488
  break;
493
489
  }
494
- case 'tabs':
490
+ case 'json':
491
+ case 'richText':
495
492
  {
496
- const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull;
497
- const { hasLocalizedField: tabHasLocalizedField, hasLocalizedManyNumberField: tabHasLocalizedManyNumberField, hasLocalizedManyTextField: tabHasLocalizedManyTextField, hasLocalizedRelationshipField: tabHasLocalizedRelationshipField, hasManyNumberField: tabHasManyNumberField, hasManyTextField: tabHasManyTextField } = traverseFields({
498
- adapter,
499
- columnPrefix,
500
- columns,
501
- disableNotNull: disableNotNullFromHere,
502
- disableUnique,
503
- fieldPrefix,
504
- fields: field.tabs.map((tab)=>({
505
- ...tab,
506
- type: 'tab'
507
- })),
508
- forceLocalized,
509
- indexes,
510
- localesColumns,
511
- localesIndexes,
512
- newTableName,
513
- parentTableName,
514
- relationsToBuild,
515
- relationships,
516
- rootRelationsToBuild,
517
- rootTableIDColType,
518
- rootTableName,
519
- versions
520
- });
521
- if (tabHasLocalizedField) hasLocalizedField = true;
522
- if (tabHasLocalizedRelationshipField) hasLocalizedRelationshipField = true;
523
- if (tabHasManyTextField) hasManyTextField = true;
524
- if (tabHasLocalizedManyTextField) hasLocalizedManyTextField = true;
525
- if (tabHasManyNumberField) hasManyNumberField = true;
526
- if (tabHasLocalizedManyNumberField) hasLocalizedManyNumberField = true;
493
+ targetTable[fieldName] = withDefault(jsonb(columnName), field);
527
494
  break;
528
495
  }
529
- case 'row':
530
- case 'collapsible':
496
+ case 'number':
531
497
  {
532
- const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull;
533
- const { hasLocalizedField: rowHasLocalizedField, hasLocalizedManyNumberField: rowHasLocalizedManyNumberField, hasLocalizedManyTextField: rowHasLocalizedManyTextField, hasLocalizedRelationshipField: rowHasLocalizedRelationshipField, hasManyNumberField: rowHasManyNumberField, hasManyTextField: rowHasManyTextField } = traverseFields({
498
+ if (field.hasMany) {
499
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
500
+ if (isLocalized) {
501
+ hasLocalizedManyNumberField = true;
502
+ }
503
+ if (field.index) {
504
+ hasManyNumberField = 'index';
505
+ } else if (!hasManyNumberField) {
506
+ hasManyNumberField = true;
507
+ }
508
+ if (field.unique) {
509
+ throw new InvalidConfiguration('Unique is not supported in Postgres for hasMany number fields.');
510
+ }
511
+ } else {
512
+ targetTable[fieldName] = withDefault(numeric(columnName), field);
513
+ }
514
+ break;
515
+ }
516
+ case 'point':
517
+ {
518
+ targetTable[fieldName] = withDefault(geometryColumn(columnName), field);
519
+ if (!adapter.extensions.postgis) {
520
+ adapter.extensions.postgis = true;
521
+ }
522
+ break;
523
+ }
524
+ case 'radio':
525
+ case 'select':
526
+ {
527
+ const enumName = createTableName({
534
528
  adapter,
535
- columnPrefix,
536
- columns,
537
- disableNotNull: disableNotNullFromHere,
538
- disableUnique,
539
- fieldPrefix,
540
- fields: field.fields,
541
- forceLocalized,
542
- indexes,
543
- localesColumns,
544
- localesIndexes,
545
- newTableName,
546
- parentTableName,
547
- relationsToBuild,
548
- relationships,
549
- rootRelationsToBuild,
550
- rootTableIDColType,
551
- rootTableName,
552
- versions
529
+ config: field,
530
+ parentTableName: newTableName,
531
+ prefix: `enum_${newTableName}_`,
532
+ target: 'enumName',
533
+ throwValidationError
553
534
  });
554
- if (rowHasLocalizedField) hasLocalizedField = true;
555
- if (rowHasLocalizedRelationshipField) hasLocalizedRelationshipField = true;
556
- if (rowHasManyTextField) hasManyTextField = true;
557
- if (rowHasLocalizedManyTextField) hasLocalizedManyTextField = true;
558
- if (rowHasManyNumberField) hasManyNumberField = true;
559
- if (rowHasLocalizedManyNumberField) hasLocalizedManyNumberField = true;
535
+ adapter.enums[enumName] = adapter.pgSchema.enum(enumName, field.options.map((option)=>{
536
+ if (optionIsObject(option)) {
537
+ return option.value;
538
+ }
539
+ return option;
540
+ }));
541
+ if (field.type === 'select' && field.hasMany) {
542
+ const selectTableName = createTableName({
543
+ adapter,
544
+ config: field,
545
+ parentTableName: newTableName,
546
+ prefix: `${newTableName}_`,
547
+ throwValidationError,
548
+ versionsCustomName: versions
549
+ });
550
+ const baseColumns = {
551
+ order: integer('order').notNull(),
552
+ parent: parentIDColumnMap[parentIDColType]('parent_id').notNull(),
553
+ value: adapter.enums[enumName]('value')
554
+ };
555
+ const baseExtraConfig = {
556
+ orderIdx: (cols)=>index(`${selectTableName}_order_idx`).on(cols.order),
557
+ parentFk: (cols)=>foreignKey({
558
+ name: `${selectTableName}_parent_fk`,
559
+ columns: [
560
+ cols.parent
561
+ ],
562
+ foreignColumns: [
563
+ adapter.tables[parentTableName].id
564
+ ]
565
+ }).onDelete('cascade'),
566
+ parentIdx: (cols)=>index(`${selectTableName}_parent_idx`).on(cols.parent)
567
+ };
568
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
569
+ if (isLocalized) {
570
+ baseColumns.locale = adapter.enums.enum__locales('locale').notNull();
571
+ baseExtraConfig.localeIdx = (cols)=>index(`${selectTableName}_locale_idx`).on(cols.locale);
572
+ }
573
+ if (field.index) {
574
+ baseExtraConfig.value = (cols)=>index(`${selectTableName}_value_idx`).on(cols.value);
575
+ }
576
+ buildTable({
577
+ adapter,
578
+ baseColumns,
579
+ baseExtraConfig,
580
+ disableNotNull,
581
+ disableUnique,
582
+ fields: [],
583
+ rootTableName,
584
+ tableName: selectTableName,
585
+ versions
586
+ });
587
+ relationsToBuild.set(fieldName, {
588
+ type: 'many',
589
+ // selects have their own localized table, independent of the base table.
590
+ localized: false,
591
+ target: selectTableName
592
+ });
593
+ adapter.relations[`relations_${selectTableName}`] = relations(adapter.tables[selectTableName], ({ one })=>({
594
+ parent: one(adapter.tables[parentTableName], {
595
+ fields: [
596
+ adapter.tables[selectTableName].parent
597
+ ],
598
+ references: [
599
+ adapter.tables[parentTableName].id
600
+ ],
601
+ relationName: fieldName
602
+ })
603
+ }));
604
+ } else {
605
+ targetTable[fieldName] = withDefault(adapter.enums[enumName](columnName), field);
606
+ }
560
607
  break;
561
608
  }
562
609
  case 'relationship':
563
610
  case 'upload':
564
611
  if (Array.isArray(field.relationTo)) {
565
- field.relationTo.forEach((relation)=>relationships.add(relation));
612
+ field.relationTo.forEach((relation)=>{
613
+ relationships.add(relation);
614
+ if (field.unique && !disableUnique && !disableRelsTableUnique) {
615
+ uniqueRelationships.add(relation);
616
+ }
617
+ });
566
618
  } else if (field.hasMany) {
567
619
  relationships.add(field.relationTo);
620
+ if (field.unique && !disableUnique && !disableRelsTableUnique) {
621
+ uniqueRelationships.add(field.relationTo);
622
+ }
568
623
  } else {
569
624
  // simple relationships get a column on the targetTable with a foreign key to the relationTo table
570
625
  const relationshipConfig = adapter.payload.collections[field.relationTo].config;
@@ -572,8 +627,12 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
572
627
  // get the id type of the related collection
573
628
  let colType = adapter.idType === 'uuid' ? 'uuid' : 'integer';
574
629
  const relatedCollectionCustomID = relationshipConfig.fields.find((field)=>fieldAffectsData(field) && field.name === 'id');
575
- if (relatedCollectionCustomID?.type === 'number') colType = 'numeric';
576
- if (relatedCollectionCustomID?.type === 'text') colType = 'varchar';
630
+ if (relatedCollectionCustomID?.type === 'number') {
631
+ colType = 'numeric';
632
+ }
633
+ if (relatedCollectionCustomID?.type === 'text') {
634
+ colType = 'varchar';
635
+ }
577
636
  // make the foreign key column for relationship using the correct id column type
578
637
  targetTable[fieldName] = parentIDColumnMap[colType](`${columnName}_id`).references(()=>adapter.tables[tableName].id, {
579
638
  onDelete: 'set null'
@@ -581,7 +640,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
581
640
  // add relationship to table
582
641
  relationsToBuild.set(fieldName, {
583
642
  type: 'one',
584
- localized: adapter.payload.config.localization && field.localized,
643
+ localized: adapter.payload.config.localization && (field.localized || forceLocalized),
585
644
  target: tableName
586
645
  });
587
646
  // add notNull when not required
@@ -590,10 +649,79 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
590
649
  }
591
650
  break;
592
651
  }
593
- if (adapter.payload.config.localization && field.localized) {
652
+ if (Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock) {
594
653
  hasLocalizedRelationshipField = true;
595
654
  }
596
655
  break;
656
+ case 'tabs':
657
+ {
658
+ const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull;
659
+ const { hasLocalizedField: tabHasLocalizedField, hasLocalizedManyNumberField: tabHasLocalizedManyNumberField, hasLocalizedManyTextField: tabHasLocalizedManyTextField, hasLocalizedRelationshipField: tabHasLocalizedRelationshipField, hasManyNumberField: tabHasManyNumberField, hasManyTextField: tabHasManyTextField } = traverseFields({
660
+ adapter,
661
+ columnPrefix,
662
+ columns,
663
+ disableNotNull: disableNotNullFromHere,
664
+ disableUnique,
665
+ fieldPrefix,
666
+ fields: field.tabs.map((tab)=>({
667
+ ...tab,
668
+ type: 'tab'
669
+ })),
670
+ forceLocalized,
671
+ indexes,
672
+ localesColumns,
673
+ localesIndexes,
674
+ newTableName,
675
+ parentTableName,
676
+ relationships,
677
+ relationsToBuild,
678
+ rootRelationsToBuild,
679
+ rootTableIDColType,
680
+ rootTableName,
681
+ uniqueRelationships,
682
+ versions,
683
+ withinLocalizedArrayOrBlock
684
+ });
685
+ if (tabHasLocalizedField) {
686
+ hasLocalizedField = true;
687
+ }
688
+ if (tabHasLocalizedRelationshipField) {
689
+ hasLocalizedRelationshipField = true;
690
+ }
691
+ if (tabHasManyTextField) {
692
+ hasManyTextField = true;
693
+ }
694
+ if (tabHasLocalizedManyTextField) {
695
+ hasLocalizedManyTextField = true;
696
+ }
697
+ if (tabHasManyNumberField) {
698
+ hasManyNumberField = true;
699
+ }
700
+ if (tabHasLocalizedManyNumberField) {
701
+ hasLocalizedManyNumberField = true;
702
+ }
703
+ break;
704
+ }
705
+ case 'text':
706
+ {
707
+ if (field.hasMany) {
708
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
709
+ if (isLocalized) {
710
+ hasLocalizedManyTextField = true;
711
+ }
712
+ if (field.index) {
713
+ hasManyTextField = 'index';
714
+ } else if (!hasManyTextField) {
715
+ hasManyTextField = true;
716
+ }
717
+ if (field.unique) {
718
+ throw new InvalidConfiguration('Unique is not supported in Postgres for hasMany text fields.');
719
+ }
720
+ } else {
721
+ targetTable[fieldName] = withDefault(varchar(columnName), field);
722
+ }
723
+ break;
724
+ }
597
725
  default:
598
726
  break;
599
727
  }