@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,7 +2,9 @@ import { type NextRequest } from 'next/server';
|
|
|
2
2
|
import { type EdgeStoreRouter } from '../../../core/internals/bucketBuilder';
|
|
3
3
|
import EdgeStoreError, {
|
|
4
4
|
EDGE_STORE_ERROR_CODES,
|
|
5
|
+
type EdgeStoreErrorCodeKey,
|
|
5
6
|
} from '../../../libs/errors/EdgeStoreError';
|
|
7
|
+
import Logger, { type LogLevel } from '../../../libs/logger';
|
|
6
8
|
import { EdgeStoreProvider } from '../../../providers/edgestore';
|
|
7
9
|
import { type Provider } from '../../../providers/types';
|
|
8
10
|
import { type MaybePromise } from '../../../types';
|
|
@@ -24,26 +26,54 @@ export type CreateContextOptions = {
|
|
|
24
26
|
req: NextRequest;
|
|
25
27
|
};
|
|
26
28
|
|
|
27
|
-
export type Config<TCtx> =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
export type Config<TCtx> = {
|
|
30
|
+
provider?: Provider;
|
|
31
|
+
router: EdgeStoreRouter<TCtx>;
|
|
32
|
+
logLevel?: LogLevel;
|
|
33
|
+
} & (TCtx extends Record<string, never>
|
|
34
|
+
? object
|
|
32
35
|
: {
|
|
33
36
|
provider?: Provider;
|
|
34
37
|
router: EdgeStoreRouter<TCtx>;
|
|
35
38
|
createContext: (opts: CreateContextOptions) => MaybePromise<TCtx>;
|
|
36
|
-
};
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
declare const globalThis: {
|
|
42
|
+
_EDGE_STORE_LOGGER: Logger;
|
|
43
|
+
};
|
|
37
44
|
|
|
38
45
|
export function createEdgeStoreNextHandler<TCtx>(config: Config<TCtx>) {
|
|
39
46
|
const { provider = EdgeStoreProvider() } = config;
|
|
47
|
+
const log = new Logger(config.logLevel);
|
|
48
|
+
globalThis._EDGE_STORE_LOGGER = log;
|
|
49
|
+
log.debug('Creating Edge Store Next handler (app adapter)');
|
|
50
|
+
|
|
40
51
|
return async (req: NextRequest) => {
|
|
41
52
|
try {
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
if (!('nextUrl' in req))
|
|
54
|
+
throw new EdgeStoreError({
|
|
55
|
+
message:
|
|
56
|
+
'Error running the app adapter. Make sure you are importing the correct adapter in your router configuration',
|
|
57
|
+
code: 'SERVER_ERROR',
|
|
58
|
+
});
|
|
59
|
+
if (req.nextUrl.pathname.endsWith('/health')) {
|
|
60
|
+
return new Response('OK', {
|
|
61
|
+
status: 200,
|
|
62
|
+
});
|
|
63
|
+
} else if (req.nextUrl.pathname.endsWith('/init')) {
|
|
64
|
+
let ctx = {} as TCtx;
|
|
65
|
+
try {
|
|
66
|
+
ctx =
|
|
67
|
+
'createContext' in config
|
|
68
|
+
? await config.createContext({ req })
|
|
69
|
+
: ({} as TCtx);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
throw new EdgeStoreError({
|
|
72
|
+
message: 'Error creating context',
|
|
73
|
+
code: 'CREATE_CONTEXT_ERROR',
|
|
74
|
+
cause: err instanceof Error ? err : undefined,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
47
77
|
const { newCookies, token, baseUrl } = await init({
|
|
48
78
|
ctx,
|
|
49
79
|
provider,
|
|
@@ -157,17 +187,30 @@ export function createEdgeStoreNextHandler<TCtx>(config: Config<TCtx>) {
|
|
|
157
187
|
}
|
|
158
188
|
} catch (err) {
|
|
159
189
|
if (err instanceof EdgeStoreError) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
190
|
+
log[err.level](err.formattedMessage());
|
|
191
|
+
if (err.cause) log[err.level](err.cause);
|
|
192
|
+
return new Response(JSON.stringify(err.formattedJson()), {
|
|
193
|
+
status: EDGE_STORE_ERROR_CODES[err.code as EdgeStoreErrorCodeKey],
|
|
194
|
+
headers: {
|
|
195
|
+
'Content-Type': 'application/json',
|
|
196
|
+
},
|
|
166
197
|
});
|
|
167
198
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
199
|
+
log.error(err);
|
|
200
|
+
return new Response(
|
|
201
|
+
JSON.stringify(
|
|
202
|
+
new EdgeStoreError({
|
|
203
|
+
message: 'Internal server error',
|
|
204
|
+
code: 'SERVER_ERROR',
|
|
205
|
+
}).formattedJson(),
|
|
206
|
+
),
|
|
207
|
+
{
|
|
208
|
+
status: 500,
|
|
209
|
+
headers: {
|
|
210
|
+
'Content-Type': 'application/json',
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
);
|
|
171
214
|
}
|
|
172
215
|
};
|
|
173
216
|
}
|
|
@@ -2,7 +2,9 @@ import { type NextApiRequest, type NextApiResponse } from 'next/types';
|
|
|
2
2
|
import { type EdgeStoreRouter } from '../../../core/internals/bucketBuilder';
|
|
3
3
|
import EdgeStoreError, {
|
|
4
4
|
EDGE_STORE_ERROR_CODES,
|
|
5
|
+
type EdgeStoreErrorCodeKey,
|
|
5
6
|
} from '../../../libs/errors/EdgeStoreError';
|
|
7
|
+
import Logger, { type LogLevel } from '../../../libs/logger';
|
|
6
8
|
import { EdgeStoreProvider } from '../../../providers/edgestore';
|
|
7
9
|
import { type Provider } from '../../../providers/types';
|
|
8
10
|
import { type MaybePromise } from '../../../types';
|
|
@@ -25,26 +27,52 @@ export type CreateContextOptions = {
|
|
|
25
27
|
res: NextApiResponse;
|
|
26
28
|
};
|
|
27
29
|
|
|
28
|
-
export type Config<TCtx> =
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
export type Config<TCtx> = {
|
|
31
|
+
provider?: Provider;
|
|
32
|
+
router: EdgeStoreRouter<TCtx>;
|
|
33
|
+
logLevel?: LogLevel;
|
|
34
|
+
} & (TCtx extends Record<string, never>
|
|
35
|
+
? object
|
|
33
36
|
: {
|
|
34
37
|
provider?: Provider;
|
|
35
38
|
router: EdgeStoreRouter<TCtx>;
|
|
36
39
|
createContext: (opts: CreateContextOptions) => MaybePromise<TCtx>;
|
|
37
|
-
};
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
declare const globalThis: {
|
|
43
|
+
_EDGE_STORE_LOGGER: Logger;
|
|
44
|
+
};
|
|
38
45
|
|
|
39
46
|
export function createEdgeStoreNextHandler<TCtx>(config: Config<TCtx>) {
|
|
40
47
|
const { provider = EdgeStoreProvider() } = config;
|
|
48
|
+
const log = new Logger(config.logLevel);
|
|
49
|
+
globalThis._EDGE_STORE_LOGGER = log;
|
|
50
|
+
log.debug('Creating Edge Store Next handler (pages adapter)');
|
|
51
|
+
|
|
41
52
|
return async (req: NextApiRequest, res: NextApiResponse) => {
|
|
42
53
|
try {
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
54
|
+
if (!('json' in res))
|
|
55
|
+
throw new EdgeStoreError({
|
|
56
|
+
message:
|
|
57
|
+
'Error running the pages adapter. Make sure you are importing the correct adapter in your router configuration',
|
|
58
|
+
code: 'SERVER_ERROR',
|
|
59
|
+
});
|
|
60
|
+
if (req.url?.includes?.('/health')) {
|
|
61
|
+
res.send('OK');
|
|
62
|
+
} else if (req.url?.includes?.('/init')) {
|
|
63
|
+
let ctx = {} as TCtx;
|
|
64
|
+
try {
|
|
65
|
+
ctx =
|
|
66
|
+
'createContext' in config
|
|
67
|
+
? await config.createContext({ req, res })
|
|
68
|
+
: ({} as TCtx);
|
|
69
|
+
} catch (err) {
|
|
70
|
+
throw new EdgeStoreError({
|
|
71
|
+
message: 'Error creating context',
|
|
72
|
+
code: 'CREATE_CONTEXT_ERROR',
|
|
73
|
+
cause: err instanceof Error ? err : undefined,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
48
76
|
const { newCookies, token, baseUrl } = await init({
|
|
49
77
|
ctx,
|
|
50
78
|
provider,
|
|
@@ -123,11 +151,20 @@ export function createEdgeStoreNextHandler<TCtx>(config: Config<TCtx>) {
|
|
|
123
151
|
}
|
|
124
152
|
} catch (err) {
|
|
125
153
|
if (err instanceof EdgeStoreError) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
res
|
|
154
|
+
log[err.level](err.formattedMessage());
|
|
155
|
+
if (err.cause) log[err.level](err.cause);
|
|
156
|
+
res
|
|
157
|
+
.status(EDGE_STORE_ERROR_CODES[err.code as EdgeStoreErrorCodeKey])
|
|
158
|
+
.json(err.formattedJson());
|
|
159
|
+
} else {
|
|
160
|
+
log.error(err);
|
|
161
|
+
res.status(500).send(
|
|
162
|
+
new EdgeStoreError({
|
|
163
|
+
message: 'Internal Server Error',
|
|
164
|
+
code: 'SERVER_ERROR',
|
|
165
|
+
}).formattedJson(),
|
|
166
|
+
);
|
|
129
167
|
}
|
|
130
|
-
res.status(500).send('Internal server error');
|
|
131
168
|
}
|
|
132
169
|
};
|
|
133
170
|
}
|
package/src/adapters/shared.ts
CHANGED
|
@@ -7,18 +7,25 @@ import {
|
|
|
7
7
|
type EdgeStoreRouter,
|
|
8
8
|
} from '../core/internals/bucketBuilder';
|
|
9
9
|
import EdgeStoreError from '../libs/errors/EdgeStoreError';
|
|
10
|
+
import type Logger from '../libs/logger';
|
|
10
11
|
import { type Provider } from '../providers/types';
|
|
11
12
|
import { IMAGE_MIME_TYPES } from './imageTypes';
|
|
12
13
|
|
|
13
14
|
// TODO: change it to 1 hour when we have a way to refresh the token
|
|
14
15
|
const DEFAULT_MAX_AGE = 30 * 24 * 60 * 60; // 30 days
|
|
15
16
|
|
|
17
|
+
declare const globalThis: {
|
|
18
|
+
_EDGE_STORE_LOGGER: Logger;
|
|
19
|
+
};
|
|
20
|
+
|
|
16
21
|
export async function init<TCtx>(params: {
|
|
17
22
|
provider: Provider;
|
|
18
23
|
router: EdgeStoreRouter<TCtx>;
|
|
19
24
|
ctx: TCtx;
|
|
20
25
|
}) {
|
|
26
|
+
const log = globalThis._EDGE_STORE_LOGGER;
|
|
21
27
|
const { ctx, provider, router } = params;
|
|
28
|
+
log.debug('Running [init]', { ctx });
|
|
22
29
|
const ctxToken = await encryptJWT(ctx);
|
|
23
30
|
const { token } = await provider.init({
|
|
24
31
|
ctx,
|
|
@@ -40,6 +47,8 @@ export async function init<TCtx>(params: {
|
|
|
40
47
|
}
|
|
41
48
|
const baseUrl = await provider.getBaseUrl();
|
|
42
49
|
|
|
50
|
+
log.debug('Finished [init]', { ctx, newCookies, token, baseUrl });
|
|
51
|
+
|
|
43
52
|
return {
|
|
44
53
|
newCookies,
|
|
45
54
|
token,
|
|
@@ -72,6 +81,8 @@ export async function requestUpload<TCtx>(params: {
|
|
|
72
81
|
ctxToken,
|
|
73
82
|
body: { bucketName, input, fileInfo },
|
|
74
83
|
} = params;
|
|
84
|
+
const log = globalThis._EDGE_STORE_LOGGER;
|
|
85
|
+
log.debug('Running [requestUpload]', { bucketName, input, fileInfo });
|
|
75
86
|
|
|
76
87
|
if (!ctxToken) {
|
|
77
88
|
throw new EdgeStoreError({
|
|
@@ -80,11 +91,18 @@ export async function requestUpload<TCtx>(params: {
|
|
|
80
91
|
});
|
|
81
92
|
}
|
|
82
93
|
const ctx = await getContext(ctxToken);
|
|
94
|
+
|
|
95
|
+
log.debug('Decrypted Context', { ctx });
|
|
96
|
+
|
|
83
97
|
const bucket = router.buckets[bucketName];
|
|
84
98
|
if (!bucket) {
|
|
85
|
-
throw new
|
|
99
|
+
throw new EdgeStoreError({
|
|
100
|
+
message: `Bucket ${bucketName} not found`,
|
|
101
|
+
code: 'BAD_REQUEST',
|
|
102
|
+
});
|
|
86
103
|
}
|
|
87
104
|
if (bucket._def.beforeUpload) {
|
|
105
|
+
log.debug('Running [beforeUpload]');
|
|
88
106
|
const canUpload = await bucket._def.beforeUpload?.({
|
|
89
107
|
ctx,
|
|
90
108
|
input,
|
|
@@ -97,16 +115,24 @@ export async function requestUpload<TCtx>(params: {
|
|
|
97
115
|
temporary: fileInfo.temporary,
|
|
98
116
|
},
|
|
99
117
|
});
|
|
118
|
+
log.debug('Finished [beforeUpload]', { canUpload });
|
|
100
119
|
if (!canUpload) {
|
|
101
|
-
throw new
|
|
120
|
+
throw new EdgeStoreError({
|
|
121
|
+
message: 'Upload not allowed for the current context',
|
|
122
|
+
code: 'UPLOAD_NOT_ALLOWED',
|
|
123
|
+
});
|
|
102
124
|
}
|
|
103
125
|
}
|
|
104
126
|
|
|
105
127
|
if (bucket._def.type === 'IMAGE') {
|
|
106
128
|
if (!IMAGE_MIME_TYPES.includes(fileInfo.type)) {
|
|
107
129
|
throw new EdgeStoreError({
|
|
108
|
-
code: '
|
|
130
|
+
code: 'MIME_TYPE_NOT_ALLOWED',
|
|
109
131
|
message: 'Only images are allowed in this bucket',
|
|
132
|
+
details: {
|
|
133
|
+
allowedMimeTypes: IMAGE_MIME_TYPES,
|
|
134
|
+
mimeType: fileInfo.type,
|
|
135
|
+
},
|
|
110
136
|
});
|
|
111
137
|
}
|
|
112
138
|
}
|
|
@@ -114,8 +140,12 @@ export async function requestUpload<TCtx>(params: {
|
|
|
114
140
|
if (bucket._def.bucketConfig?.maxSize) {
|
|
115
141
|
if (fileInfo.size > bucket._def.bucketConfig.maxSize) {
|
|
116
142
|
throw new EdgeStoreError({
|
|
117
|
-
code: '
|
|
143
|
+
code: 'FILE_TOO_LARGE',
|
|
118
144
|
message: `File size is too big. Max size is ${bucket._def.bucketConfig.maxSize}`,
|
|
145
|
+
details: {
|
|
146
|
+
maxFileSize: bucket._def.bucketConfig.maxSize,
|
|
147
|
+
fileSize: fileInfo.size,
|
|
148
|
+
},
|
|
119
149
|
});
|
|
120
150
|
}
|
|
121
151
|
}
|
|
@@ -137,10 +167,14 @@ export async function requestUpload<TCtx>(params: {
|
|
|
137
167
|
}
|
|
138
168
|
if (!accepted) {
|
|
139
169
|
throw new EdgeStoreError({
|
|
140
|
-
code: '
|
|
170
|
+
code: 'MIME_TYPE_NOT_ALLOWED',
|
|
141
171
|
message: `"${
|
|
142
172
|
fileInfo.type
|
|
143
173
|
}" is not allowed. Accepted types are ${JSON.stringify(accept)}`,
|
|
174
|
+
details: {
|
|
175
|
+
allowedMimeTypes: accept,
|
|
176
|
+
mimeType: fileInfo.type,
|
|
177
|
+
},
|
|
144
178
|
});
|
|
145
179
|
}
|
|
146
180
|
}
|
|
@@ -152,6 +186,14 @@ export async function requestUpload<TCtx>(params: {
|
|
|
152
186
|
});
|
|
153
187
|
const metadata = await bucket._def.metadata?.({ ctx, input });
|
|
154
188
|
const isPublic = bucket._def.accessControl === undefined;
|
|
189
|
+
|
|
190
|
+
log.debug('upload info', {
|
|
191
|
+
path,
|
|
192
|
+
metadata,
|
|
193
|
+
isPublic,
|
|
194
|
+
bucketType: bucket._def.type,
|
|
195
|
+
});
|
|
196
|
+
|
|
155
197
|
const requestUploadRes = await provider.requestUpload({
|
|
156
198
|
bucketName,
|
|
157
199
|
bucketType: bucket._def.type,
|
|
@@ -162,12 +204,10 @@ export async function requestUpload<TCtx>(params: {
|
|
|
162
204
|
metadata,
|
|
163
205
|
},
|
|
164
206
|
});
|
|
165
|
-
const parsedPath = path
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}, {});
|
|
207
|
+
const { parsedPath, pathOrder } = parsePath(path);
|
|
208
|
+
|
|
209
|
+
log.debug('Finished [requestUpload]');
|
|
169
210
|
|
|
170
|
-
const pathOrder = path.map((p) => p.key);
|
|
171
211
|
return {
|
|
172
212
|
...requestUploadRes,
|
|
173
213
|
size: fileInfo.size,
|
|
@@ -194,10 +234,13 @@ export async function requestUploadParts<TCtx>(params: {
|
|
|
194
234
|
}) {
|
|
195
235
|
const {
|
|
196
236
|
provider,
|
|
197
|
-
router,
|
|
198
237
|
ctxToken,
|
|
199
238
|
body: { multipart, path },
|
|
200
239
|
} = params;
|
|
240
|
+
|
|
241
|
+
const log = globalThis._EDGE_STORE_LOGGER;
|
|
242
|
+
log.debug('Running [requestUploadParts]', { multipart, path });
|
|
243
|
+
|
|
201
244
|
if (!ctxToken) {
|
|
202
245
|
throw new EdgeStoreError({
|
|
203
246
|
message: 'Missing edgestore-ctx cookie',
|
|
@@ -205,14 +248,15 @@ export async function requestUploadParts<TCtx>(params: {
|
|
|
205
248
|
});
|
|
206
249
|
}
|
|
207
250
|
await getContext(ctxToken); // just to check if the token is valid
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
throw new Error(`Bucket ${multipart.uploadId} not found`);
|
|
211
|
-
}
|
|
212
|
-
return await provider.requestUploadParts({
|
|
251
|
+
|
|
252
|
+
const res = await provider.requestUploadParts({
|
|
213
253
|
multipart,
|
|
214
254
|
path,
|
|
215
255
|
});
|
|
256
|
+
|
|
257
|
+
log.debug('Finished [requestUploadParts]');
|
|
258
|
+
|
|
259
|
+
return res;
|
|
216
260
|
}
|
|
217
261
|
|
|
218
262
|
export type CompleteMultipartUploadBody = {
|
|
@@ -237,6 +281,14 @@ export async function completeMultipartUpload<TCtx>(params: {
|
|
|
237
281
|
ctxToken,
|
|
238
282
|
body: { bucketName, uploadId, key, parts },
|
|
239
283
|
} = params;
|
|
284
|
+
|
|
285
|
+
const log = globalThis._EDGE_STORE_LOGGER;
|
|
286
|
+
log.debug('Running [completeMultipartUpload]', {
|
|
287
|
+
bucketName,
|
|
288
|
+
uploadId,
|
|
289
|
+
key,
|
|
290
|
+
});
|
|
291
|
+
|
|
240
292
|
if (!ctxToken) {
|
|
241
293
|
throw new EdgeStoreError({
|
|
242
294
|
message: 'Missing edgestore-ctx cookie',
|
|
@@ -246,13 +298,21 @@ export async function completeMultipartUpload<TCtx>(params: {
|
|
|
246
298
|
await getContext(ctxToken); // just to check if the token is valid
|
|
247
299
|
const bucket = router.buckets[bucketName];
|
|
248
300
|
if (!bucket) {
|
|
249
|
-
throw new
|
|
301
|
+
throw new EdgeStoreError({
|
|
302
|
+
message: `Bucket ${bucketName} not found`,
|
|
303
|
+
code: 'BAD_REQUEST',
|
|
304
|
+
});
|
|
250
305
|
}
|
|
251
|
-
|
|
306
|
+
|
|
307
|
+
const res = await provider.completeMultipartUpload({
|
|
252
308
|
uploadId,
|
|
253
309
|
key,
|
|
254
310
|
parts,
|
|
255
311
|
});
|
|
312
|
+
|
|
313
|
+
log.debug('Finished [completeMultipartUpload]');
|
|
314
|
+
|
|
315
|
+
return res;
|
|
256
316
|
}
|
|
257
317
|
|
|
258
318
|
export type ConfirmUploadBody = {
|
|
@@ -273,6 +333,9 @@ export async function confirmUpload<TCtx>(params: {
|
|
|
273
333
|
body: { bucketName, url },
|
|
274
334
|
} = params;
|
|
275
335
|
|
|
336
|
+
const log = globalThis._EDGE_STORE_LOGGER;
|
|
337
|
+
log.debug('Running [confirmUpload]', { bucketName, url });
|
|
338
|
+
|
|
276
339
|
if (!ctxToken) {
|
|
277
340
|
throw new EdgeStoreError({
|
|
278
341
|
message: 'Missing edgestore-ctx cookie',
|
|
@@ -282,13 +345,19 @@ export async function confirmUpload<TCtx>(params: {
|
|
|
282
345
|
await getContext(ctxToken); // just to check if the token is valid
|
|
283
346
|
const bucket = router.buckets[bucketName];
|
|
284
347
|
if (!bucket) {
|
|
285
|
-
throw new
|
|
348
|
+
throw new EdgeStoreError({
|
|
349
|
+
message: `Bucket ${bucketName} not found`,
|
|
350
|
+
code: 'BAD_REQUEST',
|
|
351
|
+
});
|
|
286
352
|
}
|
|
287
353
|
|
|
288
|
-
|
|
354
|
+
const res = await provider.confirmUpload({
|
|
289
355
|
bucket,
|
|
290
356
|
url: unproxyUrl(url),
|
|
291
357
|
});
|
|
358
|
+
|
|
359
|
+
log.debug('Finished [confirmUpload]');
|
|
360
|
+
return res;
|
|
292
361
|
}
|
|
293
362
|
|
|
294
363
|
export type DeleteFileBody = {
|
|
@@ -309,6 +378,9 @@ export async function deleteFile<TCtx>(params: {
|
|
|
309
378
|
body: { bucketName, url },
|
|
310
379
|
} = params;
|
|
311
380
|
|
|
381
|
+
const log = globalThis._EDGE_STORE_LOGGER;
|
|
382
|
+
log.debug('Running [deleteFile]', { bucketName, url });
|
|
383
|
+
|
|
312
384
|
if (!ctxToken) {
|
|
313
385
|
throw new EdgeStoreError({
|
|
314
386
|
message: 'Missing edgestore-ctx cookie',
|
|
@@ -318,38 +390,52 @@ export async function deleteFile<TCtx>(params: {
|
|
|
318
390
|
const ctx = await getContext(ctxToken);
|
|
319
391
|
const bucket = router.buckets[bucketName];
|
|
320
392
|
if (!bucket) {
|
|
321
|
-
throw new
|
|
393
|
+
throw new EdgeStoreError({
|
|
394
|
+
message: `Bucket ${bucketName} not found`,
|
|
395
|
+
code: 'BAD_REQUEST',
|
|
396
|
+
});
|
|
322
397
|
}
|
|
323
398
|
|
|
324
399
|
if (!bucket._def.beforeDelete) {
|
|
325
|
-
throw new
|
|
326
|
-
|
|
327
|
-
|
|
400
|
+
throw new EdgeStoreError({
|
|
401
|
+
message:
|
|
402
|
+
'You need to define beforeDelete if you want to delete files directly from the frontend.',
|
|
403
|
+
code: 'SERVER_ERROR',
|
|
404
|
+
});
|
|
328
405
|
}
|
|
329
406
|
|
|
330
407
|
const fileInfo = await provider.getFile({
|
|
331
|
-
url,
|
|
408
|
+
url: unproxyUrl(url),
|
|
332
409
|
});
|
|
410
|
+
|
|
333
411
|
const canDelete = await bucket._def.beforeDelete({
|
|
334
412
|
ctx,
|
|
335
413
|
fileInfo,
|
|
336
414
|
});
|
|
337
415
|
if (!canDelete) {
|
|
338
|
-
throw new
|
|
416
|
+
throw new EdgeStoreError({
|
|
417
|
+
message: 'Delete not allowed for the current context',
|
|
418
|
+
code: 'DELETE_NOT_ALLOWED',
|
|
419
|
+
});
|
|
339
420
|
}
|
|
340
|
-
|
|
421
|
+
const res = await provider.deleteFile({
|
|
341
422
|
bucket,
|
|
342
423
|
url: unproxyUrl(url),
|
|
343
424
|
});
|
|
425
|
+
|
|
426
|
+
log.debug('Finished [deleteFile]');
|
|
427
|
+
|
|
428
|
+
return res;
|
|
344
429
|
}
|
|
345
430
|
|
|
346
431
|
async function encryptJWT(ctx: any) {
|
|
347
432
|
const secret =
|
|
348
433
|
process.env.EDGE_STORE_JWT_SECRET ?? process.env.EDGE_STORE_SECRET_KEY;
|
|
349
434
|
if (!secret) {
|
|
350
|
-
throw new
|
|
351
|
-
'EDGE_STORE_JWT_SECRET or EDGE_STORE_SECRET_KEY is not defined',
|
|
352
|
-
|
|
435
|
+
throw new EdgeStoreError({
|
|
436
|
+
message: 'EDGE_STORE_JWT_SECRET or EDGE_STORE_SECRET_KEY is not defined',
|
|
437
|
+
code: 'SERVER_ERROR',
|
|
438
|
+
});
|
|
353
439
|
}
|
|
354
440
|
const encryptionSecret = await getDerivedEncryptionKey(secret);
|
|
355
441
|
return await new EncryptJWT(ctx)
|
|
@@ -364,9 +450,10 @@ async function decryptJWT(token: string) {
|
|
|
364
450
|
const secret =
|
|
365
451
|
process.env.EDGE_STORE_JWT_SECRET ?? process.env.EDGE_STORE_SECRET_KEY;
|
|
366
452
|
if (!secret) {
|
|
367
|
-
throw new
|
|
368
|
-
'EDGE_STORE_JWT_SECRET or EDGE_STORE_SECRET_KEY is not
|
|
369
|
-
|
|
453
|
+
throw new EdgeStoreError({
|
|
454
|
+
message: 'EDGE_STORE_JWT_SECRET or EDGE_STORE_SECRET_KEY is not defined',
|
|
455
|
+
code: 'SERVER_ERROR',
|
|
456
|
+
});
|
|
370
457
|
}
|
|
371
458
|
const encryptionSecret = await getDerivedEncryptionKey(secret);
|
|
372
459
|
const { payload } = await jwtDecrypt(token, encryptionSecret, {
|
|
@@ -385,7 +472,7 @@ async function getDerivedEncryptionKey(secret: string) {
|
|
|
385
472
|
);
|
|
386
473
|
}
|
|
387
474
|
|
|
388
|
-
function buildPath(params: {
|
|
475
|
+
export function buildPath(params: {
|
|
389
476
|
fileInfo: RequestUploadBody['fileInfo'];
|
|
390
477
|
bucket: AnyBuilder;
|
|
391
478
|
pathAttrs: {
|
|
@@ -398,7 +485,10 @@ function buildPath(params: {
|
|
|
398
485
|
const path = pathParams.map((param) => {
|
|
399
486
|
const paramEntries = Object.entries(param);
|
|
400
487
|
if (paramEntries[0] === undefined) {
|
|
401
|
-
throw new
|
|
488
|
+
throw new EdgeStoreError({
|
|
489
|
+
message: `Empty path param found in: ${JSON.stringify(pathParams)}`,
|
|
490
|
+
code: 'SERVER_ERROR',
|
|
491
|
+
});
|
|
402
492
|
}
|
|
403
493
|
const [key, value] = paramEntries[0];
|
|
404
494
|
// this is a string like: "ctx.xxx" or "input.yyy.zzz"
|
|
@@ -406,7 +496,10 @@ function buildPath(params: {
|
|
|
406
496
|
.split('.')
|
|
407
497
|
.reduce((acc2: any, key: string) => {
|
|
408
498
|
if (acc2[key] === undefined) {
|
|
409
|
-
throw new
|
|
499
|
+
throw new EdgeStoreError({
|
|
500
|
+
message: `Missing key ${key} in ${JSON.stringify(acc2)}`,
|
|
501
|
+
code: 'BAD_REQUEST',
|
|
502
|
+
});
|
|
410
503
|
}
|
|
411
504
|
return acc2[key];
|
|
412
505
|
}, params.pathAttrs as any) as string;
|
|
@@ -418,10 +511,19 @@ function buildPath(params: {
|
|
|
418
511
|
return path;
|
|
419
512
|
}
|
|
420
513
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
514
|
+
export function parsePath(path: { key: string; value: string }[]) {
|
|
515
|
+
const parsedPath = path.reduce<Record<string, string>>((acc, curr) => {
|
|
516
|
+
acc[curr.key] = curr.value;
|
|
517
|
+
return acc;
|
|
518
|
+
}, {});
|
|
519
|
+
const pathOrder = path.map((p) => p.key);
|
|
520
|
+
return {
|
|
521
|
+
parsedPath,
|
|
522
|
+
pathOrder,
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
async function getContext(token: string) {
|
|
425
527
|
return await decryptJWT(token);
|
|
426
528
|
}
|
|
427
529
|
|