@tier0/sdk-v2 0.8.0 → 0.9.1

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 (106) hide show
  1. package/NOTICE.md +3 -1
  2. package/README.md +45 -11
  3. package/dist/cjs/capabilities.d.ts +8 -17
  4. package/dist/cjs/capabilities.js +17 -28
  5. package/dist/cjs/capabilities.js.map +1 -1
  6. package/dist/cjs/client.d.ts +524 -3
  7. package/dist/cjs/client.js +29 -6
  8. package/dist/cjs/client.js.map +1 -1
  9. package/dist/cjs/cloud-transport.d.ts +4 -2
  10. package/dist/cjs/cloud-transport.js +27 -18
  11. package/dist/cjs/cloud-transport.js.map +1 -1
  12. package/dist/cjs/files.d.ts +26 -6
  13. package/dist/cjs/files.js +151 -28
  14. package/dist/cjs/files.js.map +1 -1
  15. package/dist/cjs/index.d.ts +2 -1
  16. package/dist/cjs/index.js +3 -1
  17. package/dist/cjs/index.js.map +1 -1
  18. package/dist/cjs/openapi/api.generated.d.ts +1 -1
  19. package/dist/cjs/openapi/codecs.generated.d.ts +30 -161
  20. package/dist/cjs/openapi/codecs.generated.js +1 -1
  21. package/dist/cjs/openapi/codecs.generated.js.map +1 -1
  22. package/dist/cjs/openapi/types.generated.d.ts +33 -85
  23. package/dist/cjs/openapi/types.generated.js.map +1 -1
  24. package/dist/cjs/runtime.d.ts +13 -0
  25. package/dist/cjs/runtime.js +51 -0
  26. package/dist/cjs/runtime.js.map +1 -0
  27. package/dist/cjs/streams/capabilities.d.ts +8 -0
  28. package/dist/cjs/streams/capabilities.js +19 -0
  29. package/dist/cjs/streams/capabilities.js.map +1 -0
  30. package/dist/cjs/streams/contract.generated.d.ts +802 -0
  31. package/dist/cjs/streams/contract.generated.js +7 -0
  32. package/dist/cjs/streams/contract.generated.js.map +1 -0
  33. package/dist/cjs/streams/index.d.ts +3 -0
  34. package/dist/cjs/streams/index.js +20 -0
  35. package/dist/cjs/streams/index.js.map +1 -0
  36. package/dist/cjs/streams/messages.d.ts +42 -0
  37. package/dist/cjs/streams/messages.js +514 -0
  38. package/dist/cjs/streams/messages.js.map +1 -0
  39. package/dist/cjs/streams/requests.d.ts +93 -0
  40. package/dist/cjs/streams/requests.js +167 -0
  41. package/dist/cjs/streams/requests.js.map +1 -0
  42. package/dist/cjs/streams/transport.d.ts +16 -0
  43. package/dist/cjs/streams/transport.js +24 -0
  44. package/dist/cjs/streams/transport.js.map +1 -0
  45. package/dist/cjs/uns-v2/generated.d.ts +87 -22
  46. package/dist/cjs/uns-v2/generated.js +43 -8
  47. package/dist/cjs/uns-v2/generated.js.map +1 -1
  48. package/dist/esm/capabilities.d.ts +8 -17
  49. package/dist/esm/capabilities.js +17 -28
  50. package/dist/esm/capabilities.js.map +1 -1
  51. package/dist/esm/client.d.ts +524 -3
  52. package/dist/esm/client.js +27 -5
  53. package/dist/esm/client.js.map +1 -1
  54. package/dist/esm/cloud-transport.d.ts +4 -2
  55. package/dist/esm/cloud-transport.js +27 -18
  56. package/dist/esm/cloud-transport.js.map +1 -1
  57. package/dist/esm/files.d.ts +26 -6
  58. package/dist/esm/files.js +151 -28
  59. package/dist/esm/files.js.map +1 -1
  60. package/dist/esm/index.d.ts +2 -1
  61. package/dist/esm/index.js +2 -1
  62. package/dist/esm/index.js.map +1 -1
  63. package/dist/esm/openapi/api.generated.d.ts +1 -1
  64. package/dist/esm/openapi/codecs.generated.d.ts +30 -161
  65. package/dist/esm/openapi/codecs.generated.js +1 -1
  66. package/dist/esm/openapi/codecs.generated.js.map +1 -1
  67. package/dist/esm/openapi/types.generated.d.ts +33 -85
  68. package/dist/esm/openapi/types.generated.js.map +1 -1
  69. package/dist/esm/runtime.d.ts +13 -0
  70. package/dist/esm/runtime.js +46 -0
  71. package/dist/esm/runtime.js.map +1 -0
  72. package/dist/esm/streams/capabilities.d.ts +8 -0
  73. package/dist/esm/streams/capabilities.js +15 -0
  74. package/dist/esm/streams/capabilities.js.map +1 -0
  75. package/dist/esm/streams/contract.generated.d.ts +802 -0
  76. package/dist/esm/streams/contract.generated.js +6 -0
  77. package/dist/esm/streams/contract.generated.js.map +1 -0
  78. package/dist/esm/streams/index.d.ts +3 -0
  79. package/dist/esm/streams/index.js +4 -0
  80. package/dist/esm/streams/index.js.map +1 -0
  81. package/dist/esm/streams/messages.d.ts +42 -0
  82. package/dist/esm/streams/messages.js +475 -0
  83. package/dist/esm/streams/messages.js.map +1 -0
  84. package/dist/esm/streams/requests.d.ts +93 -0
  85. package/dist/esm/streams/requests.js +161 -0
  86. package/dist/esm/streams/requests.js.map +1 -0
  87. package/dist/esm/streams/transport.d.ts +16 -0
  88. package/dist/esm/streams/transport.js +20 -0
  89. package/dist/esm/streams/transport.js.map +1 -0
  90. package/dist/esm/uns-v2/generated.d.ts +87 -22
  91. package/dist/esm/uns-v2/generated.js +43 -8
  92. package/dist/esm/uns-v2/generated.js.map +1 -1
  93. package/package.json +46 -12
  94. package/skills/tier0-sdk-v2/SKILL.md +3 -2
  95. package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/multipart.md +23 -8
  96. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/SKILL.md +3 -3
  97. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/create.md +9 -3
  98. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/state.md +1 -1
  99. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/update.md +1 -1
  100. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/SKILL.md +2 -1
  101. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/create.md +13 -4
  102. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/deploy.md +1 -1
  103. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/update.md +1 -1
  104. package/skills/tier0-sdk-v2/tier0-sdk-v2-streams/SKILL.md +67 -0
  105. package/skills/tier0-sdk-v2/tier0-sdk-v2-system/SKILL.md +5 -9
  106. package/skills/tier0-sdk-v2/tier0-sdk-v2-system/references/info.md +1 -1
@@ -1,3 +1,4 @@
1
+ import type { AppRuntime } from './runtime.js';
1
2
  import { type HttpClient, type RequestOptions } from './openapi/client.js';
2
3
  import { type UnsV2OperationName, type UnsV2StreamOperationName } from './uns-v2/generated.js';
