@tinacms/datalayer 1.2.27 → 1.2.29

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.
@@ -0,0 +1,46 @@
1
+ /// <reference types="node" />
2
+ import type { IncomingMessage, ServerResponse } from 'http';
3
+ declare type DatabaseClient = any;
4
+ export interface BackendAuthProvider {
5
+ initialize?: () => Promise<void>;
6
+ isAuthorized: (req: IncomingMessage, res: ServerResponse) => Promise<{
7
+ isAuthorized: true;
8
+ } | {
9
+ isAuthorized: false;
10
+ errorMessage: string;
11
+ errorCode: number;
12
+ }>;
13
+ extraRoutes?: {
14
+ [key: string]: {
15
+ secure?: boolean;
16
+ handler: NodeRouteHandler;
17
+ };
18
+ };
19
+ }
20
+ export declare const LocalBackendAuthProvider: () => BackendAuthProvider;
21
+ export interface TinaBackendOptions {
22
+ /**
23
+ * The database client to use. Imported from tina/__generated__/databaseClient
24
+ */
25
+ databaseClient: DatabaseClient;
26
+ /**
27
+ * The auth provider to use
28
+ */
29
+ authProvider: BackendAuthProvider;
30
+ /**
31
+ * Options to configure the backend
32
+ */
33
+ options?: {
34
+ /**
35
+ * The base path for the api routes (defaults to /api/tina)
36
+ *
37
+ * @default /api/tina
38
+ */
39
+ basePath?: string;
40
+ };
41
+ }
42
+ export declare type NodeApiHandler = (req: IncomingMessage, res: ServerResponse) => Promise<void>;
43
+ declare type NodeRouteHandlerOptions = Required<TinaBackendOptions['options']>;
44
+ declare type NodeRouteHandler = (req: IncomingMessage, res: ServerResponse, opts: NodeRouteHandlerOptions) => Promise<void>;
45
+ export declare function TinaNodeBackend({ authProvider, databaseClient, options, }: TinaBackendOptions): NodeApiHandler;
46
+ export {};
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
- export type { Bridge, CreateDatabase, OnPutCallback, OnDeleteCallback, Database, } from '@tinacms/graphql';
2
- export { FilesystemBridge, AuditFileSystemBridge, IsomorphicBridge, createDatabase, TinaLevelClient, resolve, } from '@tinacms/graphql';
1
+ export type { Bridge, OnPutCallback, OnDeleteCallback, Database, GitProvider, } from '@tinacms/graphql';
2
+ export { FilesystemBridge, AuditFileSystemBridge, IsomorphicBridge, TinaLevelClient, resolve, createDatabase, createLocalDatabase, } from '@tinacms/graphql';
3
+ export * from './backend';
package/dist/index.js CHANGED
@@ -22,18 +22,147 @@ __export(src_exports, {
22
22
  AuditFileSystemBridge: () => import_graphql.AuditFileSystemBridge,
23
23
  FilesystemBridge: () => import_graphql.FilesystemBridge,
24
24
  IsomorphicBridge: () => import_graphql.IsomorphicBridge,
25
+ LocalBackendAuthProvider: () => LocalBackendAuthProvider,
25
26
  TinaLevelClient: () => import_graphql.TinaLevelClient,
27
+ TinaNodeBackend: () => TinaNodeBackend,
26
28
  createDatabase: () => import_graphql.createDatabase,
29
+ createLocalDatabase: () => import_graphql.createLocalDatabase,
27
30
  resolve: () => import_graphql.resolve
28
31
  });
29
32
  module.exports = __toCommonJS(src_exports);
30
33
  var import_graphql = require("@tinacms/graphql");
