@masters-union/union-stack 0.3.16 → 0.3.17

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.
Files changed (37) hide show
  1. package/dist/cdn/loader.v1.global.js +2 -2
  2. package/dist/cdn/loader.v1.global.js.map +1 -1
  3. package/dist/{chunk-3FCZBKNN.cjs → chunk-4645KBSE.cjs} +8 -8
  4. package/dist/{chunk-3FCZBKNN.cjs.map → chunk-4645KBSE.cjs.map} +1 -1
  5. package/dist/{chunk-XBQENFBZ.js → chunk-G2H5WZDV.js} +14 -12
  6. package/dist/chunk-G2H5WZDV.js.map +1 -0
  7. package/dist/{chunk-EBE7EIOZ.cjs → chunk-PVM2ZX45.cjs} +14 -14
  8. package/dist/{chunk-EBE7EIOZ.cjs.map → chunk-PVM2ZX45.cjs.map} +1 -1
  9. package/dist/{chunk-OZGVTEMZ.js → chunk-QQFNG3ZF.js} +4 -4
  10. package/dist/{chunk-OZGVTEMZ.js.map → chunk-QQFNG3ZF.js.map} +1 -1
  11. package/dist/{chunk-7NJTA5ZD.js → chunk-RYS4MXXL.js} +4 -4
  12. package/dist/{chunk-7NJTA5ZD.js.map → chunk-RYS4MXXL.js.map} +1 -1
  13. package/dist/{chunk-GTE65IAM.cjs → chunk-TQDC5KIC.cjs} +14 -12
  14. package/dist/chunk-TQDC5KIC.cjs.map +1 -0
  15. package/dist/{client-BCLIIiX2.d.ts → client-BofkorBV.d.ts} +1 -1
  16. package/dist/{client-CSZ-4GVl.d.cts → client-C_pEvbZS.d.cts} +1 -1
  17. package/dist/index.cjs +5 -5
  18. package/dist/index.d.cts +3 -3
  19. package/dist/index.d.ts +3 -3
  20. package/dist/index.js +4 -4
  21. package/dist/node.cjs +8 -8
  22. package/dist/node.d.cts +2 -2
  23. package/dist/node.d.ts +2 -2
  24. package/dist/node.js +2 -2
  25. package/dist/picker.cjs +3 -3
  26. package/dist/picker.d.cts +3 -3
  27. package/dist/picker.d.ts +3 -3
  28. package/dist/picker.js +1 -1
  29. package/dist/react.cjs +4 -4
  30. package/dist/react.d.cts +4 -4
  31. package/dist/react.d.ts +4 -4
  32. package/dist/react.js +3 -3
  33. package/dist/{types-BWs1slkL.d.cts → types-BsGu9Oi3.d.cts} +2 -0
  34. package/dist/{types-BWs1slkL.d.ts → types-BsGu9Oi3.d.ts} +2 -0
  35. package/package.json +1 -1
  36. package/dist/chunk-GTE65IAM.cjs.map +0 -1
  37. package/dist/chunk-XBQENFBZ.js.map +0 -1
@@ -8,6 +8,7 @@ function makeError(code, message, opts = {}) {
8
8
  message,
9
9
  status: opts.status,
10
10
  retryable: opts.retryable ?? defaultRetryable(code, opts.status),
11
+ docs: opts.docs,
11
12
  cause: opts.cause
12
13
  };
13
14
  }
@@ -20,39 +21,40 @@ function fromApiResponse(status, body) {
20
21
  const err = body?.error;
21
22
  const msg = err?.message || `Request failed with status ${status}`;
22
23
  const code = (err?.code || "").toUpperCase();
24
+ const docs = typeof err?.docs === "string" ? err.docs : void 0;
23
25
  if (status === 401) {
24
- return makeError("AUTH", msg, { status, retryable: false });
26
+ return makeError("AUTH", msg, { status, retryable: false, docs });
25
27
  }
26
28
  if (status === 403) {
27
- return makeError("AUTH", msg, { status, retryable: false });
29
+ return makeError("AUTH", msg, { status, retryable: false, docs });
28
30
  }
29
31
  if (status === 413) {
30
- return makeError("VALIDATION", msg, { status, retryable: false });
32
+ return makeError("VALIDATION", msg, { status, retryable: false, docs });
31
33
  }
32
34
  if (status === 415) {
33
- return makeError("VALIDATION", msg, { status, retryable: false });
35
+ return makeError("VALIDATION", msg, { status, retryable: false, docs });
34
36
  }
35
37
  if (status === 422) {
36
38
  if (code === "EMPTY_UPLOAD") {
37
- return makeError("EMPTY_FILE", EMPTY_FILE_MESSAGE, { status, retryable: false });
39
+ return makeError("EMPTY_FILE", EMPTY_FILE_MESSAGE, { status, retryable: false, docs });
38
40
  }
39
- return makeError("VALIDATION", msg, { status, retryable: false });
41
+ return makeError("VALIDATION", msg, { status, retryable: false, docs });
40
42
  }
41
43
  if (status === 426) {
42
- return makeError("CONFIG", msg, { status, retryable: false });
44
+ return makeError("CONFIG", msg, { status, retryable: false, docs });
43
45
  }
44
46
  if (status === 429) {
45
47
  const isQuota = code === "QUOTA_EXCEEDED";
46
- return makeError(isQuota ? "QUOTA" : "NETWORK", msg, { status, retryable: !isQuota });
48
+ return makeError(isQuota ? "QUOTA" : "NETWORK", msg, { status, retryable: !isQuota, docs });
47
49
  }
48
50
  if (status >= 500) {
49
- return makeError("SERVER", msg, { status, retryable: true });
51
+ return makeError("SERVER", msg, { status, retryable: true, docs });
50
52
  }
51
- return makeError("SERVER", msg, { status, retryable: false });
53
+ return makeError("SERVER", msg, { status, retryable: false, docs });
52
54
  }
