@payloadcms/db-sqlite 3.0.0-canary.518fabe → 3.0.0-canary.51be7be

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.
@@ -1,11 +1,10 @@
1
1
  import type { AnySQLiteColumn } from 'drizzle-orm/sqlite-core';
2
2
  type CreateIndexArgs = {
3
- columnName: string;
3
+ indexName: string;
4
4
  name: string | string[];
5
- tableName: string;
6
5
  unique?: boolean;
7
6
  };
8
- export declare const createIndex: ({ name, columnName, tableName, unique }: CreateIndexArgs) => (table: {
7
+ export declare const createIndex: ({ name, indexName, unique }: CreateIndexArgs) => (table: {
9
8
  [x: string]: AnySQLiteColumn;
10
9
  }) => import("drizzle-orm/sqlite-core").IndexBuilder;
11
10
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"createIndex.d.ts","sourceRoot":"","sources":["../../src/schema/createIndex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAI9D,KAAK,eAAe,GAAG;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,eAAO,MAAM,WAAW,4CAA6C,eAAe,aACnE;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,eAAe,CAAA;CAAE,mDAehD,CAAA"}
1
+ {"version":3,"file":"createIndex.d.ts","sourceRoot":"","sources":["../../src/schema/createIndex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAI9D,KAAK,eAAe,GAAG;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACvB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,eAAO,MAAM,WAAW,gCAAiC,eAAe,aACvD;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,eAAe,CAAA;CAAE,mDAehD,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { index, uniqueIndex } from 'drizzle-orm/sqlite-core';
2
- export const createIndex = ({ name, columnName, tableName, unique })=>{
2
+ export const createIndex = ({ name, indexName, unique })=>{
3
3
  return (table)=>{
4
4
  let columns;
5
5
  if (Array.isArray(name)) {
@@ -11,9 +11,9 @@ export const createIndex = ({ name, columnName, tableName, unique })=>{
11
11
  ];
12
12
  }
13
13
  if (unique) {
14
- return uniqueIndex(`${tableName}_${columnName}_idx`).on(columns[0], ...columns.slice(1));
14
+ return uniqueIndex(indexName).on(columns[0], ...columns.slice(1));
15
15
  }
16
- return index(`${tableName}_${columnName}_idx`).on(columns[0], ...columns.slice(1));
16
+ return index(indexName).on(columns[0], ...columns.slice(1));
17
17
  };
18
18
  };
19
19
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/schema/createIndex.ts"],"sourcesContent":["import type { AnySQLiteColumn } from 'drizzle-orm/sqlite-core'\n\nimport { index, uniqueIndex } from 'drizzle-orm/sqlite-core'\n\ntype CreateIndexArgs = {\n columnName: string\n name: string | string[]\n tableName: string\n unique?: boolean\n}\n\nexport const createIndex = ({ name, columnName, tableName, unique }: CreateIndexArgs) => {\n return (table: { [x: string]: AnySQLiteColumn }) => {\n let columns\n if (Array.isArray(name)) {\n columns = name\n .map((columnName) => table[columnName])\n // exclude fields were included in compound indexes but do not exist on the table\n .filter((col) => typeof col !== 'undefined')\n } else {\n columns = [table[name]]\n }\n if (unique) {\n return uniqueIndex(`${tableName}_${columnName}_idx`).on(columns[0], ...columns.slice(1))\n }\n return index(`${tableName}_${columnName}_idx`).on(columns[0], ...columns.slice(1))\n }\n}\n"],"names":["index","uniqueIndex","createIndex","name","columnName","tableName","unique","table","columns","Array","isArray","map","filter","col","on","slice"],"mappings":"AAEA,SAASA,KAAK,EAAEC,WAAW,QAAQ,0BAAyB;AAS5D,OAAO,MAAMC,cAAc,CAAC,EAAEC,IAAI,EAAEC,UAAU,EAAEC,SAAS,EAAEC,MAAM,EAAmB;IAClF,OAAO,CAACC;QACN,IAAIC;QACJ,IAAIC,MAAMC,OAAO,CAACP,OAAO;YACvBK,UAAUL,KACPQ,GAAG,CAAC,CAACP,aAAeG,KAAK,CAACH,WAAW,CACtC,iFAAiF;aAChFQ,MAAM,CAAC,CAACC,MAAQ,OAAOA,QAAQ;QACpC,OAAO;YACLL,UAAU;gBAACD,KAAK,CAACJ,KAAK;aAAC;QACzB;QACA,IAAIG,QAAQ;YACV,OAAOL,YAAY,CAAC,EAAEI,UAAU,CAAC,EAAED,WAAW,IAAI,CAAC,EAAEU,EAAE,CAACN,OAAO,CAAC,EAAE,KAAKA,QAAQO,KAAK,CAAC;QACvF;QACA,OAAOf,MAAM,CAAC,EAAEK,UAAU,CAAC,EAAED,WAAW,IAAI,CAAC,EAAEU,EAAE,CAACN,OAAO,CAAC,EAAE,KAAKA,QAAQO,KAAK,CAAC;IACjF;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/schema/createIndex.ts"],"sourcesContent":["import type { AnySQLiteColumn } from 'drizzle-orm/sqlite-core'\n\nimport { index, uniqueIndex } from 'drizzle-orm/sqlite-core'\n\ntype CreateIndexArgs = {\n indexName: string\n name: string | string[]\n unique?: boolean\n}\n\nexport const createIndex = ({ name, indexName, unique }: CreateIndexArgs) => {\n return (table: { [x: string]: AnySQLiteColumn }) => {\n let columns\n if (Array.isArray(name)) {\n columns = name\n .map((columnName) => table[columnName])\n // exclude fields were included in compound indexes but do not exist on the table\n .filter((col) => typeof col !== 'undefined')\n } else {\n columns = [table[name]]\n }\n if (unique) {\n return uniqueIndex(indexName).on(columns[0], ...columns.slice(1))\n }\n return index(indexName).on(columns[0], ...columns.slice(1))\n }\n}\n"],"names":["index","uniqueIndex","createIndex","name","indexName","unique","table","columns","Array","isArray","map","columnName","filter","col","on","slice"],"mappings":"AAEA,SAASA,KAAK,EAAEC,WAAW,QAAQ,0BAAyB;AAQ5D,OAAO,MAAMC,cAAc,CAAC,EAAEC,IAAI,EAAEC,SAAS,EAAEC,MAAM,EAAmB;IACtE,OAAO,CAACC;QACN,IAAIC;QACJ,IAAIC,MAAMC,OAAO,CAACN,OAAO;YACvBI,UAAUJ,KACPO,GAAG,CAAC,CAACC,aAAeL,KAAK,CAACK,WAAW,CACtC,iFAAiF;aAChFC,MAAM,CAAC,CAACC,MAAQ,OAAOA,QAAQ;QACpC,OAAO;YACLN,UAAU;gBAACD,KAAK,CAACH,KAAK;aAAC;QACzB;QACA,IAAIE,QAAQ;YACV,OAAOJ,YAAYG,WAAWU,EAAE,CAACP,OAAO,CAAC,EAAE,KAAKA,QAAQQ,KAAK,CAAC;QAChE;QACA,OAAOf,MAAMI,WAAWU,EAAE,CAACP,OAAO,CAAC,EAAE,KAAKA,QAAQQ,KAAK,CAAC;IAC1D;AACF,EAAC"}
@@ -1,5 +1,5 @@
1
1
  import type { IndexBuilder, SQLiteColumnBuilder } from 'drizzle-orm/sqlite-core';
2
- import type { Field, TabAsField } from 'payload';
2
+ import type { Field, SanitizedJoins, TabAsField } from 'payload';
3
3
  import type { GenericColumns, IDType, SQLiteAdapter } from '../types.js';
4
4
  import type { RelationMap } from './build.js';
5
5
  type Args = {
@@ -7,11 +7,13 @@ type Args = {
7
7
  columnPrefix?: string;
8
8
  columns: Record<string, SQLiteColumnBuilder>;
9
9
  disableNotNull: boolean;
10
+ disableRelsTableUnique?: boolean;
10
11
  disableUnique?: boolean;
11
12
  fieldPrefix?: string;
12
13
  fields: (Field | TabAsField)[];
13
14
  forceLocalized?: boolean;
14
15
  indexes: Record<string, (cols: GenericColumns) => IndexBuilder>;
16
+ joins?: SanitizedJoins;
15
17
  locales: [string, ...string[]];
16
18
  localesColumns: Record<string, SQLiteColumnBuilder>;
17
19
  localesIndexes: Record<string, (cols: GenericColumns) => IndexBuilder>;
@@ -22,6 +24,7 @@ type Args = {
22
24
  rootRelationsToBuild?: RelationMap;
23
25
  rootTableIDColType: IDType;
24
26
  rootTableName: string;
27
+ uniqueRelationships: Set<string>;
25
28
  versions: boolean;
26
29
  /**
27
30
  * Tracks whether or not this table is built
@@ -37,6 +40,6 @@ type Result = {
37
40
  hasManyNumberField: 'index' | boolean;
38
41
  hasManyTextField: 'index' | boolean;
39
42
  };
40
- export declare const traverseFields: ({ adapter, columnPrefix, columns, disableNotNull, disableUnique, fieldPrefix, fields, forceLocalized, indexes, locales, localesColumns, localesIndexes, newTableName, parentTableName, relationships, relationsToBuild, rootRelationsToBuild, rootTableIDColType, rootTableName, versions, withinLocalizedArrayOrBlock, }: Args) => Result;
43
+ export declare const traverseFields: ({ adapter, columnPrefix, columns, disableNotNull, disableRelsTableUnique, disableUnique, fieldPrefix, fields, forceLocalized, indexes, joins, locales, localesColumns, localesIndexes, newTableName, parentTableName, relationships, relationsToBuild, rootRelationsToBuild, rootTableIDColType, rootTableName, uniqueRelationships, versions, withinLocalizedArrayOrBlock, }: Args) => Result;
41
44
  export {};
42
45
  //# sourceMappingURL=traverseFields.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"traverseFields.d.ts","sourceRoot":"","sources":["../../src/schema/traverseFields.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAChF,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAsBhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACxE,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,YAAY,CAAA;AAQ9D,KAAK,IAAI,GAAG;IACV,OAAO,EAAE,aAAa,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IAC5C,cAAc,EAAE,OAAO,CAAA;IACvB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,CAAC,KAAK,GAAG,UAAU,CAAC,EAAE,CAAA;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,YAAY,CAAC,CAAA;IAC/D,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;IAC9B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IACnD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,YAAY,CAAC,CAAA;IACtE,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC1B,gBAAgB,EAAE,WAAW,CAAA;IAC7B,oBAAoB,CAAC,EAAE,WAAW,CAAA;IAClC,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAA;CACtC,CAAA;AAED,KAAK,MAAM,GAAG;IACZ,iBAAiB,EAAE,OAAO,CAAA;IAC1B,2BAA2B,EAAE,OAAO,CAAA;IACpC,yBAAyB,EAAE,OAAO,CAAA;IAClC,6BAA6B,EAAE,OAAO,CAAA;IACtC,kBAAkB,EAAE,OAAO,GAAG,OAAO,CAAA;IACrC,gBAAgB,EAAE,OAAO,GAAG,OAAO,CAAA;CACpC,CAAA;AAED,eAAO,MAAM,cAAc,8TAsBxB,IAAI,KAAG,MAuzBT,CAAA"}
1
+ {"version":3,"file":"traverseFields.d.ts","sourceRoot":"","sources":["../../src/schema/traverseFields.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAChF,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAuBhE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACxE,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,YAAY,CAAA;AAQ9D,KAAK,IAAI,GAAG;IACV,OAAO,EAAE,aAAa,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IAC5C,cAAc,EAAE,OAAO,CAAA;IACvB,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,CAAC,KAAK,GAAG,UAAU,CAAC,EAAE,CAAA;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,YAAY,CAAC,CAAA;IAC/D,KAAK,CAAC,EAAE,cAAc,CAAA;IACtB,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;IAC9B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IACnD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,YAAY,CAAC,CAAA;IACtE,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC1B,gBAAgB,EAAE,WAAW,CAAA;IAC7B,oBAAoB,CAAC,EAAE,WAAW,CAAA;IAClC,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAA;IACrB,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAChC,QAAQ,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAA;CACtC,CAAA;AAED,KAAK,MAAM,GAAG;IACZ,iBAAiB,EAAE,OAAO,CAAA;IAC1B,2BAA2B,EAAE,OAAO,CAAA;IACpC,yBAAyB,EAAE,OAAO,CAAA;IAClC,6BAA6B,EAAE,OAAO,CAAA;IACtC,kBAAkB,EAAE,OAAO,GAAG,OAAO,CAAA;IACrC,gBAAgB,EAAE,OAAO,GAAG,OAAO,CAAA;CACpC,CAAA;AAED,eAAO,MAAM,cAAc,kXAyBxB,IAAI,KAAG,MAw3BT,CAAA"}
@@ -1,15 +1,15 @@
1
- import { createTableName, hasLocalesTable, validateExistingBlockIsIdentical } from '@payloadcms/drizzle';
1
+ import { buildIndexName, createTableName, hasLocalesTable, validateExistingBlockIsIdentical } from '@payloadcms/drizzle';
2
2
  import { relations } from 'drizzle-orm';
3
3
  import { foreignKey, index, integer, numeric, SQLiteIntegerBuilder, SQLiteNumericBuilder, SQLiteTextBuilder, text } from 'drizzle-orm/sqlite-core';
4
4
  import { InvalidConfiguration } from 'payload';
5
- import { fieldAffectsData, optionIsObject } from 'payload/shared';
5
+ import { fieldAffectsData, fieldIsVirtual, optionIsObject } from 'payload/shared';
6
6
  import toSnakeCase from 'to-snake-case';
7
7
  import { buildTable } from './build.js';
8
8
  import { createIndex } from './createIndex.js';
9
9
  import { getIDColumn } from './getIDColumn.js';
10
10
  import { idToUUID } from './idToUUID.js';
11
11
  import { withDefault } from './withDefault.js';
12
- export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull, disableUnique = false, fieldPrefix, fields, forceLocalized, indexes, locales, localesColumns, localesIndexes, newTableName, parentTableName, relationships, relationsToBuild, rootRelationsToBuild, rootTableIDColType, rootTableName, versions, withinLocalizedArrayOrBlock })=>{
12
+ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull, disableRelsTableUnique, disableUnique = false, fieldPrefix, fields, forceLocalized, indexes, joins, locales, localesColumns, localesIndexes, newTableName, parentTableName, relationships, relationsToBuild, rootRelationsToBuild, rootTableIDColType, rootTableName, uniqueRelationships, versions, withinLocalizedArrayOrBlock })=>{
13
13
  let hasLocalizedField = false;
14
14
  let hasLocalizedRelationshipField = false;
15
15
  let hasManyTextField = false;
@@ -30,6 +30,9 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
30
30
  if ('name' in field && field.name === 'id') {
31
31
  return;
32
32
  }
33
+ if (fieldIsVirtual(field)) {
34
+ return;
35
+ }
33
36
  let columnName;
34
37
  let fieldName;
35
38
  let targetTable = columns;
@@ -44,14 +47,15 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
44
47
  targetTable = localesColumns;
45
48
  targetIndexes = localesIndexes;
46
49
  }
47
- if ((field.unique || field.index) && ![
50
+ if ((field.unique || field.index || [
51
+ 'relationship',
52
+ 'upload'
53
+ ].includes(field.type)) && ![
48
54
  'array',
49
55
  'blocks',
50
56
  'group',
51
- 'point',
52
- 'relationship',
53
- 'upload'
54
- ].includes(field.type) && !('hasMany' in field && field.hasMany === true)) {
57
+ 'point'
58
+ ].includes(field.type) && !('hasMany' in field && field.hasMany === true) && !('relationTo' in field && Array.isArray(field.relationTo))) {
55
59
  const unique = disableUnique !== true && field.unique;
56
60
  if (unique) {
57
61
  const constraintValue = `${fieldPrefix || ''}${field.name}`;
@@ -60,10 +64,16 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
60
64
  }
61
65
  adapter.fieldConstraints[rootTableName][`${columnName}_idx`] = constraintValue;
62
66
  }
63
- targetIndexes[`${newTableName}_${field.name}Idx`] = createIndex({
64
- name: fieldName,
65
- columnName,
66
- tableName: newTableName,
67
+ const indexName = buildIndexName({
68
+ name: `${newTableName}_${columnName}`,
69
+ adapter: adapter
70
+ });
71
+ targetIndexes[indexName] = createIndex({
72
+ name: field.localized ? [
73
+ fieldName,
74
+ '_locale'
75
+ ] : fieldName,
76
+ indexName,
67
77
  unique
68
78
  });
69
79
  }
@@ -72,7 +82,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
72
82
  case 'text':
73
83
  {
74
84
  if (field.hasMany) {
75
- const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock;
85
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
76
86
  if (isLocalized) {
77
87
  hasLocalizedManyTextField = true;
78
88
  }
@@ -99,7 +109,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
99
109
  case 'number':
100
110
  {
101
111
  if (field.hasMany) {
102
- const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock;
112
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
103
113
  if (isLocalized) {
104
114
  hasLocalizedManyNumberField = true;
105
115
  }
@@ -175,7 +185,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
175
185
  }).onDelete('cascade'),
176
186
  parentIdx: (cols)=>index(`${selectTableName}_parent_idx`).on(cols.parent)
177
187
  };
178
- const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock;
188
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
179
189
  if (isLocalized) {
180
190
  baseColumns.locale = text('locale', {
181
191
  enum: locales
@@ -214,7 +224,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
214
224
  })
215
225
  }));
216
226
  } else {
217
- targetTable[fieldName] = withDefault(text(fieldName, {
227
+ targetTable[fieldName] = withDefault(text(columnName, {
218
228
  enum: options
219
229
  }), field);
220
230
  }
@@ -259,7 +269,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
259
269
  }).onDelete('cascade'),
260
270
  _parentIDIdx: (cols)=>index(`${arrayTableName}_parent_id_idx`).on(cols._parentID)
261
271
  };
262
- const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock;
272
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
263
273
  if (isLocalized) {
264
274
  baseColumns._locale = text('_locale', {
265
275
  enum: locales
@@ -271,12 +281,14 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
271
281
  baseColumns,
272
282
  baseExtraConfig,
273
283
  disableNotNull: disableNotNullFromHere,
284
+ disableRelsTableUnique: true,
274
285
  disableUnique,
275
286
  fields: disableUnique ? idToUUID(field.fields) : field.fields,
276
287
  rootRelationships: relationships,
277
288
  rootRelationsToBuild,
278
289
  rootTableIDColType,
279
290
  rootTableName,
291
+ rootUniqueRelationships: uniqueRelationships,
280
292
  tableName: arrayTableName,
281
293
  versions,
282
294
  withinLocalizedArrayOrBlock: isLocalized
@@ -382,7 +394,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
382
394
  _parentIDIdx: (cols)=>index(`${blockTableName}_parent_id_idx`).on(cols._parentID),
383
395
  _pathIdx: (cols)=>index(`${blockTableName}_path_idx`).on(cols._path)
384
396
  };
385
- const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock;
397
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
386
398
  if (isLocalized) {
387
399
  baseColumns._locale = text('_locale', {
388
400
  enum: locales
@@ -394,12 +406,14 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
394
406
  baseColumns,
395
407
  baseExtraConfig,
396
408
  disableNotNull: disableNotNullFromHere,
409
+ disableRelsTableUnique: true,
397
410
  disableUnique,
398
411
  fields: disableUnique ? idToUUID(block.fields) : block.fields,
399
412
  rootRelationships: relationships,
400
413
  rootRelationsToBuild,
401
414
  rootTableIDColType,
402
415
  rootTableName,
416
+ rootUniqueRelationships: uniqueRelationships,
403
417
  tableName: blockTableName,
404
418
  versions,
405
419
  withinLocalizedArrayOrBlock: isLocalized
@@ -494,6 +508,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
494
508
  fields: field.fields,
495
509
  forceLocalized,
496
510
  indexes,
511
+ joins,
497
512
  locales,
498
513
  localesColumns,
499
514
  localesIndexes,
@@ -504,6 +519,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
504
519
  rootRelationsToBuild,
505
520
  rootTableIDColType,
506
521
  rootTableName,
522
+ uniqueRelationships,
507
523
  versions,
508
524
  withinLocalizedArrayOrBlock
509
525
  });
@@ -538,6 +554,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
538
554
  fields: field.fields,
539
555
  forceLocalized: field.localized,
540
556
  indexes,
557
+ joins,
541
558
  locales,
542
559
  localesColumns,
543
560
  localesIndexes,
@@ -548,8 +565,9 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
548
565
  rootRelationsToBuild,
549
566
  rootTableIDColType,
550
567
  rootTableName,
568
+ uniqueRelationships,
551
569
  versions,
552
- withinLocalizedArrayOrBlock
570
+ withinLocalizedArrayOrBlock: withinLocalizedArrayOrBlock || field.localized
553
571
  });
554
572
  if (groupHasLocalizedField) {
555
573
  hasLocalizedField = true;
@@ -587,6 +605,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
587
605
  })),
588
606
  forceLocalized,
589
607
  indexes,
608
+ joins,
590
609
  locales,
591
610
  localesColumns,
592
611
  localesIndexes,
@@ -597,6 +616,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
597
616
  rootRelationsToBuild,
598
617
  rootTableIDColType,
599
618
  rootTableName,
619
+ uniqueRelationships,
600
620
  versions,
601
621
  withinLocalizedArrayOrBlock
602
622
  });
@@ -634,6 +654,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
634
654
  fields: field.fields,
635
655
  forceLocalized,
636
656
  indexes,
657
+ joins,
637
658
  locales,
638
659
  localesColumns,
639
660
  localesIndexes,
@@ -644,6 +665,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
644
665
  rootRelationsToBuild,
645
666
  rootTableIDColType,
646
667
  rootTableName,
668
+ uniqueRelationships,
647
669
  versions,
648
670
  withinLocalizedArrayOrBlock
649
671
  });
@@ -670,9 +692,17 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
670
692
  case 'relationship':
671
693
  case 'upload':
672
694
  if (Array.isArray(field.relationTo)) {
673
- field.relationTo.forEach((relation)=>relationships.add(relation));
695
+ field.relationTo.forEach((relation)=>{
696
+ relationships.add(relation);
697
+ if (field.unique && !disableUnique && !disableRelsTableUnique) {
698
+ uniqueRelationships.add(relation);
699
+ }
700
+ });
674
701
  } else if (field.hasMany) {
675
702
  relationships.add(field.relationTo);
703
+ if (field.unique && !disableUnique && !disableRelsTableUnique) {
704
+ uniqueRelationships.add(field.relationTo);
705
+ }
676
706
  } else {
677
707
  // simple relationships get a column on the targetTable with a foreign key to the relationTo table
678
708
  const relationshipConfig = adapter.payload.collections[field.relationTo].config;
@@ -697,7 +727,7 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
697
727
  // add relationship to table
698
728
  relationsToBuild.set(fieldName, {
699
729
  type: 'one',
700
- localized: adapter.payload.config.localization && field.localized,
730
+ localized: adapter.payload.config.localization && (field.localized || forceLocalized),
701
731
  target: tableName
702
732
  });
703
733
  // add notNull when not required
@@ -710,6 +740,28 @@ export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull,
710
740
  hasLocalizedRelationshipField = true;
711
741
  }
712
742
  break;
743
+ case 'join':
744
+ {
745
+ // fieldName could be 'posts' or 'group_posts'
746
+ // using `on` as the key for the relation
747
+ const localized = adapter.payload.config.localization && field.localized;
748
+ const fieldSchemaPath = `${fieldPrefix || ''}${field.name}`;
749
+ let target;
750
+ const joinConfig = joins[field.collection].find(({ schemaPath })=>fieldSchemaPath === schemaPath);
751
+ if (joinConfig.targetField.hasMany) {
752
+ target = `${adapter.tableNameMap.get(toSnakeCase(field.collection))}${adapter.relationshipsSuffix}`;
753
+ } else {
754
+ target = `${adapter.tableNameMap.get(toSnakeCase(field.collection))}${localized ? adapter.localesSuffix : ''}`;
755
+ }
756
+ relationsToBuild.set(fieldName, {
757
+ type: 'many',
758
+ // joins are not localized on the parent table
759
+ localized: false,
760
+ relationName: field.on.replaceAll('.', '_'),
761
+ target
762
+ });
763
+ break;
764
+ }
713
765
  default:
714
766
  break;
715
767
  }