34
+
35
+ // src/backend/index.ts
36
+ var LocalBackendAuthProvider = () => ({
37
+ isAuthorized: async () => ({ isAuthorized: true })
38
+ });
39
+ function TinaNodeBackend({
40
+ authProvider,
41
+ databaseClient,
42
+ options
43
+ }) {
44
+ const { initialize, isAuthorized, extraRoutes } = authProvider;
45
+ initialize == null ? void 0 : initialize().catch((e) => {
46
+ console.error(e);
47
+ });
48
+ const basePath = (options == null ? void 0 : options.basePath) ? `/${options.basePath.replace(/^\/?/, "").replace(/\/?$/, "")}/` : "/api/tina/";
49
+ const opts = {
50
+ basePath
51
+ };
52
+ const handler = MakeNodeApiHandler({
53
+ isAuthorized,
54
+ extraRoutes,
55
+ databaseClient,
56
+ opts
57
+ });
58
+ return handler;
59
+ }
60
+ function MakeNodeApiHandler({
61
+ isAuthorized,
62
+ extraRoutes,
63
+ databaseClient,
64
+ opts
65
+ }) {
66
+ const tinaBackendHandler = async (req, res) => {
67
+ var _a, _b, _c, _d;
68
+ const path = ((_a = req.url) == null ? void 0 : _a.startsWith("/")) ? req.url.slice(1) : req.url;
69
+ const url = new URL(path, `http://${((_b = req.headers) == null ? void 0 : _b.host) || "localhost"}`);
70
+ const routes = (_d = (_c = url.pathname) == null ? void 0 : _c.replace(opts.basePath, "")) == null ? void 0 : _d.split("/");
71
+ if (typeof routes === "string") {
72
+ throw new Error("Please name your next api route [...routes] not [route]");
73
+ }
74
+ if (!(routes == null ? void 0 : routes.length)) {
75
+ console.error(
76
+ `A request was made to ${opts.basePath} but no route was found`
77
+ );
78
+ res.statusCode = 404;
79
+ res.write(JSON.stringify({ error: "not found" }));
80
+ res.end();
81
+ return;
82
+ }
83
+ const allRoutes = {
84
+ gql: {
85
+ handler: async (req2, res2, _opts) => {
86
+ var _a2;
87
+ if (req2.method !== "POST") {
88
+ res2.statusCode = 405;
89
+ res2.write(
90
+ JSON.stringify({
91
+ error: "Method not allowed. Only POST requests are supported by /gql"
92
+ })
93
+ );
94
+ res2.end();
95
+ return;
96
+ }
97
+ if (!req2.body) {
98
+ console.error(
99
+ "Please make sure that you have a body parser set up for your server and req.body is defined"
100
+ );
101
+ res2.statusCode = 400;
102
+ res2.write(JSON.stringify({ error: "no body" }));
103
+ res2.end();
104
+ return;
105
+ }
106
+ if (!req2.body.query) {
107
+ res2.statusCode = 400;
108
+ res2.write(JSON.stringify({ error: "no query" }));
109
+ res2.end();
110
+ return;
111
+ }
112
+ if (!req2.body.variables) {
113
+ res2.statusCode = 400;
114
+ res2.write(JSON.stringify({ error: "no variables" }));
115
+ res2.end();
116
+ return;
117
+ }
118
+ const { query, variables } = req2.body;
119
+ const result = await databaseClient.request({
120
+ query,
121
+ variables,
122
+ user: (_a2 = req2 == null ? void 0 : req2.session) == null ? void 0 : _a2.user
123
+ });
124
+ res2.statusCode = 200;
125
+ res2.write(JSON.stringify(result));
126
+ res2.end();
127
+ return;
128
+ },
129
+ secure: true
130
+ },
131
+ ...extraRoutes || {}
132
+ };
133
+ const [action] = routes;
134
+ const currentRoute = allRoutes[action];
135
+ if (!currentRoute) {
136
+ res.statusCode = 404;
137
+ const errorMessage = `Error: ${action} not found in routes`;
138
+ console.error(errorMessage);
139
+ res.write(JSON.stringify({ error: errorMessage }));
140
+ res.end();
141
+ return;
142
+ }
143
+ const { handler, secure } = currentRoute;
144
+ if (secure) {
145
+ const isAuth = await isAuthorized(req, res);
146
+ if (isAuth.isAuthorized === false) {
147
+ res.statusCode = isAuth.errorCode;
148
+ res.write(JSON.stringify({ error: isAuth.errorMessage || "not found" }));
149
+ res.end();
150
+ return;
151
+ }
152
+ }
153
+ return handler(req, res, opts);
154
+ };
155
+ return tinaBackendHandler;
156
+ }
31
157
  // Annotate the CommonJS export names for ESM import in node:
