@edgestore/react 0.1.5-alpha.1 → 0.1.5-alpha.12

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.
@@ -10,6 +10,13 @@ type EdgeStoreContextValue<TRouter extends AnyRouter> = {
10
10
  * Can be used after a sign-in or sign-out, for example.
11
11
  */
12
12
  reset: () => Promise<void>;
13
+ /**
14
+ * The current state of the Edge Store provider.
15
+ *
16
+ * You can use this to wait for the provider to be initialized
17
+ * before trying to show private images on your app.
18
+ */
19
+ state: ProviderState;
13
20
  };
14
21
  export declare function createEdgeStoreProvider<TRouter extends AnyRouter>(opts?: {
15
22
  /**
@@ -31,8 +38,21 @@ export declare function createEdgeStoreProvider<TRouter extends AnyRouter>(opts?
31
38
  * @example - If your app is hosted at `https://example.com/my-app`, you can set the `basePath` to `/my-app/api/edgestore`.
32
39
  */
33
40
  basePath?: string | undefined;
34
- }) => JSX.Element;
41
+ }) => React.JSX.Element;
35
42
  useEdgeStore: () => EdgeStoreContextValue<TRouter>;
36
43
  };
44
+ type ProviderState = {
45
+ loading: true;
46
+ initialized: false;
47
+ error: false;
48
+ } | {
49
+ loading: false;
50
+ initialized: false;
51
+ error: true;
52
+ } | {
53
+ loading: false;
54
+ initialized: true;
55
+ error: false;
56
+ };
37
57
  export {};
38
58
  //# sourceMappingURL=contextProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"contextProvider.d.ts","sourceRoot":"","sources":["../src/contextProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAK1E,KAAK,qBAAqB,CAAC,OAAO,SAAS,SAAS,IAAI;IACtD,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC;;;;;OAKG;IACH,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,OAAO,SAAS,SAAS,EAAE,IAAI,CAAC,EAAE;IACxE;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;;kBASa,MAAM,SAAS;QACzB;;;;;;WAMG;;;;EAgCN"}
