@edgestore/server 0.1.5-alpha.0 → 0.1.5-alpha.10
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/adapters/express/index.d.ts +1 -0
- package/adapters/express/index.js +1 -0
- package/dist/adapters/express/index.d.ts +20 -0
- package/dist/adapters/express/index.d.ts.map +1 -0
- package/dist/adapters/express/index.js +117 -0
- package/dist/adapters/express/index.mjs +113 -0
- package/dist/adapters/next/app/index.d.ts +5 -3
- package/dist/adapters/next/app/index.d.ts.map +1 -1
- package/dist/adapters/next/app/index.js +45 -16
- package/dist/adapters/next/app/index.mjs +44 -15
- package/dist/adapters/next/pages/index.d.ts +5 -3
- package/dist/adapters/next/pages/index.d.ts.map +1 -1
- package/dist/adapters/next/pages/index.js +37 -13
- package/dist/adapters/next/pages/index.mjs +36 -12
- package/dist/adapters/shared.d.ts +19 -1
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/core/client/index.d.ts +116 -4
- package/dist/core/client/index.d.ts.map +1 -1
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +109 -34
- package/dist/core/index.mjs +110 -36
- package/dist/core/sdk/index.d.ts.map +1 -1
- package/dist/{index-f33a00fb.js → index-0c401ce1.js} +38 -4
- package/dist/{index-50ab9e08.js → index-23d1ede9.mjs} +42 -7
- package/dist/{index-30a3741e.mjs → index-a2e7ca9e.js} +49 -4
- package/dist/libs/errors/EdgeStoreApiClientError.d.ts +8 -0
- package/dist/libs/errors/EdgeStoreApiClientError.d.ts.map +1 -0
- package/dist/libs/errors/EdgeStoreCredentialsError.d.ts.map +1 -1
- package/dist/libs/errors/EdgeStoreError.d.ts +36 -4
- package/dist/libs/errors/EdgeStoreError.d.ts.map +1 -1
- package/dist/libs/logger.d.ts +13 -0
- package/dist/libs/logger.d.ts.map +1 -0
- package/dist/logger-7ea2248c.mjs +40 -0
- package/dist/logger-b530a3e1.js +42 -0
- package/dist/logger-e0066db9.js +33 -0
- package/dist/providers/aws/index.js +1 -1
- package/dist/providers/aws/index.mjs +1 -1
- package/dist/providers/azure/index.d.ts +20 -0
- package/dist/providers/azure/index.d.ts.map +1 -0
- package/dist/providers/azure/index.js +61 -0
- package/dist/providers/azure/index.mjs +57 -0
- package/dist/providers/edgestore/index.d.ts.map +1 -1
- package/dist/providers/edgestore/index.js +10 -3
- package/dist/providers/edgestore/index.mjs +10 -3
- package/dist/providers/types.d.ts +1 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/{shared-306c1af2.js → shared-06cb0d86.js} +150 -61
- package/dist/{shared-9fad0d51.js → shared-d474acc6.js} +114 -46
- package/dist/{shared-6dea9e91.mjs → shared-d7ea66fb.mjs} +141 -52
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +17 -2
- package/providers/azure/index.d.ts +1 -0
- package/providers/azure/index.js +1 -0
- package/src/adapters/express/index.ts +164 -0
- package/src/adapters/next/app/index.ts +63 -20
- package/src/adapters/next/pages/index.ts +52 -15
- package/src/adapters/shared.ts +142 -40
- package/src/core/client/index.ts +233 -51
- package/src/core/index.ts +6 -0
- package/src/core/sdk/index.ts +7 -1
- package/src/libs/errors/EdgeStoreApiClientError.ts +14 -0
- package/src/libs/errors/EdgeStoreCredentialsError.ts +1 -2
- package/src/libs/errors/EdgeStoreError.ts +74 -7
- package/src/libs/logger.ts +44 -0
- package/src/providers/aws/index.ts +1 -1
- package/src/providers/azure/index.ts +89 -0
- package/src/providers/edgestore/index.ts +9 -2
- package/src/providers/types.ts +1 -0
- package/src/types.ts +8 -0
|
@@ -2,19 +2,7 @@ import { hkdf } from '@panva/hkdf';
|
|
|
2
2
|
import { serialize } from 'cookie';
|
|
3
3
|
import { EncryptJWT, jwtDecrypt } from 'jose';
|
|
4
4
|
import { v4 } from 'uuid';
|
|
5
|
-
|
|
6
|
-
const EDGE_STORE_ERROR_CODES = {
|
|
7
|
-
BAD_REQUEST: 400,
|
|
8
|
-
UNAUTHORIZED: 401,
|
|
9
|
-
};
|
|
10
|
-
class EdgeStoreError extends Error {
|
|
11
|
-
constructor(opts) {
|
|
12
|
-
super(opts.message);
|
|
13
|
-
this.name = 'EdgeStoreError';
|
|
14
|
-
this.code = opts.code;
|
|
15
|
-
this.cause = opts.cause;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
5
|
+
import { E as EdgeStoreError } from './index-0c401ce1.js';
|
|
18
6
|
|
|
19
7
|
const IMAGE_MIME_TYPES = [
|
|
20
8
|
'image/jpeg',
|
|
@@ -30,7 +18,9 @@ const IMAGE_MIME_TYPES = [
|
|
|
30
18
|
// TODO: change it to 1 hour when we have a way to refresh the token
|
|
31
19
|
const DEFAULT_MAX_AGE = 30 * 24 * 60 * 60; // 30 days
|
|
32
20
|
async function init(params) {
|
|
21
|
+
const log = globalThis._EDGE_STORE_LOGGER;
|
|
33
22
|
const { ctx, provider, router } = params;
|
|
23
|
+
log.debug('Running [init]', { ctx });
|
|
34
24
|
const ctxToken = await encryptJWT(ctx);
|
|
35
25
|
const { token } = await provider.init({
|
|
36
26
|
ctx,
|
|
@@ -49,6 +39,7 @@ async function init(params) {
|
|
|
49
39
|
}));
|
|
50
40
|
}
|
|
51
41
|
const baseUrl = await provider.getBaseUrl();
|
|
42
|
+
log.debug('Finished [init]', { ctx, newCookies, token, baseUrl });
|
|
52
43
|
return {
|
|
53
44
|
newCookies,
|
|
54
45
|
token,
|
|
@@ -57,6 +48,8 @@ async function init(params) {
|
|
|
57
48
|
}
|
|
58
49
|
async function requestUpload(params) {
|
|
59
50
|
const { provider, router, ctxToken, body: { bucketName, input, fileInfo }, } = params;
|
|
51
|
+
const log = globalThis._EDGE_STORE_LOGGER;
|
|
52
|
+
log.debug('Running [requestUpload]', { bucketName, input, fileInfo });
|
|
60
53
|
if (!ctxToken) {
|
|
61
54
|
throw new EdgeStoreError({
|
|
62
55
|
message: 'Missing edgestore-ctx cookie',
|
|
@@ -64,11 +57,16 @@ async function requestUpload(params) {
|
|
|
64
57
|
});
|
|
65
58
|
}
|
|
66
59
|
const ctx = await getContext(ctxToken);
|
|
60
|
+
log.debug('Decrypted Context', { ctx });
|
|
67
61
|
const bucket = router.buckets[bucketName];
|
|
68
62
|
if (!bucket) {
|
|
69
|
-
throw new
|
|
63
|
+
throw new EdgeStoreError({
|
|
64
|
+
message: `Bucket ${bucketName} not found`,
|
|
65
|
+
code: 'BAD_REQUEST',
|
|
66
|
+
});
|
|
70
67
|
}
|
|
71
68
|
if (bucket._def.beforeUpload) {
|
|
69
|
+
log.debug('Running [beforeUpload]');
|
|
72
70
|
const canUpload = await bucket._def.beforeUpload?.({
|
|
73
71
|
ctx,
|
|
74
72
|
input,
|
|
@@ -81,23 +79,35 @@ async function requestUpload(params) {
|
|
|
81
79
|
temporary: fileInfo.temporary,
|
|
82
80
|
},
|
|
83
81
|
});
|
|
82
|
+
log.debug('Finished [beforeUpload]', { canUpload });
|
|
84
83
|
if (!canUpload) {
|
|
85
|
-
throw new
|
|
84
|
+
throw new EdgeStoreError({
|
|
85
|
+
message: 'Upload not allowed for the current context',
|
|
86
|
+
code: 'UPLOAD_NOT_ALLOWED',
|
|
87
|
+
});
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
if (bucket._def.type === 'IMAGE') {
|
|
89
91
|
if (!IMAGE_MIME_TYPES.includes(fileInfo.type)) {
|
|
90
92
|
throw new EdgeStoreError({
|
|
91
|
-
code: '
|
|
93
|
+
code: 'MIME_TYPE_NOT_ALLOWED',
|
|
92
94
|
message: 'Only images are allowed in this bucket',
|
|
95
|
+
details: {
|
|
96
|
+
allowedMimeTypes: IMAGE_MIME_TYPES,
|
|
97
|
+
mimeType: fileInfo.type,
|
|
98
|
+
},
|
|
93
99
|
});
|
|
94
100
|
}
|
|
95
101
|
}
|
|
96
102
|
if (bucket._def.bucketConfig?.maxSize) {
|
|
97
103
|
if (fileInfo.size > bucket._def.bucketConfig.maxSize) {
|
|
98
104
|
throw new EdgeStoreError({
|
|
99
|
-
code: '
|
|
105
|
+
code: 'FILE_TOO_LARGE',
|
|
100
106
|
message: `File size is too big. Max size is ${bucket._def.bucketConfig.maxSize}`,
|
|
107
|
+
details: {
|
|
108
|
+
maxFileSize: bucket._def.bucketConfig.maxSize,
|
|
109
|
+
fileSize: fileInfo.size,
|
|
110
|
+
},
|
|
101
111
|
});
|
|
102
112
|
}
|
|
103
113
|
}
|
|
@@ -119,8 +129,12 @@ async function requestUpload(params) {
|
|
|
119
129
|
}
|
|
120
130
|
if (!accepted) {
|
|
121
131
|
throw new EdgeStoreError({
|
|
122
|
-
code: '
|
|
132
|
+
code: 'MIME_TYPE_NOT_ALLOWED',
|
|
123
133
|
message: `"${fileInfo.type}" is not allowed. Accepted types are ${JSON.stringify(accept)}`,
|
|
134
|
+
details: {
|
|
135
|
+
allowedMimeTypes: accept,
|
|
136
|
+
mimeType: fileInfo.type,
|
|
137
|
+
},
|
|
124
138
|
});
|
|
125
139
|
}
|
|
126
140
|
}
|
|
@@ -131,6 +145,12 @@ async function requestUpload(params) {
|
|
|
131
145
|
});
|
|
132
146
|
const metadata = await bucket._def.metadata?.({ ctx, input });
|
|
133
147
|
const isPublic = bucket._def.accessControl === undefined;
|
|
148
|
+
log.debug('upload info', {
|
|
149
|
+
path,
|
|
150
|
+
metadata,
|
|
151
|
+
isPublic,
|
|
152
|
+
bucketType: bucket._def.type,
|
|
153
|
+
});
|
|
134
154
|
const requestUploadRes = await provider.requestUpload({
|
|
135
155
|
bucketName,
|
|
136
156
|
bucketType: bucket._def.type,
|
|
@@ -141,11 +161,8 @@ async function requestUpload(params) {
|
|
|
141
161
|
metadata,
|
|
142
162
|
},
|
|
143
163
|
});
|
|
144
|
-
const parsedPath = path
|
|
145
|
-
|
|
146
|
-
return acc;
|
|
147
|
-
}, {});
|
|
148
|
-
const pathOrder = path.map((p) => p.key);
|
|
164
|
+
const { parsedPath, pathOrder } = parsePath(path);
|
|
165
|
+
log.debug('Finished [requestUpload]');
|
|
149
166
|
return {
|
|
150
167
|
...requestUploadRes,
|
|
151
168
|
size: fileInfo.size,
|
|
@@ -156,7 +173,9 @@ async function requestUpload(params) {
|
|
|
156
173
|
};
|
|
157
174
|
}
|
|
158
175
|
async function requestUploadParts(params) {
|
|
159
|
-
const { provider,
|
|
176
|
+
const { provider, ctxToken, body: { multipart, path }, } = params;
|
|
177
|
+
const log = globalThis._EDGE_STORE_LOGGER;
|
|
178
|
+
log.debug('Running [requestUploadParts]', { multipart, path });
|
|
160
179
|
if (!ctxToken) {
|
|
161
180
|
throw new EdgeStoreError({
|
|
162
181
|
message: 'Missing edgestore-ctx cookie',
|
|
@@ -164,17 +183,21 @@ async function requestUploadParts(params) {
|
|
|
164
183
|
});
|
|
165
184
|
}
|
|
166
185
|
await getContext(ctxToken); // just to check if the token is valid
|
|
167
|
-
const
|
|
168
|
-
if (!bucket) {
|
|
169
|
-
throw new Error(`Bucket ${multipart.uploadId} not found`);
|
|
170
|
-
}
|
|
171
|
-
return await provider.requestUploadParts({
|
|
186
|
+
const res = await provider.requestUploadParts({
|
|
172
187
|
multipart,
|
|
173
188
|
path,
|
|
174
189
|
});
|
|
190
|
+
log.debug('Finished [requestUploadParts]');
|
|
191
|
+
return res;
|
|
175
192
|
}
|
|
176
193
|
async function completeMultipartUpload(params) {
|
|
177
194
|
const { provider, router, ctxToken, body: { bucketName, uploadId, key, parts }, } = params;
|
|
195
|
+
const log = globalThis._EDGE_STORE_LOGGER;
|
|
196
|
+
log.debug('Running [completeMultipartUpload]', {
|
|
197
|
+
bucketName,
|
|
198
|
+
uploadId,
|
|
199
|
+
key,
|
|
200
|
+
});
|
|
178
201
|
if (!ctxToken) {
|
|
179
202
|
throw new EdgeStoreError({
|
|
180
203
|
message: 'Missing edgestore-ctx cookie',
|
|
@@ -184,16 +207,23 @@ async function completeMultipartUpload(params) {
|
|
|
184
207
|
await getContext(ctxToken); // just to check if the token is valid
|
|
185
208
|
const bucket = router.buckets[bucketName];
|
|
186
209
|
if (!bucket) {
|
|
187
|
-
throw new
|
|
210
|
+
throw new EdgeStoreError({
|
|
211
|
+
message: `Bucket ${bucketName} not found`,
|
|
212
|
+
code: 'BAD_REQUEST',
|
|
213
|
+
});
|
|
188
214
|
}
|
|
189
|
-
|
|
215
|
+
const res = await provider.completeMultipartUpload({
|
|
190
216
|
uploadId,
|
|
191
217
|
key,
|
|
192
218
|
parts,
|
|
193
219
|
});
|
|
220
|
+
log.debug('Finished [completeMultipartUpload]');
|
|
221
|
+
return res;
|
|
194
222
|
}
|
|
195
223
|
async function confirmUpload(params) {
|
|
196
224
|
const { provider, router, ctxToken, body: { bucketName, url }, } = params;
|
|
225
|
+
const log = globalThis._EDGE_STORE_LOGGER;
|
|
226
|
+
log.debug('Running [confirmUpload]', { bucketName, url });
|
|
197
227
|
if (!ctxToken) {
|
|
198
228
|
throw new EdgeStoreError({
|
|
199
229
|
message: 'Missing edgestore-ctx cookie',
|
|
@@ -203,15 +233,22 @@ async function confirmUpload(params) {
|
|
|
203
233
|
await getContext(ctxToken); // just to check if the token is valid
|
|
204
234
|
const bucket = router.buckets[bucketName];
|
|
205
235
|
if (!bucket) {
|
|
206
|
-
throw new
|
|
236
|
+
throw new EdgeStoreError({
|
|
237
|
+
message: `Bucket ${bucketName} not found`,
|
|
238
|
+
code: 'BAD_REQUEST',
|
|
239
|
+
});
|
|
207
240
|
}
|
|
208
|
-
|
|
241
|
+
const res = await provider.confirmUpload({
|
|
209
242
|
bucket,
|
|
210
243
|
url: unproxyUrl(url),
|
|
211
244
|
});
|
|
245
|
+
log.debug('Finished [confirmUpload]');
|
|
246
|
+
return res;
|
|
212
247
|
}
|
|
213
248
|
async function deleteFile(params) {
|
|
214
249
|
const { provider, router, ctxToken, body: { bucketName, url }, } = params;
|
|
250
|
+
const log = globalThis._EDGE_STORE_LOGGER;
|
|
251
|
+
log.debug('Running [deleteFile]', { bucketName, url });
|
|
215
252
|
if (!ctxToken) {
|
|
216
253
|
throw new EdgeStoreError({
|
|
217
254
|
message: 'Missing edgestore-ctx cookie',
|
|
@@ -221,30 +258,44 @@ async function deleteFile(params) {
|
|
|
221
258
|
const ctx = await getContext(ctxToken);
|
|
222
259
|
const bucket = router.buckets[bucketName];
|
|
223
260
|
if (!bucket) {
|
|
224
|
-
throw new
|
|
261
|
+
throw new EdgeStoreError({
|
|
262
|
+
message: `Bucket ${bucketName} not found`,
|
|
263
|
+
code: 'BAD_REQUEST',
|
|
264
|
+
});
|
|
225
265
|
}
|
|
226
266
|
if (!bucket._def.beforeDelete) {
|
|
227
|
-
throw new
|
|
267
|
+
throw new EdgeStoreError({
|
|
268
|
+
message: 'You need to define beforeDelete if you want to delete files directly from the frontend.',
|
|
269
|
+
code: 'SERVER_ERROR',
|
|
270
|
+
});
|
|
228
271
|
}
|
|
229
272
|
const fileInfo = await provider.getFile({
|
|
230
|
-
url,
|
|
273
|
+
url: unproxyUrl(url),
|
|
231
274
|
});
|
|
232
275
|
const canDelete = await bucket._def.beforeDelete({
|
|
233
276
|
ctx,
|
|
234
277
|
fileInfo,
|
|
235
278
|
});
|
|
236
279
|
if (!canDelete) {
|
|
237
|
-
throw new
|
|
280
|
+
throw new EdgeStoreError({
|
|
281
|
+
message: 'Delete not allowed for the current context',
|
|
282
|
+
code: 'DELETE_NOT_ALLOWED',
|
|
283
|
+
});
|
|
238
284
|
}
|
|
239
|
-
|
|
285
|
+
const res = await provider.deleteFile({
|
|
240
286
|
bucket,
|
|
241
287
|
url: unproxyUrl(url),
|
|
242
288
|
});
|
|
289
|
+
log.debug('Finished [deleteFile]');
|
|
290
|
+
return res;
|
|
243
291
|
}
|
|
244
292
|
async function encryptJWT(ctx) {
|
|
245
293
|
const secret = process.env.EDGE_STORE_JWT_SECRET ?? process.env.EDGE_STORE_SECRET_KEY;
|
|
246
294
|
if (!secret) {
|
|
247
|
-
throw new
|
|
295
|
+
throw new EdgeStoreError({
|
|
296
|
+
message: 'EDGE_STORE_JWT_SECRET or EDGE_STORE_SECRET_KEY is not defined',
|
|
297
|
+
code: 'SERVER_ERROR',
|
|
298
|
+
});
|
|
248
299
|
}
|
|
249
300
|
const encryptionSecret = await getDerivedEncryptionKey(secret);
|
|
250
301
|
return await new EncryptJWT(ctx)
|
|
@@ -257,7 +308,10 @@ async function encryptJWT(ctx) {
|
|
|
257
308
|
async function decryptJWT(token) {
|
|
258
309
|
const secret = process.env.EDGE_STORE_JWT_SECRET ?? process.env.EDGE_STORE_SECRET_KEY;
|
|
259
310
|
if (!secret) {
|
|
260
|
-
throw new
|
|
311
|
+
throw new EdgeStoreError({
|
|
312
|
+
message: 'EDGE_STORE_JWT_SECRET or EDGE_STORE_SECRET_KEY is not defined',
|
|
313
|
+
code: 'SERVER_ERROR',
|
|
314
|
+
});
|
|
261
315
|
}
|
|
262
316
|
const encryptionSecret = await getDerivedEncryptionKey(secret);
|
|
263
317
|
const { payload } = await jwtDecrypt(token, encryptionSecret, {
|
|
@@ -274,7 +328,10 @@ function buildPath(params) {
|
|
|
274
328
|
const path = pathParams.map((param) => {
|
|
275
329
|
const paramEntries = Object.entries(param);
|
|
276
330
|
if (paramEntries[0] === undefined) {
|
|
277
|
-
throw new
|
|
331
|
+
throw new EdgeStoreError({
|
|
332
|
+
message: `Empty path param found in: ${JSON.stringify(pathParams)}`,
|
|
333
|
+
code: 'SERVER_ERROR',
|
|
334
|
+
});
|
|
278
335
|
}
|
|
279
336
|
const [key, value] = paramEntries[0];
|
|
280
337
|
// this is a string like: "ctx.xxx" or "input.yyy.zzz"
|
|
@@ -282,7 +339,10 @@ function buildPath(params) {
|
|
|
282
339
|
.split('.')
|
|
283
340
|
.reduce((acc2, key) => {
|
|
284
341
|
if (acc2[key] === undefined) {
|
|
285
|
-
throw new
|
|
342
|
+
throw new EdgeStoreError({
|
|
343
|
+
message: `Missing key ${key} in ${JSON.stringify(acc2)}`,
|
|
344
|
+
code: 'BAD_REQUEST',
|
|
345
|
+
});
|
|
286
346
|
}
|
|
287
347
|
return acc2[key];
|
|
288
348
|
}, params.pathAttrs);
|
|
@@ -293,10 +353,18 @@ function buildPath(params) {
|
|
|
293
353
|
});
|
|
294
354
|
return path;
|
|
295
355
|
}
|
|
356
|
+
function parsePath(path) {
|
|
357
|
+
const parsedPath = path.reduce((acc, curr) => {
|
|
358
|
+
acc[curr.key] = curr.value;
|
|
359
|
+
return acc;
|
|
360
|
+
}, {});
|
|
361
|
+
const pathOrder = path.map((p) => p.key);
|
|
362
|
+
return {
|
|
363
|
+
parsedPath,
|
|
364
|
+
pathOrder,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
296
367
|
async function getContext(token) {
|
|
297
|
-
if (!token) {
|
|
298
|
-
throw new Error('No token');
|
|
299
|
-
}
|
|
300
368
|
return await decryptJWT(token);
|
|
301
369
|
}
|
|
302
370
|
/**
|
|
@@ -317,4 +385,4 @@ function unproxyUrl(url) {
|
|
|
317
385
|
return url;
|
|
318
386
|
}
|
|
319
387
|
|
|
320
|
-
export {
|
|
388
|
+
export { requestUploadParts as a, buildPath as b, completeMultipartUpload as c, confirmUpload as d, deleteFile as e, init as i, parsePath as p, requestUpload as r };
|