@ghentcdh/crouton-api 0.0.1-alpha.51 → 0.0.1-alpha.53

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.cjs CHANGED
@@ -672,228 +672,105 @@ var init_table_utils = __esm({
672
672
  }
673
673
  });
674
674
 
675
- // ../crouton-core/src/lib/data-source/DataSourceSchema.ts
676
- var import_zod7, DataSourceShape, transformDataSource, DataSourceSchema;
677
- var init_DataSourceSchema = __esm({
678
- "../crouton-core/src/lib/data-source/DataSourceSchema.ts"() {
675
+ // ../crouton-core/src/lib/compile/action.types.ts
676
+ var import_zod7, ActionMetadataSchema, ResourceLinkActionSchema, ResourceRowProcedureActionSchema, ResourceTableProcedureActionSchema, ResourceRowActionSchema, ResourceTableActionSchema;
677
+ var init_action_types = __esm({
678
+ "../crouton-core/src/lib/compile/action.types.ts"() {
679
679
  "use strict";
680
680
  init_cjs_shims();
681
- import_zod7 = __toESM(require("zod"), 1);
682
- DataSourceShape = import_zod7.default.object({
683
- /** Datasource name (folder + `name` in data-source.json). */
684
- name: import_zod7.default.string(),
685
- /**
686
- * Env var holding the connection URL. Required for Prisma adapters; optional
687
- * for custom adapters whose connection config may differ (secrets file, SDK
688
- * key, etc.).
689
- */
690
- urlEnv: import_zod7.default.string().optional(),
691
- /** Import path for this datasource's generated Zod types (for resource `schema.ts`). */
692
- generatedTypesImport: import_zod7.default.string().optional(),
693
- /** Datasource type tag. Default `postgres`. */
694
- type: import_zod7.default.string().default("postgres"),
695
- /** Mark this as the default datasource. Default `false`. */
696
- default: import_zod7.default.boolean().default(false),
697
- /**
698
- * Adapter kind. `"prisma"` (default) expects `index.ts` to default-export a
699
- * `PrismaClient`; `"custom"` expects it to default-export a `DataSourceAdapter`.
700
- */
701
- adapter: import_zod7.default.enum([
702
- "prisma",
703
- "custom"
704
- ]).default("prisma"),
705
- /** Prisma schema path, relative to project root. Default `prisma/<name>/schema.prisma`. */
706
- prismaSchema: import_zod7.default.string().optional(),
707
- /** Prisma config path, relative to project root. Default `prisma/<name>/prisma.config.ts`. */
708
- prismaConfig: import_zod7.default.string().optional(),
709
- /** zod-prisma-types output dir, relative to project root. Default `generated/<name>/src`. */
710
- zodOutput: import_zod7.default.string().optional(),
711
- /** Prisma client output dir, relative to project root. Default `generated/<name>/client`. */
712
- clientOutput: import_zod7.default.string().optional()
681
+ import_zod7 = require("zod");
682
+ ActionMetadataSchema = import_zod7.z.object({
683
+ id: import_zod7.z.string(),
684
+ label: import_zod7.z.string().optional(),
685
+ icon: import_zod7.z.string().optional(),
686
+ tooltip: import_zod7.z.string().optional(),
687
+ condition: import_zod7.z.custom().optional()
713
688
  });
714
- transformDataSource = /* @__PURE__ */ __name((data) => {
715
- const name = data.name ?? "name";
716
- return {
717
- ...data,
718
- generatedTypesImport: data.generatedTypesImport ?? `@your-scope/generated/${name}`,
719
- prismaSchema: data.prismaSchema ?? `prisma/${name}/schema.prisma`,
720
- prismaConfig: data.prismaConfig ?? `prisma/${name}/prisma.config.ts`,
721
- zodOutput: data.zodOutput ?? `generated/${name}/src`,
722
- clientOutput: data.clientOutput ?? `generated/${name}/client`
723
- };
724
- }, "transformDataSource");
725
- DataSourceSchema = DataSourceShape.transform(transformDataSource);
726
- }
727
- });
728
-
729
- // ../crouton-core/src/lib/data-source/Security.schema.ts
730
- var import_zod8, SecuritySchema;
731
- var init_Security_schema = __esm({
732
- "../crouton-core/src/lib/data-source/Security.schema.ts"() {
733
- "use strict";
734
- init_cjs_shims();
735
- import_zod8 = require("zod");
736
- SecuritySchema = import_zod8.z.union([
737
- import_zod8.z.object({
738
- public: import_zod8.z.literal(true)
739
- }),
740
- import_zod8.z.object({
741
- guard: import_zod8.z.union([
742
- import_zod8.z.string(),
743
- import_zod8.z.array(import_zod8.z.string()).min(1)
744
- ])
745
- })
746
- ]);
747
- }
748
- });
749
-
750
- // ../crouton-core/src/lib/data-source/Operations.schema.ts
751
- var import_zod9, OpEntry, BoolOrUpsertSchema, JsonOperationsSchema, buildSubResourceOperations;
752
- var init_Operations_schema = __esm({
753
- "../crouton-core/src/lib/data-source/Operations.schema.ts"() {
754
- "use strict";
755
- init_cjs_shims();
756
- import_zod9 = require("zod");
757
- init_Security_schema();
758
- OpEntry = import_zod9.z.union([
759
- import_zod9.z.boolean(),
760
- import_zod9.z.object({
761
- security: SecuritySchema.optional()
762
- })
689
+ ResourceLinkActionSchema = ActionMetadataSchema.extend({
690
+ type: import_zod7.z.literal("link"),
691
+ href: import_zod7.z.string()
692
+ });
693
+ ResourceRowProcedureActionSchema = ActionMetadataSchema.extend({
694
+ type: import_zod7.z.literal("procedure").optional(),
695
+ method: import_zod7.z.string().optional(),
696
+ data: import_zod7.z.record(import_zod7.z.string(), import_zod7.z.unknown()).optional(),
697
+ procedure: import_zod7.z.custom((v) => typeof v === "function")
698
+ });
699
+ ResourceTableProcedureActionSchema = ActionMetadataSchema.extend({
700
+ type: import_zod7.z.literal("procedure").optional(),
701
+ method: import_zod7.z.string().optional(),
702
+ data: import_zod7.z.record(import_zod7.z.string(), import_zod7.z.unknown()).optional(),
703
+ procedure: import_zod7.z.custom((v) => typeof v === "function")
704
+ });
705
+ ResourceRowActionSchema = import_zod7.z.union([
706
+ ResourceRowProcedureActionSchema,
707
+ ResourceLinkActionSchema
763
708
  ]);
764
- BoolOrUpsertSchema = import_zod9.z.union([
765
- import_zod9.z.boolean(),
766
- import_zod9.z.object({
767
- upsertOn: import_zod9.z.union([
768
- import_zod9.z.string(),
769
- import_zod9.z.array(import_zod9.z.string())
770
- ]),
771
- security: SecuritySchema.optional()
772
- })
709
+ ResourceTableActionSchema = import_zod7.z.union([
710
+ ResourceTableProcedureActionSchema,
711
+ ResourceLinkActionSchema
773
712
  ]);
774
- JsonOperationsSchema = import_zod9.z.object({
775
- findAll: OpEntry.default(true),
776
- findOne: OpEntry.default(true),
777
- create: OpEntry.default(true),
778
- update: OpEntry.default(true),
779
- patch: OpEntry.default(true),
780
- upsert: BoolOrUpsertSchema.default(false),
781
- delete: OpEntry.default(true)
782
- });
783
- buildSubResourceOperations = /* @__PURE__ */ __name((ops, baseUri, idField = "id") => {
784
- if (!ops) return {};
785
- const idPlaceholder = `{${idField}}`;
786
- return {
787
- ...ops.findAll && {
788
- findAll: {
789
- uri: baseUri,
790
- method: "get"
791
- }
792
- },
793
- ...ops.findOne && {
794
- findOne: {
795
- uri: `${baseUri}/${idPlaceholder}`,
796
- method: "get"
797
- }
798
- },
799
- ...ops.create && {
800
- create: {
801
- uri: baseUri,
802
- method: "post"
803
- }
804
- },
805
- ...ops.update && {
806
- update: {
807
- uri: `${baseUri}/${idPlaceholder}`,
808
- method: "put"
809
- }
810
- },
811
- ...ops.patch && {
812
- patch: {
813
- uri: `${baseUri}/${idPlaceholder}`,
814
- method: "patch"
815
- }
816
- },
817
- ...ops.delete && {
818
- delete: {
819
- uri: `${baseUri}/${idPlaceholder}`,
820
- method: "delete"
821
- }
822
- }
823
- };
824
- }, "buildSubResourceOperations");
825
- }
826
- });
827
-
828
- // ../crouton-core/src/lib/data-source/index.ts
829
- var init_data_source = __esm({
830
- "../crouton-core/src/lib/data-source/index.ts"() {
831
- "use strict";
832
- init_cjs_shims();
833
- init_DataSourceSchema();
834
- init_Operations_schema();
835
- init_Security_schema();
836
713
  }
837
714
  });
838
715
 
839
716
  // ../crouton-core/src/lib/resource/FieldInput.schema.ts
840
- var import_zod10, RelationType, DetailControlSchema, DetailConfigSchema, RelationFieldInputOptionsSchema, FieldInputSchema, FieldVariantSchema, stripNull, mergeFieldVariant;
717
+ var import_zod8, RelationType, DetailControlSchema, DetailConfigSchema, RelationFieldInputOptionsSchema, FieldInputSchema, FieldVariantSchema, stripNull, mergeFieldVariant;
841
718
  var init_FieldInput_schema = __esm({
842
719
  "../crouton-core/src/lib/resource/FieldInput.schema.ts"() {
843
720
  "use strict";
844
721
  init_cjs_shims();
845
- import_zod10 = require("zod");
846
- RelationType = import_zod10.z.enum([
722
+ import_zod8 = require("zod");
723
+ RelationType = import_zod8.z.enum([
847
724
  "oneToOne",
848
725
  "manyToOne",
849
726
  "oneToMany",
850
727
  "manyToMany"
851
728
  ]);
852
- DetailControlSchema = import_zod10.z.object({
853
- property: import_zod10.z.string(),
854
- type: import_zod10.z.string().optional(),
855
- options: import_zod10.z.record(import_zod10.z.string(), import_zod10.z.unknown()).optional(),
856
- hideLabel: import_zod10.z.boolean().optional(),
857
- width: import_zod10.z.string().optional()
729
+ DetailControlSchema = import_zod8.z.object({
730
+ property: import_zod8.z.string(),
731
+ type: import_zod8.z.string().optional(),
732
+ options: import_zod8.z.record(import_zod8.z.string(), import_zod8.z.unknown()).optional(),
733
+ hideLabel: import_zod8.z.boolean().optional(),
734
+ width: import_zod8.z.string().optional()
858
735
  });
859
- DetailConfigSchema = import_zod10.z.object({
860
- layout: import_zod10.z.enum([
736
+ DetailConfigSchema = import_zod8.z.object({
737
+ layout: import_zod8.z.enum([
861
738
  "collapse",
862
739
  "row"
863
740
  ]),
864
- titleKey: import_zod10.z.string().optional(),
865
- controls: import_zod10.z.array(DetailControlSchema)
741
+ titleKey: import_zod8.z.string().optional(),
742
+ controls: import_zod8.z.array(DetailControlSchema)
866
743
  });
867
- RelationFieldInputOptionsSchema = import_zod10.z.object({
868
- colspan: import_zod10.z.number().optional().default(12),
744
+ RelationFieldInputOptionsSchema = import_zod8.z.object({
745
+ colspan: import_zod8.z.number().optional().default(12),
869
746
  /** Field to sort related records by, e.g. `"title"` or `"author.name"`. */
870
- sort: import_zod10.z.string().optional(),
747
+ sort: import_zod8.z.string().optional(),
871
748
  /** Sort direction. Defaults to `"asc"` when omitted. */
872
- sortDir: import_zod10.z.enum([
749
+ sortDir: import_zod8.z.enum([
873
750
  "asc",
874
751
  "desc"
875
752
  ]).optional(),
876
753
  /** CSS flex direction for the relation control button layout. */
877
- direction: import_zod10.z.string().optional(),
754
+ direction: import_zod8.z.string().optional(),
878
755
  /** Key used as the display label in the relation control. */
879
- displayKey: import_zod10.z.string().optional(),
756
+ displayKey: import_zod8.z.string().optional(),
880
757
  /** Path to the related resource (resolved to a URI at load time). */
881
- resource: import_zod10.z.string().optional()
882
- }).catchall(import_zod10.z.unknown());
883
- FieldInputSchema = import_zod10.z.object({
884
- type: import_zod10.z.string().optional(),
885
- customRender: import_zod10.z.string().optional(),
758
+ resource: import_zod8.z.string().optional()
759
+ }).catchall(import_zod8.z.unknown());
760
+ FieldInputSchema = import_zod8.z.object({
761
+ type: import_zod8.z.string().optional(),
762
+ customRender: import_zod8.z.string().optional(),
886
763
  /**
887
764
  * Render format hint for the frontend (e.g. `"relation"` for sub-resource
888
765
  * relations). When `format` is `"relation"`, `resource` must also be set.
889
766
  */
890
- format: import_zod10.z.string().optional(),
767
+ format: import_zod8.z.string().optional(),
891
768
  /**
892
769
  * Relative path to the child resource definition, e.g. `"./author.resource"`.
893
770
  * Only used when `format` is `"relation"`. Resolved at load time to inject
894
771
  * sub-resource URIs into `options`.
895
772
  */
896
- resource: import_zod10.z.string().optional(),
773
+ resource: import_zod8.z.string().optional(),
897
774
  /**
898
775
  * Cardinality of the relation. Used by the frontend to determine the correct
899
776
  * renderer and behaviour (e.g. single-select vs multi-select).
@@ -902,11 +779,11 @@ var init_FieldInput_schema = __esm({
902
779
  */
903
780
  relationType: RelationType.optional(),
904
781
  /** FK field on the child model pointing back to the parent, e.g. `"workId"`. Defaults to `${parentModel}Id`. */
905
- foreignKey: import_zod10.z.string().optional(),
782
+ foreignKey: import_zod8.z.string().optional(),
906
783
  /** Override the Prisma relation field name when it differs from the column id. */
907
- relation: import_zod10.z.string().optional(),
784
+ relation: import_zod8.z.string().optional(),
908
785
  /** Override the display order in form views. Lower values come first. */
909
- position: import_zod10.z.number().optional(),
786
+ position: import_zod8.z.number().optional(),
910
787
  /**
911
788
  * Value to pre-fill this field with on the create form. Injected into the
912
789
  * generated form view's JSON Schema as `properties[id].default`, which
@@ -914,10 +791,10 @@ var init_FieldInput_schema = __esm({
914
791
  * opening a blank record. Not applicable to `format: "relation"` fields —
915
792
  * relation columns are excluded from the picked data schema entirely.
916
793
  */
917
- defaultValue: import_zod10.z.unknown().optional(),
918
- options: import_zod10.z.union([
794
+ defaultValue: import_zod8.z.unknown().optional(),
795
+ options: import_zod8.z.union([
919
796
  RelationFieldInputOptionsSchema,
920
- import_zod10.z.unknown()
797
+ import_zod8.z.unknown()
921
798
  ]).optional(),
922
799
  /** Nested array detail layout (renders via `detailFixed`). */
923
800
  detail: DetailConfigSchema.optional()
@@ -967,24 +844,24 @@ var init_label_helper = __esm({
967
844
  });
968
845
 
969
846
  // ../crouton-core/src/lib/resource/CalculatedColumn.schema.ts
970
- var import_zod11, CalculatedColumnSchema;
847
+ var import_zod9, CalculatedColumnSchema;
971
848
  var init_CalculatedColumn_schema = __esm({
972
849
  "../crouton-core/src/lib/resource/CalculatedColumn.schema.ts"() {
973
850
  "use strict";
974
851
  init_cjs_shims();
975
- import_zod11 = require("zod");
852
+ import_zod9 = require("zod");
976
853
  init_FieldInput_schema();
977
854
  init_label_helper();
978
- CalculatedColumnSchema = import_zod11.z.object({
855
+ CalculatedColumnSchema = import_zod9.z.object({
979
856
  /** Column identifier used in the response payload and UI schema. */
980
- id: import_zod11.z.string(),
857
+ id: import_zod9.z.string(),
981
858
  /** SQL alias — must match `id`. */
982
- alias: import_zod11.z.string(),
859
+ alias: import_zod9.z.string(),
983
860
  /** Human-readable label shown in the table header. */
984
- label: import_zod11.z.string().optional(),
985
- sqlExpression: import_zod11.z.string(),
861
+ label: import_zod9.z.string().optional(),
862
+ sqlExpression: import_zod9.z.string(),
986
863
  /** JSON schema / cast type for the computed value. Defaults to `"number"`. `"string"` skips CAST. */
987
- type: import_zod11.z.enum([
864
+ type: import_zod9.z.enum([
988
865
  "number",
989
866
  "boolean",
990
867
  "string"
@@ -995,9 +872,9 @@ var init_CalculatedColumn_schema = __esm({
995
872
  * `position: N` places this column before the element currently at index N.
996
873
  * Can also be set via `fieldInput.position` (takes precedence).
997
874
  */
998
- position: import_zod11.z.number().optional(),
999
- hiddenInTable: import_zod11.z.boolean().optional(),
1000
- hiddenInView: import_zod11.z.boolean().optional(),
875
+ position: import_zod9.z.number().optional(),
876
+ hiddenInTable: import_zod9.z.boolean().optional(),
877
+ hiddenInView: import_zod9.z.boolean().optional(),
1001
878
  /**
1002
879
  * Field input options for rendering in form / view schemas.
1003
880
  * Supports `colspan`, `format`, and any other options passed to the Control renderer.
@@ -1009,13 +886,13 @@ var init_CalculatedColumn_schema = __esm({
1009
886
  });
1010
887
 
1011
888
  // ../crouton-core/src/lib/resource/ColumnType.schema.ts
1012
- var import_zod12, ColumnTypeShorthandSchema, JsonSchemaFragmentSchema, ColumnTypeSchema, SHORTHAND_FRAGMENTS, isShorthand, NESTED_SHORTHANDS, normalizeFragment, columnTypeToJsonSchema, columnTypeName, isObjectColumnType, isArrayColumnType;
889
+ var import_zod10, ColumnTypeShorthandSchema, JsonSchemaFragmentSchema, ColumnTypeSchema, SHORTHAND_FRAGMENTS, isShorthand, NESTED_SHORTHANDS, normalizeFragment, columnTypeToJsonSchema, columnTypeName, isObjectColumnType, isArrayColumnType;
1013
890
  var init_ColumnType_schema = __esm({
1014
891
  "../crouton-core/src/lib/resource/ColumnType.schema.ts"() {
1015
892
  "use strict";
1016
893
  init_cjs_shims();
1017
- import_zod12 = require("zod");
1018
- ColumnTypeShorthandSchema = import_zod12.z.enum([
894
+ import_zod10 = require("zod");
895
+ ColumnTypeShorthandSchema = import_zod10.z.enum([
1019
896
  "string",
1020
897
  "number",
1021
898
  "integer",
@@ -1025,32 +902,32 @@ var init_ColumnType_schema = __esm({
1025
902
  "object",
1026
903
  "array"
1027
904
  ]);
1028
- JsonSchemaFragmentSchema = import_zod12.z.lazy(() => import_zod12.z.object({
1029
- type: import_zod12.z.union([
1030
- import_zod12.z.string(),
1031
- import_zod12.z.array(import_zod12.z.string())
905
+ JsonSchemaFragmentSchema = import_zod10.z.lazy(() => import_zod10.z.object({
906
+ type: import_zod10.z.union([
907
+ import_zod10.z.string(),
908
+ import_zod10.z.array(import_zod10.z.string())
1032
909
  ]).optional(),
1033
- format: import_zod12.z.string().optional(),
1034
- enum: import_zod12.z.array(import_zod12.z.unknown()).optional(),
1035
- const: import_zod12.z.unknown().optional(),
1036
- nullable: import_zod12.z.boolean().optional(),
1037
- properties: import_zod12.z.record(import_zod12.z.string(), JsonSchemaFragmentSchema).optional(),
1038
- required: import_zod12.z.array(import_zod12.z.string()).optional(),
910
+ format: import_zod10.z.string().optional(),
911
+ enum: import_zod10.z.array(import_zod10.z.unknown()).optional(),
912
+ const: import_zod10.z.unknown().optional(),
913
+ nullable: import_zod10.z.boolean().optional(),
914
+ properties: import_zod10.z.record(import_zod10.z.string(), JsonSchemaFragmentSchema).optional(),
915
+ required: import_zod10.z.array(import_zod10.z.string()).optional(),
1039
916
  items: JsonSchemaFragmentSchema.optional(),
1040
- additionalProperties: import_zod12.z.union([
1041
- import_zod12.z.boolean(),
917
+ additionalProperties: import_zod10.z.union([
918
+ import_zod10.z.boolean(),
1042
919
  JsonSchemaFragmentSchema
1043
920
  ]).optional(),
1044
- title: import_zod12.z.string().optional(),
1045
- description: import_zod12.z.string().optional(),
1046
- default: import_zod12.z.unknown().optional(),
1047
- minimum: import_zod12.z.number().optional(),
1048
- maximum: import_zod12.z.number().optional(),
1049
- minLength: import_zod12.z.number().optional(),
1050
- maxLength: import_zod12.z.number().optional(),
1051
- pattern: import_zod12.z.string().optional()
1052
- }).catchall(import_zod12.z.unknown()));
1053
- ColumnTypeSchema = import_zod12.z.union([
921
+ title: import_zod10.z.string().optional(),
922
+ description: import_zod10.z.string().optional(),
923
+ default: import_zod10.z.unknown().optional(),
924
+ minimum: import_zod10.z.number().optional(),
925
+ maximum: import_zod10.z.number().optional(),
926
+ minLength: import_zod10.z.number().optional(),
927
+ maxLength: import_zod10.z.number().optional(),
928
+ pattern: import_zod10.z.string().optional()
929
+ }).catchall(import_zod10.z.unknown()));
930
+ ColumnTypeSchema = import_zod10.z.union([
1054
931
  ColumnTypeShorthandSchema,
1055
932
  JsonSchemaFragmentSchema
1056
933
  ]);
@@ -1134,48 +1011,48 @@ var init_ColumnType_schema = __esm({
1134
1011
  });
1135
1012
 
1136
1013
  // ../crouton-core/src/lib/resource/Column.ts
1137
- var import_zod13, WhenConditionSchema, JsonColumnSchema;
1014
+ var import_zod11, WhenConditionSchema, JsonColumnSchema;
1138
1015
  var init_Column = __esm({
1139
1016
  "../crouton-core/src/lib/resource/Column.ts"() {
1140
1017
  "use strict";
1141
1018
  init_cjs_shims();
1142
- import_zod13 = require("zod");
1019
+ import_zod11 = require("zod");
1143
1020
  init_ColumnType_schema();
1144
1021
  init_FieldInput_schema();
1145
- WhenConditionSchema = import_zod13.z.object({
1146
- field: import_zod13.z.string(),
1147
- eq: import_zod13.z.unknown().optional(),
1148
- neq: import_zod13.z.unknown().optional(),
1149
- exists: import_zod13.z.boolean().optional(),
1150
- notExists: import_zod13.z.boolean().optional()
1022
+ WhenConditionSchema = import_zod11.z.object({
1023
+ field: import_zod11.z.string(),
1024
+ eq: import_zod11.z.unknown().optional(),
1025
+ neq: import_zod11.z.unknown().optional(),
1026
+ exists: import_zod11.z.boolean().optional(),
1027
+ notExists: import_zod11.z.boolean().optional()
1151
1028
  });
1152
- JsonColumnSchema = import_zod13.z.object({
1153
- id: import_zod13.z.string(),
1154
- column: import_zod13.z.string().optional(),
1155
- label: import_zod13.z.string().optional(),
1156
- hiddenInTable: import_zod13.z.boolean().default(false),
1157
- hiddenInForm: import_zod13.z.boolean().default(false),
1158
- hiddenInView: import_zod13.z.boolean().default(false),
1159
- sortable: import_zod13.z.boolean().default(false),
1160
- defaultSort: import_zod13.z.boolean().default(false),
1161
- searchable: import_zod13.z.boolean().default(false),
1162
- filterable: import_zod13.z.boolean().default(false),
1163
- createable: import_zod13.z.boolean().default(true),
1164
- updateable: import_zod13.z.boolean().default(true),
1165
- hideLabel: import_zod13.z.boolean().default(false),
1029
+ JsonColumnSchema = import_zod11.z.object({
1030
+ id: import_zod11.z.string(),
1031
+ column: import_zod11.z.string().optional(),
1032
+ label: import_zod11.z.string().optional(),
1033
+ hiddenInTable: import_zod11.z.boolean().default(false),
1034
+ hiddenInForm: import_zod11.z.boolean().default(false),
1035
+ hiddenInView: import_zod11.z.boolean().default(false),
1036
+ sortable: import_zod11.z.boolean().default(false),
1037
+ defaultSort: import_zod11.z.boolean().default(false),
1038
+ searchable: import_zod11.z.boolean().default(false),
1039
+ filterable: import_zod11.z.boolean().default(false),
1040
+ createable: import_zod11.z.boolean().default(true),
1041
+ updateable: import_zod11.z.boolean().default(true),
1042
+ hideLabel: import_zod11.z.boolean().default(false),
1166
1043
  showWhen: WhenConditionSchema.optional(),
1167
1044
  hideWhen: WhenConditionSchema.optional(),
1168
1045
  disabledWhen: WhenConditionSchema.optional(),
1169
- displayKey: import_zod13.z.string().optional(),
1170
- sortId: import_zod13.z.string().optional(),
1046
+ displayKey: import_zod11.z.string().optional(),
1047
+ sortId: import_zod11.z.string().optional(),
1171
1048
  /**
1172
1049
  * Name of a shared enum in the project enum registry (`crouton.enums.json`).
1173
1050
  * At load time the loader injects that enum's `{ value, label }[]` into
1174
1051
  * `fieldInput.options.values`, so columns don't duplicate the option list.
1175
1052
  */
1176
- enum: import_zod13.z.string().optional(),
1177
- idField: import_zod13.z.boolean().default(false),
1178
- showInLookup: import_zod13.z.boolean().default(false),
1053
+ enum: import_zod11.z.string().optional(),
1054
+ idField: import_zod11.z.boolean().default(false),
1055
+ showInLookup: import_zod11.z.boolean().default(false),
1179
1056
  /**
1180
1057
  * Data type of the column, as a shorthand name (`"string"`, `"integer"`, …)
1181
1058
  * or a full JSON Schema fragment:
@@ -1206,12 +1083,12 @@ var init_Column = __esm({
1206
1083
  * Ignored on the id column and on columns that are neither createable nor
1207
1084
  * updateable, since the form cannot supply a value for those.
1208
1085
  */
1209
- required: import_zod13.z.boolean().optional(),
1086
+ required: import_zod11.z.boolean().optional(),
1210
1087
  /**
1211
1088
  * @deprecated Use `type` instead. Retained because it is still consumed by
1212
1089
  * the boolean predicate and the schema-less sub-resource view builder.
1213
1090
  */
1214
- columnType: import_zod13.z.string().default("string"),
1091
+ columnType: import_zod11.z.string().default("string"),
1215
1092
  fieldInput: FieldInputSchema.optional(),
1216
1093
  /**
1217
1094
  * Optional per-context override for the read-only VIEW ui. Same shape as
@@ -1235,34 +1112,34 @@ var init_Column = __esm({
1235
1112
  * Visibility (`hiddenInTable/Form/View`) on this column is inherited by all sub-columns as a
1236
1113
  * default; the referenced resource's own column visibility further restricts it.
1237
1114
  */
1238
- extend: import_zod13.z.string().optional(),
1115
+ extend: import_zod11.z.string().optional(),
1239
1116
  /**
1240
1117
  * Per-sub-column overrides when using `extend`.
1241
1118
  * Key: the virtual column id (`"{extendId}_{refColId}"`) or just the referenced column id.
1242
1119
  * Value: any `JsonColumn` fields to merge over the generated virtual column.
1243
1120
  */
1244
- columns: import_zod13.z.record(import_zod13.z.string(), import_zod13.z.record(import_zod13.z.string(), import_zod13.z.unknown())).optional()
1121
+ columns: import_zod11.z.record(import_zod11.z.string(), import_zod11.z.record(import_zod11.z.string(), import_zod11.z.unknown())).optional()
1245
1122
  });
1246
1123
  }
1247
1124
  });
1248
1125
 
1249
1126
  // ../crouton-core/src/lib/resource/ParentRef.schema.ts
1250
- var import_zod14, ParentRefSchema, resourceControllerPath;
1127
+ var import_zod12, ParentRefSchema, resourceControllerPath;
1251
1128
  var init_ParentRef_schema = __esm({
1252
1129
  "../crouton-core/src/lib/resource/ParentRef.schema.ts"() {
1253
1130
  "use strict";
1254
1131
  init_cjs_shims();
1255
- import_zod14 = require("zod");
1256
- ParentRefSchema = import_zod14.z.object({
1132
+ import_zod12 = require("zod");
1133
+ ParentRefSchema = import_zod12.z.object({
1257
1134
  /** Route segment of the parent, e.g. `"group"`. */
1258
- route: import_zod14.z.string(),
1135
+ route: import_zod12.z.string(),
1259
1136
  /**
1260
1137
  * Name of the path parameter carrying the parent id, e.g. `"groupId"`.
1261
1138
  * Avoid `"id"` — that is the child's own id in `/:id` routes.
1262
1139
  */
1263
- param: import_zod14.z.string().default("parentId"),
1140
+ param: import_zod12.z.string().default("parentId"),
1264
1141
  /** Type of the parent id, used to coerce the path param. Defaults to `'string'`. */
1265
- idType: import_zod14.z.enum([
1142
+ idType: import_zod12.z.enum([
1266
1143
  "string",
1267
1144
  "number"
1268
1145
  ]).optional()
@@ -1272,13 +1149,13 @@ var init_ParentRef_schema = __esm({
1272
1149
  });
1273
1150
 
1274
1151
  // ../crouton-core/src/lib/resource/ResourceKind.ts
1275
- var import_zod15, ResourceKindSchema;
1152
+ var import_zod13, ResourceKindSchema;
1276
1153
  var init_ResourceKind = __esm({
1277
1154
  "../crouton-core/src/lib/resource/ResourceKind.ts"() {
1278
1155
  "use strict";
1279
1156
  init_cjs_shims();
1280
- import_zod15 = require("zod");
1281
- ResourceKindSchema = import_zod15.z.enum([
1157
+ import_zod13 = require("zod");
1158
+ ResourceKindSchema = import_zod13.z.enum([
1282
1159
  "prisma",
1283
1160
  "custom"
1284
1161
  ]).default("prisma");
@@ -1286,42 +1163,42 @@ var init_ResourceKind = __esm({
1286
1163
  });
1287
1164
 
1288
1165
  // ../crouton-core/src/lib/resource/Sidebar.schema.ts
1289
- var import_zod16, SidebarGroupSchema, SidebarSchema;
1166
+ var import_zod14, SidebarGroupSchema, SidebarSchema;
1290
1167
  var init_Sidebar_schema = __esm({
1291
1168
  "../crouton-core/src/lib/resource/Sidebar.schema.ts"() {
1292
1169
  "use strict";
1293
1170
  init_cjs_shims();
1294
- import_zod16 = __toESM(require("zod"), 1);
1295
- SidebarGroupSchema = import_zod16.default.object({
1171
+ import_zod14 = __toESM(require("zod"), 1);
1172
+ SidebarGroupSchema = import_zod14.default.object({
1296
1173
  /** Human-readable heading shown in the sidebar. Defaults to a title-cased version of the slug. */
1297
- label: import_zod16.default.string().optional(),
1174
+ label: import_zod14.default.string().optional(),
1298
1175
  /** Controls the order of this group among top-level sidebar items. */
1299
- position: import_zod16.default.number().optional()
1176
+ position: import_zod14.default.number().optional()
1300
1177
  });
1301
- SidebarSchema = import_zod16.default.object({
1302
- hide: import_zod16.default.boolean().default(false),
1303
- position: import_zod16.default.number().optional(),
1304
- label: import_zod16.default.string().optional(),
1178
+ SidebarSchema = import_zod14.default.object({
1179
+ hide: import_zod14.default.boolean().default(false),
1180
+ position: import_zod14.default.number().optional(),
1181
+ label: import_zod14.default.string().optional(),
1305
1182
  /**
1306
1183
  * Slug of the group this resource belongs to.
1307
1184
  * Must match a key in `sidebarGroups` in `crouton.json`.
1308
1185
  * Resources with the same `group` are nested under a shared collapsible section.
1309
1186
  */
1310
- group: import_zod16.default.string().optional()
1187
+ group: import_zod14.default.string().optional()
1311
1188
  });
1312
1189
  }
1313
1190
  });
1314
1191
 
1315
1192
  // ../crouton-core/src/lib/resource/TableAction.schema.ts
1316
- var import_zod17, ActionConditionSchema, ActionSchema, JsonProcedureActionSchema, JsonLinkActionSchema, transformAction, JsonActionSchema;
1193
+ var import_zod15, ActionConditionSchema, ActionSchema, JsonProcedureActionSchema, JsonLinkActionSchema, transformAction, JsonActionSchema;
1317
1194
  var init_TableAction_schema = __esm({
1318
1195
  "../crouton-core/src/lib/resource/TableAction.schema.ts"() {
1319
1196
  "use strict";
1320
1197
  init_cjs_shims();
1321
- import_zod17 = require("zod");
1322
- ActionConditionSchema = import_zod17.z.object({
1198
+ import_zod15 = require("zod");
1199
+ ActionConditionSchema = import_zod15.z.object({
1323
1200
  /** Row field to evaluate. */
1324
- field: import_zod17.z.string(),
1201
+ field: import_zod15.z.string(),
1325
1202
  /**
1326
1203
  * Comparison operator. Defaults to `"eq"`.
1327
1204
  * - `eq` / `neq` — strict equality
@@ -1329,7 +1206,7 @@ var init_TableAction_schema = __esm({
1329
1206
  * - `exists` — field is not null / undefined / empty string
1330
1207
  * - `notExists` — field is null / undefined / empty string
1331
1208
  */
1332
- op: import_zod17.z.enum([
1209
+ op: import_zod15.z.enum([
1333
1210
  "eq",
1334
1211
  "neq",
1335
1212
  "gt",
@@ -1340,38 +1217,38 @@ var init_TableAction_schema = __esm({
1340
1217
  "notExists"
1341
1218
  ]).default("eq"),
1342
1219
  /** Comparison value. Not required for `exists` / `notExists`. */
1343
- value: import_zod17.z.unknown().optional()
1220
+ value: import_zod15.z.unknown().optional()
1344
1221
  });
1345
- ActionSchema = import_zod17.z.object({
1346
- type: import_zod17.z.string(),
1222
+ ActionSchema = import_zod15.z.object({
1223
+ type: import_zod15.z.string(),
1347
1224
  /** Unique identifier for the action. */
1348
- id: import_zod17.z.string(),
1225
+ id: import_zod15.z.string(),
1349
1226
  /** Human-readable button label. */
1350
- label: import_zod17.z.string(),
1227
+ label: import_zod15.z.string(),
1351
1228
  /** MDI icon name, e.g. `"mdi:open-in-new"`. */
1352
- icon: import_zod17.z.string().optional(),
1229
+ icon: import_zod15.z.string().optional(),
1353
1230
  /** Tooltip text. Falls back to `label` when omitted. */
1354
- tooltip: import_zod17.z.string().optional(),
1231
+ tooltip: import_zod15.z.string().optional(),
1355
1232
  condition: ActionConditionSchema.optional()
1356
1233
  });
1357
1234
  JsonProcedureActionSchema = ActionSchema.extend({
1358
- type: import_zod17.z.literal("procedure").default("procedure"),
1235
+ type: import_zod15.z.literal("procedure").default("procedure"),
1359
1236
  /**
1360
1237
  * Filename (without extension) inside the resource's `actions/` directory
1361
1238
  * that exports the table-action procedure, e.g. `"syncZotero"`.
1362
1239
  */
1363
- procedure: import_zod17.z.string(),
1240
+ procedure: import_zod15.z.string(),
1364
1241
  /** HTTP method for the frontend. Defaults to `"post"`. */
1365
- method: import_zod17.z.string().optional().default("post"),
1242
+ method: import_zod15.z.string().optional().default("post"),
1366
1243
  /** Static query / body params passed to the endpoint. */
1367
- data: import_zod17.z.record(import_zod17.z.string(), import_zod17.z.unknown()).optional()
1244
+ data: import_zod15.z.record(import_zod15.z.string(), import_zod15.z.unknown()).optional()
1368
1245
  });
1369
1246
  JsonLinkActionSchema = ActionSchema.extend({
1370
1247
  /** Optional condition evaluated per row. Button is hidden when the condition is false. */
1371
- type: import_zod17.z.literal("link").default("link"),
1248
+ type: import_zod15.z.literal("link").default("link"),
1372
1249
  /** URL to open. May contain `{env.VAR}` placeholders. */
1373
- href: import_zod17.z.string(),
1374
- blank: import_zod17.z.boolean().optional().default(true)
1250
+ href: import_zod15.z.string(),
1251
+ blank: import_zod15.z.boolean().optional().default(true)
1375
1252
  });
1376
1253
  transformAction = /* @__PURE__ */ __name((action) => {
1377
1254
  const label = action.label;
@@ -1380,7 +1257,7 @@ var init_TableAction_schema = __esm({
1380
1257
  ...action
1381
1258
  };
1382
1259
  }, "transformAction");
1383
- JsonActionSchema = import_zod17.z.union([
1260
+ JsonActionSchema = import_zod15.z.union([
1384
1261
  JsonProcedureActionSchema,
1385
1262
  JsonLinkActionSchema
1386
1263
  ]).transform(transformAction);
@@ -1431,19 +1308,19 @@ var init_extensions = __esm({
1431
1308
  });
1432
1309
 
1433
1310
  // ../crouton-core/src/lib/resource/include.schema.ts
1434
- var import_zod18, JsonIncludeEntrySchema;
1311
+ var import_zod16, JsonIncludeEntrySchema;
1435
1312
  var init_include_schema = __esm({
1436
1313
  "../crouton-core/src/lib/resource/include.schema.ts"() {
1437
1314
  "use strict";
1438
1315
  init_cjs_shims();
1439
- import_zod18 = require("zod");
1440
- JsonIncludeEntrySchema = import_zod18.z.lazy(() => import_zod18.z.union([
1441
- import_zod18.z.string(),
1442
- import_zod18.z.object({
1443
- relation: import_zod18.z.string(),
1444
- include: import_zod18.z.array(JsonIncludeEntrySchema).optional(),
1316
+ import_zod16 = require("zod");
1317
+ JsonIncludeEntrySchema = import_zod16.z.lazy(() => import_zod16.z.union([
1318
+ import_zod16.z.string(),
1319
+ import_zod16.z.object({
1320
+ relation: import_zod16.z.string(),
1321
+ include: import_zod16.z.array(JsonIncludeEntrySchema).optional(),
1445
1322
  /** Prisma-format orderBy clause applied to the included records. */
1446
- orderBy: import_zod18.z.record(import_zod18.z.string(), import_zod18.z.unknown()).optional()
1323
+ orderBy: import_zod16.z.record(import_zod16.z.string(), import_zod16.z.unknown()).optional()
1447
1324
  })
1448
1325
  ]));
1449
1326
  }
@@ -1460,6 +1337,105 @@ var init_version = __esm({
1460
1337
  }
1461
1338
  });
1462
1339
 
1340
+ // ../crouton-core/src/lib/data-source/Security.schema.ts
1341
+ var import_zod17, SecuritySchema;
1342
+ var init_Security_schema = __esm({
1343
+ "../crouton-core/src/lib/data-source/Security.schema.ts"() {
1344
+ "use strict";
1345
+ init_cjs_shims();
1346
+ import_zod17 = require("zod");
1347
+ SecuritySchema = import_zod17.z.union([
1348
+ import_zod17.z.object({
1349
+ public: import_zod17.z.literal(true)
1350
+ }),
1351
+ import_zod17.z.object({
1352
+ guard: import_zod17.z.union([
1353
+ import_zod17.z.string(),
1354
+ import_zod17.z.array(import_zod17.z.string()).min(1)
1355
+ ])
1356
+ })
1357
+ ]);
1358
+ }
1359
+ });
1360
+
1361
+ // ../crouton-core/src/lib/data-source/Operations.schema.ts
1362
+ var import_zod18, OpEntry, BoolOrUpsertSchema, JsonOperationsSchema, buildSubResourceOperations;
1363
+ var init_Operations_schema = __esm({
1364
+ "../crouton-core/src/lib/data-source/Operations.schema.ts"() {
1365
+ "use strict";
1366
+ init_cjs_shims();
1367
+ import_zod18 = require("zod");
1368
+ init_Security_schema();
1369
+ OpEntry = import_zod18.z.union([
1370
+ import_zod18.z.boolean(),
1371
+ import_zod18.z.object({
1372
+ security: SecuritySchema.optional()
1373
+ })
1374
+ ]);
1375
+ BoolOrUpsertSchema = import_zod18.z.union([
1376
+ import_zod18.z.boolean(),
1377
+ import_zod18.z.object({
1378
+ upsertOn: import_zod18.z.union([
1379
+ import_zod18.z.string(),
1380
+ import_zod18.z.array(import_zod18.z.string())
1381
+ ]),
1382
+ security: SecuritySchema.optional()
1383
+ })
1384
+ ]);
1385
+ JsonOperationsSchema = import_zod18.z.object({
1386
+ findAll: OpEntry.default(true),
1387
+ findOne: OpEntry.default(true),
1388
+ create: OpEntry.default(true),
1389
+ update: OpEntry.default(true),
1390
+ patch: OpEntry.default(true),
1391
+ upsert: BoolOrUpsertSchema.default(false),
1392
+ delete: OpEntry.default(true)
1393
+ });
1394
+ buildSubResourceOperations = /* @__PURE__ */ __name((ops, baseUri, idField = "id") => {
1395
+ if (!ops) return {};
1396
+ const idPlaceholder = `{${idField}}`;
1397
+ return {
1398
+ ...ops.findAll && {
1399
+ findAll: {
1400
+ uri: baseUri,
1401
+ method: "get"
1402
+ }
1403
+ },
1404
+ ...ops.findOne && {
1405
+ findOne: {
1406
+ uri: `${baseUri}/${idPlaceholder}`,
1407
+ method: "get"
1408
+ }
1409
+ },
1410
+ ...ops.create && {
1411
+ create: {
1412
+ uri: baseUri,
1413
+ method: "post"
1414
+ }
1415
+ },
1416
+ ...ops.update && {
1417
+ update: {
1418
+ uri: `${baseUri}/${idPlaceholder}`,
1419
+ method: "put"
1420
+ }
1421
+ },
1422
+ ...ops.patch && {
1423
+ patch: {
1424
+ uri: `${baseUri}/${idPlaceholder}`,
1425
+ method: "patch"
1426
+ }
1427
+ },
1428
+ ...ops.delete && {
1429
+ delete: {
1430
+ uri: `${baseUri}/${idPlaceholder}`,
1431
+ method: "delete"
1432
+ }
1433
+ }
1434
+ };
1435
+ }, "buildSubResourceOperations");
1436
+ }
1437
+ });
1438
+
1463
1439
  // ../crouton-core/src/lib/resource/ResourceJson.schema.ts
1464
1440
  var import_zod19, JsonColumnsMapSchema, ColumnsSchema, JsonDisplaySchema, normalizeColumns, ResourceJsonShape, refineByKind, buildResourceJsonSchema, ResourceJsonSchema;
1465
1441
  var init_ResourceJson_schema = __esm({
@@ -1571,12 +1547,7 @@ var init_ResourceJson_schema = __esm({
1571
1547
  * `{ "relation": "text_author", "include": ["author"] }` →
1572
1548
  * `include: { text_author: { include: { author: true } } }`
1573
1549
  */
1574
- include: import_zod19.z.array(JsonIncludeEntrySchema).default([]),
1575
- /**
1576
- * Normalized extension blocks lifted from registered top-level keys.
1577
- * Authors never write this key directly — the transform fills it.
1578
- */
1579
- extensions: import_zod19.z.record(import_zod19.z.string(), import_zod19.z.unknown()).optional()
1550
+ include: import_zod19.z.array(JsonIncludeEntrySchema).default([])
1580
1551
  });
1581
1552
  refineByKind = /* @__PURE__ */ __name((obj, ctx) => {
1582
1553
  if (obj.kind === "custom") {
@@ -1673,24 +1644,14 @@ var init_ResourceJson_schema = __esm({
1673
1644
  patch: false,
1674
1645
  delete: false
1675
1646
  }) : JsonOperationsSchema.parse({});
1676
- const raw = obj;
1677
- const extensions = {};
1678
- for (const name of ext.keys()) {
1679
- if (raw[name] !== void 0) {
1680
- extensions[name] = raw[name];
1681
- delete raw[name];
1682
- }
1683
- }
1684
1647
  return {
1685
1648
  title,
1686
1649
  ...obj,
1650
+ id: obj.id ?? obj.name,
1687
1651
  route: obj.route ?? obj.id ?? obj.name ?? "",
1688
1652
  schemaVersion,
1689
1653
  columns: normalizeColumns(obj.columns),
1690
- operations: obj.operations ?? defaultOps,
1691
- ...Object.keys(extensions).length && {
1692
- extensions
1693
- }
1654
+ operations: obj.operations ?? defaultOps
1694
1655
  };
1695
1656
  }));
1696
1657
  }, "buildResourceJsonSchema");
@@ -1812,96 +1773,6 @@ var init_resource = __esm({
1812
1773
  }
1813
1774
  });
1814
1775
 
1815
- // ../crouton-core/src/lib/config/CroutonConfig.schema.ts
1816
- var import_zod20, RulesetSchema, I18nConfigSchema, CroutonConfigSchema;
1817
- var init_CroutonConfig_schema = __esm({
1818
- "../crouton-core/src/lib/config/CroutonConfig.schema.ts"() {
1819
- "use strict";
1820
- init_cjs_shims();
1821
- import_zod20 = require("zod");
1822
- init_Operations_schema();
1823
- init_resource();
1824
- RulesetSchema = import_zod20.z.object({
1825
- hideIdInTable: import_zod20.z.boolean().default(true),
1826
- hideIdInForm: import_zod20.z.boolean().default(true),
1827
- hideIdInView: import_zod20.z.boolean().default(true),
1828
- hideTimestamps: import_zod20.z.boolean().default(true),
1829
- hideForeignKeys: import_zod20.z.boolean().default(true),
1830
- includeRelations: import_zod20.z.boolean().default(true),
1831
- hideRelationsInTable: import_zod20.z.boolean().default(true),
1832
- showRelationsInForm: import_zod20.z.boolean().default(true),
1833
- enumValueLabel: import_zod20.z.boolean().default(true),
1834
- sharedEnums: import_zod20.z.boolean().default(true),
1835
- defaultOperations: JsonOperationsSchema.default(JsonOperationsSchema.parse({}))
1836
- });
1837
- I18nConfigSchema = import_zod20.z.object({
1838
- /** Default / fallback language. */
1839
- defaultLanguage: import_zod20.z.string().default("en"),
1840
- /** All supported language codes. */
1841
- languages: import_zod20.z.array(import_zod20.z.string()).min(1),
1842
- /** Directory containing `<lang>.json` bundles, relative to project root. */
1843
- translationsDir: import_zod20.z.string().default("translations")
1844
- });
1845
- CroutonConfigSchema = import_zod20.z.object({
1846
- /**
1847
- * Application title served to the frontend via `GET /_app/layout`.
1848
- * Displayed in the admin sidebar header.
1849
- */
1850
- title: import_zod20.z.string(),
1851
- /** Where resource directories live, relative to the project root. */
1852
- resourcesDir: import_zod20.z.string(),
1853
- /** Where datasource folders live (each with a `data-source.json`). */
1854
- dataSourcesDir: import_zod20.z.string(),
1855
- /**
1856
- * Template for a model's Zod export name. `{Model}` → Prisma model name.
1857
- * Defaults to `{Model}WithRelationsSchema` (the relations-aware schema
1858
- * emitted by zod-prisma-types when `createRelationValuesTypes` is on).
1859
- */
1860
- schemaExportName: import_zod20.z.string().default("{Model}WithRelationsSchema"),
1861
- /** Path to the shared enum registry, relative to project root. Default `crouton.enums.json`. */
1862
- enumsFile: import_zod20.z.string().default("crouton.enums.json"),
1863
- /** Optional overrides of the default visibility ruleset. */
1864
- rules: RulesetSchema.default(RulesetSchema.parse({})),
1865
- /**
1866
- * Sidebar group definitions, keyed by group slug (e.g. `"metadata"`).
1867
- * Resources reference a group via `sidebar.group` in their `resource.json`.
1868
- */
1869
- sidebarGroups: import_zod20.z.record(import_zod20.z.string(), SidebarGroupSchema).default({}),
1870
- /**
1871
- * Whether form fields are saved automatically as the user edits them.
1872
- * @default true
1873
- */
1874
- autoSave: import_zod20.z.boolean().default(true),
1875
- /** Optional i18n / translation configuration. */
1876
- i18n: I18nConfigSchema.optional()
1877
- });
1878
- }
1879
- });
1880
-
1881
- // ../crouton-core/src/lib/config/readConfig.ts
1882
- var CONFIG_FILES;
1883
- var init_readConfig = __esm({
1884
- "../crouton-core/src/lib/config/readConfig.ts"() {
1885
- "use strict";
1886
- init_cjs_shims();
1887
- CONFIG_FILES = [
1888
- "crouton.json",
1889
- "crouton.mjs",
1890
- "crouton.js"
1891
- ];
1892
- }
1893
- });
1894
-
1895
- // ../crouton-core/src/lib/config/index.ts
1896
- var init_config = __esm({
1897
- "../crouton-core/src/lib/config/index.ts"() {
1898
- "use strict";
1899
- init_cjs_shims();
1900
- init_CroutonConfig_schema();
1901
- init_readConfig();
1902
- }
1903
- });
1904
-
1905
1776
  // ../crouton-core/src/lib/view/column-predicates.ts
1906
1777
  var isBoolean, isRelation, isAutocomplete, isRecordCell, isDateRange, isObjectColumn, isArrayColumn, isObjectCell;
1907
1778
  var init_column_predicates = __esm({
@@ -2376,23 +2247,23 @@ var init_column_type_schema_source = __esm({
2376
2247
  });
2377
2248
 
2378
2249
  // ../crouton-core/src/lib/view/json-schema.opts.ts
2379
- var import_zod21, isInstanceOf, jsonSchemaOverride, jsonSchemaOpts;
2250
+ var import_zod20, isInstanceOf, jsonSchemaOverride, jsonSchemaOpts;
2380
2251
  var init_json_schema_opts = __esm({
2381
2252
  "../crouton-core/src/lib/view/json-schema.opts.ts"() {
2382
2253
  "use strict";
2383
2254
  init_cjs_shims();
2384
- import_zod21 = require("zod");
2255
+ import_zod20 = require("zod");
2385
2256
  isInstanceOf = /* @__PURE__ */ __name((zodSchema, className) => {
2386
- if (!(zodSchema instanceof import_zod21.z.ZodCustom)) return false;
2257
+ if (!(zodSchema instanceof import_zod20.z.ZodCustom)) return false;
2387
2258
  const result = zodSchema.safeParse(null);
2388
2259
  return !result.success && result.error.issues[0]?.expected === className;
2389
2260
  }, "isInstanceOf");
2390
2261
  jsonSchemaOverride = /* @__PURE__ */ __name(({ zodSchema, jsonSchema }) => {
2391
- if (zodSchema instanceof import_zod21.z.ZodDate) {
2262
+ if (zodSchema instanceof import_zod20.z.ZodDate) {
2392
2263
  jsonSchema.type = "string";
2393
2264
  jsonSchema.format = "date-time";
2394
2265
  }
2395
- if (zodSchema instanceof import_zod21.z.ZodBigInt) {
2266
+ if (zodSchema instanceof import_zod20.z.ZodBigInt) {
2396
2267
  jsonSchema.type = "integer";
2397
2268
  }
2398
2269
  if (isInstanceOf(zodSchema, "Decimal")) {
@@ -2410,12 +2281,12 @@ var init_json_schema_opts = __esm({
2410
2281
  });
2411
2282
 
2412
2283
  // ../crouton-core/src/lib/view/view.builder.ts
2413
- var import_zod22, patchFilterProperties, injectFieldDefaults, zodSchemaSource, NON_NULL_TYPES, SHAPE_KEYS, applyRequiredColumns, buildView, emptyTableView, buildViewsWithSource, buildViews, buildViewsFromColumnTypes, buildViewsFromColumns;
2284
+ var import_zod21, patchFilterProperties, injectFieldDefaults, zodSchemaSource, NON_NULL_TYPES, SHAPE_KEYS, applyRequiredColumns, buildView, emptyTableView, buildViewsWithSource, buildViews, buildViewsFromColumnTypes, buildViewsFromColumns;
2414
2285
  var init_view_builder = __esm({
2415
2286
  "../crouton-core/src/lib/view/view.builder.ts"() {
2416
2287
  "use strict";
2417
2288
  init_cjs_shims();
2418
- import_zod22 = require("zod");
2289
+ import_zod21 = require("zod");
2419
2290
  init_column_predicates();
2420
2291
  init_column_type_schema_source();
2421
2292
  init_column_utils();
@@ -2483,7 +2354,7 @@ var init_view_builder = __esm({
2483
2354
  ]));
2484
2355
  const picked = schema.pick(mask);
2485
2356
  try {
2486
- return (0, import_zod22.toJSONSchema)(picked, {
2357
+ return (0, import_zod21.toJSONSchema)(picked, {
2487
2358
  target: "draft-07",
2488
2359
  ...jsonSchemaOpts
2489
2360
  });
@@ -2571,7 +2442,7 @@ var init_view_builder = __esm({
2571
2442
  if (table) {
2572
2443
  table.defaultSort = resolveDefaultSort(table.columns, columns);
2573
2444
  views.table = table;
2574
- } else if (columns?.length) {
2445
+ } else if (columns !== void 0) {
2575
2446
  views.table = emptyTableView();
2576
2447
  }
2577
2448
  const form = buildView(source, columns, (c) => !c.hiddenInForm, buildFormUiSchema, true, (c) => !c.idField && (c.createable === true || c.updateable === true));
@@ -2694,88 +2565,552 @@ var init_view_builder = __esm({
2694
2565
  }
2695
2566
  });
2696
2567
 
2697
- // ../crouton-core/src/lib/view/view.schema.ts
2698
- var import_zod23, ViewColumnConfigSchema, ViewConfigSchema, viewDefList, ViewDefEnum;
2699
- var init_view_schema = __esm({
2700
- "../crouton-core/src/lib/view/view.schema.ts"() {
2568
+ // ../crouton-core/src/lib/view/view.schema.ts
2569
+ var import_zod22, ViewColumnConfigSchema, ViewConfigSchema, viewDefList, ViewDefEnum;
2570
+ var init_view_schema = __esm({
2571
+ "../crouton-core/src/lib/view/view.schema.ts"() {
2572
+ "use strict";
2573
+ init_cjs_shims();
2574
+ import_zod22 = require("zod");
2575
+ init_FieldInput_schema();
2576
+ ViewColumnConfigSchema = import_zod22.z.object({
2577
+ id: import_zod22.z.string(),
2578
+ label: import_zod22.z.string().optional(),
2579
+ sortable: import_zod22.z.boolean().optional(),
2580
+ searchable: import_zod22.z.boolean().optional(),
2581
+ fieldInput: FieldInputSchema.optional()
2582
+ });
2583
+ ViewConfigSchema = import_zod22.z.object({
2584
+ // TODO why we have both?
2585
+ json_schema: import_zod22.z.record(import_zod22.z.string(), import_zod22.z.unknown()).optional(),
2586
+ ui_schema: import_zod22.z.record(import_zod22.z.string(), import_zod22.z.unknown()).optional(),
2587
+ // TODO why we have both?
2588
+ ui: import_zod22.z.record(import_zod22.z.string(), import_zod22.z.unknown()).optional(),
2589
+ data: import_zod22.z.record(import_zod22.z.string(), import_zod22.z.unknown()).optional(),
2590
+ columns: import_zod22.z.array(ViewColumnConfigSchema),
2591
+ defaultSort: import_zod22.z.string().optional()
2592
+ });
2593
+ viewDefList = [
2594
+ "table",
2595
+ "view",
2596
+ "form"
2597
+ ];
2598
+ ViewDefEnum = import_zod22.z.enum(viewDefList);
2599
+ }
2600
+ });
2601
+
2602
+ // ../crouton-core/src/lib/view/index.ts
2603
+ var init_view = __esm({
2604
+ "../crouton-core/src/lib/view/index.ts"() {
2605
+ "use strict";
2606
+ init_cjs_shims();
2607
+ init_column_predicates();
2608
+ init_column_utils();
2609
+ init_sort_helpers();
2610
+ init_schema_transforms();
2611
+ init_table_schema_builder();
2612
+ init_form_schema_builder();
2613
+ init_calculated_columns_builder();
2614
+ init_view_builder();
2615
+ init_column_type_schema_source();
2616
+ init_view_schema();
2617
+ init_json_schema_opts();
2618
+ }
2619
+ });
2620
+
2621
+ // ../crouton-core/src/lib/compile/column-enrichment.ts
2622
+ var init_column_enrichment = __esm({
2623
+ "../crouton-core/src/lib/compile/column-enrichment.ts"() {
2624
+ "use strict";
2625
+ init_cjs_shims();
2626
+ }
2627
+ });
2628
+
2629
+ // ../crouton-core/src/lib/compile/column-transforms.ts
2630
+ var init_column_transforms = __esm({
2631
+ "../crouton-core/src/lib/compile/column-transforms.ts"() {
2632
+ "use strict";
2633
+ init_cjs_shims();
2634
+ init_resource();
2635
+ }
2636
+ });
2637
+
2638
+ // ../crouton-core/src/lib/compile/enum-registry.ts
2639
+ var import_zod23, EnumEntrySchema, EnumRegistrySchema;
2640
+ var init_enum_registry = __esm({
2641
+ "../crouton-core/src/lib/compile/enum-registry.ts"() {
2642
+ "use strict";
2643
+ init_cjs_shims();
2644
+ import_zod23 = require("zod");
2645
+ EnumEntrySchema = import_zod23.z.object({
2646
+ value: import_zod23.z.unknown(),
2647
+ label: import_zod23.z.string()
2648
+ });
2649
+ EnumRegistrySchema = import_zod23.z.record(import_zod23.z.string(), import_zod23.z.array(EnumEntrySchema)).default({});
2650
+ }
2651
+ });
2652
+
2653
+ // ../crouton-core/src/lib/compile/relation-type.ts
2654
+ var import_zod24;
2655
+ var init_relation_type = __esm({
2656
+ "../crouton-core/src/lib/compile/relation-type.ts"() {
2657
+ "use strict";
2658
+ init_cjs_shims();
2659
+ import_zod24 = require("zod");
2660
+ }
2661
+ });
2662
+
2663
+ // ../crouton-core/src/lib/compile/schema.helpers.ts
2664
+ var init_schema_helpers = __esm({
2665
+ "../crouton-core/src/lib/compile/schema.helpers.ts"() {
2666
+ "use strict";
2667
+ init_cjs_shims();
2668
+ init_view();
2669
+ }
2670
+ });
2671
+
2672
+ // ../crouton-core/src/lib/compile/compile-resource.ts
2673
+ var init_compile_resource = __esm({
2674
+ "../crouton-core/src/lib/compile/compile-resource.ts"() {
2675
+ "use strict";
2676
+ init_cjs_shims();
2677
+ init_resource();
2678
+ init_view();
2679
+ init_column_enrichment();
2680
+ init_column_transforms();
2681
+ init_enum_registry();
2682
+ init_relation_type();
2683
+ init_schema_helpers();
2684
+ }
2685
+ });
2686
+
2687
+ // ../crouton-core/src/lib/data-source/DataSourceSchema.ts
2688
+ var import_zod25, DataSourceShape, transformDataSource, DataSourceSchema;
2689
+ var init_DataSourceSchema = __esm({
2690
+ "../crouton-core/src/lib/data-source/DataSourceSchema.ts"() {
2691
+ "use strict";
2692
+ init_cjs_shims();
2693
+ import_zod25 = __toESM(require("zod"), 1);
2694
+ DataSourceShape = import_zod25.default.object({
2695
+ /** Datasource name (folder + `name` in data-source.json). */
2696
+ name: import_zod25.default.string(),
2697
+ /**
2698
+ * Env var holding the connection URL. Required for Prisma adapters; optional
2699
+ * for custom adapters whose connection config may differ (secrets file, SDK
2700
+ * key, etc.).
2701
+ */
2702
+ urlEnv: import_zod25.default.string().optional(),
2703
+ /** Import path for this datasource's generated Zod types (for resource `schema.ts`). */
2704
+ generatedTypesImport: import_zod25.default.string().optional(),
2705
+ /** Datasource type tag. Default `postgres`. */
2706
+ type: import_zod25.default.string().default("postgres"),
2707
+ /** Mark this as the default datasource. Default `false`. */
2708
+ default: import_zod25.default.boolean().default(false),
2709
+ /**
2710
+ * Adapter kind. `"prisma"` (default) expects `index.ts` to default-export a
2711
+ * `PrismaClient`; `"custom"` expects it to default-export a `DataSourceAdapter`.
2712
+ */
2713
+ adapter: import_zod25.default.enum([
2714
+ "prisma",
2715
+ "custom"
2716
+ ]).default("prisma"),
2717
+ /** Prisma schema path, relative to project root. Default `prisma/<name>/schema.prisma`. */
2718
+ prismaSchema: import_zod25.default.string().optional(),
2719
+ /** Prisma config path, relative to project root. Default `prisma/<name>/prisma.config.ts`. */
2720
+ prismaConfig: import_zod25.default.string().optional(),
2721
+ /** zod-prisma-types output dir, relative to project root. Default `generated/<name>/src`. */
2722
+ zodOutput: import_zod25.default.string().optional(),
2723
+ /** Prisma client output dir, relative to project root. Default `generated/<name>/client`. */
2724
+ clientOutput: import_zod25.default.string().optional()
2725
+ });
2726
+ transformDataSource = /* @__PURE__ */ __name((data) => {
2727
+ const name = data.name ?? "name";
2728
+ return {
2729
+ ...data,
2730
+ generatedTypesImport: data.generatedTypesImport ?? `@your-scope/generated/${name}`,
2731
+ prismaSchema: data.prismaSchema ?? `prisma/${name}/schema.prisma`,
2732
+ prismaConfig: data.prismaConfig ?? `prisma/${name}/prisma.config.ts`,
2733
+ zodOutput: data.zodOutput ?? `generated/${name}/src`,
2734
+ clientOutput: data.clientOutput ?? `generated/${name}/client`
2735
+ };
2736
+ }, "transformDataSource");
2737
+ DataSourceSchema = DataSourceShape.transform(transformDataSource);
2738
+ }
2739
+ });
2740
+
2741
+ // ../crouton-core/src/lib/data-source/index.ts
2742
+ var init_data_source = __esm({
2743
+ "../crouton-core/src/lib/data-source/index.ts"() {
2744
+ "use strict";
2745
+ init_cjs_shims();
2746
+ init_DataSourceSchema();
2747
+ init_Operations_schema();
2748
+ init_Security_schema();
2749
+ }
2750
+ });
2751
+
2752
+ // ../crouton-core/src/lib/compile/value-label-column.ts
2753
+ var import_zod26, ValueSchema, ValueLabelColumnSchema;
2754
+ var init_value_label_column = __esm({
2755
+ "../crouton-core/src/lib/compile/value-label-column.ts"() {
2701
2756
  "use strict";
2702
2757
  init_cjs_shims();
2703
- import_zod23 = require("zod");
2704
- init_FieldInput_schema();
2705
- ViewColumnConfigSchema = import_zod23.z.object({
2706
- id: import_zod23.z.string(),
2707
- label: import_zod23.z.string().optional(),
2708
- sortable: import_zod23.z.boolean().optional(),
2709
- searchable: import_zod23.z.boolean().optional(),
2710
- fieldInput: FieldInputSchema.optional()
2758
+ import_zod26 = require("zod");
2759
+ ValueSchema = import_zod26.z.object({
2760
+ value: import_zod26.z.unknown(),
2761
+ label: import_zod26.z.string()
2711
2762
  });
2712
- ViewConfigSchema = import_zod23.z.object({
2713
- // TODO why we have both?
2714
- json_schema: import_zod23.z.record(import_zod23.z.string(), import_zod23.z.unknown()).optional(),
2715
- ui_schema: import_zod23.z.record(import_zod23.z.string(), import_zod23.z.unknown()).optional(),
2716
- // TODO why we have both?
2717
- ui: import_zod23.z.record(import_zod23.z.string(), import_zod23.z.unknown()).optional(),
2718
- data: import_zod23.z.record(import_zod23.z.string(), import_zod23.z.unknown()).optional(),
2719
- columns: import_zod23.z.array(ViewColumnConfigSchema),
2720
- defaultSort: import_zod23.z.string().optional()
2763
+ ValueLabelColumnSchema = import_zod26.z.object({
2764
+ field: import_zod26.z.string(),
2765
+ values: import_zod26.z.array(ValueSchema).default([]),
2766
+ enumName: import_zod26.z.string().optional()
2721
2767
  });
2722
- viewDefList = [
2723
- "table",
2724
- "view",
2725
- "form"
2726
- ];
2727
- ViewDefEnum = import_zod23.z.enum(viewDefList);
2728
2768
  }
2729
2769
  });
2730
2770
 
2731
- // ../crouton-core/src/lib/view/index.ts
2732
- var init_view = __esm({
2733
- "../crouton-core/src/lib/view/index.ts"() {
2771
+ // ../crouton-core/src/lib/compile/compiled-sub-resource.schema.ts
2772
+ var import_zod27, CompiledSubResourceConfigSchema;
2773
+ var init_compiled_sub_resource_schema = __esm({
2774
+ "../crouton-core/src/lib/compile/compiled-sub-resource.schema.ts"() {
2734
2775
  "use strict";
2735
2776
  init_cjs_shims();
2736
- init_column_predicates();
2737
- init_column_utils();
2738
- init_sort_helpers();
2739
- init_schema_transforms();
2740
- init_table_schema_builder();
2741
- init_form_schema_builder();
2742
- init_calculated_columns_builder();
2743
- init_view_builder();
2744
- init_column_type_schema_source();
2745
- init_view_schema();
2777
+ import_zod27 = require("zod");
2778
+ init_data_source();
2779
+ init_resource();
2780
+ init_view();
2781
+ init_value_label_column();
2782
+ CompiledSubResourceConfigSchema = import_zod27.z.object({
2783
+ column: import_zod27.z.string(),
2784
+ relation: import_zod27.z.string(),
2785
+ childRoute: import_zod27.z.string(),
2786
+ childKind: import_zod27.z.enum([
2787
+ "prisma",
2788
+ "custom"
2789
+ ]).default("prisma"),
2790
+ childDir: import_zod27.z.string().optional(),
2791
+ childModel: import_zod27.z.string(),
2792
+ foreignKey: import_zod27.z.string(),
2793
+ name: import_zod27.z.string().optional(),
2794
+ title: import_zod27.z.string().optional(),
2795
+ idField: import_zod27.z.string().optional(),
2796
+ idType: import_zod27.z.enum([
2797
+ "string",
2798
+ "number"
2799
+ ]).optional(),
2800
+ views: import_zod27.z.record(import_zod27.z.string(), ViewConfigSchema).optional(),
2801
+ operations: JsonOperationsSchema,
2802
+ actions: import_zod27.z.array(JsonActionSchema).optional(),
2803
+ modalSize: import_zod27.z.enum([
2804
+ "xs",
2805
+ "sm",
2806
+ "lg",
2807
+ "xl"
2808
+ ]).optional(),
2809
+ include: import_zod27.z.array(JsonIncludeEntrySchema).optional(),
2810
+ calculatedColumns: import_zod27.z.array(CalculatedColumnSchema).optional(),
2811
+ includeInFindOne: import_zod27.z.boolean().optional(),
2812
+ hiddenInTable: import_zod27.z.boolean().optional(),
2813
+ findOneOrderBy: import_zod27.z.record(import_zod27.z.string(), import_zod27.z.unknown()).optional(),
2814
+ valueLabelColumns: import_zod27.z.array(ValueLabelColumnSchema).optional(),
2815
+ relationType: import_zod27.z.enum([
2816
+ "oneToMany",
2817
+ "manyToOne"
2818
+ ]).optional()
2819
+ });
2820
+ }
2821
+ });
2822
+
2823
+ // ../crouton-core/src/lib/compile/schema-input.ts
2824
+ var import_zod28, JsonSchemaInputSchema, SchemaInputSchema;
2825
+ var init_schema_input = __esm({
2826
+ "../crouton-core/src/lib/compile/schema-input.ts"() {
2827
+ "use strict";
2828
+ init_cjs_shims();
2829
+ import_zod28 = require("zod");
2830
+ JsonSchemaInputSchema = import_zod28.z.object({
2831
+ type: import_zod28.z.literal("object"),
2832
+ properties: import_zod28.z.record(import_zod28.z.string(), import_zod28.z.unknown()),
2833
+ required: import_zod28.z.array(import_zod28.z.string()).optional(),
2834
+ additionalProperties: import_zod28.z.boolean().optional()
2835
+ });
2836
+ SchemaInputSchema = import_zod28.z.union([
2837
+ import_zod28.z.custom((val) => val instanceof import_zod28.ZodObject),
2838
+ JsonSchemaInputSchema
2839
+ ]);
2840
+ }
2841
+ });
2842
+
2843
+ // ../crouton-core/src/lib/compile/definition.schema.ts
2844
+ var import_zod29, OperationDefSchema, UpsertOperationDefSchema, ResourceDefinitionSchema, DefinitionCallbackSchema, DefinitionSchema;
2845
+ var init_definition_schema = __esm({
2846
+ "../crouton-core/src/lib/compile/definition.schema.ts"() {
2847
+ "use strict";
2848
+ init_cjs_shims();
2849
+ import_zod29 = require("zod");
2850
+ init_schema_input();
2851
+ init_Security_schema();
2852
+ OperationDefSchema = import_zod29.z.union([
2853
+ import_zod29.z.literal(true),
2854
+ import_zod29.z.object({
2855
+ schema: SchemaInputSchema.optional(),
2856
+ security: SecuritySchema.optional()
2857
+ })
2858
+ ]);
2859
+ UpsertOperationDefSchema = import_zod29.z.object({
2860
+ schema: SchemaInputSchema.optional(),
2861
+ upsertOn: import_zod29.z.union([
2862
+ import_zod29.z.string(),
2863
+ import_zod29.z.array(import_zod29.z.string())
2864
+ ]),
2865
+ security: SecuritySchema.optional()
2866
+ });
2867
+ ResourceDefinitionSchema = import_zod29.z.object({
2868
+ findAll: OperationDefSchema.optional(),
2869
+ findOne: OperationDefSchema.optional(),
2870
+ create: OperationDefSchema.optional(),
2871
+ update: OperationDefSchema.optional(),
2872
+ patch: OperationDefSchema.optional(),
2873
+ upsert: UpsertOperationDefSchema.optional(),
2874
+ delete: OperationDefSchema.optional()
2875
+ });
2876
+ DefinitionCallbackSchema = import_zod29.z.function({
2877
+ input: [],
2878
+ output: ResourceDefinitionSchema
2879
+ });
2880
+ DefinitionSchema = import_zod29.z.union([
2881
+ ResourceDefinitionSchema,
2882
+ DefinitionCallbackSchema
2883
+ ]);
2884
+ }
2885
+ });
2886
+
2887
+ // ../crouton-core/src/lib/compile/lookup.schema.ts
2888
+ var import_zod30, LookupSchema;
2889
+ var init_lookup_schema = __esm({
2890
+ "../crouton-core/src/lib/compile/lookup.schema.ts"() {
2891
+ "use strict";
2892
+ init_cjs_shims();
2893
+ import_zod30 = require("zod");
2894
+ LookupSchema = import_zod30.z.object({
2895
+ key: import_zod30.z.string(),
2896
+ label: import_zod30.z.string().optional()
2897
+ });
2898
+ }
2899
+ });
2900
+
2901
+ // ../crouton-core/src/lib/compile/compiled-resource.schema.ts
2902
+ var import_zod31, CompiledResourceSchema;
2903
+ var init_compiled_resource_schema = __esm({
2904
+ "../crouton-core/src/lib/compile/compiled-resource.schema.ts"() {
2905
+ "use strict";
2906
+ init_cjs_shims();
2907
+ import_zod31 = require("zod");
2908
+ init_resource();
2909
+ init_view();
2910
+ init_compiled_sub_resource_schema();
2911
+ init_definition_schema();
2912
+ init_lookup_schema();
2913
+ init_value_label_column();
2914
+ CompiledResourceSchema = ResourceJsonShape.extend({
2915
+ route: import_zod31.z.string(),
2916
+ valueLabelColumns: import_zod31.z.array(ValueLabelColumnSchema).default([]),
2917
+ subResources: import_zod31.z.lazy(() => import_zod31.z.array(CompiledSubResourceConfigSchema)).default([]),
2918
+ lookup: LookupSchema.optional(),
2919
+ views: import_zod31.z.record(import_zod31.z.string(), ViewConfigSchema),
2920
+ definition: DefinitionSchema,
2921
+ idField: import_zod31.z.string(),
2922
+ idType: import_zod31.z.enum([
2923
+ "string",
2924
+ "number"
2925
+ ]).default("string")
2926
+ });
2927
+ }
2928
+ });
2929
+
2930
+ // ../crouton-core/src/lib/compile/crud-config.ts
2931
+ var init_crud_config = __esm({
2932
+ "../crouton-core/src/lib/compile/crud-config.ts"() {
2933
+ "use strict";
2934
+ init_cjs_shims();
2935
+ }
2936
+ });
2937
+
2938
+ // ../crouton-core/src/lib/compile/to-json-schema.ts
2939
+ var import_zod32;
2940
+ var init_to_json_schema = __esm({
2941
+ "../crouton-core/src/lib/compile/to-json-schema.ts"() {
2942
+ "use strict";
2943
+ init_cjs_shims();
2944
+ import_zod32 = require("zod");
2746
2945
  init_json_schema_opts();
2747
2946
  }
2748
2947
  });
2749
2948
 
2949
+ // ../crouton-core/src/lib/compile/payload-builders.ts
2950
+ var init_payload_builders = __esm({
2951
+ "../crouton-core/src/lib/compile/payload-builders.ts"() {
2952
+ "use strict";
2953
+ init_cjs_shims();
2954
+ init_data_source();
2955
+ init_resource();
2956
+ init_crud_config();
2957
+ init_to_json_schema();
2958
+ }
2959
+ });
2960
+
2961
+ // ../crouton-core/src/lib/compile/parse-schema.ts
2962
+ var init_parse_schema = __esm({
2963
+ "../crouton-core/src/lib/compile/parse-schema.ts"() {
2964
+ "use strict";
2965
+ init_cjs_shims();
2966
+ init_resource();
2967
+ init_compile_resource();
2968
+ init_payload_builders();
2969
+ }
2970
+ });
2971
+
2972
+ // ../crouton-core/src/lib/compile/index.ts
2973
+ var init_compile = __esm({
2974
+ "../crouton-core/src/lib/compile/index.ts"() {
2975
+ "use strict";
2976
+ init_cjs_shims();
2977
+ init_action_types();
2978
+ init_compile_resource();
2979
+ init_compiled_resource_schema();
2980
+ init_compiled_sub_resource_schema();
2981
+ init_crud_config();
2982
+ init_definition_schema();
2983
+ init_enum_registry();
2984
+ init_lookup_schema();
2985
+ init_parse_schema();
2986
+ init_payload_builders();
2987
+ init_relation_type();
2988
+ init_schema_helpers();
2989
+ init_schema_input();
2990
+ init_to_json_schema();
2991
+ init_value_label_column();
2992
+ }
2993
+ });
2994
+
2995
+ // ../crouton-core/src/lib/config/CroutonConfig.schema.ts
2996
+ var import_zod33, RulesetSchema, I18nConfigSchema, CroutonConfigSchema;
2997
+ var init_CroutonConfig_schema = __esm({
2998
+ "../crouton-core/src/lib/config/CroutonConfig.schema.ts"() {
2999
+ "use strict";
3000
+ init_cjs_shims();
3001
+ import_zod33 = require("zod");
3002
+ init_Operations_schema();
3003
+ init_resource();
3004
+ RulesetSchema = import_zod33.z.object({
3005
+ hideIdInTable: import_zod33.z.boolean().default(true),
3006
+ hideIdInForm: import_zod33.z.boolean().default(true),
3007
+ hideIdInView: import_zod33.z.boolean().default(true),
3008
+ hideTimestamps: import_zod33.z.boolean().default(true),
3009
+ hideForeignKeys: import_zod33.z.boolean().default(true),
3010
+ includeRelations: import_zod33.z.boolean().default(true),
3011
+ hideRelationsInTable: import_zod33.z.boolean().default(true),
3012
+ showRelationsInForm: import_zod33.z.boolean().default(true),
3013
+ enumValueLabel: import_zod33.z.boolean().default(true),
3014
+ sharedEnums: import_zod33.z.boolean().default(true),
3015
+ defaultOperations: JsonOperationsSchema.default(JsonOperationsSchema.parse({}))
3016
+ });
3017
+ I18nConfigSchema = import_zod33.z.object({
3018
+ /** Default / fallback language. */
3019
+ defaultLanguage: import_zod33.z.string().default("en"),
3020
+ /** All supported language codes. */
3021
+ languages: import_zod33.z.array(import_zod33.z.string()).min(1),
3022
+ /** Directory containing `<lang>.json` bundles, relative to project root. */
3023
+ translationsDir: import_zod33.z.string().default("translations")
3024
+ });
3025
+ CroutonConfigSchema = import_zod33.z.object({
3026
+ /**
3027
+ * Application title served to the frontend via `GET /_app/layout`.
3028
+ * Displayed in the admin sidebar header.
3029
+ */
3030
+ title: import_zod33.z.string(),
3031
+ /** Where resource directories live, relative to the project root. */
3032
+ resourcesDir: import_zod33.z.string(),
3033
+ /** Where datasource folders live (each with a `data-source.json`). */
3034
+ dataSourcesDir: import_zod33.z.string(),
3035
+ /**
3036
+ * Template for a model's Zod export name. `{Model}` → Prisma model name.
3037
+ * Defaults to `{Model}WithRelationsSchema` (the relations-aware schema
3038
+ * emitted by zod-prisma-types when `createRelationValuesTypes` is on).
3039
+ */
3040
+ schemaExportName: import_zod33.z.string().default("{Model}WithRelationsSchema"),
3041
+ /** Path to the shared enum registry, relative to project root. Default `crouton.enums.json`. */
3042
+ enumsFile: import_zod33.z.string().default("crouton.enums.json"),
3043
+ /** Optional overrides of the default visibility ruleset. */
3044
+ rules: RulesetSchema.default(RulesetSchema.parse({})),
3045
+ /**
3046
+ * Sidebar group definitions, keyed by group slug (e.g. `"metadata"`).
3047
+ * Resources reference a group via `sidebar.group` in their `resource.json`.
3048
+ */
3049
+ sidebarGroups: import_zod33.z.record(import_zod33.z.string(), SidebarGroupSchema).default({}),
3050
+ /**
3051
+ * Whether form fields are saved automatically as the user edits them.
3052
+ * @default true
3053
+ */
3054
+ autoSave: import_zod33.z.boolean().default(true),
3055
+ /** Optional i18n / translation configuration. */
3056
+ i18n: I18nConfigSchema.optional()
3057
+ });
3058
+ }
3059
+ });
3060
+
3061
+ // ../crouton-core/src/lib/config/readConfig.ts
3062
+ var CONFIG_FILES;
3063
+ var init_readConfig = __esm({
3064
+ "../crouton-core/src/lib/config/readConfig.ts"() {
3065
+ "use strict";
3066
+ init_cjs_shims();
3067
+ CONFIG_FILES = [
3068
+ "crouton.json",
3069
+ "crouton.mjs",
3070
+ "crouton.js"
3071
+ ];
3072
+ }
3073
+ });
3074
+
3075
+ // ../crouton-core/src/lib/config/index.ts
3076
+ var init_config = __esm({
3077
+ "../crouton-core/src/lib/config/index.ts"() {
3078
+ "use strict";
3079
+ init_cjs_shims();
3080
+ init_CroutonConfig_schema();
3081
+ init_readConfig();
3082
+ }
3083
+ });
3084
+
2750
3085
  // ../crouton-core/src/lib/i18n/Translations.schema.ts
2751
- var import_zod24, NestedStringRecord, TranslationBundleSchema;
3086
+ var import_zod34, NestedStringRecord, TranslationBundleSchema;
2752
3087
  var init_Translations_schema = __esm({
2753
3088
  "../crouton-core/src/lib/i18n/Translations.schema.ts"() {
2754
3089
  "use strict";
2755
3090
  init_cjs_shims();
2756
- import_zod24 = require("zod");
2757
- NestedStringRecord = import_zod24.z.lazy(() => import_zod24.z.record(import_zod24.z.string(), import_zod24.z.union([
2758
- import_zod24.z.string(),
3091
+ import_zod34 = require("zod");
3092
+ NestedStringRecord = import_zod34.z.lazy(() => import_zod34.z.record(import_zod34.z.string(), import_zod34.z.union([
3093
+ import_zod34.z.string(),
2759
3094
  NestedStringRecord
2760
3095
  ])));
2761
- TranslationBundleSchema = import_zod24.z.object({
2762
- app: import_zod24.z.object({
2763
- title: import_zod24.z.string().optional()
3096
+ TranslationBundleSchema = import_zod34.z.object({
3097
+ app: import_zod34.z.object({
3098
+ title: import_zod34.z.string().optional()
2764
3099
  }).optional(),
2765
- sidebarGroups: import_zod24.z.record(import_zod24.z.string(), import_zod24.z.string()).optional(),
2766
- resources: import_zod24.z.record(import_zod24.z.string(), import_zod24.z.object({
2767
- title: import_zod24.z.string().optional(),
2768
- sidebar: import_zod24.z.string().optional(),
2769
- columns: import_zod24.z.record(import_zod24.z.string(), import_zod24.z.string()).optional(),
2770
- actions: import_zod24.z.record(import_zod24.z.string(), import_zod24.z.string()).optional(),
2771
- subResources: import_zod24.z.record(import_zod24.z.string(), import_zod24.z.object({
2772
- title: import_zod24.z.string().optional(),
2773
- columns: import_zod24.z.record(import_zod24.z.string(), import_zod24.z.string()).optional()
3100
+ sidebarGroups: import_zod34.z.record(import_zod34.z.string(), import_zod34.z.string()).optional(),
3101
+ resources: import_zod34.z.record(import_zod34.z.string(), import_zod34.z.object({
3102
+ title: import_zod34.z.string().optional(),
3103
+ sidebar: import_zod34.z.string().optional(),
3104
+ columns: import_zod34.z.record(import_zod34.z.string(), import_zod34.z.string()).optional(),
3105
+ actions: import_zod34.z.record(import_zod34.z.string(), import_zod34.z.string()).optional(),
3106
+ subResources: import_zod34.z.record(import_zod34.z.string(), import_zod34.z.object({
3107
+ title: import_zod34.z.string().optional(),
3108
+ columns: import_zod34.z.record(import_zod34.z.string(), import_zod34.z.string()).optional()
2774
3109
  }).optional()).optional()
2775
3110
  }).optional()).optional(),
2776
- enums: import_zod24.z.record(import_zod24.z.string(), import_zod24.z.record(import_zod24.z.string(), import_zod24.z.string())).optional(),
3111
+ enums: import_zod34.z.record(import_zod34.z.string(), import_zod34.z.record(import_zod34.z.string(), import_zod34.z.string())).optional(),
2777
3112
  ui: NestedStringRecord.optional(),
2778
- validation: import_zod24.z.record(import_zod24.z.string(), import_zod24.z.string()).optional()
3113
+ validation: import_zod34.z.record(import_zod34.z.string(), import_zod34.z.string()).optional()
2779
3114
  }).passthrough();
2780
3115
  }
2781
3116
  });
@@ -2908,6 +3243,7 @@ var init_src = __esm({
2908
3243
  init_base_builder();
2909
3244
  init_table_builder();
2910
3245
  init_table_utils();
3246
+ init_compile();
2911
3247
  init_data_source();
2912
3248
  init_resource();
2913
3249
  init_config();
@@ -2974,27 +3310,27 @@ var init_module_loader = __esm({
2974
3310
  });
2975
3311
 
2976
3312
  // src/lib/crud/hooks/hooks.types.ts
2977
- var import_zod28, WriteOpSchema, ReadOpSchema, ResourceHooksSchema;
3313
+ var import_zod38, WriteOpSchema, ReadOpSchema, ResourceHooksSchema;
2978
3314
  var init_hooks_types = __esm({
2979
3315
  "src/lib/crud/hooks/hooks.types.ts"() {
2980
3316
  "use strict";
2981
3317
  init_cjs_shims();
2982
- import_zod28 = require("zod");
2983
- WriteOpSchema = import_zod28.z.enum([
3318
+ import_zod38 = require("zod");
3319
+ WriteOpSchema = import_zod38.z.enum([
2984
3320
  "create",
2985
3321
  "update",
2986
3322
  "patch",
2987
3323
  "upsert",
2988
3324
  "delete"
2989
3325
  ]);
2990
- ReadOpSchema = import_zod28.z.enum([
3326
+ ReadOpSchema = import_zod38.z.enum([
2991
3327
  "findAll",
2992
3328
  "findOne"
2993
3329
  ]);
2994
- ResourceHooksSchema = import_zod28.z.object({
2995
- beforeWrite: import_zod28.z.custom().optional(),
2996
- afterWrite: import_zod28.z.custom().optional(),
2997
- afterRead: import_zod28.z.custom().optional()
3330
+ ResourceHooksSchema = import_zod38.z.object({
3331
+ beforeWrite: import_zod38.z.custom().optional(),
3332
+ afterWrite: import_zod38.z.custom().optional(),
3333
+ afterRead: import_zod38.z.custom().optional()
2998
3334
  });
2999
3335
  }
3000
3336
  });
@@ -3148,7 +3484,7 @@ __export(index_exports, {
3148
3484
  buildViews: () => buildViews,
3149
3485
  decorateRow: () => decorateRow,
3150
3486
  decorateRows: () => decorateRows,
3151
- isOperationEnabled: () => isOperationEnabled,
3487
+ isOperationEnabled: () => isOperationEnabled2,
3152
3488
  isRowProcedureAction: () => isRowProcedureAction,
3153
3489
  isTableProcedureAction: () => isTableProcedureAction,
3154
3490
  loadDataSourcesFromDir: () => loadDataSourcesFromDir,
@@ -3156,13 +3492,14 @@ __export(index_exports, {
3156
3492
  loadResourceHooks: () => loadResourceHooks,
3157
3493
  loadSubResourceHooks: () => loadSubResourceHooks,
3158
3494
  parseFilterString: () => parseFilterString,
3495
+ parseSchema: () => parseSchema,
3159
3496
  postWrite: () => postWrite,
3160
3497
  prepareWrite: () => prepareWrite,
3161
- resolveDefinition: () => resolveDefinition,
3162
- schemaFor: () => schemaFor,
3498
+ resolveDefinition: () => resolveDefinition2,
3499
+ schemaFor: () => schemaFor2,
3163
3500
  securityFor: () => securityFor,
3164
3501
  securityForSub: () => securityForSub,
3165
- upsertOnFor: () => upsertOnFor
3502
+ upsertOnFor: () => upsertOnFor2
3166
3503
  });
3167
3504
  module.exports = __toCommonJS(index_exports);
3168
3505
  init_cjs_shims();
@@ -3179,21 +3516,21 @@ init_cjs_shims();
3179
3516
 
3180
3517
  // src/lib/crud/app-layout/app-layout.types.ts
3181
3518
  init_cjs_shims();
3182
- var import_zod25 = require("zod");
3183
- var SidebarLeafSchema = import_zod25.z.object({
3184
- kind: import_zod25.z.literal("item").default("item"),
3185
- id: import_zod25.z.string(),
3186
- label: import_zod25.z.string(),
3187
- position: import_zod25.z.number().optional()
3519
+ var import_zod35 = require("zod");
3520
+ var SidebarLeafSchema = import_zod35.z.object({
3521
+ kind: import_zod35.z.literal("item").default("item"),
3522
+ id: import_zod35.z.string(),
3523
+ label: import_zod35.z.string(),
3524
+ position: import_zod35.z.number().optional()
3188
3525
  });
3189
- var SidebarGroupSchema2 = import_zod25.z.object({
3190
- kind: import_zod25.z.literal("group").default("group"),
3191
- id: import_zod25.z.string(),
3192
- label: import_zod25.z.string(),
3193
- position: import_zod25.z.number().optional(),
3194
- children: import_zod25.z.array(SidebarLeafSchema).default([])
3526
+ var SidebarGroupSchema2 = import_zod35.z.object({
3527
+ kind: import_zod35.z.literal("group").default("group"),
3528
+ id: import_zod35.z.string(),
3529
+ label: import_zod35.z.string(),
3530
+ position: import_zod35.z.number().optional(),
3531
+ children: import_zod35.z.array(SidebarLeafSchema).default([])
3195
3532
  });
3196
- var SidebarNodeSchema = import_zod25.z.discriminatedUnion("kind", [
3533
+ var SidebarNodeSchema = import_zod35.z.discriminatedUnion("kind", [
3197
3534
  SidebarLeafSchema,
3198
3535
  SidebarGroupSchema2
3199
3536
  ]);
@@ -3422,7 +3759,7 @@ var expandExtendColumns = /* @__PURE__ */ __name((columns, dirPath) => {
3422
3759
  }
3423
3760
  return result;
3424
3761
  }, "expandExtendColumns");
3425
- var buildValueLabelColumns = /* @__PURE__ */ __name((columns) => (columns ?? []).flatMap((c) => {
3762
+ var buildValueLabelColumns2 = /* @__PURE__ */ __name((columns) => (columns ?? []).flatMap((c) => {
3426
3763
  const opts = c.fieldInput?.options;
3427
3764
  if (!opts?.emitObject || !Array.isArray(opts.values)) return [];
3428
3765
  return [
@@ -3435,7 +3772,7 @@ var buildValueLabelColumns = /* @__PURE__ */ __name((columns) => (columns ?? [])
3435
3772
  }
3436
3773
  ];
3437
3774
  }), "buildValueLabelColumns");
3438
- var applyRelationFormatDefault = /* @__PURE__ */ __name((cols) => cols?.map((col) => {
3775
+ var applyRelationFormatDefault2 = /* @__PURE__ */ __name((cols) => cols?.map((col) => {
3439
3776
  const fi = col.fieldInput;
3440
3777
  if (fi && fi.resource && !fi.format && !fi.type) {
3441
3778
  return {
@@ -3448,7 +3785,7 @@ var applyRelationFormatDefault = /* @__PURE__ */ __name((cols) => cols?.map((col
3448
3785
  }
3449
3786
  return col;
3450
3787
  }), "applyRelationFormatDefault");
3451
- var resolveColumnFieldVariants = /* @__PURE__ */ __name((cols) => cols?.map((col) => {
3788
+ var resolveColumnFieldVariants2 = /* @__PURE__ */ __name((cols) => cols?.map((col) => {
3452
3789
  const fieldView = resolveViewField(col);
3453
3790
  const fieldTable = resolveTableField(col);
3454
3791
  return {
@@ -3539,7 +3876,7 @@ var localizeResource = /* @__PURE__ */ __name((config, t) => {
3539
3876
  columnLabels.set(col.id, translated);
3540
3877
  }
3541
3878
  translateEnumOptions(columns, t);
3542
- localized.valueLabelColumns = buildValueLabelColumns(columns);
3879
+ localized.valueLabelColumns = buildValueLabelColumns2(columns);
3543
3880
  }
3544
3881
  if (localized.views) {
3545
3882
  localized.views = patchViewTitles(localized.views, columnLabels);
@@ -3606,7 +3943,7 @@ var ResourceConfigRegistry = class {
3606
3943
  configs;
3607
3944
  translationRegistry;
3608
3945
  /**
3609
- * Per-language memo: `Map<language, Map<route, Resource>>`.
3946
+ * Per-language memo: `Map<language, Map<route, R>>`.
3610
3947
  * Cleared whenever the underlying configs reload (dev mode).
3611
3948
  */
3612
3949
  localizedCache = /* @__PURE__ */ new Map();
@@ -3644,6 +3981,10 @@ var ResourceConfigRegistry = class {
3644
3981
  }
3645
3982
  return config;
3646
3983
  }
3984
+ async findById(id, language) {
3985
+ const all = await this.getAll(language);
3986
+ return all.find((c) => c.id === id);
3987
+ }
3647
3988
  /**
3648
3989
  * On-disk directory containing `route`'s `resource.json`, if known.
3649
3990
  * Only meaningful after a load has populated the loader's internal map —
@@ -4039,49 +4380,49 @@ init_cjs_shims();
4039
4380
 
4040
4381
  // src/lib/crud/action/action.types.ts
4041
4382
  init_cjs_shims();
4042
- var import_zod26 = require("zod");
4043
- var ActionMetadataSchema = import_zod26.z.object({
4383
+ var import_zod36 = require("zod");
4384
+ var ActionMetadataSchema2 = import_zod36.z.object({
4044
4385
  /** URL segment used in the endpoint. */
4045
- id: import_zod26.z.string(),
4386
+ id: import_zod36.z.string(),
4046
4387
  /** Human-readable label shown as a button. */
4047
- label: import_zod26.z.string().optional(),
4388
+ label: import_zod36.z.string().optional(),
4048
4389
  /** MDI icon name, e.g. `"mdi:open-in-new"`. */
4049
- icon: import_zod26.z.string().optional(),
4390
+ icon: import_zod36.z.string().optional(),
4050
4391
  /** Tooltip text. Falls back to `label` when omitted. */
4051
- tooltip: import_zod26.z.string().optional(),
4392
+ tooltip: import_zod36.z.string().optional(),
4052
4393
  /** Per-row condition — button is hidden when false. */
4053
- condition: import_zod26.z.custom().optional()
4394
+ condition: import_zod36.z.custom().optional()
4054
4395
  });
4055
- var ResourceLinkActionSchema = ActionMetadataSchema.extend({
4056
- type: import_zod26.z.literal("link"),
4396
+ var ResourceLinkActionSchema2 = ActionMetadataSchema2.extend({
4397
+ type: import_zod36.z.literal("link"),
4057
4398
  /** URL to open. May contain `{id}` or `{env.VAR}` placeholders. */
4058
- href: import_zod26.z.string()
4399
+ href: import_zod36.z.string()
4059
4400
  });
4060
- var ResourceRowProcedureActionSchema = ActionMetadataSchema.extend({
4061
- type: import_zod26.z.literal("procedure").optional(),
4401
+ var ResourceRowProcedureActionSchema2 = ActionMetadataSchema2.extend({
4402
+ type: import_zod36.z.literal("procedure").optional(),
4062
4403
  /** HTTP method for the endpoint. Defaults to `"post"`. */
4063
- method: import_zod26.z.string().optional(),
4404
+ method: import_zod36.z.string().optional(),
4064
4405
  /** Static data payload merged into the request body by the frontend. */
4065
- data: import_zod26.z.record(import_zod26.z.string(), import_zod26.z.unknown()).optional(),
4406
+ data: import_zod36.z.record(import_zod36.z.string(), import_zod36.z.unknown()).optional(),
4066
4407
  /** Procedure called with `(prisma, recordId)`. */
4067
- procedure: import_zod26.z.custom((v) => typeof v === "function")
4408
+ procedure: import_zod36.z.custom((v) => typeof v === "function")
4068
4409
  });
4069
- var ResourceTableProcedureActionSchema = ActionMetadataSchema.extend({
4070
- type: import_zod26.z.literal("procedure").optional(),
4410
+ var ResourceTableProcedureActionSchema2 = ActionMetadataSchema2.extend({
4411
+ type: import_zod36.z.literal("procedure").optional(),
4071
4412
  /** HTTP method for the endpoint. Defaults to `"post"`. */
4072
- method: import_zod26.z.string().optional(),
4413
+ method: import_zod36.z.string().optional(),
4073
4414
  /** Static data payload merged into the request body by the frontend. */
4074
- data: import_zod26.z.record(import_zod26.z.string(), import_zod26.z.unknown()).optional(),
4415
+ data: import_zod36.z.record(import_zod36.z.string(), import_zod36.z.unknown()).optional(),
4075
4416
  /** Procedure called with `(prisma)` — no record id. */
4076
- procedure: import_zod26.z.custom((v) => typeof v === "function")
4417
+ procedure: import_zod36.z.custom((v) => typeof v === "function")
4077
4418
  });
4078
- var ResourceRowActionSchema = import_zod26.z.union([
4079
- ResourceRowProcedureActionSchema,
4080
- ResourceLinkActionSchema
4419
+ var ResourceRowActionSchema2 = import_zod36.z.union([
4420
+ ResourceRowProcedureActionSchema2,
4421
+ ResourceLinkActionSchema2
4081
4422
  ]);
4082
- var ResourceTableActionSchema = import_zod26.z.union([
4083
- ResourceTableProcedureActionSchema,
4084
- ResourceLinkActionSchema
4423
+ var ResourceTableActionSchema2 = import_zod36.z.union([
4424
+ ResourceTableProcedureActionSchema2,
4425
+ ResourceLinkActionSchema2
4085
4426
  ]);
4086
4427
  var isRowProcedureAction = /* @__PURE__ */ __name((action) => action.type !== "link", "isRowProcedureAction");
4087
4428
  var isTableProcedureAction = /* @__PURE__ */ __name((action) => action.type !== "link", "isTableProcedureAction");
@@ -4117,17 +4458,17 @@ var loadActions = /* @__PURE__ */ __name(async (jsonActions, basePath, scope) =>
4117
4458
  }, "loadActions");
4118
4459
 
4119
4460
  // src/lib/crud/crud.config.ts
4120
- var resolveDefinition = /* @__PURE__ */ __name((config) => {
4461
+ var resolveDefinition2 = /* @__PURE__ */ __name((config) => {
4121
4462
  const def2 = config.definition;
4122
4463
  return typeof def2 === "function" ? def2() : def2;
4123
4464
  }, "resolveDefinition");
4124
- var isOperationEnabled = /* @__PURE__ */ __name((def2, op) => def2[op] != null, "isOperationEnabled");
4125
- var schemaFor = /* @__PURE__ */ __name((def2, op) => {
4465
+ var isOperationEnabled2 = /* @__PURE__ */ __name((def2, op) => def2[op] != null, "isOperationEnabled");
4466
+ var schemaFor2 = /* @__PURE__ */ __name((def2, op) => {
4126
4467
  const entry = def2[op];
4127
4468
  if (!entry || entry === true) return void 0;
4128
4469
  return entry.schema;
4129
4470
  }, "schemaFor");
4130
- var upsertOnFor = /* @__PURE__ */ __name((def2) => def2.upsert?.upsertOn, "upsertOnFor");
4471
+ var upsertOnFor2 = /* @__PURE__ */ __name((def2) => def2.upsert?.upsertOn, "upsertOnFor");
4131
4472
  var opSecurity = /* @__PURE__ */ __name((entry) => {
4132
4473
  if (!entry || entry === true) return void 0;
4133
4474
  return entry.security;
@@ -4143,7 +4484,7 @@ init_cjs_shims();
4143
4484
 
4144
4485
  // src/lib/crud/custom-repository/custom-repository.types.ts
4145
4486
  init_cjs_shims();
4146
- var import_zod27 = require("zod");
4487
+ var import_zod37 = require("zod");
4147
4488
  var CUSTOM_OPS = [
4148
4489
  "findAll",
4149
4490
  "findOne",
@@ -4160,7 +4501,7 @@ var PARENT_METHOD = {
4160
4501
  patch: "patchByParent",
4161
4502
  delete: "deleteByParent"
4162
4503
  };
4163
- var CustomRepositorySchema = import_zod27.z.custom((value) => typeof value === "object" && value !== null);
4504
+ var CustomRepositorySchema = import_zod37.z.custom((value) => typeof value === "object" && value !== null);
4164
4505
 
4165
4506
  // src/lib/crud/custom-repository/custom-repository.loader.ts
4166
4507
  init_cjs_shims();
@@ -4243,6 +4584,7 @@ var DEFAULT_ID_FIELD = "id";
4243
4584
 
4244
4585
  // src/lib/crud/data-source/prisma.adapter.ts
4245
4586
  init_cjs_shims();
4587
+ var DB_CHECK_TIMEOUT_MS = 3e3;
4246
4588
  var PrismaDataSourceAdapter = class {
4247
4589
  static {
4248
4590
  __name(this, "PrismaDataSourceAdapter");
@@ -4255,6 +4597,13 @@ var PrismaDataSourceAdapter = class {
4255
4597
  supports(model) {
4256
4598
  return typeof this.client?.[model] !== "undefined";
4257
4599
  }
4600
+ async healthCheck() {
4601
+ const c = this.client;
4602
+ await Promise.race([
4603
+ c.$queryRaw`SELECT 1`,
4604
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Database health check timed out")), DB_CHECK_TIMEOUT_MS))
4605
+ ]);
4606
+ }
4258
4607
  async disconnect() {
4259
4608
  const c = this.client;
4260
4609
  if (typeof c?.$disconnect === "function") {
@@ -4340,7 +4689,7 @@ var unsupported = /* @__PURE__ */ __name((config, op) => {
4340
4689
  }, "unsupported");
4341
4690
  var createCustomRepository = /* @__PURE__ */ __name((prisma, config, dataSources, repository, configRegistry) => {
4342
4691
  const adapter = new PrismaDataSourceAdapter(prisma);
4343
- const repo = repository ?? {};
4692
+ const repo = repository ?? (prisma && typeof prisma === "object" ? prisma : {});
4344
4693
  const idField = config.idField ?? DEFAULT_ID_FIELD;
4345
4694
  const toId = /* @__PURE__ */ __name((id) => (config.idType ?? DEFAULT_ID_TYPE) === "number" ? +id : String(id), "toId");
4346
4695
  const parentRef = config.parent;
@@ -4496,13 +4845,17 @@ var createCustomRepository = /* @__PURE__ */ __name((prisma, config, dataSources
4496
4845
 
4497
4846
  // src/lib/crud/custom-repository/custom-repository.validate.ts
4498
4847
  init_cjs_shims();
4499
- var validateCustomRepository = /* @__PURE__ */ __name((config, repository) => {
4500
- const definition = resolveDefinition(config);
4501
- const enabled = CUSTOM_OPS.filter((op) => isOperationEnabled(definition, op));
4848
+ var validateCustomRepository = /* @__PURE__ */ __name((config, repository, adapterClient) => {
4849
+ const definition = resolveDefinition2(config);
4850
+ const enabled = CUSTOM_OPS.filter((op) => isOperationEnabled2(definition, op));
4502
4851
  const nested = !!config.parent;
4503
4852
  const methodFor = /* @__PURE__ */ __name((op) => nested ? PARENT_METHOD[op] : op, "methodFor");
4504
4853
  if (!repository) {
4505
4854
  if (enabled.length === 0) return void 0;
4855
+ if (adapterClient && typeof adapterClient === "object") {
4856
+ const missing2 = enabled.filter((op) => typeof adapterClient[methodFor(op)] !== "function");
4857
+ if (missing2.length === 0) return void 0;
4858
+ }
4506
4859
  return `No repository.ts found. A custom resource implements its own data access; create ${config.name}/repository.ts with a default export implementing: ${enabled.map(methodFor).join(", ")}.`;
4507
4860
  }
4508
4861
  const implemented = /* @__PURE__ */ __name((name) => typeof repository[name] === "function", "implemented");
@@ -5144,10 +5497,10 @@ var ReadRepository = class {
5144
5497
 
5145
5498
  // src/lib/crud/schema.utils.ts
5146
5499
  init_cjs_shims();
5147
- var import_zod29 = require("zod");
5500
+ var import_zod39 = require("zod");
5148
5501
  init_src();
5149
5502
  function isZodSchema(schema) {
5150
- return schema instanceof import_zod29.ZodObject;
5503
+ return schema instanceof import_zod39.ZodObject;
5151
5504
  }
5152
5505
  __name(isZodSchema, "isZodSchema");
5153
5506
  var isNullableProperty2 = /* @__PURE__ */ __name((property) => {
@@ -5159,11 +5512,11 @@ var dropNullableFromRequired2 = /* @__PURE__ */ __name((jsonSchema) => {
5159
5512
  if (!properties || !Array.isArray(required)) return;
5160
5513
  jsonSchema.required = required.filter((key) => !isNullableProperty2(properties[key]));
5161
5514
  }, "dropNullableFromRequired");
5162
- function toJsonSchema(schema) {
5515
+ function toJsonSchema2(schema) {
5163
5516
  if (isZodSchema(schema)) {
5164
5517
  let jsonSchema;
5165
5518
  try {
5166
- jsonSchema = (0, import_zod29.toJSONSchema)(schema, {
5519
+ jsonSchema = (0, import_zod39.toJSONSchema)(schema, {
5167
5520
  target: "openApi3",
5168
5521
  ...jsonSchemaOpts
5169
5522
  });
@@ -5177,7 +5530,7 @@ function toJsonSchema(schema) {
5177
5530
  }
5178
5531
  return schema;
5179
5532
  }
5180
- __name(toJsonSchema, "toJsonSchema");
5533
+ __name(toJsonSchema2, "toJsonSchema");
5181
5534
  var unwrap = /* @__PURE__ */ __name((schema) => {
5182
5535
  let s = schema;
5183
5536
  let t = s?._zod?.def?.type;
@@ -5276,7 +5629,7 @@ var WriteRepository = class {
5276
5629
  return new import_common8.NotFoundException(`${this.config.name} with id ${id} not found`);
5277
5630
  }
5278
5631
  upsertWhere(data) {
5279
- const keys = upsertOnFor(resolveDefinition(this.config));
5632
+ const keys = upsertOnFor2(resolveDefinition2(this.config));
5280
5633
  if (!keys) throw new import_common8.BadRequestException(`${this.config.name} has no upsertOn configured`);
5281
5634
  if (typeof keys === "string") return {
5282
5635
  [keys]: data[keys]
@@ -5567,9 +5920,9 @@ function createCrudRepository(prisma, config, dataSources, configRegistry) {
5567
5920
  if (!model) {
5568
5921
  throw new Error(`Model "${config.model}" not found on the provided PrismaClient. Check the resource config for "${config.name}".`);
5569
5922
  }
5570
- const definition = resolveDefinition(config);
5571
- const listSchema = schemaFor(definition, "findAll");
5572
- const oneSchema = schemaFor(definition, "findOne");
5923
+ const definition = resolveDefinition2(config);
5924
+ const listSchema = schemaFor2(definition, "findAll");
5925
+ const oneSchema = schemaFor2(definition, "findOne");
5573
5926
  const listSelect = listSchema ? toSelectFields(listSchema) : void 0;
5574
5927
  const oneSelect = oneSchema ? toSelectFields(oneSchema) : listSelect;
5575
5928
  const adapter = new PrismaDataSourceAdapter(prisma);
@@ -6018,7 +6371,7 @@ init_cjs_shims();
6018
6371
  var import_common13 = require("@nestjs/common");
6019
6372
  var import_swagger3 = require("@nestjs/swagger");
6020
6373
  var defaultCreate = /* @__PURE__ */ __name((ctx) => {
6021
- if (!isOperationEnabled(ctx.definition, "create")) return null;
6374
+ if (!isOperationEnabled2(ctx.definition, "create")) return null;
6022
6375
  const { cls, config, createSchema, bodyDecorator } = ctx;
6023
6376
  const methodName = "create";
6024
6377
  return {
@@ -6037,7 +6390,7 @@ var defaultCreate = /* @__PURE__ */ __name((ctx) => {
6037
6390
  };
6038
6391
  }, "defaultCreate");
6039
6392
  var childCreate = /* @__PURE__ */ __name((sub) => (ctx) => {
6040
- if (!isOperationEnabled(sub.operations, "create")) return null;
6393
+ if (!isOperationEnabled2(sub.operations, "create")) return null;
6041
6394
  const { cls } = ctx;
6042
6395
  const methodName = `createChild_${sub.childRoute}`;
6043
6396
  const createFn = /* @__PURE__ */ __name(async function(id, body, req) {
@@ -6081,7 +6434,7 @@ init_cjs_shims();
6081
6434
  var import_common14 = require("@nestjs/common");
6082
6435
  var import_swagger4 = require("@nestjs/swagger");
6083
6436
  var defaultDelete = /* @__PURE__ */ __name((ctx) => {
6084
- if (!isOperationEnabled(ctx.definition, "delete")) return null;
6437
+ if (!isOperationEnabled2(ctx.definition, "delete")) return null;
6085
6438
  const { config } = ctx;
6086
6439
  const methodName = "delete";
6087
6440
  const { name } = config;
@@ -6097,7 +6450,7 @@ var defaultDelete = /* @__PURE__ */ __name((ctx) => {
6097
6450
  };
6098
6451
  }, "defaultDelete");
6099
6452
  var deleteChild = /* @__PURE__ */ __name((sub) => (ctx) => {
6100
- if (!isOperationEnabled(sub.operations, "delete")) return null;
6453
+ if (!isOperationEnabled2(sub.operations, "delete")) return null;
6101
6454
  const { cls } = ctx;
6102
6455
  const methodName = `deleteChild_${sub.childRoute}`;
6103
6456
  const deleteFn = /* @__PURE__ */ __name(async function(childId, parentId, req) {
@@ -6275,7 +6628,7 @@ var findAllByParent = /* @__PURE__ */ __name(async (repo, id, childRoute, params
6275
6628
  };
6276
6629
  }, "findAllByParent");
6277
6630
  var defaultFindAll = /* @__PURE__ */ __name((ctx) => {
6278
- if (!isOperationEnabled(ctx.definition, "findAll")) return;
6631
+ if (!isOperationEnabled2(ctx.definition, "findAll")) return;
6279
6632
  const { config } = ctx;
6280
6633
  const lookupLabel = config.lookup?.label;
6281
6634
  const findAll = /* @__PURE__ */ __name(async function(params, q, req) {
@@ -6292,7 +6645,7 @@ var defaultFindAll = /* @__PURE__ */ __name((ctx) => {
6292
6645
  };
6293
6646
  }, "defaultFindAll");
6294
6647
  var childFindAll = /* @__PURE__ */ __name((sub) => (ctx) => {
6295
- if (!isOperationEnabled(sub.operations, "findAll")) return;
6648
+ if (!isOperationEnabled2(sub.operations, "findAll")) return;
6296
6649
  const { cls } = ctx;
6297
6650
  const methodName = `findAllBy_${sub.childRoute}`;
6298
6651
  const findAll = /* @__PURE__ */ __name(async function(params, q, id, req) {
@@ -6332,7 +6685,7 @@ var registerFindAll = /* @__PURE__ */ __name((ctx, sub) => {
6332
6685
  ...listSchema && {
6333
6686
  schema: {
6334
6687
  type: "array",
6335
- items: toJsonSchema(listSchema)
6688
+ items: toJsonSchema2(listSchema)
6336
6689
  }
6337
6690
  }
6338
6691
  })(cls.prototype, methodName, d);
@@ -6345,7 +6698,7 @@ init_cjs_shims();
6345
6698
  var import_common16 = require("@nestjs/common");
6346
6699
  var import_swagger6 = require("@nestjs/swagger");
6347
6700
  var defaultFindOne = /* @__PURE__ */ __name((ctx) => {
6348
- if (!isOperationEnabled(ctx.definition, "findOne")) return null;
6701
+ if (!isOperationEnabled2(ctx.definition, "findOne")) return null;
6349
6702
  const { cls, config } = ctx;
6350
6703
  const methodName = "findOne";
6351
6704
  return {
@@ -6362,7 +6715,7 @@ var defaultFindOne = /* @__PURE__ */ __name((ctx) => {
6362
6715
  };
6363
6716
  }, "defaultFindOne");
6364
6717
  var childFindOne = /* @__PURE__ */ __name((sub) => (ctx) => {
6365
- if (!isOperationEnabled(sub.operations, "findOne")) return null;
6718
+ if (!isOperationEnabled2(sub.operations, "findOne")) return null;
6366
6719
  const { cls } = ctx;
6367
6720
  const methodName = `findOneChild_${sub.childRoute}`;
6368
6721
  const findOneFn = /* @__PURE__ */ __name(async function(parentId, childId, req) {
@@ -6398,7 +6751,7 @@ var registerFindOne = /* @__PURE__ */ __name((ctx, sub) => {
6398
6751
  status: 200,
6399
6752
  description: `The ${name}`,
6400
6753
  ...ctx.oneSchema && {
6401
- schema: toJsonSchema(ctx.oneSchema)
6754
+ schema: toJsonSchema2(ctx.oneSchema)
6402
6755
  }
6403
6756
  })(cls.prototype, methodName, d);
6404
6757
  (0, import_swagger6.ApiNotFoundResponse)({
@@ -6413,7 +6766,7 @@ init_cjs_shims();
6413
6766
  var import_common17 = require("@nestjs/common");
6414
6767
  var import_swagger7 = require("@nestjs/swagger");
6415
6768
  var defaultPatch = /* @__PURE__ */ __name((ctx) => {
6416
- if (!isOperationEnabled(ctx.definition, "patch")) return null;
6769
+ if (!isOperationEnabled2(ctx.definition, "patch")) return null;
6417
6770
  const { cls, config, patchSchema, bodyDecorator } = ctx;
6418
6771
  const methodName = "patch";
6419
6772
  return {
@@ -6431,7 +6784,7 @@ var defaultPatch = /* @__PURE__ */ __name((ctx) => {
6431
6784
  };
6432
6785
  }, "defaultPatch");
6433
6786
  var childPatch = /* @__PURE__ */ __name((sub) => (ctx) => {
6434
- if (!isOperationEnabled(sub.operations, "patch")) return null;
6787
+ if (!isOperationEnabled2(sub.operations, "patch")) return null;
6435
6788
  const { cls } = ctx;
6436
6789
  const methodName = `patchChild_${sub.childRoute}`;
6437
6790
  const patchFn = /* @__PURE__ */ __name(async function(_id, childId, body, req) {
@@ -6482,26 +6835,26 @@ init_dev_mode();
6482
6835
 
6483
6836
  // src/lib/crud/resource/PatchResourceJson.schema.ts
6484
6837
  init_cjs_shims();
6485
- var import_zod30 = require("zod");
6486
- var FieldVariantPatchSchema = import_zod30.z.object({
6487
- type: import_zod30.z.string().nullable().optional(),
6488
- format: import_zod30.z.string().nullable().optional(),
6489
- resource: import_zod30.z.string().nullable().optional(),
6490
- position: import_zod30.z.number().nullable().optional(),
6491
- options: import_zod30.z.record(import_zod30.z.string(), import_zod30.z.unknown().nullable()).optional()
6838
+ var import_zod40 = require("zod");
6839
+ var FieldVariantPatchSchema = import_zod40.z.object({
6840
+ type: import_zod40.z.string().nullable().optional(),
6841
+ format: import_zod40.z.string().nullable().optional(),
6842
+ resource: import_zod40.z.string().nullable().optional(),
6843
+ position: import_zod40.z.number().nullable().optional(),
6844
+ options: import_zod40.z.record(import_zod40.z.string(), import_zod40.z.unknown().nullable()).optional()
6492
6845
  }).partial();
6493
- var PatchColumnSchema = import_zod30.z.object({
6494
- label: import_zod30.z.string().optional(),
6495
- column: import_zod30.z.string().optional(),
6496
- hiddenInTable: import_zod30.z.boolean().optional(),
6497
- hiddenInForm: import_zod30.z.boolean().optional(),
6498
- hiddenInView: import_zod30.z.boolean().optional(),
6846
+ var PatchColumnSchema = import_zod40.z.object({
6847
+ label: import_zod40.z.string().optional(),
6848
+ column: import_zod40.z.string().optional(),
6849
+ hiddenInTable: import_zod40.z.boolean().optional(),
6850
+ hiddenInForm: import_zod40.z.boolean().optional(),
6851
+ hiddenInView: import_zod40.z.boolean().optional(),
6499
6852
  fieldInput: FieldVariantPatchSchema.optional(),
6500
6853
  fieldView: FieldVariantPatchSchema.optional(),
6501
6854
  fieldTable: FieldVariantPatchSchema.optional()
6502
6855
  }).partial();
6503
- var PatchResourceJsonSchema = import_zod30.z.object({
6504
- columns: import_zod30.z.record(import_zod30.z.string(), PatchColumnSchema)
6856
+ var PatchResourceJsonSchema = import_zod40.z.object({
6857
+ columns: import_zod40.z.record(import_zod40.z.string(), PatchColumnSchema)
6505
6858
  });
6506
6859
 
6507
6860
  // src/lib/crud/resource/WriteResourceJson.ts
@@ -6572,6 +6925,12 @@ var writeRawResourceJson = /* @__PURE__ */ __name((jsonPath, raw) => {
6572
6925
  // src/lib/crud/operations/payload-builders.ts
6573
6926
  init_cjs_shims();
6574
6927
  init_src();
6928
+ var pickExtensions = /* @__PURE__ */ __name((config) => Object.fromEntries([
6929
+ ...getResourceExtensions().keys()
6930
+ ].filter((k) => config[k] !== void 0).map((k) => [
6931
+ k,
6932
+ config[k]
6933
+ ])), "pickExtensions");
6575
6934
  var resolveEnvPlaceholders = /* @__PURE__ */ __name((value) => value.replace(/\{env\.([^}]+)\}/g, (match, varName) => process.env[varName] ?? match), "resolveEnvPlaceholders");
6576
6935
  var RESOURCE_OPS = [
6577
6936
  "findAll",
@@ -6597,22 +6956,22 @@ var OP_SUFFIX = {
6597
6956
  patch: "/{id}",
6598
6957
  delete: "/{id}"
6599
6958
  };
6600
- var buildResourceOperations = /* @__PURE__ */ __name((definition, baseUri) => Object.fromEntries(RESOURCE_OPS.filter((op) => isOperationEnabled(definition, op)).map((op) => [
6959
+ var buildResourceOperations = /* @__PURE__ */ __name((definition, baseUri) => Object.fromEntries(RESOURCE_OPS.filter((op) => isOperationEnabled2(definition, op)).map((op) => [
6601
6960
  op,
6602
6961
  {
6603
6962
  uri: `${baseUri}${OP_SUFFIX[op]}`,
6604
6963
  method: OP_METHOD[op]
6605
6964
  }
6606
6965
  ])), "buildResourceOperations");
6607
- var buildDefinitionPayload = /* @__PURE__ */ __name((config) => {
6966
+ var buildDefinitionPayload2 = /* @__PURE__ */ __name((config) => {
6608
6967
  const { route, name, tag, idType = "string" } = config;
6609
- const definition = resolveDefinition(config);
6610
- const listSchema = schemaFor(definition, "findAll");
6611
- const oneSchema = schemaFor(definition, "findOne") ?? listSchema;
6612
- const createSchema = schemaFor(definition, "create");
6613
- const updateSchema = schemaFor(definition, "update");
6614
- const patchSchema = schemaFor(definition, "patch");
6615
- const upsertSchema = schemaFor(definition, "upsert") ?? createSchema;
6968
+ const definition = resolveDefinition2(config);
6969
+ const listSchema = schemaFor2(definition, "findAll");
6970
+ const oneSchema = schemaFor2(definition, "findOne") ?? listSchema;
6971
+ const createSchema = schemaFor2(definition, "create");
6972
+ const updateSchema = schemaFor2(definition, "update");
6973
+ const patchSchema = schemaFor2(definition, "patch");
6974
+ const upsertSchema = schemaFor2(definition, "upsert") ?? createSchema;
6616
6975
  const operations = [
6617
6976
  "findAll",
6618
6977
  "findOne",
@@ -6621,47 +6980,45 @@ var buildDefinitionPayload = /* @__PURE__ */ __name((config) => {
6621
6980
  "patch",
6622
6981
  "upsert",
6623
6982
  "delete"
6624
- ].filter((op) => isOperationEnabled(definition, op));
6983
+ ].filter((op) => isOperationEnabled2(definition, op));
6625
6984
  return {
6626
6985
  name,
6627
6986
  route,
6628
6987
  idType,
6629
6988
  tag,
6630
6989
  operations,
6631
- upsertOn: upsertOnFor(definition),
6990
+ upsertOn: upsertOnFor2(definition),
6632
6991
  display: config.display,
6633
6992
  schemas: {
6634
6993
  ...listSchema && {
6635
- findAll: toJsonSchema(listSchema)
6994
+ findAll: toJsonSchema2(listSchema)
6636
6995
  },
6637
6996
  ...oneSchema && {
6638
- findOne: toJsonSchema(oneSchema)
6997
+ findOne: toJsonSchema2(oneSchema)
6639
6998
  },
6640
6999
  ...createSchema && {
6641
- create: toJsonSchema(createSchema)
7000
+ create: toJsonSchema2(createSchema)
6642
7001
  },
6643
7002
  ...updateSchema && {
6644
- update: toJsonSchema(updateSchema)
7003
+ update: toJsonSchema2(updateSchema)
6645
7004
  },
6646
7005
  ...patchSchema && {
6647
- patch: toJsonSchema(patchSchema)
7006
+ patch: toJsonSchema2(patchSchema)
6648
7007
  },
6649
- ...isOperationEnabled(definition, "upsert") && upsertSchema ? {
6650
- upsert: toJsonSchema(upsertSchema)
7008
+ ...isOperationEnabled2(definition, "upsert") && upsertSchema ? {
7009
+ upsert: toJsonSchema2(upsertSchema)
6651
7010
  } : {}
6652
7011
  },
6653
- ...config.extensions && {
6654
- extensions: config.extensions
6655
- }
7012
+ ...pickExtensions(config)
6656
7013
  };
6657
7014
  }, "buildDefinitionPayload");
6658
- var buildResourceJsonPayload = /* @__PURE__ */ __name((config, baseUrl) => {
7015
+ var buildResourceJsonPayload2 = /* @__PURE__ */ __name((config, baseUrl) => {
6659
7016
  const { name, route } = config;
6660
- const definition = resolveDefinition(config);
7017
+ const definition = resolveDefinition2(config);
6661
7018
  const uri = `${baseUrl}/${route}`;
6662
7019
  const operations = Object.fromEntries(RESOURCE_OPS.map((op) => [
6663
7020
  op,
6664
- isOperationEnabled(definition, op)
7021
+ isOperationEnabled2(definition, op)
6665
7022
  ]));
6666
7023
  operations.lookup = `${uri}?q={text}`;
6667
7024
  const form = config.views?.["form"];
@@ -6670,13 +7027,11 @@ var buildResourceJsonPayload = /* @__PURE__ */ __name((config, baseUrl) => {
6670
7027
  ui: form.ui_schema
6671
7028
  } : null;
6672
7029
  return {
6673
- id: name,
7030
+ id: config.id ?? route,
6674
7031
  uri,
6675
7032
  operations,
6676
7033
  schema,
6677
- ...config.extensions && {
6678
- extensions: config.extensions
6679
- }
7034
+ ...pickExtensions(config)
6680
7035
  };
6681
7036
  }, "buildResourceJsonPayload");
6682
7037
  var _resolveActions = /* @__PURE__ */ __name((baseUrl, actions) => {
@@ -6699,12 +7054,12 @@ var resolveActions = /* @__PURE__ */ __name((baseUrl, actions) => {
6699
7054
  "{id}"
6700
7055
  ], actions);
6701
7056
  }, "resolveActions");
6702
- var buildViewsPayload = /* @__PURE__ */ __name((config, baseUrl) => {
7057
+ var buildViewsPayload2 = /* @__PURE__ */ __name((config, baseUrl) => {
6703
7058
  if (!config.views || !Object.keys(config.views).length) return void 0;
6704
- const definition = resolveDefinition(config);
7059
+ const definition = resolveDefinition2(config);
6705
7060
  const baseUri = config.parent ? `${baseUrl}/${config.parent.route}/{${config.parent.param}}/${config.route}` : `${baseUrl}/${config.route}`;
6706
7061
  const operations = buildResourceOperations(definition, baseUri);
6707
- if (isOperationEnabled(definition, "findAll")) {
7062
+ if (isOperationEnabled2(definition, "findAll")) {
6708
7063
  operations["lookup"] = `${baseUri}?q={text}`;
6709
7064
  }
6710
7065
  const schemas = Object.fromEntries(Object.entries(config.views).map(([key, v]) => [
@@ -6719,7 +7074,7 @@ var buildViewsPayload = /* @__PURE__ */ __name((config, baseUrl) => {
6719
7074
  ]));
6720
7075
  const baseAction = `${baseUri}${config.route}`;
6721
7076
  return {
6722
- id: config.name,
7077
+ id: config.id ?? config.route,
6723
7078
  name: config.name,
6724
7079
  route: config.route,
6725
7080
  uri: baseUri,
@@ -6734,9 +7089,7 @@ var buildViewsPayload = /* @__PURE__ */ __name((config, baseUrl) => {
6734
7089
  schemas,
6735
7090
  actions: resolveActions(baseAction, config.actions),
6736
7091
  tableActions: resolveActions(baseAction, config.tableActions),
6737
- ...config.extensions && {
6738
- extensions: config.extensions
6739
- }
7092
+ ...pickExtensions(config)
6740
7093
  };
6741
7094
  }, "buildViewsPayload");
6742
7095
  var buildSubResourceViewsPayload = /* @__PURE__ */ __name((config, sub, baseUrl) => {
@@ -6798,13 +7151,13 @@ var import_node_path9 = require("path");
6798
7151
  var registerDefinitionEndpoint = /* @__PURE__ */ __name((ctx) => {
6799
7152
  const { cls, config, schemaEnricher } = ctx;
6800
7153
  const { route, name } = config;
6801
- const definitionPayload = buildDefinitionPayload(config);
7154
+ const definitionPayload = buildDefinitionPayload2(config);
6802
7155
  def(cls, "getDefinition", async function() {
6803
7156
  const language = getRequestLanguage();
6804
7157
  let payload = definitionPayload;
6805
7158
  if (IS_DEV || language) {
6806
7159
  const fresh = await this.configRegistry.getByRoute(route, language);
6807
- if (fresh) payload = buildDefinitionPayload(fresh);
7160
+ if (fresh) payload = buildDefinitionPayload2(fresh);
6808
7161
  }
6809
7162
  if (!schemaEnricher) return payload;
6810
7163
  return {
@@ -6829,13 +7182,13 @@ var registerDefinitionEndpoint = /* @__PURE__ */ __name((ctx) => {
6829
7182
  var registerResourceJsonEndpoint = /* @__PURE__ */ __name((ctx) => {
6830
7183
  const { cls, config, baseUrl, schemaEnricher } = ctx;
6831
7184
  const { route, name } = config;
6832
- const resourceJsonPayload = buildResourceJsonPayload(config, baseUrl);
7185
+ const resourceJsonPayload = buildResourceJsonPayload2(config, baseUrl);
6833
7186
  def(cls, "getResourceJson", async function() {
6834
7187
  const language = getRequestLanguage();
6835
7188
  let payload = resourceJsonPayload;
6836
7189
  if (IS_DEV || language) {
6837
7190
  const fresh = await this.configRegistry.getByRoute(route, language);
6838
- if (fresh) payload = buildResourceJsonPayload(fresh, baseUrl);
7191
+ if (fresh) payload = buildResourceJsonPayload2(fresh, baseUrl);
6839
7192
  }
6840
7193
  if (!schemaEnricher) return payload;
6841
7194
  return {
@@ -6983,7 +7336,7 @@ init_dev_mode();
6983
7336
  var defaultSchemas = /* @__PURE__ */ __name((ctx) => {
6984
7337
  const { config, baseUrl, schemaEnricher } = ctx;
6985
7338
  const { route, name } = config;
6986
- const viewsPayload = buildViewsPayload(config, baseUrl);
7339
+ const viewsPayload = buildViewsPayload2(config, baseUrl);
6987
7340
  return {
6988
7341
  route: "schemas",
6989
7342
  methodName: "getSchemas",
@@ -6993,7 +7346,7 @@ var defaultSchemas = /* @__PURE__ */ __name((ctx) => {
6993
7346
  let payload = viewsPayload;
6994
7347
  if (IS_DEV || language) {
6995
7348
  const fresh = await this.configRegistry.getByRoute(route, language);
6996
- if (fresh) payload = buildViewsPayload(fresh, baseUrl) ?? viewsPayload;
7349
+ if (fresh) payload = buildViewsPayload2(fresh, baseUrl) ?? viewsPayload;
6997
7350
  }
6998
7351
  if (!payload || !schemaEnricher) return payload;
6999
7352
  return {
@@ -7048,7 +7401,7 @@ init_cjs_shims();
7048
7401
  var import_common20 = require("@nestjs/common");
7049
7402
  var import_swagger10 = require("@nestjs/swagger");
7050
7403
  var defaultUpdate = /* @__PURE__ */ __name((ctx) => {
7051
- if (!isOperationEnabled(ctx.definition, "update")) return null;
7404
+ if (!isOperationEnabled2(ctx.definition, "update")) return null;
7052
7405
  const { cls, config, updateSchema, bodyDecorator } = ctx;
7053
7406
  const methodName = "update";
7054
7407
  return {
@@ -7066,7 +7419,7 @@ var defaultUpdate = /* @__PURE__ */ __name((ctx) => {
7066
7419
  };
7067
7420
  }, "defaultUpdate");
7068
7421
  var childUpdate = /* @__PURE__ */ __name((sub) => (ctx) => {
7069
- if (!isOperationEnabled(sub.operations, "update")) return null;
7422
+ if (!isOperationEnabled2(sub.operations, "update")) return null;
7070
7423
  const { cls } = ctx;
7071
7424
  const methodName = `updateChild_${sub.childRoute}`;
7072
7425
  const updateFn = /* @__PURE__ */ __name(async function(_id, childId, body, req) {
@@ -7141,15 +7494,15 @@ var registerEndpoint = /* @__PURE__ */ __name((ctx, sub) => {
7141
7494
  // src/lib/crud/crud-controller.factory.ts
7142
7495
  function createCrudController(config, baseUrl, moduleDefaultSecurity, securityEnabled = false, prefix, schemaEnricher) {
7143
7496
  const { route, name, tag, idType = "string" } = config;
7144
- const definition = resolveDefinition(config);
7145
- const listSchema = schemaFor(definition, "findAll");
7146
- const oneSchema = schemaFor(definition, "findOne") ?? listSchema;
7147
- const createSchema = schemaFor(definition, "create");
7148
- const updateSchema = schemaFor(definition, "update");
7149
- const explicitPatchSchema = schemaFor(definition, "patch");
7497
+ const definition = resolveDefinition2(config);
7498
+ const listSchema = schemaFor2(definition, "findAll");
7499
+ const oneSchema = schemaFor2(definition, "findOne") ?? listSchema;
7500
+ const createSchema = schemaFor2(definition, "create");
7501
+ const updateSchema = schemaFor2(definition, "update");
7502
+ const explicitPatchSchema = schemaFor2(definition, "patch");
7150
7503
  const patchSchema = explicitPatchSchema ?? (updateSchema && isZodSchema(updateSchema) ? updateSchema.partial() : void 0) ?? updateSchema;
7151
- const upsertSchema = schemaFor(definition, "upsert") ?? createSchema;
7152
- if (isOperationEnabled(definition, "upsert") && !upsertOnFor(definition)) {
7504
+ const upsertSchema = schemaFor2(definition, "upsert") ?? createSchema;
7505
+ if (isOperationEnabled2(definition, "upsert") && !upsertOnFor2(definition)) {
7153
7506
  throw new Error(`Resource "${name}" declares 'upsert' but no upsertOn`);
7154
7507
  }
7155
7508
  const bodyDecorator = /* @__PURE__ */ __name((schema, options) => {
@@ -7954,13 +8307,13 @@ var resolveFromRoot = /* @__PURE__ */ __name((root, p) => (0, import_node_path11
7954
8307
 
7955
8308
  // ../crouton-codegen/src/scaffold.ts
7956
8309
  init_cjs_shims();
7957
- var import_zod31 = require("zod");
8310
+ var import_zod41 = require("zod");
7958
8311
  init_src();
7959
8312
  var import_promises5 = require("fs/promises");
7960
8313
  var import_node_path12 = require("path");
7961
8314
  var ScallfoldDatasourceSchema = DataSourceShape.extend({
7962
8315
  /** Folder name under `dataSourcesDir`. */
7963
- folder: import_zod31.z.string().default("default")
8316
+ folder: import_zod41.z.string().default("default")
7964
8317
  }).transform(transformDataSource);
7965
8318
 
7966
8319
  // ../crouton-codegen/src/datasource-scaffold.ts
@@ -8849,12 +9202,12 @@ init_cjs_shims();
8849
9202
 
8850
9203
  // src/lib/crud/enum-registry/enum-registry.types.ts
8851
9204
  init_cjs_shims();
8852
- var import_zod32 = require("zod");
8853
- var EnumEntrySchema = import_zod32.z.object({
8854
- value: import_zod32.z.unknown(),
8855
- label: import_zod32.z.string()
9205
+ var import_zod42 = require("zod");
9206
+ var EnumEntrySchema2 = import_zod42.z.object({
9207
+ value: import_zod42.z.unknown(),
9208
+ label: import_zod42.z.string()
8856
9209
  });
8857
- var EnumRegistrySchema = import_zod32.z.record(import_zod32.z.string(), import_zod32.z.array(EnumEntrySchema)).default({});
9210
+ var EnumRegistrySchema2 = import_zod42.z.record(import_zod42.z.string(), import_zod42.z.array(EnumEntrySchema2)).default({});
8858
9211
 
8859
9212
  // src/lib/crud/enum-registry/enum-registry.loader.ts
8860
9213
  init_cjs_shims();
@@ -8876,17 +9229,17 @@ var loadEnumRegistry = /* @__PURE__ */ __name((startDir, enumsFile) => {
8876
9229
  dir = parent;
8877
9230
  }
8878
9231
  }
8879
- if (!file || !(0, import_node_fs8.existsSync)(file)) return EnumRegistrySchema.parse(void 0);
9232
+ if (!file || !(0, import_node_fs8.existsSync)(file)) return EnumRegistrySchema2.parse(void 0);
8880
9233
  try {
8881
- return EnumRegistrySchema.parse(JSON.parse((0, import_node_fs8.readFileSync)(file, "utf-8")));
9234
+ return EnumRegistrySchema2.parse(JSON.parse((0, import_node_fs8.readFileSync)(file, "utf-8")));
8882
9235
  } catch {
8883
- return EnumRegistrySchema.parse(void 0);
9236
+ return EnumRegistrySchema2.parse(void 0);
8884
9237
  }
8885
9238
  }, "loadEnumRegistry");
8886
9239
 
8887
9240
  // src/lib/crud/enum-registry/enum-registry.injector.ts
8888
9241
  init_cjs_shims();
8889
- var injectEnumValues = /* @__PURE__ */ __name((columns, enums) => {
9242
+ var injectEnumValues2 = /* @__PURE__ */ __name((columns, enums) => {
8890
9243
  if (!columns) return;
8891
9244
  for (const col of columns) {
8892
9245
  if (!col.enum) continue;
@@ -8951,7 +9304,7 @@ var upsertOp = /* @__PURE__ */ __name((entry, schema) => {
8951
9304
  }
8952
9305
  return void 0;
8953
9306
  }, "upsertOp");
8954
- var buildResourceDefinitions = /* @__PURE__ */ __name((schema, operations, enrichedColumns) => {
9307
+ var buildResourceDefinitions2 = /* @__PURE__ */ __name((schema, operations, enrichedColumns) => {
8955
9308
  const picked = pickByColumns(schema, enrichedColumns);
8956
9309
  const createSchema = pickByColumns(schema, enrichedColumns, (c) => !c.idField && c.createable !== false);
8957
9310
  const updateSchema = pickByColumns(schema, enrichedColumns, (c) => !c.idField && c.updateable !== false);
@@ -8986,9 +9339,9 @@ init_cjs_shims();
8986
9339
 
8987
9340
  // src/lib/crud/adapter/relation-type.ts
8988
9341
  init_cjs_shims();
8989
- var import_zod33 = require("zod");
9342
+ var import_zod43 = require("zod");
8990
9343
  var unwrapZodType = /* @__PURE__ */ __name((type) => {
8991
- if (type instanceof import_zod33.ZodOptional || type instanceof import_zod33.ZodNullable) {
9344
+ if (type instanceof import_zod43.ZodOptional || type instanceof import_zod43.ZodNullable) {
8992
9345
  return unwrapZodType(type.unwrap());
8993
9346
  }
8994
9347
  return type;
@@ -8998,7 +9351,7 @@ var deriveRelationType = /* @__PURE__ */ __name((schema, columnId) => {
8998
9351
  const field = schema.shape[columnId];
8999
9352
  if (!field) return void 0;
9000
9353
  const inner = unwrapZodType(field);
9001
- return inner instanceof import_zod33.ZodArray ? "oneToMany" : "manyToOne";
9354
+ return inner instanceof import_zod43.ZodArray ? "oneToMany" : "manyToOne";
9002
9355
  }, "deriveRelationType");
9003
9356
  var deriveRelationTypeFromColumns = /* @__PURE__ */ __name((col, cols) => {
9004
9357
  const base = col.column ?? col.id;
@@ -9008,7 +9361,7 @@ var deriveRelationTypeFromColumns = /* @__PURE__ */ __name((col, cols) => {
9008
9361
  ]);
9009
9362
  return cols.some((c) => fkNames.has(c.id)) ? "manyToOne" : "oneToMany";
9010
9363
  }, "deriveRelationTypeFromColumns");
9011
- var enrichRelationTypes = /* @__PURE__ */ __name((columns, schema) => {
9364
+ var enrichRelationTypes2 = /* @__PURE__ */ __name((columns, schema) => {
9012
9365
  if (!schema) return columns;
9013
9366
  return columns.map((col) => {
9014
9367
  const fi = col.fieldInput;
@@ -9029,7 +9382,7 @@ var enrichRelationTypes = /* @__PURE__ */ __name((columns, schema) => {
9029
9382
  }, "enrichRelationTypes");
9030
9383
 
9031
9384
  // src/lib/crud/adapter/column-enrichment.ts
9032
- var enrichActionColumns = /* @__PURE__ */ __name((columns, parentRoute, subResources, baseUrl) => {
9385
+ var enrichActionColumns2 = /* @__PURE__ */ __name((columns, parentRoute, subResources, baseUrl) => {
9033
9386
  if (!columns) return columns;
9034
9387
  const base = baseUrl ?? "";
9035
9388
  return columns.map((col) => {
@@ -9093,7 +9446,7 @@ var enrichNestedRelationColumns = /* @__PURE__ */ __name((cols, dir, baseUrl) =>
9093
9446
  };
9094
9447
  });
9095
9448
  }, "enrichNestedRelationColumns");
9096
- var enrichIncludeWithSort = /* @__PURE__ */ __name((include, columns) => {
9449
+ var enrichIncludeWithSort2 = /* @__PURE__ */ __name((include, columns) => {
9097
9450
  if (!include?.length) return include;
9098
9451
  return include.map((entry) => {
9099
9452
  const relationName = typeof entry === "string" ? entry : entry.relation;
@@ -9145,8 +9498,8 @@ var buildSubResources = /* @__PURE__ */ __name((columns, parentRoute, parentMode
9145
9498
  const childRoute = childJson.route ?? resourcePath.replace(/^\.\.?\//, "").replace(/\/resource\.json$/, "").replace(/\.resource$/, "");
9146
9499
  const rawChildColumns = childJson?.columns;
9147
9500
  const expandedChildColumns = rawChildColumns ? expandExtendColumns(rawChildColumns, childDir) : void 0;
9148
- const childColumns = applyRelationFormatDefault(expandedChildColumns) ?? expandedChildColumns;
9149
- injectEnumValues(childColumns, enums);
9501
+ const childColumns = applyRelationFormatDefault2(expandedChildColumns) ?? expandedChildColumns;
9502
+ injectEnumValues2(childColumns, enums);
9150
9503
  const enrichedChildColumns = enrichNestedRelationColumns(childColumns, childDir, baseUrl);
9151
9504
  const autoIncludes = (enrichedChildColumns ?? []).filter((col) => col.fieldInput?.format === "relation" && (col.fieldInput.relationType ?? deriveRelationTypeFromColumns(col, enrichedChildColumns)) === "manyToOne").map((col) => col.fieldInput?.relation ?? col.id);
9152
9505
  const explicitIncludes = childJson?.include ?? [];
@@ -9226,8 +9579,8 @@ var buildSubResources = /* @__PURE__ */ __name((columns, parentRoute, parentMode
9226
9579
  return {};
9227
9580
  })()
9228
9581
  },
9229
- ...buildValueLabelColumns(childColumns).length && {
9230
- valueLabelColumns: buildValueLabelColumns(childColumns)
9582
+ ...buildValueLabelColumns2(childColumns).length && {
9583
+ valueLabelColumns: buildValueLabelColumns2(childColumns)
9231
9584
  },
9232
9585
  relationType: c.fieldInput?.relationType ?? deriveRelationTypeFromColumns(c, columns)
9233
9586
  };
@@ -9235,13 +9588,19 @@ var buildSubResources = /* @__PURE__ */ __name((columns, parentRoute, parentMode
9235
9588
  }, "buildSubResources");
9236
9589
 
9237
9590
  // src/lib/crud/adapter/json-adapter.ts
9591
+ var pickExtensions2 = /* @__PURE__ */ __name((obj) => Object.fromEntries([
9592
+ ...getResourceExtensions().keys()
9593
+ ].filter((k) => obj[k] !== void 0).map((k) => [
9594
+ k,
9595
+ obj[k]
9596
+ ])), "pickExtensions");
9238
9597
  var fromJson = /* @__PURE__ */ __name((json, schema, hooks, dirPath, baseUrl, actions, tableActions, enums = {}, repository) => {
9239
9598
  const isCustom = json.kind === "custom";
9240
9599
  const rawColumns = expandExtendColumns(json.columns, dirPath);
9241
- const columns = enrichRelationTypes(applyRelationFormatDefault(rawColumns) ?? rawColumns, schema);
9242
- injectEnumValues(columns, enums);
9600
+ const columns = enrichRelationTypes2(applyRelationFormatDefault2(rawColumns) ?? rawColumns, schema);
9601
+ injectEnumValues2(columns, enums);
9243
9602
  const subResources = isCustom ? [] : buildSubResources(columns, json.route, json.model ?? "", dirPath, enums, baseUrl);
9244
- const enrichedColumns = resolveColumnFieldVariants(enrichResourceRefColumns(enrichActionColumns(columns, json.route, subResources, baseUrl), dirPath, baseUrl) ?? columns);
9603
+ const enrichedColumns = resolveColumnFieldVariants2(enrichResourceRefColumns(enrichActionColumns2(columns, json.route, subResources, baseUrl), dirPath, baseUrl) ?? columns);
9245
9604
  const calculatedColumns = json.calculatedColumns ?? [];
9246
9605
  let views = isCustom ? buildViewsFromColumnTypes(enrichedColumns) : buildViews(schema, enrichedColumns);
9247
9606
  if (views && calculatedColumns.length) {
@@ -9257,8 +9616,8 @@ var fromJson = /* @__PURE__ */ __name((json, schema, hooks, dirPath, baseUrl, ac
9257
9616
  }
9258
9617
  }
9259
9618
  const lookup = buildLookup(enrichedColumns);
9260
- const enrichedInclude = enrichIncludeWithSort(json.include, enrichedColumns);
9261
- const definition = buildResourceDefinitions(schema, json.operations, enrichedColumns);
9619
+ const enrichedInclude = enrichIncludeWithSort2(json.include, enrichedColumns);
9620
+ const definition = buildResourceDefinitions2(schema, json.operations, enrichedColumns);
9262
9621
  return {
9263
9622
  ...json,
9264
9623
  name: json.name,
@@ -9307,12 +9666,10 @@ var fromJson = /* @__PURE__ */ __name((json, schema, hooks, dirPath, baseUrl, ac
9307
9666
  ...json.modalSize && {
9308
9667
  modalSize: json.modalSize
9309
9668
  },
9310
- ...buildValueLabelColumns(enrichedColumns).length && {
9311
- valueLabelColumns: buildValueLabelColumns(enrichedColumns)
9669
+ ...buildValueLabelColumns2(enrichedColumns).length && {
9670
+ valueLabelColumns: buildValueLabelColumns2(enrichedColumns)
9312
9671
  },
9313
- ...json.extensions && {
9314
- extensions: json.extensions
9315
- }
9672
+ ...pickExtensions2(json)
9316
9673
  };
9317
9674
  }, "fromJson");
9318
9675
  var buildLookup = /* @__PURE__ */ __name((columns) => {
@@ -9395,6 +9752,45 @@ var migrateResourceJsonFile = /* @__PURE__ */ __name((jsonPath, opts) => {
9395
9752
  }
9396
9753
  }, "migrateResourceJsonFile");
9397
9754
 
9755
+ // src/lib/crud/resource/resource-config.validator.ts
9756
+ init_cjs_shims();
9757
+ var ALL_OPS = [
9758
+ "findAll",
9759
+ "findOne",
9760
+ "create",
9761
+ "update",
9762
+ "patch",
9763
+ "upsert",
9764
+ "delete"
9765
+ ];
9766
+ var validateResourceConfig = /* @__PURE__ */ __name((config, opts) => {
9767
+ const errors = [];
9768
+ const warnings = [];
9769
+ const definition = resolveDefinition2(config);
9770
+ const enabledOps = ALL_OPS.filter((op) => isOperationEnabled2(definition, op));
9771
+ if (enabledOps.length === 0) {
9772
+ warnings.push("All operations are disabled \u2014 this resource serves nothing.");
9773
+ }
9774
+ if (config.kind === "custom") {
9775
+ if (config.database) {
9776
+ warnings.push('"database" is set alongside kind: "custom" \u2014 it selects the client injected as ctx.prisma, but data access still comes from repository.ts.');
9777
+ }
9778
+ if (isOperationEnabled2(definition, "upsert")) {
9779
+ warnings.push('"upsert" is enabled but custom resources do not register a PUT handler \u2014 disable it in operations or implement it yourself.');
9780
+ }
9781
+ const repoError = validateCustomRepository(config, config.repository);
9782
+ if (repoError) errors.push(repoError);
9783
+ } else {
9784
+ if (opts?.repositoryFileExistsOnDisk) {
9785
+ warnings.push('repository.ts is present on a prisma resource and will be ignored \u2014 set kind: "custom" if you want to use it for data access.');
9786
+ }
9787
+ }
9788
+ return {
9789
+ errors,
9790
+ warnings
9791
+ };
9792
+ }, "validateResourceConfig");
9793
+
9398
9794
  // src/lib/crud/loader/index.ts
9399
9795
  var import_node_fs10 = require("fs");
9400
9796
  var import_node_path18 = require("path");
@@ -9457,10 +9853,35 @@ var loadResourceConfigsFromDir = /* @__PURE__ */ __name(async (dirPath, baseUrl,
9457
9853
  });
9458
9854
  continue;
9459
9855
  }
9856
+ const errorsBeforeRepo = resourceLoadErrorsRegistry.getAll().length;
9460
9857
  const repository = json.kind === "custom" ? await loadCustomRepository(basePath, json.name) : void 0;
9858
+ const repositoryImportFailed = resourceLoadErrorsRegistry.getAll().length > errorsBeforeRepo;
9461
9859
  const actions = await loadActions(json.actions ?? [], basePath, "row");
9462
9860
  const tableActions = await loadActions(json.tableActions ?? [], basePath, "table");
9463
9861
  const config = fromJson(json, schema, hooks, basePath, baseUrl, actions, tableActions, enums, repository);
9862
+ if (repositoryImportFailed) continue;
9863
+ const repositoryFileExistsOnDisk = json.kind !== "custom" && !!findModule(basePath, "repository");
9864
+ const { errors, warnings } = validateResourceConfig(config, {
9865
+ repositoryFileExistsOnDisk
9866
+ });
9867
+ if (errors.length > 0) {
9868
+ for (const error of errors) {
9869
+ resourceLoadErrorsRegistry.record({
9870
+ name: dir,
9871
+ path: jsonFile,
9872
+ error
9873
+ });
9874
+ }
9875
+ continue;
9876
+ }
9877
+ for (const warning of warnings) {
9878
+ resourceLoadReportRegistry.record({
9879
+ state: "warning",
9880
+ name: config.name,
9881
+ path: jsonFile,
9882
+ warning
9883
+ });
9884
+ }
9464
9885
  await loadSubResourceHooks(config.subResources ?? [], basePath);
9465
9886
  await loadSubResourceRepositories(config.subResources ?? [], config.name);
9466
9887
  onResourceDir?.(config.route, basePath);
@@ -9470,7 +9891,14 @@ var loadResourceConfigsFromDir = /* @__PURE__ */ __name(async (dirPath, baseUrl,
9470
9891
  const tsFile = findModule(basePath, "resource");
9471
9892
  if (tsFile) {
9472
9893
  const config = await importDefault(tsFile);
9473
- if (!config) continue;
9894
+ if (!config) {
9895
+ resourceLoadErrorsRegistry.record({
9896
+ name: dir,
9897
+ path: tsFile,
9898
+ error: "resource.ts has no default export \u2014 add `export default { name, route, ... }`."
9899
+ });
9900
+ continue;
9901
+ }
9474
9902
  if (config.draft) {
9475
9903
  resourceLoadReportRegistry.record({
9476
9904
  state: "draft",
@@ -9480,10 +9908,30 @@ var loadResourceConfigsFromDir = /* @__PURE__ */ __name(async (dirPath, baseUrl,
9480
9908
  });
9481
9909
  continue;
9482
9910
  }
9483
- configs.push(hooks ? {
9911
+ const merged = hooks ? {
9484
9912
  ...config,
9485
9913
  hooks
9486
- } : config);
9914
+ } : config;
9915
+ const { errors, warnings } = validateResourceConfig(merged);
9916
+ if (errors.length > 0) {
9917
+ for (const error of errors) {
9918
+ resourceLoadErrorsRegistry.record({
9919
+ name: dir,
9920
+ path: tsFile,
9921
+ error
9922
+ });
9923
+ }
9924
+ continue;
9925
+ }
9926
+ for (const warning of warnings) {
9927
+ resourceLoadReportRegistry.record({
9928
+ state: "warning",
9929
+ name: merged.name,
9930
+ path: tsFile,
9931
+ warning
9932
+ });
9933
+ }
9934
+ configs.push(merged);
9487
9935
  }
9488
9936
  }
9489
9937
  return configs;
@@ -9542,7 +9990,6 @@ init_src();
9542
9990
  var import_node_fs11 = require("fs");
9543
9991
  var import_node_path19 = require("path");
9544
9992
  var import_node_url = require("url");
9545
- var DB_CHECK_TIMEOUT_MS = 3e3;
9546
9993
  var CONNECTION_STRING_PATTERN = /(?:postgresql|postgres|mysql|mongodb|sqlserver|sqlite):\/\/[^\s"')]+/gi;
9547
9994
  var stripConnectionStrings = /* @__PURE__ */ __name((message) => message.replace(CONNECTION_STRING_PATTERN, "[REDACTED]"), "stripConnectionStrings");
9548
9995
  var getCroutonVersion = /* @__PURE__ */ __name(() => {
@@ -9564,15 +10011,10 @@ var getCroutonVersion = /* @__PURE__ */ __name(() => {
9564
10011
  var getVersion = /* @__PURE__ */ __name(() => process.env["APP_VERSION"] ?? "unknown", "getVersion");
9565
10012
  var getEnvironment = /* @__PURE__ */ __name(() => process.env["ENVIRONMENT"] ?? process.env["NODE_ENV"] ?? "unknown", "getEnvironment");
9566
10013
  var checkDatabases = /* @__PURE__ */ __name(async (registry2) => {
9567
- const entries = registry2.entries();
9568
10014
  const results = [];
9569
- for (const { name, client } of entries) {
9570
- const prismaClient = client;
10015
+ for (const { name, adapter } of registry2.entries()) {
9571
10016
  try {
9572
- await Promise.race([
9573
- prismaClient.$queryRaw`SELECT 1`,
9574
- new Promise((_resolve, reject) => setTimeout(() => reject(new Error("Database health check timed out")), DB_CHECK_TIMEOUT_MS))
9575
- ]);
10017
+ await adapter.healthCheck?.();
9576
10018
  results.push({
9577
10019
  name,
9578
10020
  connected: true
@@ -9588,20 +10030,27 @@ var checkDatabases = /* @__PURE__ */ __name(async (registry2) => {
9588
10030
  return results;
9589
10031
  }, "checkDatabases");
9590
10032
  var getResourceStatus = /* @__PURE__ */ __name((loadedConfigs) => {
10033
+ const warningsByName = /* @__PURE__ */ new Map();
10034
+ for (const w of resourceLoadReportRegistry.getByState("warning")) {
10035
+ const existing = warningsByName.get(w.name) ?? [];
10036
+ existing.push(w.warning);
10037
+ warningsByName.set(w.name, existing);
10038
+ }
9591
10039
  const valid = loadedConfigs.map((c) => ({
9592
10040
  name: c.name,
9593
10041
  path: c.route,
9594
10042
  valid: true,
9595
10043
  version: c.schemaVersion ?? CURRENT_RESOURCE_VERSION,
9596
10044
  kind: c.kind ?? "prisma",
9597
- // Which operations the user's repository.ts actually implements. A resource
9598
- // only reaches this list after validateCustomRepository passed, so this is
9599
- // informational rather than a warning.
10045
+ // Which operations the user's repository.ts actually implements.
9600
10046
  ...c.kind === "custom" && c.repository ? {
9601
10047
  customOperations: CUSTOM_OPS.filter((op) => typeof c.repository?.[op] === "function")
9602
10048
  } : {},
9603
10049
  ...c.sidebar?.hide ? {
9604
10050
  hidden: true
10051
+ } : {},
10052
+ ...warningsByName.has(c.name) ? {
10053
+ warnings: warningsByName.get(c.name)
9605
10054
  } : {}
9606
10055
  }));
9607
10056
  const failed = resourceLoadErrorsRegistry.getAll().map((e) => ({
@@ -9628,10 +10077,12 @@ var getResourceStatus = /* @__PURE__ */ __name((loadedConfigs) => {
9628
10077
  var buildSummary = /* @__PURE__ */ __name((databases, resources) => {
9629
10078
  const databaseErrors = databases.filter((d) => !d.connected).length;
9630
10079
  const resourceErrors = resources.filter((r) => !r.valid).length;
10080
+ const warningCount = resources.reduce((acc, r) => acc + (r.warnings?.length ?? 0), 0);
9631
10081
  return {
9632
10082
  ok: databaseErrors === 0 && resourceErrors === 0,
9633
10083
  databaseErrors,
9634
- resourceErrors
10084
+ resourceErrors,
10085
+ warningCount
9635
10086
  };
9636
10087
  }, "buildSummary");
9637
10088
  var getSystemEnums = /* @__PURE__ */ __name(() => {
@@ -9905,9 +10356,10 @@ var CroutonApiModule = class _CroutonApiModule {
9905
10356
  const validConfigs = [];
9906
10357
  for (const c of configs) {
9907
10358
  if (c.kind === "custom") {
10359
+ let adapterClient;
9908
10360
  if (c.database) {
9909
10361
  try {
9910
- dataSourceRegistry.resolveAdapter(c.database);
10362
+ adapterClient = dataSourceRegistry.resolveAdapter(c.database).client;
9911
10363
  } catch (e) {
9912
10364
  resourceLoadErrorsRegistry.record({
9913
10365
  name: c.name,
@@ -9917,7 +10369,7 @@ var CroutonApiModule = class _CroutonApiModule {
9917
10369
  continue;
9918
10370
  }
9919
10371
  }
9920
- const problem = validateCustomRepository(c, c.repository);
10372
+ const problem = validateCustomRepository(c, c.repository, adapterClient);
9921
10373
  if (problem) {
9922
10374
  resourceLoadErrorsRegistry.record({
9923
10375
  name: c.name,
@@ -9977,6 +10429,9 @@ var CroutonApiModule = class _CroutonApiModule {
9977
10429
  return {
9978
10430
  module: _CroutonApiModule,
9979
10431
  controllers,
10432
+ exports: [
10433
+ ResourceConfigRegistry
10434
+ ],
9980
10435
  providers: [
9981
10436
  {
9982
10437
  provide: import_core2.APP_FILTER,
@@ -10034,6 +10489,36 @@ CroutonApiModule = _ts_decorate10([
10034
10489
  })
10035
10490
  ], CroutonApiModule);
10036
10491
 
10492
+ // src/lib/crud/parse-schema.ts
10493
+ init_cjs_shims();
10494
+ init_src();
10495
+ var parseSchema = /* @__PURE__ */ __name((input, appConfig, view = "schemas") => {
10496
+ if (appConfig.extensions) registerResourceExtensions(appConfig.extensions);
10497
+ const normalized = input !== null && typeof input === "object" && "json" in input ? input : {
10498
+ json: input
10499
+ };
10500
+ const parseResult = buildResourceJsonSchema().safeParse(normalized.json);
10501
+ if (!parseResult.success) {
10502
+ throw new Error(`Resource cannot be parsed: ${parseResult.error.message}`);
10503
+ }
10504
+ const resource = fromJson(parseResult.data, normalized.schema, normalized.hooks, normalized.dirPath, appConfig.baseUrl, normalized.actions, normalized.tableActions, normalized.enums ?? {}, void 0);
10505
+ let payload;
10506
+ if (view === "schemas") {
10507
+ payload = buildViewsPayload2(resource, appConfig.baseUrl);
10508
+ } else if (view === "definition") {
10509
+ payload = buildDefinitionPayload2(resource);
10510
+ } else {
10511
+ payload = buildResourceJsonPayload2(resource, appConfig.baseUrl);
10512
+ }
10513
+ if (payload && appConfig.schemaEnricher) {
10514
+ payload = {
10515
+ ...payload,
10516
+ ...appConfig.schemaEnricher(payload)
10517
+ };
10518
+ }
10519
+ return payload;
10520
+ }, "parseSchema");
10521
+
10037
10522
  // src/index.ts
10038
10523
  init_hooks();
10039
10524
  // Annotate the CommonJS export names for ESM import in node:
@@ -10063,6 +10548,7 @@ init_hooks();
10063
10548
  loadResourceHooks,
10064
10549
  loadSubResourceHooks,
10065
10550
  parseFilterString,
10551
+ parseSchema,
10066
10552
  postWrite,
10067
10553
  prepareWrite,
10068
10554
  resolveDefinition,