@edgestore/server 0.1.5-alpha.3 → 0.1.5-alpha.5
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/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 +38 -15
- package/dist/adapters/next/app/index.mjs +37 -14
- 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 +32 -12
- package/dist/adapters/next/pages/index.mjs +31 -11
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/core/client/index.d.ts +56 -2
- 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 +13 -3
- package/dist/core/index.mjs +14 -5
- package/dist/core/sdk/index.d.ts.map +1 -1
- package/dist/{index-50ab9e08.js → index-7cb3a3f3.mjs} +41 -5
- package/dist/{index-f33a00fb.js → index-9eb6248c.js} +37 -2
- package/dist/{index-30a3741e.mjs → index-e25c8209.js} +48 -2
- package/dist/libs/errors/EdgeStoreApiClientError.d.ts +8 -0
- package/dist/libs/errors/EdgeStoreApiClientError.d.ts.map +1 -0
- 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-0f08f252.mjs +40 -0
- package/dist/logger-623f2833.js +42 -0
- package/dist/logger-8f098618.js +33 -0
- 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/{shared-5d1e7f43.js → shared-53cb59dd.js} +72 -51
- package/dist/{shared-30b7a2ab.mjs → shared-b14a84ee.mjs} +65 -42
- package/dist/{shared-88655ba7.js → shared-f8ddbf7c.js} +62 -36
- package/package.json +12 -2
- package/providers/azure/index.d.ts +1 -0
- package/providers/azure/index.js +1 -0
- package/src/adapters/next/app/index.ts +52 -19
- package/src/adapters/next/pages/index.ts +43 -14
- package/src/adapters/shared.ts +62 -29
- package/src/core/client/index.ts +57 -2
- 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/EdgeStoreError.ts +76 -7
- package/src/libs/logger.ts +44 -0
- package/src/providers/azure/index.ts +89 -0
- package/src/providers/edgestore/index.ts +9 -2
package/src/core/client/index.ts
CHANGED
|
@@ -50,6 +50,26 @@ export type UploadOptions = {
|
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
export type UploadFileRequest<TBucket extends AnyBuilder> = {
|
|
53
|
+
/**
|
|
54
|
+
* Can be a string or a blob.
|
|
55
|
+
*
|
|
56
|
+
* If it's a string, it will be converted to a blob with the type `text/plain`.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* // string
|
|
61
|
+
* content: "some text"
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* // blob
|
|
67
|
+
* content: {
|
|
68
|
+
* blob: new Blob([text], { type: "text/csv" }),
|
|
69
|
+
* extension: "csv",
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
53
73
|
content:
|
|
54
74
|
| string
|
|
55
75
|
| {
|
|
@@ -125,15 +145,50 @@ type EdgeStoreClient<TRouter extends AnyRouter> = {
|
|
|
125
145
|
getFile: (params: {
|
|
126
146
|
url: string;
|
|
127
147
|
}) => Promise<GetFileRes<TRouter['buckets'][K]>>;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Use this function to upload a file to the bucket directly from your backend.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```ts
|
|
154
|
+
* // simple example
|
|
155
|
+
* await backendClient.myBucket.upload({
|
|
156
|
+
* content: "some text",
|
|
157
|
+
* });
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* // complete example
|
|
163
|
+
* await backendClient.myBucket.upload({
|
|
164
|
+
* content: {
|
|
165
|
+
* blob: new Blob([text], { type: "text/csv" }),
|
|
166
|
+
* extension: "csv",
|
|
167
|
+
* },
|
|
168
|
+
* options: {
|
|
169
|
+
* temporary: true,
|
|
170
|
+
* replaceTargetUrl: replaceUrl,
|
|
171
|
+
* manualFileName: "test.csv",
|
|
172
|
+
* },
|
|
173
|
+
* ctx: {
|
|
174
|
+
* userId: "123",
|
|
175
|
+
* userRole: "admin",
|
|
176
|
+
* },
|
|
177
|
+
* input: {
|
|
178
|
+
* type: "post",
|
|
179
|
+
* },
|
|
180
|
+
* });
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
128
183
|
upload: (
|
|
129
184
|
params: UploadFileRequest<TRouter['buckets'][K]>,
|
|
130
185
|
) => Promise<Prettify<UploadFileRes<TRouter['buckets'][K]>>>;
|
|
131
186
|
/**
|
|
132
|
-
* Confirm a temporary file upload.
|
|
187
|
+
* Confirm a temporary file upload directly from your backend.
|
|
133
188
|
*/
|
|
134
189
|
confirmUpload: (params: { url: string }) => Promise<{ success: boolean }>;
|
|
135
190
|
/**
|
|
136
|
-
* Programmatically delete a file.
|
|
191
|
+
* Programmatically delete a file directly from your backend.
|
|
137
192
|
*/
|
|
138
193
|
deleteFile: (params: { url: string }) => Promise<{
|
|
139
194
|
success: boolean;
|
package/src/core/index.ts
CHANGED
|
@@ -7,5 +7,11 @@ export type {
|
|
|
7
7
|
InferBucketPathObject,
|
|
8
8
|
InferMetadataObject,
|
|
9
9
|
} from './internals/bucketBuilder';
|
|
10
|
+
export type {
|
|
11
|
+
EdgeStoreErrorCodeKey,
|
|
12
|
+
EdgeStoreErrorDetails,
|
|
13
|
+
EdgeStoreJsonResponse,
|
|
14
|
+
} from '../libs/errors/EdgeStoreError';
|
|
15
|
+
export { EdgeStoreApiClientError } from '../libs/errors/EdgeStoreApiClientError';
|
|
10
16
|
|
|
11
17
|
export type AnyRouter = EdgeStoreRouter<any>;
|
package/src/core/sdk/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type AnyRouter } from '..';
|
|
2
2
|
import EdgeStoreCredentialsError from '../../libs/errors/EdgeStoreCredentialsError';
|
|
3
|
+
import EdgeStoreError from '../../libs/errors/EdgeStoreError';
|
|
3
4
|
import { type AnyContext, type AnyMetadata } from '../internals/bucketBuilder';
|
|
4
5
|
|
|
5
6
|
const API_ENDPOINT =
|
|
@@ -93,7 +94,12 @@ export const edgeStoreRawSdk = {
|
|
|
93
94
|
path: bucket._def.path.map((p: { [key: string]: () => string }) => {
|
|
94
95
|
const paramEntries = Object.entries(p);
|
|
95
96
|
if (paramEntries[0] === undefined) {
|
|
96
|
-
throw new
|
|
97
|
+
throw new EdgeStoreError({
|
|
98
|
+
message: `Empty path param found in: ${JSON.stringify(
|
|
99
|
+
bucket._def.path,
|
|
100
|
+
)}`,
|
|
101
|
+
code: 'SERVER_ERROR',
|
|
102
|
+
});
|
|
97
103
|
}
|
|
98
104
|
const [key, value] = paramEntries[0];
|
|
99
105
|
return {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
|
+
|
|
3
|
+
import { type EdgeStoreJsonResponse } from './EdgeStoreError';
|
|
4
|
+
|
|
5
|
+
export class EdgeStoreApiClientError extends Error {
|
|
6
|
+
public readonly data: EdgeStoreJsonResponse;
|
|
7
|
+
|
|
8
|
+
constructor(opts: { response: EdgeStoreJsonResponse }) {
|
|
9
|
+
super(opts.response.message);
|
|
10
|
+
this.name = 'EdgeStoreApiClientError';
|
|
11
|
+
|
|
12
|
+
this.data = opts.response;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,24 +1,93 @@
|
|
|
1
|
+
import { type Simplify } from '../../types';
|
|
2
|
+
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
1
4
|
export const EDGE_STORE_ERROR_CODES = {
|
|
2
5
|
BAD_REQUEST: 400,
|
|
6
|
+
FILE_TOO_LARGE: 400,
|
|
7
|
+
MIME_TYPE_NOT_ALLOWED: 400,
|
|
3
8
|
UNAUTHORIZED: 401,
|
|
9
|
+
UPLOAD_NOT_ALLOWED: 403,
|
|
10
|
+
DELETE_NOT_ALLOWED: 403,
|
|
11
|
+
CREATE_CONTEXT_ERROR: 500,
|
|
12
|
+
SERVER_ERROR: 500,
|
|
4
13
|
} as const;
|
|
5
14
|
|
|
6
15
|
export type EdgeStoreErrorCodeKey = keyof typeof EDGE_STORE_ERROR_CODES;
|
|
7
16
|
|
|
8
|
-
|
|
17
|
+
export type EdgeStoreErrorDetails<TCode extends EdgeStoreErrorCodeKey> =
|
|
18
|
+
TCode extends 'FILE_TOO_LARGE'
|
|
19
|
+
? {
|
|
20
|
+
maxFileSize: number;
|
|
21
|
+
fileSize: number;
|
|
22
|
+
}
|
|
23
|
+
: TCode extends 'MIME_TYPE_NOT_ALLOWED'
|
|
24
|
+
? {
|
|
25
|
+
allowedMimeTypes: string[];
|
|
26
|
+
mimeType: string;
|
|
27
|
+
}
|
|
28
|
+
: never;
|
|
29
|
+
|
|
30
|
+
export type EdgeStoreJsonResponse = Simplify<
|
|
31
|
+
| {
|
|
32
|
+
message: string;
|
|
33
|
+
code: 'FILE_TOO_LARGE';
|
|
34
|
+
details: EdgeStoreErrorDetails<'FILE_TOO_LARGE'>;
|
|
35
|
+
}
|
|
36
|
+
| {
|
|
37
|
+
message: string;
|
|
38
|
+
code: 'MIME_TYPE_NOT_ALLOWED';
|
|
39
|
+
details: EdgeStoreErrorDetails<'MIME_TYPE_NOT_ALLOWED'>;
|
|
40
|
+
}
|
|
41
|
+
| {
|
|
42
|
+
message: string;
|
|
43
|
+
code: Exclude<
|
|
44
|
+
EdgeStoreErrorCodeKey,
|
|
45
|
+
'FILE_TOO_LARGE' | 'MIME_TYPE_NOT_ALLOWED'
|
|
46
|
+
>;
|
|
47
|
+
}
|
|
48
|
+
>;
|
|
49
|
+
|
|
50
|
+
class EdgeStoreError<TCode extends EdgeStoreErrorCodeKey> extends Error {
|
|
9
51
|
public readonly cause?: Error;
|
|
10
|
-
public readonly code:
|
|
52
|
+
public readonly code: TCode;
|
|
53
|
+
public readonly level: 'error' | 'warn';
|
|
54
|
+
public readonly details: EdgeStoreErrorDetails<TCode>;
|
|
11
55
|
|
|
12
|
-
constructor(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
56
|
+
constructor(
|
|
57
|
+
opts: {
|
|
58
|
+
message: string;
|
|
59
|
+
code: TCode;
|
|
60
|
+
cause?: Error;
|
|
61
|
+
} & (EdgeStoreErrorDetails<TCode> extends undefined
|
|
62
|
+
? object
|
|
63
|
+
: {
|
|
64
|
+
details: EdgeStoreErrorDetails<TCode>;
|
|
65
|
+
}),
|
|
66
|
+
) {
|
|
17
67
|
super(opts.message);
|
|
18
68
|
this.name = 'EdgeStoreError';
|
|
19
69
|
|
|
20
70
|
this.code = opts.code;
|
|
21
71
|
this.cause = opts.cause;
|
|
72
|
+
this.level = EDGE_STORE_ERROR_CODES[opts.code] >= 500 ? 'error' : 'warn';
|
|
73
|
+
this.details = 'details' in opts ? opts.details : undefined!;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
formattedMessage(): string {
|
|
77
|
+
return `EdgeStore${this.level === 'error' ? 'Error' : 'Info'}: ${
|
|
78
|
+
this.message
|
|
79
|
+
}${this.details ? `\n Details: ${JSON.stringify(this.details)}` : ''}${
|
|
80
|
+
this.cause ? `\n Caused by: ${this.cause.message}` : ''
|
|
81
|
+
}`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
formattedJson(): EdgeStoreJsonResponse {
|
|
85
|
+
return {
|
|
86
|
+
message:
|
|
87
|
+
this.code === 'SERVER_ERROR' ? 'Internal server error' : this.message,
|
|
88
|
+
code: this.code,
|
|
89
|
+
details: this.details as any,
|
|
90
|
+
} satisfies EdgeStoreJsonResponse;
|
|
22
91
|
}
|
|
23
92
|
}
|
|
24
93
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
|
|
3
|
+
const logLevel = ['debug', 'info', 'warn', 'error', 'none'] as const;
|
|
4
|
+
|
|
5
|
+
export type LogLevel = typeof logLevel[number];
|
|
6
|
+
|
|
7
|
+
class Logger {
|
|
8
|
+
private logLevel: LogLevel;
|
|
9
|
+
|
|
10
|
+
constructor(logLevel?: LogLevel) {
|
|
11
|
+
this.logLevel =
|
|
12
|
+
logLevel ?? process.env.NODE_ENV === 'production' ? 'error' : 'info';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
private shouldLog(level: LogLevel): boolean {
|
|
16
|
+
return logLevel.indexOf(level) >= logLevel.indexOf(this.logLevel);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
debug(message?: any, ...optionalParams: any[]): void {
|
|
20
|
+
if (this.shouldLog('debug')) {
|
|
21
|
+
console.debug(message, ...optionalParams);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
info(message?: any, ...optionalParams: any[]): void {
|
|
26
|
+
if (this.shouldLog('info')) {
|
|
27
|
+
console.info(message, ...optionalParams);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
warn(message?: any, ...optionalParams: any[]): void {
|
|
32
|
+
if (this.shouldLog('warn')) {
|
|
33
|
+
console.warn(message, ...optionalParams);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
error(message?: any, ...optionalParams: any[]): void {
|
|
38
|
+
if (this.shouldLog('error')) {
|
|
39
|
+
console.error(message, ...optionalParams);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default Logger;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { BlobServiceClient } from '@azure/storage-blob';
|
|
2
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
+
import { type Provider } from '../types';
|
|
4
|
+
|
|
5
|
+
export type AzureProviderOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* The storage account name for Azure Blob Storage
|
|
8
|
+
* Can also be set via the `ES_AZURE_ACCOUNT_NAME` environment variable.
|
|
9
|
+
*/
|
|
10
|
+
storageAccountName?: string;
|
|
11
|
+
/**
|
|
12
|
+
* SAS token for Azure Blob Storage
|
|
13
|
+
* Can also be set via the `ES_AZURE_SAS_TOKEN` environment variable.
|
|
14
|
+
*/
|
|
15
|
+
sasToken?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Azure Blob Storage container name
|
|
18
|
+
* Can also be set via the `ES_AZURE_CONTAINER_NAME` environment variable.
|
|
19
|
+
*/
|
|
20
|
+
containerName?: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export function AzureProvider(options?: AzureProviderOptions): Provider {
|
|
24
|
+
const {
|
|
25
|
+
storageAccountName = process.env.ES_AZURE_ACCOUNT_NAME,
|
|
26
|
+
sasToken = process.env.ES_AZURE_SAS_TOKEN,
|
|
27
|
+
containerName = process.env.ES_AZURE_CONTAINER_NAME,
|
|
28
|
+
} = options ?? {};
|
|
29
|
+
|
|
30
|
+
const baseUrl = `https://${storageAccountName}.blob.core.windows.net`;
|
|
31
|
+
const blobServiceClient = new BlobServiceClient(`${baseUrl}?${sasToken}`);
|
|
32
|
+
const containerClient = blobServiceClient.getContainerClient(
|
|
33
|
+
containerName ?? '',
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
async init() {
|
|
38
|
+
return {};
|
|
39
|
+
},
|
|
40
|
+
getBaseUrl() {
|
|
41
|
+
return baseUrl;
|
|
42
|
+
},
|
|
43
|
+
async getFile({ url }) {
|
|
44
|
+
const blobClient = containerClient.getBlobClient(url);
|
|
45
|
+
|
|
46
|
+
const { contentLength, lastModified } = await blobClient.getProperties();
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
url: url,
|
|
50
|
+
metadata: {},
|
|
51
|
+
path: {},
|
|
52
|
+
size: contentLength ?? 0,
|
|
53
|
+
uploadedAt: lastModified ?? new Date(),
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
async requestUpload({ fileInfo }) {
|
|
57
|
+
const nameId = uuidv4();
|
|
58
|
+
const extension = fileInfo.extension
|
|
59
|
+
? `.${fileInfo.extension.replace('.', '')}`
|
|
60
|
+
: '';
|
|
61
|
+
const fileName = fileInfo.fileName ?? `${nameId}${extension}`;
|
|
62
|
+
|
|
63
|
+
const blobClient = containerClient.getBlobClient(fileName);
|
|
64
|
+
|
|
65
|
+
const url = blobClient.url;
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
uploadUrl: url,
|
|
69
|
+
accessUrl: url,
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
async requestUploadParts() {
|
|
73
|
+
throw new Error('Not implemented');
|
|
74
|
+
},
|
|
75
|
+
async completeMultipartUpload() {
|
|
76
|
+
throw new Error('Not implemented');
|
|
77
|
+
},
|
|
78
|
+
async confirmUpload() {
|
|
79
|
+
throw new Error('Not implemented');
|
|
80
|
+
},
|
|
81
|
+
async deleteFile({ url }) {
|
|
82
|
+
const blobClient = containerClient.getBlobClient(url);
|
|
83
|
+
await blobClient.delete();
|
|
84
|
+
return {
|
|
85
|
+
success: true,
|
|
86
|
+
};
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { initEdgeStoreSdk } from '../../core/sdk';
|
|
2
2
|
import EdgeStoreCredentialsError from '../../libs/errors/EdgeStoreCredentialsError';
|
|
3
|
+
import EdgeStoreError from '../../libs/errors/EdgeStoreError';
|
|
3
4
|
import { type Provider, type RequestUploadRes } from '../types';
|
|
4
5
|
|
|
5
6
|
const DEFAULT_BASE_URL = 'https://files.edgestore.dev';
|
|
@@ -111,7 +112,10 @@ export function EdgeStoreProvider(
|
|
|
111
112
|
thumbnailUrl: res.thumbnailUrl,
|
|
112
113
|
};
|
|
113
114
|
} else {
|
|
114
|
-
throw new
|
|
115
|
+
throw new EdgeStoreError({
|
|
116
|
+
message: 'Could not get upload url',
|
|
117
|
+
code: 'SERVER_ERROR',
|
|
118
|
+
});
|
|
115
119
|
}
|
|
116
120
|
}
|
|
117
121
|
const res = await edgeStoreSdk.requestUpload({
|
|
@@ -126,7 +130,10 @@ export function EdgeStoreProvider(
|
|
|
126
130
|
thumbnailUrl: res.thumbnailUrl,
|
|
127
131
|
};
|
|
128
132
|
}
|
|
129
|
-
throw new
|
|
133
|
+
throw new EdgeStoreError({
|
|
134
|
+
message: 'Could not get upload url',
|
|
135
|
+
code: 'SERVER_ERROR',
|
|
136
|
+
});
|
|
130
137
|
},
|
|
131
138
|
requestUploadParts: async ({ multipart, path }) => {
|
|
132
139
|
const res = await edgeStoreSdk.requestUploadParts({
|