@postxl/schema 1.7.0 → 1.8.1

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.
@@ -134,6 +134,13 @@ const fieldDiscriminatedUnionTransformer = ({ fieldInput, model, projectSchema }
134
134
  });
135
135
  return zod_1.z.NEVER;
136
136
  }
137
+ if (f.kind === 'json') {
138
+ ctx.addIssue({
139
+ code: zod_1.z.ZodIssueCode.custom,
140
+ message: `Discriminated union ${model.name}.${fieldInput.name} cannot contain JSON fields yet.`,
141
+ });
142
+ return zod_1.z.NEVER;
143
+ }
137
144
  return f;
138
145
  });
139
146
  const commonFields = new Map();
@@ -5,6 +5,7 @@ import * as Branded from './shared/brands';
5
5
  import { FieldDiscriminatedUnion, FieldDiscriminatedUnionEnriched } from './discriminated-union';
6
6
  import { FieldEnum, FieldEnumEnriched } from './enum';
7
7
  import { FieldId, FieldIdEnriched } from './id';
8
+ import { FieldJson, FieldJsonEnriched } from './json';
8
9
  import { FieldRelation, FieldRelationEnriched } from './relation';
9
10
  import { FieldScalar, FieldScalarEnriched } from './scalar';
10
11
  /**
@@ -51,7 +52,7 @@ export declare const createFieldJSONDecoder: (params: {
51
52
  seed?: string | number | boolean | Date | (string | number | boolean | Date)[] | undefined;
52
53
  }>>, z.ZodPipe<z.ZodObject<{
53
54
  name: z.ZodString;
54
- type: z.ZodUnion<readonly [z.ZodUnion<[z.ZodLiteral<"String">, z.ZodLiteral<"String?">]>, z.ZodUnion<[z.ZodLiteral<"Boolean">, z.ZodLiteral<"Boolean?">]>, z.ZodUnion<[z.ZodLiteral<"DateTime">, z.ZodLiteral<"DateTime?">]>, z.ZodUnion<[z.ZodLiteral<"Decimal">, z.ZodLiteral<"Decimal?">]>, z.ZodUnion<[z.ZodLiteral<"Float">, z.ZodLiteral<"Float?">]>, z.ZodUnion<[z.ZodLiteral<"Int">, z.ZodLiteral<"Int?">]>, z.ZodUnion<[z.ZodLiteral<"Json">, z.ZodLiteral<"Json?">]>, z.ZodUnion<[z.ZodLiteral<"Bytes">, z.ZodLiteral<"Bytes?">]>, z.ZodUnion<[z.ZodLiteral<"BigInt">, z.ZodLiteral<"BigInt?">]>]>;
55
+ type: z.ZodUnion<readonly [z.ZodUnion<[z.ZodLiteral<"String">, z.ZodLiteral<"String?">]>, z.ZodUnion<[z.ZodLiteral<"Boolean">, z.ZodLiteral<"Boolean?">]>, z.ZodUnion<[z.ZodLiteral<"DateTime">, z.ZodLiteral<"DateTime?">]>, z.ZodUnion<[z.ZodLiteral<"Decimal">, z.ZodLiteral<"Decimal?">]>, z.ZodUnion<[z.ZodLiteral<"Float">, z.ZodLiteral<"Float?">]>, z.ZodUnion<[z.ZodLiteral<"Int">, z.ZodLiteral<"Int?">]>, z.ZodUnion<[z.ZodLiteral<"Bytes">, z.ZodLiteral<"Bytes?">]>, z.ZodUnion<[z.ZodLiteral<"BigInt">, z.ZodLiteral<"BigInt?">]>]>;
55
56
  databaseName: z.ZodOptional<z.ZodString>;
56
57
  excelName: z.ZodOptional<z.ZodString>;
57
58
  label: z.ZodOptional<z.ZodString>;
@@ -67,7 +68,7 @@ export declare const createFieldJSONDecoder: (params: {
67
68
  placeholder: z.ZodOptional<z.ZodString>;
68
69
  }, z.core.$strict>, z.ZodTransform<FieldScalarEnriched, {
69
70
  name: string;
70
- type: "BigInt" | "String" | "Boolean" | "DateTime" | "Decimal" | "Float" | "Int" | "Json" | "Bytes" | "String?" | "Boolean?" | "DateTime?" | "Decimal?" | "Float?" | "Int?" | "Json?" | "Bytes?" | "BigInt?";
71
+ type: "BigInt" | "String" | "Boolean" | "DateTime" | "Decimal" | "Float" | "Int" | "Bytes" | "String?" | "Boolean?" | "DateTime?" | "Decimal?" | "Float?" | "Int?" | "Bytes?" | "BigInt?";
71
72
  databaseName?: string | undefined;
72
73
  excelName?: string | undefined;
73
74
  label?: string | undefined;
@@ -81,6 +82,28 @@ export declare const createFieldJSONDecoder: (params: {
81
82
  faker?: string | undefined;
82
83
  seed?: string | number | boolean | Date | (string | number | boolean | Date)[] | undefined;
83
84
  placeholder?: string | undefined;
85
+ }>>, z.ZodPipe<z.ZodObject<{
86
+ name: z.ZodString;
87
+ type: z.ZodUnion<readonly [z.ZodLiteral<"Json">, z.ZodLiteral<"JSON">, z.ZodLiteral<"Json?">, z.ZodLiteral<"JSON?">]>;
88
+ databaseName: z.ZodOptional<z.ZodString>;
89
+ excelName: z.ZodOptional<z.ZodString>;
90
+ label: z.ZodOptional<z.ZodString>;
91
+ description: z.ZodOptional<z.ZodString>;
92
+ isReadonly: z.ZodOptional<z.ZodBoolean>;
93
+ isUnique: z.ZodOptional<z.ZodBoolean>;
94
+ hasIndex: z.ZodOptional<z.ZodBoolean>;
95
+ placeholder: z.ZodOptional<z.ZodString>;
96
+ }, z.core.$strict>, z.ZodTransform<FieldJsonEnriched, {
97
+ name: string;
98
+ type: "Json" | "JSON" | "Json?" | "JSON?";
99
+ databaseName?: string | undefined;
100
+ excelName?: string | undefined;
101
+ label?: string | undefined;
102
+ description?: string | undefined;
103
+ isReadonly?: boolean | undefined;
104
+ isUnique?: boolean | undefined;
105
+ hasIndex?: boolean | undefined;
106
+ placeholder?: string | undefined;
84
107
  }>>, z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodObject<{
85
108
  name: z.ZodString;
86
109
  type: z.ZodUnion<[z.ZodLiteral<"DiscriminatedUnion">, z.ZodLiteral<"DiscriminatedUnion?">]>;
@@ -194,8 +217,8 @@ export declare const createFieldJSONDecoder: (params: {
194
217
  isReadonly?: boolean | undefined;
195
218
  isUnique?: boolean | undefined;
196
219
  }>>]>;
197
- export type FieldEnriched = FieldIdEnriched | FieldScalarEnriched | FieldRelationEnriched | FieldEnumEnriched | FieldDiscriminatedUnionEnriched;
198
- export type FieldEnrichedNativeDatabase = FieldIdEnriched | FieldScalarEnriched | FieldRelationEnriched | FieldEnumEnriched;
220
+ export type FieldEnriched = FieldIdEnriched | FieldScalarEnriched | FieldJsonEnriched | FieldRelationEnriched | FieldEnumEnriched | FieldDiscriminatedUnionEnriched;
221
+ export type FieldEnrichedNativeDatabase = FieldIdEnriched | FieldScalarEnriched | FieldJsonEnriched | FieldRelationEnriched | FieldEnumEnriched;
199
222
  export declare const zFieldJSONInput: (params: {
200
223
  modelNames: Model.ModelName[];
201
224
  enumNames: Enum.EnumName[];
@@ -211,7 +234,7 @@ export declare const zFieldJSONInput: (params: {
211
234
  seed: z.ZodOptional<z.ZodUnion<[z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodDate]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodDate]>>]>>;
212
235
  }, z.core.$strip>, z.ZodObject<{
213
236
  name: z.ZodString;
214
- type: z.ZodUnion<readonly [z.ZodUnion<[z.ZodLiteral<"String">, z.ZodLiteral<"String?">]>, z.ZodUnion<[z.ZodLiteral<"Boolean">, z.ZodLiteral<"Boolean?">]>, z.ZodUnion<[z.ZodLiteral<"DateTime">, z.ZodLiteral<"DateTime?">]>, z.ZodUnion<[z.ZodLiteral<"Decimal">, z.ZodLiteral<"Decimal?">]>, z.ZodUnion<[z.ZodLiteral<"Float">, z.ZodLiteral<"Float?">]>, z.ZodUnion<[z.ZodLiteral<"Int">, z.ZodLiteral<"Int?">]>, z.ZodUnion<[z.ZodLiteral<"Json">, z.ZodLiteral<"Json?">]>, z.ZodUnion<[z.ZodLiteral<"Bytes">, z.ZodLiteral<"Bytes?">]>, z.ZodUnion<[z.ZodLiteral<"BigInt">, z.ZodLiteral<"BigInt?">]>]>;
237
+ type: z.ZodUnion<readonly [z.ZodUnion<[z.ZodLiteral<"String">, z.ZodLiteral<"String?">]>, z.ZodUnion<[z.ZodLiteral<"Boolean">, z.ZodLiteral<"Boolean?">]>, z.ZodUnion<[z.ZodLiteral<"DateTime">, z.ZodLiteral<"DateTime?">]>, z.ZodUnion<[z.ZodLiteral<"Decimal">, z.ZodLiteral<"Decimal?">]>, z.ZodUnion<[z.ZodLiteral<"Float">, z.ZodLiteral<"Float?">]>, z.ZodUnion<[z.ZodLiteral<"Int">, z.ZodLiteral<"Int?">]>, z.ZodUnion<[z.ZodLiteral<"Bytes">, z.ZodLiteral<"Bytes?">]>, z.ZodUnion<[z.ZodLiteral<"BigInt">, z.ZodLiteral<"BigInt?">]>]>;
215
238
  databaseName: z.ZodOptional<z.ZodString>;
216
239
  excelName: z.ZodOptional<z.ZodString>;
217
240
  label: z.ZodOptional<z.ZodString>;
@@ -225,6 +248,17 @@ export declare const zFieldJSONInput: (params: {
225
248
  faker: z.ZodOptional<z.ZodString>;
226
249
  seed: z.ZodOptional<z.ZodUnion<[z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodDate]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodDate]>>]>>;
227
250
  placeholder: z.ZodOptional<z.ZodString>;
251
+ }, z.core.$strict>, z.ZodObject<{
252
+ name: z.ZodString;
253
+ type: z.ZodUnion<readonly [z.ZodLiteral<"Json">, z.ZodLiteral<"JSON">, z.ZodLiteral<"Json?">, z.ZodLiteral<"JSON?">]>;
254
+ databaseName: z.ZodOptional<z.ZodString>;
255
+ excelName: z.ZodOptional<z.ZodString>;
256
+ label: z.ZodOptional<z.ZodString>;
257
+ description: z.ZodOptional<z.ZodString>;
258
+ isReadonly: z.ZodOptional<z.ZodBoolean>;
259
+ isUnique: z.ZodOptional<z.ZodBoolean>;
260
+ hasIndex: z.ZodOptional<z.ZodBoolean>;
261
+ placeholder: z.ZodOptional<z.ZodString>;
228
262
  }, z.core.$strict>, z.ZodObject<{
229
263
  name: z.ZodString;
230
264
  type: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
@@ -256,8 +290,8 @@ export declare const fieldTransformer: (fieldInput: FieldEnriched, model: {
256
290
  name: Model.ModelName;
257
291
  isReadonly?: boolean;
258
292
  }>;
259
- }, ctx: z.RefinementCtx) => FieldId | FieldScalar | FieldRelation | FieldEnum | FieldDiscriminatedUnion;
260
- export type FieldDatabaseNative = FieldId | FieldScalar | FieldRelation | FieldEnum;
293
+ }, ctx: z.RefinementCtx) => FieldJson | FieldId | FieldScalar | FieldRelation | FieldEnum | FieldDiscriminatedUnion;
294
+ export type FieldDatabaseNative = FieldId | FieldScalar | FieldJson | FieldRelation | FieldEnum;
261
295
  export declare function isFieldDatabaseNative(field: Field): field is FieldDatabaseNative;
262
296
  export type Field = FieldDatabaseNative | FieldDiscriminatedUnion;
263
297
  export type Fields<FIELD = Field> = Map<Branded.FieldName, FIELD>;
@@ -7,6 +7,7 @@ const utils_1 = require("@postxl/utils");
7
7
  const discriminated_union_1 = require("./discriminated-union");
8
8
  const enum_1 = require("./enum");
9
9
  const id_1 = require("./id");
10
+ const json_1 = require("./json");
10
11
  const relation_1 = require("./relation");
11
12
  const scalar_1 = require("./scalar");
12
13
  /*
@@ -15,6 +16,7 @@ const scalar_1 = require("./scalar");
15
16
  We have different kinds of fields:
16
17
  - id: a field that is the primary key of the model
17
18
  - scalar: a field that is not the primary key of the model
19
+ - json: a JSON field stored as database Json and typed as unknown
18
20
  - relation: a field that is a relation to another model
19
21
  - enum: a field that is an enum
20
22
  - discriminatedUnion: a field that is a discriminated union
@@ -31,6 +33,7 @@ const createFieldJSONDecoder = (params) => zod_1.z.union([
31
33
  //
32
34
  id_1.zFieldIdJSON.transform(id_1.fieldIdJSONTransformer),
33
35
  scalar_1.zFieldScalarJSON.transform(scalar_1.fieldScalarJSONTransformer),
36
+ json_1.zFieldJsonJSON.transform(json_1.fieldJsonJSONTransformer),
34
37
  discriminated_union_1.zFieldDiscriminatedUnionJSON.transform(discriminated_union_1.fieldDiscriminatedUnionJSONTransformer),
35
38
  // As relation and enum fields have flexible type names (i.e. the names of the referenced model/enum) and we use the
36
39
  // type property to determine the type of the field, we need to handle these last
@@ -42,6 +45,7 @@ const zFieldJSONInput = (params) => zod_1.z.union([
42
45
  //
43
46
  id_1.zFieldIdJSON,
44
47
  scalar_1.zFieldScalarJSON,
48
+ json_1.zFieldJsonJSON,
45
49
  (0, relation_1.createRelationJSONDecoder)(params),
46
50
  (0, enum_1.createEnumJSONDecoder)(params),
47
51
  ]);
@@ -52,6 +56,8 @@ const fieldTransformer = (fieldInput, model, projectSchema, ctx) => {
52
56
  return (0, id_1.fieldIdTransformer)({ fieldInput, model, projectSchema }, ctx);
53
57
  case 'scalar':
54
58
  return (0, scalar_1.fieldScalarTransformer)({ fieldInput, model, projectSchema }, ctx);
59
+ case 'json':
60
+ return (0, json_1.fieldJsonTransformer)({ fieldInput, model, projectSchema }, ctx);
55
61
  case 'discriminatedUnion':
56
62
  return (0, discriminated_union_1.fieldDiscriminatedUnionTransformer)({ fieldInput, model, projectSchema }, ctx);
57
63
  case 'relation':
@@ -3,6 +3,7 @@ export * from './defaults';
3
3
  export * from './enum';
4
4
  export * from './field';
5
5
  export * from './id';
6
+ export * from './json';
6
7
  export * from './relation';
7
8
  export * from './scalar';
8
9
  export * from './shared/brands';
@@ -19,6 +19,7 @@ __exportStar(require("./defaults"), exports);
19
19
  __exportStar(require("./enum"), exports);
20
20
  __exportStar(require("./field"), exports);
21
21
  __exportStar(require("./id"), exports);
22
+ __exportStar(require("./json"), exports);
22
23
  __exportStar(require("./relation"), exports);
23
24
  __exportStar(require("./scalar"), exports);
24
25
  __exportStar(require("./shared/brands"), exports);
@@ -0,0 +1,61 @@
1
+ import { z } from 'zod';
2
+ import { FieldCommon, FieldTransformer } from './shared/types';
3
+ export type FieldKindJson = 'json';
4
+ export declare const fieldKindJson: FieldKindJson;
5
+ export type FieldJson = FieldCommon<FieldKindJson> & {
6
+ /**
7
+ * JSON fields are typed as unknown in generated model types by default.
8
+ */
9
+ type: 'unknown';
10
+ /**
11
+ * If true, the repository will expose an index for the field.
12
+ */
13
+ hasIndex: boolean;
14
+ generation: string;
15
+ /**
16
+ * A generic placeholder that is used to pre-populate empty fields.
17
+ */
18
+ placeholder: string;
19
+ };
20
+ /**
21
+ * JSON Schema for a json field.
22
+ */
23
+ export declare const zFieldJsonJSON: z.ZodObject<{
24
+ name: z.ZodString;
25
+ type: z.ZodUnion<readonly [z.ZodLiteral<"Json">, z.ZodLiteral<"JSON">, z.ZodLiteral<"Json?">, z.ZodLiteral<"JSON?">]>;
26
+ databaseName: z.ZodOptional<z.ZodString>;
27
+ excelName: z.ZodOptional<z.ZodString>;
28
+ label: z.ZodOptional<z.ZodString>;
29
+ description: z.ZodOptional<z.ZodString>;
30
+ isReadonly: z.ZodOptional<z.ZodBoolean>;
31
+ isUnique: z.ZodOptional<z.ZodBoolean>;
32
+ hasIndex: z.ZodOptional<z.ZodBoolean>;
33
+ placeholder: z.ZodOptional<z.ZodString>;
34
+ }, z.core.$strict>;
35
+ export type FieldJsonJSON = z.infer<typeof zFieldJsonJSON>;
36
+ export declare function fieldJsonJSONTransformer(fieldInput: FieldJsonJSON): FieldJsonEnriched;
37
+ export type FieldJsonEnriched = Omit<FieldJson, 'modelName'>;
38
+ export declare const zFieldJson: z.ZodPipe<z.ZodObject<{
39
+ name: z.ZodString;
40
+ type: z.ZodUnion<readonly [z.ZodLiteral<"Json">, z.ZodLiteral<"JSON">, z.ZodLiteral<"Json?">, z.ZodLiteral<"JSON?">]>;
41
+ databaseName: z.ZodOptional<z.ZodString>;
42
+ excelName: z.ZodOptional<z.ZodString>;
43
+ label: z.ZodOptional<z.ZodString>;
44
+ description: z.ZodOptional<z.ZodString>;
45
+ isReadonly: z.ZodOptional<z.ZodBoolean>;
46
+ isUnique: z.ZodOptional<z.ZodBoolean>;
47
+ hasIndex: z.ZodOptional<z.ZodBoolean>;
48
+ placeholder: z.ZodOptional<z.ZodString>;
49
+ }, z.core.$strict>, z.ZodTransform<FieldJsonEnriched, {
50
+ name: string;
51
+ type: "Json" | "JSON" | "Json?" | "JSON?";
52
+ databaseName?: string | undefined;
53
+ excelName?: string | undefined;
54
+ label?: string | undefined;
55
+ description?: string | undefined;
56
+ isReadonly?: boolean | undefined;
57
+ isUnique?: boolean | undefined;
58
+ hasIndex?: boolean | undefined;
59
+ placeholder?: string | undefined;
60
+ }>>;
61
+ export declare const fieldJsonTransformer: FieldTransformer<FieldKindJson, FieldJsonEnriched, FieldJson>;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.fieldJsonTransformer = exports.zFieldJson = exports.zFieldJsonJSON = exports.fieldKindJson = void 0;
37
+ exports.fieldJsonJSONTransformer = fieldJsonJSONTransformer;
38
+ const zod_1 = require("zod");
39
+ const utils_1 = require("@postxl/utils");
40
+ const Branded = __importStar(require("./shared/brands"));
41
+ const Decoders = __importStar(require("./shared/decoders"));
42
+ const utils_2 = require("./shared/utils");
43
+ exports.fieldKindJson = 'json';
44
+ const zDatabaseTypeJson = zod_1.z
45
+ .union([zod_1.z.literal('Json'), zod_1.z.literal('JSON'), zod_1.z.literal('Json?'), zod_1.z.literal('JSON?')])
46
+ .describe('The type of the field. This should be `Json`/`JSON` or `Json?`/`JSON?`.');
47
+ /**
48
+ * JSON Schema for a json field.
49
+ */
50
+ exports.zFieldJsonJSON = zod_1.z
51
+ .object({
52
+ name: Decoders.zFieldPropertyName,
53
+ type: zDatabaseTypeJson,
54
+ databaseName: Decoders.zFieldPropertyDatabaseName,
55
+ excelName: Decoders.zFieldPropertyExcelName,
56
+ label: Decoders.zFieldPropertyLabel,
57
+ description: Decoders.zFieldPropertyDescription,
58
+ isReadonly: Decoders.zFieldPropertyIsReadonly,
59
+ isUnique: Decoders.zFieldPropertyIsUnique,
60
+ hasIndex: Decoders.zFieldPropertyHasIndex,
61
+ placeholder: Decoders.zFieldPropertyPlaceholder,
62
+ })
63
+ .strict();
64
+ function fieldJsonJSONTransformer(fieldInput) {
65
+ const required = (0, utils_2.isFieldRequired)(fieldInput.type);
66
+ const label = fieldInput.label ?? (0, utils_1.toHumanReadable)(fieldInput.name);
67
+ return {
68
+ kind: exports.fieldKindJson,
69
+ type: 'unknown',
70
+ name: Branded.toFieldName(fieldInput.name),
71
+ databaseType: Branded.toDatabaseFieldType('Json'),
72
+ databaseName: Branded.toDatabaseFieldName(fieldInput.databaseName ?? (0, utils_1.toSnakeCase)(fieldInput.name)),
73
+ excelName: Branded.toExcelColumnName(fieldInput.excelName ?? fieldInput.label ?? fieldInput.name),
74
+ description: fieldInput.description,
75
+ label,
76
+ hasIndex: fieldInput.hasIndex ?? false,
77
+ isReadonly: fieldInput.isReadonly ?? false,
78
+ isRequired: required.isRequired,
79
+ isUnique: fieldInput.isUnique ?? false,
80
+ generation: '',
81
+ placeholder: fieldInput.placeholder ?? '{}',
82
+ };
83
+ }
84
+ exports.zFieldJson = exports.zFieldJsonJSON.transform(fieldJsonJSONTransformer);
85
+ const fieldJsonTransformer = ({ fieldInput, model: { name: modelName }, }) => {
86
+ return {
87
+ ...fieldInput,
88
+ modelName,
89
+ kind: 'json',
90
+ };
91
+ };
92
+ exports.fieldJsonTransformer = fieldJsonTransformer;
@@ -57,7 +57,7 @@ type FieldScalarDateNoValidation = {
57
57
  */
58
58
  export declare const zFieldScalarJSON: z.ZodObject<{
59
59
  name: z.ZodString;
60
- type: z.ZodUnion<readonly [z.ZodUnion<[z.ZodLiteral<"String">, z.ZodLiteral<"String?">]>, z.ZodUnion<[z.ZodLiteral<"Boolean">, z.ZodLiteral<"Boolean?">]>, z.ZodUnion<[z.ZodLiteral<"DateTime">, z.ZodLiteral<"DateTime?">]>, z.ZodUnion<[z.ZodLiteral<"Decimal">, z.ZodLiteral<"Decimal?">]>, z.ZodUnion<[z.ZodLiteral<"Float">, z.ZodLiteral<"Float?">]>, z.ZodUnion<[z.ZodLiteral<"Int">, z.ZodLiteral<"Int?">]>, z.ZodUnion<[z.ZodLiteral<"Json">, z.ZodLiteral<"Json?">]>, z.ZodUnion<[z.ZodLiteral<"Bytes">, z.ZodLiteral<"Bytes?">]>, z.ZodUnion<[z.ZodLiteral<"BigInt">, z.ZodLiteral<"BigInt?">]>]>;
60
+ type: z.ZodUnion<readonly [z.ZodUnion<[z.ZodLiteral<"String">, z.ZodLiteral<"String?">]>, z.ZodUnion<[z.ZodLiteral<"Boolean">, z.ZodLiteral<"Boolean?">]>, z.ZodUnion<[z.ZodLiteral<"DateTime">, z.ZodLiteral<"DateTime?">]>, z.ZodUnion<[z.ZodLiteral<"Decimal">, z.ZodLiteral<"Decimal?">]>, z.ZodUnion<[z.ZodLiteral<"Float">, z.ZodLiteral<"Float?">]>, z.ZodUnion<[z.ZodLiteral<"Int">, z.ZodLiteral<"Int?">]>, z.ZodUnion<[z.ZodLiteral<"Bytes">, z.ZodLiteral<"Bytes?">]>, z.ZodUnion<[z.ZodLiteral<"BigInt">, z.ZodLiteral<"BigInt?">]>]>;
61
61
  databaseName: z.ZodOptional<z.ZodString>;
62
62
  excelName: z.ZodOptional<z.ZodString>;
63
63
  label: z.ZodOptional<z.ZodString>;
@@ -80,7 +80,7 @@ export type FieldScalarEnriched = Omit<FieldCommon<FieldKindScalar>, 'modelName'
80
80
  };
81
81
  export declare const zFieldScalar: z.ZodPipe<z.ZodObject<{
82
82
  name: z.ZodString;
83
- type: z.ZodUnion<readonly [z.ZodUnion<[z.ZodLiteral<"String">, z.ZodLiteral<"String?">]>, z.ZodUnion<[z.ZodLiteral<"Boolean">, z.ZodLiteral<"Boolean?">]>, z.ZodUnion<[z.ZodLiteral<"DateTime">, z.ZodLiteral<"DateTime?">]>, z.ZodUnion<[z.ZodLiteral<"Decimal">, z.ZodLiteral<"Decimal?">]>, z.ZodUnion<[z.ZodLiteral<"Float">, z.ZodLiteral<"Float?">]>, z.ZodUnion<[z.ZodLiteral<"Int">, z.ZodLiteral<"Int?">]>, z.ZodUnion<[z.ZodLiteral<"Json">, z.ZodLiteral<"Json?">]>, z.ZodUnion<[z.ZodLiteral<"Bytes">, z.ZodLiteral<"Bytes?">]>, z.ZodUnion<[z.ZodLiteral<"BigInt">, z.ZodLiteral<"BigInt?">]>]>;
83
+ type: z.ZodUnion<readonly [z.ZodUnion<[z.ZodLiteral<"String">, z.ZodLiteral<"String?">]>, z.ZodUnion<[z.ZodLiteral<"Boolean">, z.ZodLiteral<"Boolean?">]>, z.ZodUnion<[z.ZodLiteral<"DateTime">, z.ZodLiteral<"DateTime?">]>, z.ZodUnion<[z.ZodLiteral<"Decimal">, z.ZodLiteral<"Decimal?">]>, z.ZodUnion<[z.ZodLiteral<"Float">, z.ZodLiteral<"Float?">]>, z.ZodUnion<[z.ZodLiteral<"Int">, z.ZodLiteral<"Int?">]>, z.ZodUnion<[z.ZodLiteral<"Bytes">, z.ZodLiteral<"Bytes?">]>, z.ZodUnion<[z.ZodLiteral<"BigInt">, z.ZodLiteral<"BigInt?">]>]>;
84
84
  databaseName: z.ZodOptional<z.ZodString>;
85
85
  excelName: z.ZodOptional<z.ZodString>;
86
86
  label: z.ZodOptional<z.ZodString>;
@@ -96,7 +96,7 @@ export declare const zFieldScalar: z.ZodPipe<z.ZodObject<{
96
96
  placeholder: z.ZodOptional<z.ZodString>;
97
97
  }, z.core.$strict>, z.ZodTransform<FieldScalarEnriched, {
98
98
  name: string;
99
- type: "BigInt" | "String" | "Boolean" | "DateTime" | "Decimal" | "Float" | "Int" | "Json" | "Bytes" | "String?" | "Boolean?" | "DateTime?" | "Decimal?" | "Float?" | "Int?" | "Json?" | "Bytes?" | "BigInt?";
99
+ type: "BigInt" | "String" | "Boolean" | "DateTime" | "Decimal" | "Float" | "Int" | "Bytes" | "String?" | "Boolean?" | "DateTime?" | "Decimal?" | "Float?" | "Int?" | "Bytes?" | "BigInt?";
100
100
  databaseName?: string | undefined;
101
101
  excelName?: string | undefined;
102
102
  label?: string | undefined;
@@ -50,7 +50,6 @@ const zDatabaseType = zod_1.z
50
50
  zod_1.z.literal('Decimal').or(zod_1.z.literal('Decimal?')),
51
51
  zod_1.z.literal('Float').or(zod_1.z.literal('Float?')),
52
52
  zod_1.z.literal('Int').or(zod_1.z.literal('Int?')),
53
- zod_1.z.literal('Json').or(zod_1.z.literal('Json?')),
54
53
  zod_1.z.literal('Bytes').or(zod_1.z.literal('Bytes?')),
55
54
  zod_1.z.literal('BigInt').or(zod_1.z.literal('BigInt?')),
56
55
  ])
@@ -73,8 +72,6 @@ function databaseTypeToFieldTypeScalar(input, ctx) {
73
72
  case 'Int':
74
73
  case 'Int?':
75
74
  return Branded.toScalarType('number');
76
- case 'Json':
77
- case 'Json?':
78
75
  case 'Bytes':
79
76
  case 'Bytes?':
80
77
  case 'BigInt':
@@ -117,7 +114,6 @@ const defaultPlaceholders = {
117
114
  Decimal: () => '1234.56',
118
115
  Float: () => '1234.56',
119
116
  Int: () => '1234',
120
- Json: () => '{}',
121
117
  Bytes: () => '1234',
122
118
  BigInt: () => '1234',
123
119
  };
@@ -126,10 +122,12 @@ function fieldScalarJSONTransformer(fieldInput, ctx) {
126
122
  const isUpdatedAt = fieldInput.isUpdatedAt ?? false;
127
123
  const required = (0, utils_2.isFieldRequired)(fieldInput.type);
128
124
  const isRequired = isCreatedAt || isUpdatedAt ? false : required.isRequired;
129
- const databaseType = Branded.toDatabaseFieldType(required.type);
130
- const type = databaseTypeToFieldTypeScalar(databaseType, ctx);
125
+ const scalarDatabaseType = zDatabaseType.parse(required.type);
126
+ const databaseType = Branded.toDatabaseFieldType(scalarDatabaseType);
127
+ const type = databaseTypeToFieldTypeScalar(scalarDatabaseType, ctx);
131
128
  const label = fieldInput.label ?? (0, utils_1.toHumanReadable)(fieldInput.name);
132
- const placeholder = fieldInput.placeholder ?? defaultPlaceholders[databaseType](label);
129
+ const placeholderFactory = defaultPlaceholders[scalarDatabaseType];
130
+ const placeholder = fieldInput.placeholder ?? placeholderFactory?.(label) ?? `${label} here...`;
133
131
  return {
134
132
  type,
135
133
  kind: exports.fieldKindScalar,
@@ -40,6 +40,8 @@ function getFieldType(field) {
40
40
  return field.databaseType;
41
41
  case 'scalar':
42
42
  return field.databaseType;
43
+ case 'json':
44
+ return field.databaseType;
43
45
  case 'discriminatedUnion':
44
46
  return 'DiscriminatedUnion';
45
47
  case 'relation':
@@ -37,6 +37,7 @@ export declare const zModelJSON: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.Z
37
37
  defaultField: z.ZodOptional<z.ZodString>;
38
38
  labelField: z.ZodOptional<z.ZodString>;
39
39
  keyField: z.ZodOptional<z.ZodString>;
40
+ defaultSort: z.ZodOptional<z.ZodArray<z.core.$ZodBranded<z.ZodString, "PXL.FieldName", "out">>>;
40
41
  indexes: z.ZodOptional<z.ZodArray<z.ZodArray<z.core.$ZodBranded<z.ZodString, "PXL.FieldName", "out">>>>;
41
42
  seed: z.ZodOptional<z.ZodArray<z.ZodAny>>;
42
43
  source: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
@@ -93,6 +93,9 @@ The label field must be a string field. If not provided, the \`name\` field is u
93
93
  .optional().describe(`The name of the field that is used as the key (unique identifier) for the entity.
94
94
  The key field must be a scalar string field. If not provided, the fallback order is: \`key\`, \`excelKey\`, \`slug\`, then \`id\`.
95
95
  The key field is used in navigation, Excel import, and other places where a human-readable identifier is needed.`),
96
+ defaultSort: zod_1.z.array(brands_1.zFieldName).optional()
97
+ .describe(`Default sort order for admin views when no explicit sort is provided.
98
+ Each entry references a field name and is applied ascending in the given order.`),
96
99
  indexes: zod_1.z
97
100
  //
98
101
  .array(zod_1.z.array(brands_1.zFieldName).min(2, { error: 'Index must have at least 2 fields' }))
@@ -12,6 +12,7 @@ export declare function modelJSONTransformer(input: ModelJSON, ctx: z.Refinement
12
12
  defaultFieldName: (string & z.core.$brand<"PXL.FieldName">) | undefined;
13
13
  labelFieldName: (string & z.core.$brand<"PXL.FieldName">) | undefined;
14
14
  keyFieldName: (string & z.core.$brand<"PXL.FieldName">) | undefined;
15
+ defaultSort: (string & z.core.$brand<"PXL.FieldName">)[] | undefined;
15
16
  isReadonly: boolean;
16
17
  excelName: string;
17
18
  description: string;
@@ -91,10 +92,11 @@ declare function addDefaults({ description, fields, standardFields, seed, faker,
91
92
  defaultField?: string | undefined;
92
93
  labelField?: string | undefined;
93
94
  keyField?: string | undefined;
95
+ defaultSort?: (string & z.core.$brand<"PXL.FieldName">)[] | undefined;
94
96
  source?: Record<string, unknown> | undefined;
95
97
  };
96
98
  type WithDefaults = ReturnType<typeof addDefaults>;
97
- declare function brandModel({ name, schema, databaseName, standardFields, defaultField, labelField, keyField, ...input }: WithDefaults): {
99
+ declare function brandModel({ name, schema, databaseName, standardFields, defaultField, labelField, keyField, defaultSort, ...input }: WithDefaults): {
98
100
  name: string & z.core.$brand<"PXL.ModelName">;
99
101
  schema: (string & z.core.$brand<"PXL.DatabaseSchemaName">) | undefined;
100
102
  databaseName: string & z.core.$brand<"PXL.DatabaseModelName">;
@@ -102,6 +104,7 @@ declare function brandModel({ name, schema, databaseName, standardFields, defaul
102
104
  defaultFieldName: (string & z.core.$brand<"PXL.FieldName">) | undefined;
103
105
  labelFieldName: (string & z.core.$brand<"PXL.FieldName">) | undefined;
104
106
  keyFieldName: (string & z.core.$brand<"PXL.FieldName">) | undefined;
107
+ defaultSort: (string & z.core.$brand<"PXL.FieldName">)[] | undefined;
105
108
  isReadonly: boolean;
106
109
  excelName: string;
107
110
  description: string;
@@ -153,6 +156,7 @@ declare function combineFields({ fields, standardFields, ...model }: BrandedMode
153
156
  defaultFieldName: (string & z.core.$brand<"PXL.FieldName">) | undefined;
154
157
  labelFieldName: (string & z.core.$brand<"PXL.FieldName">) | undefined;
155
158
  keyFieldName: (string & z.core.$brand<"PXL.FieldName">) | undefined;
159
+ defaultSort: (string & z.core.$brand<"PXL.FieldName">)[] | undefined;
156
160
  isReadonly: boolean;
157
161
  excelName: string;
158
162
  description: string;
@@ -65,7 +65,7 @@ function addDefaults({ description, fields, standardFields, seed, faker, ...inpu
65
65
  },
66
66
  };
67
67
  }
68
- function brandModel({ name, schema, databaseName, standardFields, defaultField, labelField, keyField, ...input }) {
68
+ function brandModel({ name, schema, databaseName, standardFields, defaultField, labelField, keyField, defaultSort, ...input }) {
69
69
  return {
70
70
  ...input,
71
71
  name: (0, model_brands_1.toModelName)(name),
@@ -75,6 +75,7 @@ function brandModel({ name, schema, databaseName, standardFields, defaultField,
75
75
  defaultFieldName: defaultField ? Field.toFieldName(defaultField) : undefined,
76
76
  labelFieldName: labelField ? Field.toFieldName(labelField) : undefined,
77
77
  keyFieldName: keyField ? Field.toFieldName(keyField) : undefined,
78
+ defaultSort: defaultSort?.map((fieldName) => Field.toFieldName(fieldName)),
78
79
  };
79
80
  }
80
81
  function combineFields({ fields, standardFields, ...model }, ctx) {
@@ -21,6 +21,11 @@ export type Model = {
21
21
  * Always defined since id field is always present.
22
22
  */
23
23
  keyField: Field.FieldDatabaseNative;
24
+ /**
25
+ * Default sort order used by generated admin views when no explicit sort is provided.
26
+ * Entries are field names sorted ascending in the given order.
27
+ */
28
+ defaultSort: Field.FieldName[];
24
29
  indexes: ModelIndex[];
25
30
  seed: Seed[];
26
31
  /**
@@ -108,6 +108,7 @@ export declare const zProjectSchemaJSON: z.ZodPipe<z.ZodTransform<unknown, unkno
108
108
  defaultField: z.ZodOptional<z.ZodString>;
109
109
  labelField: z.ZodOptional<z.ZodString>;
110
110
  keyField: z.ZodOptional<z.ZodString>;
111
+ defaultSort: z.ZodOptional<z.ZodArray<z.core.$ZodBranded<z.ZodString, "PXL.FieldName", "out">>>;
111
112
  indexes: z.ZodOptional<z.ZodArray<z.ZodArray<z.core.$ZodBranded<z.ZodString, "PXL.FieldName", "out">>>>;
112
113
  seed: z.ZodOptional<z.ZodArray<z.ZodAny>>;
113
114
  source: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
@@ -87,6 +87,7 @@ export declare const zProjectSchema: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown,
87
87
  defaultField: z.ZodOptional<z.ZodString>;
88
88
  labelField: z.ZodOptional<z.ZodString>;
89
89
  keyField: z.ZodOptional<z.ZodString>;
90
+ defaultSort: z.ZodOptional<z.ZodArray<z.core.$ZodBranded<z.ZodString, "PXL.FieldName", "out">>>;
90
91
  indexes: z.ZodOptional<z.ZodArray<z.ZodArray<z.core.$ZodBranded<z.ZodString, "PXL.FieldName", "out">>>>;
91
92
  seed: z.ZodOptional<z.ZodArray<z.ZodAny>>;
92
93
  source: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
@@ -191,6 +192,7 @@ export declare const zProjectSchema: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown,
191
192
  defaultField?: string | undefined;
192
193
  labelField?: string | undefined;
193
194
  keyField?: string | undefined;
195
+ defaultSort?: (string & z.core.$brand<"PXL.FieldName">)[] | undefined;
194
196
  indexes?: (string & z.core.$brand<"PXL.FieldName">)[][] | undefined;
195
197
  seed?: any[] | undefined;
196
198
  source?: Record<string, unknown> | undefined;
@@ -275,7 +275,15 @@ function decodeFields({ modelsArray, ...projectSchema }, ctx) {
275
275
  function transformModels(projectSchema, ctx) {
276
276
  const models = new Map();
277
277
  for (const inputModelName of projectSchema.modelNames) {
278
- const model = transformModel(projectSchema.models.get(inputModelName), projectSchema, ctx);
278
+ const inputModel = projectSchema.models.get(inputModelName);
279
+ if (!inputModel) {
280
+ ctx.addIssue({
281
+ code: zod_1.z.ZodIssueCode.custom,
282
+ message: `Model ${inputModelName} is missing after field decoding`,
283
+ });
284
+ return zod_1.z.NEVER;
285
+ }
286
+ const model = transformModel(inputModel, projectSchema, ctx);
279
287
  models.set(model.name, model);
280
288
  }
281
289
  const { auth, ...remainingProjectSchema } = projectSchema;
@@ -299,6 +307,7 @@ function transformModel(model, projectSchema, ctx) {
299
307
  const defaultField = extractDefaultField(model, fields, ctx);
300
308
  const labelField = extractLabelField(model, fields, ctx);
301
309
  const keyField = extractKeyField(model, fields, idField, ctx);
310
+ const defaultSort = extractDefaultSort(model, fields, ctx);
302
311
  const { defaultFieldName, labelFieldName, keyFieldName, auth, ...remainingModel } = model;
303
312
  return {
304
313
  ...remainingModel,
@@ -308,6 +317,7 @@ function transformModel(model, projectSchema, ctx) {
308
317
  defaultField,
309
318
  labelField,
310
319
  keyField,
320
+ defaultSort,
311
321
  idField,
312
322
  };
313
323
  }
@@ -438,9 +448,15 @@ function extractLabelField({ labelFieldName, ...model }, fields, ctx) {
438
448
  return zod_1.z.NEVER;
439
449
  }
440
450
  if (labelField.kind !== 'scalar' && labelField.kind !== 'id') {
451
+ const fieldType = Field.getFieldType(labelField);
452
+ const hint = labelField.kind === 'enum'
453
+ ? ` Enum fields cannot be used as label fields.`
454
+ : labelField.kind === 'relation'
455
+ ? ` Relation fields cannot be used as label fields.`
456
+ : '';
441
457
  ctx.addIssue({
442
458
  code: zod_1.z.ZodIssueCode.custom,
443
- message: `Label field ${labelFieldName} in model ${model.name} must be of type \`string\`, but instead is of type ${Field.getFieldType(labelField)}!`,
459
+ message: `Label field ${labelFieldName} in model ${model.name} must be of type \`string\`, but instead is of type \`${fieldType}\`.${hint}`,
444
460
  });
445
461
  return zod_1.z.NEVER;
446
462
  }
@@ -448,7 +464,7 @@ function extractLabelField({ labelFieldName, ...model }, fields, ctx) {
448
464
  if (type !== 'string') {
449
465
  ctx.addIssue({
450
466
  code: zod_1.z.ZodIssueCode.custom,
451
- message: `Label field ${labelFieldName} in model ${model.name} must be of type \`string\`, but instead is of type ${type}!`,
467
+ message: `Label field ${labelFieldName} in model ${model.name} must be of type \`string\`, but instead is of type \`${type}\`.`,
452
468
  });
453
469
  return zod_1.z.NEVER;
454
470
  }
@@ -522,6 +538,49 @@ function extractKeyFieldFromFallbacks(fields, idField) {
522
538
  // id field is always present and is always a string
523
539
  return idField;
524
540
  }
541
+ const defaultSortFallbackCandidates = [
542
+ Field.toFieldName('order'),
543
+ Field.toFieldName('sequence'),
544
+ Field.toFieldName('count'),
545
+ Field.toFieldName('name'),
546
+ Field.toFieldName('label'),
547
+ Field.toFieldName('id'),
548
+ ];
549
+ function extractDefaultSort(model, fields, ctx) {
550
+ const idFieldName = Field.standardFieldName_id;
551
+ const defaultSort = model.defaultSort;
552
+ if (defaultSort && defaultSort.length > 0) {
553
+ const result = [];
554
+ const seen = new Set();
555
+ for (const fieldName of defaultSort) {
556
+ if (!fields.has(fieldName)) {
557
+ ctx.addIssue({
558
+ code: zod_1.z.ZodIssueCode.custom,
559
+ message: `Default sort field ${fieldName} is not defined in model ${model.name}!`,
560
+ });
561
+ return zod_1.z.NEVER;
562
+ }
563
+ if (!seen.has(fieldName)) {
564
+ seen.add(fieldName);
565
+ result.push(fieldName);
566
+ }
567
+ }
568
+ if (!seen.has(idFieldName) && fields.has(idFieldName)) {
569
+ result.push(idFieldName);
570
+ }
571
+ return result;
572
+ }
573
+ const fallbacks = [];
574
+ for (const candidate of defaultSortFallbackCandidates) {
575
+ if (fields.has(candidate)) {
576
+ fallbacks.push(candidate);
577
+ }
578
+ }
579
+ if (!fallbacks.includes(idFieldName) && fields.has(idFieldName)) {
580
+ fallbacks.push(idFieldName);
581
+ }
582
+ return fallbacks;
583
+ }
525
584
  function isStringScalarField(field) {
526
585
  return field.kind === 'scalar' && field.type === 'string';
527
586
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postxl/schema",
3
- "version": "1.7.0",
3
+ "version": "1.8.1",
4
4
  "description": "Decoders for PXL Schema definitions and validation for PXL code generation framework",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -36,7 +36,7 @@
36
36
  "directory": "packages/schema"
37
37
  },
38
38
  "dependencies": {
39
- "@postxl/utils": "^1.3.4"
39
+ "@postxl/utils": "^1.4.0"
40
40
  },
41
41
  "devDependencies": {},
42
42
  "wallaby": {