@tinacms/schema-tools 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -13,3 +13,4 @@ limitations under the License.
13
13
  export * from './schema';
14
14
  export * from './types';
15
15
  export * from './validate';
16
+ export * from './util/namer';
package/dist/index.es.js CHANGED
@@ -165,7 +165,7 @@ class TinaSchema {
165
165
  };
166
166
  this.getCollectionByFullPath = (filepath) => {
167
167
  const collection = this.getCollections().find((collection2) => {
168
- return filepath.replace("\\", "/").startsWith(collection2.path);
168
+ return filepath.replace(/\\/g, "/").startsWith(collection2.path.replace(/\/?$/, "/"));
169
169
  });
170
170
  if (!collection) {
171
171
  throw new Error(`Unable to find collection for file at ${filepath}`);
@@ -211,6 +211,72 @@ class TinaSchema {
211
211
  return template;
212
212
  }
213
213
  };
214
+ this.transformPayload = (collectionName, payload) => {
215
+ const collection = this.getCollection(collectionName);
216
+ if (collection.templates) {
217
+ const template = collection.templates.find((template2) => {
218
+ if (typeof template2 === "string") {
219
+ throw new Error("Global templates not supported");
220
+ }
221
+ return payload["_template"] === template2.name;
222
+ });
223
+ if (!template) {
224
+ console.error(payload);
225
+ throw new Error(`Unable to find template for payload`);
226
+ }
227
+ if (typeof template === "string") {
228
+ throw new Error("Global templates not supported");
229
+ }
230
+ return {
231
+ [collectionName]: {
232
+ [template.name]: this.transformCollectablePayload(payload, template)
233
+ }
234
+ };
235
+ } else {
236
+ return {
237
+ [collectionName]: this.transformCollectablePayload(payload, collection)
238
+ };
239
+ }
240
+ };
241
+ this.transformCollectablePayload = (payload, collection) => {
242
+ const accumulator = {};
243
+ Object.entries(payload).forEach(([key, value]) => {
244
+ if (typeof collection.fields === "string") {
245
+ throw new Error("Global templates not supported");
246
+ }
247
+ const field = collection.fields.find((field2) => {
248
+ if (typeof field2 === "string") {
249
+ throw new Error("Global templates not supported");
250
+ }
251
+ return field2.name === key;
252
+ });
253
+ if (field) {
254
+ accumulator[key] = this.transformField(field, value);
255
+ }
256
+ });
257
+ return accumulator;
258
+ };
259
+ this.transformField = (field, value) => {
260
+ if (field.type === "object")
261
+ if (field.templates) {
262
+ if (field.list) {
263
+ assertShape(value, (yup2) => yup2.array(yup2.object({ _template: yup2.string().required() })));
264
+ return value.map((item) => {
265
+ const { _template, ...rest } = item;
266
+ return { [_template]: rest };
267
+ });
268
+ } else {
269
+ assertShape(value, (yup2) => yup2.object({ _template: yup2.string().required() }));
270
+ const { _template, ...rest } = value;
271
+ return { [_template]: rest };
272
+ }
273
+ } else {
274
+ return value;
275
+ }
276
+ else {
277
+ return value;
278
+ }
279
+ };
214
280
  this.isMarkdownCollection = (collectionName) => {
215
281
  const collection = this.getCollection(collectionName);
216
282
  const format = collection.format;
@@ -261,9 +327,9 @@ class TinaSchema {
261
327
  this.schema = config;
262
328
  }
263
329
  }
264
- const resolveField = ({ namespace, ...field }, schema) => {
330
+ const resolveField = (field, schema) => {
265
331
  var _a;
266
- field.parentTypename = NAMER.dataTypeName(namespace.filter((_, i) => i < namespace.length - 1));
332
+ field.parentTypename = NAMER.dataTypeName(field.namespace.filter((_, i) => i < field.namespace.length - 1));
267
333
  const extraFields = field.ui || {};
268
334
  switch (field.type) {
269
335
  case "number":
@@ -324,10 +390,7 @@ const resolveField = ({ namespace, ...field }, schema) => {
324
390
  ...extraFields
325
391
  };
326
392
  case "object":
327
- const templateInfo = schema.getTemplatesForCollectable({
328
- ...field,
329
- namespace
330
- });
393
+ const templateInfo = schema.getTemplatesForCollectable(field);
331
394
  if (templateInfo.type === "object") {
332
395
  return {
333
396
  ...field,
@@ -345,6 +408,7 @@ const resolveField = ({ namespace, ...field }, schema) => {
345
408
  templates2[lastItem(template.namespace)] = {
346
409
  label: template.label || templateName,
347
410
  key: templateName,
411
+ namespace: [...field.namespace, templateName],
348
412
  fields: template.fields.map((field2) => resolveField(field2, schema)),
349
413
  ...extraFields2
350
414
  };
@@ -353,6 +417,7 @@ const resolveField = ({ namespace, ...field }, schema) => {
353
417
  return {
354
418
  ...field,
355
419
  typeMap: typeMap2,
420
+ namespace: field.namespace,
356
421
  component: field.list ? "blocks" : "not-implemented",
357
422
  templates: templates2,
358
423
  ...extraFields
@@ -761,4 +826,4 @@ const validateSchema = ({
761
826
  }
762
827
  }
763
828
  };
764
- export { TinaSchema, TinaSchemaValidationError, addNamespaceToSchema, resolveField, resolveForm, validateSchema, validateTinaCloudSchemaConfig };
829
+ export { NAMER, TinaSchema, TinaSchemaValidationError, addNamespaceToSchema, resolveField, resolveForm, validateSchema, validateTinaCloudSchemaConfig };
package/dist/index.js CHANGED
@@ -192,7 +192,7 @@
192
192
  };
193
193
  this.getCollectionByFullPath = (filepath) => {
194
194
  const collection = this.getCollections().find((collection2) => {
195
- return filepath.replace("\\", "/").startsWith(collection2.path);
195
+ return filepath.replace(/\\/g, "/").startsWith(collection2.path.replace(/\/?$/, "/"));
196
196
  });
197
197
  if (!collection) {
198
198
  throw new Error(`Unable to find collection for file at ${filepath}`);
@@ -238,6 +238,72 @@
238
238
  return template;
239
239
  }
240
240
  };
241
+ this.transformPayload = (collectionName, payload) => {
242
+ const collection = this.getCollection(collectionName);
243
+ if (collection.templates) {
244
+ const template = collection.templates.find((template2) => {
245
+ if (typeof template2 === "string") {
246
+ throw new Error("Global templates not supported");
247
+ }
248
+ return payload["_template"] === template2.name;
249
+ });
250
+ if (!template) {
251
+ console.error(payload);
252
+ throw new Error(`Unable to find template for payload`);
253
+ }
254
+ if (typeof template === "string") {
255
+ throw new Error("Global templates not supported");
256
+ }
257
+ return {
258
+ [collectionName]: {
259
+ [template.name]: this.transformCollectablePayload(payload, template)
260
+ }
261
+ };
262
+ } else {
263
+ return {
264
+ [collectionName]: this.transformCollectablePayload(payload, collection)
265
+ };
266
+ }
267
+ };
268
+ this.transformCollectablePayload = (payload, collection) => {
269
+ const accumulator = {};
270
+ Object.entries(payload).forEach(([key, value]) => {
271
+ if (typeof collection.fields === "string") {
272
+ throw new Error("Global templates not supported");
273
+ }
274
+ const field = collection.fields.find((field2) => {
275
+ if (typeof field2 === "string") {
276
+ throw new Error("Global templates not supported");
277
+ }
278
+ return field2.name === key;
279
+ });
280
+ if (field) {
281
+ accumulator[key] = this.transformField(field, value);
282
+ }
283
+ });
284
+ return accumulator;
285
+ };
286
+ this.transformField = (field, value) => {
287
+ if (field.type === "object")
288
+ if (field.templates) {
289
+ if (field.list) {
290
+ assertShape(value, (yup2) => yup2.array(yup2.object({ _template: yup2.string().required() })));
291
+ return value.map((item) => {
292
+ const { _template, ...rest } = item;
293
+ return { [_template]: rest };
294
+ });
295
+ } else {
296
+ assertShape(value, (yup2) => yup2.object({ _template: yup2.string().required() }));
297
+ const { _template, ...rest } = value;
298
+ return { [_template]: rest };
299
+ }
300
+ } else {
301
+ return value;
302
+ }
303
+ else {
304
+ return value;
305
+ }
306
+ };
241
307
  this.isMarkdownCollection = (collectionName) => {
242
308
  const collection = this.getCollection(collectionName);
243
309
  const format = collection.format;
@@ -288,9 +354,9 @@
288
354
  this.schema = config;
289
355
  }
290
356
  }
291
- const resolveField = ({ namespace, ...field }, schema) => {
357
+ const resolveField = (field, schema) => {
292
358
  var _a;
293
- field.parentTypename = NAMER.dataTypeName(namespace.filter((_, i) => i < namespace.length - 1));
359
+ field.parentTypename = NAMER.dataTypeName(field.namespace.filter((_, i) => i < field.namespace.length - 1));
294
360
  const extraFields = field.ui || {};
295
361
  switch (field.type) {
296
362
  case "number":
@@ -351,10 +417,7 @@
351
417
  ...extraFields
352
418
  };
353
419
  case "object":
354
- const templateInfo = schema.getTemplatesForCollectable({
355
- ...field,
356
- namespace
357
- });
420
+ const templateInfo = schema.getTemplatesForCollectable(field);
358
421
  if (templateInfo.type === "object") {
359
422
  return {
360
423
  ...field,
@@ -372,6 +435,7 @@
372
435
  templates2[lastItem(template.namespace)] = {
373
436
  label: template.label || templateName,
374
437
  key: templateName,
438
+ namespace: [...field.namespace, templateName],
375
439
  fields: template.fields.map((field2) => resolveField(field2, schema)),
376
440
  ...extraFields2
377
441
  };
@@ -380,6 +444,7 @@
380
444
  return {
381
445
  ...field,
382
446
  typeMap: typeMap2,
447
+ namespace: field.namespace,
383
448
  component: field.list ? "blocks" : "not-implemented",
384
449
  templates: templates2,
385
450
  ...extraFields
@@ -788,6 +853,7 @@ ${JSON.stringify(val, null, 2)}
788
853
  }
789
854
  }
790
855
  };
856
+ exports2.NAMER = NAMER;
791
857
  exports2.TinaSchema = TinaSchema;
792
858
  exports2.TinaSchemaValidationError = TinaSchemaValidationError;
793
859
  exports2.addNamespaceToSchema = addNamespaceToSchema;
@@ -64,6 +64,13 @@ export declare class TinaSchema {
64
64
  data?: unknown;
65
65
  collection: Collectable;
66
66
  }) => Templateable;
67
+ transformPayload: (collectionName: string, payload: object) => {
68
+ [x: string]: {
69
+ [x: string]: {};
70
+ };
71
+ };
72
+ private transformCollectablePayload;
73
+ private transformField;
67
74
  isMarkdownCollection: (collectionName: string) => boolean;
68
75
  /**
69
76
  * Gets the template or templates from the item.
@@ -21,4 +21,9 @@ import { TinaSchema } from './TinaSchema';
21
21
  * @param {TinaSchema} schema the entireT Tina Schema
22
22
  * @returns unknown
23
23
  */
24
- export declare const resolveField: ({ namespace, ...field }: TinaFieldEnriched, schema: TinaSchema) => unknown;
24
+ export declare const resolveField: (field: TinaFieldEnriched, schema: TinaSchema) => {
25
+ [key: string]: unknown;
26
+ name: string;
27
+ component: string;
28
+ type: string;
29
+ };
@@ -18,5 +18,10 @@ export declare const resolveForm: ({ collection, basename, template, schema, }:
18
18
  id: string;
19
19
  label: string;
20
20
  name: string;
21
- fields: unknown[];
21
+ fields: {
22
+ [key: string]: unknown;
23
+ name: string;
24
+ component: string;
25
+ type: string;
26
+ }[];
22
27
  };
@@ -56,10 +56,17 @@ declare type Document = {
56
56
  extension: string;
57
57
  };
58
58
  };
59
+ export declare type TinaIndex = {
60
+ name: string;
61
+ fields: {
62
+ name: string;
63
+ }[];
64
+ };
59
65
  interface BaseCollection {
60
66
  label?: string;
61
67
  name: string;
62
68
  path: string;
69
+ indexes?: TinaIndex[];
63
70
  format?: FormatType;
64
71
  ui?: {
65
72
  /**
@@ -117,11 +124,12 @@ export declare type TinaFieldEnriched = TinaFieldInner<true> & {
117
124
  */
118
125
  parentTypename?: string;
119
126
  };
120
- interface TinaField {
127
+ export interface TinaField {
121
128
  name: string;
122
129
  label?: string;
123
130
  description?: string;
124
131
  required?: boolean;
132
+ indexed?: boolean;
125
133
  /**
126
134
  * Any items passed to the UI field will be passed to the underlying field.
127
135
  * NOTE: only serializable values are supported, so functions like `validate`
@@ -0,0 +1,101 @@
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
+ import { TinaCloudSchema } from './SchemaTypes';
14
+ /**
15
+ * Used with `defineStaticConfig`
16
+ *
17
+ * These are mostly similar types as whats in `schemaTypes`
18
+ * but since those have gone through several iterations
19
+ * they're pretty messy. These should act as the happy path
20
+ * for iframe/standalone setups which we hope to eventually
21
+ * make the default/only path for all Tina users.
22
+ */
23
+ export declare type TinaCMSConfig<CMSCallback = undefined, FormifyCallback = undefined, DocumentCreatorCallback = undefined, Store = undefined> = {
24
+ schema: TinaCloudSchema<false>;
25
+ /**
26
+ * The base branch to pull content from. Note that this is ignored for local development
27
+ */
28
+ branch: string | null;
29
+ /**
30
+ * Your clientId from app.tina.io
31
+ */
32
+ clientId: string | null;
33
+ /**
34
+ * Your read only token from app.tina.io
35
+ */
36
+ token: string | null;
37
+ /**
38
+ * Configurations for the autogenerated GraphQL HTTP client
39
+ */
40
+ client?: {
41
+ /**
42
+ * Autogenerated queries will traverse references to a given depth
43
+ * @default 2
44
+ */
45
+ referenceDepth?: number;
46
+ };
47
+ build: {
48
+ /**
49
+ * The folder where your application stores assets, eg. `"public"`
50
+ */
51
+ publicFolder: string;
52
+ /**
53
+ * TinaCMS is shipped as a single-page app, the value specified here will
54
+ * determine the path when visiting the TinaCMS dashboard.
55
+ *
56
+ * Eg. `"admin"` will be viewable at `[your-development-url]/admin/index.html`
57
+ */
58
+ outputFolder: string;
59
+ };
60
+ media?: {
61
+ /**
62
+ * Load a media store like Cloudinary
63
+ *
64
+ * ```ts
65
+ * loadCustomStore = async () => {
66
+ * const pack = await import("next-tinacms-cloudinary");
67
+ * return pack.TinaCloudCloudinaryMediaStore;
68
+ * }
69
+ * ```
70
+ */
71
+ loadCustomStore: () => Promise<Store>;
72
+ tina?: never;
73
+ } | {
74
+ /**
75
+ * Use Git-backed assets for media, these values will
76
+ * [Learn more](https://tina.io/docs/reference/media/repo-based/)
77
+ */
78
+ tina: {
79
+ /**
80
+ * The folder where your application stores assets, eg. `"public"`
81
+ */
82
+ publicFolder: string;
83
+ /**
84
+ * The root folder for media managed by Tina. For example, `"uploads"`
85
+ * would store content in `"<my-public-folder>/uploads"`
86
+ */
87
+ mediaRoot: string;
88
+ };
89
+ loadCustomStore?: never;
90
+ };
91
+ tinaioConfig?: {
92
+ assetsApiUrlOverride?: string;
93
+ frontendUrlOverride?: string;
94
+ identityApiUrlOverride?: string;
95
+ contentApiUrlOverride?: string;
96
+ };
97
+ cmsCallback?: CMSCallback;
98
+ formifyCallback?: FormifyCallback;
99
+ documentCreatorCallback?: DocumentCreatorCallback;
100
+ };
101
+ export {};
@@ -37,4 +37,13 @@ export interface TinaCloudSchemaConfig<Store = any> {
37
37
  mediaRoot: string;
38
38
  };
39
39
  };
40
+ /**
41
+ * Used to override the default Tina Cloud API URL
42
+ */
43
+ tinaioConfig?: {
44
+ assetsApiUrlOverride?: string;
45
+ frontendUrlOverride?: string;
46
+ identityApiUrlOverride?: string;
47
+ contentApiUrlOverride?: string;
48
+ };
40
49
  }
@@ -16,3 +16,4 @@ limitations under the License.
16
16
 
17
17
  */
18
18
  export * from './SchemaTypes';
19
+ export * from './SchemaTypes2';
@@ -0,0 +1,13 @@
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 {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinacms/schema-tools",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "main": "dist/index.js",
5
5
  "module": "./dist/index.es.js",
6
6
  "exports": {