@payloadcms/drizzle 3.0.0 → 3.0.1-canary.9494866

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 (37) hide show
  1. package/dist/postgres/schema/build.d.ts +40 -3
  2. package/dist/postgres/schema/build.d.ts.map +1 -1
  3. package/dist/postgres/schema/build.js +734 -2
  4. package/dist/postgres/schema/build.js.map +1 -1
  5. package/dist/postgres/schema/traverseFields.d.ts +0 -40
  6. package/dist/postgres/schema/traverseFields.d.ts.map +1 -1
  7. package/dist/postgres/schema/traverseFields.js +0 -741
  8. package/dist/postgres/schema/traverseFields.js.map +1 -1
  9. package/dist/queries/parseParams.d.ts +11 -0
  10. package/dist/queries/parseParams.d.ts.map +1 -1
  11. package/dist/queries/parseParams.js +23 -1
  12. package/dist/queries/parseParams.js.map +1 -1
  13. package/dist/transform/write/traverseFields.d.ts +52 -1
  14. package/dist/transform/write/traverseFields.d.ts.map +1 -1
  15. package/dist/transform/write/traverseFields.js +122 -2
  16. package/dist/transform/write/traverseFields.js.map +1 -1
  17. package/package.json +4 -4
  18. package/dist/postgres/createJSONQuery/convertPathToJSONTraversal.d.ts +0 -2
  19. package/dist/postgres/createJSONQuery/convertPathToJSONTraversal.d.ts.map +0 -1
  20. package/dist/postgres/createJSONQuery/convertPathToJSONTraversal.js +0 -16
  21. package/dist/postgres/createJSONQuery/convertPathToJSONTraversal.js.map +0 -1
  22. package/dist/postgres/createJSONQuery/formatJSONPathSegment.d.ts +0 -2
  23. package/dist/postgres/createJSONQuery/formatJSONPathSegment.d.ts.map +0 -1
  24. package/dist/postgres/createJSONQuery/formatJSONPathSegment.js +0 -5
  25. package/dist/postgres/createJSONQuery/formatJSONPathSegment.js.map +0 -1
  26. package/dist/queries/buildAndOrConditions.d.ts +0 -16
  27. package/dist/queries/buildAndOrConditions.d.ts.map +0 -1
  28. package/dist/queries/buildAndOrConditions.js +0 -26
  29. package/dist/queries/buildAndOrConditions.js.map +0 -1
  30. package/dist/transform/write/array.d.ts +0 -31
  31. package/dist/transform/write/array.d.ts.map +0 -1
  32. package/dist/transform/write/array.js +0 -62
  33. package/dist/transform/write/array.js.map +0 -1
  34. package/dist/transform/write/blocks.d.ts +0 -30
  35. package/dist/transform/write/blocks.d.ts.map +0 -1
  36. package/dist/transform/write/blocks.js +0 -66
  37. package/dist/transform/write/blocks.js.map +0 -1
@@ -1,12 +1,18 @@
1
1
  import { relations } from 'drizzle-orm';
2
- import { foreignKey, index, integer, numeric, serial, timestamp, unique, varchar } from 'drizzle-orm/pg-core';
2
+ import { boolean, foreignKey, index, integer, jsonb, numeric, PgNumericBuilder, PgUUIDBuilder, PgVarcharBuilder, serial, text, timestamp, unique, varchar } from 'drizzle-orm/pg-core';
3
+ import { InvalidConfiguration } from 'payload';
4
+ import { fieldAffectsData, fieldIsVirtual, optionIsObject } from 'payload/shared';
3
5
  import toSnakeCase from 'to-snake-case';
4
6
  import { createTableName } from '../../createTableName.js';
5
7
  import { buildIndexName } from '../../utilities/buildIndexName.js';
8
+ import { hasLocalesTable } from '../../utilities/hasLocalesTable.js';
9
+ import { validateExistingBlockIsIdentical } from '../../utilities/validateExistingBlockIsIdentical.js';
6
10
  import { createIndex } from './createIndex.js';
11
+ import { geometryColumn } from './geometryColumn.js';
12
+ import { idToUUID } from './idToUUID.js';
7
13
  import { parentIDColumnMap } from './parentIDColumnMap.js';
8
14
  import { setColumnID } from './setColumnID.js';
