@tinacms/schema-tools 0.0.8 → 0.1.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.
package/dist/index.es.js CHANGED
@@ -7,6 +7,9 @@ function addNamespaceToSchema(maybeNode, namespace = []) {
7
7
  if (typeof maybeNode === "boolean") {
8
8
  return maybeNode;
9
9
  }
10
+ if (typeof maybeNode === "function") {
11
+ return maybeNode;
12
+ }
10
13
  const newNode = { ...maybeNode };
11
14
  const keys = Object.keys(maybeNode);
12
15
  Object.values(maybeNode).map((m, index) => {
@@ -113,8 +116,9 @@ class TinaSchema {
113
116
  constructor(config) {
114
117
  this.config = config;
115
118
  this.getIsTitleFieldName = (collection) => {
119
+ var _a;
116
120
  const col = this.getCollection(collection);
117
- const field = col == null ? void 0 : col.fields.find((x) => x.type === "string" && x.isTitle);
121
+ const field = (_a = col == null ? void 0 : col.fields) == null ? void 0 : _a.find((x) => x.type === "string" && x.isTitle);
118
122
  return field == null ? void 0 : field.name;
119
123
  };
120
124
  this.getCollectionsByName = (collectionNames) => {
@@ -168,12 +172,7 @@ class TinaSchema {
168
172
  };
169
173
  this.getCollectionAndTemplateByFullPath = (filepath, templateName) => {
170
174
  let template;
171
- const collection = this.getCollections().find((collection2) => {
172
- return filepath.replace("\\", "/").startsWith(collection2.path);
173
- });
174
- if (!collection) {
175
- throw new Error(`Unable to find collection for file at ${filepath}`);
176
- }
175
+ const collection = this.getCollectionByFullPath(filepath);
177
176
  const templates = this.getTemplatesForCollectable(collection);
178
177
  if (templates.type === "union") {
179
178
  if (templateName) {
@@ -373,6 +372,7 @@ const resolveField = ({ namespace, ...field }, schema) => {
373
372
  key: templateName,
374
373
  inline: template.inline,
375
374
  name: templateName,
375
+ match: template.match,
376
376
  fields: template.fields.map((field2) => resolveField(field2, schema)),
377
377
  ...extraFields2
378
378
  };
@@ -436,7 +436,9 @@ const parseZodError = ({ zodError }) => {
436
436
  const name = z.string({
437
437
  required_error: "Name is required but not provided",
438
438
  invalid_type_error: "Name must be a string"
439
- });
439
+ }).refine((val) => val.match(/^[a-zA-Z0-9_]*$/) !== null, (val) => ({
440
+ message: `name, "${val}" must be alphanumeric and can only contain underscores`
441
+ }));
440
442
  const TypeName = [
441
443
  "string",
442
444
  "boolean",
@@ -452,6 +454,13 @@ const typeRequiredError = `type is required and must be one of ${TypeName.join("
452
454
  const nameProp = z.string({
453
455
  required_error: "name must be provided",
454
456
  invalid_type_error: "name must be a sting"
457
+ }).superRefine((val, ctx) => {
458
+ if (val.includes(" "))
459
+ ctx.addIssue({
460
+ message: "name cannot contain spaces",
461
+ code: z.ZodIssueCode.custom,
462
+ fatal: true
463
+ });
455
464
  });
456
465
  const Option = z.union([z.string(), z.object({ label: z.string(), value: z.string() })], {
457
466
  errorMap: () => {
@@ -513,7 +522,11 @@ const TinaFieldZod = z.lazy(() => {
513
522
  const TemplateTemp = z.object({
514
523
  label: z.string(),
515
524
  name: nameProp,
516
- fields: z.array(TinaFieldZod)
525
+ fields: z.array(TinaFieldZod),
526
+ match: z.object({
527
+ start: z.string(),
528
+ end: z.string()
529
+ }).optional()
517
530
  }).refine((val) => {
518
531
  var _a;
519
532
  return !hasDuplicates((_a = val.fields) == null ? void 0 : _a.map((x) => x.name));
@@ -607,6 +620,7 @@ const tinaConfigKey = z$1.object({
607
620
  mediaRoot: z$1.string()
608
621
  }).strict().optional();
609
622
  const tinaConfigZod = z$1.object({
623
+ client: z$1.object({ referenceDepth: z$1.number().optional() }).optional(),
610
624
  media: z$1.object({
611
625
  tina: tinaConfigKey,
612
626
  loadCustomStore: z$1.function().optional()
@@ -660,7 +674,7 @@ const TinaCloudSchemaZod = z.object({
660
674
  collections: z.array(TinaCloudCollection),
661
675
  config: tinaConfigZod.optional()
662
676
  }).superRefine((val, ctx) => {
663
- var _a;
677
+ var _a, _b;
664
678
  if (hasDuplicates(val.collections.map((x) => x.name))) {
665
679
  ctx.addIssue({
666
680
  code: z.ZodIssueCode.custom,
@@ -668,7 +682,12 @@ const TinaCloudSchemaZod = z.object({
668
682
  fatal: true
669
683
  });
670
684
  }
671
- const media = (_a = val == null ? void 0 : val.config) == null ? void 0 : _a.media;
685
+ (_a = val == null ? void 0 : val.collections) == null ? void 0 : _a.map((x) => {
686
+ if (!x.format) {
687
+ console.warn(`No format provided for collection ${x.name}, defaulting to .md`);
688
+ }
689
+ });
690
+ const media = (_b = val == null ? void 0 : val.config) == null ? void 0 : _b.media;
672
691
  if (media && media.tina && media.loadCustomStore) {
673
692
  ctx.addIssue({
674
693
  code: z.ZodIssueCode.custom,
package/dist/index.js CHANGED
@@ -34,6 +34,9 @@
34
34
  if (typeof maybeNode === "boolean") {
35
35
  return maybeNode;
36
36
  }
37
+ if (typeof maybeNode === "function") {
38
+ return maybeNode;
39
+ }
37
40
  const newNode = { ...maybeNode };
38
41
  const keys = Object.keys(maybeNode);
39
42
  Object.values(maybeNode).map((m, index) => {
@@ -140,8 +143,9 @@
140
143
  constructor(config) {
141
144
  this.config = config;
142
145
  this.getIsTitleFieldName = (collection) => {
146
+ var _a;
143
147
  const col = this.getCollection(collection);
144
- const field = col == null ? void 0 : col.fields.find((x) => x.type === "string" && x.isTitle);
148
+ const field = (_a = col == null ? void 0 : col.fields) == null ? void 0 : _a.find((x) => x.type === "string" && x.isTitle);
145
149
  return field == null ? void 0 : field.name;
146
150
  };
147
151
  this.getCollectionsByName = (collectionNames) => {
@@ -195,12 +199,7 @@
195
199
  };
196
200
  this.getCollectionAndTemplateByFullPath = (filepath, templateName) => {
197
201
  let template;
198
- const collection = this.getCollections().find((collection2) => {
199
- return filepath.replace("\\", "/").startsWith(collection2.path);
200
- });
201
- if (!collection) {
202
- throw new Error(`Unable to find collection for file at ${filepath}`);
203
- }
202
+ const collection = this.getCollectionByFullPath(filepath);
204
203
  const templates = this.getTemplatesForCollectable(collection);
205
204
  if (templates.type === "union") {
206
205
  if (templateName) {
@@ -400,6 +399,7 @@
400
399
  key: templateName,
401
400
  inline: template.inline,
402
401
  name: templateName,
402
+ match: template.match,
403
403
  fields: template.fields.map((field2) => resolveField(field2, schema)),
404
404
  ...extraFields2
405
405
  };
@@ -463,7 +463,9 @@
463
463
  const name = z.z.string({
464
464
  required_error: "Name is required but not provided",
465
465
  invalid_type_error: "Name must be a string"
466
- });
466
+ }).refine((val) => val.match(/^[a-zA-Z0-9_]*$/) !== null, (val) => ({
467
+ message: `name, "${val}" must be alphanumeric and can only contain underscores`
468
+ }));
467
469
  const TypeName = [
468
470
  "string",
469
471
  "boolean",
@@ -479,6 +481,13 @@
479
481
  const nameProp = z.z.string({
480
482
  required_error: "name must be provided",
481
483
  invalid_type_error: "name must be a sting"
484
+ }).superRefine((val, ctx) => {
485
+ if (val.includes(" "))
486
+ ctx.addIssue({
487
+ message: "name cannot contain spaces",
488
+ code: z.z.ZodIssueCode.custom,
489
+ fatal: true
490
+ });
482
491
  });
483
492
  const Option = z.z.union([z.z.string(), z.z.object({ label: z.z.string(), value: z.z.string() })], {
484
493
  errorMap: () => {
@@ -540,7 +549,11 @@
540
549
  const TemplateTemp = z.z.object({
541
550
  label: z.z.string(),
542
551
  name: nameProp,
543
- fields: z.z.array(TinaFieldZod)
552
+ fields: z.z.array(TinaFieldZod),
553
+ match: z.z.object({
554
+ start: z.z.string(),
555
+ end: z.z.string()
556
+ }).optional()
544
557
  }).refine((val) => {
545
558
  var _a;
546
559
  return !hasDuplicates((_a = val.fields) == null ? void 0 : _a.map((x) => x.name));
@@ -634,6 +647,7 @@
634
647
  mediaRoot: z__default["default"].string()
635
648
  }).strict().optional();
636
649
  const tinaConfigZod = z__default["default"].object({
650
+ client: z__default["default"].object({ referenceDepth: z__default["default"].number().optional() }).optional(),
637
651
  media: z__default["default"].object({
638
652
  tina: tinaConfigKey,
639
653
  loadCustomStore: z__default["default"].function().optional()
@@ -687,7 +701,7 @@
687
701
  collections: z.z.array(TinaCloudCollection),
688
702
  config: tinaConfigZod.optional()
689
703
  }).superRefine((val, ctx) => {
690
- var _a;
704
+ var _a, _b;
691
705
  if (hasDuplicates(val.collections.map((x) => x.name))) {
692
706
  ctx.addIssue({
693
707
  code: z.z.ZodIssueCode.custom,
@@ -695,7 +709,12 @@
695
709
  fatal: true
696
710
  });
697
711
  }
698
- const media = (_a = val == null ? void 0 : val.config) == null ? void 0 : _a.media;
712
+ (_a = val == null ? void 0 : val.collections) == null ? void 0 : _a.map((x) => {
713
+ if (!x.format) {
714
+ console.warn(`No format provided for collection ${x.name}, defaulting to .md`);
715
+ }
716
+ });
717
+ const media = (_b = val == null ? void 0 : val.config) == null ? void 0 : _b.media;
699
718
  if (media && media.tina && media.loadCustomStore) {
700
719
  ctx.addIssue({
701
720
  code: z.z.ZodIssueCode.custom,
@@ -10,8 +10,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
10
  See the License for the specific language governing permissions and
11
11
  limitations under the License.
12
12
  */
13
- import { TinaSchema } from '../schema';
14
13
  import type { FC } from 'react';
14
+ import { TinaSchema } from '../schema';
15
+ import type { TinaCloudSchemaConfig } from './config';
15
16
  export declare type UIField<F extends UIField = any, Shape = any> = {
16
17
  label?: string;
17
18
  description?: string;
@@ -21,15 +22,6 @@ export declare type UIField<F extends UIField = any, Shape = any> = {
21
22
  validate?(value: Shape, allValues: any, meta: any, field: UIField<F, Shape>): string | object | undefined | void;
22
23
  defaultValue?: Shape;
23
24
  };
24
- export interface TinaCloudSchemaConfig<Store = any> {
25
- media?: {
26
- loadCustomStore?: () => Promise<Store>;
27
- tina?: {
28
- publicFolder: string;
29
- mediaRoot: string;
30
- };
31
- };
32
- }
33
25
  export interface TinaCloudSchema<WithNamespace extends boolean, Store = any> {
34
26
  templates?: GlobalTemplate<WithNamespace>[];
35
27
  collections: TinaCloudCollection<WithNamespace>[];
@@ -52,11 +44,46 @@ export declare type TinaCloudCollection<WithNamespace extends boolean> = Collect
52
44
  export declare type TinaCloudCollectionBase = TinaCloudCollection<false>;
53
45
  export declare type TinaCloudCollectionEnriched = TinaCloudCollection<true>;
54
46
  declare type FormatType = 'json' | 'md' | 'markdown' | 'mdx';
47
+ declare type Document = {
48
+ _sys: {
49
+ title?: string;
50
+ template: string;
51
+ breadcrumbs: string[];
52
+ path: string;
53
+ basename: string;
54
+ relativePath: string;
55
+ filename: string;
56
+ extension: string;
57
+ };
58
+ };
55
59
  interface BaseCollection {
56
60
  label?: string;
57
61
  name: string;
58
62
  path: string;
59
63
  format?: FormatType;
64
+ ui?: {
65
+ /**
66
+ * Forms for this collection will be editable from the global sidebar rather than the form panel
67
+ */
68
+ global?: boolean | {
69
+ icon?: any;
70
+ layout: 'fullscreen' | 'popup';
71
+ };
72
+ /**
73
+ * Provide the path that your document is viewable on your site
74
+ *
75
+ * eg:
76
+ * ```ts
77
+ * router: ({ document }) => {
78
+ * return `blog-posts/${document._sys.filename}`;
79
+ * }
80
+ * ```
81
+ */
82
+ router?: (args: {
83
+ document: Document;
84
+ collection: TinaCloudCollection<true>;
85
+ }) => string | undefined;
86
+ };
60
87
  match?: string;
61
88
  }
62
89
  declare type CollectionTemplates<WithNamespace extends boolean> = WithNamespace extends true ? CollectionTemplatesWithNamespace<WithNamespace> : CollectionTemplatesInner<WithNamespace>;
@@ -317,6 +344,10 @@ export declare type Template<WithNamespace extends boolean> = WithNamespace exte
317
344
  label: string;
318
345
  name: string;
319
346
  fields: TinaFieldInner<WithNamespace>[];
347
+ match?: {
348
+ start: string;
349
+ end: string;
350
+ };
320
351
  ui?: object | (UIField<any, any> & {
321
352
  previewSrc: string;
322
353
  });
@@ -328,6 +359,10 @@ export declare type Template<WithNamespace extends boolean> = WithNamespace exte
328
359
  previewSrc: string;
329
360
  });
330
361
  fields: TinaFieldInner<WithNamespace>[];
362
+ match?: {
363
+ start: string;
364
+ end: string;
365
+ };
331
366
  };
332
367
  export declare type CollectionTemplateableUnion = {
333
368
  namespace: string[];
@@ -360,4 +395,4 @@ export declare type ResolveFormArgs = {
360
395
  template: Templateable;
361
396
  schema: TinaSchema;
362
397
  };
363
- export {};
398
+ export * from './config';
@@ -0,0 +1,40 @@
1
+ /**
2
+ Copyright 2021 Forestry.io Holdings, Inc.
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+ http://www.apache.org/licenses/LICENSE-2.0
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
12
+ */
13
+ export interface TinaCloudSchemaConfig<Store = any> {
14
+ client?: {
15
+ referenceDepth?: number;
16
+ };
17
+ build?: {
18
+ publicFolder: string;
19
+ outputFolder: string;
20
+ };
21
+ /**
22
+ * The base branch to pull content from. Note that this is ignored for local development
23
+ */
24
+ branch?: string;
25
+ /**
26
+ * Your clientId from app.tina.io
27
+ */
28
+ clientId?: string;
29
+ /**
30
+ * Your read only token from app.tina.io
31
+ */
32
+ token?: string;
33
+ media?: {
34
+ loadCustomStore?: () => Promise<Store>;
35
+ tina?: {
36
+ publicFolder: string;
37
+ mediaRoot: string;
38
+ };
39
+ };
40
+ }
@@ -11,4 +11,4 @@ See the License for the specific language governing permissions and
11
11
  limitations under the License.
12
12
  */
13
13
  import { z } from 'zod';
14
- export declare const name: z.ZodString;
14
+ export declare const name: z.ZodEffects<z.ZodString, string, string>;
@@ -14,13 +14,13 @@ import { z } from 'zod';
14
14
  export declare const TinaCloudSchemaZod: z.ZodEffects<z.ZodObject<{
15
15
  collections: z.ZodArray<z.ZodEffects<z.ZodObject<z.extendShape<{
16
16
  label: z.ZodOptional<z.ZodString>;
17
- name: z.ZodString;
17
+ name: z.ZodEffects<z.ZodString, string, string>;
18
18
  format: z.ZodOptional<z.ZodEnum<["json", "md", "markdown", "mdx"]>>;
19
19
  }, {
20
20
  fields: z.ZodEffects<z.ZodEffects<z.ZodOptional<z.ZodArray<z.ZodType<import("..").TinaFieldInner<false>, z.ZodTypeDef, import("..").TinaFieldInner<false>>, "many">>, import("..").TinaFieldInner<false>[], import("..").TinaFieldInner<false>[]>, import("..").TinaFieldInner<false>[], import("..").TinaFieldInner<false>[]>;
21
21
  templates: z.ZodEffects<z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodObject<{
22
22
  label: z.ZodString;
23
- name: z.ZodString;
23
+ name: z.ZodEffects<z.ZodString, string, string>;
24
24
  fields: z.ZodArray<z.ZodType<import("..").TinaFieldInner<false>, z.ZodTypeDef, import("..").TinaFieldInner<false>>, "many">;
25
25
  }, "strip", z.ZodTypeAny, {
26
26
  name?: string;
@@ -89,6 +89,13 @@ export declare const TinaCloudSchemaZod: z.ZodEffects<z.ZodObject<{
89
89
  label?: string;
90
90
  }>, "many">;
91
91
  config: z.ZodOptional<z.ZodObject<{
92
+ client: z.ZodOptional<z.ZodObject<{
93
+ referenceDepth: z.ZodOptional<z.ZodNumber>;
94
+ }, "strip", z.ZodTypeAny, {
95
+ referenceDepth?: number;
96
+ }, {
97
+ referenceDepth?: number;
98
+ }>>;
92
99
  media: z.ZodOptional<z.ZodObject<{
93
100
  tina: z.ZodOptional<z.ZodObject<{
94
101
  publicFolder: z.ZodString;
@@ -115,6 +122,9 @@ export declare const TinaCloudSchemaZod: z.ZodEffects<z.ZodObject<{
115
122
  loadCustomStore?: (...args: unknown[]) => unknown;
116
123
  }>>;
117
124
  }, "strip", z.ZodTypeAny, {
125
+ client?: {
126
+ referenceDepth?: number;
127
+ };
118
128
  media?: {
119
129
  tina?: {
120
130
  publicFolder?: string;
@@ -123,6 +133,9 @@ export declare const TinaCloudSchemaZod: z.ZodEffects<z.ZodObject<{
123
133
  loadCustomStore?: (...args: unknown[]) => unknown;
124
134
  };
125
135
  }, {
136
+ client?: {
137
+ referenceDepth?: number;
138
+ };
126
139
  media?: {
127
140
  tina?: {
128
141
  publicFolder?: string;
@@ -144,6 +157,9 @@ export declare const TinaCloudSchemaZod: z.ZodEffects<z.ZodObject<{
144
157
  label?: string;
145
158
  }[];
146
159
  config?: {
160
+ client?: {
161
+ referenceDepth?: number;
162
+ };
147
163
  media?: {
148
164
  tina?: {
149
165
  publicFolder?: string;
@@ -165,6 +181,9 @@ export declare const TinaCloudSchemaZod: z.ZodEffects<z.ZodObject<{
165
181
  label?: string;
166
182
  }[];
167
183
  config?: {
184
+ client?: {
185
+ referenceDepth?: number;
186
+ };
168
187
  media?: {
169
188
  tina?: {
170
189
  publicFolder?: string;
@@ -186,6 +205,9 @@ export declare const TinaCloudSchemaZod: z.ZodEffects<z.ZodObject<{
186
205
  label?: string;
187
206
  }[];
188
207
  config?: {
208
+ client?: {
209
+ referenceDepth?: number;
210
+ };
189
211
  media?: {
190
212
  tina?: {
191
213
  publicFolder?: string;
@@ -207,6 +229,9 @@ export declare const TinaCloudSchemaZod: z.ZodEffects<z.ZodObject<{
207
229
  label?: string;
208
230
  }[];
209
231
  config?: {
232
+ client?: {
233
+ referenceDepth?: number;
234
+ };
210
235
  media?: {
211
236
  tina?: {
212
237
  publicFolder?: string;
@@ -13,6 +13,13 @@ limitations under the License.
13
13
  import { TinaCloudSchemaConfig } from '../types';
14
14
  import z from 'zod';
15
15
  export declare const tinaConfigZod: z.ZodObject<{
16
+ client: z.ZodOptional<z.ZodObject<{
17
+ referenceDepth: z.ZodOptional<z.ZodNumber>;
18
+ }, "strip", z.ZodTypeAny, {
19
+ referenceDepth?: number;
20
+ }, {
21
+ referenceDepth?: number;
22
+ }>>;
16
23
  media: z.ZodOptional<z.ZodObject<{
17
24
  tina: z.ZodOptional<z.ZodObject<{
18
25
  publicFolder: z.ZodString;
@@ -39,6 +46,9 @@ export declare const tinaConfigZod: z.ZodObject<{
39
46
  loadCustomStore?: (...args: unknown[]) => unknown;
40
47
  }>>;
41
48
  }, "strip", z.ZodTypeAny, {
49
+ client?: {
50
+ referenceDepth?: number;
51
+ };
42
52
  media?: {
43
53
  tina?: {
44
54
  publicFolder?: string;
@@ -47,6 +57,9 @@ export declare const tinaConfigZod: z.ZodObject<{
47
57
  loadCustomStore?: (...args: unknown[]) => unknown;
48
58
  };
49
59
  }, {
60
+ client?: {
61
+ referenceDepth?: number;
62
+ };
50
63
  media?: {
51
64
  tina?: {
52
65
  publicFolder?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinacms/schema-tools",
3
- "version": "0.0.8",
3
+ "version": "0.1.1",
4
4
  "main": "dist/index.js",
5
5
  "module": "./dist/index.es.js",
6
6
  "exports": {
@@ -23,7 +23,7 @@
23
23
  ]
24
24
  },
25
25
  "devDependencies": {
26
- "@tinacms/scripts": "0.50.9",
26
+ "@tinacms/scripts": "0.51.1",
27
27
  "@types/yup": "^0.29.10",
28
28
  "jest": "^27.0.6",
29
29
  "react": "17.0.2",