3
4
  export interface CloudTransportConfig {
@@ -30,7 +31,8 @@ export declare class CloudTransportError extends Error {
30
31
  export declare class CloudTransport {
31
32
  #private;
32
33
  private readonly resolveClient;
33
- private readonly timeoutMs;
34
+ private readonly configuredTimeoutMs;
35
+ private get timeoutMs();
34
36
  private readonly unsV2MaxResponseBytes;
35
37
  constructor(resolveClient?: () => HttpClient, config?: CloudTransportConfig);
36
38
  /** `retryAfter`: the raw `Retry-After` header, for answers without a UNS error body. */
@@ -59,7 +61,7 @@ export declare class CloudTransport {
59
61
  status: number;
60
62
  text: string;
61
63
  }>;
62
- post(path: string, body: unknown): Promise<{
64
+ post(path: string, body: unknown, signal?: AbortSignal, runtime?: AppRuntime): Promise<{
63
65
  value: unknown;
64
66
  status: number;
65
67
  ok: boolean;
@@ -19,7 +19,8 @@ export class CloudTransportError extends Error {
19
19
  /** Single fetch, no redirects/retries; one deadline covers both headers and body. */
20
20
  export class CloudTransport {
21
21
  resolveClient;
22
- timeoutMs;
22
+ configuredTimeoutMs;
23
+ get timeoutMs() { return this.configuredTimeoutMs ?? this.resolveClient().timeoutMs; }
23
24
  unsV2MaxResponseBytes;
24
25
  #unsV2AppDataSubject;
25
26
  constructor(resolveClient = getClient, config = {}) {
@@ -28,7 +29,7 @@ export class CloudTransport {
28
29
  if (!Number.isInteger(timeout) || timeout < 1 || timeout > 2_147_483_647) {
29
30
  throw new TypeError('Tier0 SDK: transportTimeoutMs must be an integer between 1 and 2147483647.');
30
31
  }
31
- this.timeoutMs = timeout;
32
+ this.configuredTimeoutMs = config.transportTimeoutMs;
32
33
  const maxResponseBytes = config.unsV2MaxResponseBytes ?? UNS_V2_MAX_RESPONSE_BYTES;
33
34
  if (!Number.isInteger(maxResponseBytes) || maxResponseBytes < 1 || maxResponseBytes > UNS_V2_MAX_RESPONSE_BYTES) {
34
35
  throw new TypeError('Tier0 SDK: unsV2MaxResponseBytes must be an integer between 1 and 20971520.');
@@ -220,22 +221,30 @@ export class CloudTransport {
220
221
  close();
221
222
  }
222
223
  }
223
- async post(path, body) {
224
- const client = this.resolveClient();
225
- const url = `${client.getBaseURL()}${path}`;
226
- const key = client.getApiKey();
227
- const headers = { 'Content-Type': 'application/json' };
228
- if (key) {
229
- headers.Authorization = `Bearer ${key}`;
230
- headers['X-API-Key'] = key;
231
- }
224
+ async post(path, body, signal, runtime) {
232
225
  const serialized = JSON.stringify(body);
233
226
  const controller = new AbortController();
227
+ const abort = () => controller.abort();
228
+ signal?.addEventListener('abort', abort, { once: true });
229
+ if (signal?.aborted)
230
+ controller.abort();
234
231
  let response;
235
232
  let timer;
236
233
  const exchange = async () => {
237
234
  try {
238
- response = await client.getFetch()(url, { method: 'POST', headers, body: serialized, redirect: 'manual', signal: controller.signal });
235
+ if (runtime)
236
+ response = await runtime.request(path, body, { signal: controller.signal });
237
+ else {
238
+ const client = this.resolveClient();
239
+ const url = `${client.getBaseURL()}${path}`;
240
+ const key = client.getApiKey();
241
+ const headers = { 'Content-Type': 'application/json' };
242
+ if (key) {
243
+ headers.Authorization = `Bearer ${key}`;
244
+ headers['X-API-Key'] = key;
245
+ }
246
+ response = await client.getFetch()(url, { method: 'POST', headers, body: serialized, redirect: 'manual', signal: controller.signal });
247
+ }
239
248
  }
240
249
  catch {
241
250
  throw new CloudTransportError('TRANSPORT_ERROR');
@@ -251,21 +260,21 @@ export class CloudTransport {
251
260
  };
252
261
  try {
253
262
  const deadline = new Promise((_resolve, reject) => {
263
+ const stopped = () => reject(new CloudTransportError('TRANSPORT_ERROR', response?.status));
264
+ controller.signal.addEventListener('abort', stopped, { once: true });
265
+ if (controller.signal.aborted)
266
+ stopped();
254
267
  timer = setTimeout(() => {
255
- controller.abort();
256
268
  reject(new CloudTransportError('TRANSPORT_TIMEOUT', response?.status));
269
+ controller.abort();
257
270
  }, this.timeoutMs);
258
271
  });
259
272
  // Also bounds custom transports which ignore AbortSignal.
260
273
  return await Promise.race([exchange(), deadline]);
261
274
  }
262
- catch (error) {
263
- if (controller.signal.aborted)
264
- throw new CloudTransportError('TRANSPORT_TIMEOUT', response?.status);
265
- throw error;
266
- }
267
275
  finally {
268
276
  clearTimeout(timer);
277
+ signal?.removeEventListener('abort', abort);
269
278
  }
270
279
  }
271
280
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-transport.js","sourceRoot":"","sources":["../../src/cloud-transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { getClient, type HttpClient, type RequestOptions } from './openapi/client.js';\nimport { UNS_V2_OPERATIONS, UNS_V2_STREAM_OPERATIONS, type UnsV2OperationName, type UnsV2StreamOperationName } from './uns-v2/generated.js';\n\nexport interface CloudTransportConfig {\n /** Whole HTTP exchange including the response body, in milliseconds; default 60,000. */\n transportTimeoutMs?: number;\n /** UNS v2 response body limit; may only tighten the 20 MiB contract/RPC ceiling. */\n unsV2MaxResponseBytes?: number;\n /**\n * Opaque proof from the trusted App Gateway only: tier0.app-data-subject/v1,\n * X-Tier0-App-Data-Subject, aud tier0-uns-data. Proof alone is not authentication;\n * the SDK checks only compact syntax, never parses or trusts claims.\n * Create a new client per incoming request; never reuse a token across users.\n * Do not automatically forward the runtime App request assertion: its audience differs.\n */\n unsV2AppDataSubject?: string;\n}\n\nexport const DEFAULT_CLOUD_TRANSPORT_TIMEOUT_MS = 60_000;\n/** Header carrying `unsV2AppDataSubject`; the trusted App Gateway sets it on each business request. */\nexport const UNS_V2_APP_DATA_SUBJECT_HEADER = 'X-Tier0-App-Data-Subject';\nexport const UNS_V2_MAX_REQUEST_BYTES = 16 << 20;\nexport const UNS_V2_MAX_RESPONSE_BYTES = 20 << 20;\n\ntype Failure = 'TRANSPORT_ERROR' | 'PROTOCOL_ERROR' | 'TRANSPORT_TIMEOUT' | 'TRANSPORT_ABORTED';\n\n/** Internal redacted failure, translated by each public contract client. */\nexport class CloudTransportError extends Error {\n constructor(readonly kind: Failure, readonly status?: number) {\n super(kind);\n this.name = 'CloudTransportError';\n }\n}\n\n/** Single fetch, no redirects/retries; one deadline covers both headers and body. */\nexport class CloudTransport {\n private readonly timeoutMs: number;\n private readonly unsV2MaxResponseBytes: number;\n readonly #unsV2AppDataSubject: string | undefined;\n\n constructor(private readonly resolveClient: () => HttpClient = getClient, config: CloudTransportConfig = {}) {\n const timeout = config.transportTimeoutMs ?? DEFAULT_CLOUD_TRANSPORT_TIMEOUT_MS;\n if (!Number.isInteger(timeout) || timeout < 1 || timeout > 2_147_483_647) {\n throw new TypeError('Tier0 SDK: transportTimeoutMs must be an integer between 1 and 2147483647.');\n }\n this.timeoutMs = timeout;\n const maxResponseBytes = config.unsV2MaxResponseBytes ?? UNS_V2_MAX_RESPONSE_BYTES;\n if (!Number.isInteger(maxResponseBytes) || maxResponseBytes < 1 || maxResponseBytes > UNS_V2_MAX_RESPONSE_BYTES) {\n throw new TypeError('Tier0 SDK: unsV2MaxResponseBytes must be an integer between 1 and 20971520.');\n }\n this.unsV2MaxResponseBytes = maxResponseBytes;\n const subject = config.unsV2AppDataSubject;\n // ASCII-only syntax makes string length equal byte length. Do not trim or decode.\n if (subject !== undefined && (typeof subject !== 'string' || subject.length > 8192 || /[^A-Za-z0-9_.-]/.test(subject) ||\n !/^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/.test(subject))) {\n throw new TypeError('Tier0 SDK: unsV2AppDataSubject must be a compact three-segment base64url token of at most 8192 ASCII bytes.');\n }\n this.#unsV2AppDataSubject = subject;\n }\n\n /** `retryAfter`: the raw `Retry-After` header, for answers without a UNS error body. */\n async postText(path: string, body: string, options: RequestOptions = {}, operation?: UnsV2OperationName): Promise<{ text: string; status: number; ok: boolean; retryAfter?: string }> {\n options.signal?.throwIfAborted();\n const client = this.resolveClient();\n const url = `${client.getBaseURL()}${path}`;\n const key = client.getApiKey();\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n // The registered operation determines data delegation, never a route blacklist.\n if (operation !== undefined && Object.hasOwn(UNS_V2_OPERATIONS, operation) &&\n UNS_V2_OPERATIONS[operation].scope.startsWith('uns:') &&\n this.#unsV2AppDataSubject !== undefined) {\n headers[UNS_V2_APP_DATA_SUBJECT_HEADER] = this.#unsV2AppDataSubject;\n }\n if (key) {\n headers.Authorization = `Bearer ${key}`;\n headers['X-API-Key'] = key;\n }\n const controller = new AbortController();\n let response: Response | undefined;\n let reader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let rejectAbort: (error: Error) => void = () => undefined;\n const cancelled = new Promise<never>((_, reject) => { rejectAbort = reject; });\n const onAbort = () => {\n controller.abort();\n void reader?.cancel().catch(() => undefined);\n rejectAbort(new CloudTransportError('TRANSPORT_ABORTED', response?.status));\n };\n options.signal?.addEventListener('abort', onAbort, { once: true });\n const exchange = async () => {\n try {\n response = await client.getFetch()(url, { method: 'POST', headers, body, redirect: 'manual', signal: controller.signal });\n } catch {\n throw new CloudTransportError('TRANSPORT_ERROR');\n }\n const declaredLength = response.headers.get('content-length');\n if (declaredLength !== null && /^\\d+$/.test(declaredLength) && Number(declaredLength) > this.unsV2MaxResponseBytes) {\n await response.body?.cancel().catch(() => undefined);\n throw new CloudTransportError('PROTOCOL_ERROR', response.status);\n }\n if (!response.body) throw new CloudTransportError('PROTOCOL_ERROR', response.status);\n try { reader = response.body.getReader(); }\n catch { throw new CloudTransportError('PROTOCOL_ERROR', response.status); }\n const decoder = new TextDecoder('utf-8', { fatal: true });\n const chunks: string[] = [];\n let receivedBytes = 0;\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n receivedBytes += value.byteLength;\n if (receivedBytes > this.unsV2MaxResponseBytes) {\n await reader.cancel().catch(() => undefined);\n throw new CloudTransportError('PROTOCOL_ERROR', response.status);\n }\n chunks.push(decoder.decode(value, { stream: true }));\n }\n chunks.push(decoder.decode());\n } catch (error) {\n if (error instanceof CloudTransportError) throw error;\n throw new CloudTransportError('PROTOCOL_ERROR', response.status);\n } finally {\n reader.releaseLock();\n reader = undefined;\n }\n const retryAfter = response.headers.get('retry-after') ?? undefined;\n return { text: chunks.join(''), status: response.status, ok: response.ok, ...(retryAfter === undefined ? {} : { retryAfter }) };\n };\n try {\n const deadline = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n controller.abort();\n void reader?.cancel().catch(() => undefined);\n reject(new CloudTransportError('TRANSPORT_TIMEOUT', response?.status));\n }, this.timeoutMs);\n });\n // Also bounds custom transports which ignore AbortSignal.\n return await Promise.race([exchange(), deadline, cancelled]);\n } catch (error) {\n if (controller.signal.aborted) throw new CloudTransportError(options.signal?.aborted ? 'TRANSPORT_ABORTED' : 'TRANSPORT_TIMEOUT', response?.status);\n throw error;\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener('abort', onAbort);\n }\n }\n\n /**\n * Opens a server-sent event stream (GET, `Accept: text/event-stream`\n * exactly, as the gateway requires). The deadline covers the response\n * headers, and a non-stream body; a response that is not an event stream\n * is read whole (bounded like any UNS v2 response) and returned as `text`.\n * An open stream belongs to the caller: `close()` ends it and drops the\n * link to `signal`, which also ends it.\n */\n async getEventStream(path: string, options: { lastEventId?: string; signal?: AbortSignal } = {}, operation?: UnsV2StreamOperationName):\n Promise<{ status: number; stream: ReadableStream<Uint8Array>; close(): void } | { status: number; text: string }> {\n options.signal?.throwIfAborted();\n const client = this.resolveClient();\n const url = `${client.getBaseURL()}${path}`;\n const key = client.getApiKey();\n const headers: Record<string, string> = { Accept: 'text/event-stream' };\n if (operation !== undefined && Object.hasOwn(UNS_V2_STREAM_OPERATIONS, operation) &&\n UNS_V2_STREAM_OPERATIONS[operation].scope.startsWith('uns:') && this.#unsV2AppDataSubject !== undefined) {\n headers[UNS_V2_APP_DATA_SUBJECT_HEADER] = this.#unsV2AppDataSubject;\n }\n if (options.lastEventId !== undefined) headers['Last-Event-ID'] = options.lastEventId;\n if (key) {\n headers.Authorization = `Bearer ${key}`;\n headers['X-API-Key'] = key;\n }\n const controller = new AbortController();\n const onAbort = () => controller.abort();\n const close = () => {\n options.signal?.removeEventListener('abort', onAbort);\n controller.abort();\n };\n options.signal?.addEventListener('abort', onAbort, { once: true });\n let expired = false;\n const timer = setTimeout(() => { expired = true; controller.abort(); }, this.timeoutMs);\n const failure = (kind: Failure, status?: number) =>\n new CloudTransportError(expired ? 'TRANSPORT_TIMEOUT' : controller.signal.aborted ? 'TRANSPORT_ABORTED' : kind, status);\n let response: Response;\n try {\n response = await client.getFetch()(url, { method: 'GET', headers, redirect: 'manual', signal: controller.signal });\n } catch {\n clearTimeout(timer);\n close();\n throw failure('TRANSPORT_ERROR');\n }\n const type = response.headers.get('content-type') ?? '';\n if (response.status === 200 && /^text\\/event-stream\\b/i.test(type) && response.body) {\n clearTimeout(timer);\n return { status: response.status, stream: response.body, close };\n }\n try {\n if (!response.body) return { status: response.status, text: '' };\n const reader = response.body.getReader();\n const decoder = new TextDecoder('utf-8', { fatal: true });\n const chunks: string[] = [];\n let size = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n size += value.byteLength;\n if (size > this.unsV2MaxResponseBytes) {\n await reader.cancel().catch(() => undefined);\n throw new CloudTransportError('PROTOCOL_ERROR', response.status);\n }\n chunks.push(decoder.decode(value, { stream: true }));\n }\n chunks.push(decoder.decode());\n return { status: response.status, text: chunks.join('') };\n } catch (error) {\n if (error instanceof CloudTransportError) throw error;\n throw failure('PROTOCOL_ERROR', response.status);\n } finally {\n clearTimeout(timer);\n close();\n }\n }\n\n async post(path: string, body: unknown): Promise<{ value: unknown; status: number; ok: boolean }> {\n const client = this.resolveClient();\n const url = `${client.getBaseURL()}${path}`;\n const key = client.getApiKey();\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (key) {\n headers.Authorization = `Bearer ${key}`;\n headers['X-API-Key'] = key;\n }\n const serialized = JSON.stringify(body);\n const controller = new AbortController();\n let response: Response | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const exchange = async () => {\n try {\n response = await client.getFetch()(url, { method: 'POST', headers, body: serialized, redirect: 'manual', signal: controller.signal });\n } catch {\n throw new CloudTransportError('TRANSPORT_ERROR');\n }\n let value: unknown;\n try {\n value = await response.json();\n } catch {\n throw new CloudTransportError('PROTOCOL_ERROR', response.status);\n }\n return { value, status: response.status, ok: response.ok };\n };\n try {\n const deadline = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n controller.abort();\n reject(new CloudTransportError('TRANSPORT_TIMEOUT', response?.status));\n }, this.timeoutMs);\n });\n // Also bounds custom transports which ignore AbortSignal.\n return await Promise.race([exchange(), deadline]);\n } catch (error) {\n if (controller.signal.aborted) throw new CloudTransportError('TRANSPORT_TIMEOUT', response?.status);\n throw error;\n } finally {\n clearTimeout(timer);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"cloud-transport.js","sourceRoot":"","sources":["../../src/cloud-transport.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AppRuntime } from './runtime.js';\nimport { getClient, type HttpClient, type RequestOptions } from './openapi/client.js';\nimport { UNS_V2_OPERATIONS, UNS_V2_STREAM_OPERATIONS, type UnsV2OperationName, type UnsV2StreamOperationName } from './uns-v2/generated.js';\n\nexport interface CloudTransportConfig {\n /** Whole HTTP exchange including the response body, in milliseconds; default 60,000. */\n transportTimeoutMs?: number;\n /** UNS v2 response body limit; may only tighten the 20 MiB contract/RPC ceiling. */\n unsV2MaxResponseBytes?: number;\n /**\n * Opaque proof from the trusted App Gateway only: tier0.app-data-subject/v1,\n * X-Tier0-App-Data-Subject, aud tier0-uns-data. Proof alone is not authentication;\n * the SDK checks only compact syntax, never parses or trusts claims.\n * Create a new client per incoming request; never reuse a token across users.\n * Do not automatically forward the runtime App request assertion: its audience differs.\n */\n unsV2AppDataSubject?: string;\n}\n\nexport const DEFAULT_CLOUD_TRANSPORT_TIMEOUT_MS = 60_000;\n/** Header carrying `unsV2AppDataSubject`; the trusted App Gateway sets it on each business request. */\nexport const UNS_V2_APP_DATA_SUBJECT_HEADER = 'X-Tier0-App-Data-Subject';\nexport const UNS_V2_MAX_REQUEST_BYTES = 16 << 20;\nexport const UNS_V2_MAX_RESPONSE_BYTES = 20 << 20;\n\ntype Failure = 'TRANSPORT_ERROR' | 'PROTOCOL_ERROR' | 'TRANSPORT_TIMEOUT' | 'TRANSPORT_ABORTED';\n\n/** Internal redacted failure, translated by each public contract client. */\nexport class CloudTransportError extends Error {\n constructor(readonly kind: Failure, readonly status?: number) {\n super(kind);\n this.name = 'CloudTransportError';\n }\n}\n\n/** Single fetch, no redirects/retries; one deadline covers both headers and body. */\nexport class CloudTransport {\n private readonly configuredTimeoutMs: number | undefined;\n private get timeoutMs(): number { return this.configuredTimeoutMs ?? this.resolveClient().timeoutMs; }\n private readonly unsV2MaxResponseBytes: number;\n readonly #unsV2AppDataSubject: string | undefined;\n\n constructor(private readonly resolveClient: () => HttpClient = getClient, config: CloudTransportConfig = {}) {\n const timeout = config.transportTimeoutMs ?? DEFAULT_CLOUD_TRANSPORT_TIMEOUT_MS;\n if (!Number.isInteger(timeout) || timeout < 1 || timeout > 2_147_483_647) {\n throw new TypeError('Tier0 SDK: transportTimeoutMs must be an integer between 1 and 2147483647.');\n }\n this.configuredTimeoutMs = config.transportTimeoutMs;\n const maxResponseBytes = config.unsV2MaxResponseBytes ?? UNS_V2_MAX_RESPONSE_BYTES;\n if (!Number.isInteger(maxResponseBytes) || maxResponseBytes < 1 || maxResponseBytes > UNS_V2_MAX_RESPONSE_BYTES) {\n throw new TypeError('Tier0 SDK: unsV2MaxResponseBytes must be an integer between 1 and 20971520.');\n }\n this.unsV2MaxResponseBytes = maxResponseBytes;\n const subject = config.unsV2AppDataSubject;\n // ASCII-only syntax makes string length equal byte length. Do not trim or decode.\n if (subject !== undefined && (typeof subject !== 'string' || subject.length > 8192 || /[^A-Za-z0-9_.-]/.test(subject) ||\n !/^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/.test(subject))) {\n throw new TypeError('Tier0 SDK: unsV2AppDataSubject must be a compact three-segment base64url token of at most 8192 ASCII bytes.');\n }\n this.#unsV2AppDataSubject = subject;\n }\n\n /** `retryAfter`: the raw `Retry-After` header, for answers without a UNS error body. */\n async postText(path: string, body: string, options: RequestOptions = {}, operation?: UnsV2OperationName): Promise<{ text: string; status: number; ok: boolean; retryAfter?: string }> {\n options.signal?.throwIfAborted();\n const client = this.resolveClient();\n const url = `${client.getBaseURL()}${path}`;\n const key = client.getApiKey();\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n // The registered operation determines data delegation, never a route blacklist.\n if (operation !== undefined && Object.hasOwn(UNS_V2_OPERATIONS, operation) &&\n UNS_V2_OPERATIONS[operation].scope.startsWith('uns:') &&\n this.#unsV2AppDataSubject !== undefined) {\n headers[UNS_V2_APP_DATA_SUBJECT_HEADER] = this.#unsV2AppDataSubject;\n }\n if (key) {\n headers.Authorization = `Bearer ${key}`;\n headers['X-API-Key'] = key;\n }\n const controller = new AbortController();\n let response: Response | undefined;\n let reader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let rejectAbort: (error: Error) => void = () => undefined;\n const cancelled = new Promise<never>((_, reject) => { rejectAbort = reject; });\n const onAbort = () => {\n controller.abort();\n void reader?.cancel().catch(() => undefined);\n rejectAbort(new CloudTransportError('TRANSPORT_ABORTED', response?.status));\n };\n options.signal?.addEventListener('abort', onAbort, { once: true });\n const exchange = async () => {\n try {\n response = await client.getFetch()(url, { method: 'POST', headers, body, redirect: 'manual', signal: controller.signal });\n } catch {\n throw new CloudTransportError('TRANSPORT_ERROR');\n }\n const declaredLength = response.headers.get('content-length');\n if (declaredLength !== null && /^\\d+$/.test(declaredLength) && Number(declaredLength) > this.unsV2MaxResponseBytes) {\n await response.body?.cancel().catch(() => undefined);\n throw new CloudTransportError('PROTOCOL_ERROR', response.status);\n }\n if (!response.body) throw new CloudTransportError('PROTOCOL_ERROR', response.status);\n try { reader = response.body.getReader(); }\n catch { throw new CloudTransportError('PROTOCOL_ERROR', response.status); }\n const decoder = new TextDecoder('utf-8', { fatal: true });\n const chunks: string[] = [];\n let receivedBytes = 0;\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n receivedBytes += value.byteLength;\n if (receivedBytes > this.unsV2MaxResponseBytes) {\n await reader.cancel().catch(() => undefined);\n throw new CloudTransportError('PROTOCOL_ERROR', response.status);\n }\n chunks.push(decoder.decode(value, { stream: true }));\n }\n chunks.push(decoder.decode());\n } catch (error) {\n if (error instanceof CloudTransportError) throw error;\n throw new CloudTransportError('PROTOCOL_ERROR', response.status);\n } finally {\n reader.releaseLock();\n reader = undefined;\n }\n const retryAfter = response.headers.get('retry-after') ?? undefined;\n return { text: chunks.join(''), status: response.status, ok: response.ok, ...(retryAfter === undefined ? {} : { retryAfter }) };\n };\n try {\n const deadline = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n controller.abort();\n void reader?.cancel().catch(() => undefined);\n reject(new CloudTransportError('TRANSPORT_TIMEOUT', response?.status));\n }, this.timeoutMs);\n });\n // Also bounds custom transports which ignore AbortSignal.\n return await Promise.race([exchange(), deadline, cancelled]);\n } catch (error) {\n if (controller.signal.aborted) throw new CloudTransportError(options.signal?.aborted ? 'TRANSPORT_ABORTED' : 'TRANSPORT_TIMEOUT', response?.status);\n throw error;\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener('abort', onAbort);\n }\n }\n\n /**\n * Opens a server-sent event stream (GET, `Accept: text/event-stream`\n * exactly, as the gateway requires). The deadline covers the response\n * headers, and a non-stream body; a response that is not an event stream\n * is read whole (bounded like any UNS v2 response) and returned as `text`.\n * An open stream belongs to the caller: `close()` ends it and drops the\n * link to `signal`, which also ends it.\n */\n async getEventStream(path: string, options: { lastEventId?: string; signal?: AbortSignal } = {}, operation?: UnsV2StreamOperationName):\n Promise<{ status: number; stream: ReadableStream<Uint8Array>; close(): void } | { status: number; text: string }> {\n options.signal?.throwIfAborted();\n const client = this.resolveClient();\n const url = `${client.getBaseURL()}${path}`;\n const key = client.getApiKey();\n const headers: Record<string, string> = { Accept: 'text/event-stream' };\n if (operation !== undefined && Object.hasOwn(UNS_V2_STREAM_OPERATIONS, operation) &&\n UNS_V2_STREAM_OPERATIONS[operation].scope.startsWith('uns:') && this.#unsV2AppDataSubject !== undefined) {\n headers[UNS_V2_APP_DATA_SUBJECT_HEADER] = this.#unsV2AppDataSubject;\n }\n if (options.lastEventId !== undefined) headers['Last-Event-ID'] = options.lastEventId;\n if (key) {\n headers.Authorization = `Bearer ${key}`;\n headers['X-API-Key'] = key;\n }\n const controller = new AbortController();\n const onAbort = () => controller.abort();\n const close = () => {\n options.signal?.removeEventListener('abort', onAbort);\n controller.abort();\n };\n options.signal?.addEventListener('abort', onAbort, { once: true });\n let expired = false;\n const timer = setTimeout(() => { expired = true; controller.abort(); }, this.timeoutMs);\n const failure = (kind: Failure, status?: number) =>\n new CloudTransportError(expired ? 'TRANSPORT_TIMEOUT' : controller.signal.aborted ? 'TRANSPORT_ABORTED' : kind, status);\n let response: Response;\n try {\n response = await client.getFetch()(url, { method: 'GET', headers, redirect: 'manual', signal: controller.signal });\n } catch {\n clearTimeout(timer);\n close();\n throw failure('TRANSPORT_ERROR');\n }\n const type = response.headers.get('content-type') ?? '';\n if (response.status === 200 && /^text\\/event-stream\\b/i.test(type) && response.body) {\n clearTimeout(timer);\n return { status: response.status, stream: response.body, close };\n }\n try {\n if (!response.body) return { status: response.status, text: '' };\n const reader = response.body.getReader();\n const decoder = new TextDecoder('utf-8', { fatal: true });\n const chunks: string[] = [];\n let size = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n size += value.byteLength;\n if (size > this.unsV2MaxResponseBytes) {\n await reader.cancel().catch(() => undefined);\n throw new CloudTransportError('PROTOCOL_ERROR', response.status);\n }\n chunks.push(decoder.decode(value, { stream: true }));\n }\n chunks.push(decoder.decode());\n return { status: response.status, text: chunks.join('') };\n } catch (error) {\n if (error instanceof CloudTransportError) throw error;\n throw failure('PROTOCOL_ERROR', response.status);\n } finally {\n clearTimeout(timer);\n close();\n }\n }\n\n async post(path: string, body: unknown, signal?: AbortSignal, runtime?: AppRuntime): Promise<{ value: unknown; status: number; ok: boolean }> {\n const serialized = JSON.stringify(body);\n const controller = new AbortController();\n const abort = () => controller.abort();\n signal?.addEventListener('abort', abort, { once: true });\n if (signal?.aborted) controller.abort();\n let response: Response | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const exchange = async () => {\n try {\n if (runtime) response = await runtime.request(path, body, { signal: controller.signal });\n else {\n const client = this.resolveClient();\n const url = `${client.getBaseURL()}${path}`;\n const key = client.getApiKey();\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (key) {\n headers.Authorization = `Bearer ${key}`;\n headers['X-API-Key'] = key;\n }\n response = await client.getFetch()(url, { method: 'POST', headers, body: serialized, redirect: 'manual', signal: controller.signal });\n }\n } catch {\n throw new CloudTransportError('TRANSPORT_ERROR');\n }\n let value: unknown;\n try {\n value = await response.json();\n } catch {\n throw new CloudTransportError('PROTOCOL_ERROR', response.status);\n }\n return { value, status: response.status, ok: response.ok };\n };\n try {\n const deadline = new Promise<never>((_resolve, reject) => {\n const stopped = () => reject(new CloudTransportError('TRANSPORT_ERROR', response?.status));\n controller.signal.addEventListener('abort', stopped, { once: true });\n if (controller.signal.aborted) stopped();\n timer = setTimeout(() => {\n reject(new CloudTransportError('TRANSPORT_TIMEOUT', response?.status));\n controller.abort();\n }, this.timeoutMs);\n });\n // Also bounds custom transports which ignore AbortSignal.\n return await Promise.race([exchange(), deadline]);\n } finally {\n clearTimeout(timer);\n signal?.removeEventListener('abort', abort);\n }\n }\n}\n"]}
@@ -1,21 +1,36 @@
1
1
  import { HttpClient, type ClientConfig, type RequestOptions } from './openapi/client.js';
2
2
  import type { components } from './openapi/types.generated.js';
3
3
  type Schemas = components['schemas'];
4
- export type UploadOptions = Omit<Schemas['AssetFileUploadReq'], 'fileName' | 'contentType' | 'size'> & RequestOptions;
4
+ export type UploadOptions = Omit<Schemas['AssetFileUploadReq'], 'fileName' | 'contentType' | 'size'> & RequestOptions & {
5
+ multipart?: MultipartSettings;
6
+ };
5
7
  export type UploadResult = Schemas['AssetFileUploadResp'];
6
8
  export type MultipartResult = Schemas['AssetFileMultipartCompleteResp'];
7
- export interface MultipartOptions extends UploadOptions {
9
+ export interface MultipartProgress {
10
+ uploadedBytes: number;
11
+ totalBytes: number;
12
+ doneParts: number;
13
+ totalParts: number;
14
+ percent: number;
15
+ }
16
+ export interface ResumeMultipartOptions extends RequestOptions {
17
+ concurrency?: number;
18
+ maxRetries?: number;
19
+ onProgress?: (progress: MultipartProgress) => void;
20
+ }
21
+ export interface MultipartSettings extends Omit<ResumeMultipartOptions, 'signal'> {
8
22
  partSize?: number;
9
- onProgress?: (progress: {
10
- uploadedBytes: number;
11
- totalBytes: number;
12
- }) => void;
23
+ }
24
+ export interface MultipartOptions extends Omit<UploadOptions, 'multipart'>, MultipartSettings {
13
25
  }
14
26
  export interface MultipartSession {
15
27
  fileKey: string;
16
28
  uploadId: string;
17
29
  parts: Schemas['AssetFileMultipartPart'][];
18
30
  completionAttempted: boolean;
31
+ partSize?: number;
32
+ fileName?: string;
33
+ fileSize?: number;
19
34
  }
20
35
  export declare class MultipartUploadError extends Error {
21
36
  readonly session: MultipartSession;
@@ -24,6 +39,8 @@ export declare class MultipartUploadError extends Error {
24
39
  }
25
40
  export declare const MULTIPART_THRESHOLD_BYTES: number;
26
41
  export declare const DEFAULT_MULTIPART_PART_SIZE: number;
42
+ export declare const DEFAULT_MULTIPART_CONCURRENCY = 4;
43
+ export declare const DEFAULT_MULTIPART_MAX_RETRIES = 3;
27
44
  /** All platform requests are scoped to this instance; storage requests never carry its API key. */
28
45
  export declare class FilesClient {
29
46
  private readonly http;
@@ -54,6 +71,9 @@ export declare class FilesClient {
54
71
  private storage;
55
72
  upload(file: File, options?: UploadOptions): Promise<UploadResult | MultipartResult>;
56
73
  uploadMultipart(file: File, options?: MultipartOptions): Promise<MultipartResult>;
74
+ resumeMultipart(file: File, previous: MultipartSession, options?: ResumeMultipartOptions): Promise<MultipartResult>;
75
+ private putPart;
76
+ private transferMultipart;
57
77
  url(query: Parameters<typeof this.api.url>[0], options?: RequestOptions): Promise<{
58
78
  expiresAt?: number | bigint;
59
79
  fileUrl: string;
package/dist/esm/files.js CHANGED
@@ -1,4 +1,4 @@
1
- import { HttpClient, ApiError } from './openapi/client.js';
1
+ import { HttpClient, ApiError, TransportError } from './openapi/client.js';
2
2
  import { createOpenAPI } from './openapi/api.generated.js';
3
3
  export class MultipartUploadError extends Error {
4
4
  session;
@@ -12,9 +12,11 @@ export class MultipartUploadError extends Error {
12
12
  }
13
13
  export const MULTIPART_THRESHOLD_BYTES = 100 * 1024 * 1024;
14
14
  export const DEFAULT_MULTIPART_PART_SIZE = 8 * 1024 * 1024;
15
+ export const DEFAULT_MULTIPART_CONCURRENCY = 4;
16
+ export const DEFAULT_MULTIPART_MAX_RETRIES = 3;
15
17
  function positiveSafe(value, name) {
16
18
  const n = Number(value);
17
- if (!Number.isSafeInteger(n) || n <= 0)
19
+ if (!['number', 'bigint'].includes(typeof value) || !Number.isSafeInteger(n) || n <= 0)
18
20
  throw new TypeError(`Invalid ${name}`);
19
21
  return n;
20
22
  }
@@ -22,6 +24,38 @@ function validateFile(file) {
22
24
  if (!file || typeof file.name !== 'string' || !file.name || !Number.isSafeInteger(file.size) || file.size < 0 || typeof file.slice !== 'function')
23
25
  throw new TypeError('A File is required');
24
26
  }
27
+ function storageURL(value) {
28
+ const url = new URL(value);
29
+ if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password)
30
+ throw new TypeError('Invalid signed storage URL');
31
+ return url.href;
32
+ }
33
+ function transferOptions(options) {
34
+ const { concurrency = DEFAULT_MULTIPART_CONCURRENCY, maxRetries = DEFAULT_MULTIPART_MAX_RETRIES } = options;
35
+ if (!Number.isSafeInteger(concurrency) || concurrency < 1)
36
+ throw new TypeError('concurrency must be a positive safe integer');
37
+ if (!Number.isSafeInteger(maxRetries) || maxRetries < 0)
38
+ throw new TypeError('maxRetries must be a non-negative safe integer');
39
+ if (options.onProgress !== undefined && typeof options.onProgress !== 'function')
40
+ throw new TypeError('onProgress must be a function');
41
+ return { concurrency, maxRetries };
42
+ }
43
+ function retryablePart(error) {
44
+ if (error instanceof TransportError)
45
+ return error.errorCode === 'SDK_TIMEOUT';
46
+ if (error instanceof ApiError)
47
+ return [408, 429, 500, 502, 503, 504].includes(error.status);
48
+ return error instanceof TypeError || (error instanceof Error && error.name === 'AbortError');
49
+ }
50
+ function retryDelay(attempt, signal) {
51
+ signal?.throwIfAborted();
52
+ return new Promise((resolve, reject) => {
53
+ const finish = () => { signal?.removeEventListener('abort', abort); resolve(); };
54
+ const timer = setTimeout(finish, Math.min(100 * 2 ** Math.min(attempt, 5), 3000));
55
+ const abort = () => { clearTimeout(timer); signal?.removeEventListener('abort', abort); reject(signal?.reason); };
56
+ signal?.addEventListener('abort', abort, { once: true });
57
+ });
58
+ }
25
59
  /** All platform requests are scoped to this instance; storage requests never carry its API key. */
26
60
  export class FilesClient {
27
61
  http;
@@ -33,20 +67,35 @@ export class FilesClient {
33
67
  this.multipart = this.api.multipart;
34
68
  }
35
69
  async storage(urlString, init, options = {}) {
36
- const url = new URL(urlString);
37
- if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password)
38
- throw new TypeError('Invalid signed storage URL');
70
+ const url = storageURL(urlString);
71
+ options.signal?.throwIfAborted();
39
72
  const controller = new AbortController();
40
- const abort = () => controller.abort(options.signal?.reason);
41
- const timer = setTimeout(() => controller.abort(), this.http.timeoutMs);
73
+ let expired = false;
74
+ let started = false;
75
+ let rejectStopped = () => undefined;
76
+ const stopped = new Promise((_resolve, reject) => { rejectStopped = reject; });
77
+ const failure = () => new TransportError(expired ? 'TIMEOUT' : 'ABORTED', started && init.method !== 'GET');
78
+ const abort = () => { rejectStopped(failure()); controller.abort(options.signal?.reason); };
79
+ const timer = setTimeout(() => { expired = true; abort(); }, this.http.timeoutMs);
42
80
  options.signal?.addEventListener('abort', abort, { once: true });
43
- try {
44
- if (options.signal?.aborted)
45
- abort();
46
- const response = await this.http.getFetch()(url.href, { ...init, signal: controller.signal, credentials: 'omit', redirect: 'error' });
81
+ const exchange = async () => {
82
+ if (controller.signal.aborted)
83
+ throw failure();
84
+ started = true;
85
+ const response = await this.http.getFetch()(url, { ...init, signal: controller.signal, credentials: 'omit', redirect: 'error' });
86
+ // 忽略 AbortSignal 的自定义 fetch 晚返回也不能改变已交还的分片会话。
87
+ if (controller.signal.aborted) {
88
+ void response.body?.cancel().catch(() => undefined);
89
+ throw failure();
90
+ }
47
91
  if (!response.ok)
48
92
  throw new ApiError(response.status, 0, 'Object storage request failed');
49
93
  return response;
94
+ };
95
+ try {
96
+ if (options.signal?.aborted)
97
+ abort();
98
+ return await Promise.race([exchange(), stopped]);
50
99
  }
51
100
  finally {
52
101
  clearTimeout(timer);
@@ -55,9 +104,9 @@ export class FilesClient {
55
104
  }
56
105
  async upload(file, options = {}) {
57
106
  validateFile(file);
58
- if (file.size > MULTIPART_THRESHOLD_BYTES)
59
- return this.uploadMultipart(file, options);
60
- const { signal, ...metadata } = options;
107
+ const { signal, multipart, ...metadata } = options;
108
+ if (file.size > MULTIPART_THRESHOLD_BYTES || multipart !== undefined)
109
+ return this.uploadMultipart(file, { ...metadata, ...multipart, signal });
61
110
  const prepared = await this.api.prepareUpload({ ...metadata, fileName: file.name, size: file.size, contentType: file.type || 'application/octet-stream' }, { signal });
62
111
  if (!prepared.postUrl || !prepared.filePath || !prepared.postFields)
63
112
  throw new ApiError(200, 0, 'Invalid upload preparation response');
@@ -72,29 +121,103 @@ export class FilesClient {
72
121
  validateFile(file);
73
122
  if (file.size === 0)
74
123
  throw new TypeError('Multipart upload requires a non-empty file');
75
- const { signal, partSize = DEFAULT_MULTIPART_PART_SIZE, onProgress, ...metadata } = options;
124
+ const { signal, partSize = DEFAULT_MULTIPART_PART_SIZE, onProgress, concurrency, maxRetries, ...metadata } = options;
125
+ transferOptions(options);
76
126
  if (!Number.isSafeInteger(partSize) || partSize < 5 * 1024 * 1024)
77
127
  throw new TypeError('partSize must be at least 5 MiB');
128
+ signal?.throwIfAborted();
78
129
  const start = await this.multipart.init({ ...metadata, fileName: file.name, contentType: file.type || 'application/octet-stream', size: file.size, partSize }, { signal });
79
- const session = { fileKey: start.fileKey, uploadId: start.uploadId, parts: [], completionAttempted: false };
130
+ const session = { fileKey: start.fileKey, uploadId: start.uploadId, parts: [], completionAttempted: false, fileName: file.name, fileSize: file.size };
80
131
  try {
81
132
  const size = positiveSafe(start.partSize, 'server partSize');
82
133
  const count = positiveSafe(start.partCount, 'server partCount');
83
134
  if (!start.fileKey || !start.uploadId || count !== Math.ceil(file.size / size) || size < 5 * 1024 * 1024 || count > 10_000)
84
135
  throw new TypeError('Invalid multipart preparation response');
85
- for (let partNumber = 1; partNumber <= count; partNumber++) {
86
- const result = await this.multipart.partUrls({ fileKey: start.fileKey, uploadId: start.uploadId, partNumbers: [partNumber] }, { signal });
87
- const signed = result.partUrls.find(p => Number(p.partNumber) === partNumber);
88
- if (!signed?.url)
89
- throw new ApiError(200, 0, 'Missing signed part URL');
90
- const end = Math.min(partNumber * size, file.size);
91
- const response = await this.storage(signed.url, { method: 'PUT', body: file.slice((partNumber - 1) * size, end) }, { signal });
92
- const etag = response.headers.get('etag');
93
- if (!etag)
94
- throw new ApiError(response.status, 0, 'Storage response is missing ETag');
95
- session.parts.push({ partNumber, etag });
96
- onProgress?.({ uploadedBytes: end, totalBytes: file.size });
136
+ session.partSize = size;
137
+ }
138
+ catch (error) {
139
+ throw new MultipartUploadError(session, error);
140
+ }
141
+ return this.transferMultipart(file, session, { signal, onProgress, concurrency, maxRetries });
142
+ }
143
+ async resumeMultipart(file, previous, options = {}) {
144
+ validateFile(file);
145
+ transferOptions(options);
146
+ if (!previous || previous.completionAttempted !== false)
147
+ throw new TypeError('Reconcile the previous completion before resuming');
148
+ if (!previous.partSize || previous.fileSize !== file.size || previous.fileName !== file.name || file.size === 0)
149
+ throw new TypeError('Resume requires the original file name, size and server partSize');
150
+ const size = positiveSafe(previous.partSize, 'session partSize');
151
+ const count = Math.ceil(file.size / size);
152
+ if (size < 5 * 1024 * 1024 || count > 10_000 || typeof previous.fileKey !== 'string' || !previous.fileKey || typeof previous.uploadId !== 'string' || !previous.uploadId || !Array.isArray(previous.parts))
153
+ throw new TypeError('Invalid multipart session');
154
+ const seen = new Set();
155
+ const parts = previous.parts.map(part => {
156
+ const partNumber = positiveSafe(part.partNumber, 'session partNumber');
157
+ if (partNumber > count || seen.has(partNumber) || typeof part.etag !== 'string' || !part.etag.trim())
158
+ throw new TypeError('Invalid or duplicate completed part');
159
+ seen.add(partNumber);
160
+ return { partNumber, etag: part.etag };
161
+ });
162
+ return this.transferMultipart(file, { ...previous, partSize: size, parts }, options);
163
+ }
164
+ // 只重传同一签名地址的同一片内容;平台的 init/partUrls/complete 不自动重放。
165
+ async putPart(url, body, options, maxRetries) {
166
+ const signed = storageURL(url);
167
+ for (let attempt = 0;; attempt++) {
168
+ options.signal?.throwIfAborted();
169
+ try {
170
+ return await this.storage(signed, { method: 'PUT', body }, options);
97
171
  }
172
+ catch (error) {
173
+ if (options.signal?.aborted || attempt >= maxRetries || !retryablePart(error))
174
+ throw error;
175
+ await retryDelay(attempt, options.signal);
176
+ }
177
+ }
178
+ }
179
+ async transferMultipart(file, session, options) {
180
+ const { concurrency, maxRetries } = transferOptions(options);
181
+ const { signal, onProgress } = options;
182
+ const size = session.partSize;
183
+ const count = Math.ceil(file.size / size);
184
+ const completed = new Set(session.parts.map(part => Number(part.partNumber)));
185
+ const pending = Array.from({ length: count }, (_, i) => i + 1).filter(number => !completed.has(number));
186
+ let uploadedBytes = session.parts.reduce((sum, part) => sum + Math.min(size, file.size - (Number(part.partNumber) - 1) * size), 0);
187
+ let cursor = 0, failed = false, failure;
188
+ const worker = async () => {
189
+ while (!failed && cursor < pending.length) {
190
+ const partNumber = pending[cursor++];
191
+ try {
192
+ signal?.throwIfAborted();
193
+ const result = await this.multipart.partUrls({ fileKey: session.fileKey, uploadId: session.uploadId, partNumbers: [partNumber] }, { signal });
194
+ const signed = result.partUrls.find(part => Number(part.partNumber) === partNumber);
195
+ if (!signed?.url)
196
+ throw new ApiError(200, 0, 'Missing signed part URL');
197
+ const part = file.slice((partNumber - 1) * size, Math.min(partNumber * size, file.size));
198
+ const response = await this.putPart(signed.url, part, options, maxRetries);
199
+ const etag = response.headers.get('etag');
200
+ if (!etag?.trim())
201
+ throw new ApiError(response.status, 0, 'Storage response is missing ETag');
202
+ session.parts.push({ partNumber, etag });
203
+ uploadedBytes += part.size;
204
+ onProgress?.({ uploadedBytes, totalBytes: file.size, doneParts: session.parts.length, totalParts: count, percent: uploadedBytes / file.size * 100 });
205
+ }
206
+ catch (error) {
207
+ if (!failed) {
208
+ failed = true;
209
+ failure = error;
210
+ }
211
+ }
212
+ }
213
+ };
214
+ // 必须等在途分片收敛再交出会话,失败后不再领取新分片,也不隐式取消远端上传。
215
+ await Promise.all(Array.from({ length: Math.min(concurrency, pending.length) }, worker));
216
+ session.parts.sort((a, b) => Number(a.partNumber) - Number(b.partNumber));
217
+ try {
218
+ if (failed)
219
+ throw failure;
220
+ signal?.throwIfAborted();
98
221
  session.completionAttempted = true;
99
222
  return await this.multipart.complete({ fileKey: session.fileKey, uploadId: session.uploadId, parts: session.parts }, { signal });
100
223
  }
@@ -1 +1 @@
1
- {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAA0C,MAAM,qBAAqB,CAAC;AACnG,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAiB3D,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACxB;IAAoC;IAAzD,YAAqB,OAAyB,EAAW,KAAc;QACrE,KAAK,CAAC,0GAA0G,CAAC,CAAC;QAD/F,YAAO,GAAP,OAAO,CAAkB;QAAW,UAAK,GAAL,KAAK,CAAS;QAErE,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AACD,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAC3D,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3D,SAAS,YAAY,CAAC,KAAsB,EAAE,IAAY;IACxD,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACxB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC/E,OAAO,CAAC,CAAC;AACX,CAAC;AACD,SAAS,YAAY,CAAC,IAAU;IAC9B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,UAAU;QAAE,MAAM,IAAI,SAAS,CAAC,oBAAoB,CAAC,CAAC;AAC/L,CAAC;AAED,mGAAmG;AACnG,MAAM,OAAO,WAAW;IAGO;IAFZ,GAAG,CAAC;IACZ,SAAS,CAAC;IACnB,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;QAC3C,IAAI,CAAC,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QAC5C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;IACtC,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,SAAiB,EAAE,IAAiB,EAAE,UAA0B,EAAE;QACtF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;QAC/B,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ;YAAE,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAC;QACnI,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7D,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxE,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,IAAI,CAAC;YACH,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;gBAAE,KAAK,EAAE,CAAC;YACrC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;YACtI,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,+BAA+B,CAAC,CAAC;YAC1F,OAAO,QAAQ,CAAC;QAClB,CAAC;gBAAS,CAAC;YAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YAAC,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAAC,CAAC;IACzF,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAU,EAAE,UAAyB,EAAE;QAClD,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,IAAI,IAAI,CAAC,IAAI,GAAG,yBAAyB;YAAE,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACtF,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,GAAG,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,IAAI,IAAI,0BAA0B,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACvK,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU;YAAE,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,qCAAqC,CAAC,CAAC;QACvI,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC1F,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC1B,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACjF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,IAAU,EAAE,UAA4B,EAAE;QAC9D,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAC;QACvF,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,2BAA2B,EAAE,UAAU,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC;QAC5F,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI;YAAE,MAAM,IAAI,SAAS,CAAC,iCAAiC,CAAC,CAAC;QAC1H,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,IAAI,IAAI,0BAA0B,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3K,MAAM,OAAO,GAAqB,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC;QAC9H,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;YAC7D,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;YAChE,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,IAAI,KAAK,GAAG,MAAM;gBAAE,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC,CAAC;YAC1L,KAAK,IAAI,UAAU,GAAG,CAAC,EAAE,UAAU,IAAI,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC;gBAC3D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC1I,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,UAAU,CAAC,CAAC;gBAC9E,IAAI,CAAC,MAAM,EAAE,GAAG;oBAAE,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,yBAAyB,CAAC,CAAC;gBACxE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;gBACnD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC/H,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC1C,IAAI,CAAC,IAAI;oBAAE,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,kCAAkC,CAAC,CAAC;gBACtF,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;gBACzC,UAAU,EAAE,CAAC,EAAE,aAAa,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC9D,CAAC;YACD,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;YACnC,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACnI,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,IAAI,oBAAoB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAAC,CAAC;IACrE,CAAC;IAED,GAAG,CAAC,KAAyC,EAAE,OAAwB,IAAI,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACjH,MAAM,CAAC,IAAmC,EAAE,OAAwB,IAAI,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAChH,KAAK,CAAC,QAAQ,CAAC,KAAyC,EAAE,UAA0B,EAAE;QACpF,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;CACF;AACD,MAAM,UAAU,iBAAiB,CAAC,SAAuB,EAAE,IAAiB,OAAO,IAAI,WAAW,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC","sourcesContent":["import { HttpClient, ApiError, type ClientConfig, type RequestOptions } from './openapi/client.js';\nimport { createOpenAPI } from './openapi/api.generated.js';\nimport type { components } from './openapi/types.generated.js';\n\ntype Schemas = components['schemas'];\nexport type UploadOptions = Omit<Schemas['AssetFileUploadReq'], 'fileName' | 'contentType' | 'size'> & RequestOptions;\nexport type UploadResult = Schemas['AssetFileUploadResp'];\nexport type MultipartResult = Schemas['AssetFileMultipartCompleteResp'];\nexport interface MultipartOptions extends UploadOptions {\n partSize?: number;\n onProgress?: (progress: { uploadedBytes: number; totalBytes: number }) => void;\n}\nexport interface MultipartSession {\n fileKey: string;\n uploadId: string;\n parts: Schemas['AssetFileMultipartPart'][];\n completionAttempted: boolean;\n}\nexport class MultipartUploadError extends Error {\n constructor(readonly session: MultipartSession, readonly cause: unknown) {\n super('Multipart upload interrupted. The session is retained; reconcile completion before retrying or aborting.');\n this.name = 'MultipartUploadError';\n }\n}\nexport const MULTIPART_THRESHOLD_BYTES = 100 * 1024 * 1024;\nexport const DEFAULT_MULTIPART_PART_SIZE = 8 * 1024 * 1024;\n\nfunction positiveSafe(value: number | bigint, name: string): number {\n const n = Number(value);\n if (!Number.isSafeInteger(n) || n <= 0) throw new TypeError(`Invalid ${name}`);\n return n;\n}\nfunction validateFile(file: File): void {\n if (!file || typeof file.name !== 'string' || !file.name || !Number.isSafeInteger(file.size) || file.size < 0 || typeof file.slice !== 'function') throw new TypeError('A File is required');\n}\n\n/** All platform requests are scoped to this instance; storage requests never carry its API key. */\nexport class FilesClient {\n private readonly api;\n readonly multipart;\n constructor(private readonly http: HttpClient) {\n this.api = createOpenAPI(http).assets.files;\n this.multipart = this.api.multipart;\n }\n\n private async storage(urlString: string, init: RequestInit, options: RequestOptions = {}): Promise<Response> {\n const url = new URL(urlString);\n if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password) throw new TypeError('Invalid signed storage URL');\n const controller = new AbortController();\n const abort = () => controller.abort(options.signal?.reason);\n const timer = setTimeout(() => controller.abort(), this.http.timeoutMs);\n options.signal?.addEventListener('abort', abort, { once: true });\n try {\n if (options.signal?.aborted) abort();\n const response = await this.http.getFetch()(url.href, { ...init, signal: controller.signal, credentials: 'omit', redirect: 'error' });\n if (!response.ok) throw new ApiError(response.status, 0, 'Object storage request failed');\n return response;\n } finally { clearTimeout(timer); options.signal?.removeEventListener('abort', abort); }\n }\n\n async upload(file: File, options: UploadOptions = {}): Promise<UploadResult | MultipartResult> {\n validateFile(file);\n if (file.size > MULTIPART_THRESHOLD_BYTES) return this.uploadMultipart(file, options);\n const { signal, ...metadata } = options;\n const prepared = await this.api.prepareUpload({ ...metadata, fileName: file.name, size: file.size, contentType: file.type || 'application/octet-stream' }, { signal });\n if (!prepared.postUrl || !prepared.filePath || !prepared.postFields) throw new ApiError(200, 0, 'Invalid upload preparation response');\n const form = new FormData();\n for (const [name, value] of Object.entries(prepared.postFields)) form.append(name, value);\n form.append('file', file);\n await this.storage(prepared.postUrl, { method: 'POST', body: form }, { signal });\n return prepared;\n }\n\n async uploadMultipart(file: File, options: MultipartOptions = {}): Promise<MultipartResult> {\n validateFile(file);\n if (file.size === 0) throw new TypeError('Multipart upload requires a non-empty file');\n const { signal, partSize = DEFAULT_MULTIPART_PART_SIZE, onProgress, ...metadata } = options;\n if (!Number.isSafeInteger(partSize) || partSize < 5 * 1024 * 1024) throw new TypeError('partSize must be at least 5 MiB');\n const start = await this.multipart.init({ ...metadata, fileName: file.name, contentType: file.type || 'application/octet-stream', size: file.size, partSize }, { signal });\n const session: MultipartSession = { fileKey: start.fileKey, uploadId: start.uploadId, parts: [], completionAttempted: false };\n try {\n const size = positiveSafe(start.partSize, 'server partSize');\n const count = positiveSafe(start.partCount, 'server partCount');\n if (!start.fileKey || !start.uploadId || count !== Math.ceil(file.size / size) || size < 5 * 1024 * 1024 || count > 10_000) throw new TypeError('Invalid multipart preparation response');\n for (let partNumber = 1; partNumber <= count; partNumber++) {\n const result = await this.multipart.partUrls({ fileKey: start.fileKey, uploadId: start.uploadId, partNumbers: [partNumber] }, { signal });\n const signed = result.partUrls.find(p => Number(p.partNumber) === partNumber);\n if (!signed?.url) throw new ApiError(200, 0, 'Missing signed part URL');\n const end = Math.min(partNumber * size, file.size);\n const response = await this.storage(signed.url, { method: 'PUT', body: file.slice((partNumber - 1) * size, end) }, { signal });\n const etag = response.headers.get('etag');\n if (!etag) throw new ApiError(response.status, 0, 'Storage response is missing ETag');\n session.parts.push({ partNumber, etag });\n onProgress?.({ uploadedBytes: end, totalBytes: file.size });\n }\n session.completionAttempted = true;\n return await this.multipart.complete({ fileKey: session.fileKey, uploadId: session.uploadId, parts: session.parts }, { signal });\n } catch (error) { throw new MultipartUploadError(session, error); }\n }\n\n url(query: Parameters<typeof this.api.url>[0], options?: RequestOptions) { return this.api.url(query, options); }\n delete(body: Schemas['AssetFileDeleteReq'], options?: RequestOptions) { return this.api.delete(body, options); }\n async download(query: Parameters<typeof this.api.url>[0], options: RequestOptions = {}): Promise<Response> {\n const { fileUrl } = await this.api.url(query, options);\n return this.storage(fileUrl, { method: 'GET' }, options);\n }\n}\nexport function createFilesClient(config: ClientConfig = {}): FilesClient { return new FilesClient(new HttpClient(config)); }\n"]}
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAA0C,MAAM,qBAAqB,CAAC;AACnH,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAiC3D,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACxB;IAAoC;IAAzD,YAAqB,OAAyB,EAAW,KAAc;QACrE,KAAK,CAAC,0GAA0G,CAAC,CAAC;QAD/F,YAAO,GAAP,OAAO,CAAkB;QAAW,UAAK,GAAL,KAAK,CAAS;QAErE,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AACD,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAC3D,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAC3D,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAC/C,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,SAAS,YAAY,CAAC,KAAsB,EAAE,IAAY;IACxD,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACxB,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC/H,OAAO,CAAC,CAAC;AACX,CAAC;AACD,SAAS,YAAY,CAAC,IAAU;IAC9B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,UAAU;QAAE,MAAM,IAAI,SAAS,CAAC,oBAAoB,CAAC,CAAC;AAC/L,CAAC;AACD,SAAS,UAAU,CAAC,KAAa;IAC/B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ;QAAE,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAC;IACnI,OAAO,GAAG,CAAC,IAAI,CAAC;AAClB,CAAC;AACD,SAAS,eAAe,CAAC,OAA+B;IACtD,MAAM,EAAE,WAAW,GAAG,6BAA6B,EAAE,UAAU,GAAG,6BAA6B,EAAE,GAAG,OAAO,CAAC;IAC5G,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAC;IAC9H,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAC;IAC/H,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,IAAI,OAAO,OAAO,CAAC,UAAU,KAAK,UAAU;QAAE,MAAM,IAAI,SAAS,CAAC,+BAA+B,CAAC,CAAC;IACvI,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AACrC,CAAC;AACD,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,KAAK,YAAY,cAAc;QAAE,OAAO,KAAK,CAAC,SAAS,KAAK,aAAa,CAAC;IAC9E,IAAI,KAAK,YAAY,QAAQ;QAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5F,OAAO,KAAK,YAAY,SAAS,IAAI,CAAC,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;AAC/F,CAAC;AACD,SAAS,UAAU,CAAC,OAAe,EAAE,MAAoB;IACvD,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,GAAG,EAAE,GAAG,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QACjF,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QAClF,MAAM,KAAK,GAAG,GAAG,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAClH,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,mGAAmG;AACnG,MAAM,OAAO,WAAW;IAGO;IAFZ,GAAG,CAAC;IACZ,SAAS,CAAC;IACnB,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;QAC3C,IAAI,CAAC,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QAC5C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;IACtC,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,SAAiB,EAAE,IAAiB,EAAE,UAA0B,EAAE;QACtF,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QAClC,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;QACjC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,aAAa,GAA2B,GAAG,EAAE,CAAC,SAAS,CAAC;QAC5D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,GAAG,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACtF,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;QAC5G,MAAM,KAAK,GAAG,GAAG,EAAE,GAAG,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5F,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClF,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;YAC1B,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;gBAAE,MAAM,OAAO,EAAE,CAAC;YAC/C,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;YACjI,8CAA8C;YAC9C,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC9B,KAAK,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBACpD,MAAM,OAAO,EAAE,CAAC;YAClB,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,+BAA+B,CAAC,CAAC;YAC1F,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC;QACF,IAAI,CAAC;YACH,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;gBAAE,KAAK,EAAE,CAAC;YACrC,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;QACnD,CAAC;gBAAS,CAAC;YAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YAAC,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAAC,CAAC;IACzF,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAU,EAAE,UAAyB,EAAE;QAClD,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC;QACnD,IAAI,IAAI,CAAC,IAAI,GAAG,yBAAyB,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,GAAG,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC/I,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,GAAG,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,IAAI,IAAI,0BAA0B,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACvK,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU;YAAE,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,qCAAqC,CAAC,CAAC;QACvI,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC1F,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC1B,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACjF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,IAAU,EAAE,UAA4B,EAAE;QAC9D,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAC;QACvF,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,2BAA2B,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC;QACrH,eAAe,CAAC,OAAO,CAAC,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI;YAAE,MAAM,IAAI,SAAS,CAAC,iCAAiC,CAAC,CAAC;QAC1H,MAAM,EAAE,cAAc,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,IAAI,IAAI,0BAA0B,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3K,MAAM,OAAO,GAAqB,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,mBAAmB,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QACxK,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;YAC7D,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;YAChE,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,IAAI,KAAK,GAAG,MAAM;gBAAE,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC,CAAC;YAC1L,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,IAAI,oBAAoB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAAC,CAAC;QACnE,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;IAChG,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,IAAU,EAAE,QAA0B,EAAE,UAAkC,EAAE;QAChG,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,eAAe,CAAC,OAAO,CAAC,CAAC;QACzB,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,mBAAmB,KAAK,KAAK;YAAE,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAC;QAClI,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,kEAAkE,CAAC,CAAC;QACzM,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;QACjE,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QAC1C,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,IAAI,KAAK,GAAG,MAAM,IAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,2BAA2B,CAAC,CAAC;QAC7P,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACtC,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;YACvE,IAAI,UAAU,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;gBAAE,MAAM,IAAI,SAAS,CAAC,qCAAqC,CAAC,CAAC;YACjK,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACrB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QACzC,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;IACvF,CAAC;IAED,oDAAoD;IAC5C,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,IAAU,EAAE,OAA+B,EAAE,UAAkB;QAChG,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC/B,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,EAAE,EAAE,CAAC;YAClC,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;YACjC,IAAI,CAAC;gBAAC,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;YAAC,CAAC;YAC5E,OAAO,KAAK,EAAE,CAAC;gBACb,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,IAAI,OAAO,IAAI,UAAU,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;oBAAE,MAAM,KAAK,CAAC;gBAC3F,MAAM,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,IAAU,EAAE,OAAyB,EAAE,OAA+B;QACpG,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAC7D,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;QACvC,MAAM,IAAI,GAAG,OAAO,CAAC,QAAS,CAAC;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC9E,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QACxG,IAAI,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACnI,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,EAAE,OAAgB,CAAC;QACjD,MAAM,MAAM,GAAG,KAAK,IAAI,EAAE;YACxB,OAAO,CAAC,MAAM,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;gBAC1C,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;gBACrC,IAAI,CAAC;oBACH,MAAM,EAAE,cAAc,EAAE,CAAC;oBACzB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;oBAC9I,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,UAAU,CAAC,CAAC;oBACpF,IAAI,CAAC,MAAM,EAAE,GAAG;wBAAE,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,yBAAyB,CAAC,CAAC;oBACxE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;oBACzF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;oBAC3E,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBAC1C,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE;wBAAE,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,kCAAkC,CAAC,CAAC;oBAC9F,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;oBACzC,aAAa,IAAI,IAAI,CAAC,IAAI,CAAC;oBAC3B,UAAU,EAAE,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,EAAE,CAAC,CAAC;gBACvJ,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAAC,IAAI,CAAC,MAAM,EAAE,CAAC;wBAAC,MAAM,GAAG,IAAI,CAAC;wBAAC,OAAO,GAAG,KAAK,CAAC;oBAAC,CAAC;gBAAC,CAAC;YACtE,CAAC;QACH,CAAC,CAAC;QACF,wCAAwC;QACxC,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;QACzF,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAC1E,IAAI,CAAC;YACH,IAAI,MAAM;gBAAE,MAAM,OAAO,CAAC;YAC1B,MAAM,EAAE,cAAc,EAAE,CAAC;YACzB,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;YACnC,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACnI,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,IAAI,oBAAoB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAAC,CAAC;IACrE,CAAC;IAED,GAAG,CAAC,KAAyC,EAAE,OAAwB,IAAI,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACjH,MAAM,CAAC,IAAmC,EAAE,OAAwB,IAAI,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAChH,KAAK,CAAC,QAAQ,CAAC,KAAyC,EAAE,UAA0B,EAAE;QACpF,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;CACF;AACD,MAAM,UAAU,iBAAiB,CAAC,SAAuB,EAAE,IAAiB,OAAO,IAAI,WAAW,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC","sourcesContent":["import { HttpClient, ApiError, TransportError, type ClientConfig, type RequestOptions } from './openapi/client.js';\nimport { createOpenAPI } from './openapi/api.generated.js';\nimport type { components } from './openapi/types.generated.js';\n\ntype Schemas = components['schemas'];\nexport type UploadOptions = Omit<Schemas['AssetFileUploadReq'], 'fileName' | 'contentType' | 'size'> & RequestOptions & { multipart?: MultipartSettings };\nexport type UploadResult = Schemas['AssetFileUploadResp'];\nexport type MultipartResult = Schemas['AssetFileMultipartCompleteResp'];\nexport interface MultipartProgress {\n uploadedBytes: number;\n totalBytes: number;\n doneParts: number;\n totalParts: number;\n percent: number;\n}\nexport interface ResumeMultipartOptions extends RequestOptions {\n concurrency?: number;\n maxRetries?: number;\n onProgress?: (progress: MultipartProgress) => void;\n}\nexport interface MultipartSettings extends Omit<ResumeMultipartOptions, 'signal'> {\n partSize?: number;\n}\nexport interface MultipartOptions extends Omit<UploadOptions, 'multipart'>, MultipartSettings {}\nexport interface MultipartSession {\n fileKey: string;\n uploadId: string;\n parts: Schemas['AssetFileMultipartPart'][];\n completionAttempted: boolean;\n // 可选字段保留旧会话类型兼容;续传时必须有完整的文件与切片信息。\n partSize?: number;\n fileName?: string;\n fileSize?: number;\n}\nexport class MultipartUploadError extends Error {\n constructor(readonly session: MultipartSession, readonly cause: unknown) {\n super('Multipart upload interrupted. The session is retained; reconcile completion before retrying or aborting.');\n this.name = 'MultipartUploadError';\n }\n}\nexport const MULTIPART_THRESHOLD_BYTES = 100 * 1024 * 1024;\nexport const DEFAULT_MULTIPART_PART_SIZE = 8 * 1024 * 1024;\nexport const DEFAULT_MULTIPART_CONCURRENCY = 4;\nexport const DEFAULT_MULTIPART_MAX_RETRIES = 3;\n\nfunction positiveSafe(value: number | bigint, name: string): number {\n const n = Number(value);\n if (!['number', 'bigint'].includes(typeof value) || !Number.isSafeInteger(n) || n <= 0) throw new TypeError(`Invalid ${name}`);\n return n;\n}\nfunction validateFile(file: File): void {\n if (!file || typeof file.name !== 'string' || !file.name || !Number.isSafeInteger(file.size) || file.size < 0 || typeof file.slice !== 'function') throw new TypeError('A File is required');\n}\nfunction storageURL(value: string): string {\n const url = new URL(value);\n if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password) throw new TypeError('Invalid signed storage URL');\n return url.href;\n}\nfunction transferOptions(options: ResumeMultipartOptions) {\n const { concurrency = DEFAULT_MULTIPART_CONCURRENCY, maxRetries = DEFAULT_MULTIPART_MAX_RETRIES } = options;\n if (!Number.isSafeInteger(concurrency) || concurrency < 1) throw new TypeError('concurrency must be a positive safe integer');\n if (!Number.isSafeInteger(maxRetries) || maxRetries < 0) throw new TypeError('maxRetries must be a non-negative safe integer');\n if (options.onProgress !== undefined && typeof options.onProgress !== 'function') throw new TypeError('onProgress must be a function');\n return { concurrency, maxRetries };\n}\nfunction retryablePart(error: unknown): boolean {\n if (error instanceof TransportError) return error.errorCode === 'SDK_TIMEOUT';\n if (error instanceof ApiError) return [408, 429, 500, 502, 503, 504].includes(error.status);\n return error instanceof TypeError || (error instanceof Error && error.name === 'AbortError');\n}\nfunction retryDelay(attempt: number, signal?: AbortSignal): Promise<void> {\n signal?.throwIfAborted();\n return new Promise((resolve, reject) => {\n const finish = () => { signal?.removeEventListener('abort', abort); resolve(); };\n const timer = setTimeout(finish, Math.min(100 * 2 ** Math.min(attempt, 5), 3000));\n const abort = () => { clearTimeout(timer); signal?.removeEventListener('abort', abort); reject(signal?.reason); };\n signal?.addEventListener('abort', abort, { once: true });\n });\n}\n\n/** All platform requests are scoped to this instance; storage requests never carry its API key. */\nexport class FilesClient {\n private readonly api;\n readonly multipart;\n constructor(private readonly http: HttpClient) {\n this.api = createOpenAPI(http).assets.files;\n this.multipart = this.api.multipart;\n }\n\n private async storage(urlString: string, init: RequestInit, options: RequestOptions = {}): Promise<Response> {\n const url = storageURL(urlString);\n options.signal?.throwIfAborted();\n const controller = new AbortController();\n let expired = false;\n let started = false;\n let rejectStopped: (error: Error) => void = () => undefined;\n const stopped = new Promise<never>((_resolve, reject) => { rejectStopped = reject; });\n const failure = () => new TransportError(expired ? 'TIMEOUT' : 'ABORTED', started && init.method !== 'GET');\n const abort = () => { rejectStopped(failure()); controller.abort(options.signal?.reason); };\n const timer = setTimeout(() => { expired = true; abort(); }, this.http.timeoutMs);\n options.signal?.addEventListener('abort', abort, { once: true });\n const exchange = async () => {\n if (controller.signal.aborted) throw failure();\n started = true;\n const response = await this.http.getFetch()(url, { ...init, signal: controller.signal, credentials: 'omit', redirect: 'error' });\n // 忽略 AbortSignal 的自定义 fetch 晚返回也不能改变已交还的分片会话。\n if (controller.signal.aborted) {\n void response.body?.cancel().catch(() => undefined);\n throw failure();\n }\n if (!response.ok) throw new ApiError(response.status, 0, 'Object storage request failed');\n return response;\n };\n try {\n if (options.signal?.aborted) abort();\n return await Promise.race([exchange(), stopped]);\n } finally { clearTimeout(timer); options.signal?.removeEventListener('abort', abort); }\n }\n\n async upload(file: File, options: UploadOptions = {}): Promise<UploadResult | MultipartResult> {\n validateFile(file);\n const { signal, multipart, ...metadata } = options;\n if (file.size > MULTIPART_THRESHOLD_BYTES || multipart !== undefined) return this.uploadMultipart(file, { ...metadata, ...multipart, signal });\n const prepared = await this.api.prepareUpload({ ...metadata, fileName: file.name, size: file.size, contentType: file.type || 'application/octet-stream' }, { signal });\n if (!prepared.postUrl || !prepared.filePath || !prepared.postFields) throw new ApiError(200, 0, 'Invalid upload preparation response');\n const form = new FormData();\n for (const [name, value] of Object.entries(prepared.postFields)) form.append(name, value);\n form.append('file', file);\n await this.storage(prepared.postUrl, { method: 'POST', body: form }, { signal });\n return prepared;\n }\n\n async uploadMultipart(file: File, options: MultipartOptions = {}): Promise<MultipartResult> {\n validateFile(file);\n if (file.size === 0) throw new TypeError('Multipart upload requires a non-empty file');\n const { signal, partSize = DEFAULT_MULTIPART_PART_SIZE, onProgress, concurrency, maxRetries, ...metadata } = options;\n transferOptions(options);\n if (!Number.isSafeInteger(partSize) || partSize < 5 * 1024 * 1024) throw new TypeError('partSize must be at least 5 MiB');\n signal?.throwIfAborted();\n const start = await this.multipart.init({ ...metadata, fileName: file.name, contentType: file.type || 'application/octet-stream', size: file.size, partSize }, { signal });\n const session: MultipartSession = { fileKey: start.fileKey, uploadId: start.uploadId, parts: [], completionAttempted: false, fileName: file.name, fileSize: file.size };\n try {\n const size = positiveSafe(start.partSize, 'server partSize');\n const count = positiveSafe(start.partCount, 'server partCount');\n if (!start.fileKey || !start.uploadId || count !== Math.ceil(file.size / size) || size < 5 * 1024 * 1024 || count > 10_000) throw new TypeError('Invalid multipart preparation response');\n session.partSize = size;\n } catch (error) { throw new MultipartUploadError(session, error); }\n return this.transferMultipart(file, session, { signal, onProgress, concurrency, maxRetries });\n }\n\n async resumeMultipart(file: File, previous: MultipartSession, options: ResumeMultipartOptions = {}): Promise<MultipartResult> {\n validateFile(file);\n transferOptions(options);\n if (!previous || previous.completionAttempted !== false) throw new TypeError('Reconcile the previous completion before resuming');\n if (!previous.partSize || previous.fileSize !== file.size || previous.fileName !== file.name || file.size === 0) throw new TypeError('Resume requires the original file name, size and server partSize');\n const size = positiveSafe(previous.partSize, 'session partSize');\n const count = Math.ceil(file.size / size);\n if (size < 5 * 1024 * 1024 || count > 10_000 || typeof previous.fileKey !== 'string' || !previous.fileKey || typeof previous.uploadId !== 'string' || !previous.uploadId || !Array.isArray(previous.parts)) throw new TypeError('Invalid multipart session');\n const seen = new Set<number>();\n const parts = previous.parts.map(part => {\n const partNumber = positiveSafe(part.partNumber, 'session partNumber');\n if (partNumber > count || seen.has(partNumber) || typeof part.etag !== 'string' || !part.etag.trim()) throw new TypeError('Invalid or duplicate completed part');\n seen.add(partNumber);\n return { partNumber, etag: part.etag };\n });\n return this.transferMultipart(file, { ...previous, partSize: size, parts }, options);\n }\n\n // 只重传同一签名地址的同一片内容;平台的 init/partUrls/complete 不自动重放。\n private async putPart(url: string, body: Blob, options: ResumeMultipartOptions, maxRetries: number): Promise<Response> {\n const signed = storageURL(url);\n for (let attempt = 0; ; attempt++) {\n options.signal?.throwIfAborted();\n try { return await this.storage(signed, { method: 'PUT', body }, options); }\n catch (error) {\n if (options.signal?.aborted || attempt >= maxRetries || !retryablePart(error)) throw error;\n await retryDelay(attempt, options.signal);\n }\n }\n }\n\n private async transferMultipart(file: File, session: MultipartSession, options: ResumeMultipartOptions): Promise<MultipartResult> {\n const { concurrency, maxRetries } = transferOptions(options);\n const { signal, onProgress } = options;\n const size = session.partSize!;\n const count = Math.ceil(file.size / size);\n const completed = new Set(session.parts.map(part => Number(part.partNumber)));\n const pending = Array.from({ length: count }, (_, i) => i + 1).filter(number => !completed.has(number));\n let uploadedBytes = session.parts.reduce((sum, part) => sum + Math.min(size, file.size - (Number(part.partNumber) - 1) * size), 0);\n let cursor = 0, failed = false, failure: unknown;\n const worker = async () => {\n while (!failed && cursor < pending.length) {\n const partNumber = pending[cursor++];\n try {\n signal?.throwIfAborted();\n const result = await this.multipart.partUrls({ fileKey: session.fileKey, uploadId: session.uploadId, partNumbers: [partNumber] }, { signal });\n const signed = result.partUrls.find(part => Number(part.partNumber) === partNumber);\n if (!signed?.url) throw new ApiError(200, 0, 'Missing signed part URL');\n const part = file.slice((partNumber - 1) * size, Math.min(partNumber * size, file.size));\n const response = await this.putPart(signed.url, part, options, maxRetries);\n const etag = response.headers.get('etag');\n if (!etag?.trim()) throw new ApiError(response.status, 0, 'Storage response is missing ETag');\n session.parts.push({ partNumber, etag });\n uploadedBytes += part.size;\n onProgress?.({ uploadedBytes, totalBytes: file.size, doneParts: session.parts.length, totalParts: count, percent: uploadedBytes / file.size * 100 });\n } catch (error) { if (!failed) { failed = true; failure = error; } }\n }\n };\n // 必须等在途分片收敛再交出会话,失败后不再领取新分片,也不隐式取消远端上传。\n await Promise.all(Array.from({ length: Math.min(concurrency, pending.length) }, worker));\n session.parts.sort((a, b) => Number(a.partNumber) - Number(b.partNumber));\n try {\n if (failed) throw failure;\n signal?.throwIfAborted();\n session.completionAttempted = true;\n return await this.multipart.complete({ fileKey: session.fileKey, uploadId: session.uploadId, parts: session.parts }, { signal });\n } catch (error) { throw new MultipartUploadError(session, error); }\n }\n\n url(query: Parameters<typeof this.api.url>[0], options?: RequestOptions) { return this.api.url(query, options); }\n delete(body: Schemas['AssetFileDeleteReq'], options?: RequestOptions) { return this.api.delete(body, options); }\n async download(query: Parameters<typeof this.api.url>[0], options: RequestOptions = {}): Promise<Response> {\n const { fileUrl } = await this.api.url(query, options);\n return this.storage(fileUrl, { method: 'GET' }, options);\n }\n}\nexport function createFilesClient(config: ClientConfig = {}): FilesClient { return new FilesClient(new HttpClient(config)); }\n"]}