@tinacms/schema-tools 1.3.1 → 1.3.3

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.es.js CHANGED
@@ -200,14 +200,6 @@ class TinaSchema {
200
200
  this.getCollections = () => {
201
201
  return this.schema.collections.map((collection) => this.getCollection(collection.name)) || [];
202
202
  };
203
- this.getGlobalTemplate = (templateName) => {
204
- var _a;
205
- const globalTemplate = (_a = this.schema.templates) == null ? void 0 : _a.find((template) => template.name === templateName);
206
- if (!globalTemplate) {
207
- throw new Error(`Expected to find global template of name ${templateName}`);
208
- }
209
- return globalTemplate;
210
- };
211
203
  this.getCollectionByFullPath = (filepath) => {
212
204
  const possibleCollections = this.getCollections().filter((collection) => {
213
205
  return filepath.replace(/\\/g, "/").startsWith(collection.path.replace(/\/?$/, "/"));
@@ -365,11 +357,8 @@ class TinaSchema {
365
357
  };
366
358
  this.getTemplatesForCollectable = (collection) => {
367
359
  let extraFields = [];
368
- if (collection.references) {
369
- extraFields = collection.references;
370
- }
371
360
  if (collection.fields) {
372
- const template = typeof collection.fields === "string" ? this.getGlobalTemplate(collection.fields) : collection;
361
+ const template = collection;
373
362
  if (typeof template.fields === "string" || typeof template.fields === "undefined") {
374
363
  throw new Error("Exptected template to have fields but none were found");
375
364
  }
@@ -387,7 +376,7 @@ class TinaSchema {
387
376
  namespace: collection.namespace,
388
377
  type: "union",
389
378
  templates: collection.templates.map((templateOrTemplateString) => {
390
- const template = typeof templateOrTemplateString === "string" ? this.getGlobalTemplate(templateOrTemplateString) : templateOrTemplateString;
379
+ const template = templateOrTemplateString;
391
380
  return {
392
381
  ...template,
393
382
  fields: [...template.fields, ...extraFields]
@@ -404,7 +393,6 @@ class TinaSchema {
404
393
  }
405
394
  const resolveField = (field, schema) => {
406
395
  var _a;
407
- field.parentTypename = NAMER.dataTypeName(field.namespace.filter((_, i) => i < field.namespace.length - 1));
408
396
  const extraFields = field.ui || {};
409
397
  switch (field.type) {
410
398
  case "number":
@@ -586,9 +574,24 @@ const parseZodError = ({ zodError }) => {
586
574
  const name = z.string({
587
575
  required_error: "Name is required but not provided",
588
576
  invalid_type_error: "Name must be a string"
589
- }).refine((val) => val.match(/^[a-zA-Z0-9_]*$/) !== null, (val) => ({
590
- message: `name, "${val}" must be alphanumeric and can only contain underscores`
591
- }));
577
+ }).superRefine((val, ctx) => {
578
+ if (val.match(/^[a-zA-Z0-9_]*$/) === null) {
579
+ ctx.addIssue({
580
+ code: "custom",
581
+ message: `name, "${val}" must be alphanumeric and can only contain underscores. (No spaces, dashes, special characters, etc.)
582
+ If you only want to display this value in the CMS UI, you can use the label property to customize it.
583
+
584
+ If you need to use this value in your content you can use the \`nameOverride\` property to customize the value. For example:
585
+ \`\`\`
586
+ {
587
+ "name": ${val.replace(/[^a-zA-Z0-9]/g, "_")},
588
+ "nameOverride": ${val},
589
+ // ...
590
+ }
591
+ \`\`\``
592
+ });
593
+ }
594
+ });
592
595
  const TypeName = [
593
596
  "string",
594
597
  "boolean",
@@ -601,17 +604,6 @@ const TypeName = [
601
604
  ];
602
605
  const typeTypeError = `type must be one of ${TypeName.join(", ")}`;
603
606
  const typeRequiredError = `type is required and must be one of ${TypeName.join(", ")}`;
604
- const nameProp = z.string({
605
- required_error: "name must be provided",
606
- invalid_type_error: "name must be a sting"
607
- }).superRefine((val, ctx) => {
608
- if (val.includes(" "))
609
- ctx.addIssue({
610
- message: `name "${val}" cannot contain spaces`,
611
- code: z.ZodIssueCode.custom,
612
- fatal: true
613
- });
614
- });
615
607
  const Option = z.union([
616
608
  z.string(),
617
609
  z.object({ label: z.string(), value: z.string() }),
@@ -624,7 +616,7 @@ const Option = z.union([
624
616
  }
625
617
  });
626
618
  const TinaField = z.object({
627
- name: nameProp,
619
+ name,
628
620
  label: z.string().or(z.boolean()).optional(),
629
621
  description: z.string().optional(),
630
622
  required: z.boolean().optional()
@@ -675,7 +667,7 @@ const ReferenceField = FieldWithList.extend({
675
667
  const TinaFieldZod = z.lazy(() => {
676
668
  const TemplateTemp = z.object({
677
669
  label: z.string().optional(),
678
- name: nameProp,
670
+ name,
679
671
  fields: z.array(TinaFieldZod),
680
672
  match: z.object({
681
673
  start: z.string(),
@@ -836,7 +828,7 @@ const Template = z.object({
836
828
  });
837
829
  }
838
830
  });
839
- const TinaCloudCollectionBase = z.object({
831
+ const CollectionBaseSchema = z.object({
840
832
  label: z.string().optional(),
841
833
  name: name.superRefine((val, ctx) => {
842
834
  if (val === "relativePath") {
@@ -846,9 +838,10 @@ const TinaCloudCollectionBase = z.object({
846
838
  });
847
839
  }
848
840
  }),
841
+ path: z.string().transform((val) => val.replace(/^\/|\/$/g, "")),
849
842
  format: z.enum(FORMATS).optional()
850
843
  });
851
- const TinaCloudCollection = TinaCloudCollectionBase.extend({
844
+ const TinaCloudCollection = CollectionBaseSchema.extend({
852
845
  fields: z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
853
846
  const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
854
847
  if (dups) {
@@ -910,9 +903,7 @@ class TinaSchemaValidationError extends Error {
910
903
  this.name = "TinaSchemaValidationError";
911
904
  }
912
905
  }
913
- const validateSchema = ({
914
- schema
915
- }) => {
906
+ const validateSchema = ({ schema }) => {
916
907
  try {
917
908
  TinaCloudSchemaZod.parse(schema);
918
909
  } catch (e) {
package/dist/index.js CHANGED
@@ -227,14 +227,6 @@
227
227
  this.getCollections = () => {
228
228
  return this.schema.collections.map((collection) => this.getCollection(collection.name)) || [];
229
229
  };
230
- this.getGlobalTemplate = (templateName) => {
231
- var _a;
232
- const globalTemplate = (_a = this.schema.templates) == null ? void 0 : _a.find((template) => template.name === templateName);
233
- if (!globalTemplate) {
234
- throw new Error(`Expected to find global template of name ${templateName}`);
235
- }
236
- return globalTemplate;
237
- };
238
230
  this.getCollectionByFullPath = (filepath) => {
239
231
  const possibleCollections = this.getCollections().filter((collection) => {
240
232
  return filepath.replace(/\\/g, "/").startsWith(collection.path.replace(/\/?$/, "/"));
@@ -392,11 +384,8 @@
392
384
  };
393
385
  this.getTemplatesForCollectable = (collection) => {
394
386
  let extraFields = [];
395
- if (collection.references) {
396
- extraFields = collection.references;
397
- }
398
387
  if (collection.fields) {
399
- const template = typeof collection.fields === "string" ? this.getGlobalTemplate(collection.fields) : collection;
388
+ const template = collection;
400
389
  if (typeof template.fields === "string" || typeof template.fields === "undefined") {
401
390
  throw new Error("Exptected template to have fields but none were found");
402
391
  }
@@ -414,7 +403,7 @@
414
403
  namespace: collection.namespace,
415
404
  type: "union",
416
405
  templates: collection.templates.map((templateOrTemplateString) => {
417
- const template = typeof templateOrTemplateString === "string" ? this.getGlobalTemplate(templateOrTemplateString) : templateOrTemplateString;
406
+ const template = templateOrTemplateString;
418
407
  return {
419
408
  ...template,
420
409
  fields: [...template.fields, ...extraFields]
@@ -431,7 +420,6 @@
431
420
  }
432
421
  const resolveField = (field, schema) => {
433
422
  var _a;
434
- field.parentTypename = NAMER.dataTypeName(field.namespace.filter((_, i) => i < field.namespace.length - 1));
435
423
  const extraFields = field.ui || {};
436
424
  switch (field.type) {
437
425
  case "number":
@@ -613,9 +601,24 @@
613
601
  const name = z.z.string({
614
602
  required_error: "Name is required but not provided",
615
603
  invalid_type_error: "Name must be a string"
616
- }).refine((val) => val.match(/^[a-zA-Z0-9_]*$/) !== null, (val) => ({
617
- message: `name, "${val}" must be alphanumeric and can only contain underscores`
618
- }));
604
+ }).superRefine((val, ctx) => {
605
+ if (val.match(/^[a-zA-Z0-9_]*$/) === null) {
606
+ ctx.addIssue({
607
+ code: "custom",
608
+ message: `name, "${val}" must be alphanumeric and can only contain underscores. (No spaces, dashes, special characters, etc.)
609
+ If you only want to display this value in the CMS UI, you can use the label property to customize it.
610
+
611
+ If you need to use this value in your content you can use the \`nameOverride\` property to customize the value. For example:
612
+ \`\`\`
613
+ {
614
+ "name": ${val.replace(/[^a-zA-Z0-9]/g, "_")},
615
+ "nameOverride": ${val},
616
+ // ...
617
+ }
618
+ \`\`\``
619
+ });
620
+ }
621
+ });
619
622
  const TypeName = [
620
623
  "string",
621
624
  "boolean",
@@ -628,17 +631,6 @@
628
631
  ];
629
632
  const typeTypeError = `type must be one of ${TypeName.join(", ")}`;
630
633
  const typeRequiredError = `type is required and must be one of ${TypeName.join(", ")}`;
631
- const nameProp = z.z.string({
632
- required_error: "name must be provided",
633
- invalid_type_error: "name must be a sting"
634
- }).superRefine((val, ctx) => {
635
- if (val.includes(" "))
636
- ctx.addIssue({
637
- message: `name "${val}" cannot contain spaces`,
638
- code: z.z.ZodIssueCode.custom,
639
- fatal: true
640
- });
641
- });
642
634
  const Option = z.z.union([
643
635
  z.z.string(),
644
636
  z.z.object({ label: z.z.string(), value: z.z.string() }),
@@ -651,7 +643,7 @@
651
643
  }
652
644
  });
653
645
  const TinaField = z.z.object({
654
- name: nameProp,
646
+ name,
655
647
  label: z.z.string().or(z.z.boolean()).optional(),
656
648
  description: z.z.string().optional(),
657
649
  required: z.z.boolean().optional()
@@ -702,7 +694,7 @@
702
694
  const TinaFieldZod = z.z.lazy(() => {
703
695
  const TemplateTemp = z.z.object({
704
696
  label: z.z.string().optional(),
705
- name: nameProp,
697
+ name,
706
698
  fields: z.z.array(TinaFieldZod),
707
699
  match: z.z.object({
708
700
  start: z.z.string(),
@@ -863,7 +855,7 @@ ${JSON.stringify(val, null, 2)}
863
855
  });
864
856
  }
865
857
  });
866
- const TinaCloudCollectionBase = z.z.object({
858
+ const CollectionBaseSchema = z.z.object({
867
859
  label: z.z.string().optional(),
868
860
  name: name.superRefine((val, ctx) => {
869
861
  if (val === "relativePath") {
@@ -873,9 +865,10 @@ ${JSON.stringify(val, null, 2)}
873
865
  });
874
866
  }
875
867
  }),
868
+ path: z.z.string().transform((val) => val.replace(/^\/|\/$/g, "")),
876
869
  format: z.z.enum(FORMATS).optional()
877
870
  });
878
- const TinaCloudCollection = TinaCloudCollectionBase.extend({
871
+ const TinaCloudCollection = CollectionBaseSchema.extend({
879
872
  fields: z.z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
880
873
  const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
881
874
  if (dups) {
@@ -937,9 +930,7 @@ ${JSON.stringify(val, null, 2)}
937
930
  this.name = "TinaSchemaValidationError";
938
931
  }
939
932
  }
940
- const validateSchema = ({
941
- schema
942
- }) => {
933
+ const validateSchema = ({ schema }) => {
943
934
  try {
944
935
  TinaCloudSchemaZod.parse(schema);
945
936
  } catch (e) {
@@ -1,7 +1,4 @@
1
- /**
2
-
3
- */
4
- import { TinaCloudSchemaEnriched, TinaCloudSchemaBase, TinaCloudCollection, Templateable, Collectable, CollectionTemplateable } from '../types/index';
1
+ import { Schema, Collection, Template, Collectable, CollectionTemplateable } from '../types/index';
5
2
  declare type Version = {
6
3
  fullVersion: string;
7
4
  major: string;
@@ -20,39 +17,29 @@ export declare class TinaSchema {
20
17
  config: {
21
18
  version?: Version;
22
19
  meta?: Meta;
23
- } & TinaCloudSchemaBase;
24
- schema: TinaCloudSchemaEnriched;
20
+ } & Schema;
21
+ schema: Schema<true>;
25
22
  /**
26
- *
27
23
  * Create a schema class from a user defined schema object
28
- *
29
- * @param {{version?:Version;meta?:Meta}&TinaCloudSchemaBase} config
30
24
  */
31
25
  constructor(config: {
32
26
  version?: Version;
33
27
  meta?: Meta;
34
- } & TinaCloudSchemaBase);
28
+ } & Schema);
35
29
  getIsTitleFieldName: (collection: string) => string;
36
- getCollectionsByName: (collectionNames: string[]) => TinaCloudCollection<true>[];
30
+ getCollectionsByName: (collectionNames: string[]) => Collection<true>[];
37
31
  getAllCollectionPaths: () => string[];
38
- getCollection: (collectionName: string) => TinaCloudCollection<true>;
39
- getCollections: () => TinaCloudCollection<true>[];
40
- getGlobalTemplate: (templateName: string) => {
41
- label: string;
42
- name: string;
43
- ui?: import("../types/SchemaTypes").UICollection;
44
- fields: import("../types/SchemaTypes").TinaFieldInner<true>[];
45
- namespace: string[];
46
- };
47
- getCollectionByFullPath: (filepath: string) => TinaCloudCollection<true>;
32
+ getCollection: (collectionName: string) => Collection<true>;
33
+ getCollections: () => Collection<true>[];
34
+ getCollectionByFullPath: (filepath: string) => Collection<true>;
48
35
  getCollectionAndTemplateByFullPath: (filepath: string, templateName?: string) => {
49
- collection: TinaCloudCollection<true>;
50
- template: Templateable;
36
+ collection: Collection<true>;
37
+ template: Template<true>;
51
38
  };
52
39
  getTemplateForData: ({ data, collection, }: {
53
40
  data?: unknown;
54
41
  collection: Collectable;
55
- }) => Templateable;
42
+ }) => Template<true>;
56
43
  transformPayload: (collectionName: string, payload: object) => {
57
44
  [x: string]: {
58
45
  [x: string]: {};
@@ -1,20 +1,14 @@
1
1
  /**
2
2
 
3
3
  */
4
- import { TinaFieldEnriched } from '../types/index';
4
+ import { TinaField } from '../types/index';
5
5
  import { TinaSchema } from './TinaSchema';
6
6
  /**
7
- *
8
7
  * Turns a field the schema (schema.{js,ts} file) into a valid front end FieldConfig
9
- *
10
- *
11
- * @param {TinaFieldEnriched} field. The field that will be transformed
12
- * @param {TinaSchema} schema the entireT Tina Schema
13
- * @returns unknown
14
8
  */
15
- export declare const resolveField: (field: TinaFieldEnriched, schema: TinaSchema) => {
9
+ export declare const resolveField: (field: TinaField<true>, schema: TinaSchema) => {
16
10
  [key: string]: unknown;
17
11
  name: string;
18
- component: string;
12
+ component: TinaField<true>['ui']['component'];
19
13
  type: string;
20
14
  };
@@ -1,7 +1,8 @@
1
1
  /**
2
2
 
3
3
  */
4
- import type { ResolveFormArgs } from '../types/index';
4
+ import type { Template, Collection } from '../types/index';
5
+ import type { TinaSchema } from './TinaSchema';
5
6
  /**
6
7
  * Given a collection, basename, template and schema. This will transform the given information into a valid frontend form config
7
8
  */
@@ -12,7 +13,156 @@ export declare const resolveForm: ({ collection, basename, template, schema, }:
12
13
  fields: {
13
14
  [key: string]: unknown;
14
15
  name: string;
15
- component: string;
16
+ component: string | ((props: {
17
+ field: import("../types/index").TinaField<false> & {
18
+ namespace: string[];
19
+ };
20
+ input: {
21
+ name: string;
22
+ onBlur: (event?: any) => void;
23
+ onChange: (event: any) => void;
24
+ onFocus: (event?: any) => void;
25
+ type?: string;
26
+ value: string[];
27
+ };
28
+ meta: {
29
+ active?: boolean;
30
+ dirty?: boolean;
31
+ error?: any;
32
+ };
33
+ }) => any) | ((props: {
34
+ field: import("../types/index").TinaField<false> & {
35
+ namespace: string[];
36
+ };
37
+ input: {
38
+ name: string;
39
+ onBlur: (event?: any) => void;
40
+ onChange: (event: any) => void;
41
+ onFocus: (event?: any) => void;
42
+ type?: string;
43
+ value: number[];
44
+ };
45
+ meta: {
46
+ active?: boolean;
47
+ dirty?: boolean;
48
+ error?: any;
49
+ };
50
+ }) => any) | ((props: {
51
+ field: import("../types/index").TinaField<false> & {
52
+ namespace: string[];
53
+ };
54
+ input: {
55
+ name: string;
56
+ onBlur: (event?: any) => void;
57
+ onChange: (event: any) => void;
58
+ onFocus: (event?: any) => void;
59
+ type?: string;
60
+ value: boolean[];
61
+ };
62
+ meta: {
63
+ active?: boolean;
64
+ dirty?: boolean;
65
+ error?: any;
66
+ };
67
+ }) => any) | ((props: {
68
+ field: import("../types/index").TinaField<false> & {
69
+ namespace: string[];
70
+ };
71
+ input: {
72
+ name: string;
73
+ onBlur: (event?: any) => void;
74
+ onChange: (event: any) => void;
75
+ onFocus: (event?: any) => void;
76
+ type?: string;
77
+ value: {
78
+ type: "root";
79
+ children: Record<string, unknown>[];
80
+ }[];
81
+ };
82
+ meta: {
83
+ active?: boolean;
84
+ dirty?: boolean;
85
+ error?: any;
86
+ };
87
+ }) => any) | ((props: {
88
+ field: import("../types/index").TinaField<false> & {
89
+ namespace: string[];
90
+ };
91
+ input: {
92
+ name: string;
93
+ onBlur: (event?: any) => void;
94
+ onChange: (event: any) => void;
95
+ onFocus: (event?: any) => void;
96
+ type?: string;
97
+ value: string;
98
+ };
99
+ meta: {
100
+ active?: boolean;
101
+ dirty?: boolean;
102
+ error?: any;
103
+ };
104
+ }) => any) | ((props: {
105
+ field: import("../types/index").TinaField<false> & {
106
+ namespace: string[];
107
+ };
108
+ input: {
109
+ name: string;
110
+ onBlur: (event?: any) => void;
111
+ onChange: (event: any) => void;
112
+ onFocus: (event?: any) => void;
113
+ type?: string;
114
+ value: number;
115
+ };
116
+ meta: {
117
+ active?: boolean;
118
+ dirty?: boolean;
119
+ error?: any;
120
+ };
121
+ }) => any) | ((props: {
122
+ field: import("../types/index").TinaField<false> & {
123
+ namespace: string[];
124
+ };
125
+ input: {
126
+ name: string;
127
+ onBlur: (event?: any) => void;
128
+ onChange: (event: any) => void;
129
+ onFocus: (event?: any) => void;
130
+ type?: string;
131
+ value: boolean;
132
+ };
133
+ meta: {
134
+ active?: boolean;
135
+ dirty?: boolean;
136
+ error?: any;
137
+ };
138
+ }) => any) | ((props: {
139
+ field: import("../types/index").TinaField<false> & {
140
+ namespace: string[];
141
+ };
142
+ input: {
143
+ name: string;
144
+ onBlur: (event?: any) => void;
145
+ onChange: (event: any) => void;
146
+ onFocus: (event?: any) => void;
147
+ type?: string;
148
+ value: {
149
+ type: "root";
150
+ children: Record<string, unknown>[];
151
+ };
152
+ };
153
+ meta: {
154
+ active?: boolean;
155
+ dirty?: boolean;
156
+ error?: any;
157
+ };
158
+ }) => any);
16
159
  type: string;
17
160
  }[];
18
161
  };
162
+ declare type ResolveFormArgs = {
163
+ collection: Collection<true>;
164
+ basename: string;
165
+ template: Template<true>;
166
+ schema: TinaSchema;
167
+ };
168
+ export {};