53
55
 
54
56
  exports.EMPTY_FILE_MESSAGE = EMPTY_FILE_MESSAGE;
55
57
  exports.fromApiResponse = fromApiResponse;
56
58
  exports.makeError = makeError;
57
- //# sourceMappingURL=chunk-GTE65IAM.cjs.map
58
- //# sourceMappingURL=chunk-GTE65IAM.cjs.map
59
+ //# sourceMappingURL=chunk-TQDC5KIC.cjs.map
60
+ //# sourceMappingURL=chunk-TQDC5KIC.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts"],"names":[],"mappings":"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","file":"chunk-TQDC5KIC.cjs","sourcesContent":["import type { UploadError, UploadErrorCode } from './types.js';\n\n// Single source of truth for the 0-byte message. Used by the client-side guard\n// (uploader), the picker UI, and the server-side reject (mapped from a 422\n// EMPTY_UPLOAD), so the end user sees the same actionable text no matter where\n// the empty file was caught.\nexport const EMPTY_FILE_MESSAGE =\n \"This file is empty (0 bytes) and can't be uploaded. If it's stored in iCloud, \" +\n 'OneDrive, or Google Drive, open it once to download it to this device, then try again.';\n\nexport function makeError(\n code: UploadErrorCode,\n message: string,\n opts: { status?: number; retryable?: boolean; docs?: string; cause?: unknown } = {}\n): UploadError {\n return {\n code,\n message,\n status: opts.status,\n retryable: opts.retryable ?? defaultRetryable(code, opts.status),\n docs: opts.docs,\n cause: opts.cause,\n };\n}\n\nfunction defaultRetryable(code: UploadErrorCode, status?: number): boolean {\n if (code === 'NETWORK' || code === 'PART_FAILED') return true;\n if (code === 'SERVER' && status && status >= 500) return true;\n return false;\n}\n\n/** Map an HTTP error response from the cdn-be API to an UploadError. */\nexport function fromApiResponse(status: number, body: unknown): UploadError {\n const err = (body as { error?: { code?: string; message?: string; docs?: string } } | null)?.error;\n const msg = err?.message || `Request failed with status ${status}`;\n const code = (err?.code || '').toUpperCase();\n // Docs deep-link the API attaches to some errors (e.g. ORIGIN_NOT_ALLOWED).\n // Passed through on every mapping so callers can surface a \"learn more\" link.\n const docs = typeof err?.docs === 'string' ? err.docs : undefined;\n\n if (status === 401) {\n return makeError('AUTH', msg, { status, retryable: false, docs });\n }\n if (status === 403) {\n return makeError('AUTH', msg, { status, retryable: false, docs });\n }\n if (status === 413) {\n return makeError('VALIDATION', msg, { status, retryable: false, docs });\n }\n if (status === 415) {\n return makeError('VALIDATION', msg, { status, retryable: false, docs });\n }\n if (status === 422) {\n // Server rejected the assembled object. EMPTY_UPLOAD (0 bytes landed) gets\n // the dedicated code + canonical message so it reads the same as a\n // client-side empty catch; other 422s fall back to VALIDATION. Either way,\n // retrying the same source file won't help, so it's not retryable.\n if (code === 'EMPTY_UPLOAD') {\n return makeError('EMPTY_FILE', EMPTY_FILE_MESSAGE, { status, retryable: false, docs });\n }\n return makeError('VALIDATION', msg, { status, retryable: false, docs });\n }\n if (status === 426) {\n // Server-enforced minimum SDK version. Not retryable — the integrator\n // must upgrade the package (or reload, for script-loader users).\n return makeError('CONFIG', msg, { status, retryable: false, docs });\n }\n if (status === 429) {\n const isQuota = code === 'QUOTA_EXCEEDED';\n return makeError(isQuota ? 'QUOTA' : 'NETWORK', msg, { status, retryable: !isQuota, docs });\n }\n if (status >= 500) {\n return makeError('SERVER', msg, { status, retryable: true, docs });\n }\n return makeError('SERVER', msg, { status, retryable: false, docs });\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { B as BatchUploadOptions, a as PickedFile, P as PickResponse, f as PickerConfig, C as ClientConfig, d as UploadOptions, e as UploadedFile, R as ResolvedClientConfig } from './types-BWs1slkL.js';
1
+ import { B as BatchUploadOptions, a as PickedFile, P as PickResponse, f as PickerConfig, C as ClientConfig, d as UploadOptions, e as UploadedFile, R as ResolvedClientConfig } from './types-BsGu9Oi3.js';
2
2
 
