@tinacms/datalayer 0.2.0 → 0.2.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/LICENSE +176 -0
- package/dist/database/bridge/filesystem.d.ts +1 -1
- package/dist/database/store/index.d.ts +1 -1
- package/dist/index.js +41 -23
- package/package.json +8 -8
- package/CHANGELOG.md +0 -864
package/LICENSE
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
@@ -30,5 +30,5 @@ export declare class FilesystemBridge implements Bridge {
|
|
|
30
30
|
* Same as the `FileSystemBridge` except it does not save files
|
|
31
31
|
*/
|
|
32
32
|
export declare class AuditFileSystemBridge extends FilesystemBridge {
|
|
33
|
-
put(
|
|
33
|
+
put(filepath: string, data: string): Promise<void>;
|
|
34
34
|
}
|
|
@@ -140,5 +140,5 @@ export declare const makeFilterSuffixes: (filterChain: (BinaryFilter | TernaryFi
|
|
|
140
140
|
left?: string;
|
|
141
141
|
right?: string;
|
|
142
142
|
} | undefined;
|
|
143
|
-
export declare const makeKeyForField: (definition: IndexDefinition, data: object, stringEscaper: StringEscaper) => string | null;
|
|
143
|
+
export declare const makeKeyForField: (definition: IndexDefinition, data: object, stringEscaper: StringEscaper, maxStringLength?: number) => string | null;
|
|
144
144
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -51,7 +51,7 @@ var __toModule = (module2) => {
|
|
|
51
51
|
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
-
//
|
|
54
|
+
// src/index.ts
|
|
55
55
|
__export(exports, {
|
|
56
56
|
AuditFileSystemBridge: () => AuditFileSystemBridge,
|
|
57
57
|
AuditFilesystemStore: () => AuditFilesystemStore,
|
|
@@ -73,7 +73,7 @@ __export(exports, {
|
|
|
73
73
|
makeStringEscaper: () => makeStringEscaper
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
//
|
|
76
|
+
// src/database/bridge/filesystem.ts
|
|
77
77
|
var import_fs_extra = __toModule(require("fs-extra"));
|
|
78
78
|
var import_fast_glob = __toModule(require("fast-glob"));
|
|
79
79
|
var import_path = __toModule(require("path"));
|
|
@@ -109,17 +109,25 @@ var FilesystemBridge = class {
|
|
|
109
109
|
}
|
|
110
110
|
};
|
|
111
111
|
var AuditFileSystemBridge = class extends FilesystemBridge {
|
|
112
|
-
async put(
|
|
112
|
+
async put(filepath, data) {
|
|
113
|
+
if ([
|
|
114
|
+
".tina/__generated__/_lookup.json",
|
|
115
|
+
".tina/__generated__/_schema.json",
|
|
116
|
+
".tina/__generated__/_graphql.json"
|
|
117
|
+
].includes(filepath)) {
|
|
118
|
+
return super.put(filepath, data);
|
|
119
|
+
}
|
|
113
120
|
return;
|
|
114
121
|
}
|
|
115
122
|
};
|
|
116
123
|
|
|
117
|
-
//
|
|
124
|
+
// src/database/bridge/isomorphic.ts
|
|
118
125
|
var import_isomorphic_git = __toModule(require("isomorphic-git"));
|
|
119
126
|
var import_fs_extra2 = __toModule(require("fs-extra"));
|
|
120
127
|
var import_glob_parent = __toModule(require("glob-parent"));
|
|
121
128
|
var import_normalize_path2 = __toModule(require("normalize-path"));
|
|
122
129
|
var import_graphql = __toModule(require("graphql"));
|
|
130
|
+
var import_path2 = __toModule(require("path"));
|
|
123
131
|
var flat = typeof Array.prototype.flat === "undefined" ? (entries) => entries.reduce((acc, x) => acc.concat(x), []) : (entries) => entries.flat();
|
|
124
132
|
var toUint8Array = (buf) => {
|
|
125
133
|
const ab = new ArrayBuffer(buf.length);
|
|
@@ -208,9 +216,18 @@ var IsomorphicBridge = class {
|
|
|
208
216
|
let pathParts = path4.split("/");
|
|
209
217
|
const result = await import_isomorphic_git.default.walk(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
|
|
210
218
|
map: async (filepath, [head]) => {
|
|
211
|
-
if (head._fullpath === "."
|
|
219
|
+
if (head._fullpath === ".") {
|
|
212
220
|
return head;
|
|
213
221
|
}
|
|
222
|
+
if (path4.startsWith(filepath)) {
|
|
223
|
+
if ((0, import_path2.dirname)(path4) === (0, import_path2.dirname)(filepath)) {
|
|
224
|
+
if (path4 === filepath) {
|
|
225
|
+
return head;
|
|
226
|
+
}
|
|
227
|
+
} else {
|
|
228
|
+
return head;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
214
231
|
},
|
|
215
232
|
cache: this.cache,
|
|
216
233
|
trees: [import_isomorphic_git.default.TREE({ ref })]
|
|
@@ -431,16 +448,16 @@ var IsomorphicBridge = class {
|
|
|
431
448
|
}
|
|
432
449
|
};
|
|
433
450
|
|
|
434
|
-
//
|
|
451
|
+
// src/database/store/filesystem.ts
|
|
435
452
|
var import_fs_extra3 = __toModule(require("fs-extra"));
|
|
436
453
|
var import_fast_glob2 = __toModule(require("fast-glob"));
|
|
437
|
-
var
|
|
454
|
+
var import_path3 = __toModule(require("path"));
|
|
438
455
|
var import_normalize_path3 = __toModule(require("normalize-path"));
|
|
439
456
|
|
|
440
|
-
//
|
|
457
|
+
// src/database/util.ts
|
|
441
458
|
var import_gray_matter = __toModule(require("gray-matter"));
|
|
442
459
|
|
|
443
|
-
//
|
|
460
|
+
// src/util.ts
|
|
444
461
|
var yup = __toModule(require("yup"));
|
|
445
462
|
var import_graphql2 = __toModule(require("graphql"));
|
|
446
463
|
var sequential = async (items, callback) => {
|
|
@@ -479,7 +496,7 @@ var btoa = (string) => {
|
|
|
479
496
|
return Buffer.from(string).toString("base64");
|
|
480
497
|
};
|
|
481
498
|
|
|
482
|
-
//
|
|
499
|
+
// src/database/util.ts
|
|
483
500
|
var stringifyFile = (content, format, keepTemplateKey) => {
|
|
484
501
|
switch (format) {
|
|
485
502
|
case ".markdown":
|
|
@@ -534,7 +551,7 @@ var parseFile = (content, format, yupSchema) => {
|
|
|
534
551
|
}
|
|
535
552
|
};
|
|
536
553
|
|
|
537
|
-
//
|
|
554
|
+
// src/database/store/filesystem.ts
|
|
538
555
|
var FilesystemStore = class {
|
|
539
556
|
async clear() {
|
|
540
557
|
}
|
|
@@ -550,7 +567,7 @@ var FilesystemStore = class {
|
|
|
550
567
|
throw new Error(`Seeding data is not possible for Filesystem store`);
|
|
551
568
|
}
|
|
552
569
|
async get(filepath) {
|
|
553
|
-
return parseFile(await import_fs_extra3.default.readFileSync(
|
|
570
|
+
return parseFile(await import_fs_extra3.default.readFileSync(import_path3.default.join(this.rootPath, filepath)).toString(), import_path3.default.extname(filepath), (yup2) => yup2.object());
|
|
554
571
|
}
|
|
555
572
|
supportsSeeding() {
|
|
556
573
|
return false;
|
|
@@ -559,8 +576,8 @@ var FilesystemStore = class {
|
|
|
559
576
|
return false;
|
|
560
577
|
}
|
|
561
578
|
async glob(pattern, callback, extension) {
|
|
562
|
-
const basePath =
|
|
563
|
-
const itemsRaw = await (0, import_fast_glob2.default)(
|
|
579
|
+
const basePath = import_path3.default.join(this.rootPath, ...pattern.split("/"));
|
|
580
|
+
const itemsRaw = await (0, import_fast_glob2.default)(import_path3.default.join(basePath, "**", `/*${extension}`).replace(/\\/g, "/"), {
|
|
564
581
|
dot: true
|
|
565
582
|
});
|
|
566
583
|
const posixRootPath = (0, import_normalize_path3.default)(this.rootPath);
|
|
@@ -576,14 +593,14 @@ var FilesystemStore = class {
|
|
|
576
593
|
}
|
|
577
594
|
}
|
|
578
595
|
async put(filepath, data, options) {
|
|
579
|
-
await import_fs_extra3.default.outputFileSync(
|
|
596
|
+
await import_fs_extra3.default.outputFileSync(import_path3.default.join(this.rootPath, filepath), stringifyFile(data, import_path3.default.extname(filepath), options.keepTemplateKey));
|
|
580
597
|
}
|
|
581
598
|
async open() {
|
|
582
599
|
}
|
|
583
600
|
async close() {
|
|
584
601
|
}
|
|
585
602
|
async delete(filepath) {
|
|
586
|
-
await import_fs_extra3.default.remove(
|
|
603
|
+
await import_fs_extra3.default.remove(import_path3.default.join(this.rootPath, filepath));
|
|
587
604
|
}
|
|
588
605
|
};
|
|
589
606
|
var AuditFilesystemStore = class extends FilesystemStore {
|
|
@@ -592,7 +609,7 @@ var AuditFilesystemStore = class extends FilesystemStore {
|
|
|
592
609
|
}
|
|
593
610
|
};
|
|
594
611
|
|
|
595
|
-
//
|
|
612
|
+
// src/database/store/index.ts
|
|
596
613
|
var import_jsonpath_plus = __toModule(require("jsonpath-plus"));
|
|
597
614
|
var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
|
|
598
615
|
var INDEX_KEY_FIELD_SEPARATOR = "#";
|
|
@@ -921,11 +938,12 @@ var makeFilterSuffixes = (filterChain, index) => {
|
|
|
921
938
|
return {};
|
|
922
939
|
}
|
|
923
940
|
};
|
|
924
|
-
var makeKeyForField = (definition, data, stringEscaper) => {
|
|
941
|
+
var makeKeyForField = (definition, data, stringEscaper, maxStringLength = 100) => {
|
|
925
942
|
const valueParts = [];
|
|
926
943
|
for (const field of definition.fields) {
|
|
927
|
-
if (field.name in data) {
|
|
928
|
-
const
|
|
944
|
+
if (field.name in data && data[field.name] !== void 0 && data[field.name] !== null) {
|
|
945
|
+
const rawValue = data[field.name];
|
|
946
|
+
const resolvedValue = String(field.type === "datetime" ? new Date(rawValue).getTime() : field.type === "string" ? stringEscaper(rawValue) : rawValue).substring(0, maxStringLength);
|
|
929
947
|
valueParts.push(applyPadding(resolvedValue, field.pad));
|
|
930
948
|
} else {
|
|
931
949
|
return null;
|
|
@@ -934,8 +952,8 @@ var makeKeyForField = (definition, data, stringEscaper) => {
|
|
|
934
952
|
return valueParts.join(INDEX_KEY_FIELD_SEPARATOR);
|
|
935
953
|
};
|
|
936
954
|
|
|
937
|
-
//
|
|
938
|
-
var
|
|
955
|
+
// src/database/store/level.ts
|
|
956
|
+
var import_path4 = __toModule(require("path"));
|
|
939
957
|
var import_level = __toModule(require("level"));
|
|
940
958
|
var import_levelup = __toModule(require("levelup"));
|
|
941
959
|
var import_memdown = __toModule(require("memdown"));
|
|
@@ -949,7 +967,7 @@ var LevelStore = class {
|
|
|
949
967
|
if (useMemory) {
|
|
950
968
|
this.db = (0, import_levelup.default)((0, import_encoding_down.default)((0, import_memdown.default)(), { valueEncoding: "json" }));
|
|
951
969
|
} else {
|
|
952
|
-
this.db = (0, import_level.default)(
|
|
970
|
+
this.db = (0, import_level.default)(import_path4.default.join(rootPath, ".tina/__generated__/db"), {
|
|
953
971
|
valueEncoding: "json"
|
|
954
972
|
});
|
|
955
973
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tinacms/datalayer",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"typings": "dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -17,11 +17,6 @@
|
|
|
17
17
|
}
|
|
18
18
|
]
|
|
19
19
|
},
|
|
20
|
-
"scripts": {
|
|
21
|
-
"types": "yarn tsc",
|
|
22
|
-
"build": "echo \"Run `yarn build` from the root of the repository instead\"",
|
|
23
|
-
"test": "jest --passWithNoTests"
|
|
24
|
-
},
|
|
25
20
|
"dependencies": {
|
|
26
21
|
"@octokit/auth-app": "^2.6.0",
|
|
27
22
|
"@octokit/graphql": "^4.5.6",
|
|
@@ -52,7 +47,7 @@
|
|
|
52
47
|
"directory": "packages/@tinacms/datalayer"
|
|
53
48
|
},
|
|
54
49
|
"devDependencies": {
|
|
55
|
-
"@tinacms/scripts": "0.
|
|
50
|
+
"@tinacms/scripts": "0.51.1",
|
|
56
51
|
"@types/fs-extra": "^9.0.2",
|
|
57
52
|
"@types/jest": "^27.4.1",
|
|
58
53
|
"@types/js-yaml": "^3.12.5",
|
|
@@ -67,6 +62,11 @@
|
|
|
67
62
|
"jest-diff": "27.0.6",
|
|
68
63
|
"jest-file-snapshot": "^0.5.0",
|
|
69
64
|
"jest-matcher-utils": "27.0.6",
|
|
70
|
-
"typescript": "
|
|
65
|
+
"typescript": "4.3.5"
|
|
66
|
+
},
|
|
67
|
+
"scripts": {
|
|
68
|
+
"types": "pnpm tsc",
|
|
69
|
+
"build": "tinacms-scripts build",
|
|
70
|
+
"test": "jest --passWithNoTests"
|
|
71
71
|
}
|
|
72
72
|
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,864 +0,0 @@
|
|
|
1
|
-
# tina-graphql
|
|
2
|
-
|
|
3
|
-
## 0.2.0
|
|
4
|
-
|
|
5
|
-
### Minor Changes
|
|
6
|
-
|
|
7
|
-
- 4daf15b36: Updated matching logic to only return the correct extension.
|
|
8
|
-
|
|
9
|
-
This means if you are using any other files besides `.md` the format must be provided in the schema.
|
|
10
|
-
|
|
11
|
-
```ts
|
|
12
|
-
// .tina/schema.ts
|
|
13
|
-
|
|
14
|
-
import { defineSchema } from 'tinacms'
|
|
15
|
-
|
|
16
|
-
const schema = defineSchema({
|
|
17
|
-
collections: [
|
|
18
|
-
{
|
|
19
|
-
name: 'page',
|
|
20
|
-
path: 'content/page',
|
|
21
|
-
label: 'Page',
|
|
22
|
-
// Need to provide the format if the file being used (default is `.md`)
|
|
23
|
-
format: 'mdx',
|
|
24
|
-
fields: [
|
|
25
|
-
//...
|
|
26
|
-
],
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
})
|
|
30
|
-
//...
|
|
31
|
-
|
|
32
|
-
export default schema
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Patch Changes
|
|
36
|
-
|
|
37
|
-
- b348f8b6b: Experimental isomorphic git bridge implementation
|
|
38
|
-
|
|
39
|
-
## 0.1.1
|
|
40
|
-
|
|
41
|
-
### Patch Changes
|
|
42
|
-
|
|
43
|
-
- a2906d6fe: Fix datetime filtering to handle both indexed and non-indexed queries
|
|
44
|
-
- 3e2d9e43a: Adds new GraphQL `deleteDocument` mutation and logic
|
|
45
|
-
|
|
46
|
-
## 0.1.0
|
|
47
|
-
|
|
48
|
-
### Minor Changes
|
|
49
|
-
|
|
50
|
-
- a87e1e6fa: Enable query filtering, pagination, sorting
|
|
51
|
-
|
|
52
|
-
### Patch Changes
|
|
53
|
-
|
|
54
|
-
- 8b3be903f: Escape index field separator in input strings
|
|
55
|
-
- b01f2e382: Fixed an issue where `0` as a numerical operand was being evaluated as falsy.
|
|
56
|
-
|
|
57
|
-
## 0.0.2
|
|
58
|
-
|
|
59
|
-
### Patch Changes
|
|
60
|
-
|
|
61
|
-
- b399c734c: Fixes support for collection.templates in graphql
|
|
62
|
-
|
|
63
|
-
## 0.0.1
|
|
64
|
-
|
|
65
|
-
### Patch Changes
|
|
66
|
-
|
|
67
|
-
- 80732bd97: Create a @tinacms/datalayer package which houses the logic for data management for the GraphQL API. This simplifies the @tinacms/graphql package and allows for a clearer separation.
|
|
68
|
-
|
|
69
|
-
## 0.59.1
|
|
70
|
-
|
|
71
|
-
### Patch Changes
|
|
72
|
-
|
|
73
|
-
- f46c6f987: Fix type definitions for schema metadata so they're optional
|
|
74
|
-
|
|
75
|
-
## 0.59.0
|
|
76
|
-
|
|
77
|
-
### Minor Changes
|
|
78
|
-
|
|
79
|
-
- 62bea7019: #2323: fix saving bold and italic text in rich-text editor
|
|
80
|
-
|
|
81
|
-
### Patch Changes
|
|
82
|
-
|
|
83
|
-
- bd4e1f802: Pin version number from @tinacms/graphql during schema compilation. This can be used to ensure the proper version is provided when working with Tina Cloud
|
|
84
|
-
|
|
85
|
-
## 0.58.2
|
|
86
|
-
|
|
87
|
-
### Patch Changes
|
|
88
|
-
|
|
89
|
-
- fffce3af8: Don't cache graphql schema during resolution, this was causing the schema to go stale, while updating the schema.gql, so GraphQL tooling thought the value was updated, but the server was still holding on to the cached version
|
|
90
|
-
|
|
91
|
-
## 0.58.1
|
|
92
|
-
|
|
93
|
-
### Patch Changes
|
|
94
|
-
|
|
95
|
-
- 4700d7ae4: Patch fix to ensure builds include latest dependencies
|
|
96
|
-
|
|
97
|
-
## 0.58.0
|
|
98
|
-
|
|
99
|
-
### Minor Changes
|
|
100
|
-
|
|
101
|
-
- fa7a0419f: Adds experimental support for a data layer between file-based content and the GraphQL API. This allows documents to be indexed so the CMS can behave more like a traditional CMS, with the ability enforce foreign reference constraints and filtering/pagination capabilities.
|
|
102
|
-
|
|
103
|
-
### Patch Changes
|
|
104
|
-
|
|
105
|
-
- eb5fbfac7: Ensure GraphQL resolve doesn't access "bridge" documents
|
|
106
|
-
- 47d126029: Fix support of objects in a list for MDX templates
|
|
107
|
-
|
|
108
|
-
## 0.57.2
|
|
109
|
-
|
|
110
|
-
### Patch Changes
|
|
111
|
-
|
|
112
|
-
- edb2f4011: Trim path property on collections during compilation
|
|
113
|
-
|
|
114
|
-
## 0.57.1
|
|
115
|
-
|
|
116
|
-
### Patch Changes
|
|
117
|
-
|
|
118
|
-
- 60729f60c: Adds a `reference` field
|
|
119
|
-
|
|
120
|
-
## 0.57.0
|
|
121
|
-
|
|
122
|
-
### Minor Changes
|
|
123
|
-
|
|
124
|
-
- ed277e3bd: Remove aws dependency and cache logic from GithubBridge
|
|
125
|
-
- d1ed404ba: Add support for auto-generated SDK for type-safe data fetching
|
|
126
|
-
|
|
127
|
-
### Patch Changes
|
|
128
|
-
|
|
129
|
-
- 138ceb8c4: Clean up dependencies
|
|
130
|
-
- 577d6a5ad: Adds collection arg back for generic queries as optional
|
|
131
|
-
|
|
132
|
-
## 0.56.1
|
|
133
|
-
|
|
134
|
-
### Patch Changes
|
|
135
|
-
|
|
136
|
-
- 4b7795612: Adds support for collection.templates to TinaAdmin
|
|
137
|
-
|
|
138
|
-
## 0.56.0
|
|
139
|
-
|
|
140
|
-
### Minor Changes
|
|
141
|
-
|
|
142
|
-
- b99baebf1: Add rich-text editor based on mdx, bump React dependency requirement to 16.14
|
|
143
|
-
|
|
144
|
-
### Patch Changes
|
|
145
|
-
|
|
146
|
-
- 891623c7c: Adds support for List and Update to TinaAdmin
|
|
147
|
-
|
|
148
|
-
## 0.55.2
|
|
149
|
-
|
|
150
|
-
### Patch Changes
|
|
151
|
-
|
|
152
|
-
- 9ecb392ca: Fix bug which would set markdown body to undefined when the payload was emptry"
|
|
153
|
-
|
|
154
|
-
## 0.55.1
|
|
155
|
-
|
|
156
|
-
### Patch Changes
|
|
157
|
-
|
|
158
|
-
- ff4446c8e: Adds `getDocumentFields()` query for use with Tina Admin
|
|
159
|
-
- 667c33e2a: Add support for rich-text field, update build script to work with unified packages, which are ESM-only
|
|
160
|
-
|
|
161
|
-
## 0.55.0
|
|
162
|
-
|
|
163
|
-
### Minor Changes
|
|
164
|
-
|
|
165
|
-
- f3bddeb4a: Added new warning messages for list UI that we do not support by default
|
|
166
|
-
|
|
167
|
-
### Patch Changes
|
|
168
|
-
|
|
169
|
-
- 2908f8176: Fixes an issue where nested reference fields weren't updated properly when their values changed.
|
|
170
|
-
- 5d83643b2: Adds create document mutations
|
|
171
|
-
|
|
172
|
-
## 0.54.3
|
|
173
|
-
|
|
174
|
-
### Patch Changes
|
|
175
|
-
|
|
176
|
-
- 9b27192fe: Build packages with new scripting, which includes preliminary support for ES modules.
|
|
177
|
-
|
|
178
|
-
## 0.54.2
|
|
179
|
-
|
|
180
|
-
### Patch Changes
|
|
181
|
-
|
|
182
|
-
- d94fec611: Improve exported types for defineSchema
|
|
183
|
-
|
|
184
|
-
## 0.54.1
|
|
185
|
-
|
|
186
|
-
### Patch Changes
|
|
187
|
-
|
|
188
|
-
- 4de977f63: Makes `DateFieldPlugin` timezone-friendly
|
|
189
|
-
|
|
190
|
-
## 0.54.0
|
|
191
|
-
|
|
192
|
-
### Minor Changes
|
|
193
|
-
|
|
194
|
-
- 7663e0f7f: Fixed windows issue where you could not save a file
|
|
195
|
-
|
|
196
|
-
## 0.53.0
|
|
197
|
-
|
|
198
|
-
### Minor Changes
|
|
199
|
-
|
|
200
|
-
- b4f5e973f: Update datetime field to expect and receive ISO string
|
|
201
|
-
|
|
202
|
-
## 0.52.2
|
|
203
|
-
|
|
204
|
-
### Patch Changes
|
|
205
|
-
|
|
206
|
-
- b4bbdda86: Better error messaging when no tina schema files are found
|
|
207
|
-
|
|
208
|
-
## 0.52.1
|
|
209
|
-
|
|
210
|
-
### Patch Changes
|
|
211
|
-
|
|
212
|
-
- b05c91c6: Remove console.log
|
|
213
|
-
|
|
214
|
-
## 0.52.0
|
|
215
|
-
|
|
216
|
-
### Minor Changes
|
|
217
|
-
|
|
218
|
-
- aa4507697: When working with a new document that queries for a reference, we were not properly building the path information required to update that reference, resulting in an error until the page was refreshed.
|
|
219
|
-
|
|
220
|
-
## 0.51.1
|
|
221
|
-
|
|
222
|
-
### Patch Changes
|
|
223
|
-
|
|
224
|
-
- 589c7806: Fix issue where the `isBody` field wasn't properly removing that value from frontmatter. Ensure that the field is not treating any differently for JSON format
|
|
225
|
-
|
|
226
|
-
## 0.51.0
|
|
227
|
-
|
|
228
|
-
### Minor Changes
|
|
229
|
-
|
|
230
|
-
- 5a934f6b: Fixed windows path issues
|
|
231
|
-
|
|
232
|
-
### Patch Changes
|
|
233
|
-
|
|
234
|
-
- 271a72d7: Use collection label (defined in schema.ts) as form label
|
|
235
|
-
|
|
236
|
-
## 0.50.2
|
|
237
|
-
|
|
238
|
-
### Patch Changes
|
|
239
|
-
|
|
240
|
-
- 0970961f: addPendingDocument was expecting params, which are not supported for new doc creation at this time
|
|
241
|
-
|
|
242
|
-
## 0.50.1
|
|
243
|
-
|
|
244
|
-
### Patch Changes
|
|
245
|
-
|
|
246
|
-
- 65b3e3a3: Uses checkbox-group field
|
|
247
|
-
|
|
248
|
-
## 0.50.0
|
|
249
|
-
|
|
250
|
-
### Minor Changes
|
|
251
|
-
|
|
252
|
-
- 7f3c8c1a: # 🔧 Changes coming to TinaCMS ⚙️
|
|
253
|
-
|
|
254
|
-
👋 You may have noticed we've been hard at-work lately building out a more opinionated approach to TinaCMS. To that end, we've settled around a few key points we'd like to announce. To see the work in progress, check out the [main](https://github.com/tinacms/tinacms/tree/main) branch, which will become the primary branch soon.
|
|
255
|
-
|
|
256
|
-
## Consolidating @tinacms packages in to @tinacms/toolkit
|
|
257
|
-
|
|
258
|
-
By nature, Tina relies heavily on React context, and the dependency mismatches from over-modularizing our toolkit has led to many bugs related to missing context. To fix this, we'll be consolidating nearly every package in the @tinacms scope to a single package called `@tinacms/toolkit`
|
|
259
|
-
|
|
260
|
-
We'll also be rolling out esm support as it's now much easier to address build improvements
|
|
261
|
-
|
|
262
|
-
## A more focused tinacms package
|
|
263
|
-
|
|
264
|
-
The `tinacms` package now comes baked-in with APIs for working with the TinaCMS GraphQL API. Because `@tinacms/toolkit` now encompasses everything you'd need to build your own CMS integration, we're repurposing the `tinacms` package to more accurately reflect the "batteries-included" approach.
|
|
265
|
-
|
|
266
|
-
If you haven't been introduced, the GraphQL API is a Git-backed CMS which we'll be leaning into more in the future. With a generous free tier and direct syncing with Github its something we're really excited to push forward. Sign up for free here
|
|
267
|
-
Note: tinacms still exports the same APIs, but we'll gradually start moving the backend-agnostic tools to @tinacms/toolkit.
|
|
268
|
-
|
|
269
|
-
## Consolidating the tina-graphql-gateway repo
|
|
270
|
-
|
|
271
|
-
The tina-graphql-gateway repo will be absorbed into this one. If you've been working with our GraphQL APIs you'll need to follow our migration guide.
|
|
272
|
-
|
|
273
|
-
## Moving from Lerna to Yarn PNP
|
|
274
|
-
|
|
275
|
-
We've had success with Yarn 2 and PNP in other monorepos, if you're a contributor you'll notice some updates to the DX, which should hopefully result in a smoother experience.
|
|
276
|
-
|
|
277
|
-
## FAQ
|
|
278
|
-
|
|
279
|
-
### What about other backends?
|
|
280
|
-
|
|
281
|
-
The `@tinacms/toolkit` isn't going anywhere. And if you're using packages like `react-tinacms-strapi` or r`eact-tinacms-github` with success, that won't change much, they'll just be powered by `@tinacms/toolkit` under the hood.
|
|
282
|
-
|
|
283
|
-
### Do I need to do anything?
|
|
284
|
-
|
|
285
|
-
We'll be bumping all packages to `0.50.0` to reflect the changes. If you're using @tincams scoped packages those won't receive the upgrade. Unscoped packages like `react-tinacms-editor` will be upgraded, and should be bumped to 0.50.0 as well.
|
|
286
|
-
When we move to `1.0.0` we'll be pushing internal APIs to `@tinacms/toolkit`, so that's the long-term location of
|
|
287
|
-
|
|
288
|
-
### Will you continue to patch older versions?
|
|
289
|
-
|
|
290
|
-
We'll continue to make security patches, however major bug fixes will likely not see any updates. Keep in mind that `@tinacms/toolkit` will continue to be developed.
|
|
291
|
-
|
|
292
|
-
## 0.2.0
|
|
293
|
-
|
|
294
|
-
### Minor Changes
|
|
295
|
-
|
|
296
|
-
- 7351d92f: # Define schema changes
|
|
297
|
-
|
|
298
|
-
We're going to be leaning on a more _primitive_ concept of how types are defined with Tina, and in doing so will be introducing some breaking changes to the way schemas are defined. Read the detailed [RFC discussion](https://github.com/tinacms/rfcs/pull/18) for more on this topic, specifically the [latter portions](https://github.com/tinacms/rfcs/pull/18#issuecomment-805400313) of the discussion.
|
|
299
|
-
|
|
300
|
-
## Collections now accept a `fields` _or_ `templates` property
|
|
301
|
-
|
|
302
|
-
You can now provide `fields` instead of `templates` for your collection, doing so will result in a more straightforward schema definition:
|
|
303
|
-
|
|
304
|
-
```js
|
|
305
|
-
{
|
|
306
|
-
collections: [
|
|
307
|
-
{
|
|
308
|
-
name: 'post',
|
|
309
|
-
label: 'Post',
|
|
310
|
-
path: 'content/posts',
|
|
311
|
-
fields: [
|
|
312
|
-
{
|
|
313
|
-
name: 'title',
|
|
314
|
-
label: 'Title',
|
|
315
|
-
type: 'string', // read on below to learn more about _type_ changes
|
|
316
|
-
},
|
|
317
|
-
],
|
|
318
|
-
// defining `fields` and `templates` would result in a compilation error
|
|
319
|
-
},
|
|
320
|
-
]
|
|
321
|
-
}
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
**Why?**
|
|
325
|
-
|
|
326
|
-
Previously, a collection could define multiple templates, the ambiguity introduced with this feature meant that your documents needed a `_template` field on them so we'd know which one they belonged to. It also mean having to disambiguate your queries in graphql:
|
|
327
|
-
|
|
328
|
-
```graphql
|
|
329
|
-
getPostDocument(relativePage: $relativePath) {
|
|
330
|
-
data {
|
|
331
|
-
...on Article_Doc_Data {
|
|
332
|
-
title
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
Going forward, if you use `fields` on a collection, you can omit the `_template` key and simplify your query:
|
|
339
|
-
|
|
340
|
-
```graphql
|
|
341
|
-
getPostDocument(relativePage: $relativePath) {
|
|
342
|
-
data {
|
|
343
|
-
title
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
## `type` changes
|
|
349
|
-
|
|
350
|
-
Types will look a little bit different, and are meant to reflect the lowest form of the shape they can represent. Moving forward, the `ui` field will represent the UI portion of what you might expect. For a blog post "description" field, you'd define it like this:
|
|
351
|
-
|
|
352
|
-
```js
|
|
353
|
-
{
|
|
354
|
-
type: "string",
|
|
355
|
-
label: "Description",
|
|
356
|
-
name: "description",
|
|
357
|
-
}
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
By default `string` will use the `text` field, but you can change that by specifying the `component`:
|
|
361
|
-
|
|
362
|
-
```js
|
|
363
|
-
{
|
|
364
|
-
type: "string",
|
|
365
|
-
label: "Description",
|
|
366
|
-
name: "description",
|
|
367
|
-
ui: {
|
|
368
|
-
component: "textarea"
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
For the most part, the UI properties are added to the field and adhere to the existing capabilities of Tina's core [field plugins](https://tina.io/docs/fields/). But there's nothing stopping you from providing your own components -- just be sure to register those with the CMS object on the frontend:
|
|
374
|
-
|
|
375
|
-
```js
|
|
376
|
-
{
|
|
377
|
-
type: "string",
|
|
378
|
-
label: "Description",
|
|
379
|
-
name: "description",
|
|
380
|
-
ui: {
|
|
381
|
-
component: "myMapField"
|
|
382
|
-
someAdditionalMapConfig: 'some-value'
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
[Register](https://tina.io/docs/fields/custom-fields/#registering-the-plugin) your `myMapField` with Tina:
|
|
388
|
-
|
|
389
|
-
```js
|
|
390
|
-
cms.fields.add({
|
|
391
|
-
name: 'myMapField',
|
|
392
|
-
Component: MapPicker,
|
|
393
|
-
})
|
|
394
|
-
```
|
|
395
|
-
|
|
396
|
-
### One important gotcha
|
|
397
|
-
|
|
398
|
-
Every property in the `defineSchema` API must be serlializable. Meaning functions will not work. For example, there's no way to define a `validate` or `parse` function at this level. However, you can either use the [formify](https://tina.io/docs/tina-cloud/client/#formify) API to get access to the Tina form, or provide your own logic by specifying a plugin of your choice:
|
|
399
|
-
|
|
400
|
-
```js
|
|
401
|
-
{
|
|
402
|
-
type: "string",
|
|
403
|
-
label: "Description",
|
|
404
|
-
name: "description",
|
|
405
|
-
ui: {
|
|
406
|
-
component: "myText"
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
And then when you register the plugin, provide your custom logic here:
|
|
412
|
-
|
|
413
|
-
```js
|
|
414
|
-
import { TextFieldPlugin } from 'tinacms'
|
|
415
|
-
|
|
416
|
-
// ...
|
|
417
|
-
|
|
418
|
-
cms.fields.add({
|
|
419
|
-
...TextFieldPlugin, // spread existing text plugin
|
|
420
|
-
name: 'myText',
|
|
421
|
-
validate: value => {
|
|
422
|
-
someValidationLogic(value)
|
|
423
|
-
},
|
|
424
|
-
})
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
**Why?**
|
|
428
|
-
|
|
429
|
-
The reality is that under the hood this has made no difference to the backend, so we're removing it as a point of friction. Instead, `type` is the true definition of the field's _shape_, while `ui` can be used for customizing the look and behavior of the field's UI.
|
|
430
|
-
|
|
431
|
-
## Defensive coding in Tina
|
|
432
|
-
|
|
433
|
-
When working with GraphQL, there are 2 reasons a property may not be present.
|
|
434
|
-
|
|
435
|
-
1. The data is not a required property. That is to say, if I have a blog post document, and "category" is an optional field, we'll need to make sure we factor that into how we render our page:
|
|
436
|
-
|
|
437
|
-
```tsx
|
|
438
|
-
const MyPage = props => {
|
|
439
|
-
return (
|
|
440
|
-
<>
|
|
441
|
-
<h2>{props.getPostDocument.data.title}</h2>
|
|
442
|
-
<MyCategoryComponent>
|
|
443
|
-
{props.getPostDocument.data?.category}
|
|
444
|
-
</MyCategoryComponent>
|
|
445
|
-
</>
|
|
446
|
-
)
|
|
447
|
-
}
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
2. The query did not ask for that field:
|
|
451
|
-
|
|
452
|
-
```graphql
|
|
453
|
-
{
|
|
454
|
-
getPostDocument {
|
|
455
|
-
data {
|
|
456
|
-
title
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
But with Tina, there's a 3rd scenario: the document may be in an invalid state. Meaning, we could mark the field as `required` _and_ query for the appropriate field, and _still_ not have the expected shape of data. Due to the contextual nature of Tina, it's very common to be in an intermediate state, where your data is incomplete simply because you're still working on it. Most APIs would throw an error when a document is in an invalid state. Or, more likely, you couldn't even request it.
|
|
463
|
-
|
|
464
|
-
## Undefined list fields will return `null`
|
|
465
|
-
|
|
466
|
-
Previously an listable field which wasn't defined in the document was treated as an emptry array. So for example:
|
|
467
|
-
|
|
468
|
-
```md
|
|
469
|
-
---
|
|
470
|
-
title: 'Hello, World'
|
|
471
|
-
categories:
|
|
472
|
-
- sports
|
|
473
|
-
- movies
|
|
474
|
-
---
|
|
475
|
-
```
|
|
476
|
-
|
|
477
|
-
The responsee would be `categories: ['sports', 'movies']`. If you omit the items, but kept the empty array:
|
|
478
|
-
|
|
479
|
-
```md
|
|
480
|
-
---
|
|
481
|
-
title: 'Hello, World'
|
|
482
|
-
categories: []
|
|
483
|
-
---
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
The responsee would be `categories: []`. If you omit the field entirely:
|
|
487
|
-
|
|
488
|
-
```md
|
|
489
|
-
---
|
|
490
|
-
title: 'Hello, World'
|
|
491
|
-
---
|
|
492
|
-
```
|
|
493
|
-
|
|
494
|
-
The response will be `categories: null`. Previously this would have been `[]`, which was incorrect.
|
|
495
|
-
|
|
496
|
-
## For a listable item which is `required: true` you _must_ provide a `ui.defaultItem` property
|
|
497
|
-
|
|
498
|
-
### Why?
|
|
499
|
-
|
|
500
|
-
It's possible for Tina's editing capabilities to introduce an invalid state during edits to list items. Imagine the scenario where you are iterating through an array of objects, and each object has a categories array on it we'd like to render:
|
|
501
|
-
|
|
502
|
-
```tsx
|
|
503
|
-
const MyPage = props => {
|
|
504
|
-
return props.blocks.map(block => {
|
|
505
|
-
return (
|
|
506
|
-
<>
|
|
507
|
-
<h2>{block.categories.split(',')}</h2>
|
|
508
|
-
</>
|
|
509
|
-
)
|
|
510
|
-
})
|
|
511
|
-
}
|
|
512
|
-
```
|
|
513
|
-
|
|
514
|
-
For a new item, `categories` will be null, so we'll get an error. This only happens when you're editing your page with Tina, so it's not a production-facing issue.
|
|
515
|
-
|
|
516
|
-
## Every `type` can be a list
|
|
517
|
-
|
|
518
|
-
Previously, we had a `list` field, which allowed you to supply a `field` property. Instead, _every_ primitive type can be represented as a list:
|
|
519
|
-
|
|
520
|
-
```js
|
|
521
|
-
{
|
|
522
|
-
type: "string",
|
|
523
|
-
label: "Categories",
|
|
524
|
-
name: "categories",
|
|
525
|
-
list: true
|
|
526
|
-
}
|
|
527
|
-
```
|
|
528
|
-
|
|
529
|
-
Additionally, enumerable lists and selects are inferred from the `options` property. The following example is represented by a `select` field:
|
|
530
|
-
|
|
531
|
-
```js
|
|
532
|
-
{
|
|
533
|
-
type: "string",
|
|
534
|
-
label: "Categories",
|
|
535
|
-
name: "categories",
|
|
536
|
-
options: ["fitness", "movies", "music"]
|
|
537
|
-
}
|
|
538
|
-
```
|
|
539
|
-
|
|
540
|
-
While this, is a `checkbox` field
|
|
541
|
-
|
|
542
|
-
```js
|
|
543
|
-
{
|
|
544
|
-
type: "string",
|
|
545
|
-
label: "Categories",
|
|
546
|
-
name: "categories"
|
|
547
|
-
list: true,
|
|
548
|
-
options: ["fitness", "movies", "music"]
|
|
549
|
-
}
|
|
550
|
-
```
|
|
551
|
-
|
|
552
|
-
> Note we may introduce an `enum` type, but haven't discussed it thoroughly
|
|
553
|
-
|
|
554
|
-
## Introducing the `object` type
|
|
555
|
-
|
|
556
|
-
Tina currently represents the concept of an _object_ in two ways: a `group` (and `group-list`), which is a uniform collection of fields; and `blocks`, which is a polymporphic collection. Moving forward, we'll be introducing a more comporehensive type, which envelopes the behavior of both `group` and `blocks`, and since _every_ field can be a `list`, this also makes `group-list` redundant.
|
|
557
|
-
|
|
558
|
-
> Note: we've previously assumed that `blocks` usage would _always_ be as an array. We'll be keeping that assumption with the `blocks` type for compatibility, but `object` will allow for non-array polymorphic objects.
|
|
559
|
-
|
|
560
|
-
### Defining an `object` type
|
|
561
|
-
|
|
562
|
-
An `object` type takes either a `fields` _or_ `templates` property (just like the `collections` definition). If you supply `fields`, you'll end up with what is essentially a `group` item. And if you say `list: true`, you'll have what used to be a `group-list` definition.
|
|
563
|
-
|
|
564
|
-
Likewise, if you supply a `templates` field and `list: true`, you'll get the same API as `blocks`. However you can also say `list: false` (or omit it entirely), and you'll have a polymorphic object which is _not_ an array.
|
|
565
|
-
|
|
566
|
-
This is identical to the current `blocks` definition:
|
|
567
|
-
|
|
568
|
-
```js
|
|
569
|
-
{
|
|
570
|
-
type: "object",
|
|
571
|
-
label: "Page Sections",
|
|
572
|
-
name: "pageSections",
|
|
573
|
-
list: true,
|
|
574
|
-
templates: [{
|
|
575
|
-
label: "Hero",
|
|
576
|
-
name: "hero",
|
|
577
|
-
fields: [{
|
|
578
|
-
label: "Title",
|
|
579
|
-
name: "title",
|
|
580
|
-
type: "string"
|
|
581
|
-
}]
|
|
582
|
-
}]
|
|
583
|
-
}
|
|
584
|
-
```
|
|
585
|
-
|
|
586
|
-
And here is one for `group`:
|
|
587
|
-
|
|
588
|
-
```js
|
|
589
|
-
{
|
|
590
|
-
type: "object",
|
|
591
|
-
label: "Hero",
|
|
592
|
-
name: "hero",
|
|
593
|
-
fields: [{
|
|
594
|
-
label: "Title",
|
|
595
|
-
name: "title",
|
|
596
|
-
type: "string"
|
|
597
|
-
}]
|
|
598
|
-
}
|
|
599
|
-
```
|
|
600
|
-
|
|
601
|
-
## `dataJSON` field
|
|
602
|
-
|
|
603
|
-
You can now request `dataJSON` for the entire data object as a single query key. This is great for more tedius queries like theme files where including each item in the result is cumbersome.
|
|
604
|
-
|
|
605
|
-
> Note there is no typescript help for this feature for now
|
|
606
|
-
|
|
607
|
-
```graphql
|
|
608
|
-
getThemeDocument(relativePath: $relativePath) {
|
|
609
|
-
dataJSON
|
|
610
|
-
}
|
|
611
|
-
```
|
|
612
|
-
|
|
613
|
-
```json
|
|
614
|
-
{
|
|
615
|
-
"getThemeDocument": {
|
|
616
|
-
"dataJSON": {
|
|
617
|
-
"every": "field",
|
|
618
|
-
"in": {
|
|
619
|
-
"the": "document"
|
|
620
|
-
},
|
|
621
|
-
"is": "returned"
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
```
|
|
626
|
-
|
|
627
|
-
## Lists queries will now adhere to the GraphQL connection spec
|
|
628
|
-
|
|
629
|
-
[Read the spec](https://relay.dev/graphql/connections.htm)
|
|
630
|
-
|
|
631
|
-
Previously, lists would return a simple array of items:
|
|
632
|
-
|
|
633
|
-
```graphql
|
|
634
|
-
{
|
|
635
|
-
getPostsList {
|
|
636
|
-
id
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
```
|
|
640
|
-
|
|
641
|
-
Which would result in:
|
|
642
|
-
|
|
643
|
-
```json
|
|
644
|
-
{
|
|
645
|
-
"data": {
|
|
646
|
-
"getPostsList": [
|
|
647
|
-
{
|
|
648
|
-
"id": "content/posts/voteForPedro.md"
|
|
649
|
-
}
|
|
650
|
-
]
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
```
|
|
654
|
-
|
|
655
|
-
In the new API, you'll need to step through `edges` & `nodes`:
|
|
656
|
-
|
|
657
|
-
```graphql
|
|
658
|
-
{
|
|
659
|
-
getPostsList {
|
|
660
|
-
edges {
|
|
661
|
-
node {
|
|
662
|
-
id
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
```
|
|
668
|
-
|
|
669
|
-
```json
|
|
670
|
-
{
|
|
671
|
-
"data": {
|
|
672
|
-
"getPostsList": {
|
|
673
|
-
"edges": [
|
|
674
|
-
{
|
|
675
|
-
"node": {
|
|
676
|
-
"id": "content/posts/voteForPedro.md"
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
]
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
```
|
|
684
|
-
|
|
685
|
-
**Why?**
|
|
686
|
-
|
|
687
|
-
The GraphQL connection spec opens up a more future-proof structure, allowing us to put more information in to the _connection_ itself like how many results have been returned, and how to request the next page of data.
|
|
688
|
-
|
|
689
|
-
Read [a detailed explanation](https://graphql.org/learn/pagination/) of how the connection spec provides a richer set of capabilities.
|
|
690
|
-
|
|
691
|
-
> Note: sorting and filtering is still not supported for list queries.
|
|
692
|
-
|
|
693
|
-
## `_body` is no longer included by default
|
|
694
|
-
|
|
695
|
-
There is instead an `isBody` boolean which can be added to any `string` field
|
|
696
|
-
|
|
697
|
-
**Why?**
|
|
698
|
-
|
|
699
|
-
Since markdown files sort of have an implicit "body" to them, we were automatically populating a field which represented the body of your markdown file. This wasn't that useful, and kind of annoying. Instead, just attach `isBody` to the field which you want to represent your markdown "body":
|
|
700
|
-
|
|
701
|
-
```js
|
|
702
|
-
{
|
|
703
|
-
collections: [{
|
|
704
|
-
name: "post",
|
|
705
|
-
label: "Post",
|
|
706
|
-
path: "content/posts",
|
|
707
|
-
fields: [
|
|
708
|
-
{
|
|
709
|
-
name: "title",
|
|
710
|
-
label: "Title",
|
|
711
|
-
type: "string"
|
|
712
|
-
}
|
|
713
|
-
{
|
|
714
|
-
name: "myBody",
|
|
715
|
-
label: "My Body",
|
|
716
|
-
type: "string",
|
|
717
|
-
component: 'textarea',
|
|
718
|
-
isBody: true
|
|
719
|
-
}
|
|
720
|
-
]
|
|
721
|
-
}]
|
|
722
|
-
}
|
|
723
|
-
```
|
|
724
|
-
|
|
725
|
-
This would result in a form field called `My Body` getting saved to the body of your markdown file (if you're using markdown):
|
|
726
|
-
|
|
727
|
-
```md
|
|
728
|
-
---
|
|
729
|
-
title: Hello, World!
|
|
730
|
-
---
|
|
731
|
-
|
|
732
|
-
This is the body of the file, it's edited through the "My Body" field in your form.
|
|
733
|
-
```
|
|
734
|
-
|
|
735
|
-
## References now point to more than one collection.
|
|
736
|
-
|
|
737
|
-
Instead of a `collection` property, you must now define a `collections` field, which is an array:
|
|
738
|
-
|
|
739
|
-
```js
|
|
740
|
-
{
|
|
741
|
-
type: "reference",
|
|
742
|
-
label: "Author",
|
|
743
|
-
name: "author",
|
|
744
|
-
collections: ["author"]
|
|
745
|
-
}
|
|
746
|
-
```
|
|
747
|
-
|
|
748
|
-
```graphql
|
|
749
|
-
{
|
|
750
|
-
getPostDocument(relativePath: "hello.md") {
|
|
751
|
-
data {
|
|
752
|
-
title
|
|
753
|
-
author {
|
|
754
|
-
...on Author_Document {
|
|
755
|
-
name
|
|
756
|
-
}
|
|
757
|
-
...on Post_Document {
|
|
758
|
-
title
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
```
|
|
764
|
-
|
|
765
|
-
## Other breaking changes
|
|
766
|
-
|
|
767
|
-
### The `template` field on polymorphic objects (formerly _blocks_) is now `_template`
|
|
768
|
-
|
|
769
|
-
**Old API:**
|
|
770
|
-
|
|
771
|
-
```md
|
|
772
|
-
---
|
|
773
|
-
---
|
|
774
|
-
myBlocks:
|
|
775
|
-
- template: hero
|
|
776
|
-
title: Hello
|
|
777
|
-
---
|
|
778
|
-
```
|
|
779
|
-
|
|
780
|
-
**New API:**
|
|
781
|
-
|
|
782
|
-
```md
|
|
783
|
-
---
|
|
784
|
-
---
|
|
785
|
-
myBlocks:
|
|
786
|
-
- \_template: hero
|
|
787
|
-
title: Hello
|
|
788
|
-
---
|
|
789
|
-
```
|
|
790
|
-
|
|
791
|
-
### `data` `__typename` values have changed
|
|
792
|
-
|
|
793
|
-
They now include the proper namespace to prevent naming collisions and no longer require `_Doc_Data` suffix. All generated `__typename` properties are going to be slightly different. We weren't fully namespacing fields so it wasn't possible to guarantee that no collisions would occur. The pain felt here will likely be most seen when querying and filtering through blocks. This ensures the stability of this type in the future
|
|
794
|
-
|
|
795
|
-
```graphql
|
|
796
|
-
{
|
|
797
|
-
getPageDocument(relativePath: "home.md") {
|
|
798
|
-
data {
|
|
799
|
-
title
|
|
800
|
-
myBlocks {
|
|
801
|
-
...on Page_Hero_Data { # previously this would have been Hero_Data
|
|
802
|
-
# ...
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
```
|
|
808
|
-
|
|
809
|
-
### Patch Changes
|
|
810
|
-
|
|
811
|
-
- fdb7724b: Fix stringify for json extensions
|
|
812
|
-
- d42e2bcf: Adds number, datetime, and boolean fields back into primitive field generators
|
|
813
|
-
- 5cd5ce76: - Improve types for ui field
|
|
814
|
-
- Marks system fields as required so the user has a guarantee that they'll be there
|
|
815
|
-
- Return null for listable fields which are null or undefined
|
|
816
|
-
- Handle null values for reference fields better
|
|
817
|
-
- 8c425440: Remmove accidental additional of dataJSON in schema
|
|
818
|
-
- Updated dependencies [7351d92f]
|
|
819
|
-
- tina-graphql-helpers@0.1.2
|
|
820
|
-
|
|
821
|
-
## 0.1.25
|
|
822
|
-
|
|
823
|
-
### Patch Changes
|
|
824
|
-
|
|
825
|
-
- 348ef1e5: Testing version bumps go into a PR
|
|
826
|
-
|
|
827
|
-
## 0.1.24
|
|
828
|
-
|
|
829
|
-
### Patch Changes
|
|
830
|
-
|
|
831
|
-
- b36de960: lruClearCache should just be clearCache for now
|
|
832
|
-
|
|
833
|
-
## 0.1.23
|
|
834
|
-
|
|
835
|
-
### Patch Changes
|
|
836
|
-
|
|
837
|
-
- Bump packages to reflect new changest capabilities
|
|
838
|
-
- Updated dependencies [undefined]
|
|
839
|
-
- tina-graphql-helpers@0.1.1
|
|
840
|
-
|
|
841
|
-
## 0.1.22
|
|
842
|
-
|
|
843
|
-
### Patch Changes
|
|
844
|
-
|
|
845
|
-
- Updated dependencies [undefined]
|
|
846
|
-
- tina-graphql-helpers@0.1.0
|
|
847
|
-
|
|
848
|
-
## 0.1.21
|
|
849
|
-
|
|
850
|
-
### Patch Changes
|
|
851
|
-
|
|
852
|
-
- Testin
|
|
853
|
-
|
|
854
|
-
## 0.1.20
|
|
855
|
-
|
|
856
|
-
### Patch Changes
|
|
857
|
-
|
|
858
|
-
- Testing
|
|
859
|
-
|
|
860
|
-
## 0.1.13
|
|
861
|
-
|
|
862
|
-
### Patch Changes
|
|
863
|
-
|
|
864
|
-
- Testing out changesets
|