@murumets-ee/entity 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +658 -51
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -64
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _$drizzle_orm0 from "drizzle-orm";
|
|
2
2
|
import { SQL } from "drizzle-orm";
|
|
3
3
|
import * as _$drizzle_orm_pg_core0 from "drizzle-orm/pg-core";
|
|
4
|
-
import { PgTableWithColumns } from "drizzle-orm/pg-core";
|
|
4
|
+
import { PgTable, PgTableWithColumns } from "drizzle-orm/pg-core";
|
|
5
5
|
import { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
6
6
|
|
|
7
7
|
//#region src/admin-config.d.ts
|
|
@@ -585,6 +585,13 @@ declare class ReferencedEntityError extends Error {
|
|
|
585
585
|
}
|
|
586
586
|
//#endregion
|
|
587
587
|
//#region src/schema-generator.d.ts
|
|
588
|
+
type AnyTable = PgTable<any>;
|
|
589
|
+
/**
|
|
590
|
+
* Convert a field config to a Drizzle column.
|
|
591
|
+
*
|
|
592
|
+
* @param nullable - When true, skips notNull and default constraints.
|
|
593
|
+
* Used for translation table columns (translations are partial overrides).
|
|
594
|
+
*/
|
|
588
595
|
/**
|
|
589
596
|
* Generate a runtime Drizzle schema from an entity definition.
|
|
590
597
|
* Every field becomes its own column — no JSONB.
|
|
@@ -613,16 +620,16 @@ declare function generateSchema(entity: Entity): _$drizzle_orm_pg_core0.PgTableW
|
|
|
613
620
|
};
|
|
614
621
|
dialect: "pg";
|
|
615
622
|
}>;
|
|
616
|
-
/**
|
|
617
|
-
* Generate TypeScript code string for an entity schema.
|
|
618
|
-
* Every field becomes its own column — no JSONB.
|
|
619
|
-
*/
|
|
620
|
-
declare function generateSchemaCode(entity: Entity): string;
|
|
621
623
|
/**
|
|
622
624
|
* Generate runtime translation table schema.
|
|
623
625
|
* Each translatable field gets its own nullable column.
|
|
626
|
+
*
|
|
627
|
+
* When `parent` is provided, `entityId` gets a `.references()` FK — used
|
|
628
|
+
* by `lumi migrate` so generated SQL includes `REFERENCES parent(id) ON
|
|
629
|
+
* DELETE CASCADE`. Callers that only need the table shape for query
|
|
630
|
+
* building (core/app.ts, content/plugin.ts) can omit `parent`.
|
|
624
631
|
*/
|
|
625
|
-
declare function generateTranslationSchema(entity: Entity): _$drizzle_orm_pg_core0.PgTableWithColumns<{
|
|
632
|
+
declare function generateTranslationSchema(entity: Entity, parent?: AnyTable): _$drizzle_orm_pg_core0.PgTableWithColumns<{
|
|
626
633
|
name: string;
|
|
627
634
|
schema: undefined;
|
|
628
635
|
columns: {
|
|
@@ -646,11 +653,6 @@ declare function generateTranslationSchema(entity: Entity): _$drizzle_orm_pg_cor
|
|
|
646
653
|
};
|
|
647
654
|
dialect: "pg";
|
|
648
655
|
}> | null;
|
|
649
|
-
/**
|
|
650
|
-
* Generate TypeScript code string for a translation table.
|
|
651
|
-
* Each translatable field gets its own nullable column.
|
|
652
|
-
*/
|
|
653
|
-
declare function generateTranslationSchemaCode(entity: Entity): string | null;
|
|
654
656
|
/**
|
|
655
657
|
* Check if an entity has any blocks fields
|
|
656
658
|
*/
|
|
@@ -661,8 +663,11 @@ declare function hasBlocksFields(entity: Entity): boolean;
|
|
|
661
663
|
*
|
|
662
664
|
* When blocks field has localized: false (default), locale is NULL (shared layout).
|
|
663
665
|
* When blocks field has localized: true, locale is set per-locale.
|
|
666
|
+
*
|
|
667
|
+
* `parent` is optional — when provided, emits a `.references()` FK (for
|
|
668
|
+
* migration generation); query-runtime callers can omit it.
|
|
664
669
|
*/
|
|
665
|
-
declare function generateLayoutSchema(entity: Entity): _$drizzle_orm_pg_core0.PgTableWithColumns<{
|
|
670
|
+
declare function generateLayoutSchema(entity: Entity, parent?: AnyTable): _$drizzle_orm_pg_core0.PgTableWithColumns<{
|
|
666
671
|
name: string;
|
|
667
672
|
schema: undefined;
|
|
668
673
|
columns: {
|
|
@@ -803,42 +808,12 @@ declare function isVersionable(entity: Entity): boolean;
|
|
|
803
808
|
* Requires both publishable() behavior AND at least one translatable field.
|
|
804
809
|
*/
|
|
805
810
|
declare function needsLocaleStatus(entity: Entity): boolean;
|
|
806
|
-
/**
|
|
807
|
-
* Generate TypeScript code string for a per-locale publish status table.
|
|
808
|
-
*/
|
|
809
|
-
declare function generateLocaleStatusCode(entity: Entity): string;
|
|
810
811
|
/**
|
|
811
812
|
* Check if an entity is publishable (has publishable() behavior).
|
|
812
813
|
*/
|
|
813
814
|
declare function isPublishable(entity: Entity): boolean;
|
|
814
|
-
/**
|
|
815
|
-
|
|
816
|
-
*/
|
|
817
|
-
declare function generateDraftsCode(entity: Entity): string;
|
|
818
|
-
/**
|
|
819
|
-
* Generate TypeScript code string for the shared content locks table.
|
|
820
|
-
*/
|
|
821
|
-
declare function generateContentLocksCode(): string;
|
|
822
|
-
/**
|
|
823
|
-
* Check if an entity has blocks fields with translatable block content (non-localized mode).
|
|
824
|
-
*/
|
|
825
|
-
declare function hasTranslatableBlocks(entity: Entity): boolean;
|
|
826
|
-
/**
|
|
827
|
-
* Generate TypeScript code string for a layout table (blocks storage).
|
|
828
|
-
*/
|
|
829
|
-
declare function generateLayoutCode(entity: Entity): string;
|
|
830
|
-
/**
|
|
831
|
-
* Generate TypeScript code string for a layout translation table.
|
|
832
|
-
*/
|
|
833
|
-
declare function generateLayoutTranslationCode(entity: Entity): string;
|
|
834
|
-
/**
|
|
835
|
-
* Generate TypeScript code string for a versions table.
|
|
836
|
-
*/
|
|
837
|
-
declare function generateVersionsCode(entity: Entity): string;
|
|
838
|
-
/**
|
|
839
|
-
* Generate layout translation table for non-localized blocks with translatable fields.
|
|
840
|
-
*/
|
|
841
|
-
declare function generateLayoutTranslationSchema(entity: Entity): _$drizzle_orm_pg_core0.PgTableWithColumns<{
|
|
815
|
+
/** Per-locale publish status table for publishable + translatable entities. */
|
|
816
|
+
declare function generateLocaleStatusSchema(entity: Entity, parent: AnyTable): _$drizzle_orm_pg_core0.PgTableWithColumns<{
|
|
842
817
|
name: string;
|
|
843
818
|
schema: undefined;
|
|
844
819
|
columns: {
|
|
@@ -859,8 +834,8 @@ declare function generateLayoutTranslationSchema(entity: Entity): _$drizzle_orm_
|
|
|
859
834
|
identity: undefined;
|
|
860
835
|
generated: undefined;
|
|
861
836
|
}, {}, {}>;
|
|
862
|
-
|
|
863
|
-
name: "
|
|
837
|
+
entityId: _$drizzle_orm_pg_core0.PgColumn<{
|
|
838
|
+
name: "entity_id";
|
|
864
839
|
tableName: string;
|
|
865
840
|
dataType: "string";
|
|
866
841
|
columnType: "PgUUID";
|
|
@@ -895,8 +870,105 @@ declare function generateLayoutTranslationSchema(entity: Entity): _$drizzle_orm_
|
|
|
895
870
|
}, {}, {
|
|
896
871
|
length: 10;
|
|
897
872
|
}>;
|
|
898
|
-
|
|
899
|
-
name: "
|
|
873
|
+
status: _$drizzle_orm_pg_core0.PgColumn<{
|
|
874
|
+
name: "status";
|
|
875
|
+
tableName: string;
|
|
876
|
+
dataType: "string";
|
|
877
|
+
columnType: "PgVarchar";
|
|
878
|
+
data: string;
|
|
879
|
+
driverParam: string;
|
|
880
|
+
notNull: true;
|
|
881
|
+
hasDefault: true;
|
|
882
|
+
isPrimaryKey: false;
|
|
883
|
+
isAutoincrement: false;
|
|
884
|
+
hasRuntimeDefault: false;
|
|
885
|
+
enumValues: [string, ...string[]];
|
|
886
|
+
baseColumn: never;
|
|
887
|
+
identity: undefined;
|
|
888
|
+
generated: undefined;
|
|
889
|
+
}, {}, {
|
|
890
|
+
length: 20;
|
|
891
|
+
}>;
|
|
892
|
+
publishedAt: _$drizzle_orm_pg_core0.PgColumn<{
|
|
893
|
+
name: "published_at";
|
|
894
|
+
tableName: string;
|
|
895
|
+
dataType: "date";
|
|
896
|
+
columnType: "PgTimestamp";
|
|
897
|
+
data: Date;
|
|
898
|
+
driverParam: string;
|
|
899
|
+
notNull: false;
|
|
900
|
+
hasDefault: false;
|
|
901
|
+
isPrimaryKey: false;
|
|
902
|
+
isAutoincrement: false;
|
|
903
|
+
hasRuntimeDefault: false;
|
|
904
|
+
enumValues: undefined;
|
|
905
|
+
baseColumn: never;
|
|
906
|
+
identity: undefined;
|
|
907
|
+
generated: undefined;
|
|
908
|
+
}, {}, {}>;
|
|
909
|
+
};
|
|
910
|
+
dialect: "pg";
|
|
911
|
+
}>;
|
|
912
|
+
/** Drafts overlay table for publishable entities. */
|
|
913
|
+
declare function generateDraftsSchema(entity: Entity, parent: AnyTable): _$drizzle_orm_pg_core0.PgTableWithColumns<{
|
|
914
|
+
name: string;
|
|
915
|
+
schema: undefined;
|
|
916
|
+
columns: {
|
|
917
|
+
id: _$drizzle_orm_pg_core0.PgColumn<{
|
|
918
|
+
name: "id";
|
|
919
|
+
tableName: string;
|
|
920
|
+
dataType: "string";
|
|
921
|
+
columnType: "PgUUID";
|
|
922
|
+
data: string;
|
|
923
|
+
driverParam: string;
|
|
924
|
+
notNull: true;
|
|
925
|
+
hasDefault: true;
|
|
926
|
+
isPrimaryKey: true;
|
|
927
|
+
isAutoincrement: false;
|
|
928
|
+
hasRuntimeDefault: false;
|
|
929
|
+
enumValues: undefined;
|
|
930
|
+
baseColumn: never;
|
|
931
|
+
identity: undefined;
|
|
932
|
+
generated: undefined;
|
|
933
|
+
}, {}, {}>;
|
|
934
|
+
entityId: _$drizzle_orm_pg_core0.PgColumn<{
|
|
935
|
+
name: "entity_id";
|
|
936
|
+
tableName: string;
|
|
937
|
+
dataType: "string";
|
|
938
|
+
columnType: "PgUUID";
|
|
939
|
+
data: string;
|
|
940
|
+
driverParam: string;
|
|
941
|
+
notNull: true;
|
|
942
|
+
hasDefault: false;
|
|
943
|
+
isPrimaryKey: false;
|
|
944
|
+
isAutoincrement: false;
|
|
945
|
+
hasRuntimeDefault: false;
|
|
946
|
+
enumValues: undefined;
|
|
947
|
+
baseColumn: never;
|
|
948
|
+
identity: undefined;
|
|
949
|
+
generated: undefined;
|
|
950
|
+
}, {}, {}>;
|
|
951
|
+
locale: _$drizzle_orm_pg_core0.PgColumn<{
|
|
952
|
+
name: "locale";
|
|
953
|
+
tableName: string;
|
|
954
|
+
dataType: "string";
|
|
955
|
+
columnType: "PgVarchar";
|
|
956
|
+
data: string;
|
|
957
|
+
driverParam: string;
|
|
958
|
+
notNull: true;
|
|
959
|
+
hasDefault: true;
|
|
960
|
+
isPrimaryKey: false;
|
|
961
|
+
isAutoincrement: false;
|
|
962
|
+
hasRuntimeDefault: false;
|
|
963
|
+
enumValues: [string, ...string[]];
|
|
964
|
+
baseColumn: never;
|
|
965
|
+
identity: undefined;
|
|
966
|
+
generated: undefined;
|
|
967
|
+
}, {}, {
|
|
968
|
+
length: 10;
|
|
969
|
+
}>;
|
|
970
|
+
data: _$drizzle_orm_pg_core0.PgColumn<{
|
|
971
|
+
name: "data";
|
|
900
972
|
tableName: string;
|
|
901
973
|
dataType: "json";
|
|
902
974
|
columnType: "PgJsonb";
|
|
@@ -912,9 +984,544 @@ declare function generateLayoutTranslationSchema(entity: Entity): _$drizzle_orm_
|
|
|
912
984
|
identity: undefined;
|
|
913
985
|
generated: undefined;
|
|
914
986
|
}, {}, {}>;
|
|
987
|
+
createdBy: _$drizzle_orm_pg_core0.PgColumn<{
|
|
988
|
+
name: "created_by";
|
|
989
|
+
tableName: string;
|
|
990
|
+
dataType: "string";
|
|
991
|
+
columnType: "PgVarchar";
|
|
992
|
+
data: string;
|
|
993
|
+
driverParam: string;
|
|
994
|
+
notNull: true;
|
|
995
|
+
hasDefault: false;
|
|
996
|
+
isPrimaryKey: false;
|
|
997
|
+
isAutoincrement: false;
|
|
998
|
+
hasRuntimeDefault: false;
|
|
999
|
+
enumValues: [string, ...string[]];
|
|
1000
|
+
baseColumn: never;
|
|
1001
|
+
identity: undefined;
|
|
1002
|
+
generated: undefined;
|
|
1003
|
+
}, {}, {
|
|
1004
|
+
length: 255;
|
|
1005
|
+
}>;
|
|
1006
|
+
createdByName: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1007
|
+
name: "created_by_name";
|
|
1008
|
+
tableName: string;
|
|
1009
|
+
dataType: "string";
|
|
1010
|
+
columnType: "PgVarchar";
|
|
1011
|
+
data: string;
|
|
1012
|
+
driverParam: string;
|
|
1013
|
+
notNull: false;
|
|
1014
|
+
hasDefault: false;
|
|
1015
|
+
isPrimaryKey: false;
|
|
1016
|
+
isAutoincrement: false;
|
|
1017
|
+
hasRuntimeDefault: false;
|
|
1018
|
+
enumValues: [string, ...string[]];
|
|
1019
|
+
baseColumn: never;
|
|
1020
|
+
identity: undefined;
|
|
1021
|
+
generated: undefined;
|
|
1022
|
+
}, {}, {
|
|
1023
|
+
length: 255;
|
|
1024
|
+
}>;
|
|
1025
|
+
createdAt: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1026
|
+
name: "created_at";
|
|
1027
|
+
tableName: string;
|
|
1028
|
+
dataType: "date";
|
|
1029
|
+
columnType: "PgTimestamp";
|
|
1030
|
+
data: Date;
|
|
1031
|
+
driverParam: string;
|
|
1032
|
+
notNull: true;
|
|
1033
|
+
hasDefault: true;
|
|
1034
|
+
isPrimaryKey: false;
|
|
1035
|
+
isAutoincrement: false;
|
|
1036
|
+
hasRuntimeDefault: false;
|
|
1037
|
+
enumValues: undefined;
|
|
1038
|
+
baseColumn: never;
|
|
1039
|
+
identity: undefined;
|
|
1040
|
+
generated: undefined;
|
|
1041
|
+
}, {}, {}>;
|
|
1042
|
+
updatedAt: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1043
|
+
name: "updated_at";
|
|
1044
|
+
tableName: string;
|
|
1045
|
+
dataType: "date";
|
|
1046
|
+
columnType: "PgTimestamp";
|
|
1047
|
+
data: Date;
|
|
1048
|
+
driverParam: string;
|
|
1049
|
+
notNull: true;
|
|
1050
|
+
hasDefault: true;
|
|
1051
|
+
isPrimaryKey: false;
|
|
1052
|
+
isAutoincrement: false;
|
|
1053
|
+
hasRuntimeDefault: false;
|
|
1054
|
+
enumValues: undefined;
|
|
1055
|
+
baseColumn: never;
|
|
1056
|
+
identity: undefined;
|
|
1057
|
+
generated: undefined;
|
|
1058
|
+
}, {}, {}>;
|
|
915
1059
|
};
|
|
916
1060
|
dialect: "pg";
|
|
917
|
-
}
|
|
1061
|
+
}>;
|
|
1062
|
+
/** Versions history table for versionable entities. */
|
|
1063
|
+
declare function generateVersionsSchema(entity: Entity, parent: AnyTable): _$drizzle_orm_pg_core0.PgTableWithColumns<{
|
|
1064
|
+
name: string;
|
|
1065
|
+
schema: undefined;
|
|
1066
|
+
columns: {
|
|
1067
|
+
id: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1068
|
+
name: "id";
|
|
1069
|
+
tableName: string;
|
|
1070
|
+
dataType: "string";
|
|
1071
|
+
columnType: "PgUUID";
|
|
1072
|
+
data: string;
|
|
1073
|
+
driverParam: string;
|
|
1074
|
+
notNull: true;
|
|
1075
|
+
hasDefault: true;
|
|
1076
|
+
isPrimaryKey: true;
|
|
1077
|
+
isAutoincrement: false;
|
|
1078
|
+
hasRuntimeDefault: false;
|
|
1079
|
+
enumValues: undefined;
|
|
1080
|
+
baseColumn: never;
|
|
1081
|
+
identity: undefined;
|
|
1082
|
+
generated: undefined;
|
|
1083
|
+
}, {}, {}>;
|
|
1084
|
+
entityId: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1085
|
+
name: "entity_id";
|
|
1086
|
+
tableName: string;
|
|
1087
|
+
dataType: "string";
|
|
1088
|
+
columnType: "PgUUID";
|
|
1089
|
+
data: string;
|
|
1090
|
+
driverParam: string;
|
|
1091
|
+
notNull: true;
|
|
1092
|
+
hasDefault: false;
|
|
1093
|
+
isPrimaryKey: false;
|
|
1094
|
+
isAutoincrement: false;
|
|
1095
|
+
hasRuntimeDefault: false;
|
|
1096
|
+
enumValues: undefined;
|
|
1097
|
+
baseColumn: never;
|
|
1098
|
+
identity: undefined;
|
|
1099
|
+
generated: undefined;
|
|
1100
|
+
}, {}, {}>;
|
|
1101
|
+
version: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1102
|
+
name: "version";
|
|
1103
|
+
tableName: string;
|
|
1104
|
+
dataType: "number";
|
|
1105
|
+
columnType: "PgInteger";
|
|
1106
|
+
data: number;
|
|
1107
|
+
driverParam: string | number;
|
|
1108
|
+
notNull: true;
|
|
1109
|
+
hasDefault: false;
|
|
1110
|
+
isPrimaryKey: false;
|
|
1111
|
+
isAutoincrement: false;
|
|
1112
|
+
hasRuntimeDefault: false;
|
|
1113
|
+
enumValues: undefined;
|
|
1114
|
+
baseColumn: never;
|
|
1115
|
+
identity: undefined;
|
|
1116
|
+
generated: undefined;
|
|
1117
|
+
}, {}, {}>;
|
|
1118
|
+
locale: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1119
|
+
name: "locale";
|
|
1120
|
+
tableName: string;
|
|
1121
|
+
dataType: "string";
|
|
1122
|
+
columnType: "PgVarchar";
|
|
1123
|
+
data: string;
|
|
1124
|
+
driverParam: string;
|
|
1125
|
+
notNull: true;
|
|
1126
|
+
hasDefault: true;
|
|
1127
|
+
isPrimaryKey: false;
|
|
1128
|
+
isAutoincrement: false;
|
|
1129
|
+
hasRuntimeDefault: false;
|
|
1130
|
+
enumValues: [string, ...string[]];
|
|
1131
|
+
baseColumn: never;
|
|
1132
|
+
identity: undefined;
|
|
1133
|
+
generated: undefined;
|
|
1134
|
+
}, {}, {
|
|
1135
|
+
length: 10;
|
|
1136
|
+
}>;
|
|
1137
|
+
data: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1138
|
+
name: "data";
|
|
1139
|
+
tableName: string;
|
|
1140
|
+
dataType: "json";
|
|
1141
|
+
columnType: "PgJsonb";
|
|
1142
|
+
data: unknown;
|
|
1143
|
+
driverParam: unknown;
|
|
1144
|
+
notNull: true;
|
|
1145
|
+
hasDefault: false;
|
|
1146
|
+
isPrimaryKey: false;
|
|
1147
|
+
isAutoincrement: false;
|
|
1148
|
+
hasRuntimeDefault: false;
|
|
1149
|
+
enumValues: undefined;
|
|
1150
|
+
baseColumn: never;
|
|
1151
|
+
identity: undefined;
|
|
1152
|
+
generated: undefined;
|
|
1153
|
+
}, {}, {}>;
|
|
1154
|
+
delta: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1155
|
+
name: "delta";
|
|
1156
|
+
tableName: string;
|
|
1157
|
+
dataType: "json";
|
|
1158
|
+
columnType: "PgJsonb";
|
|
1159
|
+
data: unknown;
|
|
1160
|
+
driverParam: unknown;
|
|
1161
|
+
notNull: false;
|
|
1162
|
+
hasDefault: false;
|
|
1163
|
+
isPrimaryKey: false;
|
|
1164
|
+
isAutoincrement: false;
|
|
1165
|
+
hasRuntimeDefault: false;
|
|
1166
|
+
enumValues: undefined;
|
|
1167
|
+
baseColumn: never;
|
|
1168
|
+
identity: undefined;
|
|
1169
|
+
generated: undefined;
|
|
1170
|
+
}, {}, {}>;
|
|
1171
|
+
status: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1172
|
+
name: "status";
|
|
1173
|
+
tableName: string;
|
|
1174
|
+
dataType: "string";
|
|
1175
|
+
columnType: "PgVarchar";
|
|
1176
|
+
data: string;
|
|
1177
|
+
driverParam: string;
|
|
1178
|
+
notNull: false;
|
|
1179
|
+
hasDefault: false;
|
|
1180
|
+
isPrimaryKey: false;
|
|
1181
|
+
isAutoincrement: false;
|
|
1182
|
+
hasRuntimeDefault: false;
|
|
1183
|
+
enumValues: [string, ...string[]];
|
|
1184
|
+
baseColumn: never;
|
|
1185
|
+
identity: undefined;
|
|
1186
|
+
generated: undefined;
|
|
1187
|
+
}, {}, {
|
|
1188
|
+
length: 20;
|
|
1189
|
+
}>;
|
|
1190
|
+
createdBy: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1191
|
+
name: "created_by";
|
|
1192
|
+
tableName: string;
|
|
1193
|
+
dataType: "string";
|
|
1194
|
+
columnType: "PgVarchar";
|
|
1195
|
+
data: string;
|
|
1196
|
+
driverParam: string;
|
|
1197
|
+
notNull: false;
|
|
1198
|
+
hasDefault: false;
|
|
1199
|
+
isPrimaryKey: false;
|
|
1200
|
+
isAutoincrement: false;
|
|
1201
|
+
hasRuntimeDefault: false;
|
|
1202
|
+
enumValues: [string, ...string[]];
|
|
1203
|
+
baseColumn: never;
|
|
1204
|
+
identity: undefined;
|
|
1205
|
+
generated: undefined;
|
|
1206
|
+
}, {}, {
|
|
1207
|
+
length: 255;
|
|
1208
|
+
}>;
|
|
1209
|
+
createdByName: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1210
|
+
name: "created_by_name";
|
|
1211
|
+
tableName: string;
|
|
1212
|
+
dataType: "string";
|
|
1213
|
+
columnType: "PgVarchar";
|
|
1214
|
+
data: string;
|
|
1215
|
+
driverParam: string;
|
|
1216
|
+
notNull: false;
|
|
1217
|
+
hasDefault: false;
|
|
1218
|
+
isPrimaryKey: false;
|
|
1219
|
+
isAutoincrement: false;
|
|
1220
|
+
hasRuntimeDefault: false;
|
|
1221
|
+
enumValues: [string, ...string[]];
|
|
1222
|
+
baseColumn: never;
|
|
1223
|
+
identity: undefined;
|
|
1224
|
+
generated: undefined;
|
|
1225
|
+
}, {}, {
|
|
1226
|
+
length: 255;
|
|
1227
|
+
}>;
|
|
1228
|
+
createdAt: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1229
|
+
name: "created_at";
|
|
1230
|
+
tableName: string;
|
|
1231
|
+
dataType: "date";
|
|
1232
|
+
columnType: "PgTimestamp";
|
|
1233
|
+
data: Date;
|
|
1234
|
+
driverParam: string;
|
|
1235
|
+
notNull: true;
|
|
1236
|
+
hasDefault: true;
|
|
1237
|
+
isPrimaryKey: false;
|
|
1238
|
+
isAutoincrement: false;
|
|
1239
|
+
hasRuntimeDefault: false;
|
|
1240
|
+
enumValues: undefined;
|
|
1241
|
+
baseColumn: never;
|
|
1242
|
+
identity: undefined;
|
|
1243
|
+
generated: undefined;
|
|
1244
|
+
}, {}, {}>;
|
|
1245
|
+
isAutosave: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1246
|
+
name: "is_autosave";
|
|
1247
|
+
tableName: string;
|
|
1248
|
+
dataType: "boolean";
|
|
1249
|
+
columnType: "PgBoolean";
|
|
1250
|
+
data: boolean;
|
|
1251
|
+
driverParam: boolean;
|
|
1252
|
+
notNull: true;
|
|
1253
|
+
hasDefault: true;
|
|
1254
|
+
isPrimaryKey: false;
|
|
1255
|
+
isAutoincrement: false;
|
|
1256
|
+
hasRuntimeDefault: false;
|
|
1257
|
+
enumValues: undefined;
|
|
1258
|
+
baseColumn: never;
|
|
1259
|
+
identity: undefined;
|
|
1260
|
+
generated: undefined;
|
|
1261
|
+
}, {}, {}>;
|
|
1262
|
+
};
|
|
1263
|
+
dialect: "pg";
|
|
1264
|
+
}>;
|
|
1265
|
+
/**
|
|
1266
|
+
* Shared content locks table — one per project, independent of any entity.
|
|
1267
|
+
* Included exactly once in `buildRuntimeSchema()` when any entity is publishable.
|
|
1268
|
+
*/
|
|
1269
|
+
declare function generateContentLocksSchema(): _$drizzle_orm_pg_core0.PgTableWithColumns<{
|
|
1270
|
+
name: "toolkit_content_locks";
|
|
1271
|
+
schema: undefined;
|
|
1272
|
+
columns: {
|
|
1273
|
+
id: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1274
|
+
name: "id";
|
|
1275
|
+
tableName: "toolkit_content_locks";
|
|
1276
|
+
dataType: "string";
|
|
1277
|
+
columnType: "PgUUID";
|
|
1278
|
+
data: string;
|
|
1279
|
+
driverParam: string;
|
|
1280
|
+
notNull: true;
|
|
1281
|
+
hasDefault: true;
|
|
1282
|
+
isPrimaryKey: true;
|
|
1283
|
+
isAutoincrement: false;
|
|
1284
|
+
hasRuntimeDefault: false;
|
|
1285
|
+
enumValues: undefined;
|
|
1286
|
+
baseColumn: never;
|
|
1287
|
+
identity: undefined;
|
|
1288
|
+
generated: undefined;
|
|
1289
|
+
}, {}, {}>;
|
|
1290
|
+
entityType: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1291
|
+
name: "entity_type";
|
|
1292
|
+
tableName: "toolkit_content_locks";
|
|
1293
|
+
dataType: "string";
|
|
1294
|
+
columnType: "PgVarchar";
|
|
1295
|
+
data: string;
|
|
1296
|
+
driverParam: string;
|
|
1297
|
+
notNull: true;
|
|
1298
|
+
hasDefault: false;
|
|
1299
|
+
isPrimaryKey: false;
|
|
1300
|
+
isAutoincrement: false;
|
|
1301
|
+
hasRuntimeDefault: false;
|
|
1302
|
+
enumValues: [string, ...string[]];
|
|
1303
|
+
baseColumn: never;
|
|
1304
|
+
identity: undefined;
|
|
1305
|
+
generated: undefined;
|
|
1306
|
+
}, {}, {
|
|
1307
|
+
length: 100;
|
|
1308
|
+
}>;
|
|
1309
|
+
entityId: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1310
|
+
name: "entity_id";
|
|
1311
|
+
tableName: "toolkit_content_locks";
|
|
1312
|
+
dataType: "string";
|
|
1313
|
+
columnType: "PgVarchar";
|
|
1314
|
+
data: string;
|
|
1315
|
+
driverParam: string;
|
|
1316
|
+
notNull: true;
|
|
1317
|
+
hasDefault: false;
|
|
1318
|
+
isPrimaryKey: false;
|
|
1319
|
+
isAutoincrement: false;
|
|
1320
|
+
hasRuntimeDefault: false;
|
|
1321
|
+
enumValues: [string, ...string[]];
|
|
1322
|
+
baseColumn: never;
|
|
1323
|
+
identity: undefined;
|
|
1324
|
+
generated: undefined;
|
|
1325
|
+
}, {}, {
|
|
1326
|
+
length: 255;
|
|
1327
|
+
}>;
|
|
1328
|
+
locale: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1329
|
+
name: "locale";
|
|
1330
|
+
tableName: "toolkit_content_locks";
|
|
1331
|
+
dataType: "string";
|
|
1332
|
+
columnType: "PgVarchar";
|
|
1333
|
+
data: string;
|
|
1334
|
+
driverParam: string;
|
|
1335
|
+
notNull: true;
|
|
1336
|
+
hasDefault: true;
|
|
1337
|
+
isPrimaryKey: false;
|
|
1338
|
+
isAutoincrement: false;
|
|
1339
|
+
hasRuntimeDefault: false;
|
|
1340
|
+
enumValues: [string, ...string[]];
|
|
1341
|
+
baseColumn: never;
|
|
1342
|
+
identity: undefined;
|
|
1343
|
+
generated: undefined;
|
|
1344
|
+
}, {}, {
|
|
1345
|
+
length: 10;
|
|
1346
|
+
}>;
|
|
1347
|
+
lockedBy: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1348
|
+
name: "locked_by";
|
|
1349
|
+
tableName: "toolkit_content_locks";
|
|
1350
|
+
dataType: "string";
|
|
1351
|
+
columnType: "PgVarchar";
|
|
1352
|
+
data: string;
|
|
1353
|
+
driverParam: string;
|
|
1354
|
+
notNull: true;
|
|
1355
|
+
hasDefault: false;
|
|
1356
|
+
isPrimaryKey: false;
|
|
1357
|
+
isAutoincrement: false;
|
|
1358
|
+
hasRuntimeDefault: false;
|
|
1359
|
+
enumValues: [string, ...string[]];
|
|
1360
|
+
baseColumn: never;
|
|
1361
|
+
identity: undefined;
|
|
1362
|
+
generated: undefined;
|
|
1363
|
+
}, {}, {
|
|
1364
|
+
length: 255;
|
|
1365
|
+
}>;
|
|
1366
|
+
lockedByName: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1367
|
+
name: "locked_by_name";
|
|
1368
|
+
tableName: "toolkit_content_locks";
|
|
1369
|
+
dataType: "string";
|
|
1370
|
+
columnType: "PgVarchar";
|
|
1371
|
+
data: string;
|
|
1372
|
+
driverParam: string;
|
|
1373
|
+
notNull: false;
|
|
1374
|
+
hasDefault: false;
|
|
1375
|
+
isPrimaryKey: false;
|
|
1376
|
+
isAutoincrement: false;
|
|
1377
|
+
hasRuntimeDefault: false;
|
|
1378
|
+
enumValues: [string, ...string[]];
|
|
1379
|
+
baseColumn: never;
|
|
1380
|
+
identity: undefined;
|
|
1381
|
+
generated: undefined;
|
|
1382
|
+
}, {}, {
|
|
1383
|
+
length: 255;
|
|
1384
|
+
}>;
|
|
1385
|
+
lockedAt: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1386
|
+
name: "locked_at";
|
|
1387
|
+
tableName: "toolkit_content_locks";
|
|
1388
|
+
dataType: "date";
|
|
1389
|
+
columnType: "PgTimestamp";
|
|
1390
|
+
data: Date;
|
|
1391
|
+
driverParam: string;
|
|
1392
|
+
notNull: true;
|
|
1393
|
+
hasDefault: true;
|
|
1394
|
+
isPrimaryKey: false;
|
|
1395
|
+
isAutoincrement: false;
|
|
1396
|
+
hasRuntimeDefault: false;
|
|
1397
|
+
enumValues: undefined;
|
|
1398
|
+
baseColumn: never;
|
|
1399
|
+
identity: undefined;
|
|
1400
|
+
generated: undefined;
|
|
1401
|
+
}, {}, {}>;
|
|
1402
|
+
expiresAt: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1403
|
+
name: "expires_at";
|
|
1404
|
+
tableName: "toolkit_content_locks";
|
|
1405
|
+
dataType: "date";
|
|
1406
|
+
columnType: "PgTimestamp";
|
|
1407
|
+
data: Date;
|
|
1408
|
+
driverParam: string;
|
|
1409
|
+
notNull: true;
|
|
1410
|
+
hasDefault: false;
|
|
1411
|
+
isPrimaryKey: false;
|
|
1412
|
+
isAutoincrement: false;
|
|
1413
|
+
hasRuntimeDefault: false;
|
|
1414
|
+
enumValues: undefined;
|
|
1415
|
+
baseColumn: never;
|
|
1416
|
+
identity: undefined;
|
|
1417
|
+
generated: undefined;
|
|
1418
|
+
}, {}, {}>;
|
|
1419
|
+
};
|
|
1420
|
+
dialect: "pg";
|
|
1421
|
+
}>;
|
|
1422
|
+
/**
|
|
1423
|
+
* Check if an entity has blocks fields with translatable block content (non-localized mode).
|
|
1424
|
+
*/
|
|
1425
|
+
declare function hasTranslatableBlocks(entity: Entity): boolean;
|
|
1426
|
+
/**
|
|
1427
|
+
* Generate layout translation table for non-localized blocks with translatable fields.
|
|
1428
|
+
*
|
|
1429
|
+
* `layoutParent` is optional — when provided, emits a `.references()` FK
|
|
1430
|
+
* pointing at the corresponding `{entity}_layout` table (for migration
|
|
1431
|
+
* generation).
|
|
1432
|
+
*/
|
|
1433
|
+
declare function generateLayoutTranslationSchema(entity: Entity, layoutParent?: AnyTable): _$drizzle_orm_pg_core0.PgTableWithColumns<{
|
|
1434
|
+
name: string;
|
|
1435
|
+
schema: undefined;
|
|
1436
|
+
columns: {
|
|
1437
|
+
id: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1438
|
+
name: "id";
|
|
1439
|
+
tableName: string;
|
|
1440
|
+
dataType: "string";
|
|
1441
|
+
columnType: "PgUUID";
|
|
1442
|
+
data: string;
|
|
1443
|
+
driverParam: string;
|
|
1444
|
+
notNull: true;
|
|
1445
|
+
hasDefault: true;
|
|
1446
|
+
isPrimaryKey: true;
|
|
1447
|
+
isAutoincrement: false;
|
|
1448
|
+
hasRuntimeDefault: false;
|
|
1449
|
+
enumValues: undefined;
|
|
1450
|
+
baseColumn: never;
|
|
1451
|
+
identity: undefined;
|
|
1452
|
+
generated: undefined;
|
|
1453
|
+
}, {}, {}>;
|
|
1454
|
+
layoutId: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1455
|
+
name: "layout_id";
|
|
1456
|
+
tableName: string;
|
|
1457
|
+
dataType: "string";
|
|
1458
|
+
columnType: "PgUUID";
|
|
1459
|
+
data: string;
|
|
1460
|
+
driverParam: string;
|
|
1461
|
+
notNull: true;
|
|
1462
|
+
hasDefault: false;
|
|
1463
|
+
isPrimaryKey: false;
|
|
1464
|
+
isAutoincrement: false;
|
|
1465
|
+
hasRuntimeDefault: false;
|
|
1466
|
+
enumValues: undefined;
|
|
1467
|
+
baseColumn: never;
|
|
1468
|
+
identity: undefined;
|
|
1469
|
+
generated: undefined;
|
|
1470
|
+
}, {}, {}>;
|
|
1471
|
+
locale: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1472
|
+
name: "locale";
|
|
1473
|
+
tableName: string;
|
|
1474
|
+
dataType: "string";
|
|
1475
|
+
columnType: "PgVarchar";
|
|
1476
|
+
data: string;
|
|
1477
|
+
driverParam: string;
|
|
1478
|
+
notNull: true;
|
|
1479
|
+
hasDefault: false;
|
|
1480
|
+
isPrimaryKey: false;
|
|
1481
|
+
isAutoincrement: false;
|
|
1482
|
+
hasRuntimeDefault: false;
|
|
1483
|
+
enumValues: [string, ...string[]];
|
|
1484
|
+
baseColumn: never;
|
|
1485
|
+
identity: undefined;
|
|
1486
|
+
generated: undefined;
|
|
1487
|
+
}, {}, {
|
|
1488
|
+
length: 10;
|
|
1489
|
+
}>;
|
|
1490
|
+
fields: _$drizzle_orm_pg_core0.PgColumn<{
|
|
1491
|
+
name: "fields";
|
|
1492
|
+
tableName: string;
|
|
1493
|
+
dataType: "json";
|
|
1494
|
+
columnType: "PgJsonb";
|
|
1495
|
+
data: unknown;
|
|
1496
|
+
driverParam: unknown;
|
|
1497
|
+
notNull: true;
|
|
1498
|
+
hasDefault: false;
|
|
1499
|
+
isPrimaryKey: false;
|
|
1500
|
+
isAutoincrement: false;
|
|
1501
|
+
hasRuntimeDefault: false;
|
|
1502
|
+
enumValues: undefined;
|
|
1503
|
+
baseColumn: never;
|
|
1504
|
+
identity: undefined;
|
|
1505
|
+
generated: undefined;
|
|
1506
|
+
}, {}, {}>;
|
|
1507
|
+
};
|
|
1508
|
+
dialect: "pg";
|
|
1509
|
+
}> | null;
|
|
1510
|
+
/**
|
|
1511
|
+
* Build the full runtime schema map for a list of entities.
|
|
1512
|
+
*
|
|
1513
|
+
* Returns a `Record<string, PgTable>` suitable for feeding into
|
|
1514
|
+
* `drizzle-kit/api`'s `generateDrizzleJson()`. Includes every table
|
|
1515
|
+
* that would have been emitted into `generated/schema.ts` by the old
|
|
1516
|
+
* codegen pipeline: main entity, translations, layout, layout
|
|
1517
|
+
* translations, versions, drafts, locale status, and the shared
|
|
1518
|
+
* content locks table.
|
|
1519
|
+
*
|
|
1520
|
+
* This is the single entry point used by `lumi migrate` — plugin
|
|
1521
|
+
* internal tables are added separately by reading each plugin's
|
|
1522
|
+
* `tables` field.
|
|
1523
|
+
*/
|
|
1524
|
+
declare function buildEntitySchemaMap(entities: Entity[]): Record<string, AnyTable>;
|
|
918
1525
|
//#endregion
|
|
919
|
-
export { type AuditableFields, type Behavior, type BehaviorFactory, type BlockDefinitionRef, type BlocksField, type BooleanField, CountCache, type CountCacheLike, type CursorInput, type DateField, type Entity, type EntityAdminConfig, type EntityDefinition, type EntityInput, type EntityUsage, type FieldConfig, type FieldToTS, type HierarchicalFields, type IdField, type InferCreateInput, type InferEntity, type InferEntityDTO, type InferUpdateInput, type JsonField, type MediaField, type NumberField, type PublishableFields, type ReferenceField, ReferencedEntityError, type RevisionableFields, type RichTextField, type SelectField, type SlugField, type SluggableFields, type SluggableOptions, type TextField, auditable, behavior, buildCursorCondition, decodeCursor, defineEntity, encodeCursor, estimateRowCount, field,
|
|
1526
|
+
export { type AuditableFields, type Behavior, type BehaviorFactory, type BlockDefinitionRef, type BlocksField, type BooleanField, CountCache, type CountCacheLike, type CursorInput, type DateField, type Entity, type EntityAdminConfig, type EntityDefinition, type EntityInput, type EntityUsage, type FieldConfig, type FieldToTS, type HierarchicalFields, type IdField, type InferCreateInput, type InferEntity, type InferEntityDTO, type InferUpdateInput, type JsonField, type MediaField, type NumberField, type PublishableFields, type ReferenceField, ReferencedEntityError, type RevisionableFields, type RichTextField, type SelectField, type SlugField, type SluggableFields, type SluggableOptions, type TextField, auditable, behavior, buildCursorCondition, buildEntitySchemaMap, decodeCursor, defineEntity, encodeCursor, estimateRowCount, field, generateContentLocksSchema, generateDraftsSchema, generateLayoutSchema, generateLayoutTranslationSchema, generateLocaleStatusSchema, generateSchema, generateTranslationSchema, generateVersionsSchema, hasBlocksFields, hasTranslatableBlocks, hierarchical, isPublishable, isVersionable, needsLocaleStatus, publishable, revisionable, sluggable, slugify, timestamped };
|
|
920
1527
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/admin-config.ts","../src/fields/base.ts","../src/types/infer.ts","../src/behaviors/types.ts","../src/behaviors/auditable.ts","../src/behaviors/hierarchical.ts","../src/behaviors/publishable.ts","../src/behaviors/revisionable.ts","../src/behaviors/sluggable.ts","../src/fields/builders.ts","../src/behaviors/timestamped.ts","../src/behaviors/index.ts","../src/count-cache.ts","../src/count-estimate.ts","../src/cursor.ts","../src/define-entity.ts","../src/refs/find-usages.ts","../src/refs/errors.ts","../src/schema-generator.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/admin-config.ts","../src/fields/base.ts","../src/types/infer.ts","../src/behaviors/types.ts","../src/behaviors/auditable.ts","../src/behaviors/hierarchical.ts","../src/behaviors/publishable.ts","../src/behaviors/revisionable.ts","../src/behaviors/sluggable.ts","../src/fields/builders.ts","../src/behaviors/timestamped.ts","../src/behaviors/index.ts","../src/count-cache.ts","../src/count-estimate.ts","../src/cursor.ts","../src/define-entity.ts","../src/refs/find-usages.ts","../src/refs/errors.ts","../src/schema-generator.ts"],"mappings":";;;;;;;;;;;UAIiB,iBAAA;;EAEf,KAAA;EAFe;EAIf,KAAA;;EAEA,aAAA;EAJA;EAMA,IAAA;EAFA;EAIA,WAAA;EAAA;EAEA,MAAA;EAEA;EAAA,YAAA;EAIA;EAFA,aAAA;EAEkC;EAAlC,cAAA,GAAiB,MAAA;IAAiB,KAAA;IAAgB,WAAA;IAAsB,WAAA;EAAA;EAQxE;EANA,WAAA;EAUA;EARA,oBAAA;EAoBA;EAlBA,QAAA;EAuBiB;EArBjB,UAAA;;EAEA,aAAA;;EAEA,SAAA;EC7B8B;;;;;EDmC9B,MAAA;EC/BA;;;;;EDqCA,YAAA;ECjCM;AAIR;;;EDkCE,iBAAA;AAAA;;;;;;;UC9Ce,eAAA;EACf,QAAA;EACA,OAAA;EACA,YAAA;EACA,OAAA;EACA,MAAA;EACA,MAAA;IACE,IAAA;IACA,IAAA;EAAA;AAAA;AAAA,UAIa,OAAA,SAAgB,eAAA;EAC/B,IAAA;AAAA;AAAA,UAGe,SAAA,SAAkB,eAAA;EACjC,IAAA;EACA,SAAA;EACA,SAAA;EACA,OAAA,GAAU,MAAA;AAAA;AAAA,UAGK,WAAA,SAAoB,eAAA;EACnC,IAAA;EACA,GAAA;EACA,GAAA;EACA,OAAA;AAAA;AAAA,UAGe,YAAA,SAAqB,eAAA;EACpC,IAAA;AAAA;AAAA,UAGe,SAAA,SAAkB,eAAA;EACjC,IAAA;EACA,OAAA,GAAU,IAAA;EACV,OAAA,GAAU,IAAA;AAAA;AAAA,UAGK,WAAA,SAAoB,eAAA;EACnC,IAAA;EACA,OAAA;AAAA;AAAA,UAGe,cAAA,SAAuB,eAAA;EACtC,IAAA;EACA,MAAA;EACA,WAAA;EACA,QAAA;AAAA;AAAA,UAGe,UAAA,SAAmB,eAAA;EAClC,IAAA;EACA,MAAA;EACA,OAAA;AAAA;AAAA,UAGe,aAAA,SAAsB,eAAA;EACrC,IAAA;EACA,MAAA;AAAA;AAAA,UAGe,SAAA,SAAkB,eAAA;EACjC,IAAA;EACA,IAAA;EACA,MAAA;AAAA;;;;;UAOe,kBAAA;EACf,IAAA;EACA,MAAA,EAAQ,MAAA,SAAe,WAAA;AAAA;;;;;;;;;UAWR,SAAA,SAAkB,eAAA;EACjC,IAAA;AAAA;AAAA,UAGe,WAAA,SAAoB,eAAA;EACnC,IAAA;EACA,MAAA,WAAiB,kBAAA;EACjB,GAAA;EACA,GAAA;EACA,SAAA;AAAA;AAAA,KAGU,WAAA,GACR,OAAA,GACA,SAAA,GACA,WAAA,GACA,YAAA,GACA,SAAA,GACA,WAAA,GACA,cAAA,GACA,UAAA,GACA,aAAA,GACA,SAAA,GACA,SAAA,GACA,WAAA;;;;;;;KC7EQ,SAAA,WAAoB,WAAA,IAAe,CAAA,SAAU,OAAA,YAErD,CAAA,SAAU,SAAA,YAER,CAAA,SAAU,WAAA,YAER,CAAA,SAAU,YAAA,aAER,CAAA,SAAU,SAAA,GACR,IAAA,YACA,CAAA,SAAU,WAAA,GACR,CAAA,sBACA,CAAA,SAAU,cAAA,GACR,CAAA,qDAGA,CAAA,SAAU,UAAA,YAER,CAAA,SAAU,aAAA,GACR,MAAA,sBACA,CAAA,SAAU,SAAA,YAER,CAAA,SAAU,SAAA,GACR,MAAA,oBACA,CAAA,SAAU,WAAA,GACR,KAAA;EAAQ,MAAA;EAAgB,GAAA;EAAA,CAAc,GAAA;AAAA;;;;;KAWpD,iBAAA,gBAAiC,MAAA,SAAe,WAAA,mBAC9C,MAAA,GAAS,MAAA,CAAO,CAAA,6BAA8B,CAAA,iBACpD,MAAA;AAAA,KAEI,iBAAA,gBAAiC,MAAA,SAAe,WAAA,mBAC9C,MAAA,GAAS,MAAA,CAAO,CAAA,qCAAsC,CAAA,SAC5D,MAAA;;;;;;AD3ER;;;KCyFY,cAAA,gBAA8B,MAAA,SAAe,WAAA;EAAkB,EAAA;AAAA,YACnE,OAAA,CAAQ,iBAAA,CAAkB,MAAA,WAAiB,SAAA,CAAU,MAAA,CAAO,CAAA,eACxD,iBAAA,CAAkB,MAAA,KAAW,SAAA,CAAU,MAAA,CAAO,CAAA;;KAOrD,mBAAA;;;ADtFL;;;KC6FY,gBAAA,gBAAgC,MAAA,SAAe,WAAA,KAAgB,IAAA,SACjE,OAAA,CAAQ,iBAAA,CAAkB,MAAA,WAAiB,SAAA,CAAU,MAAA,CAAO,CAAA,eAC5D,iBAAA,CAAkB,MAAA,KAAW,SAAA,CAAU,MAAA,CAAO,CAAA,aAEtD,mBAAA;;KAQG,eAAA;AAAA,KAEO,gBAAA,gBAAgC,MAAA,SAAe,WAAA,KAAgB,OAAA,CACzE,IAAA,CAAK,cAAA,CAAe,MAAA,GAAS,eAAA;;;;;;;ADjG/B;;;KCkHY,iBAAA;EACV,MAAA,EAAQ,WAAA;IAAgB,OAAA;EAAA;EACxB,WAAA,EAAa,SAAA;AAAA;;KAIH,eAAA;EACV,SAAA,EAAW,SAAA;EACX,SAAA,EAAW,SAAA;EACX,SAAA,EAAW,SAAA;EACX,SAAA,EAAW,SAAA;AAAA;ADjHb;AAAA,KCqHY,eAAA;EACV,IAAA,EAAM,SAAA;AAAA;;KAII,kBAAA;EACV,QAAA,EAAU,WAAA;AAAA;;KAIA,kBAAA;EACV,QAAA,EAAU,cAAA;IAAmB,WAAA;EAAA;EAC7B,IAAA,EAAM,SAAA;EACN,KAAA,EAAO,WAAA;AAAA;AD5HT;;;;;;;AAAA,KC6IY,WAAA,MAAiB,CAAA;EAAY,SAAA,kBAA2B,MAAA,SAAe,WAAA;AAAA,IAC/E,cAAA,CAAe,CAAA;;;UCjLF,QAAA,WAAmB,MAAA,SAAe,WAAA,IAAe,MAAA,SAAe,WAAA;EAC/E,IAAA;EACA,MAAA,GAAS,CAAA;EACT,KAAA;IACE,YAAA,IAAgB,IAAA,EAAM,MAAA,sBAA4B,OAAA,CAAQ,MAAA;IAC1D,WAAA,IAAe,MAAA,EAAQ,MAAA,sBAA4B,OAAA;IACnD,YAAA,IAAgB,EAAA,UAAY,IAAA,EAAM,MAAA,sBAA4B,OAAA,CAAQ,MAAA;IACtE,WAAA,IAAe,MAAA,EAAQ,MAAA,sBAA4B,OAAA;IACnD,YAAA,IAAgB,EAAA,aAAe,OAAA;IAC/B,WAAA,IAAe,EAAA,aAAe,OAAA;EAAA;AAAA;AAAA,KAItB,eAAA,OAAsB,IAAA,gBAAoB,QAAA;;;iBCStC,SAAA,CAAA,GAAa,QAAA,CAAS,eAAA;;;UCfrB,mBAAA;ELHf;;;;;;EKUA,QAAA;AAAA;AAAA,iBAGc,YAAA,CAAa,QAAA,GAAW,mBAAA,GAAsB,QAAA,CAAS,kBAAA;;;iBClBvD,WAAA,CAAA,GAAe,QAAA,CAAS,iBAAA;;;iBCAxB,YAAA,CAAA,GAAgB,QAAA,CAAS,kBAAA;;;UCAxB,gBAAA;ERLA;EQOf,YAAA;AAAA;;;;iBAMc,OAAA,CAAQ,IAAA;AAAA,iBASR,SAAA,CACd,WAAA,UACA,OAAA,GAAU,gBAAA,GACT,QAAA,CAAS,eAAA;;;cCJC,KAAA;ETHY;;;uBSQF,OAAA,CAAQ,OAAA,QAAQ,MAAA,GAAgB,CAAA,KAAI,OAAA,GAAU,CAAA;ETlBnE;;;yBS8BuB,OAAA,CAAQ,SAAA,QAAU,MAAA,GAAgB,CAAA,KAAI,SAAA,GAAY,CAAA;ETtBzE;;;2BSgCyB,OAAA,CAAQ,WAAA,QAAY,MAAA,GAAgB,CAAA,KAAI,WAAA,GAAc,CAAA;ET9B7B;;;4BSwCxB,OAAA,CAAQ,YAAA,QAAa,MAAA,GAAgB,CAAA,KAAI,YAAA,GAAe,CAAA;ETlClF;;;yBS6CuB,OAAA,CAAQ,SAAA,QAAU,MAAA,GAAgB,CAAA,KAAI,SAAA,GAAY,CAAA;ETjCzE;;;;;8DS+CkB,IAAA,CAAK,OAAA,CAAQ,WAAA,oBAAwB,MAAA;IAE3C,OAAA,EAAS,CAAA;EAAA,IAAM,CAAA,KACxB,WAAA;IAAgB,OAAA,EAAS,CAAA;EAAA,IAAM,CAAA;;;;;gEAahB,OAAA,CAAQ,IAAA,CAAK,cAAA,mCAA0C,MAAA;IAE7D,MAAA;IAAgB,WAAA,GAAc,CAAA;EAAA,IAAM,CAAA,KAC7C,cAAA;IAAmB,WAAA,EAAa,CAAA;EAAA,IAAM,CAAA;ER7FnC;;AAIR;0BQqG0B,OAAA,CAAQ,UAAA,QAAW,MAAA,GAAgB,CAAA,KAAI,UAAA,GAAa,CAAA;;;;6BAUjD,OAAA,CAAQ,aAAA,QAAc,MAAA,GAAgB,CAAA,KAAI,aAAA,GAAgB,CAAA;ER3G5D;;;yBQqHF,OAAA,CAAQ,SAAA,QAAU,MAAA,EAC/B,IAAA,CAAK,SAAA,YAAqB,CAAA,KACjC,SAAA,GAAY,CAAA;ERtHf;;;yBQkIuB,OAAA,CAAQ,SAAA,QAAU,MAAA,GAAgB,CAAA,KAAI,SAAA,GAAY,CAAA;ER/H/D;;;AAGZ;oCQsIoC,kBAAA,IAAoB,MAAA;IACpD,MAAA,EAAQ,CAAA;IACR,GAAA;IACA,GAAA;IACA,SAAA;EAAA,MACE,WAAA;IAAgB,MAAA,EAAQ,CAAA;EAAA;AAAA;;;KC9JlB,iBAAA;EACV,SAAA,EAAW,UAAA,QAAkB,KAAA,CAAM,IAAA;EACnC,SAAA,EAAW,UAAA,QAAkB,KAAA,CAAM,IAAA;AAAA;AAAA,iBAGrB,WAAA,CAAA,GAAe,QAAA,CAAS,iBAAA;;;;;;cCM3B,QAAA;;;;;;;;;;;;;;;;;AXhBb;;;;;;;;;UYaiB,cAAA;EACf,GAAA,CAAI,GAAA;EACJ,GAAA,CAAI,GAAA,UAAa,KAAA;EACjB,UAAA,CAAW,MAAA;AAAA;AAAA,cAQA,UAAA,YAAsB,cAAA;EAAA,QACzB,KAAA;EAAA,QACA,KAAA;cAEI,KAAA;EZNZ;;;EYaA,GAAA,CAAI,GAAA;EZLJ;;;EYiBA,GAAA,CAAI,GAAA,UAAa,KAAA;EZAA;;;;EYQjB,UAAA,CAAW,MAAA;EXtDI;;;EWiEf,KAAA,CAAA;EXhEA;;;EW4EA,KAAA,CAAA;EXxEA;;;EAAA,IW+EI,IAAA,CAAA;AAAA;;;;;;;;;;;;;;iBC/DgB,gBAAA,CAAiB,EAAA,EAAI,kBAAA,EAAoB,SAAA,WAAoB,OAAA;;;;UCDlE,WAAA;EdHE;EcKjB,KAAA;EdLkD;EcOlD,KAAA;EdLA;EcOA,SAAA;EdHA;EcKA,EAAA;AAAA;;UAIQ,aAAA;EACR,KAAA;EACA,KAAA;EACA,SAAA;EACA,EAAA;AAAA;;;AbpCF;;iBaqDgB,YAAA,CACd,IAAA,EAAM,MAAA,mBACN,SAAA,UACA,SAAA;;;;;;;;iBAkBc,YAAA,CAAa,OAAA,WAAkB,aAAA;;;;Ab9D/C;;;;;AAIA;;;;iBamHgB,oBAAA,CAEd,KAAA,EAAO,kBAAA,OACP,MAAA,EAAQ,aAAA,GACP,GAAA;;;;;;;;;UCrHc,gBAAA,WACL,MAAA,SAAe,WAAA,IAAe,MAAA,SAAe,WAAA;EAEvD,IAAA;EACA,IAAA;EACA,MAAA,EAAQ,CAAA;EACR,KAAA;EACA,MAAA;IACE,IAAA;IACA,MAAA;IACA,MAAA;IACA,MAAA;EAAA;EfYF;EeTA,KAAA,GAAQ,iBAAA;AAAA;;;;;KAOE,WAAA,WACA,MAAA,SAAe,WAAA,IAAe,MAAA,SAAe,WAAA,aAC7C,QAAA,KAAa,QAAA,MACrB,gBAAA,CAAiB,CAAA;EAAO,SAAA,GAAY,CAAA;AAAA;;;;;UAMvB,MAAA,mBACG,MAAA,SAAe,WAAA,IAAe,MAAA,SAAe,WAAA;EAE/D,IAAA;EACA,IAAA;EACA,MAAA,EAAQ,MAAA,SAAe,WAAA;EACvB,SAAA,GAAY,QAAA;EACZ,KAAA;EACA,MAAA;IACE,IAAA;IACA,MAAA;IACA,MAAA;IACA,MAAA;EAAA;Ed5Ca;Ec+Cf,KAAA,GAAQ,iBAAA;EACR,SAAA,EAAW,SAAA;EACX,KAAA,EAAO,QAAA;AAAA;;;;;KAOJ,qBAAA,WAAgC,QAAA,MAAc,CAAA,UACjD,QAAA,kCACsB,QAAA,MAEpB,EAAA,GAAK,qBAAA,CAAsB,IAAA;;;;;;;;;;;Ad9C/B;;;;;AAIA;iBc8DgB,YAAA,WACJ,MAAA,SAAe,WAAA,mBACT,QAAA,QAAA,CAEhB,UAAA,EAAY,gBAAA,CAAiB,CAAA;EAAO,SAAA,GAAY,CAAA;AAAA,IAC/C,MAAA;EAAS,EAAA,EAAI,OAAA;AAAA,IAAY,qBAAA,CAAsB,CAAA,IAAK,CAAA;;;UChGtC,WAAA;EACf,YAAA;EACA,QAAA;EACA,WAAA;AAAA;;;cCPW,qBAAA,SAA8B,KAAA;EAAA,SACzB,UAAA;EAAA,SACA,QAAA;EAAA,SACA,MAAA,EAAQ,WAAA;cAEZ,UAAA,UAAoB,QAAA,UAAkB,MAAA,EAAQ,WAAA;AAAA;;;KCcvD,QAAA,GAAW,OAAA;;;;;;;;;;;iBAkHA,cAAA,CAAe,MAAA,EAAQ,MAAA,0BAAM,kBAAA;;;;;;;gBAAA,cAAA,CAAA,cAAA;;;;;;;;;;;;;;;;;;;;;;;AjB1H7C;;;iBiBkLgB,yBAAA,CAA0B,MAAA,EAAQ,MAAA,EAAQ,MAAA,GAAS,QAAA,0BAAQ,kBAAA;;;;;;;gBAAA,cAAA,CAAA,cAAA;;;;;;;;;;;;;;;;;;AjBhK3E;;iBiBsMgB,eAAA,CAAgB,MAAA,EAAQ,MAAA;;;AjBlMxC;;;;;;;;iBiBgNgB,oBAAA,CAAqB,MAAA,EAAQ,MAAA,EAAQ,MAAA,GAAS,QAAA,0BAAQ,kBAAA;;;;QAAA,sBAAA,CAAA,QAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoCtD,aAAA,CAAc,MAAA,EAAQ,MAAA;;;;;iBAQtB,iBAAA,CAAkB,MAAA,EAAQ,MAAA;;;;iBAU1B,aAAA,CAAc,MAAA,EAAQ,MAAA;;iBActB,0BAAA,CAA2B,MAAA,EAAQ,MAAA,EAAQ,MAAA,EAAQ,QAAA,0BAAQ,kBAAA;;;;QAAA,sBAAA,CAAA,QAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAqB3D,oBAAA,CAAqB,MAAA,EAAQ,MAAA,EAAQ,MAAA,EAAQ,QAAA,0BAAQ,kBAAA;;;;QAAA,sBAAA,CAAA,QAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwBrD,sBAAA,CAAuB,MAAA,EAAQ,MAAA,EAAQ,MAAA,EAAQ,QAAA,0BAAQ,kBAAA;;;;QAAA,sBAAA,CAAA,QAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8BvD,0BAAA,CAAA,0BAA0B,kBAAA;;;;QAAA,sBAAA,CAAA,QAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsB1B,qBAAA,CAAsB,MAAA,EAAQ,MAAA;;;;ARnZ9C;;;;iBQ0agB,+BAAA,CAAgC,MAAA,EAAQ,MAAA,EAAQ,YAAA,GAAe,QAAA,0BAAQ,kBAAA;;;;QAAA,sBAAA,CAAA,QAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ALzZvF;;;iBK2cgB,oBAAA,CAAqB,QAAA,EAAU,MAAA,KAAW,MAAA,SAAe,QAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,65 +1,2 @@
|
|
|
1
|
-
import{and as e,eq as t,gt as n,lt as r,or as i,sql as a}from"drizzle-orm";import{boolean as o,doublePrecision as s,index as c,integer as l,jsonb as u,pgTable as d,text as f,timestamp as p,unique as m,uuid as h,varchar as g}from"drizzle-orm/pg-core";const _={id:e=>({type:`id`,required:!0,indexed:!0,...e}),text:e=>({type:`text`,...e}),number:e=>({type:`number`,...e}),boolean:e=>({type:`boolean`,default:!1,...e}),date:e=>({type:`date`,...e}),select:e=>({type:`select`,...e}),reference:e=>({type:`reference`,cardinality:`one`,onDelete:`set-null`,...e}),media:e=>({type:`media`,...e}),richtext:e=>({type:`richtext`,...e}),slug:e=>({type:`slug`,unique:!0,indexed:!0,...e}),json:e=>({type:`json`,...e}),blocks:e=>({type:`blocks`,...e})};async function v(){try{return(await import([`@murumets-ee`,`core`].join(`/`))).getCurrentUser()?.id}catch{return}}function y(){return{name:`auditable`,fields:{createdBy:_.text(),updatedBy:_.text(),createdAt:_.date({indexed:!0}),updatedAt:_.date({indexed:!0})},hooks:{beforeCreate:async e=>{e.createdAt=new Date,e.updatedAt=new Date;let t=await v();return t&&(e.createdBy=t,e.updatedBy=t),e},beforeUpdate:async(e,t)=>{t.updatedAt=new Date;let n=await v();return n&&(t.updatedBy=n),t}}}}function b(e){return{name:`hierarchical`,fields:{parentId:_.reference({entity:`_self`,required:!1}),path:_.text({indexed:!0,maxLength:2048}),depth:_.number({integer:!0,default:0,indexed:!0})},hooks:{beforeCreate:async e=>(e.parentId||(e.depth=0),e)}}}function x(){return{name:`publishable`,fields:{status:_.select({options:[`draft`,`published`],default:`draft`,indexed:!0}),publishedAt:_.date({indexed:!0})},hooks:{beforeUpdate:async(e,t)=>(t.status===`published`&&!t.publishedAt&&(t.publishedAt=new Date),t)}}}function S(){return{name:`revisionable`,fields:{_version:_.number({required:!0,default:1,integer:!0})},hooks:{beforeCreate:async e=>(e._version=1,e),beforeUpdate:async(e,t)=>(t._version=(Number(t._version)||0)+1,t)}}}function C(e){return e.toLowerCase().trim().replace(/[^\w\s-]/g,``).replace(/[\s_-]+/g,`-`).replace(/^-+|-+$/g,``)}function w(e,t){return{name:`sluggable`,fields:{slug:_.slug({from:e,...t?.translatable?{translatable:!0}:{}})},hooks:{beforeCreate:async t=>(!t.slug&&t[e]&&(t.slug=C(String(t[e]))),t),beforeUpdate:async(t,n)=>(n[e]&&!n.slug&&(n.slug=C(String(n[e]))),n)}}}function T(){return{name:`timestamped`,fields:{createdAt:_.date({indexed:!0}),updatedAt:_.date({indexed:!0})},hooks:{beforeCreate:async e=>(e.createdAt=new Date,e.updatedAt=new Date,e),beforeUpdate:async(e,t)=>(t.updatedAt=new Date,t)}}}const E={publishable:x,auditable:y,sluggable:w,revisionable:S,hierarchical:b,timestamped:T};var D=class{cache=new Map;ttlMs;constructor(e=5e3){this.ttlMs=e}get(e){let t=this.cache.get(e);if(!t||Date.now()>t.expiresAt){t&&this.cache.delete(e);return}return t.count}set(e,t){this.cache.set(e,{count:t,expiresAt:Date.now()+this.ttlMs})}invalidate(e){for(let t of this.cache.keys())t.startsWith(e)&&this.cache.delete(t)}prune(){let e=Date.now();for(let[t,n]of this.cache.entries())e>n.expiresAt&&this.cache.delete(t)}clear(){this.cache.clear()}get size(){return this.cache.size}};async function O(e,t){let n=await e.execute(a`SELECT reltuples::bigint AS estimate FROM pg_class WHERE relname = ${t}`),r=(Array.isArray(n)?n:n.rows??[])[0],i=Number(r?.estimate??0);return i>0?i:0}const k=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function A(e,t,n){let r={field:t,value:e[t],direction:n,id:e.id};return btoa(JSON.stringify(r))}function j(e){try{let t=atob(e),n=JSON.parse(t);if(typeof n!=`object`||!n)return null;let r=n;return typeof r.field!=`string`||!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(r.field)||typeof r.value!=`string`&&typeof r.value!=`number`||r.direction!==`asc`&&r.direction!==`desc`||r.id!==void 0&&(typeof r.id!=`string`||!k.test(r.id))?null:{field:r.field,value:r.value,direction:r.direction,id:r.id}}catch{return null}}function M(a,o){let s=a[o.field];if(!s)return null;let c=o.direction===`desc`?r:n,l=c(s,o.value);if(!o.id)return l;let u=a.id;if(!u)return l;let d=c(u,o.id);return i(l,e(t(s,o.value),d))}function N(e){let t={},n={};for(let r of e.behaviors||[]){if(r.fields)for(let[e,n]of Object.entries(r.fields)){if(t[e]){console.warn(`Field '${e}' from behavior '${r.name}' conflicts with existing field. Skipping.`);continue}t[e]=n}if(r.hooks)for(let[e,t]of Object.entries(r.hooks)){let r=e;if(t){let e=n[r];if(e){let i=e,a=t;n[r]=async(...e)=>{let t=await i(...e);if(t!==void 0){let n=[...e];return n[n.length-1]=t,await a(...n)}return await a(...e)}}else n[r]=t}}}let r={id:_.id(),...t,...e.fields};for(let[,e]of Object.entries(r))e.type===`slug`&&!e.translatable&&r[e.from]?.translatable&&(e.translatable=!0);return{...e,allFields:r,hooks:n}}var P=class extends Error{entityName;entityId;usages;constructor(e,t,n){let r=n.length;super(`Cannot delete ${e} '${t}': referenced by ${r} other entit${r===1?`y`:`ies`}`),this.name=`ReferencedEntityError`,this.entityName=e,this.entityId=t,this.usages=n}};function F(e,t,n){let r=n?.nullable??!1;switch(t.type){case`id`:return h(e).primaryKey().defaultRandom();case`text`:if(t.maxLength&&t.maxLength<=255){let n=g(e,{length:t.maxLength});return t.unique&&(n=n.unique()),!r&&t.required&&(n=n.notNull()),!r&&t.default!==void 0&&(n=n.default(t.default)),n}else{let n=f(e);return t.unique&&(n=n.unique()),!r&&t.required&&(n=n.notNull()),!r&&t.default!==void 0&&(n=n.default(t.default)),n}case`number`:{let n=t.integer?l(e):s(e);return!r&&t.required&&(n=n.notNull()),!r&&t.default!==void 0&&(n=n.default(t.default)),n}case`boolean`:{let n=o(e);if(!r&&t.required&&(n=n.notNull()),!r){let e=t.default===void 0?!1:t.default;n=n.default(e)}return n}case`date`:{let n=p(e,{withTimezone:!0});return!r&&t.required&&(n=n.notNull()),!r&&t.default!==void 0&&(n=n.default(t.default)),n}case`select`:{let n=g(e,{length:100});return!r&&t.required&&(n=n.notNull()),!r&&t.default!==void 0&&(n=n.default(t.default)),n}case`reference`:{if(t.cardinality===`many`)return h(e).array();let n=h(e);return!r&&t.required&&(n=n.notNull()),n}case`media`:{let n=h(e);return!r&&t.required&&(n=n.notNull()),n}case`slug`:{let n=g(e,{length:255});return t.unique&&!r&&(n=n.unique()),!r&&t.required&&(n=n.notNull()),n}case`richtext`:{let n=f(e);return!r&&t.required&&(n=n.notNull()),n}case`json`:return u(e);default:return f(e)}}function I(e,t,n){let r=n?.nullable??!1;switch(t.type){case`id`:return`id: uuid('id').primaryKey().defaultRandom()`;case`text`:{let n=t.maxLength,i=n&&n<=255?`varchar('${e}', { length: ${n} })`:`text('${e}')`;return t.unique&&(i+=`.unique()`),!r&&t.required&&(i+=`.notNull()`),!r&&t.default&&(i+=`.default('${t.default}')`),`${e}: ${i}`}case`number`:{let n=t.integer?`integer('${e}')`:`doublePrecision('${e}')`;return!r&&t.required&&(n+=`.notNull()`),!r&&t.default!==void 0&&(n+=`.default(${t.default})`),`${e}: ${n}`}case`boolean`:return r?`${e}: boolean('${e}')`:`${e}: boolean('${e}').default(${t.default??!1})`;case`date`:{let n=`timestamp('${e}', { withTimezone: true })`;return!r&&t.required&&(n+=`.notNull()`),`${e}: ${n}`}case`reference`:{if(t.cardinality===`many`)return`${e}: uuid('${e}').array()`;let n=`uuid('${e}')`;return!r&&t.required&&(n+=`.notNull()`),`${e}: ${n}`}case`media`:{let n=`uuid('${e}')`;return!r&&t.required&&(n+=`.notNull()`),`${e}: ${n}`}case`slug`:{let n=`varchar('${e}', { length: 255 })`;return t.unique&&!r&&(n+=`.unique()`),!r&&t.required&&(n+=`.notNull()`),`${e}: ${n}`}case`select`:{let n=`varchar('${e}', { length: 100 })`;return!r&&t.required&&(n+=`.notNull()`),!r&&t.default&&(n+=`.default('${t.default}')`),`${e}: ${n}`}case`richtext`:{let n=`text('${e}')`;return!r&&t.required&&(n+=`.notNull()`),`${e}: ${n}`}case`json`:return`${e}: jsonb('${e}')`;default:return`${e}: text('${e}')`}}function L(e){let t=e.name,n={};for(let[t,r]of Object.entries(e.allFields))r.type!==`blocks`&&(n[t]=F(t,r));(e.scope===`team`||e.scope===`user`)&&(n._scopeId=h(`_scope_id`));let r=Object.entries(e.allFields).filter(([e,t])=>t.type!==`blocks`&&t.type!==`id`&&t.indexed&&!t.unique),i=e.behaviors?.some(e=>e.name===`publishable`)??!1;return r.length===0&&!i?d(t,n):d(t,n,e=>{let n={};for(let[i]of r)n[`idx_${t}_${i}`]=c(`idx_${t}_${i}`).on(e[i]);return i&&e.status&&e.createdAt&&(n[`idx_${t}_status_created`]=c(`idx_${t}_status_created`).on(e.status,e.createdAt)),n})}function R(e){let t=e.name,n=[],r=Object.entries(e.allFields).filter(([e,t])=>t.type!==`blocks`&&t.type!==`id`&&t.indexed&&!t.unique),i=e.behaviors?.some(e=>e.name===`publishable`)??!1,a=r.length>0||i;n.push(`export const ${t} = pgTable('${t}', {`);for(let[t,r]of Object.entries(e.allFields)){if(r.type===`blocks`)continue;let e=I(t,r);n.push(` ${e},`)}if((e.scope===`team`||e.scope===`user`)&&n.push(` _scopeId: uuid('_scope_id'),`),a){n.push(`}, (table) => ({`);for(let[e]of r)n.push(` idx_${t}_${e}: index('idx_${t}_${e}').on(table.${e}),`);i&&n.push(` idx_${t}_status_created: index('idx_${t}_status_created').on(table.status, table.createdAt),`),n.push(`}))`)}else n.push(`)`);return n.join(`
|
|
2
|
-
`)}function z(e){let t=Object.entries(e.allFields).filter(([e,t])=>t.translatable);if(t.length===0)return null;let n=`${e.name}_translations`,r={id:h(`id`).primaryKey().defaultRandom(),entityId:h(`entity_id`).notNull(),locale:g(`locale`,{length:10}).notNull()},i=t.some(([e,t])=>t.type===`slug`);for(let[e,n]of t)r[e]=F(e,n,{nullable:!0});return d(n,r,e=>({uniqueEntityLocale:m().on(e.entityId,e.locale),...i&&e.slug?{uniqueSlugLocale:m().on(e.slug,e.locale)}:{}}))}function B(e){let t=Object.entries(e.allFields).filter(([e,t])=>t.translatable);if(t.length===0)return null;let n=`${e.name}_translations`,r=e.name,i=[];i.push(`export const ${n} = pgTable('${n}', {`),i.push(` id: uuid('id').primaryKey().defaultRandom(),`),i.push(` entityId: uuid('entity_id').notNull().references(() => ${r}.id, { onDelete: 'cascade' }),`),i.push(` locale: varchar('locale', { length: 10 }).notNull(),`);for(let[e,n]of t){let t=I(e,n,{nullable:!0});i.push(` ${t},`)}let a=t.some(([e,t])=>t.type===`slug`);return i.push(`}, (table) => ({`),i.push(` uniqueEntityLocale: unique().on(table.entityId, table.locale), // One translation per locale`),a&&i.push(` uniqueSlugLocale: unique().on(table.slug, table.locale), // Per-locale slug uniqueness`),i.push(`}))`),i.join(`
|
|
3
|
-
`)}function V(e){return Object.values(e.allFields).some(e=>e.type===`blocks`)}function H(e){if(!V(e))return null;let t=`${e.name}_layout`;return d(t,{id:h(`id`).primaryKey().defaultRandom(),entityId:h(`entity_id`).notNull(),fieldName:g(`field_name`,{length:100}).notNull(),blockType:g(`block_type`,{length:100}).notNull(),sortOrder:l(`sort_order`).notNull().default(0),data:u(`data`),locale:g(`locale`,{length:10})},e=>({idx_entity_locale_sort:c(`idx_${t}_entity_locale_sort`).on(e.entityId,e.locale,e.sortOrder)}))}function U(e){return e.behaviors?.some(e=>e.name===`versionable`)??!1}function W(e){if(!(e.behaviors?.some(e=>e.name===`publishable`)??!1))return!1;let t=e.allFields;return Object.values(t).some(e=>e.translatable)}function G(e){let t=e.name,n=`${t}_locale_status`;return`export const ${n} = pgTable('${n}', {
|
|
4
|
-
id: uuid('id').primaryKey().defaultRandom(),
|
|
5
|
-
entityId: uuid('entity_id').notNull().references(() => ${t}.id, { onDelete: 'cascade' }),
|
|
6
|
-
locale: varchar('locale', { length: 10 }).notNull(),
|
|
7
|
-
status: varchar('status', { length: 20 }).notNull().default('draft'),
|
|
8
|
-
publishedAt: timestamp('published_at', { withTimezone: true }),
|
|
9
|
-
}, (table) => ({
|
|
10
|
-
uniqueEntityLocale: unique().on(table.entityId, table.locale),
|
|
11
|
-
}))`}function K(e){return e.behaviors?.some(e=>e.name===`publishable`)??!1}function q(e){let t=e.name,n=`${t}_drafts`;return`export const ${n} = pgTable('${n}', {
|
|
12
|
-
id: uuid('id').primaryKey().defaultRandom(),
|
|
13
|
-
entityId: uuid('entity_id').notNull().references(() => ${t}.id, { onDelete: 'cascade' }),
|
|
14
|
-
locale: varchar('locale', { length: 10 }).notNull().default('_'),
|
|
15
|
-
data: jsonb('data').notNull(),
|
|
16
|
-
createdBy: varchar('created_by', { length: 255 }).notNull(),
|
|
17
|
-
createdByName: varchar('created_by_name', { length: 255 }),
|
|
18
|
-
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
19
|
-
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
20
|
-
}, (table) => ({
|
|
21
|
-
uniqueEntityLocale: unique().on(table.entityId, table.locale),
|
|
22
|
-
}))`}function J(){return`export const toolkit_content_locks = pgTable('toolkit_content_locks', {
|
|
23
|
-
id: uuid('id').primaryKey().defaultRandom(),
|
|
24
|
-
entityType: varchar('entity_type', { length: 100 }).notNull(),
|
|
25
|
-
entityId: varchar('entity_id', { length: 255 }).notNull(),
|
|
26
|
-
locale: varchar('locale', { length: 10 }).notNull().default('_'),
|
|
27
|
-
lockedBy: varchar('locked_by', { length: 255 }).notNull(),
|
|
28
|
-
lockedByName: varchar('locked_by_name', { length: 255 }),
|
|
29
|
-
lockedAt: timestamp('locked_at', { withTimezone: true }).notNull().defaultNow(),
|
|
30
|
-
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
|
|
31
|
-
}, (table) => ({
|
|
32
|
-
uniqueEntityLock: unique().on(table.entityType, table.entityId, table.locale),
|
|
33
|
-
}))`}function Y(e){let t=e.allFields;return Object.values(t).some(e=>e.type!==`blocks`||e.localized?!1:e.blocks?.some(e=>Object.values(e.fields).some(e=>e.translatable)))}function X(e){let t=e.name,n=`${t}_layout`;return`export const ${n} = pgTable('${n}', {
|
|
34
|
-
id: uuid('id').primaryKey().defaultRandom(),
|
|
35
|
-
entityId: uuid('entity_id').notNull().references(() => ${t}.id, { onDelete: 'cascade' }),
|
|
36
|
-
fieldName: varchar('field_name', { length: 100 }).notNull(),
|
|
37
|
-
blockType: varchar('block_type', { length: 100 }).notNull(),
|
|
38
|
-
sortOrder: integer('sort_order').notNull().default(0),
|
|
39
|
-
data: jsonb('data'),
|
|
40
|
-
locale: varchar('locale', { length: 10 }),
|
|
41
|
-
}, (table) => ({
|
|
42
|
-
idx_entity_locale_sort: index('idx_${n}_entity_locale_sort').on(table.entityId, table.locale, table.sortOrder),
|
|
43
|
-
}))`}function Z(e){let t=e.name,n=`${t}_layout_translations`;return`export const ${n} = pgTable('${n}', {
|
|
44
|
-
id: uuid('id').primaryKey().defaultRandom(),
|
|
45
|
-
layoutId: uuid('layout_id').notNull().references(() => ${`${t}_layout`}.id, { onDelete: 'cascade' }),
|
|
46
|
-
locale: varchar('locale', { length: 10 }).notNull(),
|
|
47
|
-
fields: jsonb('fields').notNull(),
|
|
48
|
-
}, (table) => ({
|
|
49
|
-
uniqueLayoutLocale: unique().on(table.layoutId, table.locale),
|
|
50
|
-
}))`}function Q(e){let t=e.name,n=`${t}_versions`;return`export const ${n} = pgTable('${n}', {
|
|
51
|
-
id: uuid('id').primaryKey().defaultRandom(),
|
|
52
|
-
entityId: uuid('entity_id').notNull().references(() => ${t}.id, { onDelete: 'cascade' }),
|
|
53
|
-
version: integer('version').notNull(),
|
|
54
|
-
locale: varchar('locale', { length: 10 }).notNull().default('_'),
|
|
55
|
-
data: jsonb('data').notNull(),
|
|
56
|
-
delta: jsonb('delta'),
|
|
57
|
-
status: varchar('status', { length: 20 }),
|
|
58
|
-
createdBy: varchar('created_by', { length: 255 }),
|
|
59
|
-
createdByName: varchar('created_by_name', { length: 255 }),
|
|
60
|
-
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
61
|
-
isAutosave: boolean('is_autosave').notNull().default(false),
|
|
62
|
-
}, (table) => ({
|
|
63
|
-
uniqueEntityVersionLocale: unique().on(table.entityId, table.version, table.locale),
|
|
64
|
-
}))`}function $(e){let t=Object.values(e.allFields).filter(e=>e.type===`blocks`&&!(`localized`in e&&e.localized));return t.length===0||!t.some(e=>e.type===`blocks`?e.blocks.some(e=>Object.values(e.fields).some(e=>e.translatable)):!1)?null:d(`${e.name}_layout_translations`,{id:h(`id`).primaryKey().defaultRandom(),layoutId:h(`layout_id`).notNull(),locale:g(`locale`,{length:10}).notNull(),fields:u(`fields`).notNull()},e=>({uniqueLayoutLocale:m().on(e.layoutId,e.locale)}))}export{D as CountCache,P as ReferencedEntityError,y as auditable,E as behavior,M as buildCursorCondition,j as decodeCursor,N as defineEntity,A as encodeCursor,O as estimateRowCount,_ as field,J as generateContentLocksCode,q as generateDraftsCode,X as generateLayoutCode,H as generateLayoutSchema,Z as generateLayoutTranslationCode,$ as generateLayoutTranslationSchema,G as generateLocaleStatusCode,L as generateSchema,R as generateSchemaCode,z as generateTranslationSchema,B as generateTranslationSchemaCode,Q as generateVersionsCode,V as hasBlocksFields,Y as hasTranslatableBlocks,b as hierarchical,K as isPublishable,U as isVersionable,W as needsLocaleStatus,x as publishable,S as revisionable,w as sluggable,C as slugify,T as timestamped};
|
|
1
|
+
import{and as e,eq as t,gt as n,lt as r,or as i,sql as a}from"drizzle-orm";import{boolean as o,doublePrecision as s,index as c,integer as l,jsonb as u,pgTable as d,text as f,timestamp as p,unique as m,uuid as h,varchar as g}from"drizzle-orm/pg-core";const _={id:e=>({type:`id`,required:!0,indexed:!0,...e}),text:e=>({type:`text`,...e}),number:e=>({type:`number`,...e}),boolean:e=>({type:`boolean`,default:!1,...e}),date:e=>({type:`date`,...e}),select:e=>({type:`select`,...e}),reference:e=>({type:`reference`,cardinality:`one`,onDelete:`set-null`,...e}),media:e=>({type:`media`,...e}),richtext:e=>({type:`richtext`,...e}),slug:e=>({type:`slug`,unique:!0,indexed:!0,...e}),json:e=>({type:`json`,...e}),blocks:e=>({type:`blocks`,...e})};async function v(){try{return(await import([`@murumets-ee`,`core`].join(`/`))).getCurrentUser()?.id}catch{return}}function y(){return{name:`auditable`,fields:{createdBy:_.text(),updatedBy:_.text(),createdAt:_.date({indexed:!0}),updatedAt:_.date({indexed:!0})},hooks:{beforeCreate:async e=>{e.createdAt=new Date,e.updatedAt=new Date;let t=await v();return t&&(e.createdBy=t,e.updatedBy=t),e},beforeUpdate:async(e,t)=>{t.updatedAt=new Date;let n=await v();return n&&(t.updatedBy=n),t}}}}function b(e){return{name:`hierarchical`,fields:{parentId:_.reference({entity:`_self`,required:!1}),path:_.text({indexed:!0,maxLength:2048}),depth:_.number({integer:!0,default:0,indexed:!0})},hooks:{beforeCreate:async e=>(e.parentId||(e.depth=0),e)}}}function x(){return{name:`publishable`,fields:{status:_.select({options:[`draft`,`published`],default:`draft`,indexed:!0}),publishedAt:_.date({indexed:!0})},hooks:{beforeUpdate:async(e,t)=>(t.status===`published`&&!t.publishedAt&&(t.publishedAt=new Date),t)}}}function S(){return{name:`revisionable`,fields:{_version:_.number({required:!0,default:1,integer:!0})},hooks:{beforeCreate:async e=>(e._version=1,e),beforeUpdate:async(e,t)=>(t._version=(Number(t._version)||0)+1,t)}}}function C(e){return e.toLowerCase().trim().replace(/[^\w\s-]/g,``).replace(/[\s_-]+/g,`-`).replace(/^-+|-+$/g,``)}function w(e,t){return{name:`sluggable`,fields:{slug:_.slug({from:e,...t?.translatable?{translatable:!0}:{}})},hooks:{beforeCreate:async t=>(!t.slug&&t[e]&&(t.slug=C(String(t[e]))),t),beforeUpdate:async(t,n)=>(n[e]&&!n.slug&&(n.slug=C(String(n[e]))),n)}}}function T(){return{name:`timestamped`,fields:{createdAt:_.date({indexed:!0}),updatedAt:_.date({indexed:!0})},hooks:{beforeCreate:async e=>(e.createdAt=new Date,e.updatedAt=new Date,e),beforeUpdate:async(e,t)=>(t.updatedAt=new Date,t)}}}const E={publishable:x,auditable:y,sluggable:w,revisionable:S,hierarchical:b,timestamped:T};var D=class{cache=new Map;ttlMs;constructor(e=5e3){this.ttlMs=e}get(e){let t=this.cache.get(e);if(!t||Date.now()>t.expiresAt){t&&this.cache.delete(e);return}return t.count}set(e,t){this.cache.set(e,{count:t,expiresAt:Date.now()+this.ttlMs})}invalidate(e){for(let t of this.cache.keys())t.startsWith(e)&&this.cache.delete(t)}prune(){let e=Date.now();for(let[t,n]of this.cache.entries())e>n.expiresAt&&this.cache.delete(t)}clear(){this.cache.clear()}get size(){return this.cache.size}};async function O(e,t){let n=await e.execute(a`SELECT reltuples::bigint AS estimate FROM pg_class WHERE relname = ${t}`),r=(Array.isArray(n)?n:n.rows??[])[0],i=Number(r?.estimate??0);return i>0?i:0}const k=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function A(e,t,n){let r={field:t,value:e[t],direction:n,id:e.id};return btoa(JSON.stringify(r))}function j(e){try{let t=atob(e),n=JSON.parse(t);if(typeof n!=`object`||!n)return null;let r=n;return typeof r.field!=`string`||!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(r.field)||typeof r.value!=`string`&&typeof r.value!=`number`||r.direction!==`asc`&&r.direction!==`desc`||r.id!==void 0&&(typeof r.id!=`string`||!k.test(r.id))?null:{field:r.field,value:r.value,direction:r.direction,id:r.id}}catch{return null}}function M(a,o){let s=a[o.field];if(!s)return null;let c=o.direction===`desc`?r:n,l=c(s,o.value);if(!o.id)return l;let u=a.id;if(!u)return l;let d=c(u,o.id);return i(l,e(t(s,o.value),d))}function N(e){let t={},n={};for(let r of e.behaviors||[]){if(r.fields)for(let[e,n]of Object.entries(r.fields)){if(t[e]){console.warn(`Field '${e}' from behavior '${r.name}' conflicts with existing field. Skipping.`);continue}t[e]=n}if(r.hooks)for(let[e,t]of Object.entries(r.hooks)){let r=e;if(t){let e=n[r];if(e){let i=e,a=t;n[r]=async(...e)=>{let t=await i(...e);if(t!==void 0){let n=[...e];return n[n.length-1]=t,await a(...n)}return await a(...e)}}else n[r]=t}}}let r={id:_.id(),...t,...e.fields};for(let[,e]of Object.entries(r))e.type===`slug`&&!e.translatable&&r[e.from]?.translatable&&(e.translatable=!0);return{...e,allFields:r,hooks:n}}var P=class extends Error{entityName;entityId;usages;constructor(e,t,n){let r=n.length;super(`Cannot delete ${e} '${t}': referenced by ${r} other entit${r===1?`y`:`ies`}`),this.name=`ReferencedEntityError`,this.entityName=e,this.entityId=t,this.usages=n}};const F=d(`entity_refs`,{sourceEntity:g(`source_entity`,{length:100}).notNull(),sourceId:h(`source_id`).notNull(),sourceField:g(`source_field`,{length:100}).notNull(),targetEntity:g(`target_entity`,{length:100}).notNull(),targetId:h(`target_id`).notNull()},e=>[m(`uq_entity_refs`).on(e.sourceEntity,e.sourceId,e.sourceField,e.targetEntity,e.targetId),c(`idx_entity_refs_target`).on(e.targetEntity,e.targetId),c(`idx_entity_refs_source`).on(e.sourceEntity,e.sourceId)]);function I(e,t,n){let r=n?.nullable??!1;switch(t.type){case`id`:return h(e).primaryKey().defaultRandom();case`text`:if(t.maxLength&&t.maxLength<=255){let n=g(e,{length:t.maxLength});return t.unique&&(n=n.unique()),!r&&t.required&&(n=n.notNull()),!r&&t.default!==void 0&&(n=n.default(t.default)),n}else{let n=f(e);return t.unique&&(n=n.unique()),!r&&t.required&&(n=n.notNull()),!r&&t.default!==void 0&&(n=n.default(t.default)),n}case`number`:{let n=t.integer?l(e):s(e);return!r&&t.required&&(n=n.notNull()),!r&&t.default!==void 0&&(n=n.default(t.default)),n}case`boolean`:{let n=o(e);if(!r&&t.required&&(n=n.notNull()),!r){let e=t.default===void 0?!1:t.default;n=n.default(e)}return n}case`date`:{let n=p(e,{withTimezone:!0});return!r&&t.required&&(n=n.notNull()),!r&&t.default!==void 0&&(n=n.default(t.default)),n}case`select`:{let n=g(e,{length:100});return!r&&t.required&&(n=n.notNull()),!r&&t.default!==void 0&&(n=n.default(t.default)),n}case`reference`:{if(t.cardinality===`many`)return h(e).array();let n=h(e);return!r&&t.required&&(n=n.notNull()),n}case`media`:{let n=h(e);return!r&&t.required&&(n=n.notNull()),n}case`slug`:{let n=g(e,{length:255});return t.unique&&!r&&(n=n.unique()),!r&&t.required&&(n=n.notNull()),n}case`richtext`:{let n=f(e);return!r&&t.required&&(n=n.notNull()),n}case`json`:return u(e);default:return f(e)}}function L(e){let t=e.name,n={};for(let[t,r]of Object.entries(e.allFields))r.type!==`blocks`&&(n[t]=I(t,r));(e.scope===`team`||e.scope===`user`)&&(n._scopeId=h(`_scope_id`));let r=Object.entries(e.allFields).filter(([e,t])=>t.type!==`blocks`&&t.type!==`id`&&t.indexed&&!t.unique),i=e.behaviors?.some(e=>e.name===`publishable`)??!1;return r.length===0&&!i?d(t,n):d(t,n,e=>{let n={};for(let[i]of r)n[`idx_${t}_${i}`]=c(`idx_${t}_${i}`).on(e[i]);return i&&e.status&&e.createdAt&&(n[`idx_${t}_status_created`]=c(`idx_${t}_status_created`).on(e.status,e.createdAt)),n})}function R(e,t){let n=Object.entries(e.allFields).filter(([e,t])=>t.translatable);if(n.length===0)return null;let r=`${e.name}_translations`,i=t?h(`entity_id`).notNull().references(()=>t.id,{onDelete:`cascade`}):h(`entity_id`).notNull(),a={id:h(`id`).primaryKey().defaultRandom(),entityId:i,locale:g(`locale`,{length:10}).notNull()},o=n.some(([e,t])=>t.type===`slug`);for(let[e,t]of n)a[e]=I(e,t,{nullable:!0});return d(r,a,e=>({uniqueEntityLocale:m().on(e.entityId,e.locale),...o&&e.slug?{uniqueSlugLocale:m().on(e.slug,e.locale)}:{}}))}function z(e){return Object.values(e.allFields).some(e=>e.type===`blocks`)}function B(e,t){if(!z(e))return null;let n=`${e.name}_layout`,r=t?h(`entity_id`).notNull().references(()=>t.id,{onDelete:`cascade`}):h(`entity_id`).notNull();return d(n,{id:h(`id`).primaryKey().defaultRandom(),entityId:r,fieldName:g(`field_name`,{length:100}).notNull(),blockType:g(`block_type`,{length:100}).notNull(),sortOrder:l(`sort_order`).notNull().default(0),data:u(`data`),locale:g(`locale`,{length:10})},e=>({idx_entity_locale_sort:c(`idx_${n}_entity_locale_sort`).on(e.entityId,e.locale,e.sortOrder)}))}function V(e){return e.behaviors?.some(e=>e.name===`versionable`)??!1}function H(e){if(!(e.behaviors?.some(e=>e.name===`publishable`)??!1))return!1;let t=e.allFields;return Object.values(t).some(e=>e.translatable)}function U(e){return e.behaviors?.some(e=>e.name===`publishable`)??!1}function W(e,t){return d(`${e.name}_locale_status`,{id:h(`id`).primaryKey().defaultRandom(),entityId:h(`entity_id`).notNull().references(()=>t.id,{onDelete:`cascade`}),locale:g(`locale`,{length:10}).notNull(),status:g(`status`,{length:20}).notNull().default(`draft`),publishedAt:p(`published_at`,{withTimezone:!0})},e=>({uniqueEntityLocale:m().on(e.entityId,e.locale)}))}function G(e,t){return d(`${e.name}_drafts`,{id:h(`id`).primaryKey().defaultRandom(),entityId:h(`entity_id`).notNull().references(()=>t.id,{onDelete:`cascade`}),locale:g(`locale`,{length:10}).notNull().default(`_`),data:u(`data`).notNull(),createdBy:g(`created_by`,{length:255}).notNull(),createdByName:g(`created_by_name`,{length:255}),createdAt:p(`created_at`,{withTimezone:!0}).notNull().defaultNow(),updatedAt:p(`updated_at`,{withTimezone:!0}).notNull().defaultNow()},e=>({uniqueEntityLocale:m().on(e.entityId,e.locale)}))}function K(e,t){return d(`${e.name}_versions`,{id:h(`id`).primaryKey().defaultRandom(),entityId:h(`entity_id`).notNull().references(()=>t.id,{onDelete:`cascade`}),version:l(`version`).notNull(),locale:g(`locale`,{length:10}).notNull().default(`_`),data:u(`data`).notNull(),delta:u(`delta`),status:g(`status`,{length:20}),createdBy:g(`created_by`,{length:255}),createdByName:g(`created_by_name`,{length:255}),createdAt:p(`created_at`,{withTimezone:!0}).notNull().defaultNow(),isAutosave:o(`is_autosave`).notNull().default(!1)},e=>({uniqueEntityVersionLocale:m().on(e.entityId,e.version,e.locale)}))}function q(){return d(`toolkit_content_locks`,{id:h(`id`).primaryKey().defaultRandom(),entityType:g(`entity_type`,{length:100}).notNull(),entityId:g(`entity_id`,{length:255}).notNull(),locale:g(`locale`,{length:10}).notNull().default(`_`),lockedBy:g(`locked_by`,{length:255}).notNull(),lockedByName:g(`locked_by_name`,{length:255}),lockedAt:p(`locked_at`,{withTimezone:!0}).notNull().defaultNow(),expiresAt:p(`expires_at`,{withTimezone:!0}).notNull()},e=>({uniqueEntityLock:m().on(e.entityType,e.entityId,e.locale)}))}function J(e){let t=e.allFields;return Object.values(t).some(e=>e.type!==`blocks`||e.localized?!1:e.blocks?.some(e=>Object.values(e.fields).some(e=>e.translatable)))}function Y(e,t){let n=Object.values(e.allFields).filter(e=>e.type===`blocks`&&!(`localized`in e&&e.localized));if(n.length===0||!n.some(e=>e.type===`blocks`?e.blocks.some(e=>Object.values(e.fields).some(e=>e.translatable)):!1))return null;let r=`${e.name}_layout_translations`,i=t?h(`layout_id`).notNull().references(()=>t.id,{onDelete:`cascade`}):h(`layout_id`).notNull();return d(r,{id:h(`id`).primaryKey().defaultRandom(),layoutId:i,locale:g(`locale`,{length:10}).notNull(),fields:u(`fields`).notNull()},e=>({uniqueLayoutLocale:m().on(e.layoutId,e.locale)}))}function X(e){let t={},n=!1;for(let r of e){let e=L(r);t[r.name]=e;let i=R(r,e);if(i&&(t[`${r.name}_translations`]=i),z(r)){let n=B(r,e);if(n){t[`${r.name}_layout`]=n;let e=Y(r,n);e&&(t[`${r.name}_layout_translations`]=e)}}V(r)&&(t[`${r.name}_versions`]=K(r,e)),H(r)&&(t[`${r.name}_locale_status`]=W(r,e)),U(r)&&(t[`${r.name}_drafts`]=G(r,e),n=!0)}return n&&(t.toolkit_content_locks=q()),t.entity_refs=F,t}export{D as CountCache,P as ReferencedEntityError,y as auditable,E as behavior,M as buildCursorCondition,X as buildEntitySchemaMap,j as decodeCursor,N as defineEntity,A as encodeCursor,O as estimateRowCount,_ as field,q as generateContentLocksSchema,G as generateDraftsSchema,B as generateLayoutSchema,Y as generateLayoutTranslationSchema,W as generateLocaleStatusSchema,L as generateSchema,R as generateTranslationSchema,K as generateVersionsSchema,z as hasBlocksFields,J as hasTranslatableBlocks,b as hierarchical,U as isPublishable,V as isVersionable,H as needsLocaleStatus,x as publishable,S as revisionable,w as sluggable,C as slugify,T as timestamped};
|
|
65
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/fields/builders.ts","../src/behaviors/auditable.ts","../src/behaviors/hierarchical.ts","../src/behaviors/publishable.ts","../src/behaviors/revisionable.ts","../src/behaviors/sluggable.ts","../src/behaviors/timestamped.ts","../src/behaviors/index.ts","../src/count-cache.ts","../src/count-estimate.ts","../src/cursor.ts","../src/define-entity.ts","../src/refs/errors.ts","../src/schema-generator.ts"],"sourcesContent":["/**\n * Fluent API for building field definitions\n * Provides type-safe field builders with sensible defaults.\n *\n * Each builder uses a `const` generic parameter on the config to preserve\n * literal types (e.g., `required: true` stays `true`, not `boolean`).\n * This enables compile-time type inference in the entity system.\n */\n\nimport type {\n BlockDefinitionRef,\n BlocksField,\n BooleanField,\n DateField,\n IdField,\n JsonField,\n MediaField,\n NumberField,\n ReferenceField,\n RichTextField,\n SelectField,\n SlugField,\n TextField,\n} from './base.js'\n\nexport const field = {\n /**\n * ID field (auto-added to every entity)\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n id: <const C extends Partial<IdField> = {}>(config?: C): IdField & C =>\n ({\n type: 'id',\n required: true,\n indexed: true,\n ...config,\n }) as IdField & C,\n\n /**\n * Text field\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n text: <const C extends Partial<TextField> = {}>(config?: C): TextField & C =>\n ({\n type: 'text',\n ...config,\n }) as TextField & C,\n\n /**\n * Number field\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n number: <const C extends Partial<NumberField> = {}>(config?: C): NumberField & C =>\n ({\n type: 'number',\n ...config,\n }) as NumberField & C,\n\n /**\n * Boolean field\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n boolean: <const C extends Partial<BooleanField> = {}>(config?: C): BooleanField & C =>\n ({\n type: 'boolean',\n default: false,\n ...config,\n }) as BooleanField & C,\n\n /**\n * Date field\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n date: <const C extends Partial<DateField> = {}>(config?: C): DateField & C =>\n ({\n type: 'date',\n ...config,\n }) as DateField & C,\n\n /**\n * Select field (enum)\n * Preserves literal option types for type inference.\n * e.g. field.select({ options: ['news', 'tutorial'] }) infers 'news' | 'tutorial'\n */\n select: <\n const O extends readonly string[],\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n const C extends Omit<Partial<SelectField>, 'options'> = {},\n >(\n config: { options: O } & C,\n ): SelectField & { options: O } & C =>\n ({\n type: 'select',\n ...config,\n }) as SelectField & { options: O } & C,\n\n /**\n * Reference field (foreign key to another entity)\n * Preserves literal cardinality to distinguish string vs string[] in inferred types.\n */\n reference: <\n C extends 'one' | 'many' = 'one',\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n const R extends Partial<Omit<ReferenceField, 'entity' | 'cardinality'>> = {},\n >(\n config: { entity: string; cardinality?: C } & R,\n ): ReferenceField & { cardinality: C } & R =>\n ({\n type: 'reference',\n cardinality: 'one' as C,\n onDelete: 'set-null',\n ...config,\n }) as ReferenceField & { cardinality: C } & R,\n\n /**\n * Media field (file upload)\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n media: <const C extends Partial<MediaField> = {}>(config?: C): MediaField & C =>\n ({\n type: 'media',\n ...config,\n }) as MediaField & C,\n\n /**\n * Rich text field (WYSIWYG editor)\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n richtext: <const C extends Partial<RichTextField> = {}>(config?: C): RichTextField & C =>\n ({\n type: 'richtext',\n ...config,\n }) as RichTextField & C,\n\n /**\n * Slug field (URL-safe string, auto-generated from source field)\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n slug: <const C extends Partial<SlugField> = {}>(\n config: Pick<SlugField, 'from'> & C,\n ): SlugField & C =>\n ({\n type: 'slug',\n unique: true,\n indexed: true,\n ...config,\n }) as SlugField & C,\n\n /**\n * JSON field (arbitrary JSON data, stored as JSONB)\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n json: <const C extends Partial<JsonField> = {}>(config?: C): JsonField & C =>\n ({\n type: 'json',\n ...config,\n }) as JsonField & C,\n\n /**\n * Blocks field — ordered array of typed content blocks\n * Preserves literal block tuple type for discriminated union inference.\n */\n blocks: <const B extends readonly BlockDefinitionRef[]>(config: {\n blocks: B\n min?: number\n max?: number\n localized?: boolean\n }): BlocksField & { blocks: B } =>\n ({\n type: 'blocks' as const,\n ...config,\n }) as BlocksField & { blocks: B },\n}\n","/**\n * Auditable behavior\n * Adds createdBy, updatedBy, createdAt, updatedAt fields + auto-set logic.\n *\n * When @murumets-ee/core is available (i.e. running inside createApp), the hooks\n * automatically populate createdBy/updatedBy from the RequestContext.\n */\n\nimport { field } from '../fields/builders.js'\nimport type { AuditableFields } from '../types/infer.js'\nimport type { Behavior } from './types.js'\n\n/**\n * Try to get the current user ID from @murumets-ee/core's RequestContext.\n * Returns undefined if @murumets-ee/core isn't loaded or no user is in context.\n *\n * Uses a dynamic import string indirection to avoid TypeScript resolving\n * @murumets-ee/core at compile time (which would create a circular dep: entity → core → entity).\n */\nasync function getCurrentUserId(): Promise<string | undefined> {\n try {\n // Module name built at runtime so TypeScript doesn't try to resolve it during DTS emit\n const moduleName = ['@murumets-ee', 'core'].join('/')\n const core = await (import(moduleName) as Promise<{\n getCurrentUser: () => { id: string } | undefined\n }>)\n return core.getCurrentUser()?.id\n } catch {\n return undefined\n }\n}\n\nexport function auditable(): Behavior<AuditableFields> {\n return {\n name: 'auditable',\n fields: {\n createdBy: field.text(),\n updatedBy: field.text(),\n createdAt: field.date({ indexed: true }),\n updatedAt: field.date({ indexed: true }),\n },\n hooks: {\n beforeCreate: async (data) => {\n data.createdAt = new Date()\n data.updatedAt = new Date()\n const userId = await getCurrentUserId()\n if (userId) {\n data.createdBy = userId\n data.updatedBy = userId\n }\n return data\n },\n beforeUpdate: async (_id, data) => {\n data.updatedAt = new Date()\n const userId = await getCurrentUserId()\n if (userId) {\n data.updatedBy = userId\n }\n return data\n },\n },\n }\n}\n","/**\n * Hierarchical behavior\n * Adds parentId, path, depth fields for materialized path tree structures.\n *\n * Path format: /uuid1/uuid2/uuid3\n * - Root items: /{ownId}\n * - Children: /{rootId}/.../{parentId}/{ownId}\n *\n * The behavior declares fields and sets safe defaults in hooks.\n * Heavy lifting (path computation, circular ref validation, descendant cascading)\n * is done by TaxonomyClient which has DB access.\n */\n\nimport { field } from '../fields/builders.js'\nimport type { HierarchicalFields } from '../types/infer.js'\nimport type { Behavior } from './types.js'\n\nexport interface HierarchicalOptions {\n /**\n * What happens when deleting a node that has children.\n * - 'restrict': Prevent deletion (default)\n * - 'cascade': Delete all descendants\n * - 'reparent': Move children to the deleted node's parent\n */\n onDelete?: 'restrict' | 'cascade' | 'reparent'\n}\n\nexport function hierarchical(_options?: HierarchicalOptions): Behavior<HierarchicalFields> {\n return {\n name: 'hierarchical',\n fields: {\n parentId: field.reference({ entity: '_self', required: false }),\n path: field.text({ indexed: true, maxLength: 2048 }),\n depth: field.number({ integer: true, default: 0, indexed: true }),\n },\n hooks: {\n beforeCreate: async (data) => {\n // Set defaults for root-level items.\n // TaxonomyClient overrides these after insert when it has the ID.\n if (!data.parentId) {\n data.depth = 0\n }\n return data\n },\n },\n }\n}\n","/**\n * Publishable behavior\n * Adds status (draft/published) and publishedAt fields + auto-set logic\n */\n\nimport { field } from '../fields/builders.js'\nimport type { PublishableFields } from '../types/infer.js'\nimport type { Behavior } from './types.js'\n\nexport function publishable(): Behavior<PublishableFields> {\n return {\n name: 'publishable',\n fields: {\n status: field.select({\n options: ['draft', 'published'] as const,\n default: 'draft',\n indexed: true,\n }),\n publishedAt: field.date({ indexed: true }),\n },\n hooks: {\n beforeUpdate: async (_id, data) => {\n // Auto-set publishedAt when status changes to published (if not already set)\n if (data.status === 'published' && !data.publishedAt) {\n data.publishedAt = new Date()\n }\n return data\n },\n },\n }\n}\n","/**\n * Revisionable behavior\n * Adds _version field + auto-increment on update\n */\n\nimport { field } from '../fields/builders.js'\nimport type { RevisionableFields } from '../types/infer.js'\nimport type { Behavior } from './types.js'\n\nexport function revisionable(): Behavior<RevisionableFields> {\n return {\n name: 'revisionable',\n fields: {\n _version: field.number({ required: true, default: 1, integer: true }),\n },\n hooks: {\n beforeCreate: async (data) => {\n data._version = 1\n return data\n },\n beforeUpdate: async (_id, data) => {\n // Increment version on every update\n data._version = (Number(data._version) || 0) + 1\n return data\n },\n },\n }\n}\n","/**\n * Sluggable behavior\n * Adds slug field + auto-generation from source field\n */\n\nimport { field } from '../fields/builders.js'\nimport type { SluggableFields } from '../types/infer.js'\nimport type { Behavior } from './types.js'\n\nexport interface SluggableOptions {\n /** Make the slug translatable — each locale gets its own slug. Default: false */\n translatable?: boolean\n}\n\n/**\n * Convert text to URL-safe slug\n */\nexport function slugify(text: string): string {\n return text\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, '') // Remove non-word chars except spaces and hyphens\n .replace(/[\\s_-]+/g, '-') // Replace spaces, underscores with single hyphen\n .replace(/^-+|-+$/g, '') // Remove leading/trailing hyphens\n}\n\nexport function sluggable(\n sourceField: string,\n options?: SluggableOptions,\n): Behavior<SluggableFields> {\n return {\n name: 'sluggable',\n fields: {\n slug: field.slug({\n from: sourceField,\n ...(options?.translatable ? { translatable: true } : {}),\n }),\n },\n hooks: {\n beforeCreate: async (data) => {\n // Auto-generate slug from source field if not provided\n if (!data.slug && data[sourceField]) {\n data.slug = slugify(String(data[sourceField]))\n }\n return data\n },\n beforeUpdate: async (_id, data) => {\n // Re-generate slug if source field changed and slug not manually set\n if (data[sourceField] && !data.slug) {\n data.slug = slugify(String(data[sourceField]))\n }\n return data\n },\n },\n }\n}\n","/**\n * Timestamped behavior\n * Adds createdAt and updatedAt fields with auto-set logic.\n * Lighter alternative to auditable() when you don't need createdBy/updatedBy tracking.\n */\n\nimport { field } from '../fields/builders.js'\nimport type { Behavior } from './types.js'\n\nexport type TimestampedFields = {\n createdAt: ReturnType<typeof field.date>\n updatedAt: ReturnType<typeof field.date>\n}\n\nexport function timestamped(): Behavior<TimestampedFields> {\n return {\n name: 'timestamped',\n fields: {\n createdAt: field.date({ indexed: true }),\n updatedAt: field.date({ indexed: true }),\n },\n hooks: {\n beforeCreate: async (data) => {\n data.createdAt = new Date()\n data.updatedAt = new Date()\n return data\n },\n beforeUpdate: async (_id, data) => {\n data.updatedAt = new Date()\n return data\n },\n },\n }\n}\n","/**\n * Behavior exports\n * All behaviors are exported under the `behavior` namespace\n */\n\nimport { auditable } from './auditable.js'\nimport { hierarchical } from './hierarchical.js'\nimport { publishable } from './publishable.js'\nimport { revisionable } from './revisionable.js'\nimport { sluggable } from './sluggable.js'\nimport { timestamped } from './timestamped.js'\n\nexport { publishable, auditable, sluggable, revisionable, hierarchical, timestamped }\nexport type { SluggableOptions } from './sluggable.js'\nexport { slugify } from './sluggable.js'\nexport type { Behavior, BehaviorFactory } from './types.js'\n\n/**\n * Behavior namespace for fluent API\n */\nexport const behavior = {\n publishable,\n auditable,\n sluggable,\n revisionable,\n hierarchical,\n timestamped,\n}\n","/**\n * In-memory TTL cache for COUNT(*) query results.\n *\n * Reduces database load on paginated list pages where the total count\n * is recalculated on every pagination/sort/search interaction. The cache\n * is per-process (not shared across workers) with a short TTL (default 5s)\n * so counts are at most a few seconds stale.\n *\n * Cache keys include the entity name + serialized WHERE clause, so filtered\n * and unfiltered counts are cached independently.\n */\n\n/**\n * Interface for count cache implementations.\n * Used in client configs to avoid TypeScript private-field structural incompatibility\n * across separate .d.ts files.\n */\nexport interface CountCacheLike {\n get(key: string): number | undefined\n set(key: string, count: number): void\n invalidate(prefix: string): void\n}\n\ninterface CountCacheEntry {\n count: number\n expiresAt: number\n}\n\nexport class CountCache implements CountCacheLike {\n private cache = new Map<string, CountCacheEntry>()\n private ttlMs: number\n\n constructor(ttlMs = 5000) {\n this.ttlMs = ttlMs\n }\n\n /**\n * Get a cached count. Returns undefined on miss or expired entry.\n */\n get(key: string): number | undefined {\n const entry = this.cache.get(key)\n if (!entry || Date.now() > entry.expiresAt) {\n if (entry) this.cache.delete(key)\n return undefined\n }\n return entry.count\n }\n\n /**\n * Cache a count result with the configured TTL.\n */\n set(key: string, count: number): void {\n this.cache.set(key, { count, expiresAt: Date.now() + this.ttlMs })\n }\n\n /**\n * Invalidate all cache entries whose key starts with the given prefix.\n * Typically called with the entity name after mutations (create/update/delete).\n */\n invalidate(prefix: string): void {\n for (const key of this.cache.keys()) {\n if (key.startsWith(prefix)) {\n this.cache.delete(key)\n }\n }\n }\n\n /**\n * Remove all expired entries. Useful for periodic cleanup in long-running processes.\n */\n prune(): void {\n const now = Date.now()\n for (const [key, entry] of this.cache.entries()) {\n if (now > entry.expiresAt) {\n this.cache.delete(key)\n }\n }\n }\n\n /**\n * Clear the entire cache.\n */\n clear(): void {\n this.cache.clear()\n }\n\n /**\n * Number of entries currently in the cache (including expired ones not yet pruned).\n */\n get size(): number {\n return this.cache.size\n }\n}\n","/**\n * Postgres row count estimation using pg_class statistics.\n *\n * For unfiltered counts on large tables, querying `pg_class.reltuples`\n * is effectively instant (no table scan) and returns a good approximation\n * that is updated by VACUUM and ANALYZE. This is suitable for pagination\n * totals where exact precision is not critical.\n *\n * SECURITY: The table name is NOT interpolated into SQL — it is passed as a\n * parameterized value to the `relname = $1` comparison. This prevents SQL injection.\n */\n\nimport { sql } from 'drizzle-orm'\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'\n\n/**\n * Estimate the total row count for a table using Postgres statistics.\n *\n * Returns the approximate row count from `pg_class.reltuples`, which is\n * updated by VACUUM/ANALYZE. Returns 0 if the table is not found or\n * statistics are not yet available (e.g., freshly created table).\n *\n * @param db - Drizzle Postgres database instance\n * @param tableName - The Postgres table name (without schema prefix)\n * @returns Estimated row count (non-negative integer)\n */\nexport async function estimateRowCount(db: PostgresJsDatabase, tableName: string): Promise<number> {\n const result = await db.execute(\n sql`SELECT reltuples::bigint AS estimate FROM pg_class WHERE relname = ${tableName}`,\n )\n\n const rows = Array.isArray(result) ? result : ((result as { rows?: unknown[] }).rows ?? [])\n const row = rows[0] as { estimate?: string | number } | undefined\n const estimate = Number(row?.estimate ?? 0)\n\n // reltuples can be -1 for tables that have never been analyzed\n return estimate > 0 ? estimate : 0\n}\n","/**\n * Cursor-based (keyset) pagination utilities.\n *\n * Cursor pagination avoids the performance cliff of OFFSET at scale (1M+ rows).\n * Instead of `OFFSET N`, it uses a WHERE condition:\n * `WHERE (sortField < lastValue) OR (sortField = lastValue AND id < lastId)`\n * which Postgres can serve from an index in constant time.\n *\n * The cursor is opaque to the client — base64-encoded JSON.\n *\n * Security:\n * - `field` must be whitelisted against the entity's actual fields\n * - `id` must be a valid UUID\n * - `value` is parameterized (never interpolated into SQL)\n * - Malformed cursors return null (caller returns 400)\n */\n\nimport { and, eq, gt, lt, or, type SQL } from 'drizzle-orm'\nimport type { PgTableWithColumns } from 'drizzle-orm/pg-core'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Cursor input for keyset pagination. */\nexport interface CursorInput {\n /** Sort field name (e.g. 'createdAt'). Must be a real column on the entity. */\n field: string\n /** Last seen value of the sort field. */\n value: string | number\n /** Sort direction — must match the ORDER BY direction. */\n direction: 'asc' | 'desc'\n /** Tie-breaker: last seen entity ID. Required for non-unique sort fields. */\n id?: string\n}\n\n/** Decoded cursor (internal, after validation). */\ninterface DecodedCursor {\n field: string\n value: string | number\n direction: 'asc' | 'desc'\n id?: string\n}\n\n// ---------------------------------------------------------------------------\n// UUID validation (same format used throughout the toolkit)\n// ---------------------------------------------------------------------------\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\n// ---------------------------------------------------------------------------\n// Encode / decode\n// ---------------------------------------------------------------------------\n\n/**\n * Encode a cursor for API transport (base64url).\n * Built from the last item in a result set.\n */\nexport function encodeCursor(\n item: Record<string, unknown>,\n sortField: string,\n direction: 'asc' | 'desc',\n): string {\n const payload: CursorInput = {\n field: sortField,\n value: item[sortField] as string | number,\n direction,\n id: item.id as string | undefined,\n }\n return btoa(JSON.stringify(payload))\n}\n\n/**\n * Decode and validate a cursor string from query params.\n * Returns null if the cursor is malformed, tampered, or invalid.\n *\n * Security: the `field` value is NOT validated here — the caller must\n * whitelist it against the entity's actual columns.\n */\nexport function decodeCursor(encoded: string): DecodedCursor | null {\n try {\n const json = atob(encoded)\n const parsed: unknown = JSON.parse(json)\n\n if (typeof parsed !== 'object' || parsed === null) return null\n const obj = parsed as Record<string, unknown>\n\n // Validate field\n if (typeof obj.field !== 'string' || !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(obj.field)) {\n return null\n }\n\n // Validate value (string or number)\n if (typeof obj.value !== 'string' && typeof obj.value !== 'number') {\n return null\n }\n\n // Validate direction\n if (obj.direction !== 'asc' && obj.direction !== 'desc') {\n return null\n }\n\n // Validate id (optional, must be UUID if present)\n if (obj.id !== undefined) {\n if (typeof obj.id !== 'string' || !UUID_RE.test(obj.id)) {\n return null\n }\n }\n\n return {\n field: obj.field,\n value: obj.value,\n direction: obj.direction,\n id: obj.id as string | undefined,\n }\n } catch {\n return null\n }\n}\n\n// ---------------------------------------------------------------------------\n// SQL condition builder\n// ---------------------------------------------------------------------------\n\n/**\n * Build the keyset WHERE condition from a decoded cursor.\n *\n * For DESC: `WHERE (field < value) OR (field = value AND id < cursorId)`\n * For ASC: `WHERE (field > value) OR (field = value AND id > cursorId)`\n *\n * The caller must verify that `cursor.field` exists on the table before calling.\n *\n * @param table - Drizzle table with columns\n * @param cursor - Decoded and validated cursor\n * @returns SQL condition, or null if the field doesn't exist on the table\n */\nexport function buildCursorCondition(\n // biome-ignore lint/suspicious/noExplicitAny: dynamic table columns require PgTableWithColumns<any> for property access\n table: PgTableWithColumns<any>,\n cursor: DecodedCursor,\n): SQL | null {\n const column = table[cursor.field]\n if (!column) return null\n\n const isDesc = cursor.direction === 'desc'\n const compare = isDesc ? lt : gt\n\n // Primary condition: sort field passes the cursor value\n const fieldCondition = compare(column, cursor.value)\n\n // Without tie-breaker ID, use simple comparison\n if (!cursor.id) {\n return fieldCondition\n }\n\n // With tie-breaker: (field < value) OR (field = value AND id < cursorId)\n const idColumn = table.id\n if (!idColumn) return fieldCondition\n\n const idCondition = compare(idColumn, cursor.id)\n return or(fieldCondition, and(eq(column, cursor.value), idCondition))!\n}\n","/**\n * Entity definition API\n * The core function for defining entities with full type inference.\n *\n * The generic parameters are inferred from the call site:\n * - F is inferred from `definition.fields`\n * - B is inferred from `definition.behaviors` (as a tuple)\n *\n * The returned Entity carries the complete field map:\n * { id: IdField } & BehaviorFields & UserFields\n */\n\nimport type { EntityAdminConfig } from './admin-config.js'\nimport type { Behavior } from './behaviors/types.js'\nimport type { FieldConfig, IdField } from './fields/base.js'\nimport { field } from './fields/builders.js'\n\n/**\n * Entity definition input (without behaviors — behaviors are typed separately\n * on the `defineEntity` function to enable tuple inference).\n *\n * @typeParam F - The literal field map. Inferred automatically from the call site.\n */\nexport interface EntityDefinition<\n F extends Record<string, FieldConfig> = Record<string, FieldConfig>,\n> {\n name: string\n kind?: 'collection' | 'singleton'\n fields: F\n scope?: 'global' | 'team' | 'user'\n access?: {\n view?: string\n create?: string\n update?: string\n delete?: string\n }\n /** Admin UI configuration — controls sidebar, list, and form display */\n admin?: EntityAdminConfig\n}\n\n/**\n * Full input for defineEntity (fields + behaviors + other config).\n * Behaviors are typed as a tuple `B` for type extraction.\n */\nexport type EntityInput<\n F extends Record<string, FieldConfig> = Record<string, FieldConfig>,\n B extends Behavior[] = Behavior[],\n> = EntityDefinition<F> & { behaviors?: B }\n\n/**\n * A fully resolved entity with merged behavior fields.\n * @typeParam AllFields - The complete field map (id + behaviors + user fields).\n */\nexport interface Entity<\n AllFields extends Record<string, FieldConfig> = Record<string, FieldConfig>,\n> {\n name: string\n kind?: 'collection' | 'singleton'\n fields: Record<string, FieldConfig>\n behaviors?: Behavior[]\n scope?: 'global' | 'team' | 'user'\n access?: {\n view?: string\n create?: string\n update?: string\n delete?: string\n }\n /** Admin UI configuration — controls sidebar, list, and form display */\n admin?: EntityAdminConfig\n allFields: AllFields\n hooks: Behavior['hooks']\n}\n\n/**\n * Extract and intersect behavior field types from a behaviors tuple.\n * Walks the tuple recursively (depth bounded by number of behaviors, max ~5).\n */\ntype ExtractBehaviorFields<B extends Behavior[]> = B extends [\n Behavior<infer F1>,\n ...infer Rest extends Behavior[],\n]\n ? F1 & ExtractBehaviorFields<Rest>\n : // biome-ignore lint/complexity/noBannedTypes: empty object is correct for base case of intersection\n {}\n\n/**\n * Define an entity with full type inference.\n *\n * @example\n * const Article = defineEntity({\n * name: 'article',\n * fields: {\n * title: field.text({ required: true }),\n * featured: field.boolean(),\n * },\n * behaviors: [publishable(), auditable()],\n * })\n *\n * type ArticleDTO = InferEntity<typeof Article>\n * // { id: string; title: string; featured?: boolean | null; status?: ...; createdAt?: ...; }\n */\nexport function defineEntity<\n F extends Record<string, FieldConfig>,\n const B extends Behavior[] = [],\n>(\n definition: EntityDefinition<F> & { behaviors?: B },\n): Entity<{ id: IdField } & ExtractBehaviorFields<B> & F> {\n // Merge behavior fields into main fields\n const behaviorFields: Record<string, FieldConfig> = {}\n const hooks: NonNullable<Behavior['hooks']> = {}\n\n for (const behavior of definition.behaviors || []) {\n // Merge fields from behavior\n if (behavior.fields) {\n for (const [fieldName, fieldConfig] of Object.entries(behavior.fields)) {\n if (behaviorFields[fieldName]) {\n console.warn(\n `Field '${fieldName}' from behavior '${behavior.name}' conflicts with existing field. Skipping.`,\n )\n continue\n }\n behaviorFields[fieldName] = fieldConfig\n }\n }\n\n // Merge hooks from behavior\n if (behavior.hooks) {\n for (const [hookName, hookFn] of Object.entries(behavior.hooks)) {\n const typedHookName = hookName as keyof NonNullable<Behavior['hooks']>\n\n if (hookFn) {\n const existingHook = hooks[typedHookName]\n\n if (existingHook) {\n // Chain hooks: execute existing first, then new one\n const previousHook = existingHook as (...args: unknown[]) => Promise<unknown>\n const currentHook = hookFn as (...args: unknown[]) => Promise<unknown>\n\n const chainedHook = async (...args: unknown[]) => {\n const result = await previousHook(...args)\n if (result !== undefined) {\n // Hook returned modified data — replace last arg (the data param),\n // keep leading args (e.g. id) intact for hooks like beforeUpdate(id, data)\n const nextArgs = [...args]\n nextArgs[nextArgs.length - 1] = result\n return await currentHook(...nextArgs)\n }\n return await currentHook(...args)\n }\n // biome-ignore lint/suspicious/noExplicitAny: dynamic dispatch over heterogeneous hook signatures\n hooks[typedHookName] = chainedHook as any\n } else {\n // biome-ignore lint/suspicious/noExplicitAny: dynamic dispatch over heterogeneous hook signatures\n hooks[typedHookName] = hookFn as any\n }\n }\n }\n }\n }\n\n // Build complete field set\n // Order: id (always first) → behavior fields → user-defined fields\n const allFields: Record<string, FieldConfig> = {\n id: field.id(), // Every entity gets an ID\n ...behaviorFields,\n ...definition.fields,\n }\n\n // Auto-infer translatable slugs: if a slug field's source field is translatable,\n // the slug should be translatable too (each locale gets its own URL-safe slug).\n for (const [, fieldConfig] of Object.entries(allFields)) {\n if (\n fieldConfig.type === 'slug' &&\n !fieldConfig.translatable &&\n allFields[fieldConfig.from]?.translatable\n ) {\n fieldConfig.translatable = true\n }\n }\n\n // The cast through `unknown` is safe: runtime merge order (id + behaviors + user fields)\n // exactly mirrors the type-level intersection. TypeScript cannot verify imperative\n // Object.entries() loops produce the same result as a type-level intersection,\n // so we cast at this single auditable boundary.\n return {\n ...definition,\n allFields,\n hooks,\n } as unknown as Entity<{ id: IdField } & ExtractBehaviorFields<B> & F>\n}\n","/**\n * Error thrown when attempting to delete an entity that is still referenced.\n */\n\nimport type { EntityUsage } from './find-usages.js'\n\nexport class ReferencedEntityError extends Error {\n public readonly entityName: string\n public readonly entityId: string\n public readonly usages: EntityUsage[]\n\n constructor(entityName: string, entityId: string, usages: EntityUsage[]) {\n const count = usages.length\n super(\n `Cannot delete ${entityName} '${entityId}': referenced by ${count} other entit${count === 1 ? 'y' : 'ies'}`,\n )\n this.name = 'ReferencedEntityError'\n this.entityName = entityName\n this.entityId = entityId\n this.usages = usages\n }\n}\n","/**\n * Schema generator\n * Converts entity definitions to Drizzle schemas.\n * Every field gets its own Postgres column — no JSONB blobs.\n */\n\nimport type { PgColumnBuilderBase } from 'drizzle-orm/pg-core'\nimport {\n boolean,\n doublePrecision,\n index,\n integer,\n jsonb,\n pgTable,\n text,\n timestamp,\n unique,\n uuid,\n varchar,\n} from 'drizzle-orm/pg-core'\nimport type { Entity } from './define-entity.js'\nimport type { FieldConfig } from './fields/base.js'\n\n/**\n * Convert a field config to a Drizzle column.\n *\n * @param nullable - When true, skips notNull and default constraints.\n * Used for translation table columns (translations are partial overrides).\n */\nexport function fieldToColumn(\n fieldName: string,\n fieldConfig: FieldConfig,\n options?: { nullable?: boolean },\n): PgColumnBuilderBase {\n const nullable = options?.nullable ?? false\n\n switch (fieldConfig.type) {\n case 'id':\n return uuid(fieldName).primaryKey().defaultRandom()\n\n case 'text':\n if (fieldConfig.maxLength && fieldConfig.maxLength <= 255) {\n let column = varchar(fieldName, { length: fieldConfig.maxLength })\n if (fieldConfig.unique) column = column.unique()\n if (!nullable && fieldConfig.required) column = column.notNull()\n if (!nullable && fieldConfig.default !== undefined)\n column = column.default(fieldConfig.default as string)\n return column\n } else {\n let column = text(fieldName)\n if (fieldConfig.unique) column = column.unique()\n if (!nullable && fieldConfig.required) column = column.notNull()\n if (!nullable && fieldConfig.default !== undefined)\n column = column.default(fieldConfig.default as string)\n return column\n }\n\n case 'number': {\n let numColumn = fieldConfig.integer ? integer(fieldName) : doublePrecision(fieldName)\n if (!nullable && fieldConfig.required) numColumn = numColumn.notNull()\n if (!nullable && fieldConfig.default !== undefined)\n numColumn = numColumn.default(fieldConfig.default as number)\n return numColumn\n }\n\n case 'boolean': {\n let boolColumn = boolean(fieldName)\n if (!nullable && fieldConfig.required) boolColumn = boolColumn.notNull()\n if (!nullable) {\n const boolDefault =\n fieldConfig.default !== undefined ? (fieldConfig.default as boolean) : false\n boolColumn = boolColumn.default(boolDefault)\n }\n return boolColumn\n }\n\n case 'date': {\n let dateColumn = timestamp(fieldName, { withTimezone: true })\n if (!nullable && fieldConfig.required) dateColumn = dateColumn.notNull()\n if (!nullable && fieldConfig.default !== undefined)\n dateColumn = dateColumn.default(fieldConfig.default as Date)\n return dateColumn\n }\n\n case 'select': {\n let selectColumn = varchar(fieldName, { length: 100 })\n if (!nullable && fieldConfig.required) selectColumn = selectColumn.notNull()\n if (!nullable && fieldConfig.default !== undefined)\n selectColumn = selectColumn.default(fieldConfig.default as string)\n return selectColumn\n }\n\n case 'reference': {\n if (fieldConfig.cardinality === 'many') {\n return uuid(fieldName).array()\n }\n let refColumn = uuid(fieldName)\n if (!nullable && fieldConfig.required) refColumn = refColumn.notNull()\n return refColumn\n }\n\n case 'media': {\n let mediaColumn = uuid(fieldName)\n if (!nullable && fieldConfig.required) mediaColumn = mediaColumn.notNull()\n return mediaColumn\n }\n\n case 'slug': {\n let slugColumn = varchar(fieldName, { length: 255 })\n // For translation tables (nullable=true), skip per-column unique —\n // translatable slugs use composite UNIQUE(slug, locale) at table level instead.\n if (fieldConfig.unique && !nullable) slugColumn = slugColumn.unique()\n if (!nullable && fieldConfig.required) slugColumn = slugColumn.notNull()\n return slugColumn\n }\n\n case 'richtext': {\n // TipTap HTML strings stored as text\n let rtColumn = text(fieldName)\n if (!nullable && fieldConfig.required) rtColumn = rtColumn.notNull()\n return rtColumn\n }\n\n case 'json':\n return jsonb(fieldName)\n\n default:\n return text(fieldName)\n }\n}\n\n/**\n * Generate TypeScript code string for a single column.\n *\n * @param nullable - When true, skips notNull and default constraints.\n */\nfunction generateColumnCode(\n fieldName: string,\n fieldConfig: FieldConfig,\n options?: { nullable?: boolean },\n): string {\n const nullable = options?.nullable ?? false\n\n switch (fieldConfig.type) {\n case 'id':\n return `id: uuid('id').primaryKey().defaultRandom()`\n\n case 'text': {\n const maxLen = fieldConfig.maxLength\n let textCol =\n maxLen && maxLen <= 255 ? `varchar('${fieldName}', { length: ${maxLen} })` : `text('${fieldName}')`\n if (fieldConfig.unique) textCol += `.unique()`\n if (!nullable && fieldConfig.required) textCol += `.notNull()`\n if (!nullable && fieldConfig.default) textCol += `.default('${fieldConfig.default}')`\n return `${fieldName}: ${textCol}`\n }\n\n case 'number': {\n let numCol = fieldConfig.integer\n ? `integer('${fieldName}')`\n : `doublePrecision('${fieldName}')`\n if (!nullable && fieldConfig.required) numCol += `.notNull()`\n if (!nullable && fieldConfig.default !== undefined)\n numCol += `.default(${fieldConfig.default})`\n return `${fieldName}: ${numCol}`\n }\n\n case 'boolean': {\n if (nullable) {\n return `${fieldName}: boolean('${fieldName}')`\n }\n const boolDefault = fieldConfig.default ?? false\n return `${fieldName}: boolean('${fieldName}').default(${boolDefault})`\n }\n\n case 'date': {\n let dateCol = `timestamp('${fieldName}', { withTimezone: true })`\n if (!nullable && fieldConfig.required) dateCol += `.notNull()`\n return `${fieldName}: ${dateCol}`\n }\n\n case 'reference': {\n if (fieldConfig.cardinality === 'many') {\n return `${fieldName}: uuid('${fieldName}').array()`\n }\n let refCol = `uuid('${fieldName}')`\n if (!nullable && fieldConfig.required) refCol += `.notNull()`\n return `${fieldName}: ${refCol}`\n }\n\n case 'media': {\n let mediaCol = `uuid('${fieldName}')`\n if (!nullable && fieldConfig.required) mediaCol += `.notNull()`\n return `${fieldName}: ${mediaCol}`\n }\n\n case 'slug': {\n let slugCol = `varchar('${fieldName}', { length: 255 })`\n if (fieldConfig.unique && !nullable) slugCol += `.unique()`\n if (!nullable && fieldConfig.required) slugCol += `.notNull()`\n return `${fieldName}: ${slugCol}`\n }\n\n case 'select': {\n let selectCol = `varchar('${fieldName}', { length: 100 })`\n if (!nullable && fieldConfig.required) selectCol += `.notNull()`\n if (!nullable && fieldConfig.default) selectCol += `.default('${fieldConfig.default}')`\n return `${fieldName}: ${selectCol}`\n }\n\n case 'richtext': {\n let rtCol = `text('${fieldName}')`\n if (!nullable && fieldConfig.required) rtCol += `.notNull()`\n return `${fieldName}: ${rtCol}`\n }\n\n case 'json':\n return `${fieldName}: jsonb('${fieldName}')`\n\n default:\n return `${fieldName}: text('${fieldName}')`\n }\n}\n\n/**\n * Generate a runtime Drizzle schema from an entity definition.\n * Every field becomes its own column — no JSONB.\n */\nexport function generateSchema(entity: Entity) {\n const tableName = entity.name\n const columns: Record<string, PgColumnBuilderBase> = {}\n\n for (const [fieldName, fieldConfig] of Object.entries(entity.allFields)) {\n if (fieldConfig.type === 'blocks') continue // stored in layout table\n columns[fieldName] = fieldToColumn(fieldName, fieldConfig)\n }\n\n if (entity.scope === 'team' || entity.scope === 'user') {\n columns._scopeId = uuid('_scope_id')\n }\n\n // Collect fields that need indexes (skip id/unique — they already have btree indexes)\n const indexedFields = Object.entries(entity.allFields).filter(\n ([_, config]) =>\n config.type !== 'blocks' && config.type !== 'id' && config.indexed && !config.unique,\n )\n\n const isPublishableEntity = entity.behaviors?.some((b) => b.name === 'publishable') ?? false\n\n if (indexedFields.length === 0 && !isPublishableEntity) {\n return pgTable(tableName, columns)\n }\n\n return pgTable(tableName, columns, (table) => {\n // biome-ignore lint/suspicious/noExplicitAny: dynamic table columns from pgTable callback\n const constraints: Record<string, any> = {}\n\n for (const [fieldName] of indexedFields) {\n constraints[`idx_${tableName}_${fieldName}`] = index(`idx_${tableName}_${fieldName}`).on(\n table[fieldName],\n )\n }\n\n // Composite index for publishable entities: status + createdAt (most common list query)\n if (isPublishableEntity && table.status && table.createdAt) {\n constraints[`idx_${tableName}_status_created`] = index(`idx_${tableName}_status_created`).on(\n table.status,\n table.createdAt,\n )\n }\n\n return constraints\n })\n}\n\n/**\n * Generate TypeScript code string for an entity schema.\n * Every field becomes its own column — no JSONB.\n */\nexport function generateSchemaCode(entity: Entity): string {\n const tableName = entity.name\n const lines: string[] = []\n\n // Collect fields that need indexes (skip id/unique — they already have btree indexes)\n const indexedFields = Object.entries(entity.allFields).filter(\n ([_, config]) =>\n config.type !== 'blocks' && config.type !== 'id' && config.indexed && !config.unique,\n )\n\n const isPublishableEntity = entity.behaviors?.some((b) => b.name === 'publishable') ?? false\n const needsIndexes = indexedFields.length > 0 || isPublishableEntity\n\n lines.push(`export const ${tableName} = pgTable('${tableName}', {`)\n\n for (const [fieldName, fieldConfig] of Object.entries(entity.allFields)) {\n if (fieldConfig.type === 'blocks') continue // stored in layout table\n const columnCode = generateColumnCode(fieldName, fieldConfig)\n lines.push(` ${columnCode},`)\n }\n\n if (entity.scope === 'team' || entity.scope === 'user') {\n lines.push(` _scopeId: uuid('_scope_id'),`)\n }\n\n if (needsIndexes) {\n lines.push(`}, (table) => ({`)\n\n for (const [fieldName] of indexedFields) {\n lines.push(\n ` idx_${tableName}_${fieldName}: index('idx_${tableName}_${fieldName}').on(table.${fieldName}),`,\n )\n }\n\n // Composite index for publishable entities: status + createdAt\n if (isPublishableEntity) {\n lines.push(\n ` idx_${tableName}_status_created: index('idx_${tableName}_status_created').on(table.status, table.createdAt),`,\n )\n }\n\n lines.push(`}))`)\n } else {\n lines.push(`)`)\n }\n\n return lines.join('\\n')\n}\n\n/**\n * Generate runtime translation table schema.\n * Each translatable field gets its own nullable column.\n */\nexport function generateTranslationSchema(entity: Entity) {\n const translatableFields = Object.entries(entity.allFields).filter(\n ([_, config]) => config.translatable,\n )\n\n if (translatableFields.length === 0) return null\n\n const tableName = `${entity.name}_translations`\n const columns: Record<string, PgColumnBuilderBase> = {\n id: uuid('id').primaryKey().defaultRandom(),\n entityId: uuid('entity_id').notNull(),\n locale: varchar('locale', { length: 10 }).notNull(),\n }\n\n const hasTranslatableSlug = translatableFields.some(([_, config]) => config.type === 'slug')\n\n for (const [fieldName, fieldConfig] of translatableFields) {\n columns[fieldName] = fieldToColumn(fieldName, fieldConfig, { nullable: true })\n }\n\n return pgTable(tableName, columns, (table) => ({\n uniqueEntityLocale: unique().on(table.entityId, table.locale),\n // Per-locale slug uniqueness: no two entities can share the same slug in the same locale\n ...(hasTranslatableSlug && table.slug\n ? { uniqueSlugLocale: unique().on(table.slug, table.locale) }\n : {}),\n }))\n}\n\n/**\n * Generate TypeScript code string for a translation table.\n * Each translatable field gets its own nullable column.\n */\nexport function generateTranslationSchemaCode(entity: Entity): string | null {\n const translatableFields = Object.entries(entity.allFields).filter(\n ([_, config]) => config.translatable,\n )\n\n if (translatableFields.length === 0) return null\n\n const tableName = `${entity.name}_translations`\n const entityTableName = entity.name\n const lines: string[] = []\n\n lines.push(`export const ${tableName} = pgTable('${tableName}', {`)\n lines.push(` id: uuid('id').primaryKey().defaultRandom(),`)\n lines.push(\n ` entityId: uuid('entity_id').notNull().references(() => ${entityTableName}.id, { onDelete: 'cascade' }),`,\n )\n lines.push(` locale: varchar('locale', { length: 10 }).notNull(),`)\n\n for (const [fieldName, fieldConfig] of translatableFields) {\n const columnCode = generateColumnCode(fieldName, fieldConfig, { nullable: true })\n lines.push(` ${columnCode},`)\n }\n\n const hasTranslatableSlug = translatableFields.some(([_, config]) => config.type === 'slug')\n\n lines.push(`}, (table) => ({`)\n lines.push(\n ` uniqueEntityLocale: unique().on(table.entityId, table.locale), // One translation per locale`,\n )\n if (hasTranslatableSlug) {\n lines.push(\n ` uniqueSlugLocale: unique().on(table.slug, table.locale), // Per-locale slug uniqueness`,\n )\n }\n lines.push(`}))`)\n\n return lines.join('\\n')\n}\n\n/**\n * Check if an entity has any blocks fields\n */\nexport function hasBlocksFields(entity: Entity): boolean {\n return Object.values(entity.allFields).some((f) => f.type === 'blocks')\n}\n\n/**\n * Generate layout table schema for entities with blocks fields.\n * Stores block instances in a separate table with ordering.\n *\n * When blocks field has localized: false (default), locale is NULL (shared layout).\n * When blocks field has localized: true, locale is set per-locale.\n */\nexport function generateLayoutSchema(entity: Entity) {\n if (!hasBlocksFields(entity)) return null\n\n const tableName = `${entity.name}_layout`\n\n return pgTable(\n tableName,\n {\n id: uuid('id').primaryKey().defaultRandom(),\n entityId: uuid('entity_id').notNull(),\n fieldName: varchar('field_name', { length: 100 }).notNull(),\n blockType: varchar('block_type', { length: 100 }).notNull(),\n sortOrder: integer('sort_order').notNull().default(0),\n data: jsonb('data'),\n locale: varchar('locale', { length: 10 }),\n },\n (table) => ({\n // Covers: WHERE entity_id IN (...) AND locale IS NULL ORDER BY sort_order\n idx_entity_locale_sort: index(`idx_${tableName}_entity_locale_sort`).on(\n table.entityId,\n table.locale,\n table.sortOrder,\n ),\n }),\n )\n}\n\n/**\n * Check if an entity has the versionable behavior\n */\nexport function isVersionable(entity: Entity): boolean {\n return entity.behaviors?.some((b) => b.name === 'versionable') ?? false\n}\n\n/**\n * Check if an entity needs a per-locale publish status table.\n * Requires both publishable() behavior AND at least one translatable field.\n */\nexport function needsLocaleStatus(entity: Entity): boolean {\n const isPublishable = entity.behaviors?.some((b) => b.name === 'publishable') ?? false\n if (!isPublishable) return false\n const allFields = entity.allFields as Record<string, { translatable?: boolean }>\n return Object.values(allFields).some((f) => f.translatable)\n}\n\n/**\n * Generate TypeScript code string for a per-locale publish status table.\n */\nexport function generateLocaleStatusCode(entity: Entity): string {\n const name = entity.name\n const varName = `${name}_locale_status`\n return `export const ${varName} = pgTable('${varName}', {\n id: uuid('id').primaryKey().defaultRandom(),\n entityId: uuid('entity_id').notNull().references(() => ${name}.id, { onDelete: 'cascade' }),\n locale: varchar('locale', { length: 10 }).notNull(),\n status: varchar('status', { length: 20 }).notNull().default('draft'),\n publishedAt: timestamp('published_at', { withTimezone: true }),\n}, (table) => ({\n uniqueEntityLocale: unique().on(table.entityId, table.locale),\n}))`\n}\n\n/**\n * Check if an entity is publishable (has publishable() behavior).\n */\nexport function isPublishable(entity: Entity): boolean {\n return entity.behaviors?.some((b) => b.name === 'publishable') ?? false\n}\n\n/**\n * Generate TypeScript code string for a drafts overlay table.\n */\nexport function generateDraftsCode(entity: Entity): string {\n const name = entity.name\n const varName = `${name}_drafts`\n return `export const ${varName} = pgTable('${varName}', {\n id: uuid('id').primaryKey().defaultRandom(),\n entityId: uuid('entity_id').notNull().references(() => ${name}.id, { onDelete: 'cascade' }),\n locale: varchar('locale', { length: 10 }).notNull().default('_'),\n data: jsonb('data').notNull(),\n createdBy: varchar('created_by', { length: 255 }).notNull(),\n createdByName: varchar('created_by_name', { length: 255 }),\n createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),\n}, (table) => ({\n uniqueEntityLocale: unique().on(table.entityId, table.locale),\n}))`\n}\n\n/**\n * Generate TypeScript code string for the shared content locks table.\n */\nexport function generateContentLocksCode(): string {\n return `export const toolkit_content_locks = pgTable('toolkit_content_locks', {\n id: uuid('id').primaryKey().defaultRandom(),\n entityType: varchar('entity_type', { length: 100 }).notNull(),\n entityId: varchar('entity_id', { length: 255 }).notNull(),\n locale: varchar('locale', { length: 10 }).notNull().default('_'),\n lockedBy: varchar('locked_by', { length: 255 }).notNull(),\n lockedByName: varchar('locked_by_name', { length: 255 }),\n lockedAt: timestamp('locked_at', { withTimezone: true }).notNull().defaultNow(),\n expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),\n}, (table) => ({\n uniqueEntityLock: unique().on(table.entityType, table.entityId, table.locale),\n}))`\n}\n\n/**\n * Check if an entity has blocks fields with translatable block content (non-localized mode).\n */\nexport function hasTranslatableBlocks(entity: Entity): boolean {\n const allFields = entity.allFields as Record<\n string,\n {\n type: string\n localized?: boolean\n blocks?: Array<{ fields: Record<string, { translatable?: boolean }> }>\n }\n >\n return Object.values(allFields).some((f) => {\n if (f.type !== 'blocks') return false\n if (f.localized) return false\n return f.blocks?.some((block) => Object.values(block.fields).some((bf) => bf.translatable))\n })\n}\n\n/**\n * Generate TypeScript code string for a layout table (blocks storage).\n */\nexport function generateLayoutCode(entity: Entity): string {\n const name = entity.name\n const varName = `${name}_layout`\n return `export const ${varName} = pgTable('${varName}', {\n id: uuid('id').primaryKey().defaultRandom(),\n entityId: uuid('entity_id').notNull().references(() => ${name}.id, { onDelete: 'cascade' }),\n fieldName: varchar('field_name', { length: 100 }).notNull(),\n blockType: varchar('block_type', { length: 100 }).notNull(),\n sortOrder: integer('sort_order').notNull().default(0),\n data: jsonb('data'),\n locale: varchar('locale', { length: 10 }),\n}, (table) => ({\n idx_entity_locale_sort: index('idx_${varName}_entity_locale_sort').on(table.entityId, table.locale, table.sortOrder),\n}))`\n}\n\n/**\n * Generate TypeScript code string for a layout translation table.\n */\nexport function generateLayoutTranslationCode(entity: Entity): string {\n const name = entity.name\n const varName = `${name}_layout_translations`\n const layoutVar = `${name}_layout`\n return `export const ${varName} = pgTable('${varName}', {\n id: uuid('id').primaryKey().defaultRandom(),\n layoutId: uuid('layout_id').notNull().references(() => ${layoutVar}.id, { onDelete: 'cascade' }),\n locale: varchar('locale', { length: 10 }).notNull(),\n fields: jsonb('fields').notNull(),\n}, (table) => ({\n uniqueLayoutLocale: unique().on(table.layoutId, table.locale),\n}))`\n}\n\n/**\n * Generate TypeScript code string for a versions table.\n */\nexport function generateVersionsCode(entity: Entity): string {\n const name = entity.name\n const varName = `${name}_versions`\n return `export const ${varName} = pgTable('${varName}', {\n id: uuid('id').primaryKey().defaultRandom(),\n entityId: uuid('entity_id').notNull().references(() => ${name}.id, { onDelete: 'cascade' }),\n version: integer('version').notNull(),\n locale: varchar('locale', { length: 10 }).notNull().default('_'),\n data: jsonb('data').notNull(),\n delta: jsonb('delta'),\n status: varchar('status', { length: 20 }),\n createdBy: varchar('created_by', { length: 255 }),\n createdByName: varchar('created_by_name', { length: 255 }),\n createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),\n isAutosave: boolean('is_autosave').notNull().default(false),\n}, (table) => ({\n uniqueEntityVersionLocale: unique().on(table.entityId, table.version, table.locale),\n}))`\n}\n\n/**\n * Generate layout translation table for non-localized blocks with translatable fields.\n */\nexport function generateLayoutTranslationSchema(entity: Entity) {\n const blocksFields = Object.values(entity.allFields).filter(\n (f) => f.type === 'blocks' && !('localized' in f && f.localized),\n )\n\n if (blocksFields.length === 0) return null\n\n const hasTranslatableBlockFields = blocksFields.some((bf) => {\n if (bf.type !== 'blocks') return false\n return bf.blocks.some((block) => Object.values(block.fields).some((f) => f.translatable))\n })\n\n if (!hasTranslatableBlockFields) return null\n\n const tableName = `${entity.name}_layout_translations`\n\n return pgTable(\n tableName,\n {\n id: uuid('id').primaryKey().defaultRandom(),\n layoutId: uuid('layout_id').notNull(),\n locale: varchar('locale', { length: 10 }).notNull(),\n fields: jsonb('fields').notNull(),\n },\n (table) => ({\n uniqueLayoutLocale: unique().on(table.layoutId, table.locale),\n }),\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/fields/builders.ts","../src/behaviors/auditable.ts","../src/behaviors/hierarchical.ts","../src/behaviors/publishable.ts","../src/behaviors/revisionable.ts","../src/behaviors/sluggable.ts","../src/behaviors/timestamped.ts","../src/behaviors/index.ts","../src/count-cache.ts","../src/count-estimate.ts","../src/cursor.ts","../src/define-entity.ts","../src/refs/errors.ts","../src/refs/schema.ts","../src/schema-generator.ts"],"sourcesContent":["/**\n * Fluent API for building field definitions\n * Provides type-safe field builders with sensible defaults.\n *\n * Each builder uses a `const` generic parameter on the config to preserve\n * literal types (e.g., `required: true` stays `true`, not `boolean`).\n * This enables compile-time type inference in the entity system.\n */\n\nimport type {\n BlockDefinitionRef,\n BlocksField,\n BooleanField,\n DateField,\n IdField,\n JsonField,\n MediaField,\n NumberField,\n ReferenceField,\n RichTextField,\n SelectField,\n SlugField,\n TextField,\n} from './base.js'\n\nexport const field = {\n /**\n * ID field (auto-added to every entity)\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n id: <const C extends Partial<IdField> = {}>(config?: C): IdField & C =>\n ({\n type: 'id',\n required: true,\n indexed: true,\n ...config,\n }) as IdField & C,\n\n /**\n * Text field\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n text: <const C extends Partial<TextField> = {}>(config?: C): TextField & C =>\n ({\n type: 'text',\n ...config,\n }) as TextField & C,\n\n /**\n * Number field\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n number: <const C extends Partial<NumberField> = {}>(config?: C): NumberField & C =>\n ({\n type: 'number',\n ...config,\n }) as NumberField & C,\n\n /**\n * Boolean field\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n boolean: <const C extends Partial<BooleanField> = {}>(config?: C): BooleanField & C =>\n ({\n type: 'boolean',\n default: false,\n ...config,\n }) as BooleanField & C,\n\n /**\n * Date field\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n date: <const C extends Partial<DateField> = {}>(config?: C): DateField & C =>\n ({\n type: 'date',\n ...config,\n }) as DateField & C,\n\n /**\n * Select field (enum)\n * Preserves literal option types for type inference.\n * e.g. field.select({ options: ['news', 'tutorial'] }) infers 'news' | 'tutorial'\n */\n select: <\n const O extends readonly string[],\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n const C extends Omit<Partial<SelectField>, 'options'> = {},\n >(\n config: { options: O } & C,\n ): SelectField & { options: O } & C =>\n ({\n type: 'select',\n ...config,\n }) as SelectField & { options: O } & C,\n\n /**\n * Reference field (foreign key to another entity)\n * Preserves literal cardinality to distinguish string vs string[] in inferred types.\n */\n reference: <\n C extends 'one' | 'many' = 'one',\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n const R extends Partial<Omit<ReferenceField, 'entity' | 'cardinality'>> = {},\n >(\n config: { entity: string; cardinality?: C } & R,\n ): ReferenceField & { cardinality: C } & R =>\n ({\n type: 'reference',\n cardinality: 'one' as C,\n onDelete: 'set-null',\n ...config,\n }) as ReferenceField & { cardinality: C } & R,\n\n /**\n * Media field (file upload)\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n media: <const C extends Partial<MediaField> = {}>(config?: C): MediaField & C =>\n ({\n type: 'media',\n ...config,\n }) as MediaField & C,\n\n /**\n * Rich text field (WYSIWYG editor)\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n richtext: <const C extends Partial<RichTextField> = {}>(config?: C): RichTextField & C =>\n ({\n type: 'richtext',\n ...config,\n }) as RichTextField & C,\n\n /**\n * Slug field (URL-safe string, auto-generated from source field)\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n slug: <const C extends Partial<SlugField> = {}>(\n config: Pick<SlugField, 'from'> & C,\n ): SlugField & C =>\n ({\n type: 'slug',\n unique: true,\n indexed: true,\n ...config,\n }) as SlugField & C,\n\n /**\n * JSON field (arbitrary JSON data, stored as JSONB)\n */\n // biome-ignore lint/complexity/noBannedTypes: {} is correct as empty generic default\n json: <const C extends Partial<JsonField> = {}>(config?: C): JsonField & C =>\n ({\n type: 'json',\n ...config,\n }) as JsonField & C,\n\n /**\n * Blocks field — ordered array of typed content blocks\n * Preserves literal block tuple type for discriminated union inference.\n */\n blocks: <const B extends readonly BlockDefinitionRef[]>(config: {\n blocks: B\n min?: number\n max?: number\n localized?: boolean\n }): BlocksField & { blocks: B } =>\n ({\n type: 'blocks' as const,\n ...config,\n }) as BlocksField & { blocks: B },\n}\n","/**\n * Auditable behavior\n * Adds createdBy, updatedBy, createdAt, updatedAt fields + auto-set logic.\n *\n * When @murumets-ee/core is available (i.e. running inside createApp), the hooks\n * automatically populate createdBy/updatedBy from the RequestContext.\n */\n\nimport { field } from '../fields/builders.js'\nimport type { AuditableFields } from '../types/infer.js'\nimport type { Behavior } from './types.js'\n\n/**\n * Try to get the current user ID from @murumets-ee/core's RequestContext.\n * Returns undefined if @murumets-ee/core isn't loaded or no user is in context.\n *\n * Uses a dynamic import string indirection to avoid TypeScript resolving\n * @murumets-ee/core at compile time (which would create a circular dep: entity → core → entity).\n */\nasync function getCurrentUserId(): Promise<string | undefined> {\n try {\n // Module name built at runtime so TypeScript doesn't try to resolve it during DTS emit\n const moduleName = ['@murumets-ee', 'core'].join('/')\n const core = await (import(moduleName) as Promise<{\n getCurrentUser: () => { id: string } | undefined\n }>)\n return core.getCurrentUser()?.id\n } catch {\n return undefined\n }\n}\n\nexport function auditable(): Behavior<AuditableFields> {\n return {\n name: 'auditable',\n fields: {\n createdBy: field.text(),\n updatedBy: field.text(),\n createdAt: field.date({ indexed: true }),\n updatedAt: field.date({ indexed: true }),\n },\n hooks: {\n beforeCreate: async (data) => {\n data.createdAt = new Date()\n data.updatedAt = new Date()\n const userId = await getCurrentUserId()\n if (userId) {\n data.createdBy = userId\n data.updatedBy = userId\n }\n return data\n },\n beforeUpdate: async (_id, data) => {\n data.updatedAt = new Date()\n const userId = await getCurrentUserId()\n if (userId) {\n data.updatedBy = userId\n }\n return data\n },\n },\n }\n}\n","/**\n * Hierarchical behavior\n * Adds parentId, path, depth fields for materialized path tree structures.\n *\n * Path format: /uuid1/uuid2/uuid3\n * - Root items: /{ownId}\n * - Children: /{rootId}/.../{parentId}/{ownId}\n *\n * The behavior declares fields and sets safe defaults in hooks.\n * Heavy lifting (path computation, circular ref validation, descendant cascading)\n * is done by TaxonomyClient which has DB access.\n */\n\nimport { field } from '../fields/builders.js'\nimport type { HierarchicalFields } from '../types/infer.js'\nimport type { Behavior } from './types.js'\n\nexport interface HierarchicalOptions {\n /**\n * What happens when deleting a node that has children.\n * - 'restrict': Prevent deletion (default)\n * - 'cascade': Delete all descendants\n * - 'reparent': Move children to the deleted node's parent\n */\n onDelete?: 'restrict' | 'cascade' | 'reparent'\n}\n\nexport function hierarchical(_options?: HierarchicalOptions): Behavior<HierarchicalFields> {\n return {\n name: 'hierarchical',\n fields: {\n parentId: field.reference({ entity: '_self', required: false }),\n path: field.text({ indexed: true, maxLength: 2048 }),\n depth: field.number({ integer: true, default: 0, indexed: true }),\n },\n hooks: {\n beforeCreate: async (data) => {\n // Set defaults for root-level items.\n // TaxonomyClient overrides these after insert when it has the ID.\n if (!data.parentId) {\n data.depth = 0\n }\n return data\n },\n },\n }\n}\n","/**\n * Publishable behavior\n * Adds status (draft/published) and publishedAt fields + auto-set logic\n */\n\nimport { field } from '../fields/builders.js'\nimport type { PublishableFields } from '../types/infer.js'\nimport type { Behavior } from './types.js'\n\nexport function publishable(): Behavior<PublishableFields> {\n return {\n name: 'publishable',\n fields: {\n status: field.select({\n options: ['draft', 'published'] as const,\n default: 'draft',\n indexed: true,\n }),\n publishedAt: field.date({ indexed: true }),\n },\n hooks: {\n beforeUpdate: async (_id, data) => {\n // Auto-set publishedAt when status changes to published (if not already set)\n if (data.status === 'published' && !data.publishedAt) {\n data.publishedAt = new Date()\n }\n return data\n },\n },\n }\n}\n","/**\n * Revisionable behavior\n * Adds _version field + auto-increment on update\n */\n\nimport { field } from '../fields/builders.js'\nimport type { RevisionableFields } from '../types/infer.js'\nimport type { Behavior } from './types.js'\n\nexport function revisionable(): Behavior<RevisionableFields> {\n return {\n name: 'revisionable',\n fields: {\n _version: field.number({ required: true, default: 1, integer: true }),\n },\n hooks: {\n beforeCreate: async (data) => {\n data._version = 1\n return data\n },\n beforeUpdate: async (_id, data) => {\n // Increment version on every update\n data._version = (Number(data._version) || 0) + 1\n return data\n },\n },\n }\n}\n","/**\n * Sluggable behavior\n * Adds slug field + auto-generation from source field\n */\n\nimport { field } from '../fields/builders.js'\nimport type { SluggableFields } from '../types/infer.js'\nimport type { Behavior } from './types.js'\n\nexport interface SluggableOptions {\n /** Make the slug translatable — each locale gets its own slug. Default: false */\n translatable?: boolean\n}\n\n/**\n * Convert text to URL-safe slug\n */\nexport function slugify(text: string): string {\n return text\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, '') // Remove non-word chars except spaces and hyphens\n .replace(/[\\s_-]+/g, '-') // Replace spaces, underscores with single hyphen\n .replace(/^-+|-+$/g, '') // Remove leading/trailing hyphens\n}\n\nexport function sluggable(\n sourceField: string,\n options?: SluggableOptions,\n): Behavior<SluggableFields> {\n return {\n name: 'sluggable',\n fields: {\n slug: field.slug({\n from: sourceField,\n ...(options?.translatable ? { translatable: true } : {}),\n }),\n },\n hooks: {\n beforeCreate: async (data) => {\n // Auto-generate slug from source field if not provided\n if (!data.slug && data[sourceField]) {\n data.slug = slugify(String(data[sourceField]))\n }\n return data\n },\n beforeUpdate: async (_id, data) => {\n // Re-generate slug if source field changed and slug not manually set\n if (data[sourceField] && !data.slug) {\n data.slug = slugify(String(data[sourceField]))\n }\n return data\n },\n },\n }\n}\n","/**\n * Timestamped behavior\n * Adds createdAt and updatedAt fields with auto-set logic.\n * Lighter alternative to auditable() when you don't need createdBy/updatedBy tracking.\n */\n\nimport { field } from '../fields/builders.js'\nimport type { Behavior } from './types.js'\n\nexport type TimestampedFields = {\n createdAt: ReturnType<typeof field.date>\n updatedAt: ReturnType<typeof field.date>\n}\n\nexport function timestamped(): Behavior<TimestampedFields> {\n return {\n name: 'timestamped',\n fields: {\n createdAt: field.date({ indexed: true }),\n updatedAt: field.date({ indexed: true }),\n },\n hooks: {\n beforeCreate: async (data) => {\n data.createdAt = new Date()\n data.updatedAt = new Date()\n return data\n },\n beforeUpdate: async (_id, data) => {\n data.updatedAt = new Date()\n return data\n },\n },\n }\n}\n","/**\n * Behavior exports\n * All behaviors are exported under the `behavior` namespace\n */\n\nimport { auditable } from './auditable.js'\nimport { hierarchical } from './hierarchical.js'\nimport { publishable } from './publishable.js'\nimport { revisionable } from './revisionable.js'\nimport { sluggable } from './sluggable.js'\nimport { timestamped } from './timestamped.js'\n\nexport { publishable, auditable, sluggable, revisionable, hierarchical, timestamped }\nexport type { SluggableOptions } from './sluggable.js'\nexport { slugify } from './sluggable.js'\nexport type { Behavior, BehaviorFactory } from './types.js'\n\n/**\n * Behavior namespace for fluent API\n */\nexport const behavior = {\n publishable,\n auditable,\n sluggable,\n revisionable,\n hierarchical,\n timestamped,\n}\n","/**\n * In-memory TTL cache for COUNT(*) query results.\n *\n * Reduces database load on paginated list pages where the total count\n * is recalculated on every pagination/sort/search interaction. The cache\n * is per-process (not shared across workers) with a short TTL (default 5s)\n * so counts are at most a few seconds stale.\n *\n * Cache keys include the entity name + serialized WHERE clause, so filtered\n * and unfiltered counts are cached independently.\n */\n\n/**\n * Interface for count cache implementations.\n * Used in client configs to avoid TypeScript private-field structural incompatibility\n * across separate .d.ts files.\n */\nexport interface CountCacheLike {\n get(key: string): number | undefined\n set(key: string, count: number): void\n invalidate(prefix: string): void\n}\n\ninterface CountCacheEntry {\n count: number\n expiresAt: number\n}\n\nexport class CountCache implements CountCacheLike {\n private cache = new Map<string, CountCacheEntry>()\n private ttlMs: number\n\n constructor(ttlMs = 5000) {\n this.ttlMs = ttlMs\n }\n\n /**\n * Get a cached count. Returns undefined on miss or expired entry.\n */\n get(key: string): number | undefined {\n const entry = this.cache.get(key)\n if (!entry || Date.now() > entry.expiresAt) {\n if (entry) this.cache.delete(key)\n return undefined\n }\n return entry.count\n }\n\n /**\n * Cache a count result with the configured TTL.\n */\n set(key: string, count: number): void {\n this.cache.set(key, { count, expiresAt: Date.now() + this.ttlMs })\n }\n\n /**\n * Invalidate all cache entries whose key starts with the given prefix.\n * Typically called with the entity name after mutations (create/update/delete).\n */\n invalidate(prefix: string): void {\n for (const key of this.cache.keys()) {\n if (key.startsWith(prefix)) {\n this.cache.delete(key)\n }\n }\n }\n\n /**\n * Remove all expired entries. Useful for periodic cleanup in long-running processes.\n */\n prune(): void {\n const now = Date.now()\n for (const [key, entry] of this.cache.entries()) {\n if (now > entry.expiresAt) {\n this.cache.delete(key)\n }\n }\n }\n\n /**\n * Clear the entire cache.\n */\n clear(): void {\n this.cache.clear()\n }\n\n /**\n * Number of entries currently in the cache (including expired ones not yet pruned).\n */\n get size(): number {\n return this.cache.size\n }\n}\n","/**\n * Postgres row count estimation using pg_class statistics.\n *\n * For unfiltered counts on large tables, querying `pg_class.reltuples`\n * is effectively instant (no table scan) and returns a good approximation\n * that is updated by VACUUM and ANALYZE. This is suitable for pagination\n * totals where exact precision is not critical.\n *\n * SECURITY: The table name is NOT interpolated into SQL — it is passed as a\n * parameterized value to the `relname = $1` comparison. This prevents SQL injection.\n */\n\nimport { sql } from 'drizzle-orm'\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'\n\n/**\n * Estimate the total row count for a table using Postgres statistics.\n *\n * Returns the approximate row count from `pg_class.reltuples`, which is\n * updated by VACUUM/ANALYZE. Returns 0 if the table is not found or\n * statistics are not yet available (e.g., freshly created table).\n *\n * @param db - Drizzle Postgres database instance\n * @param tableName - The Postgres table name (without schema prefix)\n * @returns Estimated row count (non-negative integer)\n */\nexport async function estimateRowCount(db: PostgresJsDatabase, tableName: string): Promise<number> {\n const result = await db.execute(\n sql`SELECT reltuples::bigint AS estimate FROM pg_class WHERE relname = ${tableName}`,\n )\n\n const rows = Array.isArray(result) ? result : ((result as { rows?: unknown[] }).rows ?? [])\n const row = rows[0] as { estimate?: string | number } | undefined\n const estimate = Number(row?.estimate ?? 0)\n\n // reltuples can be -1 for tables that have never been analyzed\n return estimate > 0 ? estimate : 0\n}\n","/**\n * Cursor-based (keyset) pagination utilities.\n *\n * Cursor pagination avoids the performance cliff of OFFSET at scale (1M+ rows).\n * Instead of `OFFSET N`, it uses a WHERE condition:\n * `WHERE (sortField < lastValue) OR (sortField = lastValue AND id < lastId)`\n * which Postgres can serve from an index in constant time.\n *\n * The cursor is opaque to the client — base64-encoded JSON.\n *\n * Security:\n * - `field` must be whitelisted against the entity's actual fields\n * - `id` must be a valid UUID\n * - `value` is parameterized (never interpolated into SQL)\n * - Malformed cursors return null (caller returns 400)\n */\n\nimport { and, eq, gt, lt, or, type SQL } from 'drizzle-orm'\nimport type { PgTableWithColumns } from 'drizzle-orm/pg-core'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Cursor input for keyset pagination. */\nexport interface CursorInput {\n /** Sort field name (e.g. 'createdAt'). Must be a real column on the entity. */\n field: string\n /** Last seen value of the sort field. */\n value: string | number\n /** Sort direction — must match the ORDER BY direction. */\n direction: 'asc' | 'desc'\n /** Tie-breaker: last seen entity ID. Required for non-unique sort fields. */\n id?: string\n}\n\n/** Decoded cursor (internal, after validation). */\ninterface DecodedCursor {\n field: string\n value: string | number\n direction: 'asc' | 'desc'\n id?: string\n}\n\n// ---------------------------------------------------------------------------\n// UUID validation (same format used throughout the toolkit)\n// ---------------------------------------------------------------------------\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\n// ---------------------------------------------------------------------------\n// Encode / decode\n// ---------------------------------------------------------------------------\n\n/**\n * Encode a cursor for API transport (base64url).\n * Built from the last item in a result set.\n */\nexport function encodeCursor(\n item: Record<string, unknown>,\n sortField: string,\n direction: 'asc' | 'desc',\n): string {\n const payload: CursorInput = {\n field: sortField,\n value: item[sortField] as string | number,\n direction,\n id: item.id as string | undefined,\n }\n return btoa(JSON.stringify(payload))\n}\n\n/**\n * Decode and validate a cursor string from query params.\n * Returns null if the cursor is malformed, tampered, or invalid.\n *\n * Security: the `field` value is NOT validated here — the caller must\n * whitelist it against the entity's actual columns.\n */\nexport function decodeCursor(encoded: string): DecodedCursor | null {\n try {\n const json = atob(encoded)\n const parsed: unknown = JSON.parse(json)\n\n if (typeof parsed !== 'object' || parsed === null) return null\n const obj = parsed as Record<string, unknown>\n\n // Validate field\n if (typeof obj.field !== 'string' || !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(obj.field)) {\n return null\n }\n\n // Validate value (string or number)\n if (typeof obj.value !== 'string' && typeof obj.value !== 'number') {\n return null\n }\n\n // Validate direction\n if (obj.direction !== 'asc' && obj.direction !== 'desc') {\n return null\n }\n\n // Validate id (optional, must be UUID if present)\n if (obj.id !== undefined) {\n if (typeof obj.id !== 'string' || !UUID_RE.test(obj.id)) {\n return null\n }\n }\n\n return {\n field: obj.field,\n value: obj.value,\n direction: obj.direction,\n id: obj.id as string | undefined,\n }\n } catch {\n return null\n }\n}\n\n// ---------------------------------------------------------------------------\n// SQL condition builder\n// ---------------------------------------------------------------------------\n\n/**\n * Build the keyset WHERE condition from a decoded cursor.\n *\n * For DESC: `WHERE (field < value) OR (field = value AND id < cursorId)`\n * For ASC: `WHERE (field > value) OR (field = value AND id > cursorId)`\n *\n * The caller must verify that `cursor.field` exists on the table before calling.\n *\n * @param table - Drizzle table with columns\n * @param cursor - Decoded and validated cursor\n * @returns SQL condition, or null if the field doesn't exist on the table\n */\nexport function buildCursorCondition(\n // biome-ignore lint/suspicious/noExplicitAny: dynamic table columns require PgTableWithColumns<any> for property access\n table: PgTableWithColumns<any>,\n cursor: DecodedCursor,\n): SQL | null {\n const column = table[cursor.field]\n if (!column) return null\n\n const isDesc = cursor.direction === 'desc'\n const compare = isDesc ? lt : gt\n\n // Primary condition: sort field passes the cursor value\n const fieldCondition = compare(column, cursor.value)\n\n // Without tie-breaker ID, use simple comparison\n if (!cursor.id) {\n return fieldCondition\n }\n\n // With tie-breaker: (field < value) OR (field = value AND id < cursorId)\n const idColumn = table.id\n if (!idColumn) return fieldCondition\n\n const idCondition = compare(idColumn, cursor.id)\n return or(fieldCondition, and(eq(column, cursor.value), idCondition))!\n}\n","/**\n * Entity definition API\n * The core function for defining entities with full type inference.\n *\n * The generic parameters are inferred from the call site:\n * - F is inferred from `definition.fields`\n * - B is inferred from `definition.behaviors` (as a tuple)\n *\n * The returned Entity carries the complete field map:\n * { id: IdField } & BehaviorFields & UserFields\n */\n\nimport type { EntityAdminConfig } from './admin-config.js'\nimport type { Behavior } from './behaviors/types.js'\nimport type { FieldConfig, IdField } from './fields/base.js'\nimport { field } from './fields/builders.js'\n\n/**\n * Entity definition input (without behaviors — behaviors are typed separately\n * on the `defineEntity` function to enable tuple inference).\n *\n * @typeParam F - The literal field map. Inferred automatically from the call site.\n */\nexport interface EntityDefinition<\n F extends Record<string, FieldConfig> = Record<string, FieldConfig>,\n> {\n name: string\n kind?: 'collection' | 'singleton'\n fields: F\n scope?: 'global' | 'team' | 'user'\n access?: {\n view?: string\n create?: string\n update?: string\n delete?: string\n }\n /** Admin UI configuration — controls sidebar, list, and form display */\n admin?: EntityAdminConfig\n}\n\n/**\n * Full input for defineEntity (fields + behaviors + other config).\n * Behaviors are typed as a tuple `B` for type extraction.\n */\nexport type EntityInput<\n F extends Record<string, FieldConfig> = Record<string, FieldConfig>,\n B extends Behavior[] = Behavior[],\n> = EntityDefinition<F> & { behaviors?: B }\n\n/**\n * A fully resolved entity with merged behavior fields.\n * @typeParam AllFields - The complete field map (id + behaviors + user fields).\n */\nexport interface Entity<\n AllFields extends Record<string, FieldConfig> = Record<string, FieldConfig>,\n> {\n name: string\n kind?: 'collection' | 'singleton'\n fields: Record<string, FieldConfig>\n behaviors?: Behavior[]\n scope?: 'global' | 'team' | 'user'\n access?: {\n view?: string\n create?: string\n update?: string\n delete?: string\n }\n /** Admin UI configuration — controls sidebar, list, and form display */\n admin?: EntityAdminConfig\n allFields: AllFields\n hooks: Behavior['hooks']\n}\n\n/**\n * Extract and intersect behavior field types from a behaviors tuple.\n * Walks the tuple recursively (depth bounded by number of behaviors, max ~5).\n */\ntype ExtractBehaviorFields<B extends Behavior[]> = B extends [\n Behavior<infer F1>,\n ...infer Rest extends Behavior[],\n]\n ? F1 & ExtractBehaviorFields<Rest>\n : // biome-ignore lint/complexity/noBannedTypes: empty object is correct for base case of intersection\n {}\n\n/**\n * Define an entity with full type inference.\n *\n * @example\n * const Article = defineEntity({\n * name: 'article',\n * fields: {\n * title: field.text({ required: true }),\n * featured: field.boolean(),\n * },\n * behaviors: [publishable(), auditable()],\n * })\n *\n * type ArticleDTO = InferEntity<typeof Article>\n * // { id: string; title: string; featured?: boolean | null; status?: ...; createdAt?: ...; }\n */\nexport function defineEntity<\n F extends Record<string, FieldConfig>,\n const B extends Behavior[] = [],\n>(\n definition: EntityDefinition<F> & { behaviors?: B },\n): Entity<{ id: IdField } & ExtractBehaviorFields<B> & F> {\n // Merge behavior fields into main fields\n const behaviorFields: Record<string, FieldConfig> = {}\n const hooks: NonNullable<Behavior['hooks']> = {}\n\n for (const behavior of definition.behaviors || []) {\n // Merge fields from behavior\n if (behavior.fields) {\n for (const [fieldName, fieldConfig] of Object.entries(behavior.fields)) {\n if (behaviorFields[fieldName]) {\n console.warn(\n `Field '${fieldName}' from behavior '${behavior.name}' conflicts with existing field. Skipping.`,\n )\n continue\n }\n behaviorFields[fieldName] = fieldConfig\n }\n }\n\n // Merge hooks from behavior\n if (behavior.hooks) {\n for (const [hookName, hookFn] of Object.entries(behavior.hooks)) {\n const typedHookName = hookName as keyof NonNullable<Behavior['hooks']>\n\n if (hookFn) {\n const existingHook = hooks[typedHookName]\n\n if (existingHook) {\n // Chain hooks: execute existing first, then new one\n const previousHook = existingHook as (...args: unknown[]) => Promise<unknown>\n const currentHook = hookFn as (...args: unknown[]) => Promise<unknown>\n\n const chainedHook = async (...args: unknown[]) => {\n const result = await previousHook(...args)\n if (result !== undefined) {\n // Hook returned modified data — replace last arg (the data param),\n // keep leading args (e.g. id) intact for hooks like beforeUpdate(id, data)\n const nextArgs = [...args]\n nextArgs[nextArgs.length - 1] = result\n return await currentHook(...nextArgs)\n }\n return await currentHook(...args)\n }\n // biome-ignore lint/suspicious/noExplicitAny: dynamic dispatch over heterogeneous hook signatures\n hooks[typedHookName] = chainedHook as any\n } else {\n // biome-ignore lint/suspicious/noExplicitAny: dynamic dispatch over heterogeneous hook signatures\n hooks[typedHookName] = hookFn as any\n }\n }\n }\n }\n }\n\n // Build complete field set\n // Order: id (always first) → behavior fields → user-defined fields\n const allFields: Record<string, FieldConfig> = {\n id: field.id(), // Every entity gets an ID\n ...behaviorFields,\n ...definition.fields,\n }\n\n // Auto-infer translatable slugs: if a slug field's source field is translatable,\n // the slug should be translatable too (each locale gets its own URL-safe slug).\n for (const [, fieldConfig] of Object.entries(allFields)) {\n if (\n fieldConfig.type === 'slug' &&\n !fieldConfig.translatable &&\n allFields[fieldConfig.from]?.translatable\n ) {\n fieldConfig.translatable = true\n }\n }\n\n // The cast through `unknown` is safe: runtime merge order (id + behaviors + user fields)\n // exactly mirrors the type-level intersection. TypeScript cannot verify imperative\n // Object.entries() loops produce the same result as a type-level intersection,\n // so we cast at this single auditable boundary.\n return {\n ...definition,\n allFields,\n hooks,\n } as unknown as Entity<{ id: IdField } & ExtractBehaviorFields<B> & F>\n}\n","/**\n * Error thrown when attempting to delete an entity that is still referenced.\n */\n\nimport type { EntityUsage } from './find-usages.js'\n\nexport class ReferencedEntityError extends Error {\n public readonly entityName: string\n public readonly entityId: string\n public readonly usages: EntityUsage[]\n\n constructor(entityName: string, entityId: string, usages: EntityUsage[]) {\n const count = usages.length\n super(\n `Cannot delete ${entityName} '${entityId}': referenced by ${count} other entit${count === 1 ? 'y' : 'ies'}`,\n )\n this.name = 'ReferencedEntityError'\n this.entityName = entityName\n this.entityId = entityId\n this.usages = usages\n }\n}\n","/**\n * entity_refs — Universal reference tracking table.\n *\n * Every reference between entities (field.media(), field.reference(), block media fields)\n * gets a row here at write time. This enables:\n * - Instant \"where is this used?\" queries (one indexed lookup)\n * - Universal delete protection (can't delete referenced entities)\n * - Correct results (schema-aware, no LIKE text search)\n */\n\nimport { index, pgTable, unique, uuid, varchar } from 'drizzle-orm/pg-core'\n\nexport const entityRefs = pgTable(\n 'entity_refs',\n {\n sourceEntity: varchar('source_entity', { length: 100 }).notNull(),\n sourceId: uuid('source_id').notNull(),\n sourceField: varchar('source_field', { length: 100 }).notNull(),\n targetEntity: varchar('target_entity', { length: 100 }).notNull(),\n targetId: uuid('target_id').notNull(),\n },\n (t) => [\n unique('uq_entity_refs').on(\n t.sourceEntity,\n t.sourceId,\n t.sourceField,\n t.targetEntity,\n t.targetId,\n ),\n index('idx_entity_refs_target').on(t.targetEntity, t.targetId),\n index('idx_entity_refs_source').on(t.sourceEntity, t.sourceId),\n ],\n)\n","/**\n * Schema generator\n * Converts entity definitions to Drizzle schemas.\n * Every field gets its own Postgres column — no JSONB blobs.\n */\n\nimport type { PgColumnBuilderBase, PgTable } from 'drizzle-orm/pg-core'\nimport {\n boolean,\n doublePrecision,\n index,\n integer,\n jsonb,\n pgTable,\n text,\n timestamp,\n unique,\n uuid,\n varchar,\n} from 'drizzle-orm/pg-core'\nimport type { Entity } from './define-entity.js'\nimport type { FieldConfig } from './fields/base.js'\nimport { entityRefs } from './refs/schema.js'\n\n// biome-ignore lint/suspicious/noExplicitAny: PgTable<any> is the drizzle convention for parametric tables\ntype AnyTable = PgTable<any>\n\n/**\n * Convert a field config to a Drizzle column.\n *\n * @param nullable - When true, skips notNull and default constraints.\n * Used for translation table columns (translations are partial overrides).\n */\nexport function fieldToColumn(\n fieldName: string,\n fieldConfig: FieldConfig,\n options?: { nullable?: boolean },\n): PgColumnBuilderBase {\n const nullable = options?.nullable ?? false\n\n switch (fieldConfig.type) {\n case 'id':\n return uuid(fieldName).primaryKey().defaultRandom()\n\n case 'text':\n if (fieldConfig.maxLength && fieldConfig.maxLength <= 255) {\n let column = varchar(fieldName, { length: fieldConfig.maxLength })\n if (fieldConfig.unique) column = column.unique()\n if (!nullable && fieldConfig.required) column = column.notNull()\n if (!nullable && fieldConfig.default !== undefined)\n column = column.default(fieldConfig.default as string)\n return column\n } else {\n let column = text(fieldName)\n if (fieldConfig.unique) column = column.unique()\n if (!nullable && fieldConfig.required) column = column.notNull()\n if (!nullable && fieldConfig.default !== undefined)\n column = column.default(fieldConfig.default as string)\n return column\n }\n\n case 'number': {\n let numColumn = fieldConfig.integer ? integer(fieldName) : doublePrecision(fieldName)\n if (!nullable && fieldConfig.required) numColumn = numColumn.notNull()\n if (!nullable && fieldConfig.default !== undefined)\n numColumn = numColumn.default(fieldConfig.default as number)\n return numColumn\n }\n\n case 'boolean': {\n let boolColumn = boolean(fieldName)\n if (!nullable && fieldConfig.required) boolColumn = boolColumn.notNull()\n if (!nullable) {\n const boolDefault =\n fieldConfig.default !== undefined ? (fieldConfig.default as boolean) : false\n boolColumn = boolColumn.default(boolDefault)\n }\n return boolColumn\n }\n\n case 'date': {\n let dateColumn = timestamp(fieldName, { withTimezone: true })\n if (!nullable && fieldConfig.required) dateColumn = dateColumn.notNull()\n if (!nullable && fieldConfig.default !== undefined)\n dateColumn = dateColumn.default(fieldConfig.default as Date)\n return dateColumn\n }\n\n case 'select': {\n let selectColumn = varchar(fieldName, { length: 100 })\n if (!nullable && fieldConfig.required) selectColumn = selectColumn.notNull()\n if (!nullable && fieldConfig.default !== undefined)\n selectColumn = selectColumn.default(fieldConfig.default as string)\n return selectColumn\n }\n\n case 'reference': {\n if (fieldConfig.cardinality === 'many') {\n return uuid(fieldName).array()\n }\n let refColumn = uuid(fieldName)\n if (!nullable && fieldConfig.required) refColumn = refColumn.notNull()\n return refColumn\n }\n\n case 'media': {\n let mediaColumn = uuid(fieldName)\n if (!nullable && fieldConfig.required) mediaColumn = mediaColumn.notNull()\n return mediaColumn\n }\n\n case 'slug': {\n let slugColumn = varchar(fieldName, { length: 255 })\n // For translation tables (nullable=true), skip per-column unique —\n // translatable slugs use composite UNIQUE(slug, locale) at table level instead.\n if (fieldConfig.unique && !nullable) slugColumn = slugColumn.unique()\n if (!nullable && fieldConfig.required) slugColumn = slugColumn.notNull()\n return slugColumn\n }\n\n case 'richtext': {\n // TipTap HTML strings stored as text\n let rtColumn = text(fieldName)\n if (!nullable && fieldConfig.required) rtColumn = rtColumn.notNull()\n return rtColumn\n }\n\n case 'json':\n return jsonb(fieldName)\n\n default:\n return text(fieldName)\n }\n}\n\n/**\n * Generate a runtime Drizzle schema from an entity definition.\n * Every field becomes its own column — no JSONB.\n */\nexport function generateSchema(entity: Entity) {\n const tableName = entity.name\n const columns: Record<string, PgColumnBuilderBase> = {}\n\n for (const [fieldName, fieldConfig] of Object.entries(entity.allFields)) {\n if (fieldConfig.type === 'blocks') continue // stored in layout table\n columns[fieldName] = fieldToColumn(fieldName, fieldConfig)\n }\n\n if (entity.scope === 'team' || entity.scope === 'user') {\n columns._scopeId = uuid('_scope_id')\n }\n\n // Collect fields that need indexes (skip id/unique — they already have btree indexes)\n const indexedFields = Object.entries(entity.allFields).filter(\n ([_, config]) =>\n config.type !== 'blocks' && config.type !== 'id' && config.indexed && !config.unique,\n )\n\n const isPublishableEntity = entity.behaviors?.some((b) => b.name === 'publishable') ?? false\n\n if (indexedFields.length === 0 && !isPublishableEntity) {\n return pgTable(tableName, columns)\n }\n\n return pgTable(tableName, columns, (table) => {\n // biome-ignore lint/suspicious/noExplicitAny: dynamic table columns from pgTable callback\n const constraints: Record<string, any> = {}\n\n for (const [fieldName] of indexedFields) {\n constraints[`idx_${tableName}_${fieldName}`] = index(`idx_${tableName}_${fieldName}`).on(\n table[fieldName],\n )\n }\n\n // Composite index for publishable entities: status + createdAt (most common list query)\n if (isPublishableEntity && table.status && table.createdAt) {\n constraints[`idx_${tableName}_status_created`] = index(`idx_${tableName}_status_created`).on(\n table.status,\n table.createdAt,\n )\n }\n\n return constraints\n })\n}\n\n/**\n * Generate runtime translation table schema.\n * Each translatable field gets its own nullable column.\n *\n * When `parent` is provided, `entityId` gets a `.references()` FK — used\n * by `lumi migrate` so generated SQL includes `REFERENCES parent(id) ON\n * DELETE CASCADE`. Callers that only need the table shape for query\n * building (core/app.ts, content/plugin.ts) can omit `parent`.\n */\nexport function generateTranslationSchema(entity: Entity, parent?: AnyTable) {\n const translatableFields = Object.entries(entity.allFields).filter(\n ([_, config]) => config.translatable,\n )\n\n if (translatableFields.length === 0) return null\n\n const tableName = `${entity.name}_translations`\n const entityIdCol = parent\n ? uuid('entity_id')\n .notNull()\n // biome-ignore lint/suspicious/noExplicitAny: parent is dynamically typed\n .references(() => (parent as any).id, { onDelete: 'cascade' })\n : uuid('entity_id').notNull()\n const columns: Record<string, PgColumnBuilderBase> = {\n id: uuid('id').primaryKey().defaultRandom(),\n entityId: entityIdCol,\n locale: varchar('locale', { length: 10 }).notNull(),\n }\n\n const hasTranslatableSlug = translatableFields.some(([_, config]) => config.type === 'slug')\n\n for (const [fieldName, fieldConfig] of translatableFields) {\n columns[fieldName] = fieldToColumn(fieldName, fieldConfig, { nullable: true })\n }\n\n return pgTable(tableName, columns, (table) => ({\n uniqueEntityLocale: unique().on(table.entityId, table.locale),\n // Per-locale slug uniqueness: no two entities can share the same slug in the same locale\n ...(hasTranslatableSlug && table.slug\n ? { uniqueSlugLocale: unique().on(table.slug, table.locale) }\n : {}),\n }))\n}\n\n/**\n * Check if an entity has any blocks fields\n */\nexport function hasBlocksFields(entity: Entity): boolean {\n return Object.values(entity.allFields).some((f) => f.type === 'blocks')\n}\n\n/**\n * Generate layout table schema for entities with blocks fields.\n * Stores block instances in a separate table with ordering.\n *\n * When blocks field has localized: false (default), locale is NULL (shared layout).\n * When blocks field has localized: true, locale is set per-locale.\n *\n * `parent` is optional — when provided, emits a `.references()` FK (for\n * migration generation); query-runtime callers can omit it.\n */\nexport function generateLayoutSchema(entity: Entity, parent?: AnyTable) {\n if (!hasBlocksFields(entity)) return null\n\n const tableName = `${entity.name}_layout`\n const entityIdCol = parent\n ? uuid('entity_id')\n .notNull()\n // biome-ignore lint/suspicious/noExplicitAny: parent is dynamically typed\n .references(() => (parent as any).id, { onDelete: 'cascade' })\n : uuid('entity_id').notNull()\n\n return pgTable(\n tableName,\n {\n id: uuid('id').primaryKey().defaultRandom(),\n entityId: entityIdCol,\n fieldName: varchar('field_name', { length: 100 }).notNull(),\n blockType: varchar('block_type', { length: 100 }).notNull(),\n sortOrder: integer('sort_order').notNull().default(0),\n data: jsonb('data'),\n locale: varchar('locale', { length: 10 }),\n },\n (table) => ({\n // Covers: WHERE entity_id IN (...) AND locale IS NULL ORDER BY sort_order\n idx_entity_locale_sort: index(`idx_${tableName}_entity_locale_sort`).on(\n table.entityId,\n table.locale,\n table.sortOrder,\n ),\n }),\n )\n}\n\n/**\n * Check if an entity has the versionable behavior\n */\nexport function isVersionable(entity: Entity): boolean {\n return entity.behaviors?.some((b) => b.name === 'versionable') ?? false\n}\n\n/**\n * Check if an entity needs a per-locale publish status table.\n * Requires both publishable() behavior AND at least one translatable field.\n */\nexport function needsLocaleStatus(entity: Entity): boolean {\n const isPublishable = entity.behaviors?.some((b) => b.name === 'publishable') ?? false\n if (!isPublishable) return false\n const allFields = entity.allFields as Record<string, { translatable?: boolean }>\n return Object.values(allFields).some((f) => f.translatable)\n}\n\n/**\n * Check if an entity is publishable (has publishable() behavior).\n */\nexport function isPublishable(entity: Entity): boolean {\n return entity.behaviors?.some((b) => b.name === 'publishable') ?? false\n}\n\n// ---------------------------------------------------------------------------\n// Runtime generators for infrastructure tables attached to an entity.\n//\n// Each one takes the parent entity's runtime `pgTable` so the\n// `.references()` FK is wired. These replace the old `generate*Code()`\n// string helpers that produced source lines to be concatenated into\n// `generated/schema.ts`.\n// ---------------------------------------------------------------------------\n\n/** Per-locale publish status table for publishable + translatable entities. */\nexport function generateLocaleStatusSchema(entity: Entity, parent: AnyTable) {\n const tableName = `${entity.name}_locale_status`\n return pgTable(\n tableName,\n {\n id: uuid('id').primaryKey().defaultRandom(),\n entityId: uuid('entity_id')\n .notNull()\n // biome-ignore lint/suspicious/noExplicitAny: parent is dynamically typed\n .references(() => (parent as any).id, { onDelete: 'cascade' }),\n locale: varchar('locale', { length: 10 }).notNull(),\n status: varchar('status', { length: 20 }).notNull().default('draft'),\n publishedAt: timestamp('published_at', { withTimezone: true }),\n },\n (table) => ({\n uniqueEntityLocale: unique().on(table.entityId, table.locale),\n }),\n )\n}\n\n/** Drafts overlay table for publishable entities. */\nexport function generateDraftsSchema(entity: Entity, parent: AnyTable) {\n const tableName = `${entity.name}_drafts`\n return pgTable(\n tableName,\n {\n id: uuid('id').primaryKey().defaultRandom(),\n entityId: uuid('entity_id')\n .notNull()\n // biome-ignore lint/suspicious/noExplicitAny: parent is dynamically typed\n .references(() => (parent as any).id, { onDelete: 'cascade' }),\n locale: varchar('locale', { length: 10 }).notNull().default('_'),\n data: jsonb('data').notNull(),\n createdBy: varchar('created_by', { length: 255 }).notNull(),\n createdByName: varchar('created_by_name', { length: 255 }),\n createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),\n },\n (table) => ({\n uniqueEntityLocale: unique().on(table.entityId, table.locale),\n }),\n )\n}\n\n/** Versions history table for versionable entities. */\nexport function generateVersionsSchema(entity: Entity, parent: AnyTable) {\n const tableName = `${entity.name}_versions`\n return pgTable(\n tableName,\n {\n id: uuid('id').primaryKey().defaultRandom(),\n entityId: uuid('entity_id')\n .notNull()\n // biome-ignore lint/suspicious/noExplicitAny: parent is dynamically typed\n .references(() => (parent as any).id, { onDelete: 'cascade' }),\n version: integer('version').notNull(),\n locale: varchar('locale', { length: 10 }).notNull().default('_'),\n data: jsonb('data').notNull(),\n delta: jsonb('delta'),\n status: varchar('status', { length: 20 }),\n createdBy: varchar('created_by', { length: 255 }),\n createdByName: varchar('created_by_name', { length: 255 }),\n createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),\n isAutosave: boolean('is_autosave').notNull().default(false),\n },\n (table) => ({\n uniqueEntityVersionLocale: unique().on(table.entityId, table.version, table.locale),\n }),\n )\n}\n\n/**\n * Shared content locks table — one per project, independent of any entity.\n * Included exactly once in `buildRuntimeSchema()` when any entity is publishable.\n */\nexport function generateContentLocksSchema() {\n return pgTable(\n 'toolkit_content_locks',\n {\n id: uuid('id').primaryKey().defaultRandom(),\n entityType: varchar('entity_type', { length: 100 }).notNull(),\n entityId: varchar('entity_id', { length: 255 }).notNull(),\n locale: varchar('locale', { length: 10 }).notNull().default('_'),\n lockedBy: varchar('locked_by', { length: 255 }).notNull(),\n lockedByName: varchar('locked_by_name', { length: 255 }),\n lockedAt: timestamp('locked_at', { withTimezone: true }).notNull().defaultNow(),\n expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),\n },\n (table) => ({\n uniqueEntityLock: unique().on(table.entityType, table.entityId, table.locale),\n }),\n )\n}\n\n/**\n * Check if an entity has blocks fields with translatable block content (non-localized mode).\n */\nexport function hasTranslatableBlocks(entity: Entity): boolean {\n const allFields = entity.allFields as Record<\n string,\n {\n type: string\n localized?: boolean\n blocks?: Array<{ fields: Record<string, { translatable?: boolean }> }>\n }\n >\n return Object.values(allFields).some((f) => {\n if (f.type !== 'blocks') return false\n if (f.localized) return false\n return f.blocks?.some((block) => Object.values(block.fields).some((bf) => bf.translatable))\n })\n}\n\n/**\n * Generate layout translation table for non-localized blocks with translatable fields.\n *\n * `layoutParent` is optional — when provided, emits a `.references()` FK\n * pointing at the corresponding `{entity}_layout` table (for migration\n * generation).\n */\nexport function generateLayoutTranslationSchema(entity: Entity, layoutParent?: AnyTable) {\n const blocksFields = Object.values(entity.allFields).filter(\n (f) => f.type === 'blocks' && !('localized' in f && f.localized),\n )\n\n if (blocksFields.length === 0) return null\n\n const hasTranslatableBlockFields = blocksFields.some((bf) => {\n if (bf.type !== 'blocks') return false\n return bf.blocks.some((block) => Object.values(block.fields).some((f) => f.translatable))\n })\n\n if (!hasTranslatableBlockFields) return null\n\n const tableName = `${entity.name}_layout_translations`\n const layoutIdCol = layoutParent\n ? uuid('layout_id')\n .notNull()\n // biome-ignore lint/suspicious/noExplicitAny: parent is dynamically typed\n .references(() => (layoutParent as any).id, { onDelete: 'cascade' })\n : uuid('layout_id').notNull()\n\n return pgTable(\n tableName,\n {\n id: uuid('id').primaryKey().defaultRandom(),\n layoutId: layoutIdCol,\n locale: varchar('locale', { length: 10 }).notNull(),\n fields: jsonb('fields').notNull(),\n },\n (table) => ({\n uniqueLayoutLocale: unique().on(table.layoutId, table.locale),\n }),\n )\n}\n\n/**\n * Build the full runtime schema map for a list of entities.\n *\n * Returns a `Record<string, PgTable>` suitable for feeding into\n * `drizzle-kit/api`'s `generateDrizzleJson()`. Includes every table\n * that would have been emitted into `generated/schema.ts` by the old\n * codegen pipeline: main entity, translations, layout, layout\n * translations, versions, drafts, locale status, and the shared\n * content locks table.\n *\n * This is the single entry point used by `lumi migrate` — plugin\n * internal tables are added separately by reading each plugin's\n * `tables` field.\n */\nexport function buildEntitySchemaMap(entities: Entity[]): Record<string, AnyTable> {\n const schema: Record<string, AnyTable> = {}\n let hasAnyPublishable = false\n\n for (const entity of entities) {\n const main = generateSchema(entity)\n schema[entity.name] = main\n\n const translations = generateTranslationSchema(entity, main)\n if (translations) schema[`${entity.name}_translations`] = translations\n\n if (hasBlocksFields(entity)) {\n const layout = generateLayoutSchema(entity, main)\n if (layout) {\n schema[`${entity.name}_layout`] = layout\n const layoutTrans = generateLayoutTranslationSchema(entity, layout)\n if (layoutTrans) schema[`${entity.name}_layout_translations`] = layoutTrans\n }\n }\n\n if (isVersionable(entity)) {\n schema[`${entity.name}_versions`] = generateVersionsSchema(entity, main)\n }\n if (needsLocaleStatus(entity)) {\n schema[`${entity.name}_locale_status`] = generateLocaleStatusSchema(entity, main)\n }\n if (isPublishable(entity)) {\n schema[`${entity.name}_drafts`] = generateDraftsSchema(entity, main)\n hasAnyPublishable = true\n }\n }\n\n if (hasAnyPublishable) {\n schema.toolkit_content_locks = generateContentLocksSchema()\n }\n\n // Universal reference tracking table — used by AdminClient.syncRefs()\n // for delete protection and cross-entity usage queries.\n schema.entity_refs = entityRefs\n\n return schema\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@murumets-ee/entity",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"license": "Elastic-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"drizzle-orm": "^0.45.1",
|
|
29
29
|
"zod": "^3.24.1",
|
|
30
30
|
"server-only": "^0.0.1",
|
|
31
|
-
"@murumets-ee/db": "0.
|
|
31
|
+
"@murumets-ee/db": "0.2.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"tsdown": "^0.21.7",
|