3
3
  interface PickerTheme {
4
4
  /** Primary accent color (buttons, progress bar, focus rings). */
@@ -1,4 +1,4 @@
1
- import { B as BatchUploadOptions, a as PickedFile, P as PickResponse, f as PickerConfig, C as ClientConfig, d as UploadOptions, e as UploadedFile, R as ResolvedClientConfig } from './types-BWs1slkL.cjs';
1
+ import { B as BatchUploadOptions, a as PickedFile, P as PickResponse, f as PickerConfig, C as ClientConfig, d as UploadOptions, e as UploadedFile, R as ResolvedClientConfig } from './types-BsGu9Oi3.cjs';
2
2
 
3
3
  interface PickerTheme {
4
4
  /** Primary accent color (buttons, progress bar, focus rings). */
package/dist/index.cjs CHANGED
@@ -1,19 +1,19 @@
1
1
  'use strict';
2
2
 
3
- var chunk3FCZBKNN_cjs = require('./chunk-3FCZBKNN.cjs');
4
- require('./chunk-EBE7EIOZ.cjs');
5
- require('./chunk-GTE65IAM.cjs');
3
+ var chunk4645KBSE_cjs = require('./chunk-4645KBSE.cjs');
4
+ require('./chunk-PVM2ZX45.cjs');
5
+ require('./chunk-TQDC5KIC.cjs');
6
6
 
7
7
  // src/index.ts
8
8
  var UnionStack = {
9
9
  init(cfg) {
10
- return new chunk3FCZBKNN_cjs.UnionStackClient(cfg);
10
+ return new chunk4645KBSE_cjs.UnionStackClient(cfg);
11
11
  }
12
12
  };
13
13
 
14
14
  Object.defineProperty(exports, "UnionStackClient", {
15
15
  enumerable: true,
16
- get: function () { return chunk3FCZBKNN_cjs.UnionStackClient; }
16
+ get: function () { return chunk4645KBSE_cjs.UnionStackClient; }
17
17
  });
18
18
  exports.UnionStack = UnionStack;
19
19
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { U as UnionStackClient } from './client-CSZ-4GVl.cjs';
2
- import { C as ClientConfig } from './types-BWs1slkL.cjs';
3
- export { B as BatchUploadOptions, P as PickResponse, a as PickedFile, b as ProgressEvent, S as Source, U as UploadError, c as UploadErrorCode, d as UploadOptions, e as UploadedFile } from './types-BWs1slkL.cjs';
1
+ import { U as UnionStackClient } from './client-C_pEvbZS.cjs';
2
+ import { C as ClientConfig } from './types-BsGu9Oi3.cjs';
3
+ export { B as BatchUploadOptions, P as PickResponse, a as PickedFile, b as ProgressEvent, S as Source, U as UploadError, c as UploadErrorCode, d as UploadOptions, e as UploadedFile } from './types-BsGu9Oi3.cjs';
4
4
 
5
5
  declare const UnionStack: {
6
6
  init(cfg: ClientConfig): UnionStackClient;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { U as UnionStackClient } from './client-BCLIIiX2.js';
2
- import { C as ClientConfig } from './types-BWs1slkL.js';
3
- export { B as BatchUploadOptions, P as PickResponse, a as PickedFile, b as ProgressEvent, S as Source, U as UploadError, c as UploadErrorCode, d as UploadOptions, e as UploadedFile } from './types-BWs1slkL.js';
1
+ import { U as UnionStackClient } from './client-BofkorBV.js';
2
+ import { C as ClientConfig } from './types-BsGu9Oi3.js';
3
+ export { B as BatchUploadOptions, P as PickResponse, a as PickedFile, b as ProgressEvent, S as Source, U as UploadError, c as UploadErrorCode, d as UploadOptions, e as UploadedFile } from './types-BsGu9Oi3.js';
4
4
 
5
5
  declare const UnionStack: {
6
6
  init(cfg: ClientConfig): UnionStackClient;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { UnionStackClient } from './chunk-OZGVTEMZ.js';
2
- export { UnionStackClient } from './chunk-OZGVTEMZ.js';
3
- import './chunk-7NJTA5ZD.js';
4
- import './chunk-XBQENFBZ.js';
1
+ import { UnionStackClient } from './chunk-QQFNG3ZF.js';
2
+ export { UnionStackClient } from './chunk-QQFNG3ZF.js';
3
+ import './chunk-RYS4MXXL.js';
4
+ import './chunk-G2H5WZDV.js';
5
5
 
6
6
  // src/index.ts
7
7
  var UnionStack = {
package/dist/node.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkEBE7EIOZ_cjs = require('./chunk-EBE7EIOZ.cjs');
4
- var chunkGTE65IAM_cjs = require('./chunk-GTE65IAM.cjs');
3
+ var chunkPVM2ZX45_cjs = require('./chunk-PVM2ZX45.cjs');
4
+ var chunkTQDC5KIC_cjs = require('./chunk-TQDC5KIC.cjs');
5
5
  var path = require('path');
6
6
  var promises = require('fs/promises');
7
7
  var fs = require('fs');
@@ -98,7 +98,7 @@ async function resolveSource(source, opts = {}) {
98
98
  const blob = openAsBlob2 ? await openAsBlob2(source, { type: mimetype }) : new Blob([toBlobPart(await promises.readFile(source))], { type: mimetype });
99
99
  return { blob, filename, mimetype };
100
100
  } catch (cause) {
101
- throw chunkGTE65IAM_cjs.makeError("VALIDATION", `Could not read file at "${source}".`, {
101
+ throw chunkTQDC5KIC_cjs.makeError("VALIDATION", `Could not read file at "${source}".`, {
102
102
  retryable: false,
103
103
  cause
104
104
  });
@@ -121,7 +121,7 @@ async function resolveSource(source, opts = {}) {
121
121
  const mimetype = opts.mimeType || mimeFromName(filename);
122
122
  return { blob: new Blob([toBlobPart(source)], { type: mimetype }), filename, mimetype };
123
123
  }
124
- throw chunkGTE65IAM_cjs.makeError(
124
+ throw chunkTQDC5KIC_cjs.makeError(
125
125
  "VALIDATION",
126
126
  "Unsupported upload source. Pass a file path, Buffer, Uint8Array, ArrayBuffer, Blob, or Readable stream.",
127
127
  { retryable: false }
@@ -134,7 +134,7 @@ var DEFAULT_FILE_CONCURRENCY = 5;
134
134
  var UnionStackNodeClient = class {
135
135
  constructor(cfg) {
136
136
  if (!cfg?.apiKey) {
137
- throw chunkGTE65IAM_cjs.makeError("CONFIG", 'apiKey is required. Pass { apiKey: "unionstack_live_\u2026" }.', {
137
+ throw chunkTQDC5KIC_cjs.makeError("CONFIG", 'apiKey is required. Pass { apiKey: "unionstack_live_\u2026" }.', {
138
138
  retryable: false
139
139
  });
140
140
  }
@@ -145,9 +145,9 @@ var UnionStackNodeClient = class {
145
145
  skipConfigPrefetch: true,
146
146
  // Tag the traffic as server-to-server ("node/…") so cdn-be can tell it
147
147
  // apart from browser SDK calls ("js/…").
148
- sdkHeader: chunkEBE7EIOZ_cjs.NODE_SDK_VERSION_HEADER
148
+ sdkHeader: chunkPVM2ZX45_cjs.NODE_SDK_VERSION_HEADER
149
149
  };
150
- this.uploader = new chunkEBE7EIOZ_cjs.Uploader(this.cfg);
150
+ this.uploader = new chunkPVM2ZX45_cjs.Uploader(this.cfg);
151
151
  }
152
152
  /**
153
153
  * Upload one file. Accepts a path on disk, a Buffer/Uint8Array/ArrayBuffer, a
@@ -169,7 +169,7 @@ var UnionStackNodeClient = class {
169
169
  */
170
170
  async uploadMany(sources, opts = {}) {
171
171
  if (!Array.isArray(sources) || sources.length === 0) {
172
- const err = chunkGTE65IAM_cjs.makeError("VALIDATION", "uploadMany requires a non-empty array of sources.", {
172
+ const err = chunkTQDC5KIC_cjs.makeError("VALIDATION", "uploadMany requires a non-empty array of sources.", {
173
173
  retryable: false
174
174
  });
175
175
  opts.onError?.(err);
package/dist/node.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Readable } from 'node:stream';
2
- import { C as ClientConfig, d as UploadOptions, e as UploadedFile, B as BatchUploadOptions, P as PickResponse, R as ResolvedClientConfig } from './types-BWs1slkL.cjs';
3
- export { a as PickedFile, b as ProgressEvent, S as Source, U as UploadError, c as UploadErrorCode } from './types-BWs1slkL.cjs';
2
+ import { C as ClientConfig, d as UploadOptions, e as UploadedFile, B as BatchUploadOptions, P as PickResponse, R as ResolvedClientConfig } from './types-BsGu9Oi3.cjs';
3
+ export { a as PickedFile, b as ProgressEvent, S as Source, U as UploadError, c as UploadErrorCode } from './types-BsGu9Oi3.cjs';
4
4
 
5
5
  /**
6
6
  * Anything the Node client knows how to turn into an upload.
package/dist/node.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Readable } from 'node:stream';
2
- import { C as ClientConfig, d as UploadOptions, e as UploadedFile, B as BatchUploadOptions, P as PickResponse, R as ResolvedClientConfig } from './types-BWs1slkL.js';
3
- export { a as PickedFile, b as ProgressEvent, S as Source, U as UploadError, c as UploadErrorCode } from './types-BWs1slkL.js';
2
+ import { C as ClientConfig, d as UploadOptions, e as UploadedFile, B as BatchUploadOptions, P as PickResponse, R as ResolvedClientConfig } from './types-BsGu9Oi3.js';
3
+ export { a as PickedFile, b as ProgressEvent, S as Source, U as UploadError, c as UploadErrorCode } from './types-BsGu9Oi3.js';
4
4
 
5
5
  /**
6
6
  * Anything the Node client knows how to turn into an upload.
package/dist/node.js CHANGED
@@ -1,5 +1,5 @@
1
- import { NODE_SDK_VERSION_HEADER, Uploader } from './chunk-7NJTA5ZD.js';
2
- import { makeError } from './chunk-XBQENFBZ.js';
1
+ import { NODE_SDK_VERSION_HEADER, Uploader } from './chunk-RYS4MXXL.js';
2
+ import { makeError } from './chunk-G2H5WZDV.js';
3
3
  import { basename, extname } from 'path';
4
4
  import { readFile } from 'fs/promises';
5
5
  import * as fs from 'fs';
package/dist/picker.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkGTE65IAM_cjs = require('./chunk-GTE65IAM.cjs');
3
+ var chunkTQDC5KIC_cjs = require('./chunk-TQDC5KIC.cjs');
4
4
 
5
5
  // src/picker/styles.ts
6
6
  var STYLE_ID = "unionstack-picker-styles";
@@ -1713,7 +1713,7 @@ var Picker = class {
1713
1713
  edited: false,
1714
1714
  state: "failed",
1715
1715
  progress: 0,
1716
- error: chunkGTE65IAM_cjs.EMPTY_FILE_MESSAGE,
1716
+ error: chunkTQDC5KIC_cjs.EMPTY_FILE_MESSAGE,
1717
1717
  errorCode: "EMPTY_FILE"
1718
1718
  };
1719
1719
  this.items.push(item2);
@@ -2114,7 +2114,7 @@ var Picker = class {
2114
2114
  item.errorCode = err.code;
2115
2115
  this.setItemState(item, "failed");
2116
2116
  }
2117
- if (err.code === "EMPTY_FILE") this.flashNotice(chunkGTE65IAM_cjs.EMPTY_FILE_MESSAGE);
2117
+ if (err.code === "EMPTY_FILE") this.flashNotice(chunkTQDC5KIC_cjs.EMPTY_FILE_MESSAGE);
2118
2118
  this.opts.onFileUploadFailed?.(p, err);
2119
2119
  },
2120
2120
  onUploadDone: (r) => {
package/dist/picker.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { U as UnionStackClient, P as PickerOptions, a as PickerHandle } from './client-CSZ-4GVl.cjs';
2
- export { b as PickerBranding, c as PickerTheme } from './client-CSZ-4GVl.cjs';
3
- import { P as PickResponse } from './types-BWs1slkL.cjs';
1
+ import { U as UnionStackClient, P as PickerOptions, a as PickerHandle } from './client-C_pEvbZS.cjs';
2
+ export { b as PickerBranding, c as PickerTheme } from './client-C_pEvbZS.cjs';
3
+ import { P as PickResponse } from './types-BsGu9Oi3.cjs';
4
4
 
5
5
  /**
6
6
  * Single-shot file picker modal. Built imperatively (no framework) so it can
package/dist/picker.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { U as UnionStackClient, P as PickerOptions, a as PickerHandle } from './client-BCLIIiX2.js';
2
- export { b as PickerBranding, c as PickerTheme } from './client-BCLIIiX2.js';
3
- import { P as PickResponse } from './types-BWs1slkL.js';
1
+ import { U as UnionStackClient, P as PickerOptions, a as PickerHandle } from './client-BofkorBV.js';
2
+ export { b as PickerBranding, c as PickerTheme } from './client-BofkorBV.js';
3
+ import { P as PickResponse } from './types-BsGu9Oi3.js';
4
4
 
5
5
  /**
6
6
  * Single-shot file picker modal. Built imperatively (no framework) so it can
package/dist/picker.js CHANGED
@@ -1,4 +1,4 @@
1
- import { EMPTY_FILE_MESSAGE } from './chunk-XBQENFBZ.js';
1
+ import { EMPTY_FILE_MESSAGE } from './chunk-G2H5WZDV.js';
2
2
 
3
3
  // src/picker/styles.ts
4
4
  var STYLE_ID = "unionstack-picker-styles";
package/dist/react.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunk3FCZBKNN_cjs = require('./chunk-3FCZBKNN.cjs');
4
- require('./chunk-EBE7EIOZ.cjs');
5
- require('./chunk-GTE65IAM.cjs');
3
+ var chunk4645KBSE_cjs = require('./chunk-4645KBSE.cjs');
4
+ require('./chunk-PVM2ZX45.cjs');
5
+ require('./chunk-TQDC5KIC.cjs');
6
6
  var React3 = require('react');
7
7
 
8
8
  function _interopNamespace(e) {
@@ -28,7 +28,7 @@ var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
28
28
  var UnionStackContext = React3__namespace.createContext(null);
29
29
  function UnionStackProvider({ children, ...cfg }) {
30
30
  const client = React3__namespace.useMemo(
31
- () => new chunk3FCZBKNN_cjs.UnionStackClient(cfg),
31
+ () => new chunk4645KBSE_cjs.UnionStackClient(cfg),
32
32
  // eslint-disable-next-line react-hooks/exhaustive-deps
33
33
  [cfg.apiKey, cfg.chunkSize]
34
34
  );
package/dist/react.d.cts CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
- import { U as UnionStackClient, P as PickerOptions } from './client-CSZ-4GVl.cjs';
3
- export { b as PickerBranding, a as PickerHandle, c as PickerTheme } from './client-CSZ-4GVl.cjs';
4
- import { C as ClientConfig, e as UploadedFile, a as PickedFile, U as UploadError, B as BatchUploadOptions, P as PickResponse } from './types-BWs1slkL.cjs';
5
- export { b as ProgressEvent, c as UploadErrorCode, d as UploadOptions } from './types-BWs1slkL.cjs';
2
+ import { U as UnionStackClient, P as PickerOptions } from './client-C_pEvbZS.cjs';
3
+ export { b as PickerBranding, a as PickerHandle, c as PickerTheme } from './client-C_pEvbZS.cjs';
4
+ import { C as ClientConfig, e as UploadedFile, a as PickedFile, U as UploadError, B as BatchUploadOptions, P as PickResponse } from './types-BsGu9Oi3.cjs';
5
+ export { b as ProgressEvent, c as UploadErrorCode, d as UploadOptions } from './types-BsGu9Oi3.cjs';
6
6
 
7
7
  interface UnionStackProviderProps extends ClientConfig {
8
8
  children: React.ReactNode;
package/dist/react.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
- import { U as UnionStackClient, P as PickerOptions } from './client-BCLIIiX2.js';
3
- export { b as PickerBranding, a as PickerHandle, c as PickerTheme } from './client-BCLIIiX2.js';
4
- import { C as ClientConfig, e as UploadedFile, a as PickedFile, U as UploadError, B as BatchUploadOptions, P as PickResponse } from './types-BWs1slkL.js';
5
- export { b as ProgressEvent, c as UploadErrorCode, d as UploadOptions } from './types-BWs1slkL.js';
2
+ import { U as UnionStackClient, P as PickerOptions } from './client-BofkorBV.js';
3
+ export { b as PickerBranding, a as PickerHandle, c as PickerTheme } from './client-BofkorBV.js';
4
+ import { C as ClientConfig, e as UploadedFile, a as PickedFile, U as UploadError, B as BatchUploadOptions, P as PickResponse } from './types-BsGu9Oi3.js';
5
+ export { b as ProgressEvent, c as UploadErrorCode, d as UploadOptions } from './types-BsGu9Oi3.js';
6
6
 
7
7
  interface UnionStackProviderProps extends ClientConfig {
8
8
  children: React.ReactNode;
package/dist/react.js CHANGED
@@ -1,6 +1,6 @@
1
- import { UnionStackClient } from './chunk-OZGVTEMZ.js';
2
- import './chunk-7NJTA5ZD.js';
3
- import './chunk-XBQENFBZ.js';
1
+ import { UnionStackClient } from './chunk-QQFNG3ZF.js';
2
+ import './chunk-RYS4MXXL.js';
3
+ import './chunk-G2H5WZDV.js';
4
4
  import * as React3 from 'react';
5
5
 
6
6
  var UnionStackContext = React3.createContext(null);
@@ -5,6 +5,8 @@ interface UploadError {
5
5
  status?: number;
6
6
  /** True if a retry has a reasonable chance of succeeding. */
7
7
  retryable: boolean;
8
+ /** Docs deep-link to the fix for this error, when the API provides one. */
9
+ docs?: string;
8
10
  /** Raw error from fetch / server (debugging only — don't display). */
9
11
  cause?: unknown;
10
12
  }
@@ -5,6 +5,8 @@ interface UploadError {
5
5
  status?: number;
6
6
  /** True if a retry has a reasonable chance of succeeding. */
7
7
  retryable: boolean;
8
+ /** Docs deep-link to the fix for this error, when the API provides one. */
9
+ docs?: string;
8
10
  /** Raw error from fetch / server (debugging only — don't display). */
9
11
  cause?: unknown;
10
12
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@masters-union/union-stack",
3
- "version": "0.3.16",
3
+ "version": "0.3.17",
4
4
  "description": "UnionStack — file upload SDK. Direct-to-R2 multipart uploads with a small client surface.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/errors.ts"],"names":[],"mappings":";;;AAMO,IAAM,kBAAA,GACX;AAGK,SAAS,SAAA,CACd,IAAA,EACA,OAAA,EACA,IAAA,GAAkE,EAAC,EACtD;AACb,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,WAAW,IAAA,CAAK,SAAA,IAAa,gBAAA,CAAiB,IAAA,EAAM,KAAK,MAAM,CAAA;AAAA,IAC/D,OAAO,IAAA,CAAK;AAAA,GACd;AACF;AAEA,SAAS,gBAAA,CAAiB,MAAuB,MAAA,EAA0B;AACzE,EAAA,IAAI,IAAA,KAAS,SAAA,IAAa,IAAA,KAAS,aAAA,EAAe,OAAO,IAAA;AACzD,EAAA,IAAI,IAAA,KAAS,QAAA,IAAY,MAAA,IAAU,MAAA,IAAU,KAAK,OAAO,IAAA;AACzD,EAAA,OAAO,KAAA;AACT;AAGO,SAAS,eAAA,CAAgB,QAAgB,IAAA,EAA4B;AAC1E,EAAA,MAAM,MAAO,IAAA,EAAiE,KAAA;AAC9E,EAAA,MAAM,GAAA,GAAM,GAAA,EAAK,OAAA,IAAW,CAAA,2BAAA,EAA8B,MAAM,CAAA,CAAA;AAChE,EAAA,MAAM,IAAA,GAAA,CAAQ,GAAA,EAAK,IAAA,IAAQ,EAAA,EAAI,WAAA,EAAY;AAE3C,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,UAAU,MAAA,EAAQ,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAC5D;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,UAAU,MAAA,EAAQ,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAC5D;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,UAAU,YAAA,EAAc,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAClE;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,UAAU,YAAA,EAAc,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAClE;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAKlB,IAAA,IAAI,SAAS,cAAA,EAAgB;AAC3B,MAAA,OAAO,UAAU,YAAA,EAAc,kBAAA,EAAoB,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,IACjF;AACA,IAAA,OAAO,UAAU,YAAA,EAAc,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAClE;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAGlB,IAAA,OAAO,UAAU,QAAA,EAAU,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAC9D;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,MAAM,UAAU,IAAA,KAAS,gBAAA;AACzB,IAAA,OAAO,SAAA,CAAU,OAAA,GAAU,OAAA,GAAU,SAAA,EAAW,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,CAAC,OAAA,EAAS,CAAA;AAAA,EACtF;AACA,EAAA,IAAI,UAAU,GAAA,EAAK;AACjB,IAAA,OAAO,UAAU,QAAA,EAAU,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,MAAM,CAAA;AAAA,EAC7D;AACA,EAAA,OAAO,UAAU,QAAA,EAAU,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAC9D","file":"chunk-GTE65IAM.cjs","sourcesContent":["import type { UploadError, UploadErrorCode } from './types.js';\n\n// Single source of truth for the 0-byte message. Used by the client-side guard\n// (uploader), the picker UI, and the server-side reject (mapped from a 422\n// EMPTY_UPLOAD), so the end user sees the same actionable text no matter where\n// the empty file was caught.\nexport const EMPTY_FILE_MESSAGE =\n \"This file is empty (0 bytes) and can't be uploaded. If it's stored in iCloud, \" +\n 'OneDrive, or Google Drive, open it once to download it to this device, then try again.';\n\nexport function makeError(\n code: UploadErrorCode,\n message: string,\n opts: { status?: number; retryable?: boolean; cause?: unknown } = {}\n): UploadError {\n return {\n code,\n message,\n status: opts.status,\n retryable: opts.retryable ?? defaultRetryable(code, opts.status),\n cause: opts.cause,\n };\n}\n\nfunction defaultRetryable(code: UploadErrorCode, status?: number): boolean {\n if (code === 'NETWORK' || code === 'PART_FAILED') return true;\n if (code === 'SERVER' && status && status >= 500) return true;\n return false;\n}\n\n/** Map an HTTP error response from the cdn-be API to an UploadError. */\nexport function fromApiResponse(status: number, body: unknown): UploadError {\n const err = (body as { error?: { code?: string; message?: string } } | null)?.error;\n const msg = err?.message || `Request failed with status ${status}`;\n const code = (err?.code || '').toUpperCase();\n\n if (status === 401) {\n return makeError('AUTH', msg, { status, retryable: false });\n }\n if (status === 403) {\n return makeError('AUTH', msg, { status, retryable: false });\n }\n if (status === 413) {\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 415) {\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 422) {\n // Server rejected the assembled object. EMPTY_UPLOAD (0 bytes landed) gets\n // the dedicated code + canonical message so it reads the same as a\n // client-side empty catch; other 422s fall back to VALIDATION. Either way,\n // retrying the same source file won't help, so it's not retryable.\n if (code === 'EMPTY_UPLOAD') {\n return makeError('EMPTY_FILE', EMPTY_FILE_MESSAGE, { status, retryable: false });\n }\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 426) {\n // Server-enforced minimum SDK version. Not retryable — the integrator\n // must upgrade the package (or reload, for script-loader users).\n return makeError('CONFIG', msg, { status, retryable: false });\n }\n if (status === 429) {\n const isQuota = code === 'QUOTA_EXCEEDED';\n return makeError(isQuota ? 'QUOTA' : 'NETWORK', msg, { status, retryable: !isQuota });\n }\n if (status >= 500) {\n return makeError('SERVER', msg, { status, retryable: true });\n }\n return makeError('SERVER', msg, { status, retryable: false });\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/errors.ts"],"names":[],"mappings":";AAMO,IAAM,kBAAA,GACX;AAGK,SAAS,SAAA,CACd,IAAA,EACA,OAAA,EACA,IAAA,GAAkE,EAAC,EACtD;AACb,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,WAAW,IAAA,CAAK,SAAA,IAAa,gBAAA,CAAiB,IAAA,EAAM,KAAK,MAAM,CAAA;AAAA,IAC/D,OAAO,IAAA,CAAK;AAAA,GACd;AACF;AAEA,SAAS,gBAAA,CAAiB,MAAuB,MAAA,EAA0B;AACzE,EAAA,IAAI,IAAA,KAAS,SAAA,IAAa,IAAA,KAAS,aAAA,EAAe,OAAO,IAAA;AACzD,EAAA,IAAI,IAAA,KAAS,QAAA,IAAY,MAAA,IAAU,MAAA,IAAU,KAAK,OAAO,IAAA;AACzD,EAAA,OAAO,KAAA;AACT;AAGO,SAAS,eAAA,CAAgB,QAAgB,IAAA,EAA4B;AAC1E,EAAA,MAAM,MAAO,IAAA,EAAiE,KAAA;AAC9E,EAAA,MAAM,GAAA,GAAM,GAAA,EAAK,OAAA,IAAW,CAAA,2BAAA,EAA8B,MAAM,CAAA,CAAA;AAChE,EAAA,MAAM,IAAA,GAAA,CAAQ,GAAA,EAAK,IAAA,IAAQ,EAAA,EAAI,WAAA,EAAY;AAE3C,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,UAAU,MAAA,EAAQ,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAC5D;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,UAAU,MAAA,EAAQ,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAC5D;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,UAAU,YAAA,EAAc,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAClE;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,UAAU,YAAA,EAAc,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAClE;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAKlB,IAAA,IAAI,SAAS,cAAA,EAAgB;AAC3B,MAAA,OAAO,UAAU,YAAA,EAAc,kBAAA,EAAoB,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,IACjF;AACA,IAAA,OAAO,UAAU,YAAA,EAAc,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAClE;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAGlB,IAAA,OAAO,UAAU,QAAA,EAAU,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAC9D;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,MAAM,UAAU,IAAA,KAAS,gBAAA;AACzB,IAAA,OAAO,SAAA,CAAU,OAAA,GAAU,OAAA,GAAU,SAAA,EAAW,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,CAAC,OAAA,EAAS,CAAA;AAAA,EACtF;AACA,EAAA,IAAI,UAAU,GAAA,EAAK;AACjB,IAAA,OAAO,UAAU,QAAA,EAAU,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,MAAM,CAAA;AAAA,EAC7D;AACA,EAAA,OAAO,UAAU,QAAA,EAAU,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAC9D","file":"chunk-XBQENFBZ.js","sourcesContent":["import type { UploadError, UploadErrorCode } from './types.js';\n\n// Single source of truth for the 0-byte message. Used by the client-side guard\n// (uploader), the picker UI, and the server-side reject (mapped from a 422\n// EMPTY_UPLOAD), so the end user sees the same actionable text no matter where\n// the empty file was caught.\nexport const EMPTY_FILE_MESSAGE =\n \"This file is empty (0 bytes) and can't be uploaded. If it's stored in iCloud, \" +\n 'OneDrive, or Google Drive, open it once to download it to this device, then try again.';\n\nexport function makeError(\n code: UploadErrorCode,\n message: string,\n opts: { status?: number; retryable?: boolean; cause?: unknown } = {}\n): UploadError {\n return {\n code,\n message,\n status: opts.status,\n retryable: opts.retryable ?? defaultRetryable(code, opts.status),\n cause: opts.cause,\n };\n}\n\nfunction defaultRetryable(code: UploadErrorCode, status?: number): boolean {\n if (code === 'NETWORK' || code === 'PART_FAILED') return true;\n if (code === 'SERVER' && status && status >= 500) return true;\n return false;\n}\n\n/** Map an HTTP error response from the cdn-be API to an UploadError. */\nexport function fromApiResponse(status: number, body: unknown): UploadError {\n const err = (body as { error?: { code?: string; message?: string } } | null)?.error;\n const msg = err?.message || `Request failed with status ${status}`;\n const code = (err?.code || '').toUpperCase();\n\n if (status === 401) {\n return makeError('AUTH', msg, { status, retryable: false });\n }\n if (status === 403) {\n return makeError('AUTH', msg, { status, retryable: false });\n }\n if (status === 413) {\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 415) {\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 422) {\n // Server rejected the assembled object. EMPTY_UPLOAD (0 bytes landed) gets\n // the dedicated code + canonical message so it reads the same as a\n // client-side empty catch; other 422s fall back to VALIDATION. Either way,\n // retrying the same source file won't help, so it's not retryable.\n if (code === 'EMPTY_UPLOAD') {\n return makeError('EMPTY_FILE', EMPTY_FILE_MESSAGE, { status, retryable: false });\n }\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 426) {\n // Server-enforced minimum SDK version. Not retryable — the integrator\n // must upgrade the package (or reload, for script-loader users).\n return makeError('CONFIG', msg, { status, retryable: false });\n }\n if (status === 429) {\n const isQuota = code === 'QUOTA_EXCEEDED';\n return makeError(isQuota ? 'QUOTA' : 'NETWORK', msg, { status, retryable: !isQuota });\n }\n if (status >= 500) {\n return makeError('SERVER', msg, { status, retryable: true });\n }\n return makeError('SERVER', msg, { status, retryable: false });\n}\n"]}