1
+ {"version":3,"file":"contextProvider.d.ts","sourceRoot":"","sources":["../src/contextProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAU1E,KAAK,qBAAqB,CAAC,OAAO,SAAS,SAAS,IAAI;IACtD,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC;;;;;OAKG;IACH,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B;;;;;OAKG;IACH,KAAK,EAAE,aAAa,CAAC;CACtB,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,OAAO,SAAS,SAAS,EAAE,IAAI,CAAC,EAAE;IACxE;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;;kBASa,MAAM,SAAS;QACzB;;;;;;WAMG;;;;EAgCN;AAED,KAAK,aAAa,GACd;IACE,OAAO,EAAE,IAAI,CAAC;IACd,WAAW,EAAE,KAAK,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;CACd,GACD;IACE,OAAO,EAAE,KAAK,CAAC;IACf,WAAW,EAAE,KAAK,CAAC;IACnB,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,OAAO,EAAE,KAAK,CAAC;IACf,WAAW,EAAE,IAAI,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;CACd,CAAC"}
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- import { type AnyRouter, type InferBucketPathObject, type InferMetadataObject } from '@edgestore/server/core';
2
+ import { type AnyRouter, type InferBucketPathObject, type InferMetadataObject, type UploadOptions } from '@edgestore/server/core';
3
3
  import { type z } from 'zod';
4
4
  /**
5
5
  * @internal
@@ -44,35 +44,6 @@ export type BucketFunctions<TRouter extends AnyRouter> = {
44
44
  };
45
45
  };
46
46
  type OnProgressChangeHandler = (progress: number) => void;
47
- type UploadOptions = {
48
- /**
49
- * e.g. 'my-file-name.jpg'
50
- *
51
- * By default, a unique file name will be generated for each upload.
52
- * If you want to use a custom file name, you can use this option.
53
- * If you use the same file name for multiple uploads, the previous file will be overwritten.
54
- * But it might take some time for the CDN cache to be cleared.
55
- * So maybe you will keep seeing the old file for a while.
56
- *
57
- * If you want to replace an existing file immediately leave the `manualFileName` option empty and use the `replaceTargetUrl` option.
58
- */
59
- manualFileName?: string;
60
- /**
61
- * Use this to replace an existing file.
62
- * It will automatically delete the existing file when the upload is complete.
63
- */
64
- replaceTargetUrl?: string;
65
- /**
66
- * If true, the file needs to be confirmed by using the `confirmUpload` function.
67
- * If the file is not confirmed within 24 hours, it will be deleted.
68
- *
69
- * This is useful for pages where the file is uploaded as soon as it is selected,
70
- * but the user can leave the page without submitting the form.
71
- *
72
- * This avoids unnecessary zombie files in the bucket.
73
- */
74
- temporary?: boolean;
75
- };
76
47
  export declare function createNextProxy<TRouter extends AnyRouter>({ apiPath, uploadingCountRef, maxConcurrentUploads, }: {
77
48
  apiPath: string;
78
49
  uploadingCountRef: React.MutableRefObject<number>;
@@ -1 +1 @@
1
- {"version":3,"file":"createNextProxy.d.ts","sourceRoot":"","sources":["../src/createNextProxy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"createNextProxy.d.ts","sourceRoot":"","sources":["../src/createNextProxy.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var React = require('react');
6
+ var core = require('@edgestore/server/core');
6
7
 
7
8
  function _interopNamespace(e) {
8
9
  if (e && e.__esModule) return e;
@@ -24,13 +25,24 @@ function _interopNamespace(e) {
24
25
 
25
26
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
26
27
 
27
- class EdgeStoreError extends Error {
28
+ class EdgeStoreClientError extends Error {
28
29
  constructor(message){
29
30
  super(message);
30
31
  this.name = 'EdgeStoreError';
31
32
  }
32
33
  }
33
34
 
35
+ async function handleError(res) {
36
+ try {
37
+ const json = await res.json();
38
+ throw new core.EdgeStoreApiClientError({
39
+ response: json
40
+ });
41
+ } catch (err) {
42
+ throw new EdgeStoreClientError(`Failed to parse response. Make sure the api is correctly configured at ${res.url}`);
43
+ }
44
+ }
45
+
34
46
  function createNextProxy({ apiPath, uploadingCountRef, maxConcurrentUploads = 5 }) {
35
47
  return new Proxy({}, {
36
48
  get (_, prop) {
@@ -57,7 +69,7 @@ function createNextProxy({ apiPath, uploadingCountRef, maxConcurrentUploads = 5
57
69
  apiPath
58
70
  });
59
71
  if (!success) {
60
- throw new EdgeStoreError('Failed to confirm upload');
72
+ throw new EdgeStoreClientError('Failed to confirm upload');
61
73
  }
62
74
  },
63
75
  delete: async (params)=>{
@@ -66,7 +78,7 @@ function createNextProxy({ apiPath, uploadingCountRef, maxConcurrentUploads = 5
66
78
  apiPath
67
79
  });
68
80
  if (!success) {
69
- throw new EdgeStoreError('Failed to delete file');
81
+ throw new EdgeStoreClientError('Failed to delete file');
70
82
  }
71
83
  }
72
84
  };
@@ -95,6 +107,9 @@ async function uploadFile({ file, input, onProgressChange, options }, { apiPath,
95
107
  'Content-Type': 'application/json'
96
108
  }
97
109
  });
110
+ if (!res.ok) {
111
+ await handleError(res);
112
+ }
98
113
  const json = await res.json();
99
114
  if ('multipart' in json) {
100
115
  await multipartUpload({
@@ -109,7 +124,7 @@ async function uploadFile({ file, input, onProgressChange, options }, { apiPath,
109
124
  // Upload the file to the signed URL and get the progress
110
125
  await uploadFileInner(file, json.uploadUrl, onProgressChange);
111
126
  } else {
112
- throw new EdgeStoreError('An error occurred');
127
+ throw new EdgeStoreClientError('An error occurred');
113
128
  }
114
129
  return {
115
130
  url: getUrl(json.accessUrl, apiPath),
@@ -130,7 +145,8 @@ async function uploadFile({ file, input, onProgressChange, options }, { apiPath,
130
145
  * Since third party cookies doesn't work on localhost,
131
146
  * we need to proxy the file through the server.
132
147
  */ function getUrl(url, apiPath) {
133
- if (process.env.NODE_ENV === 'development' && !url.includes('/_public/')) {
148
+ const mode = process !== undefined ? process.env.NODE_ENV : undefined?.DEV ? 'development' : 'production';
149
+ if (mode === 'development' && !url.includes('/_public/')) {
134
150
  const proxyUrl = new URL(window.location.origin);
135
151
  proxyUrl.pathname = `${apiPath}/proxy-file`;
136
152
  proxyUrl.search = new URLSearchParams({
@@ -144,6 +160,8 @@ const uploadFileInner = async (file, uploadUrl, onProgressChange)=>{
144
160
  const promise = new Promise((resolve, reject)=>{
145
161
  const request = new XMLHttpRequest();
146
162
  request.open('PUT', uploadUrl);
163
+ // This is for Azure provider. Specifies the blob type
164
+ request.setRequestHeader('x-ms-blob-type', 'BlockBlob');
147
165
  request.addEventListener('loadstart', ()=>{
148
166
  onProgressChange?.(0);
149
167
  });
@@ -189,7 +207,7 @@ async function multipartUpload(params) {
189
207
  onProgressChange?.(totalProgress);
190
208
  });
191
209
  if (!eTag) {
192
- throw new EdgeStoreError('Could not get ETag from multipart response');
210
+ throw new EdgeStoreClientError('Could not get ETag from multipart response');
193
211
  }
194
212
  return {
195
213
  partNumber: part.partNumber,
@@ -220,7 +238,7 @@ async function multipartUpload(params) {
220
238
  }
221
239
  });
222
240
  if (!res.ok) {
223
- throw new EdgeStoreError('Multi-part upload failed');
241
+ await handleError(res);
224
242
  }
225
243
  }
226
244
  async function confirmUpload({ url }, { apiPath, bucketName }) {
@@ -235,7 +253,7 @@ async function confirmUpload({ url }, { apiPath, bucketName }) {
235
253
  }
236
254
  });
237
255
  if (!res.ok) {
238
- throw new EdgeStoreError('An error occurred');
256
+ await handleError(res);
239
257
  }
240
258
  return res.json();
241
259
  }
@@ -251,7 +269,7 @@ async function deleteFile({ url }, { apiPath, bucketName }) {
251
269
  }
252
270
  });
253
271
  if (!res.ok) {
254
- throw new EdgeStoreError('An error occurred');
272
+ await handleError(res);
255
273
  }
256
274
  return res.json();
257
275
  }
@@ -293,7 +311,7 @@ async function queuedPromises({ items, fn, maxParallel, maxRetries = 0 }) {
293
311
  return results;
294
312
  }
295
313
 
296
- const DEFAULT_BASE_URL = process.env.NEXT_PUBLIC_EDGE_STORE_BASE_URL ?? 'https://files.edgestore.dev';
314
+ const DEFAULT_BASE_URL = (process !== undefined ? process.env.NEXT_PUBLIC_EDGE_STORE_BASE_URL : undefined?.EDGE_STORE_BASE_URL) ?? 'https://files.edgestore.dev';
297
315
  function createEdgeStoreProvider(opts) {
298
316
  const EdgeStoreContext = /*#__PURE__*/ React__namespace.createContext(undefined);
299
317
  const EdgeStoreProvider = ({ children, basePath })=>{
@@ -322,23 +340,71 @@ function createEdgeStoreProvider(opts) {
322
340
  }
323
341
  function EdgeStoreProviderInner({ children, context, basePath, maxConcurrentUploads }) {
324
342
  const apiPath = basePath ? `${basePath}` : '/api/edgestore';
343
+ const [state, setState] = React__namespace.useState({
344
+ loading: true,
345
+ initialized: false,
346
+ error: false
347
+ });
325
348
  const uploadingCountRef = React__namespace.useRef(0);
349
+ const initExecuted = React__namespace.useRef(false); // to make sure we don't run init twice
326
350
  React__namespace.useEffect(()=>{
327
- void init();
351
+ if (!initExecuted.current) {
352
+ void init();
353
+ }
354
+ return ()=>{
355
+ initExecuted.current = true;
356
+ };
328
357
  // eslint-disable-next-line react-hooks/exhaustive-deps
329
358
  }, []);
330
359
  async function init() {
331
- const res = await fetch(`${apiPath}/init`, {
332
- method: 'POST'
333
- });
334
- if (res.ok) {
335
- const json = await res.json();
336
- await fetch(`${DEFAULT_BASE_URL}/_init`, {
337
- method: 'GET',
338
- headers: {
339
- 'x-edgestore-token': json.token
360
+ try {
361
+ setState({
362
+ loading: true,
363
+ initialized: false,
364
+ error: false
365
+ });
366
+ const res = await fetch(`${apiPath}/init`, {
367
+ method: 'POST'
368
+ });
369
+ if (res.ok) {
370
+ const json = await res.json();
371
+ const innerRes = await fetch(`${DEFAULT_BASE_URL}/_init`, {
372
+ method: 'GET',
373
+ credentials: 'include',
374
+ headers: {
375
+ 'x-edgestore-token': json.token
376
+ }
377
+ });
378
+ if (innerRes.ok) {
379
+ // update state
380
+ setState({
381
+ loading: false,
382
+ initialized: true,
383
+ error: false
384
+ });
385
+ } else {
386
+ setState({
387
+ loading: false,
388
+ initialized: false,
389
+ error: true
390
+ });
391
+ throw new EdgeStoreClientError("Couldn't initialize Edge Store.");
340
392
  }
393
+ } else {
394
+ setState({
395
+ loading: false,
396
+ initialized: false,
397
+ error: true
398
+ });
399
+ await handleError(res);
400
+ }
401
+ } catch (err) {
402
+ setState({
403
+ loading: false,
404
+ initialized: false,
405
+ error: true
341
406
  });
407
+ throw err;
342
408
  }
343
409
  }
344
410
  async function reset() {
@@ -351,7 +417,8 @@ function EdgeStoreProviderInner({ children, context, basePath, maxConcurrentUplo
351
417
  uploadingCountRef,
352
418
  maxConcurrentUploads
353
419
  }),
354
- reset
420
+ reset,
421
+ state
355
422
  }
356
423
  }, children));
357
424
  }
package/dist/index.mjs CHANGED
@@ -1,12 +1,24 @@
1
1
  import * as React from 'react';
2
+ import { EdgeStoreApiClientError } from '@edgestore/server/core';
2
3
 
3
- class EdgeStoreError extends Error {
4
+ class EdgeStoreClientError extends Error {
4
5
  constructor(message){
5
6
  super(message);
6
7
  this.name = 'EdgeStoreError';
7
8
  }
8
9
  }
9
10
 
11
+ async function handleError(res) {
12
+ try {
13
+ const json = await res.json();
14
+ throw new EdgeStoreApiClientError({
15
+ response: json
16
+ });
17
+ } catch (err) {
18
+ throw new EdgeStoreClientError(`Failed to parse response. Make sure the api is correctly configured at ${res.url}`);
19
+ }
20
+ }
21
+
10
22
  function createNextProxy({ apiPath, uploadingCountRef, maxConcurrentUploads = 5 }) {
11
23
  return new Proxy({}, {
12
24
  get (_, prop) {
@@ -33,7 +45,7 @@ function createNextProxy({ apiPath, uploadingCountRef, maxConcurrentUploads = 5
33
45
  apiPath
34
46
  });
35
47
  if (!success) {
36
- throw new EdgeStoreError('Failed to confirm upload');
48
+ throw new EdgeStoreClientError('Failed to confirm upload');
37
49
  }
38
50
  },
39
51
  delete: async (params)=>{
@@ -42,7 +54,7 @@ function createNextProxy({ apiPath, uploadingCountRef, maxConcurrentUploads = 5
42
54
  apiPath
43
55
  });
44
56
  if (!success) {
45
- throw new EdgeStoreError('Failed to delete file');
57
+ throw new EdgeStoreClientError('Failed to delete file');
46
58
  }
47
59
  }
48
60
  };
@@ -71,6 +83,9 @@ async function uploadFile({ file, input, onProgressChange, options }, { apiPath,
71
83
  'Content-Type': 'application/json'
72
84
  }
73
85
  });
86
+ if (!res.ok) {
87
+ await handleError(res);
88
+ }
74
89
  const json = await res.json();
75
90
  if ('multipart' in json) {
76
91
  await multipartUpload({
@@ -85,7 +100,7 @@ async function uploadFile({ file, input, onProgressChange, options }, { apiPath,
85
100
  // Upload the file to the signed URL and get the progress
86
101
  await uploadFileInner(file, json.uploadUrl, onProgressChange);
87
102
  } else {
88
- throw new EdgeStoreError('An error occurred');
103
+ throw new EdgeStoreClientError('An error occurred');
89
104
  }
90
105
  return {
91
106
  url: getUrl(json.accessUrl, apiPath),
@@ -106,7 +121,8 @@ async function uploadFile({ file, input, onProgressChange, options }, { apiPath,
106
121
  * Since third party cookies doesn't work on localhost,
107
122
  * we need to proxy the file through the server.
108
123
  */ function getUrl(url, apiPath) {
109
- if (process.env.NODE_ENV === 'development' && !url.includes('/_public/')) {
124
+ const mode = process !== undefined ? process.env.NODE_ENV : import.meta.env?.DEV ? 'development' : 'production';
125
+ if (mode === 'development' && !url.includes('/_public/')) {
110
126
  const proxyUrl = new URL(window.location.origin);
111
127
  proxyUrl.pathname = `${apiPath}/proxy-file`;
112
128
  proxyUrl.search = new URLSearchParams({
@@ -120,6 +136,8 @@ const uploadFileInner = async (file, uploadUrl, onProgressChange)=>{
120
136
  const promise = new Promise((resolve, reject)=>{
121
137
  const request = new XMLHttpRequest();
122
138
  request.open('PUT', uploadUrl);
139
+ // This is for Azure provider. Specifies the blob type
140
+ request.setRequestHeader('x-ms-blob-type', 'BlockBlob');
123
141
  request.addEventListener('loadstart', ()=>{
124
142
  onProgressChange?.(0);
125
143
  });
@@ -165,7 +183,7 @@ async function multipartUpload(params) {
165
183
  onProgressChange?.(totalProgress);
166
184
  });
167
185
  if (!eTag) {
168
- throw new EdgeStoreError('Could not get ETag from multipart response');
186
+ throw new EdgeStoreClientError('Could not get ETag from multipart response');
169
187
  }
170
188
  return {
171
189
  partNumber: part.partNumber,
@@ -196,7 +214,7 @@ async function multipartUpload(params) {
196
214
  }
197
215
  });
198
216
  if (!res.ok) {
199
- throw new EdgeStoreError('Multi-part upload failed');
217
+ await handleError(res);
200
218
  }
201
219
  }
202
220
  async function confirmUpload({ url }, { apiPath, bucketName }) {
@@ -211,7 +229,7 @@ async function confirmUpload({ url }, { apiPath, bucketName }) {
211
229
  }
212
230
  });
213
231
  if (!res.ok) {
214
- throw new EdgeStoreError('An error occurred');
232
+ await handleError(res);
215
233
  }
216
234
  return res.json();
217
235
  }
@@ -227,7 +245,7 @@ async function deleteFile({ url }, { apiPath, bucketName }) {
227
245
  }
228
246
  });
229
247
  if (!res.ok) {
230
- throw new EdgeStoreError('An error occurred');
248
+ await handleError(res);
231
249
  }
232
250
  return res.json();
233
251
  }
@@ -269,7 +287,7 @@ async function queuedPromises({ items, fn, maxParallel, maxRetries = 0 }) {
269
287
  return results;
270
288
  }
271
289
 
272
- const DEFAULT_BASE_URL = process.env.NEXT_PUBLIC_EDGE_STORE_BASE_URL ?? 'https://files.edgestore.dev';
290
+ const DEFAULT_BASE_URL = (process !== undefined ? process.env.NEXT_PUBLIC_EDGE_STORE_BASE_URL : import.meta.env?.EDGE_STORE_BASE_URL) ?? 'https://files.edgestore.dev';
273
291
  function createEdgeStoreProvider(opts) {
274
292
  const EdgeStoreContext = /*#__PURE__*/ React.createContext(undefined);
275
293
  const EdgeStoreProvider = ({ children, basePath })=>{
@@ -298,23 +316,71 @@ function createEdgeStoreProvider(opts) {
298
316
  }
299
317
  function EdgeStoreProviderInner({ children, context, basePath, maxConcurrentUploads }) {
300
318
  const apiPath = basePath ? `${basePath}` : '/api/edgestore';
319
+ const [state, setState] = React.useState({
320
+ loading: true,
321
+ initialized: false,
322
+ error: false
323
+ });
301
324
  const uploadingCountRef = React.useRef(0);
325
+ const initExecuted = React.useRef(false); // to make sure we don't run init twice
302
326
  React.useEffect(()=>{
303
- void init();
327
+ if (!initExecuted.current) {
328
+ void init();
329
+ }
330
+ return ()=>{
331
+ initExecuted.current = true;
332
+ };
304
333
  // eslint-disable-next-line react-hooks/exhaustive-deps
305
334
  }, []);
306
335
  async function init() {
307
- const res = await fetch(`${apiPath}/init`, {
308
- method: 'POST'
309
- });
310
- if (res.ok) {
311
- const json = await res.json();
312
- await fetch(`${DEFAULT_BASE_URL}/_init`, {
313
- method: 'GET',
314
- headers: {
315
- 'x-edgestore-token': json.token
336
+ try {
337
+ setState({
338
+ loading: true,
339
+ initialized: false,
340
+ error: false
341
+ });
342
+ const res = await fetch(`${apiPath}/init`, {
343
+ method: 'POST'
344
+ });
345
+ if (res.ok) {
346
+ const json = await res.json();
347
+ const innerRes = await fetch(`${DEFAULT_BASE_URL}/_init`, {
348
+ method: 'GET',
349
+ credentials: 'include',
350
+ headers: {
351
+ 'x-edgestore-token': json.token
352
+ }
353
+ });
354
+ if (innerRes.ok) {
355
+ // update state
356
+ setState({
357
+ loading: false,
358
+ initialized: true,
359
+ error: false
360
+ });
361
+ } else {
362
+ setState({
363
+ loading: false,
364
+ initialized: false,
365
+ error: true
366
+ });
367
+ throw new EdgeStoreClientError("Couldn't initialize Edge Store.");
316
368
  }
369
+ } else {
370
+ setState({
371
+ loading: false,
372
+ initialized: false,
373
+ error: true
374
+ });
375
+ await handleError(res);
376
+ }
377
+ } catch (err) {
378
+ setState({
379
+ loading: false,
380
+ initialized: false,
381
+ error: true
317
382
  });
383
+ throw err;
318
384
  }
319
385
  }
320
386
  async function reset() {
@@ -327,7 +393,8 @@ function EdgeStoreProviderInner({ children, context, basePath, maxConcurrentUplo
327
393
  uploadingCountRef,
328
394
  maxConcurrentUploads
329
395
  }),
330
- reset
396
+ reset,
397
+ state
331
398
  }
332
399
  }, children));
333
400
  }
@@ -0,0 +1,5 @@
1
+ declare class EdgeStoreClientError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export default EdgeStoreClientError;
5
+ //# sourceMappingURL=EdgeStoreClientError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EdgeStoreClientError.d.ts","sourceRoot":"","sources":["../../../src/libs/errors/EdgeStoreClientError.ts"],"names":[],"mappings":"AAAA,cAAM,oBAAqB,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED,eAAe,oBAAoB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function handleError(res: Response): Promise<never>;
2
+ //# sourceMappingURL=handleError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handleError.d.ts","sourceRoot":"","sources":["../../../src/libs/errors/handleError.ts"],"names":[],"mappings":"AAGA,wBAAsB,WAAW,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAS/D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edgestore/react",
3
- "version": "0.1.5-alpha.1",
3
+ "version": "0.1.5-alpha.12",
4
4
  "description": "Upload files with ease from React/Next.js",
5
5
  "homepage": "https://edgestore.dev",
6
6
  "repository": "https://github.com/edgestorejs/edgestore.git",
@@ -60,14 +60,14 @@
60
60
  "uuid": "^9.0.0"
61
61
  },
62
62
  "peerDependencies": {
63
- "@edgestore/server": "0.1.5-alpha.1",
63
+ "@edgestore/server": "0.1.5-alpha.12",
64
64
  "next": "*",
65
65
  "react": ">=16.8.0",
66
66
  "react-dom": ">=16.8.0",
67
67
  "zod": ">=3.0.0"
68
68
  },
69
69
  "devDependencies": {
70
- "@edgestore/server": "0.1.5-alpha.1",
70
+ "@edgestore/server": "0.1.5-alpha.12",
71
71
  "@types/cookie": "^0.5.1",
72
72
  "@types/node": "^18.11.18",
73
73
  "@types/uuid": "^9.0.1",
@@ -77,5 +77,5 @@
77
77
  "typescript": "^5.1.6",
78
78
  "zod": "^3.21.4"
79
79
  },
80
- "gitHead": "94b31fd879a0f4f9ed13cc08c9646e29d03c3f92"
80
+ "gitHead": "ddd35396955072690b24e55c37f6423445d26644"
81
81
  }
@@ -1,9 +1,14 @@
1
1
  import { type AnyRouter } from '@edgestore/server/core';
2
2
  import * as React from 'react';
3
3
  import { createNextProxy, type BucketFunctions } from './createNextProxy';
4
+ import EdgeStoreClientError from './libs/errors/EdgeStoreClientError';
5
+ import { handleError } from './libs/errors/handleError';
4
6
 
5
7
  const DEFAULT_BASE_URL =
6
- process.env.NEXT_PUBLIC_EDGE_STORE_BASE_URL ?? 'https://files.edgestore.dev';
8
+ (process !== undefined
9
+ ? process.env.NEXT_PUBLIC_EDGE_STORE_BASE_URL
10
+ : // @ts-expect-error - In Vite, the env variables are available on `import.meta`.
11
+ import.meta.env?.EDGE_STORE_BASE_URL) ?? 'https://files.edgestore.dev';
7
12
 
8
13
  type EdgeStoreContextValue<TRouter extends AnyRouter> = {
9
14
  edgestore: BucketFunctions<TRouter>;
@@ -14,6 +19,13 @@ type EdgeStoreContextValue<TRouter extends AnyRouter> = {
14
19
  * Can be used after a sign-in or sign-out, for example.
15
20
  */
16
21
  reset: () => Promise<void>;
22
+ /**
23
+ * The current state of the Edge Store provider.
24
+ *
25
+ * You can use this to wait for the provider to be initialized
26
+ * before trying to show private images on your app.
27
+ */
28
+ state: ProviderState;
17
29
  };
18
30
 
19
31
  export function createEdgeStoreProvider<TRouter extends AnyRouter>(opts?: {
@@ -75,6 +87,23 @@ export function createEdgeStoreProvider<TRouter extends AnyRouter>(opts?: {
75
87
  };
76
88
  }
77
89
 
90
+ type ProviderState =
91
+ | {
92
+ loading: true;
93
+ initialized: false;
94
+ error: false;
95
+ }
96
+ | {
97
+ loading: false;
98
+ initialized: false;
99
+ error: true;
100
+ }
101
+ | {
102
+ loading: false;
103
+ initialized: true;
104
+ error: false;
105
+ };
106
+
78
107
  function EdgeStoreProviderInner<TRouter extends AnyRouter>({
79
108
  children,
80
109
  context,
@@ -87,24 +116,73 @@ function EdgeStoreProviderInner<TRouter extends AnyRouter>({
87
116
  maxConcurrentUploads?: number;
88
117
  }) {
89
118
  const apiPath = basePath ? `${basePath}` : '/api/edgestore';
119
+ const [state, setState] = React.useState<ProviderState>({
120
+ loading: true,
121
+ initialized: false,
122
+ error: false,
123
+ });
90
124
  const uploadingCountRef = React.useRef(0);
125
+ const initExecuted = React.useRef(false); // to make sure we don't run init twice
91
126
  React.useEffect(() => {
92
- void init();
127
+ if (!initExecuted.current) {
128
+ void init();
129
+ }
130
+
131
+ return () => {
132
+ initExecuted.current = true;
133
+ };
93
134
  // eslint-disable-next-line react-hooks/exhaustive-deps
94
135
  }, []);
95
136
 
96
137
  async function init() {
97
- const res = await fetch(`${apiPath}/init`, {
98
- method: 'POST',
99
- });
100
- if (res.ok) {
101
- const json = await res.json();
102
- await fetch(`${DEFAULT_BASE_URL}/_init`, {
103
- method: 'GET',
104
- headers: {
105
- 'x-edgestore-token': json.token,
106
- },
138
+ try {
139
+ setState({
140
+ loading: true,
141
+ initialized: false,
142
+ error: false,
143
+ });
144
+ const res = await fetch(`${apiPath}/init`, {
145
+ method: 'POST',
146
+ });
147
+ if (res.ok) {
148
+ const json = await res.json();
149
+ const innerRes = await fetch(`${DEFAULT_BASE_URL}/_init`, {
150
+ method: 'GET',
151
+ credentials: 'include',
152
+ headers: {
153
+ 'x-edgestore-token': json.token,
154
+ },
155
+ });
156
+ if (innerRes.ok) {
157
+ // update state
158
+ setState({
159
+ loading: false,
160
+ initialized: true,
161
+ error: false,
162
+ });
163
+ } else {
164
+ setState({
165
+ loading: false,
166
+ initialized: false,
167
+ error: true,
168
+ });
169
+ throw new EdgeStoreClientError("Couldn't initialize Edge Store.");
170
+ }
171
+ } else {
172
+ setState({
173
+ loading: false,
174
+ initialized: false,
175
+ error: true,
176
+ });
177
+ await handleError(res);
178
+ }
179
+ } catch (err) {
180
+ setState({
181
+ loading: false,
182
+ initialized: false,
183
+ error: true,
107
184
  });
185
+ throw err;
108
186
  }
109
187
  }
110
188
 
@@ -122,6 +200,7 @@ function EdgeStoreProviderInner<TRouter extends AnyRouter>({
122
200
  maxConcurrentUploads,
123
201
  }),
124
202
  reset,
203
+ state,
125
204
  }}
126
205
  >
127
206
  {children}
@@ -3,9 +3,11 @@ import {
3
3
  type AnyRouter,
4
4
  type InferBucketPathObject,
5
5
  type InferMetadataObject,
6
+ type UploadOptions,
6
7
  } from '@edgestore/server/core';
7
8
  import { type z } from 'zod';
8
- import EdgeStoreError from './libs/errors/EdgeStoreError';
9
+ import EdgeStoreClientError from './libs/errors/EdgeStoreClientError';
10
+ import { handleError } from './libs/errors/handleError';
9
11
 
10
12
  /**
11
13
  * @internal
@@ -62,36 +64,6 @@ export type BucketFunctions<TRouter extends AnyRouter> = {
62
64
 
63
65
  type OnProgressChangeHandler = (progress: number) => void;
64
66
 
65
- type UploadOptions = {
66
- /**
67
- * e.g. 'my-file-name.jpg'
68
- *
69
- * By default, a unique file name will be generated for each upload.
70
- * If you want to use a custom file name, you can use this option.
71
- * If you use the same file name for multiple uploads, the previous file will be overwritten.
72
- * But it might take some time for the CDN cache to be cleared.
73
- * So maybe you will keep seeing the old file for a while.
74
- *
75
- * If you want to replace an existing file immediately leave the `manualFileName` option empty and use the `replaceTargetUrl` option.
76
- */
77
- manualFileName?: string;
78
- /**
79
- * Use this to replace an existing file.
80
- * It will automatically delete the existing file when the upload is complete.
81
- */
82
- replaceTargetUrl?: string;
83
- /**
84
- * If true, the file needs to be confirmed by using the `confirmUpload` function.
85
- * If the file is not confirmed within 24 hours, it will be deleted.
86
- *
87
- * This is useful for pages where the file is uploaded as soon as it is selected,
88
- * but the user can leave the page without submitting the form.
89
- *
90
- * This avoids unnecessary zombie files in the bucket.
91
- */
92
- temporary?: boolean;
93
- };
94
-
95
67
  export function createNextProxy<TRouter extends AnyRouter>({
96
68
  apiPath,
97
69
  uploadingCountRef,
@@ -129,7 +101,7 @@ export function createNextProxy<TRouter extends AnyRouter>({
129
101
  apiPath,
130
102
  });
131
103
  if (!success) {
132
- throw new EdgeStoreError('Failed to confirm upload');
104
+ throw new EdgeStoreClientError('Failed to confirm upload');
133
105
  }
134
106
  },
135
107
  delete: async (params: { url: string }) => {
@@ -138,7 +110,7 @@ export function createNextProxy<TRouter extends AnyRouter>({
138
110
  apiPath,
139
111
  });
140
112
  if (!success) {
141
- throw new EdgeStoreError('Failed to delete file');
113
+ throw new EdgeStoreClientError('Failed to delete file');
142
114
  }
143
115
  },
144
116
  };
@@ -187,6 +159,9 @@ async function uploadFile(
187
159
  'Content-Type': 'application/json',
188
160
  },
189
161
  });
162
+ if (!res.ok) {
163
+ await handleError(res);
164
+ }
190
165
  const json = (await res.json()) as RequestUploadRes;
191
166
  if ('multipart' in json) {
192
167
  await multipartUpload({
@@ -201,7 +176,7 @@ async function uploadFile(
201
176
  // Upload the file to the signed URL and get the progress
202
177
  await uploadFileInner(file, json.uploadUrl, onProgressChange);
203
178
  } else {
204
- throw new EdgeStoreError('An error occurred');
179
+ throw new EdgeStoreClientError('An error occurred');
205
180
  }
206
181
  return {
207
182
  url: getUrl(json.accessUrl, apiPath),
@@ -226,7 +201,14 @@ async function uploadFile(
226
201
  * we need to proxy the file through the server.
227
202
  */
228
203
  function getUrl(url: string, apiPath: string) {
229
- if (process.env.NODE_ENV === 'development' && !url.includes('/_public/')) {
204
+ const mode =
205
+ process !== undefined
206
+ ? process.env.NODE_ENV
207
+ : // @ts-expect-error - DEV is injected by Vite
208
+ import.meta.env?.DEV
209
+ ? 'development'
210
+ : 'production';
211
+ if (mode === 'development' && !url.includes('/_public/')) {
230
212
  const proxyUrl = new URL(window.location.origin);
231
213
  proxyUrl.pathname = `${apiPath}/proxy-file`;
232
214
  proxyUrl.search = new URLSearchParams({
@@ -245,6 +227,8 @@ const uploadFileInner = async (
245
227
  const promise = new Promise<string | null>((resolve, reject) => {
246
228
  const request = new XMLHttpRequest();
247
229
  request.open('PUT', uploadUrl);
230
+ // This is for Azure provider. Specifies the blob type
231
+ request.setRequestHeader('x-ms-blob-type', 'BlockBlob');
248
232
  request.addEventListener('loadstart', () => {
249
233
  onProgressChange?.(0);
250
234
  });
@@ -310,7 +294,9 @@ async function multipartUpload(params: {
310
294
  onProgressChange?.(totalProgress);
311
295
  });
312
296
  if (!eTag) {
313
- throw new EdgeStoreError('Could not get ETag from multipart response');
297
+ throw new EdgeStoreClientError(
298
+ 'Could not get ETag from multipart response',
299
+ );
314
300
  }
315
301
  return {
316
302
  partNumber: part.partNumber,
@@ -346,7 +332,7 @@ async function multipartUpload(params: {
346
332
  },
347
333
  });
348
334
  if (!res.ok) {
349
- throw new EdgeStoreError('Multi-part upload failed');
335
+ await handleError(res);
350
336
  }
351
337
  }
352
338
 
@@ -375,7 +361,7 @@ async function confirmUpload(
375
361
  },
376
362
  });
377
363
  if (!res.ok) {
378
- throw new EdgeStoreError('An error occurred');
364
+ await handleError(res);
379
365
  }
380
366
  return res.json();
381
367
  }
@@ -405,7 +391,7 @@ async function deleteFile(
405
391
  },
406
392
  });
407
393
  if (!res.ok) {
408
- throw new EdgeStoreError('An error occurred');
394
+ await handleError(res);
409
395
  }
410
396
  return res.json();
411
397
  }
@@ -1,8 +1,8 @@
1
- class EdgeStoreError extends Error {
1
+ class EdgeStoreClientError extends Error {
2
2
  constructor(message: string) {
3
3
  super(message);
4
4
  this.name = 'EdgeStoreError';
5
5
  }
6
6
  }
7
7
 
8
- export default EdgeStoreError;
8
+ export default EdgeStoreClientError;
@@ -0,0 +1,13 @@
1
+ import { EdgeStoreApiClientError } from '@edgestore/server/core';
2
+ import EdgeStoreClientError from './EdgeStoreClientError';
3
+
4
+ export async function handleError(res: Response): Promise<never> {
5
+ try {
6
+ const json = await res.json();
7
+ throw new EdgeStoreApiClientError({ response: json });
8
+ } catch (err) {
9
+ throw new EdgeStoreClientError(
10
+ `Failed to parse response. Make sure the api is correctly configured at ${res.url}`,
11
+ );
12
+ }
13
+ }
@@ -1,5 +0,0 @@
1
- declare class EdgeStoreError extends Error {
2
- constructor(message: string);
3
- }
4
- export default EdgeStoreError;
5
- //# sourceMappingURL=EdgeStoreError.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EdgeStoreError.d.ts","sourceRoot":"","sources":["../../../src/libs/errors/EdgeStoreError.ts"],"names":[],"mappings":"AAAA,cAAM,cAAe,SAAQ,KAAK;gBACpB,OAAO,EAAE,MAAM;CAI5B;AAED,eAAe,cAAc,CAAC"}