next-tinacms-dos 1.1.1 → 1.2.0
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 +3 -2
- package/dist/dos-media-store.d.ts +0 -1
- package/dist/handlers.d.ts +1 -0
- package/dist/handlers.js +59 -24
- package/dist/index.es.js +54878 -21
- package/dist/index.js +54880 -23
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -6,12 +6,12 @@ Manage **Digital Ocean Space media assets** in TinaCMS.
|
|
|
6
6
|
|
|
7
7
|
### With Yarn
|
|
8
8
|
```bash
|
|
9
|
-
yarn add next-tinacms-dos
|
|
9
|
+
yarn add next-tinacms-dos @tinacms/auth
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
### With NPM
|
|
13
13
|
```bash
|
|
14
|
-
npm install next-tinacms-dos
|
|
14
|
+
npm install next-tinacms-dos @tinacms/auth
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Connect with Digital Ocean Space
|
|
@@ -116,6 +116,7 @@ export default createMediaHandler({
|
|
|
116
116
|
region: 'us-east-1',
|
|
117
117
|
},
|
|
118
118
|
bucket: process.env.NEXT_PUBLIC_SPACE_NAME || '',
|
|
119
|
+
mediaRoot: 'images',
|
|
119
120
|
authorized: async (req, _res) => {
|
|
120
121
|
if (process.env.NEXT_PUBLIC_USE_LOCAL_CLIENT === "1") {
|
|
121
122
|
return true;
|
|
@@ -8,7 +8,6 @@ export declare class DOSMediaStore implements MediaStore {
|
|
|
8
8
|
persist(media: MediaUploadOptions[]): Promise<Media[]>;
|
|
9
9
|
delete(media: Media): Promise<void>;
|
|
10
10
|
list(options: MediaListOptions): Promise<MediaList>;
|
|
11
|
-
previewSrc: (publicId: string | Media) => string;
|
|
12
11
|
parse: (img: any) => any;
|
|
13
12
|
private buildQuery;
|
|
14
13
|
}
|
package/dist/handlers.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { NextApiRequest, NextApiResponse } from 'next';
|
|
|
6
6
|
export interface DOSConfig {
|
|
7
7
|
config: S3ClientConfig;
|
|
8
8
|
bucket: string;
|
|
9
|
+
mediaRoot?: string;
|
|
9
10
|
authorized: (_req: NextApiRequest, _res: NextApiResponse) => Promise<boolean>;
|
|
10
11
|
}
|
|
11
12
|
export interface DOSOptions {
|
package/dist/handlers.js
CHANGED
|
@@ -40,6 +40,15 @@ var mediaHandlerConfig = {
|
|
|
40
40
|
var createMediaHandler = (config, options) => {
|
|
41
41
|
const client = new import_client_s3.S3Client(config.config);
|
|
42
42
|
const bucket = config.bucket;
|
|
43
|
+
let mediaRoot = config.mediaRoot || "";
|
|
44
|
+
if (mediaRoot) {
|
|
45
|
+
if (!mediaRoot.endsWith("/")) {
|
|
46
|
+
mediaRoot = mediaRoot + "/";
|
|
47
|
+
}
|
|
48
|
+
if (mediaRoot.startsWith("/")) {
|
|
49
|
+
mediaRoot = mediaRoot.substr(1);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
43
52
|
let cdnUrl = (options == null ? void 0 : options.cdnUrl) || config.config.endpoint.toString().replace(/http(s|):\/\//i, `https://${bucket}.`);
|
|
44
53
|
cdnUrl = cdnUrl + (cdnUrl.endsWith("/") ? "" : "/");
|
|
45
54
|
return async (req, res) => {
|
|
@@ -50,9 +59,9 @@ var createMediaHandler = (config, options) => {
|
|
|
50
59
|
}
|
|
51
60
|
switch (req.method) {
|
|
52
61
|
case "GET":
|
|
53
|
-
return listMedia(req, res, client, bucket, cdnUrl);
|
|
62
|
+
return listMedia(req, res, client, bucket, mediaRoot, cdnUrl);
|
|
54
63
|
case "POST":
|
|
55
|
-
return uploadMedia(req, res, client, bucket, cdnUrl);
|
|
64
|
+
return uploadMedia(req, res, client, bucket, mediaRoot, cdnUrl);
|
|
56
65
|
case "DELETE":
|
|
57
66
|
return deleteAsset(req, res, client, bucket);
|
|
58
67
|
default:
|
|
@@ -60,7 +69,7 @@ var createMediaHandler = (config, options) => {
|
|
|
60
69
|
}
|
|
61
70
|
};
|
|
62
71
|
};
|
|
63
|
-
async function uploadMedia(req, res, client, bucket, cdnUrl) {
|
|
72
|
+
async function uploadMedia(req, res, client, bucket, mediaRoot, cdnUrl) {
|
|
64
73
|
const upload = (0, import_util.promisify)((0, import_multer.default)({
|
|
65
74
|
storage: import_multer.default.diskStorage({
|
|
66
75
|
directory: (req2, file, cb) => {
|
|
@@ -81,26 +90,43 @@ async function uploadMedia(req, res, client, bucket, cdnUrl) {
|
|
|
81
90
|
const filename = import_path.default.basename(filePath);
|
|
82
91
|
const params = {
|
|
83
92
|
Bucket: bucket,
|
|
84
|
-
Key: prefix + filename,
|
|
93
|
+
Key: mediaRoot ? import_path.default.join(mediaRoot, prefix + filename) : prefix + filename,
|
|
85
94
|
Body: blob,
|
|
86
95
|
ACL: "public-read"
|
|
87
96
|
};
|
|
88
97
|
const command = new import_client_s3.PutObjectCommand(params);
|
|
89
98
|
try {
|
|
99
|
+
const src = cdnUrl + prefix + filename;
|
|
90
100
|
await client.send(command);
|
|
91
101
|
res.json({
|
|
92
102
|
type: "file",
|
|
93
103
|
id: prefix + filename,
|
|
94
104
|
filename,
|
|
95
105
|
directory: prefix,
|
|
96
|
-
|
|
97
|
-
src: cdnUrl + prefix + filename
|
|
106
|
+
thumbnail: src,
|
|
107
|
+
src: cdnUrl + (mediaRoot ? import_path.default.join(mediaRoot, prefix + filename) : prefix + filename)
|
|
98
108
|
});
|
|
99
109
|
} catch (e) {
|
|
100
110
|
res.status(500).send(findErrorMessage(e));
|
|
101
111
|
}
|
|
102
112
|
}
|
|
103
|
-
|
|
113
|
+
function stripMediaRoot(mediaRoot, key) {
|
|
114
|
+
if (!mediaRoot) {
|
|
115
|
+
return key;
|
|
116
|
+
}
|
|
117
|
+
const mediaRootParts = mediaRoot.split("/").filter((part) => part);
|
|
118
|
+
if (!mediaRootParts || !mediaRootParts[0]) {
|
|
119
|
+
return key;
|
|
120
|
+
}
|
|
121
|
+
const keyParts = key.split("/").filter((part) => part);
|
|
122
|
+
for (let i = 0; i < mediaRootParts.length; i++) {
|
|
123
|
+
if (keyParts[0] === mediaRootParts[i]) {
|
|
124
|
+
keyParts.shift();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return keyParts.join("/");
|
|
128
|
+
}
|
|
129
|
+
async function listMedia(req, res, client, bucket, mediaRoot, cdnUrl) {
|
|
104
130
|
var _a;
|
|
105
131
|
try {
|
|
106
132
|
const {
|
|
@@ -114,20 +140,28 @@ async function listMedia(req, res, client, bucket, cdnUrl) {
|
|
|
114
140
|
const params = {
|
|
115
141
|
Bucket: bucket,
|
|
116
142
|
Delimiter: "/",
|
|
117
|
-
Prefix: prefix,
|
|
143
|
+
Prefix: mediaRoot ? import_path.default.join(mediaRoot, prefix) : prefix,
|
|
118
144
|
Marker: offset == null ? void 0 : offset.toString(),
|
|
119
145
|
MaxKeys: directory && !offset ? +limit + 1 : +limit
|
|
120
146
|
};
|
|
121
|
-
const
|
|
122
|
-
const response = await client.send(command);
|
|
147
|
+
const response = await client.send(new import_client_s3.ListObjectsCommand(params));
|
|
123
148
|
const items = [];
|
|
124
|
-
(_a = response.CommonPrefixes) == null ? void 0 : _a.forEach(({ Prefix }) =>
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
149
|
+
(_a = response.CommonPrefixes) == null ? void 0 : _a.forEach(({ Prefix }) => {
|
|
150
|
+
const strippedPrefix = stripMediaRoot(mediaRoot, Prefix);
|
|
151
|
+
if (!strippedPrefix) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
items.push({
|
|
155
|
+
id: Prefix,
|
|
156
|
+
type: "dir",
|
|
157
|
+
filename: import_path.default.basename(strippedPrefix),
|
|
158
|
+
directory: import_path.default.dirname(strippedPrefix)
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
items.push(...(response.Contents || []).filter((file) => {
|
|
162
|
+
const strippedKey = stripMediaRoot(mediaRoot, file.Key);
|
|
163
|
+
return strippedKey !== prefix;
|
|
164
|
+
}).map(getDOSToTinaFunc(cdnUrl, mediaRoot)));
|
|
131
165
|
res.json({
|
|
132
166
|
items,
|
|
133
167
|
offset: response.NextMarker
|
|
@@ -154,9 +188,8 @@ async function deleteAsset(req, res, client, bucket) {
|
|
|
154
188
|
Bucket: bucket,
|
|
155
189
|
Key: objectKey
|
|
156
190
|
};
|
|
157
|
-
const command = new import_client_s3.DeleteObjectCommand(params);
|
|
158
191
|
try {
|
|
159
|
-
const data = await client.send(
|
|
192
|
+
const data = await client.send(new import_client_s3.DeleteObjectCommand(params));
|
|
160
193
|
res.json(data);
|
|
161
194
|
} catch (err) {
|
|
162
195
|
res.status(500).json({
|
|
@@ -164,16 +197,18 @@ async function deleteAsset(req, res, client, bucket) {
|
|
|
164
197
|
});
|
|
165
198
|
}
|
|
166
199
|
}
|
|
167
|
-
function getDOSToTinaFunc(cdnUrl) {
|
|
200
|
+
function getDOSToTinaFunc(cdnUrl, mediaRoot) {
|
|
168
201
|
return function dosToTina(file) {
|
|
169
|
-
const
|
|
170
|
-
const
|
|
202
|
+
const strippedKey = stripMediaRoot(mediaRoot, file.Key);
|
|
203
|
+
const filename = import_path.default.basename(strippedKey);
|
|
204
|
+
const directory = import_path.default.dirname(strippedKey) + "/";
|
|
205
|
+
const src = cdnUrl + file.Key;
|
|
171
206
|
return {
|
|
172
207
|
id: file.Key,
|
|
173
208
|
filename,
|
|
174
209
|
directory,
|
|
175
|
-
src
|
|
176
|
-
|
|
210
|
+
src,
|
|
211
|
+
thumbnail: src,
|
|
177
212
|
type: "file"
|
|
178
213
|
};
|
|
179
214
|
};
|