9
- import { traverseFields } from './traverseFields.js';
15
+ import { withDefault } from './withDefault.js';
10
16
  export const buildTable = ({ adapter, baseColumns = {}, baseExtraConfig = {}, disableNotNull, disableRelsTableUnique = false, disableUnique = false, fields, rootRelationships, rootRelationsToBuild, rootTableIDColType, rootTableName: incomingRootTableName, rootUniqueRelationships, tableName, timestamps, versions, withinLocalizedArrayOrBlock })=>{
11
17
  const isRoot = !incomingRootTableName;
12
18
  const rootTableName = incomingRootTableName || tableName;
@@ -400,5 +406,731 @@ export const buildTable = ({ adapter, baseColumns = {}, baseExtraConfig = {}, di
400
406
  relationsToBuild
401
407
  };
402
408
  };
409
+ 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 })=>{
410
+ const throwValidationError = true;
411
+ let hasLocalizedField = false;
412
+ let hasLocalizedRelationshipField = false;
413
+ let hasManyTextField = false;
414
+ let hasLocalizedManyTextField = false;
415
+ let hasManyNumberField = false;
416
+ let hasLocalizedManyNumberField = false;
417
+ let parentIDColType = 'integer';
418
+ if (columns.id instanceof PgUUIDBuilder) {
419
+ parentIDColType = 'uuid';
420
+ }
421
+ if (columns.id instanceof PgNumericBuilder) {
422
+ parentIDColType = 'numeric';
423
+ }
424
+ if (columns.id instanceof PgVarcharBuilder) {
425
+ parentIDColType = 'varchar';
426
+ }
427
+ fields.forEach((field)=>{
428
+ if ('name' in field && field.name === 'id') {
429
+ return;
430
+ }
431
+ if (fieldIsVirtual(field)) {
432
+ return;
433
+ }
434
+ let columnName;
435
+ let fieldName;
436
+ let targetTable = columns;
437
+ let targetIndexes = indexes;
438
+ if (fieldAffectsData(field)) {
439
+ columnName = `${columnPrefix || ''}${field.name[0] === '_' ? '_' : ''}${toSnakeCase(field.name)}`;
440
+ fieldName = `${fieldPrefix?.replace('.', '_') || ''}${field.name}`;
441
+ // If field is localized,
442
+ // add the column to the locale table instead of main table
443
+ if (adapter.payload.config.localization && (field.localized || forceLocalized) && field.type !== 'array' && field.type !== 'blocks' && ('hasMany' in field && field.hasMany !== true || !('hasMany' in field))) {
444
+ hasLocalizedField = true;
445
+ targetTable = localesColumns;
446
+ targetIndexes = localesIndexes;
447
+ }
448
+ if ((field.unique || field.index || [
449
+ 'relationship',
450
+ 'upload'
451
+ ].includes(field.type)) && ![
452
+ 'array',
453
+ 'blocks',
454
+ 'group'
455
+ ].includes(field.type) && !('hasMany' in field && field.hasMany === true) && !('relationTo' in field && Array.isArray(field.relationTo))) {
456
+ const unique = disableUnique !== true && field.unique;
457
+ if (unique) {
458
+ const constraintValue = `${fieldPrefix || ''}${field.name}`;
459
+ if (!adapter.fieldConstraints?.[rootTableName]) {
460
+ adapter.fieldConstraints[rootTableName] = {};
461
+ }
462
+ adapter.fieldConstraints[rootTableName][`${columnName}_idx`] = constraintValue;
463
+ }
464
+ const indexName = buildIndexName({
465
+ name: `${newTableName}_${columnName}`,
466
+ adapter
467
+ });
468
+ targetIndexes[indexName] = createIndex({
469
+ name: field.localized ? [
470
+ fieldName,
471
+ '_locale'
472
+ ] : fieldName,
473
+ indexName,
474
+ unique
475
+ });
476
+ }
477
+ }
478
+ switch(field.type){
479
+ case 'array':
480
+ {
481
+ const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull;
482
+ const arrayTableName = createTableName({
483
+ adapter,
484
+ config: field,
485
+ parentTableName: newTableName,
486
+ prefix: `${newTableName}_`,
487
+ throwValidationError,
488
+ versionsCustomName: versions
489
+ });
490
+ const baseColumns = {
491
+ _order: integer('_order').notNull(),
492
+ _parentID: parentIDColumnMap[parentIDColType]('_parent_id').notNull()
493
+ };
494
+ const baseExtraConfig = {
495
+ _orderIdx: (cols)=>index(`${arrayTableName}_order_idx`).on(cols._order),
496
+ _parentIDFk: (cols)=>foreignKey({
497
+ name: `${arrayTableName}_parent_id_fk`,
498
+ columns: [
499
+ cols['_parentID']
500
+ ],
501
+ foreignColumns: [
502
+ adapter.tables[parentTableName].id
503
+ ]
504
+ }).onDelete('cascade'),
505
+ _parentIDIdx: (cols)=>index(`${arrayTableName}_parent_id_idx`).on(cols._parentID)
506
+ };
507
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
508
+ if (isLocalized) {
509
+ baseColumns._locale = adapter.enums.enum__locales('_locale').notNull();
510
+ baseExtraConfig._localeIdx = (cols)=>index(`${arrayTableName}_locale_idx`).on(cols._locale);
511
+ }
512
+ const { hasLocalizedManyNumberField: subHasLocalizedManyNumberField, hasLocalizedManyTextField: subHasLocalizedManyTextField, hasLocalizedRelationshipField: subHasLocalizedRelationshipField, hasManyNumberField: subHasManyNumberField, hasManyTextField: subHasManyTextField, relationsToBuild: subRelationsToBuild } = buildTable({
513
+ adapter,
514
+ baseColumns,
515
+ baseExtraConfig,
516
+ disableNotNull: disableNotNullFromHere,
517
+ disableRelsTableUnique: true,
518
+ disableUnique,
519
+ fields: disableUnique ? idToUUID(field.fields) : field.fields,
520
+ rootRelationships: relationships,
521
+ rootRelationsToBuild,
522
+ rootTableIDColType,
523
+ rootTableName,
524
+ rootUniqueRelationships: uniqueRelationships,
525
+ tableName: arrayTableName,
526
+ versions,
527
+ withinLocalizedArrayOrBlock: isLocalized
528
+ });
529
+ if (subHasLocalizedManyNumberField) {
530
+ hasLocalizedManyNumberField = subHasLocalizedManyNumberField;
531
+ }
532
+ if (subHasLocalizedRelationshipField) {
533
+ hasLocalizedRelationshipField = subHasLocalizedRelationshipField;
534
+ }
535
+ if (subHasLocalizedManyTextField) {
536
+ hasLocalizedManyTextField = subHasLocalizedManyTextField;
537
+ }
538
+ if (subHasManyTextField) {
539
+ if (!hasManyTextField || subHasManyTextField === 'index') {
540
+ hasManyTextField = subHasManyTextField;
541
+ }
542
+ }
543
+ if (subHasManyNumberField) {
544
+ if (!hasManyNumberField || subHasManyNumberField === 'index') {
545
+ hasManyNumberField = subHasManyNumberField;
546
+ }
547
+ }
548
+ relationsToBuild.set(fieldName, {
549
+ type: 'many',
550
+ // arrays have their own localized table, independent of the base table.
551
+ localized: false,
552
+ target: arrayTableName
553
+ });
554
+ adapter.relations[`relations_${arrayTableName}`] = relations(adapter.tables[arrayTableName], ({ many, one })=>{
555
+ const result = {
556
+ _parentID: one(adapter.tables[parentTableName], {
557
+ fields: [
558
+ adapter.tables[arrayTableName]._parentID
559
+ ],
560
+ references: [
561
+ adapter.tables[parentTableName].id
562
+ ],
563
+ relationName: fieldName
564
+ })
565
+ };
566
+ if (hasLocalesTable(field.fields)) {
567
+ result._locales = many(adapter.tables[`${arrayTableName}${adapter.localesSuffix}`], {
568
+ relationName: '_locales'
569
+ });
570
+ }
571
+ subRelationsToBuild.forEach(({ type, localized, target }, key)=>{
572
+ if (type === 'one') {
573
+ const arrayWithLocalized = localized ? `${arrayTableName}${adapter.localesSuffix}` : arrayTableName;
574
+ result[key] = one(adapter.tables[target], {
575
+ fields: [
576
+ adapter.tables[arrayWithLocalized][key]
577
+ ],
578
+ references: [
579
+ adapter.tables[target].id
580
+ ],
581
+ relationName: key
582
+ });
583
+ }
584
+ if (type === 'many') {
585
+ result[key] = many(adapter.tables[target], {
586
+ relationName: key
587
+ });
588
+ }
589
+ });
590
+ return result;
591
+ });
592
+ break;
593
+ }
594
+ case 'blocks':
595
+ {
596
+ const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull;
597
+ field.blocks.forEach((block)=>{
598
+ const blockTableName = createTableName({
599
+ adapter,
600
+ config: block,
601
+ parentTableName: rootTableName,
602
+ prefix: `${rootTableName}_blocks_`,
603
+ throwValidationError,
604
+ versionsCustomName: versions
605
+ });
606
+ if (!adapter.tables[blockTableName]) {
607
+ const baseColumns = {
608
+ _order: integer('_order').notNull(),
609
+ _parentID: parentIDColumnMap[rootTableIDColType]('_parent_id').notNull(),
610
+ _path: text('_path').notNull()
611
+ };
612
+ const baseExtraConfig = {
613
+ _orderIdx: (cols)=>index(`${blockTableName}_order_idx`).on(cols._order),
614
+ _parentIdFk: (cols)=>foreignKey({
615
+ name: `${blockTableName}_parent_id_fk`,
616
+ columns: [
617
+ cols._parentID
618
+ ],
619
+ foreignColumns: [
620
+ adapter.tables[rootTableName].id
621
+ ]
622
+ }).onDelete('cascade'),
623
+ _parentIDIdx: (cols)=>index(`${blockTableName}_parent_id_idx`).on(cols._parentID),
624
+ _pathIdx: (cols)=>index(`${blockTableName}_path_idx`).on(cols._path)
625
+ };
626
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
627
+ if (isLocalized) {
628
+ baseColumns._locale = adapter.enums.enum__locales('_locale').notNull();
629
+ baseExtraConfig._localeIdx = (cols)=>index(`${blockTableName}_locale_idx`).on(cols._locale);
630
+ }
631
+ const { hasLocalizedManyNumberField: subHasLocalizedManyNumberField, hasLocalizedManyTextField: subHasLocalizedManyTextField, hasLocalizedRelationshipField: subHasLocalizedRelationshipField, hasManyNumberField: subHasManyNumberField, hasManyTextField: subHasManyTextField, relationsToBuild: subRelationsToBuild } = buildTable({
632
+ adapter,
633
+ baseColumns,
634
+ baseExtraConfig,
635
+ disableNotNull: disableNotNullFromHere,
636
+ disableRelsTableUnique: true,
637
+ disableUnique,
638
+ fields: disableUnique ? idToUUID(block.fields) : block.fields,
639
+ rootRelationships: relationships,
640
+ rootRelationsToBuild,
641
+ rootTableIDColType,
642
+ rootTableName,
643
+ rootUniqueRelationships: uniqueRelationships,
644
+ tableName: blockTableName,
645
+ versions,
646
+ withinLocalizedArrayOrBlock: isLocalized
647
+ });
648
+ if (subHasLocalizedManyNumberField) {
649
+ hasLocalizedManyNumberField = subHasLocalizedManyNumberField;
650
+ }
651
+ if (subHasLocalizedRelationshipField) {
652
+ hasLocalizedRelationshipField = subHasLocalizedRelationshipField;
653
+ }
654
+ if (subHasLocalizedManyTextField) {
655
+ hasLocalizedManyTextField = subHasLocalizedManyTextField;
656
+ }
657
+ if (subHasManyTextField) {
658
+ if (!hasManyTextField || subHasManyTextField === 'index') {
659
+ hasManyTextField = subHasManyTextField;
660
+ }
661
+ }
662
+ if (subHasManyNumberField) {
663
+ if (!hasManyNumberField || subHasManyNumberField === 'index') {
664
+ hasManyNumberField = subHasManyNumberField;
665
+ }
666
+ }
667
+ adapter.relations[`relations_${blockTableName}`] = relations(adapter.tables[blockTableName], ({ many, one })=>{
668
+ const result = {
669
+ _parentID: one(adapter.tables[rootTableName], {
670
+ fields: [
671
+ adapter.tables[blockTableName]._parentID
672
+ ],
673
+ references: [
674
+ adapter.tables[rootTableName].id
675
+ ],
676
+ relationName: `_blocks_${block.slug}`
677
+ })
678
+ };
679
+ if (hasLocalesTable(block.fields)) {
680
+ result._locales = many(adapter.tables[`${blockTableName}${adapter.localesSuffix}`], {
681
+ relationName: '_locales'
682
+ });
683
+ }
684
+ subRelationsToBuild.forEach(({ type, localized, target }, key)=>{
685
+ if (type === 'one') {
686
+ const blockWithLocalized = localized ? `${blockTableName}${adapter.localesSuffix}` : blockTableName;
687
+ result[key] = one(adapter.tables[target], {
688
+ fields: [
689
+ adapter.tables[blockWithLocalized][key]
690
+ ],
691
+ references: [
692
+ adapter.tables[target].id
693
+ ],
694
+ relationName: key
695
+ });
696
+ }
697
+ if (type === 'many') {
698
+ result[key] = many(adapter.tables[target], {
699
+ relationName: key
700
+ });
701
+ }
702
+ });
703
+ return result;
704
+ });
705
+ } else if (process.env.NODE_ENV !== 'production' && !versions) {
706
+ validateExistingBlockIsIdentical({
707
+ block,
708
+ localized: field.localized,
709
+ rootTableName,
710
+ table: adapter.tables[blockTableName],
711
+ tableLocales: adapter.tables[`${blockTableName}${adapter.localesSuffix}`]
712
+ });
713
+ }
714
+ // blocks relationships are defined from the collection or globals table down to the block, bypassing any subBlocks
715
+ rootRelationsToBuild.set(`_blocks_${block.slug}`, {
716
+ type: 'many',
717
+ // blocks are not localized on the parent table
718
+ localized: false,
719
+ target: blockTableName
720
+ });
721
+ });
722
+ break;
723
+ }
724
+ case 'checkbox':
725
+ {
726
+ targetTable[fieldName] = withDefault(boolean(columnName), field);
727
+ break;
728
+ }
729
+ case 'code':
730
+ case 'email':
731
+ case 'textarea':
732
+ {
733
+ targetTable[fieldName] = withDefault(varchar(columnName), field);
734
+ break;
735
+ }
736
+ case 'collapsible':
737
+ case 'row':
738
+ {
739
+ const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull;
740
+ const { hasLocalizedField: rowHasLocalizedField, hasLocalizedManyNumberField: rowHasLocalizedManyNumberField, hasLocalizedManyTextField: rowHasLocalizedManyTextField, hasLocalizedRelationshipField: rowHasLocalizedRelationshipField, hasManyNumberField: rowHasManyNumberField, hasManyTextField: rowHasManyTextField } = traverseFields({
741
+ adapter,
742
+ columnPrefix,
743
+ columns,
744
+ disableNotNull: disableNotNullFromHere,
745
+ disableUnique,
746
+ fieldPrefix,
747
+ fields: field.fields,
748
+ forceLocalized,
749
+ indexes,
750
+ localesColumns,
751
+ localesIndexes,
752
+ newTableName,
753
+ parentTableName,
754
+ relationships,
755
+ relationsToBuild,
756
+ rootRelationsToBuild,
757
+ rootTableIDColType,
758
+ rootTableName,
759
+ uniqueRelationships,
760
+ versions,
761
+ withinLocalizedArrayOrBlock
762
+ });
763
+ if (rowHasLocalizedField) {
764
+ hasLocalizedField = true;
765
+ }
766
+ if (rowHasLocalizedRelationshipField) {
767
+ hasLocalizedRelationshipField = true;
768
+ }
769
+ if (rowHasManyTextField) {
770
+ hasManyTextField = true;
771
+ }
772
+ if (rowHasLocalizedManyTextField) {
773
+ hasLocalizedManyTextField = true;
774
+ }
775
+ if (rowHasManyNumberField) {
776
+ hasManyNumberField = true;
777
+ }
778
+ if (rowHasLocalizedManyNumberField) {
779
+ hasLocalizedManyNumberField = true;
780
+ }
781
+ break;
782
+ }
783
+ case 'date':
784
+ {
785
+ targetTable[fieldName] = withDefault(timestamp(columnName, {
786
+ mode: 'string',
787
+ precision: 3,
788
+ withTimezone: true
789
+ }), field);
790
+ break;
791
+ }
792
+ case 'group':
793
+ case 'tab':
794
+ {
795
+ if (!('name' in field)) {
796
+ const { hasLocalizedField: groupHasLocalizedField, hasLocalizedManyNumberField: groupHasLocalizedManyNumberField, hasLocalizedManyTextField: groupHasLocalizedManyTextField, hasLocalizedRelationshipField: groupHasLocalizedRelationshipField, hasManyNumberField: groupHasManyNumberField, hasManyTextField: groupHasManyTextField } = traverseFields({
797
+ adapter,
798
+ columnPrefix,
799
+ columns,
800
+ disableNotNull,
801
+ disableUnique,
802
+ fieldPrefix,
803
+ fields: field.fields,
804
+ forceLocalized,
805
+ indexes,
806
+ localesColumns,
807
+ localesIndexes,
808
+ newTableName,
809
+ parentTableName,
810
+ relationships,
811
+ relationsToBuild,
812
+ rootRelationsToBuild,
813
+ rootTableIDColType,
814
+ rootTableName,
815
+ uniqueRelationships,
816
+ versions,
817
+ withinLocalizedArrayOrBlock
818
+ });
819
+ if (groupHasLocalizedField) {
820
+ hasLocalizedField = true;
821
+ }
822
+ if (groupHasLocalizedRelationshipField) {
823
+ hasLocalizedRelationshipField = true;
824
+ }
825
+ if (groupHasManyTextField) {
826
+ hasManyTextField = true;
827
+ }
828
+ if (groupHasLocalizedManyTextField) {
829
+ hasLocalizedManyTextField = true;
830
+ }
831
+ if (groupHasManyNumberField) {
832
+ hasManyNumberField = true;
833
+ }
834
+ if (groupHasLocalizedManyNumberField) {
835
+ hasLocalizedManyNumberField = true;
836
+ }
837
+ break;
838
+ }
839
+ const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull;
840
+ const { hasLocalizedField: groupHasLocalizedField, hasLocalizedManyNumberField: groupHasLocalizedManyNumberField, hasLocalizedManyTextField: groupHasLocalizedManyTextField, hasLocalizedRelationshipField: groupHasLocalizedRelationshipField, hasManyNumberField: groupHasManyNumberField, hasManyTextField: groupHasManyTextField } = traverseFields({
841
+ adapter,
842
+ columnPrefix: `${columnName}_`,
843
+ columns,
844
+ disableNotNull: disableNotNullFromHere,
845
+ disableUnique,
846
+ fieldPrefix: `${fieldName}.`,
847
+ fields: field.fields,
848
+ forceLocalized: field.localized,
849
+ indexes,
850
+ localesColumns,
851
+ localesIndexes,
852
+ newTableName: `${parentTableName}_${columnName}`,
853
+ parentTableName,
854
+ relationships,
855
+ relationsToBuild,
856
+ rootRelationsToBuild,
857
+ rootTableIDColType,
858
+ rootTableName,
859
+ uniqueRelationships,
860
+ versions,
861
+ withinLocalizedArrayOrBlock: withinLocalizedArrayOrBlock || field.localized
862
+ });
863
+ if (groupHasLocalizedField) {
864
+ hasLocalizedField = true;
865
+ }
866
+ if (groupHasLocalizedRelationshipField) {
867
+ hasLocalizedRelationshipField = true;
868
+ }
869
+ if (groupHasManyTextField) {
870
+ hasManyTextField = true;
871
+ }
872
+ if (groupHasLocalizedManyTextField) {
873
+ hasLocalizedManyTextField = true;
874
+ }
875
+ if (groupHasManyNumberField) {
876
+ hasManyNumberField = true;
877
+ }
878
+ if (groupHasLocalizedManyNumberField) {
879
+ hasLocalizedManyNumberField = true;
880
+ }
881
+ break;
882
+ }
883
+ case 'json':
884
+ case 'richText':
885
+ {
886
+ targetTable[fieldName] = withDefault(jsonb(columnName), field);
887
+ break;
888
+ }
889
+ case 'number':
890
+ {
891
+ if (field.hasMany) {
892
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
893
+ if (isLocalized) {
894
+ hasLocalizedManyNumberField = true;
895
+ }
896
+ if (field.index) {
897
+ hasManyNumberField = 'index';
898
+ } else if (!hasManyNumberField) {
899
+ hasManyNumberField = true;
900
+ }
901
+ if (field.unique) {
902
+ throw new InvalidConfiguration('Unique is not supported in Postgres for hasMany number fields.');
903
+ }
904
+ } else {
905
+ targetTable[fieldName] = withDefault(numeric(columnName), field);
906
+ }
907
+ break;
908
+ }
909
+ case 'point':
910
+ {
911
+ targetTable[fieldName] = withDefault(geometryColumn(columnName), field);
912
+ if (!adapter.extensions.postgis) {
913
+ adapter.extensions.postgis = true;
914
+ }
915
+ break;
916
+ }
917
+ case 'radio':
918
+ case 'select':
919
+ {
920
+ const enumName = createTableName({
921
+ adapter,
922
+ config: field,
923
+ parentTableName: newTableName,
924
+ prefix: `enum_${newTableName}_`,
925
+ target: 'enumName',
926
+ throwValidationError
927
+ });
928
+ adapter.enums[enumName] = adapter.pgSchema.enum(enumName, field.options.map((option)=>{
929
+ if (optionIsObject(option)) {
930
+ return option.value;
931
+ }
932
+ return option;
933
+ }));
934
+ if (field.type === 'select' && field.hasMany) {
935
+ const selectTableName = createTableName({
936
+ adapter,
937
+ config: field,
938
+ parentTableName: newTableName,
939
+ prefix: `${newTableName}_`,
940
+ throwValidationError,
941
+ versionsCustomName: versions
942
+ });
943
+ const baseColumns = {
944
+ order: integer('order').notNull(),
945
+ parent: parentIDColumnMap[parentIDColType]('parent_id').notNull(),
946
+ value: adapter.enums[enumName]('value')
947
+ };
948
+ const baseExtraConfig = {
949
+ orderIdx: (cols)=>index(`${selectTableName}_order_idx`).on(cols.order),
950
+ parentFk: (cols)=>foreignKey({
951
+ name: `${selectTableName}_parent_fk`,
952
+ columns: [
953
+ cols.parent
954
+ ],
955
+ foreignColumns: [
956
+ adapter.tables[parentTableName].id
957
+ ]
958
+ }).onDelete('cascade'),
959
+ parentIdx: (cols)=>index(`${selectTableName}_parent_idx`).on(cols.parent)
960
+ };
961
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
962
+ if (isLocalized) {
963
+ baseColumns.locale = adapter.enums.enum__locales('locale').notNull();
964
+ baseExtraConfig.localeIdx = (cols)=>index(`${selectTableName}_locale_idx`).on(cols.locale);
965
+ }
966
+ if (field.index) {
967
+ baseExtraConfig.value = (cols)=>index(`${selectTableName}_value_idx`).on(cols.value);
968
+ }
969
+ buildTable({
970
+ adapter,
971
+ baseColumns,
972
+ baseExtraConfig,
973
+ disableNotNull,
974
+ disableUnique,
975
+ fields: [],
976
+ rootTableName,
977
+ tableName: selectTableName,
978
+ versions
979
+ });
980
+ relationsToBuild.set(fieldName, {
981
+ type: 'many',
982
+ // selects have their own localized table, independent of the base table.
983
+ localized: false,
984
+ target: selectTableName
985
+ });
986
+ adapter.relations[`relations_${selectTableName}`] = relations(adapter.tables[selectTableName], ({ one })=>({
987
+ parent: one(adapter.tables[parentTableName], {
988
+ fields: [
989
+ adapter.tables[selectTableName].parent
990
+ ],
991
+ references: [
992
+ adapter.tables[parentTableName].id
993
+ ],
994
+ relationName: fieldName
995
+ })
996
+ }));
997
+ } else {
998
+ targetTable[fieldName] = withDefault(adapter.enums[enumName](columnName), field);
999
+ }
1000
+ break;
1001
+ }
1002
+ case 'relationship':
1003
+ case 'upload':
1004
+ if (Array.isArray(field.relationTo)) {
1005
+ field.relationTo.forEach((relation)=>{
1006
+ relationships.add(relation);
1007
+ if (field.unique && !disableUnique && !disableRelsTableUnique) {
1008
+ uniqueRelationships.add(relation);
1009
+ }
1010
+ });
1011
+ } else if (field.hasMany) {
1012
+ relationships.add(field.relationTo);
1013
+ if (field.unique && !disableUnique && !disableRelsTableUnique) {
1014
+ uniqueRelationships.add(field.relationTo);
1015
+ }
1016
+ } else {
1017
+ // simple relationships get a column on the targetTable with a foreign key to the relationTo table
1018
+ const relationshipConfig = adapter.payload.collections[field.relationTo].config;
1019
+ const tableName = adapter.tableNameMap.get(toSnakeCase(field.relationTo));
1020
+ // get the id type of the related collection
1021
+ let colType = adapter.idType === 'uuid' ? 'uuid' : 'integer';
1022
+ const relatedCollectionCustomID = relationshipConfig.fields.find((field)=>fieldAffectsData(field) && field.name === 'id');
1023
+ if (relatedCollectionCustomID?.type === 'number') {
1024
+ colType = 'numeric';
1025
+ }
1026
+ if (relatedCollectionCustomID?.type === 'text') {
1027
+ colType = 'varchar';
1028
+ }
1029
+ // make the foreign key column for relationship using the correct id column type
1030
+ targetTable[fieldName] = parentIDColumnMap[colType](`${columnName}_id`).references(()=>adapter.tables[tableName].id, {
1031
+ onDelete: 'set null'
1032
+ });
1033
+ // add relationship to table
1034
+ relationsToBuild.set(fieldName, {
1035
+ type: 'one',
1036
+ localized: adapter.payload.config.localization && (field.localized || forceLocalized),
1037
+ target: tableName
1038
+ });
1039
+ // add notNull when not required
1040
+ if (!disableNotNull && field.required && !field.admin?.condition) {
1041
+ targetTable[fieldName].notNull();
1042
+ }
1043
+ break;
1044
+ }
1045
+ if (Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock) {
1046
+ hasLocalizedRelationshipField = true;
1047
+ }
1048
+ break;
1049
+ case 'tabs':
1050
+ {
1051
+ const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull;
1052
+ const { hasLocalizedField: tabHasLocalizedField, hasLocalizedManyNumberField: tabHasLocalizedManyNumberField, hasLocalizedManyTextField: tabHasLocalizedManyTextField, hasLocalizedRelationshipField: tabHasLocalizedRelationshipField, hasManyNumberField: tabHasManyNumberField, hasManyTextField: tabHasManyTextField } = traverseFields({
1053
+ adapter,
1054
+ columnPrefix,
1055
+ columns,
1056
+ disableNotNull: disableNotNullFromHere,
1057
+ disableUnique,
1058
+ fieldPrefix,
1059
+ fields: field.tabs.map((tab)=>({
1060
+ ...tab,
1061
+ type: 'tab'
1062
+ })),
1063
+ forceLocalized,
1064
+ indexes,
1065
+ localesColumns,
1066
+ localesIndexes,
1067
+ newTableName,
1068
+ parentTableName,
1069
+ relationships,
1070
+ relationsToBuild,
1071
+ rootRelationsToBuild,
1072
+ rootTableIDColType,
1073
+ rootTableName,
1074
+ uniqueRelationships,
1075
+ versions,
1076
+ withinLocalizedArrayOrBlock
1077
+ });
1078
+ if (tabHasLocalizedField) {
1079
+ hasLocalizedField = true;
1080
+ }
1081
+ if (tabHasLocalizedRelationshipField) {
1082
+ hasLocalizedRelationshipField = true;
1083
+ }
1084
+ if (tabHasManyTextField) {
1085
+ hasManyTextField = true;
1086
+ }
1087
+ if (tabHasLocalizedManyTextField) {
1088
+ hasLocalizedManyTextField = true;
1089
+ }
1090
+ if (tabHasManyNumberField) {
1091
+ hasManyNumberField = true;
1092
+ }
1093
+ if (tabHasLocalizedManyNumberField) {
1094
+ hasLocalizedManyNumberField = true;
1095
+ }
1096
+ break;
1097
+ }
1098
+ case 'text':
1099
+ {
1100
+ if (field.hasMany) {
1101
+ const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized;
1102
+ if (isLocalized) {
1103
+ hasLocalizedManyTextField = true;
1104
+ }
1105
+ if (field.index) {
1106
+ hasManyTextField = 'index';
1107
+ } else if (!hasManyTextField) {
1108
+ hasManyTextField = true;
1109
+ }
1110
+ if (field.unique) {
1111
+ throw new InvalidConfiguration('Unique is not supported in Postgres for hasMany text fields.');
1112
+ }
1113
+ } else {
1114
+ targetTable[fieldName] = withDefault(varchar(columnName), field);
1115
+ }
1116
+ break;
1117
+ }
1118
+ default:
1119
+ break;
1120
+ }
1121
+ const condition = field.admin && field.admin.condition;
1122
+ if (!disableNotNull && targetTable[fieldName] && 'required' in field && field.required && !condition) {
1123
+ targetTable[fieldName].notNull();
1124
+ }
1125
+ });
1126
+ return {
1127
+ hasLocalizedField,
1128
+ hasLocalizedManyNumberField,
1129
+ hasLocalizedManyTextField,
1130
+ hasLocalizedRelationshipField,
1131
+ hasManyNumberField,
1132
+ hasManyTextField
1133
+ };
1134
+ };
403
1135
 
404
1136
  //# sourceMappingURL=build.js.map