tinacms 1.2.1 → 1.2.2
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/admin/api.d.ts +3 -3
- package/dist/admin/index.d.ts +2 -4
- package/dist/index.es.js +141 -14
- package/dist/index.js +140 -14
- package/dist/internalClient/index.d.ts +105 -4
- package/package.json +6 -4
package/dist/admin/api.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*/
|
|
4
1
|
import type { TinaCMS } from '@tinacms/toolkit';
|
|
5
2
|
import type { TinaSchema } from '@tinacms/schema-tools';
|
|
6
3
|
import type { Client } from '../internalClient';
|
|
@@ -18,6 +15,9 @@ export declare class TinaAdminApi {
|
|
|
18
15
|
schema: TinaSchema;
|
|
19
16
|
constructor(cms: TinaCMS);
|
|
20
17
|
isAuthenticated(): Promise<boolean>;
|
|
18
|
+
checkGraphqlSchema({ localSchema }: {
|
|
19
|
+
localSchema: any;
|
|
20
|
+
}): Promise<boolean>;
|
|
21
21
|
fetchCollections(): import("@tinacms/schema-tools").TinaCloudCollection<true>[];
|
|
22
22
|
renameDocument({ collection, relativePath, newRelativePath }: {
|
|
23
23
|
collection: any;
|
package/dist/admin/index.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*/
|
|
4
1
|
/// <reference types="react" />
|
|
5
|
-
export declare const TinaAdmin: ({ preview, config, }: {
|
|
2
|
+
export declare const TinaAdmin: ({ preview, config, schemaJson, }: {
|
|
3
|
+
schemaJson?: any;
|
|
6
4
|
preview?: (props: object) => JSX.Element;
|
|
7
5
|
config: object;
|
|
8
6
|
}) => JSX.Element;
|
package/dist/index.es.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
import { useCMS, Form, GlobalFormPlugin, EventBus, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, TinaMediaStore, DummyMediaStore, Nav, BranchBanner, LocalWarning, BillingWarning, Select, Input, ReactDateTimeWithStyles, textFieldClasses, Toggle, OverflowMenu, CursorPaginator, PopupModal, BaseTextField, wrapFieldsWithMeta, FormStatus, FormBuilder } from "@tinacms/toolkit";
|
|
2
3
|
export * from "@tinacms/toolkit";
|
|
3
4
|
export { MdxFieldPluginExtendible } from "@tinacms/toolkit";
|
|
4
5
|
import * as G from "graphql";
|
|
5
|
-
import { TypeInfo, visit, visitWithTypeInfo, getNamedType, GraphQLObjectType, isLeafType, GraphQLUnionType, isScalarType as isScalarType$1, getIntrospectionQuery, buildClientSchema, print, parse } from "graphql";
|
|
6
|
+
import { TypeInfo, visit, visitWithTypeInfo, getNamedType, GraphQLObjectType, isLeafType, GraphQLUnionType, isScalarType as isScalarType$1, getIntrospectionQuery, buildClientSchema, print, parse, buildSchema } from "graphql";
|
|
6
7
|
import set from "lodash.set";
|
|
7
8
|
import React, { useState, useCallback, useEffect, Fragment, useMemo } from "react";
|
|
8
9
|
import { getIn, setIn } from "final-form";
|
|
9
10
|
import { resolveForm, TinaSchema, addNamespaceToSchema, parseURL, validateSchema } from "@tinacms/schema-tools";
|
|
10
11
|
export { NAMER, resolveForm } from "@tinacms/schema-tools";
|
|
11
|
-
import gql$1 from "graphql-tag";
|
|
12
12
|
import * as yup from "yup";
|
|
13
|
+
import gql$1 from "graphql-tag";
|
|
13
14
|
import { setEditing, TinaDataContext, EditContext, useEditState } from "@tinacms/sharedctx";
|
|
15
|
+
import { diff } from "@graphql-inspector/core";
|
|
14
16
|
import { NavLink, useSearchParams, useNavigate, useParams, useLocation, Link, HashRouter, Routes, Route } from "react-router-dom";
|
|
15
17
|
import { Transition, Menu } from "@headlessui/react";
|
|
16
18
|
import { useWindowWidth } from "@react-hook/window-size";
|
|
@@ -2114,6 +2116,38 @@ const parseRefForBranchName = (ref) => {
|
|
|
2114
2116
|
const matches = ref.match(captureBranchName);
|
|
2115
2117
|
return matches[1];
|
|
2116
2118
|
};
|
|
2119
|
+
const ListBranchResponse = z.object({
|
|
2120
|
+
name: z.string(),
|
|
2121
|
+
protected: z.boolean(),
|
|
2122
|
+
commit: z.object({ sha: z.string(), url: z.string() })
|
|
2123
|
+
}).array();
|
|
2124
|
+
const IndexStatusResponse = z.object({
|
|
2125
|
+
status: z.union([
|
|
2126
|
+
z.literal("complete"),
|
|
2127
|
+
z.literal("unknown"),
|
|
2128
|
+
z.literal("failed"),
|
|
2129
|
+
z.literal("inprogress")
|
|
2130
|
+
]).optional(),
|
|
2131
|
+
timestamp: z.number().optional()
|
|
2132
|
+
});
|
|
2133
|
+
async function asyncPoll(fn, pollInterval = 5 * 1e3, pollTimeout = 30 * 1e3) {
|
|
2134
|
+
const endTime = new Date().getTime() + pollTimeout;
|
|
2135
|
+
const checkCondition = (resolve, reject) => {
|
|
2136
|
+
Promise.resolve(fn()).then((result) => {
|
|
2137
|
+
const now = new Date().getTime();
|
|
2138
|
+
if (result.done) {
|
|
2139
|
+
resolve(result.data);
|
|
2140
|
+
} else if (now < endTime) {
|
|
2141
|
+
setTimeout(checkCondition, pollInterval, resolve, reject);
|
|
2142
|
+
} else {
|
|
2143
|
+
reject(new Error("AsyncPoller: reached timeout"));
|
|
2144
|
+
}
|
|
2145
|
+
}).catch((err) => {
|
|
2146
|
+
reject(err);
|
|
2147
|
+
});
|
|
2148
|
+
};
|
|
2149
|
+
return new Promise(checkCondition);
|
|
2150
|
+
}
|
|
2117
2151
|
class Client {
|
|
2118
2152
|
constructor({ tokenStorage = "MEMORY", ...options }) {
|
|
2119
2153
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P;
|
|
@@ -2431,12 +2465,64 @@ mutation addPendingDocumentMutation(
|
|
|
2431
2465
|
return null;
|
|
2432
2466
|
}
|
|
2433
2467
|
}
|
|
2468
|
+
async waitForIndexStatus({ ref }) {
|
|
2469
|
+
try {
|
|
2470
|
+
const result = await asyncPoll(async () => {
|
|
2471
|
+
try {
|
|
2472
|
+
const result2 = await this.getIndexStatus({ ref });
|
|
2473
|
+
if (!(result2.status === "inprogress" || result2.status === "unknown")) {
|
|
2474
|
+
return Promise.resolve({
|
|
2475
|
+
done: true,
|
|
2476
|
+
data: result2
|
|
2477
|
+
});
|
|
2478
|
+
} else {
|
|
2479
|
+
return Promise.resolve({
|
|
2480
|
+
done: false
|
|
2481
|
+
});
|
|
2482
|
+
}
|
|
2483
|
+
} catch (err) {
|
|
2484
|
+
return Promise.reject(err);
|
|
2485
|
+
}
|
|
2486
|
+
}, 5e3, 9e5);
|
|
2487
|
+
return result;
|
|
2488
|
+
} catch (error) {
|
|
2489
|
+
if (error.message === "AsyncPoller: reached timeout") {
|
|
2490
|
+
console.warn(error);
|
|
2491
|
+
return {
|
|
2492
|
+
status: "timeout"
|
|
2493
|
+
};
|
|
2494
|
+
}
|
|
2495
|
+
throw error;
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
async getIndexStatus({ ref }) {
|
|
2499
|
+
const url = `${this.contentApiBase}/db/${this.clientId}/status/${ref}`;
|
|
2500
|
+
const res = await this.fetchWithToken(url);
|
|
2501
|
+
const result = await res.json();
|
|
2502
|
+
const parsedResult = IndexStatusResponse.parse(result);
|
|
2503
|
+
return parsedResult;
|
|
2504
|
+
}
|
|
2434
2505
|
async listBranches() {
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2506
|
+
try {
|
|
2507
|
+
const url = `${this.contentApiBase}/github/${this.clientId}/list_branches`;
|
|
2508
|
+
const res = await this.fetchWithToken(url, {
|
|
2509
|
+
method: "GET"
|
|
2510
|
+
});
|
|
2511
|
+
const branches = await res.json();
|
|
2512
|
+
const parsedBranches = ListBranchResponse.parse(branches);
|
|
2513
|
+
const indexStatusPromises = parsedBranches.map(async (branch) => {
|
|
2514
|
+
const indexStatus2 = await this.getIndexStatus({ ref: branch.name });
|
|
2515
|
+
return {
|
|
2516
|
+
...branch,
|
|
2517
|
+
indexStatus: indexStatus2
|
|
2518
|
+
};
|
|
2519
|
+
});
|
|
2520
|
+
const indexStatus = await Promise.all(indexStatusPromises);
|
|
2521
|
+
return indexStatus;
|
|
2522
|
+
} catch (error) {
|
|
2523
|
+
console.error("There was an error listing branches.", error);
|
|
2524
|
+
throw error;
|
|
2525
|
+
}
|
|
2440
2526
|
}
|
|
2441
2527
|
async createBranch({ baseBranch, branchName }) {
|
|
2442
2528
|
const url = `${this.contentApiBase}/github/${this.clientId}/create_branch`;
|
|
@@ -2538,6 +2624,17 @@ class TinaAdminApi {
|
|
|
2538
2624
|
async isAuthenticated() {
|
|
2539
2625
|
return await this.api.isAuthenticated();
|
|
2540
2626
|
}
|
|
2627
|
+
async checkGraphqlSchema({ localSchema }) {
|
|
2628
|
+
const schemaFromCloud = await this.api.getSchema();
|
|
2629
|
+
const schema1 = schemaFromCloud;
|
|
2630
|
+
const schema2 = buildSchema(print(localSchema));
|
|
2631
|
+
const diffOutput = await diff(schema1, schema2);
|
|
2632
|
+
if (diffOutput.length > 0) {
|
|
2633
|
+
return false;
|
|
2634
|
+
} else {
|
|
2635
|
+
return true;
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2541
2638
|
fetchCollections() {
|
|
2542
2639
|
return this.schema.getCollections();
|
|
2543
2640
|
}
|
|
@@ -5376,7 +5473,7 @@ const CollectionListPage = () => {
|
|
|
5376
5473
|
onChange: (e) => {
|
|
5377
5474
|
setVars((old) => ({
|
|
5378
5475
|
...old,
|
|
5379
|
-
after: e.format(),
|
|
5476
|
+
after: typeof e.format === "function" ? e.format() : "",
|
|
5380
5477
|
booleanEquals: null,
|
|
5381
5478
|
startsWith: ""
|
|
5382
5479
|
}));
|
|
@@ -5394,7 +5491,7 @@ const CollectionListPage = () => {
|
|
|
5394
5491
|
onChange: (e) => {
|
|
5395
5492
|
setVars((old) => ({
|
|
5396
5493
|
...old,
|
|
5397
|
-
before: e.format(),
|
|
5494
|
+
before: typeof e.format === "function" ? e.format() : "",
|
|
5398
5495
|
booleanEquals: null,
|
|
5399
5496
|
startsWith: ""
|
|
5400
5497
|
}));
|
|
@@ -6052,9 +6149,30 @@ const PreviewInner = ({ preview, config }) => {
|
|
|
6052
6149
|
...config
|
|
6053
6150
|
});
|
|
6054
6151
|
};
|
|
6152
|
+
const CheckSchema = ({
|
|
6153
|
+
schemaJson,
|
|
6154
|
+
children
|
|
6155
|
+
}) => {
|
|
6156
|
+
const cms = useCMS();
|
|
6157
|
+
const api = new TinaAdminApi(cms);
|
|
6158
|
+
const url = api.api.contentApiUrl;
|
|
6159
|
+
useEffect(() => {
|
|
6160
|
+
if (schemaJson && cms) {
|
|
6161
|
+
api.checkGraphqlSchema({
|
|
6162
|
+
localSchema: schemaJson
|
|
6163
|
+
}).then((x) => {
|
|
6164
|
+
if (x === false) {
|
|
6165
|
+
cms.alerts.error("GraphQL Schema Mismatch. Editing may not work. If you just switched branches, try going back to the previous branch");
|
|
6166
|
+
}
|
|
6167
|
+
});
|
|
6168
|
+
}
|
|
6169
|
+
}, [cms, JSON.stringify(schemaJson || {}), url]);
|
|
6170
|
+
return children;
|
|
6171
|
+
};
|
|
6055
6172
|
const TinaAdmin = ({
|
|
6056
6173
|
preview,
|
|
6057
|
-
config
|
|
6174
|
+
config,
|
|
6175
|
+
schemaJson
|
|
6058
6176
|
}) => {
|
|
6059
6177
|
const isSSR2 = typeof window === "undefined";
|
|
6060
6178
|
const { edit } = useEditState();
|
|
@@ -6065,9 +6183,18 @@ const TinaAdmin = ({
|
|
|
6065
6183
|
return /* @__PURE__ */ React.createElement(Layout, null, /* @__PURE__ */ React.createElement(LoginPage, null));
|
|
6066
6184
|
}
|
|
6067
6185
|
return /* @__PURE__ */ React.createElement(GetCMS, null, (cms) => {
|
|
6186
|
+
var _a, _b, _c;
|
|
6068
6187
|
const isTinaAdminEnabled = cms.flags.get("tina-admin") === false ? false : true;
|
|
6069
6188
|
if (isTinaAdminEnabled) {
|
|
6070
|
-
|
|
6189
|
+
const tinaClient = (_a = cms.api) == null ? void 0 : _a.tina;
|
|
6190
|
+
const collectionWithRouter = (_c = (_b = tinaClient == null ? void 0 : tinaClient.schema) == null ? void 0 : _b.config) == null ? void 0 : _c.collections.find((x) => {
|
|
6191
|
+
var _a2;
|
|
6192
|
+
return typeof ((_a2 = x == null ? void 0 : x.ui) == null ? void 0 : _a2.router) === "function";
|
|
6193
|
+
});
|
|
6194
|
+
const hasRouter = Boolean(collectionWithRouter);
|
|
6195
|
+
return /* @__PURE__ */ React.createElement(CheckSchema, {
|
|
6196
|
+
schemaJson
|
|
6197
|
+
}, /* @__PURE__ */ React.createElement(HashRouter, null, /* @__PURE__ */ React.createElement(SetPreviewFlag, {
|
|
6071
6198
|
preview,
|
|
6072
6199
|
cms
|
|
6073
6200
|
}), /* @__PURE__ */ React.createElement(Routes, null, preview && /* @__PURE__ */ React.createElement(Route, {
|
|
@@ -6109,11 +6236,11 @@ const TinaAdmin = ({
|
|
|
6109
6236
|
}), /* @__PURE__ */ React.createElement(Route, {
|
|
6110
6237
|
path: "/",
|
|
6111
6238
|
element: /* @__PURE__ */ React.createElement(MaybeRedirectToPreview, {
|
|
6112
|
-
redirect: !!preview
|
|
6239
|
+
redirect: !!preview && hasRouter
|
|
6113
6240
|
}, /* @__PURE__ */ React.createElement(DefaultWrapper, {
|
|
6114
6241
|
cms
|
|
6115
6242
|
}, /* @__PURE__ */ React.createElement(DashboardPage, null)))
|
|
6116
|
-
})));
|
|
6243
|
+
}))));
|
|
6117
6244
|
} else {
|
|
6118
6245
|
return /* @__PURE__ */ React.createElement(Layout, null, /* @__PURE__ */ React.createElement(HashRouter, null, /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, {
|
|
6119
6246
|
path: "logout",
|
|
@@ -6160,4 +6287,4 @@ const defineStaticConfig = (config) => {
|
|
|
6160
6287
|
return config;
|
|
6161
6288
|
};
|
|
6162
6289
|
const defineConfig = defineStaticConfig;
|
|
6163
|
-
export { AuthWallInner, Client, DEFAULT_LOCAL_TINA_GQL_SERVER_URL, LocalClient, RouteMappingPlugin, TinaAdmin, TinaAdminApi, TinaCMSProvider2, TinaCloudAuthWall, TinaCloudProvider, TinaDataProvider, assertShape, createClient, TinaCMSProvider2 as default, defineConfig, defineLegacyConfig, defineSchema, defineStaticConfig, getStaticPropsForTina, gql, safeAssertShape, staticRequest, useDocumentCreatorPlugin, useGraphqlForms, useTinaAuthRedirect };
|
|
6290
|
+
export { AuthWallInner, Client, DEFAULT_LOCAL_TINA_GQL_SERVER_URL, LocalClient, RouteMappingPlugin, TinaAdmin, TinaAdminApi, TinaCMSProvider2, TinaCloudAuthWall, TinaCloudProvider, TinaDataProvider, assertShape, asyncPoll, createClient, TinaCMSProvider2 as default, defineConfig, defineLegacyConfig, defineSchema, defineStaticConfig, getStaticPropsForTina, gql, safeAssertShape, staticRequest, useDocumentCreatorPlugin, useGraphqlForms, useTinaAuthRedirect };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function(global, factory) {
|
|
2
|
-
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("@tinacms/toolkit"), require("graphql"), require("lodash.set"), require("react"), require("final-form"), require("@tinacms/schema-tools"), require("graphql-tag"), require("
|
|
3
|
-
})(this, function(exports2, toolkit, G, set, React, finalForm, schemaTools, gql$1,
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("zod"), require("@tinacms/toolkit"), require("graphql"), require("lodash.set"), require("react"), require("final-form"), require("@tinacms/schema-tools"), require("yup"), require("graphql-tag"), require("@tinacms/sharedctx"), require("@graphql-inspector/core"), require("react-router-dom"), require("@headlessui/react"), require("@react-hook/window-size")) : typeof define === "function" && define.amd ? define(["exports", "zod", "@tinacms/toolkit", "graphql", "lodash.set", "react", "final-form", "@tinacms/schema-tools", "yup", "graphql-tag", "@tinacms/sharedctx", "@graphql-inspector/core", "react-router-dom", "@headlessui/react", "@react-hook/window-size"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.tinacms = {}, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP));
|
|
3
|
+
})(this, function(exports2, zod, toolkit, G, set, React, finalForm, schemaTools, yup, gql$1, sharedctx, core, reactRouterDom, react, windowSize) {
|
|
4
4
|
"use strict";
|
|
5
5
|
function _interopDefaultLegacy(e) {
|
|
6
6
|
return e && typeof e === "object" && "default" in e ? e : { "default": e };
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
var G__namespace = /* @__PURE__ */ _interopNamespace(G);
|
|
29
29
|
var set__default = /* @__PURE__ */ _interopDefaultLegacy(set);
|
|
30
30
|
var React__default = /* @__PURE__ */ _interopDefaultLegacy(React);
|
|
31
|
-
var gql__default = /* @__PURE__ */ _interopDefaultLegacy(gql$1);
|
|
32
31
|
var yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
|
|
32
|
+
var gql__default = /* @__PURE__ */ _interopDefaultLegacy(gql$1);
|
|
33
33
|
function popupWindow(url, title, window2, w, h) {
|
|
34
34
|
const y = window2.top.outerHeight / 2 + window2.top.screenY - h / 2;
|
|
35
35
|
const x = window2.top.outerWidth / 2 + window2.top.screenX - w / 2;
|
|
@@ -2130,6 +2130,38 @@
|
|
|
2130
2130
|
const matches = ref.match(captureBranchName);
|
|
2131
2131
|
return matches[1];
|
|
2132
2132
|
};
|
|
2133
|
+
const ListBranchResponse = zod.z.object({
|
|
2134
|
+
name: zod.z.string(),
|
|
2135
|
+
protected: zod.z.boolean(),
|
|
2136
|
+
commit: zod.z.object({ sha: zod.z.string(), url: zod.z.string() })
|
|
2137
|
+
}).array();
|
|
2138
|
+
const IndexStatusResponse = zod.z.object({
|
|
2139
|
+
status: zod.z.union([
|
|
2140
|
+
zod.z.literal("complete"),
|
|
2141
|
+
zod.z.literal("unknown"),
|
|
2142
|
+
zod.z.literal("failed"),
|
|
2143
|
+
zod.z.literal("inprogress")
|
|
2144
|
+
]).optional(),
|
|
2145
|
+
timestamp: zod.z.number().optional()
|
|
2146
|
+
});
|
|
2147
|
+
async function asyncPoll(fn, pollInterval = 5 * 1e3, pollTimeout = 30 * 1e3) {
|
|
2148
|
+
const endTime = new Date().getTime() + pollTimeout;
|
|
2149
|
+
const checkCondition = (resolve, reject) => {
|
|
2150
|
+
Promise.resolve(fn()).then((result) => {
|
|
2151
|
+
const now = new Date().getTime();
|
|
2152
|
+
if (result.done) {
|
|
2153
|
+
resolve(result.data);
|
|
2154
|
+
} else if (now < endTime) {
|
|
2155
|
+
setTimeout(checkCondition, pollInterval, resolve, reject);
|
|
2156
|
+
} else {
|
|
2157
|
+
reject(new Error("AsyncPoller: reached timeout"));
|
|
2158
|
+
}
|
|
2159
|
+
}).catch((err) => {
|
|
2160
|
+
reject(err);
|
|
2161
|
+
});
|
|
2162
|
+
};
|
|
2163
|
+
return new Promise(checkCondition);
|
|
2164
|
+
}
|
|
2133
2165
|
class Client {
|
|
2134
2166
|
constructor({ tokenStorage = "MEMORY", ...options }) {
|
|
2135
2167
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P;
|
|
@@ -2447,12 +2479,64 @@ mutation addPendingDocumentMutation(
|
|
|
2447
2479
|
return null;
|
|
2448
2480
|
}
|
|
2449
2481
|
}
|
|
2482
|
+
async waitForIndexStatus({ ref }) {
|
|
2483
|
+
try {
|
|
2484
|
+
const result = await asyncPoll(async () => {
|
|
2485
|
+
try {
|
|
2486
|
+
const result2 = await this.getIndexStatus({ ref });
|
|
2487
|
+
if (!(result2.status === "inprogress" || result2.status === "unknown")) {
|
|
2488
|
+
return Promise.resolve({
|
|
2489
|
+
done: true,
|
|
2490
|
+
data: result2
|
|
2491
|
+
});
|
|
2492
|
+
} else {
|
|
2493
|
+
return Promise.resolve({
|
|
2494
|
+
done: false
|
|
2495
|
+
});
|
|
2496
|
+
}
|
|
2497
|
+
} catch (err) {
|
|
2498
|
+
return Promise.reject(err);
|
|
2499
|
+
}
|
|
2500
|
+
}, 5e3, 9e5);
|
|
2501
|
+
return result;
|
|
2502
|
+
} catch (error) {
|
|
2503
|
+
if (error.message === "AsyncPoller: reached timeout") {
|
|
2504
|
+
console.warn(error);
|
|
2505
|
+
return {
|
|
2506
|
+
status: "timeout"
|
|
2507
|
+
};
|
|
2508
|
+
}
|
|
2509
|
+
throw error;
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
async getIndexStatus({ ref }) {
|
|
2513
|
+
const url = `${this.contentApiBase}/db/${this.clientId}/status/${ref}`;
|
|
2514
|
+
const res = await this.fetchWithToken(url);
|
|
2515
|
+
const result = await res.json();
|
|
2516
|
+
const parsedResult = IndexStatusResponse.parse(result);
|
|
2517
|
+
return parsedResult;
|
|
2518
|
+
}
|
|
2450
2519
|
async listBranches() {
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2520
|
+
try {
|
|
2521
|
+
const url = `${this.contentApiBase}/github/${this.clientId}/list_branches`;
|
|
2522
|
+
const res = await this.fetchWithToken(url, {
|
|
2523
|
+
method: "GET"
|
|
2524
|
+
});
|
|
2525
|
+
const branches = await res.json();
|
|
2526
|
+
const parsedBranches = ListBranchResponse.parse(branches);
|
|
2527
|
+
const indexStatusPromises = parsedBranches.map(async (branch) => {
|
|
2528
|
+
const indexStatus2 = await this.getIndexStatus({ ref: branch.name });
|
|
2529
|
+
return {
|
|
2530
|
+
...branch,
|
|
2531
|
+
indexStatus: indexStatus2
|
|
2532
|
+
};
|
|
2533
|
+
});
|
|
2534
|
+
const indexStatus = await Promise.all(indexStatusPromises);
|
|
2535
|
+
return indexStatus;
|
|
2536
|
+
} catch (error) {
|
|
2537
|
+
console.error("There was an error listing branches.", error);
|
|
2538
|
+
throw error;
|
|
2539
|
+
}
|
|
2456
2540
|
}
|
|
2457
2541
|
async createBranch({ baseBranch, branchName }) {
|
|
2458
2542
|
const url = `${this.contentApiBase}/github/${this.clientId}/create_branch`;
|
|
@@ -2554,6 +2638,17 @@ mutation addPendingDocumentMutation(
|
|
|
2554
2638
|
async isAuthenticated() {
|
|
2555
2639
|
return await this.api.isAuthenticated();
|
|
2556
2640
|
}
|
|
2641
|
+
async checkGraphqlSchema({ localSchema }) {
|
|
2642
|
+
const schemaFromCloud = await this.api.getSchema();
|
|
2643
|
+
const schema1 = schemaFromCloud;
|
|
2644
|
+
const schema2 = G.buildSchema(G.print(localSchema));
|
|
2645
|
+
const diffOutput = await core.diff(schema1, schema2);
|
|
2646
|
+
if (diffOutput.length > 0) {
|
|
2647
|
+
return false;
|
|
2648
|
+
} else {
|
|
2649
|
+
return true;
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2557
2652
|
fetchCollections() {
|
|
2558
2653
|
return this.schema.getCollections();
|
|
2559
2654
|
}
|
|
@@ -5392,7 +5487,7 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
5392
5487
|
onChange: (e) => {
|
|
5393
5488
|
setVars((old) => ({
|
|
5394
5489
|
...old,
|
|
5395
|
-
after: e.format(),
|
|
5490
|
+
after: typeof e.format === "function" ? e.format() : "",
|
|
5396
5491
|
booleanEquals: null,
|
|
5397
5492
|
startsWith: ""
|
|
5398
5493
|
}));
|
|
@@ -5410,7 +5505,7 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
5410
5505
|
onChange: (e) => {
|
|
5411
5506
|
setVars((old) => ({
|
|
5412
5507
|
...old,
|
|
5413
|
-
before: e.format(),
|
|
5508
|
+
before: typeof e.format === "function" ? e.format() : "",
|
|
5414
5509
|
booleanEquals: null,
|
|
5415
5510
|
startsWith: ""
|
|
5416
5511
|
}));
|
|
@@ -6068,9 +6163,30 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
6068
6163
|
...config
|
|
6069
6164
|
});
|
|
6070
6165
|
};
|
|
6166
|
+
const CheckSchema = ({
|
|
6167
|
+
schemaJson,
|
|
6168
|
+
children
|
|
6169
|
+
}) => {
|
|
6170
|
+
const cms = toolkit.useCMS();
|
|
6171
|
+
const api = new TinaAdminApi(cms);
|
|
6172
|
+
const url = api.api.contentApiUrl;
|
|
6173
|
+
React.useEffect(() => {
|
|
6174
|
+
if (schemaJson && cms) {
|
|
6175
|
+
api.checkGraphqlSchema({
|
|
6176
|
+
localSchema: schemaJson
|
|
6177
|
+
}).then((x) => {
|
|
6178
|
+
if (x === false) {
|
|
6179
|
+
cms.alerts.error("GraphQL Schema Mismatch. Editing may not work. If you just switched branches, try going back to the previous branch");
|
|
6180
|
+
}
|
|
6181
|
+
});
|
|
6182
|
+
}
|
|
6183
|
+
}, [cms, JSON.stringify(schemaJson || {}), url]);
|
|
6184
|
+
return children;
|
|
6185
|
+
};
|
|
6071
6186
|
const TinaAdmin = ({
|
|
6072
6187
|
preview,
|
|
6073
|
-
config
|
|
6188
|
+
config,
|
|
6189
|
+
schemaJson
|
|
6074
6190
|
}) => {
|
|
6075
6191
|
const isSSR2 = typeof window === "undefined";
|
|
6076
6192
|
const { edit } = sharedctx.useEditState();
|
|
@@ -6081,9 +6197,18 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
6081
6197
|
return /* @__PURE__ */ React__default["default"].createElement(Layout, null, /* @__PURE__ */ React__default["default"].createElement(LoginPage, null));
|
|
6082
6198
|
}
|
|
6083
6199
|
return /* @__PURE__ */ React__default["default"].createElement(GetCMS, null, (cms) => {
|
|
6200
|
+
var _a, _b, _c;
|
|
6084
6201
|
const isTinaAdminEnabled = cms.flags.get("tina-admin") === false ? false : true;
|
|
6085
6202
|
if (isTinaAdminEnabled) {
|
|
6086
|
-
|
|
6203
|
+
const tinaClient = (_a = cms.api) == null ? void 0 : _a.tina;
|
|
6204
|
+
const collectionWithRouter = (_c = (_b = tinaClient == null ? void 0 : tinaClient.schema) == null ? void 0 : _b.config) == null ? void 0 : _c.collections.find((x) => {
|
|
6205
|
+
var _a2;
|
|
6206
|
+
return typeof ((_a2 = x == null ? void 0 : x.ui) == null ? void 0 : _a2.router) === "function";
|
|
6207
|
+
});
|
|
6208
|
+
const hasRouter = Boolean(collectionWithRouter);
|
|
6209
|
+
return /* @__PURE__ */ React__default["default"].createElement(CheckSchema, {
|
|
6210
|
+
schemaJson
|
|
6211
|
+
}, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.HashRouter, null, /* @__PURE__ */ React__default["default"].createElement(SetPreviewFlag, {
|
|
6087
6212
|
preview,
|
|
6088
6213
|
cms
|
|
6089
6214
|
}), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Routes, null, preview && /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
|
|
@@ -6125,11 +6250,11 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
6125
6250
|
}), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
|
|
6126
6251
|
path: "/",
|
|
6127
6252
|
element: /* @__PURE__ */ React__default["default"].createElement(MaybeRedirectToPreview, {
|
|
6128
|
-
redirect: !!preview
|
|
6253
|
+
redirect: !!preview && hasRouter
|
|
6129
6254
|
}, /* @__PURE__ */ React__default["default"].createElement(DefaultWrapper, {
|
|
6130
6255
|
cms
|
|
6131
6256
|
}, /* @__PURE__ */ React__default["default"].createElement(DashboardPage, null)))
|
|
6132
|
-
})));
|
|
6257
|
+
}))));
|
|
6133
6258
|
} else {
|
|
6134
6259
|
return /* @__PURE__ */ React__default["default"].createElement(Layout, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.HashRouter, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Routes, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
|
|
6135
6260
|
path: "logout",
|
|
@@ -6206,6 +6331,7 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
6206
6331
|
exports2.TinaCloudProvider = TinaCloudProvider;
|
|
6207
6332
|
exports2.TinaDataProvider = TinaDataProvider;
|
|
6208
6333
|
exports2.assertShape = assertShape;
|
|
6334
|
+
exports2.asyncPoll = asyncPoll;
|
|
6209
6335
|
exports2.createClient = createClient;
|
|
6210
6336
|
exports2["default"] = TinaCMSProvider2;
|
|
6211
6337
|
exports2.defineConfig = defineConfig;
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*/
|
|
4
1
|
import { TokenObject } from '../auth/authenticate';
|
|
5
2
|
import { BranchData, EventBus } from '@tinacms/toolkit';
|
|
6
3
|
import { DocumentNode, GraphQLSchema } from 'graphql';
|
|
@@ -24,6 +21,90 @@ interface ServerOptions {
|
|
|
24
21
|
tinaioConfig?: TinaIOConfig;
|
|
25
22
|
tokenStorage?: 'MEMORY' | 'LOCAL_STORAGE' | 'CUSTOM';
|
|
26
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* The function you pass to `asyncPoll` should return a promise
|
|
26
|
+
* that resolves with object that satisfies this interface.
|
|
27
|
+
*
|
|
28
|
+
* The `done` property indicates to the async poller whether to
|
|
29
|
+
* continue polling or not.
|
|
30
|
+
*
|
|
31
|
+
* When done is `true` that means you've got what you need
|
|
32
|
+
* and the poller will resolve with `data`.
|
|
33
|
+
*
|
|
34
|
+
* When done is `false` taht means you don't have what you need
|
|
35
|
+
* and the poller will continue polling.
|
|
36
|
+
*/
|
|
37
|
+
export interface AsyncData<T> {
|
|
38
|
+
done: boolean;
|
|
39
|
+
data?: T;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Your custom function you provide to the async poller should
|
|
43
|
+
* satisfy this interface. Your function returns a promise that
|
|
44
|
+
* resolves with `AsyncData` to indicate to the poller whether
|
|
45
|
+
* you have what you need or we should continue polling.
|
|
46
|
+
*/
|
|
47
|
+
export interface AsyncFunction<T> extends Function {
|
|
48
|
+
(): PromiseLike<AsyncData<T>>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* How to repeatedly call an async function until get a desired result.
|
|
52
|
+
*
|
|
53
|
+
* Inspired by the following gist:
|
|
54
|
+
* https://gist.github.com/twmbx/2321921670c7e95f6fad164fbdf3170e#gistcomment-3053587
|
|
55
|
+
* https://davidwalsh.name/javascript-polling
|
|
56
|
+
*
|
|
57
|
+
* Usage:
|
|
58
|
+
asyncPoll(
|
|
59
|
+
async (): Promise<AsyncData<any>> => {
|
|
60
|
+
try {
|
|
61
|
+
const result = await getYourAsyncResult();
|
|
62
|
+
if (result.isWhatYouWant) {
|
|
63
|
+
return Promise.resolve({
|
|
64
|
+
done: true,
|
|
65
|
+
data: result,
|
|
66
|
+
});
|
|
67
|
+
} else {
|
|
68
|
+
return Promise.resolve({
|
|
69
|
+
done: false
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
} catch (err) {
|
|
73
|
+
return Promise.reject(err);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
500, // interval
|
|
77
|
+
15000, // timeout
|
|
78
|
+
);
|
|
79
|
+
*/
|
|
80
|
+
export declare function asyncPoll<T>(
|
|
81
|
+
/**
|
|
82
|
+
* Function to call periodically until it resolves or rejects.
|
|
83
|
+
*
|
|
84
|
+
* It should resolve as soon as possible indicating if it found
|
|
85
|
+
* what it was looking for or not. If not then it will be reinvoked
|
|
86
|
+
* after the `pollInterval` if we haven't timed out.
|
|
87
|
+
*
|
|
88
|
+
* Rejections will stop the polling and be propagated.
|
|
89
|
+
*/
|
|
90
|
+
fn: AsyncFunction<T>,
|
|
91
|
+
/**
|
|
92
|
+
* Milliseconds to wait before attempting to resolve the promise again.
|
|
93
|
+
* The promise won't be called concurrently. This is the wait period
|
|
94
|
+
* after the promise has resolved/rejected before trying again for a
|
|
95
|
+
* successful resolve so long as we haven't timed out.
|
|
96
|
+
*
|
|
97
|
+
* Default 5 seconds.
|
|
98
|
+
*/
|
|
99
|
+
pollInterval?: number,
|
|
100
|
+
/**
|
|
101
|
+
* Max time to keep polling to receive a successful resolved response.
|
|
102
|
+
* If the promise never resolves before the timeout then this method
|
|
103
|
+
* rejects with a timeout error.
|
|
104
|
+
*
|
|
105
|
+
* Default 30 seconds.
|
|
106
|
+
*/
|
|
107
|
+
pollTimeout?: number): Promise<T>;
|
|
27
108
|
export declare class Client {
|
|
28
109
|
onLogin?: OnLoginFunc;
|
|
29
110
|
onLogout?: () => Promise<void>;
|
|
@@ -121,7 +202,27 @@ export declare class Client {
|
|
|
121
202
|
delinquencyDate: number;
|
|
122
203
|
billingState: 'current' | 'late' | 'delinquent';
|
|
123
204
|
}>;
|
|
124
|
-
|
|
205
|
+
waitForIndexStatus({ ref }: {
|
|
206
|
+
ref: string;
|
|
207
|
+
}): Promise<any>;
|
|
208
|
+
getIndexStatus({ ref }: {
|
|
209
|
+
ref: string;
|
|
210
|
+
}): Promise<{
|
|
211
|
+
status?: "unknown" | "complete" | "failed" | "inprogress";
|
|
212
|
+
timestamp?: number;
|
|
213
|
+
}>;
|
|
214
|
+
listBranches(): Promise<{
|
|
215
|
+
indexStatus: {
|
|
216
|
+
status?: "unknown" | "complete" | "failed" | "inprogress";
|
|
217
|
+
timestamp?: number;
|
|
218
|
+
};
|
|
219
|
+
name?: string;
|
|
220
|
+
protected?: boolean;
|
|
221
|
+
commit?: {
|
|
222
|
+
url?: string;
|
|
223
|
+
sha?: string;
|
|
224
|
+
};
|
|
225
|
+
}[]>;
|
|
125
226
|
createBranch({ baseBranch, branchName }: BranchData): Promise<string>;
|
|
126
227
|
}
|
|
127
228
|
export declare const DEFAULT_LOCAL_TINA_GQL_SERVER_URL = "http://localhost:4001/graphql";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tinacms",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "./dist/index.es.js",
|
|
6
6
|
"exports": {
|
|
@@ -51,13 +51,14 @@
|
|
|
51
51
|
"typings": "dist/index.d.ts",
|
|
52
52
|
"license": "Apache-2.0",
|
|
53
53
|
"dependencies": {
|
|
54
|
+
"@graphql-inspector/core": "^4.0.0",
|
|
54
55
|
"@graphql-tools/relay-operation-optimizer": "^6.4.1",
|
|
55
56
|
"@headlessui/react": "^1.5.0",
|
|
56
57
|
"@heroicons/react": "^1.0.4",
|
|
57
58
|
"@react-hook/window-size": "^3.0.7",
|
|
58
|
-
"@tinacms/schema-tools": "1.3.
|
|
59
|
+
"@tinacms/schema-tools": "1.3.2",
|
|
59
60
|
"@tinacms/sharedctx": "1.0.1",
|
|
60
|
-
"@tinacms/toolkit": "1.3.
|
|
61
|
+
"@tinacms/toolkit": "1.3.4",
|
|
61
62
|
"crypto-js": "^4.0.0",
|
|
62
63
|
"encoding": "0.1.13",
|
|
63
64
|
"fetch-ponyfill": "^7.1.0",
|
|
@@ -68,7 +69,8 @@
|
|
|
68
69
|
"prism-react-renderer": "^1.3.5",
|
|
69
70
|
"react-icons": "^4.3.1",
|
|
70
71
|
"react-router-dom": "6",
|
|
71
|
-
"yup": "^0.32.0"
|
|
72
|
+
"yup": "^0.32.0",
|
|
73
|
+
"zod": "^3.14.3"
|
|
72
74
|
},
|
|
73
75
|
"devDependencies": {
|
|
74
76
|
"@graphql-tools/utils": "^8.6.1",
|