@edgestore/react 0.1.5-alpha.8 → 0.1.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.
@@ -1,4 +1,4 @@
1
- import { type AnyRouter } from '@edgestore/server/core';
1
+ import { type AnyRouter } from '@edgestore/shared';
2
2
  import * as React from 'react';
3
3
  import { type BucketFunctions } from './createNextProxy';
4
4
  type EdgeStoreContextValue<TRouter extends AnyRouter> = {
@@ -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
  /**
@@ -34,5 +41,18 @@ export declare function createEdgeStoreProvider<TRouter extends AnyRouter>(opts?
34
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,mBAAmB,CAAC;AACnD,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, type UploadOptions } from '@edgestore/server/core';
2
+ import { type AnyRouter, type InferBucketPathObject, type InferMetadataObject, type UploadOptions } from '@edgestore/shared';
3
3
  import { type z } from 'zod';
4
4
  /**
5
5
  * @internal
@@ -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,7 +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
+ var shared = require('@edgestore/shared');
7
7
 
8
8
  function _interopNamespace(e) {
9
9
  if (e && e.__esModule) return e;
@@ -32,6 +32,18 @@ class EdgeStoreClientError extends Error {
32
32
  }
33
33
  }
34
34
 
35
+ async function handleError(res) {
36
+ let json = {};
37
+ try {
38
+ json = await res.json();
39
+ } catch (err) {
40
+ throw new EdgeStoreClientError(`Failed to parse response. Make sure the api is correctly configured at ${res.url}`);
41
+ }
42
+ throw new shared.EdgeStoreApiClientError({
43
+ response: json
44
+ });
45
+ }
46
+
35
47
  function createNextProxy({ apiPath, uploadingCountRef, maxConcurrentUploads = 5 }) {
36
48
  return new Proxy({}, {
37
49
  get (_, prop) {
@@ -44,10 +56,11 @@ function createNextProxy({ apiPath, uploadingCountRef, maxConcurrentUploads = 5
44
56
  await new Promise((resolve)=>setTimeout(resolve, 300));
45
57
  }
46
58
  uploadingCountRef.current++;
47
- return await uploadFile(params, {
59
+ const test = await uploadFile(params, {
48
60
  bucketName: bucketName,
49
61
  apiPath
50
62
  });
63
+ return test;
51
64
  } finally{
52
65
  uploadingCountRef.current--;
53
66
  }
@@ -80,6 +93,7 @@ async function uploadFile({ file, input, onProgressChange, options }, { apiPath,
80
93
  onProgressChange?.(0);
81
94
  const res = await fetch(`${apiPath}/request-upload`, {
82
95
  method: 'POST',
96
+ credentials: 'include',
83
97
  body: JSON.stringify({
84
98
  bucketName,
85
99
  input,
@@ -97,9 +111,7 @@ async function uploadFile({ file, input, onProgressChange, options }, { apiPath,
97
111
  }
98
112
  });
99
113
  if (!res.ok) {
100
- throw new core.EdgeStoreApiClientError({
101
- response: await res.json()
102
- });
114
+ await handleError(res);
103
115
  }
104
116
  const json = await res.json();
105
117
  if ('multipart' in json) {
@@ -136,7 +148,8 @@ async function uploadFile({ file, input, onProgressChange, options }, { apiPath,
136
148
  * Since third party cookies doesn't work on localhost,
137
149
  * we need to proxy the file through the server.
138
150
  */ function getUrl(url, apiPath) {
139
- if (process.env.NODE_ENV === 'development' && !url.includes('/_public/')) {
151
+ const mode = typeof process !== 'undefined' ? process.env.NODE_ENV : undefined?.DEV ? 'development' : 'production';
152
+ if (mode === 'development' && !url.includes('/_public/')) {
140
153
  const proxyUrl = new URL(window.location.origin);
141
154
  proxyUrl.pathname = `${apiPath}/proxy-file`;
142
155
  proxyUrl.search = new URLSearchParams({
@@ -217,6 +230,7 @@ async function multipartUpload(params) {
217
230
  // Complete multipart upload
218
231
  const res = await fetch(`${apiPath}/complete-multipart-upload`, {
219
232
  method: 'POST',
233
+ credentials: 'include',
220
234
  body: JSON.stringify({
221
235
  bucketName,
222
236
  uploadId,
@@ -228,14 +242,13 @@ async function multipartUpload(params) {
228
242
  }
229
243
  });
230
244
  if (!res.ok) {
231
- throw new core.EdgeStoreApiClientError({
232
- response: await res.json()
233
- });
245
+ await handleError(res);
234
246
  }
235
247
  }
236
248
  async function confirmUpload({ url }, { apiPath, bucketName }) {
237
249
  const res = await fetch(`${apiPath}/confirm-upload`, {
238
250
  method: 'POST',
251
+ credentials: 'include',
239
252
  body: JSON.stringify({
240
253
  url,
241
254
  bucketName
@@ -245,15 +258,14 @@ async function confirmUpload({ url }, { apiPath, bucketName }) {
245
258
  }
246
259
  });
247
260
  if (!res.ok) {
248
- throw new core.EdgeStoreApiClientError({
249
- response: await res.json()
250
- });
261
+ await handleError(res);
251
262
  }
252
263
  return res.json();
253
264
  }
254
265
  async function deleteFile({ url }, { apiPath, bucketName }) {
255
266
  const res = await fetch(`${apiPath}/delete-file`, {
256
267
  method: 'POST',
268
+ credentials: 'include',
257
269
  body: JSON.stringify({
258
270
  url,
259
271
  bucketName
@@ -263,9 +275,7 @@ async function deleteFile({ url }, { apiPath, bucketName }) {
263
275
  }
264
276
  });
265
277
  if (!res.ok) {
266
- throw new core.EdgeStoreApiClientError({
267
- response: await res.json()
268
- });
278
+ await handleError(res);
269
279
  }
270
280
  return res.json();
271
281
  }
@@ -307,7 +317,7 @@ async function queuedPromises({ items, fn, maxParallel, maxRetries = 0 }) {
307
317
  return results;
308
318
  }
309
319
 
310
- const DEFAULT_BASE_URL = process.env.NEXT_PUBLIC_EDGE_STORE_BASE_URL ?? 'https://files.edgestore.dev';
320
+ const DEFAULT_BASE_URL = (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_EDGE_STORE_BASE_URL : undefined?.EDGE_STORE_BASE_URL) ?? 'https://files.edgestore.dev';
311
321
  function createEdgeStoreProvider(opts) {
312
322
  const EdgeStoreContext = /*#__PURE__*/ React__namespace.createContext(undefined);
313
323
  const EdgeStoreProvider = ({ children, basePath })=>{
@@ -336,24 +346,72 @@ function createEdgeStoreProvider(opts) {
336
346
  }
337
347
  function EdgeStoreProviderInner({ children, context, basePath, maxConcurrentUploads }) {
338
348
  const apiPath = basePath ? `${basePath}` : '/api/edgestore';
349
+ const [state, setState] = React__namespace.useState({
350
+ loading: true,
351
+ initialized: false,
352
+ error: false
353
+ });
339
354
  const uploadingCountRef = React__namespace.useRef(0);
355
+ const initExecuted = React__namespace.useRef(false); // to make sure we don't run init twice
340
356
  React__namespace.useEffect(()=>{
341
- void init();
357
+ if (!initExecuted.current) {
358
+ void init();
359
+ }
360
+ return ()=>{
361
+ initExecuted.current = true;
362
+ };
342
363
  // eslint-disable-next-line react-hooks/exhaustive-deps
343
364
  }, []);
344
365
  async function init() {
345
- const res = await fetch(`${apiPath}/init`, {
346
- method: 'POST'
347
- });
348
- if (res.ok) {
349
- const json = await res.json();
350
- await fetch(`${DEFAULT_BASE_URL}/_init`, {
351
- method: 'GET',
352
- credentials: 'include',
353
- headers: {
354
- 'x-edgestore-token': json.token
366
+ try {
367
+ setState({
368
+ loading: true,
369
+ initialized: false,
370
+ error: false
371
+ });
372
+ const res = await fetch(`${apiPath}/init`, {
373
+ method: 'POST',
374
+ credentials: 'include'
375
+ });
376
+ if (res.ok) {
377
+ const json = await res.json();
378
+ const innerRes = await fetch(`${DEFAULT_BASE_URL}/_init`, {
379
+ method: 'GET',
380
+ credentials: 'include',
381
+ headers: {
382
+ 'x-edgestore-token': json.token
383
+ }
384
+ });
385
+ if (innerRes.ok) {
386
+ // update state
387
+ setState({
388
+ loading: false,
389
+ initialized: true,
390
+ error: false
391
+ });
392
+ } else {
393
+ setState({
394
+ loading: false,
395
+ initialized: false,
396
+ error: true
397
+ });
398
+ throw new EdgeStoreClientError("Couldn't initialize Edge Store.");
355
399
  }
400
+ } else {
401
+ setState({
402
+ loading: false,
403
+ initialized: false,
404
+ error: true
405
+ });
406
+ await handleError(res);
407
+ }
408
+ } catch (err) {
409
+ setState({
410
+ loading: false,
411
+ initialized: false,
412
+ error: true
356
413
  });
414
+ throw err;
357
415
  }
358
416
  }
359
417
  async function reset() {
@@ -366,7 +424,8 @@ function EdgeStoreProviderInner({ children, context, basePath, maxConcurrentUplo
366
424
  uploadingCountRef,
367
425
  maxConcurrentUploads
368
426
  }),
369
- reset
427
+ reset,
428
+ state
370
429
  }
371
430
  }, children));
372
431
  }
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { EdgeStoreApiClientError } from '@edgestore/server/core';
2
+ import { EdgeStoreApiClientError } from '@edgestore/shared';
3
3
 
4
4
  class EdgeStoreClientError extends Error {
5
5
  constructor(message){
@@ -8,6 +8,18 @@ class EdgeStoreClientError extends Error {
8
8
  }
9
9
  }
10
10
 
11
+ async function handleError(res) {
12
+ let json = {};
13
+ try {
14
+ json = await res.json();
15
+ } catch (err) {
16
+ throw new EdgeStoreClientError(`Failed to parse response. Make sure the api is correctly configured at ${res.url}`);
17
+ }
18
+ throw new EdgeStoreApiClientError({
19
+ response: json
20
+ });
21
+ }
22
+
11
23
  function createNextProxy({ apiPath, uploadingCountRef, maxConcurrentUploads = 5 }) {
12
24
  return new Proxy({}, {
13
25
  get (_, prop) {
@@ -20,10 +32,11 @@ function createNextProxy({ apiPath, uploadingCountRef, maxConcurrentUploads = 5
20
32
  await new Promise((resolve)=>setTimeout(resolve, 300));
21
33
  }
22
34
  uploadingCountRef.current++;
23
- return await uploadFile(params, {
35
+ const test = await uploadFile(params, {
24
36
  bucketName: bucketName,
25
37
  apiPath
26
38
  });
39
+ return test;
27
40
  } finally{
28
41
  uploadingCountRef.current--;
29
42
  }
@@ -56,6 +69,7 @@ async function uploadFile({ file, input, onProgressChange, options }, { apiPath,
56
69
  onProgressChange?.(0);
57
70
  const res = await fetch(`${apiPath}/request-upload`, {
58
71
  method: 'POST',
72
+ credentials: 'include',
59
73
  body: JSON.stringify({
60
74
  bucketName,
61
75
  input,
@@ -73,9 +87,7 @@ async function uploadFile({ file, input, onProgressChange, options }, { apiPath,
73
87
  }
74
88
  });
75
89
  if (!res.ok) {
76
- throw new EdgeStoreApiClientError({
77
- response: await res.json()
78
- });
90
+ await handleError(res);
79
91
  }
80
92
  const json = await res.json();
81
93
  if ('multipart' in json) {
@@ -112,7 +124,8 @@ async function uploadFile({ file, input, onProgressChange, options }, { apiPath,
112
124
  * Since third party cookies doesn't work on localhost,
113
125
  * we need to proxy the file through the server.
114
126
  */ function getUrl(url, apiPath) {
115
- if (process.env.NODE_ENV === 'development' && !url.includes('/_public/')) {
127
+ const mode = typeof process !== 'undefined' ? process.env.NODE_ENV : import.meta.env?.DEV ? 'development' : 'production';
128
+ if (mode === 'development' && !url.includes('/_public/')) {
116
129
  const proxyUrl = new URL(window.location.origin);
117
130
  proxyUrl.pathname = `${apiPath}/proxy-file`;
118
131
  proxyUrl.search = new URLSearchParams({
@@ -193,6 +206,7 @@ async function multipartUpload(params) {
193
206
  // Complete multipart upload
194
207
  const res = await fetch(`${apiPath}/complete-multipart-upload`, {
195
208
  method: 'POST',
209
+ credentials: 'include',
196
210
  body: JSON.stringify({
197
211
  bucketName,
198
212
  uploadId,
@@ -204,14 +218,13 @@ async function multipartUpload(params) {
204
218
  }
205
219
  });
206
220
  if (!res.ok) {
207
- throw new EdgeStoreApiClientError({
208
- response: await res.json()
209
- });
221
+ await handleError(res);
210
222
  }
211
223
  }
212
224
  async function confirmUpload({ url }, { apiPath, bucketName }) {
213
225
  const res = await fetch(`${apiPath}/confirm-upload`, {
214
226
  method: 'POST',
227
+ credentials: 'include',
215
228
  body: JSON.stringify({
216
229
  url,
217
230
  bucketName
@@ -221,15 +234,14 @@ async function confirmUpload({ url }, { apiPath, bucketName }) {
221
234
  }
222
235
  });
223
236
  if (!res.ok) {
224
- throw new EdgeStoreApiClientError({
225
- response: await res.json()
226
- });
237
+ await handleError(res);
227
238
  }
228
239
  return res.json();
229
240
  }
230
241
  async function deleteFile({ url }, { apiPath, bucketName }) {
231
242
  const res = await fetch(`${apiPath}/delete-file`, {
232
243
  method: 'POST',
244
+ credentials: 'include',
233
245
  body: JSON.stringify({
234
246
  url,
235
247
  bucketName
@@ -239,9 +251,7 @@ async function deleteFile({ url }, { apiPath, bucketName }) {
239
251
  }
240
252
  });
241
253
  if (!res.ok) {
242
- throw new EdgeStoreApiClientError({
243
- response: await res.json()
244
- });
254
+ await handleError(res);
245
255
  }
246
256
  return res.json();
247
257
  }
@@ -283,7 +293,7 @@ async function queuedPromises({ items, fn, maxParallel, maxRetries = 0 }) {
283
293
  return results;
284
294
  }
285
295
 
286
- const DEFAULT_BASE_URL = process.env.NEXT_PUBLIC_EDGE_STORE_BASE_URL ?? 'https://files.edgestore.dev';
296
+ const DEFAULT_BASE_URL = (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_EDGE_STORE_BASE_URL : import.meta.env?.EDGE_STORE_BASE_URL) ?? 'https://files.edgestore.dev';
287
297
  function createEdgeStoreProvider(opts) {
288
298
  const EdgeStoreContext = /*#__PURE__*/ React.createContext(undefined);
289
299
  const EdgeStoreProvider = ({ children, basePath })=>{
@@ -312,24 +322,72 @@ function createEdgeStoreProvider(opts) {
312
322
  }
313
323
  function EdgeStoreProviderInner({ children, context, basePath, maxConcurrentUploads }) {
314
324
  const apiPath = basePath ? `${basePath}` : '/api/edgestore';
325
+ const [state, setState] = React.useState({
326
+ loading: true,
327
+ initialized: false,
328
+ error: false
329
+ });
315
330
  const uploadingCountRef = React.useRef(0);
331
+ const initExecuted = React.useRef(false); // to make sure we don't run init twice
316
332
  React.useEffect(()=>{
317
- void init();
333
+ if (!initExecuted.current) {
334
+ void init();
335
+ }
336
+ return ()=>{
337
+ initExecuted.current = true;
338
+ };
318
339
  // eslint-disable-next-line react-hooks/exhaustive-deps
319
340
  }, []);
320
341
  async function init() {
321
- const res = await fetch(`${apiPath}/init`, {
322
- method: 'POST'
323
- });
324
- if (res.ok) {
325
- const json = await res.json();
326
- await fetch(`${DEFAULT_BASE_URL}/_init`, {
327
- method: 'GET',
328
- credentials: 'include',
329
- headers: {
330
- 'x-edgestore-token': json.token
342
+ try {
343
+ setState({
344
+ loading: true,
345
+ initialized: false,
346
+ error: false
347
+ });
348
+ const res = await fetch(`${apiPath}/init`, {
349
+ method: 'POST',
350
+ credentials: 'include'
351
+ });
352
+ if (res.ok) {
353
+ const json = await res.json();
354
+ const innerRes = await fetch(`${DEFAULT_BASE_URL}/_init`, {
355
+ method: 'GET',
356
+ credentials: 'include',
357
+ headers: {
358
+ 'x-edgestore-token': json.token
359
+ }
360
+ });
361
+ if (innerRes.ok) {
362
+ // update state
363
+ setState({
364
+ loading: false,
365
+ initialized: true,
366
+ error: false
367
+ });
368
+ } else {
369
+ setState({
370
+ loading: false,
371
+ initialized: false,
372
+ error: true
373
+ });
374
+ throw new EdgeStoreClientError("Couldn't initialize Edge Store.");
331
375
  }
376
+ } else {
377
+ setState({
378
+ loading: false,
379
+ initialized: false,
380
+ error: true
381
+ });
382
+ await handleError(res);
383
+ }
384
+ } catch (err) {
385
+ setState({
386
+ loading: false,
387
+ initialized: false,
388
+ error: true
332
389
  });
390
+ throw err;
333
391
  }
334
392
  }
335
393
  async function reset() {
@@ -342,7 +400,8 @@ function EdgeStoreProviderInner({ children, context, basePath, maxConcurrentUplo
342
400
  uploadingCountRef,
343
401
  maxConcurrentUploads
344
402
  }),
345
- reset
403
+ reset,
404
+ state
346
405
  }
347
406
  }, children));
348
407
  }
@@ -2,4 +2,4 @@ declare class EdgeStoreClientError extends Error {
2
2
  constructor(message: string);
3
3
  }
4
4
  export default EdgeStoreClientError;
5
- //# sourceMappingURL=EdgeStoreError.d.ts.map
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,CAU/D"}
@@ -0,0 +1,2 @@
1
+ export { EdgeStoreApiClientError } from '@edgestore/shared';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var shared = require('@edgestore/shared');
6
+
7
+
8
+
9
+ Object.defineProperty(exports, 'EdgeStoreApiClientError', {
10
+ enumerable: true,
11
+ get: function () { return shared.EdgeStoreApiClientError; }
12
+ });
@@ -0,0 +1 @@
1
+ export { EdgeStoreApiClientError } from '@edgestore/shared';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edgestore/react",
3
- "version": "0.1.5-alpha.8",
3
+ "version": "0.1.5",
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",
@@ -36,6 +36,11 @@
36
36
  "import": "./dist/utils/index.mjs",
37
37
  "require": "./dist/utils/index.js",
38
38
  "default": "./dist/utils/index.js"
39
+ },
40
+ "./shared": {
41
+ "import": "./dist/shared/index.mjs",
42
+ "require": "./dist/shared/index.js",
43
+ "default": "./dist/shared/index.js"
39
44
  }
40
45
  },
41
46
  "files": [
@@ -44,6 +49,7 @@
44
49
  "README.md",
45
50
  "package.json",
46
51
  "utils",
52
+ "shared",
47
53
  "!**/*.test.*"
48
54
  ],
49
55
  "private": false,
@@ -60,14 +66,15 @@
60
66
  "uuid": "^9.0.0"
61
67
  },
62
68
  "peerDependencies": {
63
- "@edgestore/server": "0.1.5-alpha.8",
69
+ "@edgestore/shared": "0.1.5",
64
70
  "next": "*",
65
71
  "react": ">=16.8.0",
66
72
  "react-dom": ">=16.8.0",
67
73
  "zod": ">=3.0.0"
68
74
  },
69
75
  "devDependencies": {
70
- "@edgestore/server": "0.1.5-alpha.8",
76
+ "@edgestore/shared": "0.1.5",
77
+ "@swc/helpers": "0.5.3",
71
78
  "@types/cookie": "^0.5.1",
72
79
  "@types/node": "^18.11.18",
73
80
  "@types/uuid": "^9.0.1",
@@ -75,7 +82,7 @@
75
82
  "react": "^18.2.0",
76
83
  "react-dom": "^18.2.0",
77
84
  "typescript": "^5.1.6",
78
- "zod": "^3.21.4"
85
+ "zod": "3.21.4"
79
86
  },
80
- "gitHead": "7884d8bb14b983582e29c9de5c4230120bf675c5"
87
+ "gitHead": "44951b90386930abadb67009cc9a5d1826b5cecb"
81
88
  }
@@ -0,0 +1 @@
1
+ export * from '../dist/shared';
@@ -0,0 +1 @@
1
+ module.exports = require('../dist/shared');
@@ -1,9 +1,14 @@
1
- import { type AnyRouter } from '@edgestore/server/core';
1
+ import { type AnyRouter } from '@edgestore/shared';
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
+ (typeof 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,25 +116,74 @@ 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',
138
+ try {
139
+ setState({
140
+ loading: true,
141
+ initialized: false,
142
+ error: false,
143
+ });
144
+ const res = await fetch(`${apiPath}/init`, {
145
+ method: 'POST',
104
146
  credentials: 'include',
105
- headers: {
106
- 'x-edgestore-token': json.token,
107
- },
108
147
  });
148
+ if (res.ok) {
149
+ const json = await res.json();
150
+ const innerRes = await fetch(`${DEFAULT_BASE_URL}/_init`, {
151
+ method: 'GET',
152
+ credentials: 'include',
153
+ headers: {
154
+ 'x-edgestore-token': json.token,
155
+ },
156
+ });
157
+ if (innerRes.ok) {
158
+ // update state
159
+ setState({
160
+ loading: false,
161
+ initialized: true,
162
+ error: false,
163
+ });
164
+ } else {
165
+ setState({
166
+ loading: false,
167
+ initialized: false,
168
+ error: true,
169
+ });
170
+ throw new EdgeStoreClientError("Couldn't initialize Edge Store.");
171
+ }
172
+ } else {
173
+ setState({
174
+ loading: false,
175
+ initialized: false,
176
+ error: true,
177
+ });
178
+ await handleError(res);
179
+ }
180
+ } catch (err) {
181
+ setState({
182
+ loading: false,
183
+ initialized: false,
184
+ error: true,
185
+ });
186
+ throw err;
109
187
  }
110
188
  }
111
189
 
@@ -123,6 +201,7 @@ function EdgeStoreProviderInner<TRouter extends AnyRouter>({
123
201
  maxConcurrentUploads,
124
202
  }),
125
203
  reset,
204
+ state,
126
205
  }}
127
206
  >
128
207
  {children}
@@ -1,13 +1,13 @@
1
- import { type RequestUploadRes } from '@edgestore/server/adapters';
2
1
  import {
3
- EdgeStoreApiClientError,
4
2
  type AnyRouter,
5
3
  type InferBucketPathObject,
6
4
  type InferMetadataObject,
5
+ type SharedRequestUploadRes,
7
6
  type UploadOptions,
8
- } from '@edgestore/server/core';
7
+ } from '@edgestore/shared';
9
8
  import { type z } from 'zod';
10
- import EdgeStoreClientError from './libs/errors/EdgeStoreError';
9
+ import EdgeStoreClientError from './libs/errors/EdgeStoreClientError';
10
+ import { handleError } from './libs/errors/handleError';
11
11
 
12
12
  /**
13
13
  * @internal
@@ -87,10 +87,11 @@ export function createNextProxy<TRouter extends AnyRouter>({
87
87
  await new Promise((resolve) => setTimeout(resolve, 300));
88
88
  }
89
89
  uploadingCountRef.current++;
90
- return await uploadFile(params, {
90
+ const test = await uploadFile(params, {
91
91
  bucketName: bucketName as string,
92
92
  apiPath,
93
93
  });
94
+ return test;
94
95
  } finally {
95
96
  uploadingCountRef.current--;
96
97
  }
@@ -143,6 +144,7 @@ async function uploadFile(
143
144
  onProgressChange?.(0);
144
145
  const res = await fetch(`${apiPath}/request-upload`, {
145
146
  method: 'POST',
147
+ credentials: 'include',
146
148
  body: JSON.stringify({
147
149
  bucketName,
148
150
  input,
@@ -160,11 +162,9 @@ async function uploadFile(
160
162
  },
161
163
  });
162
164
  if (!res.ok) {
163
- throw new EdgeStoreApiClientError({
164
- response: await res.json(),
165
- });
165
+ await handleError(res);
166
166
  }
167
- const json = (await res.json()) as RequestUploadRes;
167
+ const json = (await res.json()) as SharedRequestUploadRes;
168
168
  if ('multipart' in json) {
169
169
  await multipartUpload({
170
170
  bucketName,
@@ -203,7 +203,14 @@ async function uploadFile(
203
203
  * we need to proxy the file through the server.
204
204
  */
205
205
  function getUrl(url: string, apiPath: string) {
206
- if (process.env.NODE_ENV === 'development' && !url.includes('/_public/')) {
206
+ const mode =
207
+ typeof process !== 'undefined'
208
+ ? process.env.NODE_ENV
209
+ : // @ts-expect-error - DEV is injected by Vite
210
+ import.meta.env?.DEV
211
+ ? 'development'
212
+ : 'production';
213
+ if (mode === 'development' && !url.includes('/_public/')) {
207
214
  const proxyUrl = new URL(window.location.origin);
208
215
  proxyUrl.pathname = `${apiPath}/proxy-file`;
209
216
  proxyUrl.search = new URLSearchParams({
@@ -252,7 +259,10 @@ const uploadFileInner = async (
252
259
 
253
260
  async function multipartUpload(params: {
254
261
  bucketName: string;
255
- multipartInfo: Extract<RequestUploadRes, { multipart: any }>['multipart'];
262
+ multipartInfo: Extract<
263
+ SharedRequestUploadRes,
264
+ { multipart: any }
265
+ >['multipart'];
256
266
  onProgressChange: OnProgressChangeHandler | undefined;
257
267
  file: File;
258
268
  apiPath: string;
@@ -316,6 +326,7 @@ async function multipartUpload(params: {
316
326
  // Complete multipart upload
317
327
  const res = await fetch(`${apiPath}/complete-multipart-upload`, {
318
328
  method: 'POST',
329
+ credentials: 'include',
319
330
  body: JSON.stringify({
320
331
  bucketName,
321
332
  uploadId,
@@ -327,9 +338,7 @@ async function multipartUpload(params: {
327
338
  },
328
339
  });
329
340
  if (!res.ok) {
330
- throw new EdgeStoreApiClientError({
331
- response: await res.json(),
332
- });
341
+ await handleError(res);
333
342
  }
334
343
  }
335
344
 
@@ -349,6 +358,7 @@ async function confirmUpload(
349
358
  ) {
350
359
  const res = await fetch(`${apiPath}/confirm-upload`, {
351
360
  method: 'POST',
361
+ credentials: 'include',
352
362
  body: JSON.stringify({
353
363
  url,
354
364
  bucketName,
@@ -358,9 +368,7 @@ async function confirmUpload(
358
368
  },
359
369
  });
360
370
  if (!res.ok) {
361
- throw new EdgeStoreApiClientError({
362
- response: await res.json(),
363
- });
371
+ await handleError(res);
364
372
  }
365
373
  return res.json();
366
374
  }
@@ -381,6 +389,7 @@ async function deleteFile(
381
389
  ) {
382
390
  const res = await fetch(`${apiPath}/delete-file`, {
383
391
  method: 'POST',
392
+ credentials: 'include',
384
393
  body: JSON.stringify({
385
394
  url,
386
395
  bucketName,
@@ -390,9 +399,7 @@ async function deleteFile(
390
399
  },
391
400
  });
392
401
  if (!res.ok) {
393
- throw new EdgeStoreApiClientError({
394
- response: await res.json(),
395
- });
402
+ await handleError(res);
396
403
  }
397
404
  return res.json();
398
405
  }
@@ -0,0 +1,14 @@
1
+ import { EdgeStoreApiClientError } from '@edgestore/shared';
2
+ import EdgeStoreClientError from './EdgeStoreClientError';
3
+
4
+ export async function handleError(res: Response): Promise<never> {
5
+ let json: any = {};
6
+ try {
7
+ json = await res.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
+ throw new EdgeStoreApiClientError({ response: json });
14
+ }
@@ -0,0 +1 @@
1
+ export { EdgeStoreApiClientError } from '@edgestore/shared';
@@ -1 +0,0 @@
1
- {"version":3,"file":"EdgeStoreError.d.ts","sourceRoot":"","sources":["../../../src/libs/errors/EdgeStoreError.ts"],"names":[],"mappings":"AAAA,cAAM,oBAAqB,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED,eAAe,oBAAoB,CAAC"}