32
158
  0 && (module.exports = {
33
159
  AuditFileSystemBridge,
34
160
  FilesystemBridge,
35
161
  IsomorphicBridge,
162
+ LocalBackendAuthProvider,
36
163
  TinaLevelClient,
164
+ TinaNodeBackend,
37
165
  createDatabase,
166
+ createLocalDatabase,
38
167
  resolve
39
168
  });
package/dist/index.mjs CHANGED
@@ -3,15 +3,140 @@ import {
3
3
  FilesystemBridge,
4
4
  AuditFileSystemBridge,
5
5
  IsomorphicBridge,
6
- createDatabase,
7
6
  TinaLevelClient,
8
- resolve
7
+ resolve,
8
+ createDatabase,
9
+ createLocalDatabase
9
10
  } from "@tinacms/graphql";
11
+
12
+ // src/backend/index.ts
13
+ var LocalBackendAuthProvider = () => ({
14
+ isAuthorized: async () => ({ isAuthorized: true })
15
+ });
16
+ function TinaNodeBackend({
17
+ authProvider,
18
+ databaseClient,
19
+ options
20
+ }) {
21
+ const { initialize, isAuthorized, extraRoutes } = authProvider;
22
+ initialize?.().catch((e) => {
23
+ console.error(e);
24
+ });
25
+ const basePath = options?.basePath ? `/${options.basePath.replace(/^\/?/, "").replace(/\/?$/, "")}/` : "/api/tina/";
26
+ const opts = {
27
+ basePath
28
+ };
29
+ const handler = MakeNodeApiHandler({
30
+ isAuthorized,
31
+ extraRoutes,
32
+ databaseClient,
33
+ opts
34
+ });
35
+ return handler;
36
+ }
37
+ function MakeNodeApiHandler({
38
+ isAuthorized,
39
+ extraRoutes,
40
+ databaseClient,
41
+ opts
42
+ }) {
43
+ const tinaBackendHandler = async (req, res) => {
44
+ const path = req.url?.startsWith("/") ? req.url.slice(1) : req.url;
45
+ const url = new URL(path, `http://${req.headers?.host || "localhost"}`);
46
+ const routes = url.pathname?.replace(opts.basePath, "")?.split("/");
47
+ if (typeof routes === "string") {
48
+ throw new Error("Please name your next api route [...routes] not [route]");
49
+ }
50
+ if (!routes?.length) {
51
+ console.error(
52
+ `A request was made to ${opts.basePath} but no route was found`
53
+ );
54
+ res.statusCode = 404;
55
+ res.write(JSON.stringify({ error: "not found" }));
56
+ res.end();
57
+ return;
58
+ }
59
+ const allRoutes = {
60
+ gql: {
61
+ handler: async (req2, res2, _opts) => {
62
+ if (req2.method !== "POST") {
63
+ res2.statusCode = 405;
64
+ res2.write(
65
+ JSON.stringify({
66
+ error: "Method not allowed. Only POST requests are supported by /gql"
67
+ })
68
+ );
69
+ res2.end();
70
+ return;
71
+ }
72
+ if (!req2.body) {
73
+ console.error(
74
+ "Please make sure that you have a body parser set up for your server and req.body is defined"
75
+ );
76
+ res2.statusCode = 400;
77
+ res2.write(JSON.stringify({ error: "no body" }));
78
+ res2.end();
79
+ return;
80
+ }
81
+ if (!req2.body.query) {
82
+ res2.statusCode = 400;
83
+ res2.write(JSON.stringify({ error: "no query" }));
84
+ res2.end();
85
+ return;
86
+ }
87
+ if (!req2.body.variables) {
88
+ res2.statusCode = 400;
89
+ res2.write(JSON.stringify({ error: "no variables" }));
90
+ res2.end();
91
+ return;
92
+ }
93
+ const { query, variables } = req2.body;
94
+ const result = await databaseClient.request({
95
+ query,
96
+ variables,
97
+ user: req2?.session?.user
98
+ });
99
+ res2.statusCode = 200;
100
+ res2.write(JSON.stringify(result));
101
+ res2.end();
102
+ return;
103
+ },
104
+ secure: true
105
+ },
106
+ ...extraRoutes || {}
107
+ };
108
+ const [action] = routes;
109
+ const currentRoute = allRoutes[action];
110
+ if (!currentRoute) {
111
+ res.statusCode = 404;
112
+ const errorMessage = `Error: ${action} not found in routes`;
113
+ console.error(errorMessage);
114
+ res.write(JSON.stringify({ error: errorMessage }));
115
+ res.end();
116
+ return;
117
+ }
118
+ const { handler, secure } = currentRoute;
119
+ if (secure) {
120
+ const isAuth = await isAuthorized(req, res);
121
+ if (isAuth.isAuthorized === false) {
122
+ res.statusCode = isAuth.errorCode;
123
+ res.write(JSON.stringify({ error: isAuth.errorMessage || "not found" }));
124
+ res.end();
125
+ return;
126
+ }
127
+ }
128
+ return handler(req, res, opts);
129
+ };
130
+ return tinaBackendHandler;
131
+ }
10
132
  export {
11
133
  AuditFileSystemBridge,
12
134
  FilesystemBridge,
13
135
  IsomorphicBridge,
136
+ LocalBackendAuthProvider,
14
137
  TinaLevelClient,
138
+ TinaNodeBackend,
15
139
  createDatabase,
140
+ createLocalDatabase,
16
141
  resolve
17
142
  };
