@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;
@@ -23,7 +23,8 @@ exports.CloudTransportError = CloudTransportError;
23
23
  /** Single fetch, no redirects/retries; one deadline covers both headers and body. */
24
24
  class CloudTransport {
25
25
  resolveClient;
26
- timeoutMs;
26
+ configuredTimeoutMs;
27
+ get timeoutMs() { return this.configuredTimeoutMs ?? this.resolveClient().timeoutMs; }
27
28
  unsV2MaxResponseBytes;
28
29
  #unsV2AppDataSubject;
29
30
  constructor(resolveClient = client_js_1.getClient, config = {}) {
@@ -32,7 +33,7 @@ class CloudTransport {
32
33
  if (!Number.isInteger(timeout) || timeout < 1 || timeout > 2_147_483_647) {
33
34
  throw new TypeError('Tier0 SDK: transportTimeoutMs must be an integer between 1 and 2147483647.');
34
35
  }
35
- this.timeoutMs = timeout;
36
+ this.configuredTimeoutMs = config.transportTimeoutMs;
36
37
  const maxResponseBytes = config.unsV2MaxResponseBytes ?? exports.UNS_V2_MAX_RESPONSE_BYTES;
37
38
  if (!Number.isInteger(maxResponseBytes) || maxResponseBytes < 1 || maxResponseBytes > exports.UNS_V2_MAX_RESPONSE_BYTES) {
38
39
  throw new TypeError('Tier0 SDK: unsV2MaxResponseBytes must be an integer between 1 and 20971520.');
@@ -224,22 +225,30 @@ class CloudTransport {
224
225
  close();
225
226
  }
226
227
  }
227
- async post(path, body) {
228
- const client = this.resolveClient();
229
- const url = `${client.getBaseURL()}${path}`;
230
- const key = client.getApiKey();
231
- const headers = { 'Content-Type': 'application/json' };
232
- if (key) {
233
- headers.Authorization = `Bearer ${key}`;
234
- headers['X-API-Key'] = key;
235
- }
228
+ async post(path, body, signal, runtime) {
236
229
  const serialized = JSON.stringify(body);
237
230
  const controller = new AbortController();
231
+ const abort = () => controller.abort();
232
+ signal?.addEventListener('abort', abort, { once: true });
233
+ if (signal?.aborted)
234
+ controller.abort();
238
235
  let response;
239
236
  let timer;
240
237
  const exchange = async () => {
241
238
  try {
242
- response = await client.getFetch()(url, { method: 'POST', headers, body: serialized, redirect: 'manual', signal: controller.signal });
239
+ if (runtime)
240
+ response = await runtime.request(path, body, { signal: controller.signal });
241
+ else {
242
+ const client = this.resolveClient();
243
+ const url = `${client.getBaseURL()}${path}`;
244
+ const key = client.getApiKey();
245
+ const headers = { 'Content-Type': 'application/json' };
246
+ if (key) {
247
+ headers.Authorization = `Bearer ${key}`;
248
+ headers['X-API-Key'] = key;
249
+ }
250
+ response = await client.getFetch()(url, { method: 'POST', headers, body: serialized, redirect: 'manual', signal: controller.signal });
251
+ }
243
252
  }
244
253
  catch {
245
254
  throw new CloudTransportError('TRANSPORT_ERROR');
@@ -255,21 +264,21 @@ class CloudTransport {
255
264
  };
256
265
  try {
257
266
  const deadline = new Promise((_resolve, reject) => {
267
+ const stopped = () => reject(new CloudTransportError('TRANSPORT_ERROR', response?.status));
268
+ controller.signal.addEventListener('abort', stopped, { once: true });
269
+ if (controller.signal.aborted)
270
+ stopped();
258
271
  timer = setTimeout(() => {
259
- controller.abort();
260
272
  reject(new CloudTransportError('TRANSPORT_TIMEOUT', response?.status));
273
+ controller.abort();
261
274
  }, this.timeoutMs);
262
275
  });
263
276
  // Also bounds custom transports which ignore AbortSignal.
264
277
  return await Promise.race([exchange(), deadline]);
265
278
  }
266
- catch (error) {
267
- if (controller.signal.aborted)
268
- throw new CloudTransportError('TRANSPORT_TIMEOUT', response?.status);
269
- throw error;
270
- }
271
279
  finally {
272
280
  clearTimeout(timer);
281
+ signal?.removeEventListener('abort', abort);
273
282
  }
274
283
  }
275
284
  }
@@ -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/cjs/files.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FilesClient = exports.DEFAULT_MULTIPART_PART_SIZE = exports.MULTIPART_THRESHOLD_BYTES = exports.MultipartUploadError = void 0;
3
+ exports.FilesClient = exports.DEFAULT_MULTIPART_MAX_RETRIES = exports.DEFAULT_MULTIPART_CONCURRENCY = exports.DEFAULT_MULTIPART_PART_SIZE = exports.MULTIPART_THRESHOLD_BYTES = exports.MultipartUploadError = void 0;
4
4
  exports.createFilesClient = createFilesClient;
5
5
  const client_js_1 = require("./openapi/client.js");
6
6
  const api_generated_js_1 = require("./openapi/api.generated.js");
@@ -17,9 +17,11 @@ class MultipartUploadError extends Error {
17
17
  exports.MultipartUploadError = MultipartUploadError;
18
18
  exports.MULTIPART_THRESHOLD_BYTES = 100 * 1024 * 1024;
19
19
  exports.DEFAULT_MULTIPART_PART_SIZE = 8 * 1024 * 1024;
20
+ exports.DEFAULT_MULTIPART_CONCURRENCY = 4;
21
+ exports.DEFAULT_MULTIPART_MAX_RETRIES = 3;
20
22
  function positiveSafe(value, name) {
21
23
  const n = Number(value);
22
- if (!Number.isSafeInteger(n) || n <= 0)
24
+ if (!['number', 'bigint'].includes(typeof value) || !Number.isSafeInteger(n) || n <= 0)
23
25
  throw new TypeError(`Invalid ${name}`);
24
26
  return n;
25
27
  }
@@ -27,6 +29,38 @@ function validateFile(file) {
27
29
  if (!file || typeof file.name !== 'string' || !file.name || !Number.isSafeInteger(file.size) || file.size < 0 || typeof file.slice !== 'function')
28
30
  throw new TypeError('A File is required');
29
31
  }
32
+ function storageURL(value) {
33
+ const url = new URL(value);
34
+ if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password)
35
+ throw new TypeError('Invalid signed storage URL');
36
+ return url.href;
37
+ }
38
+ function transferOptions(options) {
39
+ const { concurrency = exports.DEFAULT_MULTIPART_CONCURRENCY, maxRetries = exports.DEFAULT_MULTIPART_MAX_RETRIES } = options;
40
+ if (!Number.isSafeInteger(concurrency) || concurrency < 1)
41
+ throw new TypeError('concurrency must be a positive safe integer');
42
+ if (!Number.isSafeInteger(maxRetries) || maxRetries < 0)
43
+ throw new TypeError('maxRetries must be a non-negative safe integer');
44
+ if (options.onProgress !== undefined && typeof options.onProgress !== 'function')
45
+ throw new TypeError('onProgress must be a function');
46
+ return { concurrency, maxRetries };
47
+ }
48
+ function retryablePart(error) {
49
+ if (error instanceof client_js_1.TransportError)
50
+ return error.errorCode === 'SDK_TIMEOUT';
51
+ if (error instanceof client_js_1.ApiError)
52
+ return [408, 429, 500, 502, 503, 504].includes(error.status);
53
+ return error instanceof TypeError || (error instanceof Error && error.name === 'AbortError');
54
+ }
55
+ function retryDelay(attempt, signal) {
56
+ signal?.throwIfAborted();
57
+ return new Promise((resolve, reject) => {
58
+ const finish = () => { signal?.removeEventListener('abort', abort); resolve(); };
59
+ const timer = setTimeout(finish, Math.min(100 * 2 ** Math.min(attempt, 5), 3000));
60
+ const abort = () => { clearTimeout(timer); signal?.removeEventListener('abort', abort); reject(signal?.reason); };
61
+ signal?.addEventListener('abort', abort, { once: true });
62
+ });
63
+ }
30
64
  /** All platform requests are scoped to this instance; storage requests never carry its API key. */
31
65
  class FilesClient {
32
66
  http;
@@ -38,20 +72,35 @@ class FilesClient {
38
72
  this.multipart = this.api.multipart;
39
73
  }
40
74
  async storage(urlString, init, options = {}) {
41
- const url = new URL(urlString);
42
- if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password)
43
- throw new TypeError('Invalid signed storage URL');
75
+ const url = storageURL(urlString);
76
+ options.signal?.throwIfAborted();
44
77
  const controller = new AbortController();
45
- const abort = () => controller.abort(options.signal?.reason);
46
- const timer = setTimeout(() => controller.abort(), this.http.timeoutMs);
78
+ let expired = false;
79
+ let started = false;
80
+ let rejectStopped = () => undefined;
81
+ const stopped = new Promise((_resolve, reject) => { rejectStopped = reject; });
82
+ const failure = () => new client_js_1.TransportError(expired ? 'TIMEOUT' : 'ABORTED', started && init.method !== 'GET');
83
+ const abort = () => { rejectStopped(failure()); controller.abort(options.signal?.reason); };
84
+ const timer = setTimeout(() => { expired = true; abort(); }, this.http.timeoutMs);
47
85
  options.signal?.addEventListener('abort', abort, { once: true });
48
- try {
49
- if (options.signal?.aborted)
50
- abort();
51
- const response = await this.http.getFetch()(url.href, { ...init, signal: controller.signal, credentials: 'omit', redirect: 'error' });
86
+ const exchange = async () => {
87
+ if (controller.signal.aborted)
88
+ throw failure();
89
+ started = true;
90
+ const response = await this.http.getFetch()(url, { ...init, signal: controller.signal, credentials: 'omit', redirect: 'error' });
91
+ // 忽略 AbortSignal 的自定义 fetch 晚返回也不能改变已交还的分片会话。
92
+ if (controller.signal.aborted) {
93
+ void response.body?.cancel().catch(() => undefined);
94
+ throw failure();
95
+ }
52
96
  if (!response.ok)
53
97
  throw new client_js_1.ApiError(response.status, 0, 'Object storage request failed');
54
98
  return response;
99
+ };
100
+ try {
101
+ if (options.signal?.aborted)
102
+ abort();
103
+ return await Promise.race([exchange(), stopped]);
55
104
  }
56
105
  finally {
57
106
  clearTimeout(timer);
@@ -60,9 +109,9 @@ class FilesClient {
60
109
  }
61
110
  async upload(file, options = {}) {
62
111
  validateFile(file);
63
- if (file.size > exports.MULTIPART_THRESHOLD_BYTES)
64
- return this.uploadMultipart(file, options);
65
- const { signal, ...metadata } = options;
112
+ const { signal, multipart, ...metadata } = options;
113
+ if (file.size > exports.MULTIPART_THRESHOLD_BYTES || multipart !== undefined)
114
+ return this.uploadMultipart(file, { ...metadata, ...multipart, signal });
66
115
  const prepared = await this.api.prepareUpload({ ...metadata, fileName: file.name, size: file.size, contentType: file.type || 'application/octet-stream' }, { signal });
67
116
  if (!prepared.postUrl || !prepared.filePath || !prepared.postFields)
68
117
  throw new client_js_1.ApiError(200, 0, 'Invalid upload preparation response');
@@ -77,29 +126,103 @@ class FilesClient {
77
126
  validateFile(file);
78
127
  if (file.size === 0)
79
128
  throw new TypeError('Multipart upload requires a non-empty file');
80
- const { signal, partSize = exports.DEFAULT_MULTIPART_PART_SIZE, onProgress, ...metadata } = options;
129
+ const { signal, partSize = exports.DEFAULT_MULTIPART_PART_SIZE, onProgress, concurrency, maxRetries, ...metadata } = options;
130
+ transferOptions(options);
81
131
  if (!Number.isSafeInteger(partSize) || partSize < 5 * 1024 * 1024)
82
132
  throw new TypeError('partSize must be at least 5 MiB');
133
+ signal?.throwIfAborted();
83
134
  const start = await this.multipart.init({ ...metadata, fileName: file.name, contentType: file.type || 'application/octet-stream', size: file.size, partSize }, { signal });
84
- const session = { fileKey: start.fileKey, uploadId: start.uploadId, parts: [], completionAttempted: false };
135
+ const session = { fileKey: start.fileKey, uploadId: start.uploadId, parts: [], completionAttempted: false, fileName: file.name, fileSize: file.size };
85
136
  try {
86
137
  const size = positiveSafe(start.partSize, 'server partSize');
87
138
  const count = positiveSafe(start.partCount, 'server partCount');
88
139
  if (!start.fileKey || !start.uploadId || count !== Math.ceil(file.size / size) || size < 5 * 1024 * 1024 || count > 10_000)
89
140
  throw new TypeError('Invalid multipart preparation response');
90
- for (let partNumber = 1; partNumber <= count; partNumber++) {
91
- const result = await this.multipart.partUrls({ fileKey: start.fileKey, uploadId: start.uploadId, partNumbers: [partNumber] }, { signal });
92
- const signed = result.partUrls.find(p => Number(p.partNumber) === partNumber);
93
- if (!signed?.url)
94
- throw new client_js_1.ApiError(200, 0, 'Missing signed part URL');
95
- const end = Math.min(partNumber * size, file.size);
96
- const response = await this.storage(signed.url, { method: 'PUT', body: file.slice((partNumber - 1) * size, end) }, { signal });
97
- const etag = response.headers.get('etag');
98
- if (!etag)
99
- throw new client_js_1.ApiError(response.status, 0, 'Storage response is missing ETag');
100
- session.parts.push({ partNumber, etag });
101
- onProgress?.({ uploadedBytes: end, totalBytes: file.size });
141
+ session.partSize = size;
142
+ }
143
+ catch (error) {
144
+ throw new MultipartUploadError(session, error);
145
+ }
146
+ return this.transferMultipart(file, session, { signal, onProgress, concurrency, maxRetries });
147
+ }
148
+ async resumeMultipart(file, previous, options = {}) {
149
+ validateFile(file);
150
+ transferOptions(options);
151
+ if (!previous || previous.completionAttempted !== false)
152
+ throw new TypeError('Reconcile the previous completion before resuming');
153
+ if (!previous.partSize || previous.fileSize !== file.size || previous.fileName !== file.name || file.size === 0)
154
+ throw new TypeError('Resume requires the original file name, size and server partSize');
155
+ const size = positiveSafe(previous.partSize, 'session partSize');
156
+ const count = Math.ceil(file.size / size);
157
+ if (size < 5 * 1024 * 1024 || count > 10_000 || typeof previous.fileKey !== 'string' || !previous.fileKey || typeof previous.uploadId !== 'string' || !previous.uploadId || !Array.isArray(previous.parts))
158
+ throw new TypeError('Invalid multipart session');
159
+ const seen = new Set();
160
+ const parts = previous.parts.map(part => {
161
+ const partNumber = positiveSafe(part.partNumber, 'session partNumber');
162
+ if (partNumber > count || seen.has(partNumber) || typeof part.etag !== 'string' || !part.etag.trim())
163
+ throw new TypeError('Invalid or duplicate completed part');
164
+ seen.add(partNumber);
165
+ return { partNumber, etag: part.etag };
166
+ });
167
+ return this.transferMultipart(file, { ...previous, partSize: size, parts }, options);
168
+ }
169
+ // 只重传同一签名地址的同一片内容;平台的 init/partUrls/complete 不自动重放。
170
+ async putPart(url, body, options, maxRetries) {
171
+ const signed = storageURL(url);
172
+ for (let attempt = 0;; attempt++) {
173
+ options.signal?.throwIfAborted();
174
+ try {
175
+ return await this.storage(signed, { method: 'PUT', body }, options);
102
176
  }
177
+ catch (error) {
178
+ if (options.signal?.aborted || attempt >= maxRetries || !retryablePart(error))
179
+ throw error;
180
+ await retryDelay(attempt, options.signal);
181
+ }
182
+ }
183
+ }
184
+ async transferMultipart(file, session, options) {
185
+ const { concurrency, maxRetries } = transferOptions(options);
186
+ const { signal, onProgress } = options;
187
+ const size = session.partSize;
188
+ const count = Math.ceil(file.size / size);
189
+ const completed = new Set(session.parts.map(part => Number(part.partNumber)));
190
+ const pending = Array.from({ length: count }, (_, i) => i + 1).filter(number => !completed.has(number));
191
+ let uploadedBytes = session.parts.reduce((sum, part) => sum + Math.min(size, file.size - (Number(part.partNumber) - 1) * size), 0);
192
+ let cursor = 0, failed = false, failure;
193
+ const worker = async () => {
194
+ while (!failed && cursor < pending.length) {
195
+ const partNumber = pending[cursor++];
196
+ try {
197
+ signal?.throwIfAborted();
198
+ const result = await this.multipart.partUrls({ fileKey: session.fileKey, uploadId: session.uploadId, partNumbers: [partNumber] }, { signal });
199
+ const signed = result.partUrls.find(part => Number(part.partNumber) === partNumber);
200
+ if (!signed?.url)
201
+ throw new client_js_1.ApiError(200, 0, 'Missing signed part URL');
202
+ const part = file.slice((partNumber - 1) * size, Math.min(partNumber * size, file.size));
203
+ const response = await this.putPart(signed.url, part, options, maxRetries);
204
+ const etag = response.headers.get('etag');
205
+ if (!etag?.trim())
206
+ throw new client_js_1.ApiError(response.status, 0, 'Storage response is missing ETag');
207
+ session.parts.push({ partNumber, etag });
208
+ uploadedBytes += part.size;
209
+ onProgress?.({ uploadedBytes, totalBytes: file.size, doneParts: session.parts.length, totalParts: count, percent: uploadedBytes / file.size * 100 });
210
+ }
211
+ catch (error) {
212
+ if (!failed) {
213
+ failed = true;
214
+ failure = error;
215
+ }
216
+ }
217
+ }
218
+ };
219
+ // 必须等在途分片收敛再交出会话,失败后不再领取新分片,也不隐式取消远端上传。
220
+ await Promise.all(Array.from({ length: Math.min(concurrency, pending.length) }, worker));
221
+ session.parts.sort((a, b) => Number(a.partNumber) - Number(b.partNumber));
222
+ try {
223
+ if (failed)
224
+ throw failure;
225
+ signal?.throwIfAborted();
103
226
  session.completionAttempted = true;
104
227
  return await this.multipart.complete({ fileKey: session.fileKey, uploadId: session.uploadId, parts: session.parts }, { signal });
105
228
  }
@@ -1 +1 @@
1
- {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/files.ts"],"names":[],"mappings":"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","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":"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","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"]}