next-tinacms-dos 0.0.0-42987e4-20251020234826 → 0.0.0-4416a28-20251109220109
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/handlers.js +58 -28
- package/dist/index.js +125 -122
- package/dist/index.mjs +130 -0
- package/package.json +4 -4
package/dist/handlers.js
CHANGED
|
@@ -1,21 +1,50 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
1
29
|
// src/handlers.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
30
|
+
var handlers_exports = {};
|
|
31
|
+
__export(handlers_exports, {
|
|
32
|
+
createMediaHandler: () => createMediaHandler,
|
|
33
|
+
mediaHandlerConfig: () => mediaHandlerConfig
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(handlers_exports);
|
|
36
|
+
var import_client_s3 = require("@aws-sdk/client-s3");
|
|
37
|
+
var import_path = __toESM(require("path"));
|
|
38
|
+
var import_fs = __toESM(require("fs"));
|
|
39
|
+
var import_multer = __toESM(require("multer"));
|
|
40
|
+
var import_util = require("util");
|
|
12
41
|
var mediaHandlerConfig = {
|
|
13
42
|
api: {
|
|
14
43
|
bodyParser: false
|
|
15
44
|
}
|
|
16
45
|
};
|
|
17
46
|
var createMediaHandler = (config, options) => {
|
|
18
|
-
const client = new S3Client(config.config);
|
|
47
|
+
const client = new import_client_s3.S3Client(config.config);
|
|
19
48
|
const bucket = config.bucket;
|
|
20
49
|
let mediaRoot = config.mediaRoot || "";
|
|
21
50
|
if (mediaRoot) {
|
|
@@ -47,9 +76,9 @@ var createMediaHandler = (config, options) => {
|
|
|
47
76
|
};
|
|
48
77
|
};
|
|
49
78
|
async function uploadMedia(req, res, client, bucket, mediaRoot, cdnUrl) {
|
|
50
|
-
const upload = promisify(
|
|
51
|
-
|
|
52
|
-
storage:
|
|
79
|
+
const upload = (0, import_util.promisify)(
|
|
80
|
+
(0, import_multer.default)({
|
|
81
|
+
storage: import_multer.default.diskStorage({
|
|
53
82
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
54
83
|
// @ts-ignore
|
|
55
84
|
directory: (req2, file, cb) => {
|
|
@@ -67,16 +96,16 @@ async function uploadMedia(req, res, client, bucket, mediaRoot, cdnUrl) {
|
|
|
67
96
|
if (prefix) prefix = prefix + "/";
|
|
68
97
|
const filePath = req.file.path;
|
|
69
98
|
const fileType = req.file?.mimetype;
|
|
70
|
-
const blob =
|
|
71
|
-
const filename =
|
|
99
|
+
const blob = import_fs.default.readFileSync(filePath);
|
|
100
|
+
const filename = import_path.default.basename(filePath);
|
|
72
101
|
const params = {
|
|
73
102
|
Bucket: bucket,
|
|
74
|
-
Key: mediaRoot ?
|
|
103
|
+
Key: mediaRoot ? import_path.default.join(mediaRoot, prefix + filename) : prefix + filename,
|
|
75
104
|
Body: blob,
|
|
76
105
|
ACL: "public-read",
|
|
77
106
|
ContentType: fileType || "application/octet-stream"
|
|
78
107
|
};
|
|
79
|
-
const command = new PutObjectCommand(params);
|
|
108
|
+
const command = new import_client_s3.PutObjectCommand(params);
|
|
80
109
|
try {
|
|
81
110
|
const src = cdnUrl + prefix + filename;
|
|
82
111
|
await client.send(command);
|
|
@@ -90,7 +119,7 @@ async function uploadMedia(req, res, client, bucket, mediaRoot, cdnUrl) {
|
|
|
90
119
|
"400x400": src,
|
|
91
120
|
"1000x1000": src
|
|
92
121
|
},
|
|
93
|
-
src: cdnUrl + (mediaRoot ?
|
|
122
|
+
src: cdnUrl + (mediaRoot ? import_path.default.join(mediaRoot, prefix + filename) : prefix + filename)
|
|
94
123
|
});
|
|
95
124
|
} catch (e) {
|
|
96
125
|
console.error("Error uploading media");
|
|
@@ -126,11 +155,11 @@ async function listMedia(req, res, client, bucket, mediaRoot, cdnUrl) {
|
|
|
126
155
|
const params = {
|
|
127
156
|
Bucket: bucket,
|
|
128
157
|
Delimiter: "/",
|
|
129
|
-
Prefix: mediaRoot ?
|
|
158
|
+
Prefix: mediaRoot ? import_path.default.join(mediaRoot, prefix) : prefix,
|
|
130
159
|
Marker: offset?.toString(),
|
|
131
160
|
MaxKeys: directory && !offset ? +limit + 1 : +limit
|
|
132
161
|
};
|
|
133
|
-
const response = await client.send(new ListObjectsCommand(params));
|
|
162
|
+
const response = await client.send(new import_client_s3.ListObjectsCommand(params));
|
|
134
163
|
const items = [];
|
|
135
164
|
response.CommonPrefixes?.forEach(({ Prefix }) => {
|
|
136
165
|
const strippedPrefix = stripMediaRoot(mediaRoot, Prefix);
|
|
@@ -140,8 +169,8 @@ async function listMedia(req, res, client, bucket, mediaRoot, cdnUrl) {
|
|
|
140
169
|
items.push({
|
|
141
170
|
id: Prefix,
|
|
142
171
|
type: "dir",
|
|
143
|
-
filename:
|
|
144
|
-
directory:
|
|
172
|
+
filename: import_path.default.basename(strippedPrefix),
|
|
173
|
+
directory: import_path.default.dirname(strippedPrefix)
|
|
145
174
|
});
|
|
146
175
|
});
|
|
147
176
|
items.push(
|
|
@@ -180,7 +209,7 @@ async function deleteAsset(req, res, client, bucket) {
|
|
|
180
209
|
Key: objectKey
|
|
181
210
|
};
|
|
182
211
|
try {
|
|
183
|
-
const data = await client.send(new DeleteObjectCommand(params));
|
|
212
|
+
const data = await client.send(new import_client_s3.DeleteObjectCommand(params));
|
|
184
213
|
res.json(data);
|
|
185
214
|
} catch (err) {
|
|
186
215
|
console.error("Error deleting media");
|
|
@@ -193,8 +222,8 @@ async function deleteAsset(req, res, client, bucket) {
|
|
|
193
222
|
function getDOSToTinaFunc(cdnUrl, mediaRoot) {
|
|
194
223
|
return function dosToTina(file) {
|
|
195
224
|
const strippedKey = stripMediaRoot(mediaRoot, file.Key);
|
|
196
|
-
const filename =
|
|
197
|
-
const directory =
|
|
225
|
+
const filename = import_path.default.basename(strippedKey);
|
|
226
|
+
const directory = import_path.default.dirname(strippedKey) + "/";
|
|
198
227
|
const src = cdnUrl + file.Key;
|
|
199
228
|
return {
|
|
200
229
|
id: file.Key,
|
|
@@ -210,7 +239,8 @@ function getDOSToTinaFunc(cdnUrl, mediaRoot) {
|
|
|
210
239
|
};
|
|
211
240
|
};
|
|
212
241
|
}
|
|
213
|
-
export
|
|
242
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
243
|
+
0 && (module.exports = {
|
|
214
244
|
createMediaHandler,
|
|
215
245
|
mediaHandlerConfig
|
|
216
|
-
};
|
|
246
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -1,130 +1,133 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
message: "Something went wrong fetching your media from Digital Ocean Space.",
|
|
13
|
-
docsLink: "https://tina.io/docs/r/digital-ocean-spaces"
|
|
14
|
-
});
|
|
15
|
-
const E_UNAUTHORIZED = new MediaListError({
|
|
16
|
-
title: "Unauthorized",
|
|
17
|
-
message: "You don't have access to this resource.",
|
|
18
|
-
docsLink: "https://tina.io/docs/r/digital-ocean-spaces"
|
|
19
|
-
});
|
|
20
|
-
const E_CONFIG = new MediaListError({
|
|
21
|
-
title: "Missing Credentials",
|
|
22
|
-
message: "Unable to connect to Digital Ocean Space because one or more environment variables are missing.",
|
|
23
|
-
docsLink: "https://tina.io/docs/r/digital-ocean-spaces/"
|
|
24
|
-
});
|
|
25
|
-
const E_KEY_FAIL = new MediaListError({
|
|
26
|
-
title: "Bad Credentials",
|
|
27
|
-
message: "Unable to connect to Digital Ocean Space because one or more environment variables are misconfigured.",
|
|
28
|
-
docsLink: "https://tina.io/docs/r/digital-ocean-spaces/"
|
|
29
|
-
});
|
|
30
|
-
const E_BAD_ROUTE = new MediaListError({
|
|
31
|
-
title: "Bad Route",
|
|
32
|
-
message: "The Digital Ocean Space API route is missing or misconfigured.",
|
|
33
|
-
docsLink: "https://tina.io/docs/r/digital-ocean-spaces/#set-up-api-routes"
|
|
34
|
-
});
|
|
35
|
-
const interpretErrorMessage = (message) => {
|
|
36
|
-
switch (message) {
|
|
37
|
-
case "Must supply cloud_name":
|
|
38
|
-
case "Must supply api_key":
|
|
39
|
-
case "Must supply api_secret":
|
|
40
|
-
return E_CONFIG;
|
|
41
|
-
case "unknown api_key":
|
|
42
|
-
return E_KEY_FAIL;
|
|
43
|
-
default:
|
|
44
|
-
return E_DEFAULT;
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
class DOSMediaStore {
|
|
48
|
-
constructor() {
|
|
49
|
-
this.fetchFunction = (input, init) => {
|
|
50
|
-
return fetch(input, init);
|
|
51
|
-
};
|
|
52
|
-
this.accept = DEFAULT_MEDIA_UPLOAD_TYPES;
|
|
53
|
-
this.parse = (img) => {
|
|
54
|
-
return img.src;
|
|
55
|
-
};
|
|
1
|
+
(function(global, factory) {
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("tinacms")) : typeof define === "function" && define.amd ? define(["exports", "tinacms"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["next-tinacms-dos"] = {}, global.NOOP));
|
|
3
|
+
})(this, function(exports2, tinacms) {
|
|
4
|
+
"use strict";
|
|
5
|
+
class MediaListError extends Error {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
super(config.message);
|
|
8
|
+
this.ERR_TYPE = "MediaListError";
|
|
9
|
+
this.title = config.title;
|
|
10
|
+
this.docsLink = config.docsLink;
|
|
11
|
+
}
|
|
56
12
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
13
|
+
const E_DEFAULT = new MediaListError({
|
|
14
|
+
title: "An Error Occurred",
|
|
15
|
+
message: "Something went wrong fetching your media from Digital Ocean Space.",
|
|
16
|
+
docsLink: "https://tina.io/docs/r/digital-ocean-spaces"
|
|
17
|
+
});
|
|
18
|
+
const E_UNAUTHORIZED = new MediaListError({
|
|
19
|
+
title: "Unauthorized",
|
|
20
|
+
message: "You don't have access to this resource.",
|
|
21
|
+
docsLink: "https://tina.io/docs/r/digital-ocean-spaces"
|
|
22
|
+
});
|
|
23
|
+
const E_CONFIG = new MediaListError({
|
|
24
|
+
title: "Missing Credentials",
|
|
25
|
+
message: "Unable to connect to Digital Ocean Space because one or more environment variables are missing.",
|
|
26
|
+
docsLink: "https://tina.io/docs/r/digital-ocean-spaces/"
|
|
27
|
+
});
|
|
28
|
+
const E_KEY_FAIL = new MediaListError({
|
|
29
|
+
title: "Bad Credentials",
|
|
30
|
+
message: "Unable to connect to Digital Ocean Space because one or more environment variables are misconfigured.",
|
|
31
|
+
docsLink: "https://tina.io/docs/r/digital-ocean-spaces/"
|
|
32
|
+
});
|
|
33
|
+
const E_BAD_ROUTE = new MediaListError({
|
|
34
|
+
title: "Bad Route",
|
|
35
|
+
message: "The Digital Ocean Space API route is missing or misconfigured.",
|
|
36
|
+
docsLink: "https://tina.io/docs/r/digital-ocean-spaces/#set-up-api-routes"
|
|
37
|
+
});
|
|
38
|
+
const interpretErrorMessage = (message) => {
|
|
39
|
+
switch (message) {
|
|
40
|
+
case "Must supply cloud_name":
|
|
41
|
+
case "Must supply api_key":
|
|
42
|
+
case "Must supply api_secret":
|
|
43
|
+
return E_CONFIG;
|
|
44
|
+
case "unknown api_key":
|
|
45
|
+
return E_KEY_FAIL;
|
|
46
|
+
default:
|
|
47
|
+
return E_DEFAULT;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
class DOSMediaStore {
|
|
51
|
+
constructor() {
|
|
52
|
+
this.fetchFunction = (input, init) => {
|
|
53
|
+
return fetch(input, init);
|
|
54
|
+
};
|
|
55
|
+
this.accept = tinacms.DEFAULT_MEDIA_UPLOAD_TYPES;
|
|
56
|
+
this.parse = (img) => {
|
|
57
|
+
return img.src;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
async persist(media) {
|
|
61
|
+
const newFiles = [];
|
|
62
|
+
for (const item of media) {
|
|
63
|
+
const { file, directory } = item;
|
|
64
|
+
const formData = new FormData();
|
|
65
|
+
formData.append("file", file);
|
|
66
|
+
formData.append("directory", directory);
|
|
67
|
+
formData.append("filename", file.name);
|
|
68
|
+
const res = await this.fetchFunction(`/api/dos/media`, {
|
|
69
|
+
method: "POST",
|
|
70
|
+
body: formData
|
|
71
|
+
});
|
|
72
|
+
if (res.status != 200) {
|
|
73
|
+
const responseData = await res.json();
|
|
74
|
+
throw new Error(responseData.message);
|
|
75
|
+
}
|
|
76
|
+
const fileRes = await res.json();
|
|
77
|
+
await new Promise((resolve) => {
|
|
78
|
+
setTimeout(resolve, 2e3);
|
|
79
|
+
});
|
|
80
|
+
newFiles.push(fileRes);
|
|
72
81
|
}
|
|
73
|
-
|
|
74
|
-
await new Promise((resolve) => {
|
|
75
|
-
setTimeout(resolve, 2e3);
|
|
76
|
-
});
|
|
77
|
-
newFiles.push(fileRes);
|
|
82
|
+
return newFiles;
|
|
78
83
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
method: "DELETE"
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
async list(options) {
|
|
87
|
-
const query = this.buildQuery(options);
|
|
88
|
-
const response = await this.fetchFunction("/api/dos/media" + query);
|
|
89
|
-
if (response.status == 401) {
|
|
90
|
-
throw E_UNAUTHORIZED;
|
|
84
|
+
async delete(media) {
|
|
85
|
+
await this.fetchFunction(`/api/dos/media/${encodeURIComponent(media.id)}`, {
|
|
86
|
+
method: "DELETE"
|
|
87
|
+
});
|
|
91
88
|
}
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
async list(options) {
|
|
90
|
+
const query = this.buildQuery(options);
|
|
91
|
+
const response = await this.fetchFunction("/api/dos/media" + query);
|
|
92
|
+
if (response.status == 401) {
|
|
93
|
+
throw E_UNAUTHORIZED;
|
|
94
|
+
}
|
|
95
|
+
if (response.status == 404) {
|
|
96
|
+
throw E_BAD_ROUTE;
|
|
97
|
+
}
|
|
98
|
+
if (response.status >= 500) {
|
|
99
|
+
const { e } = await response.json();
|
|
100
|
+
const error = interpretErrorMessage(e);
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
const { items, offset } = await response.json();
|
|
104
|
+
return {
|
|
105
|
+
items: items.map((item) => item),
|
|
106
|
+
nextOffset: offset
|
|
107
|
+
};
|
|
94
108
|
}
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
throw error;
|
|
109
|
+
buildQuery(options) {
|
|
110
|
+
const params = Object.keys(options).filter((key) => options[key] !== "" && options[key] !== void 0).map((key) => `${key}=${options[key]}`).join("&");
|
|
111
|
+
return `?${params}`;
|
|
99
112
|
}
|
|
100
|
-
const { items, offset } = await response.json();
|
|
101
|
-
return {
|
|
102
|
-
items: items.map((item) => item),
|
|
103
|
-
nextOffset: offset
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
buildQuery(options) {
|
|
107
|
-
const params = Object.keys(options).filter((key) => options[key] !== "" && options[key] !== void 0).map((key) => `${key}=${options[key]}`).join("&");
|
|
108
|
-
return `?${params}`;
|
|
109
113
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
}
|
|
114
|
+
class TinaCloudDOSMediaStore extends DOSMediaStore {
|
|
115
|
+
constructor(client) {
|
|
116
|
+
super();
|
|
117
|
+
this.client = client;
|
|
118
|
+
this.fetchFunction = async (input, init) => {
|
|
119
|
+
try {
|
|
120
|
+
const url = input.toString();
|
|
121
|
+
const query = `${url.includes("?") ? "&" : "?"}clientID=${client.clientId}`;
|
|
122
|
+
const res = client.authProvider.fetchWithToken(url + query, init);
|
|
123
|
+
return res;
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error(error);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
125
129
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
};
|
|
130
|
+
exports2.DOSMediaStore = DOSMediaStore;
|
|
131
|
+
exports2.TinaCloudDOSMediaStore = TinaCloudDOSMediaStore;
|
|
132
|
+
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
|
133
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { DEFAULT_MEDIA_UPLOAD_TYPES } from "tinacms";
|
|
2
|
+
class MediaListError extends Error {
|
|
3
|
+
constructor(config) {
|
|
4
|
+
super(config.message);
|
|
5
|
+
this.ERR_TYPE = "MediaListError";
|
|
6
|
+
this.title = config.title;
|
|
7
|
+
this.docsLink = config.docsLink;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
const E_DEFAULT = new MediaListError({
|
|
11
|
+
title: "An Error Occurred",
|
|
12
|
+
message: "Something went wrong fetching your media from Digital Ocean Space.",
|
|
13
|
+
docsLink: "https://tina.io/docs/r/digital-ocean-spaces"
|
|
14
|
+
});
|
|
15
|
+
const E_UNAUTHORIZED = new MediaListError({
|
|
16
|
+
title: "Unauthorized",
|
|
17
|
+
message: "You don't have access to this resource.",
|
|
18
|
+
docsLink: "https://tina.io/docs/r/digital-ocean-spaces"
|
|
19
|
+
});
|
|
20
|
+
const E_CONFIG = new MediaListError({
|
|
21
|
+
title: "Missing Credentials",
|
|
22
|
+
message: "Unable to connect to Digital Ocean Space because one or more environment variables are missing.",
|
|
23
|
+
docsLink: "https://tina.io/docs/r/digital-ocean-spaces/"
|
|
24
|
+
});
|
|
25
|
+
const E_KEY_FAIL = new MediaListError({
|
|
26
|
+
title: "Bad Credentials",
|
|
27
|
+
message: "Unable to connect to Digital Ocean Space because one or more environment variables are misconfigured.",
|
|
28
|
+
docsLink: "https://tina.io/docs/r/digital-ocean-spaces/"
|
|
29
|
+
});
|
|
30
|
+
const E_BAD_ROUTE = new MediaListError({
|
|
31
|
+
title: "Bad Route",
|
|
32
|
+
message: "The Digital Ocean Space API route is missing or misconfigured.",
|
|
33
|
+
docsLink: "https://tina.io/docs/r/digital-ocean-spaces/#set-up-api-routes"
|
|
34
|
+
});
|
|
35
|
+
const interpretErrorMessage = (message) => {
|
|
36
|
+
switch (message) {
|
|
37
|
+
case "Must supply cloud_name":
|
|
38
|
+
case "Must supply api_key":
|
|
39
|
+
case "Must supply api_secret":
|
|
40
|
+
return E_CONFIG;
|
|
41
|
+
case "unknown api_key":
|
|
42
|
+
return E_KEY_FAIL;
|
|
43
|
+
default:
|
|
44
|
+
return E_DEFAULT;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
class DOSMediaStore {
|
|
48
|
+
constructor() {
|
|
49
|
+
this.fetchFunction = (input, init) => {
|
|
50
|
+
return fetch(input, init);
|
|
51
|
+
};
|
|
52
|
+
this.accept = DEFAULT_MEDIA_UPLOAD_TYPES;
|
|
53
|
+
this.parse = (img) => {
|
|
54
|
+
return img.src;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async persist(media) {
|
|
58
|
+
const newFiles = [];
|
|
59
|
+
for (const item of media) {
|
|
60
|
+
const { file, directory } = item;
|
|
61
|
+
const formData = new FormData();
|
|
62
|
+
formData.append("file", file);
|
|
63
|
+
formData.append("directory", directory);
|
|
64
|
+
formData.append("filename", file.name);
|
|
65
|
+
const res = await this.fetchFunction(`/api/dos/media`, {
|
|
66
|
+
method: "POST",
|
|
67
|
+
body: formData
|
|
68
|
+
});
|
|
69
|
+
if (res.status != 200) {
|
|
70
|
+
const responseData = await res.json();
|
|
71
|
+
throw new Error(responseData.message);
|
|
72
|
+
}
|
|
73
|
+
const fileRes = await res.json();
|
|
74
|
+
await new Promise((resolve) => {
|
|
75
|
+
setTimeout(resolve, 2e3);
|
|
76
|
+
});
|
|
77
|
+
newFiles.push(fileRes);
|
|
78
|
+
}
|
|
79
|
+
return newFiles;
|
|
80
|
+
}
|
|
81
|
+
async delete(media) {
|
|
82
|
+
await this.fetchFunction(`/api/dos/media/${encodeURIComponent(media.id)}`, {
|
|
83
|
+
method: "DELETE"
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
async list(options) {
|
|
87
|
+
const query = this.buildQuery(options);
|
|
88
|
+
const response = await this.fetchFunction("/api/dos/media" + query);
|
|
89
|
+
if (response.status == 401) {
|
|
90
|
+
throw E_UNAUTHORIZED;
|
|
91
|
+
}
|
|
92
|
+
if (response.status == 404) {
|
|
93
|
+
throw E_BAD_ROUTE;
|
|
94
|
+
}
|
|
95
|
+
if (response.status >= 500) {
|
|
96
|
+
const { e } = await response.json();
|
|
97
|
+
const error = interpretErrorMessage(e);
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
const { items, offset } = await response.json();
|
|
101
|
+
return {
|
|
102
|
+
items: items.map((item) => item),
|
|
103
|
+
nextOffset: offset
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
buildQuery(options) {
|
|
107
|
+
const params = Object.keys(options).filter((key) => options[key] !== "" && options[key] !== void 0).map((key) => `${key}=${options[key]}`).join("&");
|
|
108
|
+
return `?${params}`;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
class TinaCloudDOSMediaStore extends DOSMediaStore {
|
|
112
|
+
constructor(client) {
|
|
113
|
+
super();
|
|
114
|
+
this.client = client;
|
|
115
|
+
this.fetchFunction = async (input, init) => {
|
|
116
|
+
try {
|
|
117
|
+
const url = input.toString();
|
|
118
|
+
const query = `${url.includes("?") ? "&" : "?"}clientID=${client.clientId}`;
|
|
119
|
+
const res = client.authProvider.fetchWithToken(url + query, init);
|
|
120
|
+
return res;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error(error);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export {
|
|
128
|
+
DOSMediaStore,
|
|
129
|
+
TinaCloudDOSMediaStore
|
|
130
|
+
};
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-tinacms-dos",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-4416a28-20251109220109",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
|
-
"module": "
|
|
5
|
+
"module": "dist/index.mjs",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist"
|
|
8
8
|
],
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
]
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
|
-
"tinacms": "0.0.0-
|
|
21
|
+
"tinacms": "0.0.0-4416a28-20251109220109"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/crypto-js": "^3.1.47",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"react-dom": "^18.3.1",
|
|
30
30
|
"typescript": "^5.7.3",
|
|
31
31
|
"@tinacms/scripts": "1.4.0",
|
|
32
|
-
"tinacms": "0.0.0-
|
|
32
|
+
"tinacms": "0.0.0-4416a28-20251109220109"
|
|
33
33
|
},
|
|
34
34
|
"publishConfig": {
|
|
35
35
|
"registry": "https://registry.npmjs.org"
|