package/package.json CHANGED
@@ -1,16 +1,24 @@
1
1
  {
2
2
  "name": "@tinacms/datalayer",
3
- "version": "1.2.27",
3
+ "version": "1.2.29",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
- "typings": "dist/index.d.ts",
6
+ "typings": "dist/index",
7
7
  "files": [
8
8
  "package.json",
9
9
  "dist"
10
10
  ],
11
11
  "exports": {
12
- "import": "./dist/index.mjs",
13
- "require": "./dist/index.js"
12
+ ".": {
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.js",
15
+ "types": "./dist/index.d.ts"
16
+ },
17
+ "./dist/*": {
18
+ "import": "./dist/*.mjs",
19
+ "require": "./dist/*.js",
20
+ "types": "./dist/*.d.ts"
21
+ }
14
22
  },
15
23
  "license": "SEE LICENSE IN LICENSE",
16
24
  "buildConfig": {
@@ -23,7 +31,7 @@
23
31
  ]
24
32
  },
25
33
  "dependencies": {
26
- "@tinacms/graphql": "1.4.27"
34
+ "@tinacms/graphql": "1.4.29"
27
35
  },
28
36
  "publishConfig": {
29
37
  "registry": "https://registry.npmjs.org"
@@ -33,7 +41,7 @@
33
41
  "directory": "packages/@tinacms/datalayer"
34
42
  },
35
43
  "devDependencies": {
36
- "@tinacms/scripts": "1.1.2",
44
+ "@tinacms/scripts": "1.1.3",
37
45
  "@types/fs-extra": "^9.0.2",
38
46
  "@types/jest": "^27.4.1",
39
47
  "@types/js-yaml": "^3.12.5",