tinacms 3.13.0 → 3.14.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/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
  [![npm version](https://img.shields.io/npm/v/tinacms.svg?style=flat)](https://www.npmjs.com/package/tinacms)
3
3
  [![Build, Test, Lint for Main](https://github.com/tinacms/tinacms/actions/workflows/main.yml/badge.svg?branch=main&event=push)](https://github.com/tinacms/tinacms/actions/workflows/main.yml)
4
4
 
5
- # [![TINA CMS](./.github/assets/tinacms-logo-small-default.svg)](https://tina.io)
5
+ # [![TINA CMS](https://raw.githubusercontent.com/tinacms/tinacms/main/.github/assets/tinacms-logo-small-default.svg)](https://tina.io)
6
6
 
7
- [![Tina Demo](./.github/assets/homepage-demo-2.gif)](https://tina.io/)
7
+ [![Tina Demo](https://raw.githubusercontent.com/tinacms/tinacms/main/.github/assets/homepage-demo-2.gif)](https://tina.io/)
8
8
 
9
9
  Tina is a headless content management system with support for **Markdown**, MDX, JSON, YAML, and more.
10
10
 
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Resolve a router splat into a same-origin preview path.
3
+ *
4
+ * Do not filter the splat instead: the URL parser treats `\` as `/` and drops
5
+ * leading tabs, so a character filter does not hold. Resolve the value first,
6
+ * then reject any result that left this origin.
7
+ *
8
+ * `offOrigin` is true only when a splat was supplied and resolved elsewhere, so
9
+ * callers can tell a rejected link from an empty one.
10
+ */
11
+ export declare function resolvePreviewPath(splat: string | undefined, baseOrigin?: string): {
12
+ path: string;
13
+ offOrigin: boolean;
14
+ };
@@ -0,0 +1 @@
1
+ export * from './unifiedClient';
@@ -0,0 +1,175 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ class AsyncLock {
5
+ constructor() {
6
+ __publicField(this, "queues", /* @__PURE__ */ new Map());
7
+ }
8
+ acquire(key, fn) {
9
+ const prev = this.queues.get(key) ?? Promise.resolve();
10
+ const next = prev.then(fn);
11
+ this.queues.set(
12
+ key,
13
+ next.then(
14
+ () => void 0,
15
+ () => void 0
16
+ )
17
+ );
18
+ return next;
19
+ }
20
+ }
21
+ const TINA_HOST = "content.tinajs.io";
22
+ function replaceGithubPathSplit(url, replacement) {
23
+ const parts = url.split("github/");
24
+ if (parts.length > 1 && replacement) {
25
+ return parts[0] + "github/" + replacement;
26
+ } else {
27
+ return url;
28
+ }
29
+ }
30
+ function isEdgeRuntimeWithoutFs() {
31
+ if (typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers") {
32
+ return true;
33
+ }
34
+ if (typeof globalThis.EdgeRuntime !== "undefined") {
35
+ return true;
36
+ }
37
+ return false;
38
+ }
39
+ class TinaClient {
40
+ constructor({
41
+ token,
42
+ url,
43
+ queries,
44
+ errorPolicy,
45
+ cacheDir,
46
+ cache
47
+ }) {
48
+ __publicField(this, "apiUrl");
49
+ __publicField(this, "readonlyToken");
50
+ __publicField(this, "queries");
51
+ __publicField(this, "errorPolicy");
52
+ __publicField(this, "initialized", false);
53
+ __publicField(this, "cacheLock");
54
+ __publicField(this, "cacheDir");
55
+ __publicField(this, "cache");
56
+ __publicField(this, "cacheEnabled");
57
+ this.apiUrl = url;
58
+ this.readonlyToken = token == null ? void 0 : token.trim();
59
+ this.queries = queries(this);
60
+ this.errorPolicy = errorPolicy || "throw";
61
+ this.cacheDir = cacheDir || "";
62
+ this.cacheEnabled = cache !== false;
63
+ }
64
+ async init() {
65
+ if (this.initialized) {
66
+ return;
67
+ }
68
+ try {
69
+ if (this.cacheEnabled && this.cacheDir && typeof window === "undefined" && !isEdgeRuntimeWithoutFs()) {
70
+ this.cache = await this.createCache(this.cacheDir);
71
+ if (this.cache) {
72
+ this.cacheLock = new AsyncLock();
73
+ }
74
+ }
75
+ } catch (e) {
76
+ console.error(e);
77
+ }
78
+ this.initialized = true;
79
+ }
80
+ async createCache(_dir) {
81
+ return null;
82
+ }
83
+ async request({ errorPolicy, ...args }, options) {
84
+ var _a;
85
+ await this.init();
86
+ const errorPolicyDefined = errorPolicy || this.errorPolicy;
87
+ const headers = new Headers();
88
+ if (this.readonlyToken) {
89
+ headers.append("X-API-KEY", this.readonlyToken);
90
+ }
91
+ headers.append("Content-Type", "application/json");
92
+ if (options == null ? void 0 : options.fetchOptions) {
93
+ if ((_a = options == null ? void 0 : options.fetchOptions) == null ? void 0 : _a.headers) {
94
+ Object.entries(options.fetchOptions.headers).forEach(([key2, value]) => {
95
+ headers.append(key2, value);
96
+ });
97
+ }
98
+ }
99
+ const { headers: _, ...providedFetchOptions } = (options == null ? void 0 : options.fetchOptions) || {};
100
+ const bodyString = JSON.stringify({
101
+ query: args.query,
102
+ variables: (args == null ? void 0 : args.variables) || {}
103
+ });
104
+ const optionsObject = {
105
+ method: "POST",
106
+ headers,
107
+ body: bodyString,
108
+ redirect: "follow",
109
+ ...providedFetchOptions
110
+ };
111
+ const draftBranch = headers.get("x-branch");
112
+ const url = replaceGithubPathSplit((args == null ? void 0 : args.url) || this.apiUrl, draftBranch);
113
+ let key = "";
114
+ let result;
115
+ if (this.cache) {
116
+ key = this.cache.makeKey(bodyString);
117
+ await this.cacheLock.acquire(key, async () => {
118
+ result = await this.cache.get(key);
119
+ if (!result) {
120
+ result = await requestFromServer(
121
+ url,
122
+ args.query,
123
+ optionsObject,
124
+ errorPolicyDefined
125
+ );
126
+ await this.cache.set(key, result);
127
+ }
128
+ });
129
+ } else {
130
+ result = await requestFromServer(
131
+ url,
132
+ args.query,
133
+ optionsObject,
134
+ errorPolicyDefined
135
+ );
136
+ }
137
+ return result;
138
+ }
139
+ }
140
+ async function requestFromServer(url, query, optionsObject, errorPolicyDefined) {
141
+ const res = await fetch(url, optionsObject);
142
+ if (!res.ok) {
143
+ let additionalInfo = "";
144
+ if (res.status === 401) {
145
+ additionalInfo = "Please check that your client ID, URL and read only token are configured properly.";
146
+ }
147
+ throw new Error(
148
+ `Server responded with status code ${res.status}, ${res.statusText}. ${additionalInfo ? additionalInfo : ""} Please see our FAQ for more information: https://tina.io/docs/r/FAQ/`
149
+ );
150
+ }
151
+ const json = await res.json();
152
+ if (json.errors && errorPolicyDefined === "throw") {
153
+ throw new Error(
154
+ `Unable to fetch, please see our FAQ for more information: https://tina.io/docs/r/FAQ/
155
+ Errors:
156
+ ${json.errors.map((error) => error.message).join("\n")}`
157
+ );
158
+ }
159
+ const result = {
160
+ data: json == null ? void 0 : json.data,
161
+ errors: (json == null ? void 0 : json.errors) || null,
162
+ query
163
+ };
164
+ return result;
165
+ }
166
+ function createClient(args) {
167
+ const client = new TinaClient(args);
168
+ return client;
169
+ }
170
+ export {
171
+ AsyncLock,
172
+ TINA_HOST,
173
+ TinaClient,
174
+ createClient
175
+ };
package/dist/client.d.ts CHANGED
@@ -1,4 +1,7 @@
1
- /**
2
-
3
- */
4
1
  export * from './unifiedClient';
2
+ import { TinaClient as BaseTinaClient } from './unifiedClient';
3
+ import type { TinaClientArgs } from './unifiedClient';
4
+ export declare class TinaClient<GenQueries> extends BaseTinaClient<GenQueries> {
5
+ protected createCache(dir: string): Promise<import("./cache").Cache>;
6
+ }
7
+ export declare function createClient<GenQueries>(args: TinaClientArgs<GenQueries>): TinaClient<GenQueries>;
package/dist/client.js CHANGED
@@ -1,125 +1,3 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropNames = Object.getOwnPropertyNames;
3
- var __esm = (fn, res, err) => function __init() {
4
- if (err) throw err[0];
5
- try {
6
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
7
- } catch (e) {
8
- throw err = [e], e;
9
- }
10
- };
11
- var __export = (target, all) => {
12
- for (var name in all)
13
- __defProp(target, name, { get: all[name], enumerable: true });
14
- };
15
-
16
- // src/cache/node-cache.ts
17
- var node_cache_exports = {};
18
- __export(node_cache_exports, {
19
- NodeCache: () => NodeCache,
20
- makeCacheDir: () => makeCacheDir
21
- });
22
- var resolveModule, getRootPath, makeCacheDir, NodeCache;
23
- var init_node_cache = __esm({
24
- "src/cache/node-cache.ts"() {
25
- resolveModule = (mod) => {
26
- if (mod && typeof mod === "object" && "default" in mod && mod.default) {
27
- return mod.default;
28
- }
29
- return mod;
30
- };
31
- getRootPath = (pathParts, pathArg) => {
32
- if (pathParts.length === 0) return null;
33
- const isWindows = pathArg.sep === "\\";
34
- const root = pathParts[0];
35
- return isWindows ? `${root}${pathArg.sep}` : `${pathArg.sep}${root}`;
36
- };
37
- makeCacheDir = (dir, fsArg, pathArg, osArg) => {
38
- const normalizedDir = pathArg.normalize(dir);
39
- const pathParts = normalizedDir.split(pathArg.sep).filter(Boolean);
40
- const cacheHash = pathParts[pathParts.length - 1];
41
- const rootPath = getRootPath(pathParts, pathArg);
42
- const rootExists = rootPath && fsArg.existsSync(rootPath);
43
- const cacheDir = rootExists ? normalizedDir : pathArg.join(osArg.tmpdir(), cacheHash);
44
- try {
45
- fsArg.mkdirSync(cacheDir, { recursive: true });
46
- } catch (error) {
47
- console.warn(
48
- `Warning: Failed to create cache directory: ${error.message}. Caching will be disabled.`
49
- );
50
- return null;
51
- }
52
- return cacheDir;
53
- };
54
- NodeCache = async (dir) => {
55
- try {
56
- const [fsModule, pathModule, osModule, cryptoModule] = await Promise.all([
57
- import("node:fs"),
58
- import("node:path"),
59
- import("node:os"),
60
- import("node:crypto")
61
- ]);
62
- const fs = resolveModule(fsModule);
63
- const path = resolveModule(pathModule);
64
- const os = resolveModule(osModule);
65
- const crypto = resolveModule(cryptoModule);
66
- if (typeof path?.join !== "function") {
67
- console.warn(
68
- "Warning: Node.js path module not available. Caching will be disabled."
69
- );
70
- return null;
71
- }
72
- const cacheDir = makeCacheDir(dir, fs, path, os);
73
- if (cacheDir === null) {
74
- return null;
75
- }
76
- return {
77
- makeKey: (key) => {
78
- const input = key && key instanceof Object ? JSON.stringify(key) : key || "";
79
- return crypto.createHash("sha256").update(input).digest("hex");
80
- },
81
- get: async (key) => {
82
- let readValue;
83
- const cacheFilename = path.join(cacheDir, key);
84
- try {
85
- const data = await fs.promises.readFile(cacheFilename, "utf-8");
86
- readValue = JSON.parse(data);
87
- } catch (e) {
88
- if (e.code !== "ENOENT") {
89
- console.warn(
90
- `Warning: Failed to read cache file ${cacheFilename}: ${e.message}`
91
- );
92
- }
93
- }
94
- return readValue;
95
- },
96
- set: async (key, value) => {
97
- const cacheFilename = path.join(cacheDir, key);
98
- try {
99
- await fs.promises.writeFile(cacheFilename, JSON.stringify(value), {
100
- encoding: "utf-8",
101
- flag: "wx"
102
- });
103
- } catch (e) {
104
- if (e.code !== "EEXIST") {
105
- console.warn(
106
- `Warning: Failed to write cache file ${cacheFilename}: ${e.message}`
107
- );
108
- }
109
- }
110
- }
111
- };
112
- } catch (e) {
113
- console.warn(
114
- "Warning: Failed to initialize cache. Caching will be disabled.",
115
- e.message
116
- );
117
- return null;
118
- }
119
- };
120
- }
121
- });
122
-
123
1
  // src/unifiedClient/asyncLock.ts
124
2
  var AsyncLock = class {
125
3
  queues = /* @__PURE__ */ new Map();
@@ -187,8 +65,7 @@ var TinaClient = class {
187
65
  }
188
66
  try {
189
67
  if (this.cacheEnabled && this.cacheDir && typeof window === "undefined" && !isEdgeRuntimeWithoutFs()) {
190
- const { NodeCache: NodeCache2 } = await Promise.resolve().then(() => (init_node_cache(), node_cache_exports));
191
- this.cache = await NodeCache2(this.cacheDir);
68
+ this.cache = await this.createCache(this.cacheDir);
192
69
  if (this.cache) {
193
70
  this.cacheLock = new AsyncLock();
194
71
  }
@@ -198,6 +75,9 @@ var TinaClient = class {
198
75
  }
199
76
  this.initialized = true;
200
77
  }
78
+ async createCache(_dir) {
79
+ return null;
80
+ }
201
81
  async request({ errorPolicy, ...args }, options) {
202
82
  await this.init();
203
83
  const errorPolicyDefined = errorPolicy || this.errorPolicy;
@@ -280,13 +160,116 @@ async function requestFromServer(url, query, optionsObject, errorPolicyDefined)
280
160
  };
281
161
  return result;
282
162
  }
163
+
164
+ // src/cache/node-cache.ts
165
+ var resolveModule = (mod) => {
166
+ if (mod && typeof mod === "object" && "default" in mod && mod.default) {
167
+ return mod.default;
168
+ }
169
+ return mod;
170
+ };
171
+ var getRootPath = (pathParts, pathArg) => {
172
+ if (pathParts.length === 0) return null;
173
+ const isWindows = pathArg.sep === "\\";
174
+ const root = pathParts[0];
175
+ return isWindows ? `${root}${pathArg.sep}` : `${pathArg.sep}${root}`;
176
+ };
177
+ var makeCacheDir = (dir, fsArg, pathArg, osArg) => {
178
+ const normalizedDir = pathArg.normalize(dir);
179
+ const pathParts = normalizedDir.split(pathArg.sep).filter(Boolean);
180
+ const cacheHash = pathParts[pathParts.length - 1];
181
+ const rootPath = getRootPath(pathParts, pathArg);
182
+ const rootExists = rootPath && fsArg.existsSync(rootPath);
183
+ const cacheDir = rootExists ? normalizedDir : pathArg.join(osArg.tmpdir(), cacheHash);
184
+ try {
185
+ fsArg.mkdirSync(cacheDir, { recursive: true });
186
+ } catch (error) {
187
+ console.warn(
188
+ `Warning: Failed to create cache directory: ${error.message}. Caching will be disabled.`
189
+ );
190
+ return null;
191
+ }
192
+ return cacheDir;
193
+ };
194
+ var NodeCache = async (dir) => {
195
+ try {
196
+ const [fsModule, pathModule, osModule, cryptoModule] = await Promise.all([
197
+ import("node:fs"),
198
+ import("node:path"),
199
+ import("node:os"),
200
+ import("node:crypto")
201
+ ]);
202
+ const fs = resolveModule(fsModule);
203
+ const path = resolveModule(pathModule);
204
+ const os = resolveModule(osModule);
205
+ const crypto = resolveModule(cryptoModule);
206
+ if (typeof path?.join !== "function") {
207
+ console.warn(
208
+ "Warning: Node.js path module not available. Caching will be disabled."
209
+ );
210
+ return null;
211
+ }
212
+ const cacheDir = makeCacheDir(dir, fs, path, os);
213
+ if (cacheDir === null) {
214
+ return null;
215
+ }
216
+ return {
217
+ makeKey: (key) => {
218
+ const input = key && key instanceof Object ? JSON.stringify(key) : key || "";
219
+ return crypto.createHash("sha256").update(input).digest("hex");
220
+ },
221
+ get: async (key) => {
222
+ let readValue;
223
+ const cacheFilename = path.join(cacheDir, key);
224
+ try {
225
+ const data = await fs.promises.readFile(cacheFilename, "utf-8");
226
+ readValue = JSON.parse(data);
227
+ } catch (e) {
228
+ if (e.code !== "ENOENT") {
229
+ console.warn(
230
+ `Warning: Failed to read cache file ${cacheFilename}: ${e.message}`
231
+ );
232
+ }
233
+ }
234
+ return readValue;
235
+ },
236
+ set: async (key, value) => {
237
+ const cacheFilename = path.join(cacheDir, key);
238
+ try {
239
+ await fs.promises.writeFile(cacheFilename, JSON.stringify(value), {
240
+ encoding: "utf-8",
241
+ flag: "wx"
242
+ });
243
+ } catch (e) {
244
+ if (e.code !== "EEXIST") {
245
+ console.warn(
246
+ `Warning: Failed to write cache file ${cacheFilename}: ${e.message}`
247
+ );
248
+ }
249
+ }
250
+ }
251
+ };
252
+ } catch (e) {
253
+ console.warn(
254
+ "Warning: Failed to initialize cache. Caching will be disabled.",
255
+ e.message
256
+ );
257
+ return null;
258
+ }
259
+ };
260
+
261
+ // src/client.ts
262
+ var TinaClient2 = class extends TinaClient {
263
+ createCache(dir) {
264
+ return NodeCache(dir);
265
+ }
266
+ };
283
267
  function createClient(args) {
284
- const client = new TinaClient(args);
285
- return client;
268
+ return new TinaClient2(args);
286
269
  }
287
270
  export {
288
271
  AsyncLock,
289
272
  TINA_HOST,
290
- TinaClient,
273
+ TinaClient2 as TinaClient,
291
274
  createClient
292
275
  };