@tearleads/client-sdk 0.1.32 → 0.1.33

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 (27) hide show
  1. package/internal/api-client/ApiClient.js +3 -27
  2. package/internal/api-client/ApiClient.js.map +1 -1
  3. package/internal/api-client/routes/blobs/multipartUpload.js +139 -0
  4. package/internal/api-client/routes/blobs/multipartUpload.js.map +1 -0
  5. package/internal/api-client/types.d.ts +1 -1
  6. package/internal/api-client/types.js.map +1 -1
  7. package/internal/validators/operation/blobDownloads.js +3 -9
  8. package/internal/validators/operation/blobDownloads.js.map +1 -1
  9. package/internal/validators/operation/blobTransferSchemas.js +11 -0
  10. package/internal/validators/operation/blobTransferSchemas.js.map +1 -0
  11. package/internal/validators/operation/index.d.ts +1 -0
  12. package/internal/validators/operation/index.js +1 -0
  13. package/internal/validators/operation/index.js.map +1 -1
  14. package/internal/validators/operation/multipartPartUploads.d.ts +179 -0
  15. package/internal/validators/operation/multipartPartUploads.js +47 -0
  16. package/internal/validators/operation/multipartPartUploads.js.map +1 -0
  17. package/internal/validators/operation/registry.d.ts +2 -0
  18. package/internal/validators/operation/registry.js +2 -0
  19. package/internal/validators/operation/registry.js.map +1 -1
  20. package/internal/validators/util/blob.d.ts +2 -4
  21. package/internal/validators/util/blob.js +2 -4
  22. package/internal/validators/util/blob.js.map +1 -1
  23. package/package.json +1 -1
  24. package/workflows/blobs/multipartStageFailures.js +1 -1
  25. package/workflows/blobs/multipartStageFailures.js.map +1 -1
  26. package/workflows/blobs/multipartUpload.js +15 -12
  27. package/workflows/blobs/multipartUpload.js.map +1 -1
@@ -11,6 +11,7 @@ import { createDocumentOperation, getDocumentPurgeProofOperation, linkDocumentOp
11
11
  import { documentSyncOperation } from "./documentSync.js";
12
12
  import { getHealthOperation } from "./health.js";
13
13
  import { completeMultipartBlobStageOperation, getMultipartBlobStageOperation, initiateMultipartBlobStageOperation, } from "./multipartBlobs.js";
14
+ import { authorizeMultipartBlobPartUploadOperation } from "./multipartPartUploads.js";
14
15
  import { claimNativeOrganizationSubscriptionOperation, getOrganizationBillingHistoryOperation, getOrganizationBillingManagementUrlOperation, getOrganizationBillingOperation, getOrganizationNativePurchaseEligibilityOperation, startOrganizationTrialOperation, } from "./organizationBilling.js";
15
16
  import { getOrganizationPolicyHistoryOperation } from "./organizationPolicyHistory.js";
16
17
  import { createOrganizationGroupOperation, createOrganizationOperation, deleteOrganizationGroupOperation, getOrganizationDataUsageOperation, getOrganizationReadModelOperation, listOrganizationGroupMembersOperation, updateOrganizationProfileOperation, updateOrganizationRosterEntryOperation, } from "./organizations.js";
@@ -42,6 +43,7 @@ export const protocolOperations = [
42
43
  initiateMultipartBlobStageOperation,
43
44
  getMultipartBlobStageOperation,
44
45
  completeMultipartBlobStageOperation,
46
+ authorizeMultipartBlobPartUploadOperation,
45
47
  uploadMultipartBlobPartBytesOperation,
46
48
  listDocumentAttachmentsOperation,
47
49
  getDocumentAttributionOperation,
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["registry.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n bindBlobAttachmentOperation,\n detachBlobAttachmentOperation,\n listDocumentAttachmentsOperation,\n} from \"./attachments\";\nimport {\n challengeOperation,\n destroySessionOperation,\n listSessionsOperation,\n logoutOperation,\n registerOperation,\n userIdentityOperation,\n verifyOperation,\n webSocketTicketOperation,\n} from \"./auth\";\nimport {\n receiveRevenueCatWebhookOperation,\n receiveStripeWebhookOperation,\n} from \"./billingWebhooks\";\nimport {\n getBlobBytesOperation,\n uploadMultipartBlobPartBytesOperation,\n} from \"./blobBytes\";\nimport { getBlobDownloadOperation } from \"./blobDownloads\";\nimport {\n createContainerOperation,\n createContainerWithMetadataDocumentOperation,\n deleteContainerOperation,\n moveContainerOperation,\n reciteContainerOperation,\n rekeyContainerOperation,\n revokeContainerOperation,\n shareContainerOperation,\n} from \"./containerMutations\";\nimport {\n getContainerKekLogOperation,\n listContainerDocumentsOperation,\n listContainerParentLanesOperation,\n} from \"./containerReads\";\nimport { getContainerReplacementAuthorizationsOperation } from \"./containerReplacement\";\nimport {\n getDocumentAttributionOperation,\n listDocumentAttributionRangesOperation,\n} from \"./documentAttribution\";\nimport {\n createDocumentOperation,\n getDocumentPurgeProofOperation,\n linkDocumentOperation,\n purgeDocumentOperation,\n unlinkDocumentOperation,\n} from \"./documentMutations\";\nimport { documentSyncOperation } from \"./documentSync\";\nimport { getHealthOperation } from \"./health\";\nimport {\n completeMultipartBlobStageOperation,\n getMultipartBlobStageOperation,\n initiateMultipartBlobStageOperation,\n} from \"./multipartBlobs\";\nimport {\n claimNativeOrganizationSubscriptionOperation,\n getOrganizationBillingHistoryOperation,\n getOrganizationBillingManagementUrlOperation,\n getOrganizationBillingOperation,\n getOrganizationNativePurchaseEligibilityOperation,\n startOrganizationTrialOperation,\n} from \"./organizationBilling\";\nimport { getOrganizationPolicyHistoryOperation } from \"./organizationPolicyHistory\";\nimport {\n createOrganizationGroupOperation,\n createOrganizationOperation,\n deleteOrganizationGroupOperation,\n getOrganizationDataUsageOperation,\n getOrganizationReadModelOperation,\n listOrganizationGroupMembersOperation,\n updateOrganizationProfileOperation,\n updateOrganizationRosterEntryOperation,\n} from \"./organizations\";\nimport {\n commitOrganizationGroupPolicyOperation,\n getPrincipalPolicyOperation,\n putPrincipalPolicyOperation,\n} from \"./principals\";\nimport { getProjectionPolicyHistoryOperation } from \"./projectionPolicyHistory\";\nimport {\n getRootIdentityOperation,\n listRootIdentitiesOperation,\n listRootIdentityOrganizationsOperation,\n} from \"./root\";\nimport {\n getRootOrganizationDataUsageOperation,\n getRootOrganizationOperation,\n listRootDataUsageReportOperation,\n listRootOrganizationIdentitiesOperation,\n listRootOrganizationsOperation,\n} from \"./rootOrganizations\";\nimport {\n cancelStripeSubscriptionOperation,\n createStripeCheckoutOperation,\n createStripeCheckoutSessionOperation,\n createStripePortalOperation,\n getStripeCheckoutOptionsOperation,\n} from \"./stripeCheckout\";\nimport {\n getContainerWriterProjectionOperation,\n getDocumentWriterProjectionOperation,\n} from \"./writerProjections\";\n\n// Name each imported operation type instead of expanding every Zod schema in\n// the emitted declaration; the exact readonly tuple and runtime order stay intact.\nexport const protocolOperations: readonly [\n typeof getContainerReplacementAuthorizationsOperation,\n typeof getHealthOperation,\n typeof challengeOperation,\n typeof destroySessionOperation,\n typeof listSessionsOperation,\n typeof logoutOperation,\n typeof registerOperation,\n typeof userIdentityOperation,\n typeof verifyOperation,\n typeof webSocketTicketOperation,\n typeof getBlobBytesOperation,\n typeof getBlobDownloadOperation,\n typeof receiveRevenueCatWebhookOperation,\n typeof receiveStripeWebhookOperation,\n typeof bindBlobAttachmentOperation,\n typeof detachBlobAttachmentOperation,\n typeof initiateMultipartBlobStageOperation,\n typeof getMultipartBlobStageOperation,\n typeof completeMultipartBlobStageOperation,\n typeof uploadMultipartBlobPartBytesOperation,\n typeof listDocumentAttachmentsOperation,\n typeof getDocumentAttributionOperation,\n typeof listDocumentAttributionRangesOperation,\n typeof createDocumentOperation,\n typeof getDocumentPurgeProofOperation,\n typeof linkDocumentOperation,\n typeof purgeDocumentOperation,\n typeof unlinkDocumentOperation,\n typeof getContainerKekLogOperation,\n typeof listContainerDocumentsOperation,\n typeof listContainerParentLanesOperation,\n typeof createContainerOperation,\n typeof createContainerWithMetadataDocumentOperation,\n typeof deleteContainerOperation,\n typeof moveContainerOperation,\n typeof reciteContainerOperation,\n typeof rekeyContainerOperation,\n typeof revokeContainerOperation,\n typeof shareContainerOperation,\n typeof getContainerWriterProjectionOperation,\n typeof getDocumentWriterProjectionOperation,\n typeof createOrganizationOperation,\n typeof getOrganizationBillingOperation,\n typeof getOrganizationBillingHistoryOperation,\n typeof getOrganizationBillingManagementUrlOperation,\n typeof getOrganizationNativePurchaseEligibilityOperation,\n typeof claimNativeOrganizationSubscriptionOperation,\n typeof startOrganizationTrialOperation,\n typeof getStripeCheckoutOptionsOperation,\n typeof createStripeCheckoutOperation,\n typeof createStripeCheckoutSessionOperation,\n typeof createStripePortalOperation,\n typeof cancelStripeSubscriptionOperation,\n typeof getOrganizationDataUsageOperation,\n typeof getOrganizationReadModelOperation,\n typeof getOrganizationPolicyHistoryOperation,\n typeof createOrganizationGroupOperation,\n typeof deleteOrganizationGroupOperation,\n typeof listOrganizationGroupMembersOperation,\n typeof updateOrganizationProfileOperation,\n typeof updateOrganizationRosterEntryOperation,\n typeof getPrincipalPolicyOperation,\n typeof getProjectionPolicyHistoryOperation,\n typeof commitOrganizationGroupPolicyOperation,\n typeof putPrincipalPolicyOperation,\n typeof listRootIdentitiesOperation,\n typeof listRootOrganizationsOperation,\n typeof getRootOrganizationDataUsageOperation,\n typeof listRootDataUsageReportOperation,\n typeof getRootOrganizationOperation,\n typeof listRootOrganizationIdentitiesOperation,\n typeof getRootIdentityOperation,\n typeof listRootIdentityOrganizationsOperation,\n typeof documentSyncOperation,\n] = [\n getContainerReplacementAuthorizationsOperation,\n getHealthOperation,\n challengeOperation,\n destroySessionOperation,\n listSessionsOperation,\n logoutOperation,\n registerOperation,\n userIdentityOperation,\n verifyOperation,\n webSocketTicketOperation,\n getBlobBytesOperation,\n getBlobDownloadOperation,\n receiveRevenueCatWebhookOperation,\n receiveStripeWebhookOperation,\n bindBlobAttachmentOperation,\n detachBlobAttachmentOperation,\n initiateMultipartBlobStageOperation,\n getMultipartBlobStageOperation,\n completeMultipartBlobStageOperation,\n uploadMultipartBlobPartBytesOperation,\n listDocumentAttachmentsOperation,\n getDocumentAttributionOperation,\n listDocumentAttributionRangesOperation,\n createDocumentOperation,\n getDocumentPurgeProofOperation,\n linkDocumentOperation,\n purgeDocumentOperation,\n unlinkDocumentOperation,\n getContainerKekLogOperation,\n listContainerDocumentsOperation,\n listContainerParentLanesOperation,\n createContainerOperation,\n createContainerWithMetadataDocumentOperation,\n deleteContainerOperation,\n moveContainerOperation,\n reciteContainerOperation,\n rekeyContainerOperation,\n revokeContainerOperation,\n shareContainerOperation,\n getContainerWriterProjectionOperation,\n getDocumentWriterProjectionOperation,\n createOrganizationOperation,\n getOrganizationBillingOperation,\n getOrganizationBillingHistoryOperation,\n getOrganizationBillingManagementUrlOperation,\n getOrganizationNativePurchaseEligibilityOperation,\n claimNativeOrganizationSubscriptionOperation,\n startOrganizationTrialOperation,\n getStripeCheckoutOptionsOperation,\n createStripeCheckoutOperation,\n createStripeCheckoutSessionOperation,\n createStripePortalOperation,\n cancelStripeSubscriptionOperation,\n getOrganizationDataUsageOperation,\n getOrganizationReadModelOperation,\n getOrganizationPolicyHistoryOperation,\n createOrganizationGroupOperation,\n deleteOrganizationGroupOperation,\n listOrganizationGroupMembersOperation,\n updateOrganizationProfileOperation,\n updateOrganizationRosterEntryOperation,\n getPrincipalPolicyOperation,\n getProjectionPolicyHistoryOperation,\n commitOrganizationGroupPolicyOperation,\n putPrincipalPolicyOperation,\n listRootIdentitiesOperation,\n listRootOrganizationsOperation,\n getRootOrganizationDataUsageOperation,\n listRootDataUsageReportOperation,\n getRootOrganizationOperation,\n listRootOrganizationIdentitiesOperation,\n getRootIdentityOperation,\n listRootIdentityOrganizationsOperation,\n documentSyncOperation,\n];\n"]}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["registry.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n bindBlobAttachmentOperation,\n detachBlobAttachmentOperation,\n listDocumentAttachmentsOperation,\n} from \"./attachments\";\nimport {\n challengeOperation,\n destroySessionOperation,\n listSessionsOperation,\n logoutOperation,\n registerOperation,\n userIdentityOperation,\n verifyOperation,\n webSocketTicketOperation,\n} from \"./auth\";\nimport {\n receiveRevenueCatWebhookOperation,\n receiveStripeWebhookOperation,\n} from \"./billingWebhooks\";\nimport {\n getBlobBytesOperation,\n uploadMultipartBlobPartBytesOperation,\n} from \"./blobBytes\";\nimport { getBlobDownloadOperation } from \"./blobDownloads\";\nimport {\n createContainerOperation,\n createContainerWithMetadataDocumentOperation,\n deleteContainerOperation,\n moveContainerOperation,\n reciteContainerOperation,\n rekeyContainerOperation,\n revokeContainerOperation,\n shareContainerOperation,\n} from \"./containerMutations\";\nimport {\n getContainerKekLogOperation,\n listContainerDocumentsOperation,\n listContainerParentLanesOperation,\n} from \"./containerReads\";\nimport { getContainerReplacementAuthorizationsOperation } from \"./containerReplacement\";\nimport {\n getDocumentAttributionOperation,\n listDocumentAttributionRangesOperation,\n} from \"./documentAttribution\";\nimport {\n createDocumentOperation,\n getDocumentPurgeProofOperation,\n linkDocumentOperation,\n purgeDocumentOperation,\n unlinkDocumentOperation,\n} from \"./documentMutations\";\nimport { documentSyncOperation } from \"./documentSync\";\nimport { getHealthOperation } from \"./health\";\nimport {\n completeMultipartBlobStageOperation,\n getMultipartBlobStageOperation,\n initiateMultipartBlobStageOperation,\n} from \"./multipartBlobs\";\nimport { authorizeMultipartBlobPartUploadOperation } from \"./multipartPartUploads\";\nimport {\n claimNativeOrganizationSubscriptionOperation,\n getOrganizationBillingHistoryOperation,\n getOrganizationBillingManagementUrlOperation,\n getOrganizationBillingOperation,\n getOrganizationNativePurchaseEligibilityOperation,\n startOrganizationTrialOperation,\n} from \"./organizationBilling\";\nimport { getOrganizationPolicyHistoryOperation } from \"./organizationPolicyHistory\";\nimport {\n createOrganizationGroupOperation,\n createOrganizationOperation,\n deleteOrganizationGroupOperation,\n getOrganizationDataUsageOperation,\n getOrganizationReadModelOperation,\n listOrganizationGroupMembersOperation,\n updateOrganizationProfileOperation,\n updateOrganizationRosterEntryOperation,\n} from \"./organizations\";\nimport {\n commitOrganizationGroupPolicyOperation,\n getPrincipalPolicyOperation,\n putPrincipalPolicyOperation,\n} from \"./principals\";\nimport { getProjectionPolicyHistoryOperation } from \"./projectionPolicyHistory\";\nimport {\n getRootIdentityOperation,\n listRootIdentitiesOperation,\n listRootIdentityOrganizationsOperation,\n} from \"./root\";\nimport {\n getRootOrganizationDataUsageOperation,\n getRootOrganizationOperation,\n listRootDataUsageReportOperation,\n listRootOrganizationIdentitiesOperation,\n listRootOrganizationsOperation,\n} from \"./rootOrganizations\";\nimport {\n cancelStripeSubscriptionOperation,\n createStripeCheckoutOperation,\n createStripeCheckoutSessionOperation,\n createStripePortalOperation,\n getStripeCheckoutOptionsOperation,\n} from \"./stripeCheckout\";\nimport {\n getContainerWriterProjectionOperation,\n getDocumentWriterProjectionOperation,\n} from \"./writerProjections\";\n\n// Name each imported operation type instead of expanding every Zod schema in\n// the emitted declaration; the exact readonly tuple and runtime order stay intact.\nexport const protocolOperations: readonly [\n typeof getContainerReplacementAuthorizationsOperation,\n typeof getHealthOperation,\n typeof challengeOperation,\n typeof destroySessionOperation,\n typeof listSessionsOperation,\n typeof logoutOperation,\n typeof registerOperation,\n typeof userIdentityOperation,\n typeof verifyOperation,\n typeof webSocketTicketOperation,\n typeof getBlobBytesOperation,\n typeof getBlobDownloadOperation,\n typeof receiveRevenueCatWebhookOperation,\n typeof receiveStripeWebhookOperation,\n typeof bindBlobAttachmentOperation,\n typeof detachBlobAttachmentOperation,\n typeof initiateMultipartBlobStageOperation,\n typeof getMultipartBlobStageOperation,\n typeof completeMultipartBlobStageOperation,\n typeof authorizeMultipartBlobPartUploadOperation,\n typeof uploadMultipartBlobPartBytesOperation,\n typeof listDocumentAttachmentsOperation,\n typeof getDocumentAttributionOperation,\n typeof listDocumentAttributionRangesOperation,\n typeof createDocumentOperation,\n typeof getDocumentPurgeProofOperation,\n typeof linkDocumentOperation,\n typeof purgeDocumentOperation,\n typeof unlinkDocumentOperation,\n typeof getContainerKekLogOperation,\n typeof listContainerDocumentsOperation,\n typeof listContainerParentLanesOperation,\n typeof createContainerOperation,\n typeof createContainerWithMetadataDocumentOperation,\n typeof deleteContainerOperation,\n typeof moveContainerOperation,\n typeof reciteContainerOperation,\n typeof rekeyContainerOperation,\n typeof revokeContainerOperation,\n typeof shareContainerOperation,\n typeof getContainerWriterProjectionOperation,\n typeof getDocumentWriterProjectionOperation,\n typeof createOrganizationOperation,\n typeof getOrganizationBillingOperation,\n typeof getOrganizationBillingHistoryOperation,\n typeof getOrganizationBillingManagementUrlOperation,\n typeof getOrganizationNativePurchaseEligibilityOperation,\n typeof claimNativeOrganizationSubscriptionOperation,\n typeof startOrganizationTrialOperation,\n typeof getStripeCheckoutOptionsOperation,\n typeof createStripeCheckoutOperation,\n typeof createStripeCheckoutSessionOperation,\n typeof createStripePortalOperation,\n typeof cancelStripeSubscriptionOperation,\n typeof getOrganizationDataUsageOperation,\n typeof getOrganizationReadModelOperation,\n typeof getOrganizationPolicyHistoryOperation,\n typeof createOrganizationGroupOperation,\n typeof deleteOrganizationGroupOperation,\n typeof listOrganizationGroupMembersOperation,\n typeof updateOrganizationProfileOperation,\n typeof updateOrganizationRosterEntryOperation,\n typeof getPrincipalPolicyOperation,\n typeof getProjectionPolicyHistoryOperation,\n typeof commitOrganizationGroupPolicyOperation,\n typeof putPrincipalPolicyOperation,\n typeof listRootIdentitiesOperation,\n typeof listRootOrganizationsOperation,\n typeof getRootOrganizationDataUsageOperation,\n typeof listRootDataUsageReportOperation,\n typeof getRootOrganizationOperation,\n typeof listRootOrganizationIdentitiesOperation,\n typeof getRootIdentityOperation,\n typeof listRootIdentityOrganizationsOperation,\n typeof documentSyncOperation,\n] = [\n getContainerReplacementAuthorizationsOperation,\n getHealthOperation,\n challengeOperation,\n destroySessionOperation,\n listSessionsOperation,\n logoutOperation,\n registerOperation,\n userIdentityOperation,\n verifyOperation,\n webSocketTicketOperation,\n getBlobBytesOperation,\n getBlobDownloadOperation,\n receiveRevenueCatWebhookOperation,\n receiveStripeWebhookOperation,\n bindBlobAttachmentOperation,\n detachBlobAttachmentOperation,\n initiateMultipartBlobStageOperation,\n getMultipartBlobStageOperation,\n completeMultipartBlobStageOperation,\n authorizeMultipartBlobPartUploadOperation,\n uploadMultipartBlobPartBytesOperation,\n listDocumentAttachmentsOperation,\n getDocumentAttributionOperation,\n listDocumentAttributionRangesOperation,\n createDocumentOperation,\n getDocumentPurgeProofOperation,\n linkDocumentOperation,\n purgeDocumentOperation,\n unlinkDocumentOperation,\n getContainerKekLogOperation,\n listContainerDocumentsOperation,\n listContainerParentLanesOperation,\n createContainerOperation,\n createContainerWithMetadataDocumentOperation,\n deleteContainerOperation,\n moveContainerOperation,\n reciteContainerOperation,\n rekeyContainerOperation,\n revokeContainerOperation,\n shareContainerOperation,\n getContainerWriterProjectionOperation,\n getDocumentWriterProjectionOperation,\n createOrganizationOperation,\n getOrganizationBillingOperation,\n getOrganizationBillingHistoryOperation,\n getOrganizationBillingManagementUrlOperation,\n getOrganizationNativePurchaseEligibilityOperation,\n claimNativeOrganizationSubscriptionOperation,\n startOrganizationTrialOperation,\n getStripeCheckoutOptionsOperation,\n createStripeCheckoutOperation,\n createStripeCheckoutSessionOperation,\n createStripePortalOperation,\n cancelStripeSubscriptionOperation,\n getOrganizationDataUsageOperation,\n getOrganizationReadModelOperation,\n getOrganizationPolicyHistoryOperation,\n createOrganizationGroupOperation,\n deleteOrganizationGroupOperation,\n listOrganizationGroupMembersOperation,\n updateOrganizationProfileOperation,\n updateOrganizationRosterEntryOperation,\n getPrincipalPolicyOperation,\n getProjectionPolicyHistoryOperation,\n commitOrganizationGroupPolicyOperation,\n putPrincipalPolicyOperation,\n listRootIdentitiesOperation,\n listRootOrganizationsOperation,\n getRootOrganizationDataUsageOperation,\n listRootDataUsageReportOperation,\n getRootOrganizationOperation,\n listRootOrganizationIdentitiesOperation,\n getRootIdentityOperation,\n listRootIdentityOrganizationsOperation,\n documentSyncOperation,\n];\n"]}
@@ -1,7 +1,5 @@
1
1
  /**
2
- * Protocol ceiling for one buffered multipart blob part. The API buffers a
3
- * part before uploading it, and the Workers isolate that serves uploads has
4
- * 128 MB of memory, so the ceiling leaves room for the copy the digest check
5
- * makes.
2
+ * Protocol ceiling for a multipart blob part. Bounds client hashing and native
3
+ * HTTP bridge buffers for direct uploads, and API buffers for non-signing stores.
6
4
  */
7
5
  export declare const MAX_MULTIPART_BLOB_PART_BYTES: number;
@@ -1,8 +1,6 @@
1
1
  /**
2
- * Protocol ceiling for one buffered multipart blob part. The API buffers a
3
- * part before uploading it, and the Workers isolate that serves uploads has
4
- * 128 MB of memory, so the ceiling leaves room for the copy the digest check
5
- * makes.
2
+ * Protocol ceiling for a multipart blob part. Bounds client hashing and native
3
+ * HTTP bridge buffers for direct uploads, and API buffers for non-signing stores.
6
4
  */
7
5
  export const MAX_MULTIPART_BLOB_PART_BYTES = 32 * 1024 * 1024;
8
6
  //# sourceMappingURL=blob.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"blob.js","sourceRoot":"","sources":["blob.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC","sourcesContent":["/**\n * Protocol ceiling for one buffered multipart blob part. The API buffers a\n * part before uploading it, and the Workers isolate that serves uploads has\n * 128 MB of memory, so the ceiling leaves room for the copy the digest check\n * makes.\n */\nexport const MAX_MULTIPART_BLOB_PART_BYTES = 32 * 1024 * 1024;\n"]}
1
+ {"version":3,"file":"blob.js","sourceRoot":"","sources":["blob.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC","sourcesContent":["/**\n * Protocol ceiling for a multipart blob part. Bounds client hashing and native\n * HTTP bridge buffers for direct uploads, and API buffers for non-signing stores.\n */\nexport const MAX_MULTIPART_BLOB_PART_BYTES = 32 * 1024 * 1024;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tearleads/client-sdk",
3
- "version": "0.1.32",
3
+ "version": "0.1.33",
4
4
  "description": "React-free Tearleads client runtime: local SQLite persistence, keys, sync, encrypted blobs, and domain workflows.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -5,7 +5,7 @@ export function multipartStagePath(stageId) {
5
5
  export function multipartApiFailureMessage(input) {
6
6
  const failure = input.apiClient.getRequestFailure?.(input.request)?.message;
7
7
  return failure
8
- ? `${input.fallback} Last API failure: ${failure}`
8
+ ? `${input.fallback} Last request failure: ${failure}`
9
9
  : input.fallback;
10
10
  }
11
11
  function provesMultipartStageReplacement(failure) {
@@ -1 +1 @@
1
- {"version":3,"file":"multipartStageFailures.js","sourceRoot":"","sources":["multipartStageFailures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,MAAM,gCAAgC,CAAC;AAUlF,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,OAAO,2BAA2B,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,KAI1C;IACC,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,iBAAiB,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC5E,OAAO,OAAO;QACZ,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,sBAAsB,OAAO,EAAE;QAClD,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;AACrB,CAAC;AAED,SAAS,+BAA+B,CACtC,OAAmC;IAEnC,OAAO,CACL,OAAO,EAAE,IAAI,KAAK,MAAM;QACxB,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,GAAG;YACtB,OAAO,CAAC,IAAI,KAAK,gCAAgC,CAAC,QAAQ,CAAC;YAC3D,CAAC,OAAO,CAAC,MAAM,KAAK,GAAG;gBACrB,OAAO,CAAC,IAAI,KAAK,gCAAgC,CAAC,OAAO,CAAC,CAAC,CAChE,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,+BAA+B,CAAC,KAMrD;IACC,MAAM,OAAO,GAAG;QACd,MAAM,EAAE,KAAc;QACtB,IAAI,EAAE,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC;KACxC,CAAC;IACF,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,iBAAiB,EAAE,CAAC,OAAO,CAAC,CAAC;IAC7D,IAAI,CAAC,+BAA+B,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,0BAA0B,CAAC;YACzB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,QAAQ,EAAE,uDAAuD,KAAK,CAAC,OAAO,GAAG;YACjF,OAAO;SACR,CAAC,CACH,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,kBAAkB,EAAE,CAAC;QAC7B,MAAM,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["import { MULTIPART_BLOB_STAGE_ERROR_CODES } from \"@tearleads/validators/response\";\nimport type { BlobAttachmentApi } from \"../../data/documents/blob/shared/types\";\n\ntype RequestFailureInput = Parameters<\n NonNullable<BlobAttachmentApi[\"getRequestFailure\"]>\n>[0];\ntype RequestFailure = ReturnType<\n NonNullable<BlobAttachmentApi[\"getRequestFailure\"]>\n>;\n\nexport function multipartStagePath(stageId: string): string {\n return `/blobs/stages/multipart/${encodeURIComponent(stageId)}`;\n}\n\nexport function multipartApiFailureMessage(input: {\n readonly apiClient: BlobAttachmentApi;\n readonly fallback: string;\n readonly request: RequestFailureInput;\n}): string {\n const failure = input.apiClient.getRequestFailure?.(input.request)?.message;\n return failure\n ? `${input.fallback} Last API failure: ${failure}`\n : input.fallback;\n}\n\nfunction provesMultipartStageReplacement(\n failure: RequestFailure | undefined,\n): boolean {\n return (\n failure?.kind === \"http\" &&\n ((failure.status === 404 &&\n failure.code === MULTIPART_BLOB_STAGE_ERROR_CODES.notFound) ||\n (failure.status === 409 &&\n failure.code === MULTIPART_BLOB_STAGE_ERROR_CODES.expired))\n );\n}\n\nexport async function assertMultipartStageReplaceable(input: {\n readonly apiClient: BlobAttachmentApi;\n readonly onStageUnavailable?:\n | ((stageId: string) => Promise<void>)\n | undefined;\n readonly stageId: string;\n}): Promise<void> {\n const request = {\n method: \"GET\" as const,\n path: multipartStagePath(input.stageId),\n };\n const failure = input.apiClient.getRequestFailure?.(request);\n if (!provesMultipartStageReplacement(failure)) {\n throw new Error(\n multipartApiFailureMessage({\n apiClient: input.apiClient,\n fallback: `Multipart blob resume stage lookup failed for stage ${input.stageId}.`,\n request,\n }),\n );\n }\n if (input.onStageUnavailable) {\n await input.onStageUnavailable(input.stageId);\n throw new Error(\n \"Multipart stage is unavailable; upload attempt stopped for recovery.\",\n );\n }\n}\n"]}
1
+ {"version":3,"file":"multipartStageFailures.js","sourceRoot":"","sources":["multipartStageFailures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,MAAM,gCAAgC,CAAC;AAUlF,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,OAAO,2BAA2B,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,KAI1C;IACC,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,iBAAiB,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC5E,OAAO,OAAO;QACZ,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,0BAA0B,OAAO,EAAE;QACtD,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;AACrB,CAAC;AAED,SAAS,+BAA+B,CACtC,OAAmC;IAEnC,OAAO,CACL,OAAO,EAAE,IAAI,KAAK,MAAM;QACxB,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,GAAG;YACtB,OAAO,CAAC,IAAI,KAAK,gCAAgC,CAAC,QAAQ,CAAC;YAC3D,CAAC,OAAO,CAAC,MAAM,KAAK,GAAG;gBACrB,OAAO,CAAC,IAAI,KAAK,gCAAgC,CAAC,OAAO,CAAC,CAAC,CAChE,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,+BAA+B,CAAC,KAMrD;IACC,MAAM,OAAO,GAAG;QACd,MAAM,EAAE,KAAc;QACtB,IAAI,EAAE,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC;KACxC,CAAC;IACF,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,iBAAiB,EAAE,CAAC,OAAO,CAAC,CAAC;IAC7D,IAAI,CAAC,+BAA+B,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,0BAA0B,CAAC;YACzB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,QAAQ,EAAE,uDAAuD,KAAK,CAAC,OAAO,GAAG;YACjF,OAAO;SACR,CAAC,CACH,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,kBAAkB,EAAE,CAAC;QAC7B,MAAM,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["import { MULTIPART_BLOB_STAGE_ERROR_CODES } from \"@tearleads/validators/response\";\nimport type { BlobAttachmentApi } from \"../../data/documents/blob/shared/types\";\n\ntype RequestFailureInput = Parameters<\n NonNullable<BlobAttachmentApi[\"getRequestFailure\"]>\n>[0];\ntype RequestFailure = ReturnType<\n NonNullable<BlobAttachmentApi[\"getRequestFailure\"]>\n>;\n\nexport function multipartStagePath(stageId: string): string {\n return `/blobs/stages/multipart/${encodeURIComponent(stageId)}`;\n}\n\nexport function multipartApiFailureMessage(input: {\n readonly apiClient: BlobAttachmentApi;\n readonly fallback: string;\n readonly request: RequestFailureInput;\n}): string {\n const failure = input.apiClient.getRequestFailure?.(input.request)?.message;\n return failure\n ? `${input.fallback} Last request failure: ${failure}`\n : input.fallback;\n}\n\nfunction provesMultipartStageReplacement(\n failure: RequestFailure | undefined,\n): boolean {\n return (\n failure?.kind === \"http\" &&\n ((failure.status === 404 &&\n failure.code === MULTIPART_BLOB_STAGE_ERROR_CODES.notFound) ||\n (failure.status === 409 &&\n failure.code === MULTIPART_BLOB_STAGE_ERROR_CODES.expired))\n );\n}\n\nexport async function assertMultipartStageReplaceable(input: {\n readonly apiClient: BlobAttachmentApi;\n readonly onStageUnavailable?:\n | ((stageId: string) => Promise<void>)\n | undefined;\n readonly stageId: string;\n}): Promise<void> {\n const request = {\n method: \"GET\" as const,\n path: multipartStagePath(input.stageId),\n };\n const failure = input.apiClient.getRequestFailure?.(request);\n if (!provesMultipartStageReplacement(failure)) {\n throw new Error(\n multipartApiFailureMessage({\n apiClient: input.apiClient,\n fallback: `Multipart blob resume stage lookup failed for stage ${input.stageId}.`,\n request,\n }),\n );\n }\n if (input.onStageUnavailable) {\n await input.onStageUnavailable(input.stageId);\n throw new Error(\n \"Multipart stage is unavailable; upload attempt stopped for recovery.\",\n );\n }\n}\n"]}
@@ -1,14 +1,19 @@
1
1
  import { bytesToHex, MAX_BLOB_CHUNK_COUNT } from "../../internal/crypto/index.js";
2
+ import { MAX_MULTIPART_BLOB_PART_BYTES } from "../../internal/validators/util/index.js";
2
3
  import { assertMultipartStageReplaceable, multipartApiFailureMessage, multipartStagePath, } from "./multipartStageFailures.js";
3
4
  const DEFAULT_MULTIPART_UPLOAD_CONCURRENCY = 4;
4
5
  const MAX_MULTIPART_UPLOAD_CONCURRENCY = 4;
5
- const MAX_MULTIPART_PART_BYTES = 5 * 1024 * 1024 * 1024;
6
6
  function pathSegment(value) {
7
7
  return encodeURIComponent(String(value));
8
8
  }
9
- function multipartPartPath(input) {
9
+ function multipartPartRequest(input) {
10
10
  const basePath = `${multipartStagePath(input.stageId)}/parts/${pathSegment(input.partNumber)}`;
11
- return `${basePath}/bytes`;
11
+ const authorization = { method: "POST", path: `${basePath}/upload` };
12
+ // A successful authorization clears its previous failure. If a memory-store
13
+ // byte request then fails, its separate transport diagnostic is authoritative.
14
+ return input.apiClient.getRequestFailure?.(authorization)
15
+ ? authorization
16
+ : { method: "PUT", path: `${basePath}/bytes` };
12
17
  }
13
18
  async function sha256BytesHex(bytes) {
14
19
  return bytesToHex(new Uint8Array(await crypto.subtle.digest("SHA-256", bytes)));
@@ -51,13 +56,11 @@ async function uploadMultipartPartTasks(input) {
51
56
  throw new Error(multipartApiFailureMessage({
52
57
  apiClient: input.apiClient,
53
58
  fallback: `Multipart blob part ${task.partNumber} upload failed for stage ${input.stageId}.`,
54
- request: {
55
- method: "PUT",
56
- path: multipartPartPath({
57
- partNumber: task.partNumber,
58
- stageId: input.stageId,
59
- }),
60
- },
59
+ request: multipartPartRequest({
60
+ apiClient: input.apiClient,
61
+ partNumber: task.partNumber,
62
+ stageId: input.stageId,
63
+ }),
61
64
  }));
62
65
  }
63
66
  input.completeParts[task.partIndex] = {
@@ -199,8 +202,8 @@ function assertMultipartPlanLimits(encryption) {
199
202
  throw new Error(`Multipart blob upload would require ${encryption.partCount.toLocaleString()} parts; the maximum is ${MAX_BLOB_CHUNK_COUNT.toLocaleString()} parts.`);
200
203
  }
201
204
  for (let index = 0; index < encryption.partCount; index += 1) {
202
- if (encryption.getPartByteLength(index) > MAX_MULTIPART_PART_BYTES) {
203
- throw new Error(`Encrypted blob part ${index + 1} exceeds the 5 GiB multipart part limit.`);
205
+ if (encryption.getPartByteLength(index) > MAX_MULTIPART_BLOB_PART_BYTES) {
206
+ throw new Error(`Encrypted blob part ${index + 1} exceeds the 32 MiB multipart part limit.`);
204
207
  }
205
208
  }
206
209
  }
@@ -1 +1 @@
1
- {"version":3,"file":"multipartUpload.js","sourceRoot":"","sources":["multipartUpload.ts"],"names":[],"mappings":"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","sourcesContent":["import { bytesToHex, MAX_BLOB_CHUNK_COUNT } from \"@tearleads/crypto\";\nimport type {\n InitiateMultipartBlobStageResponse,\n MultipartBlobStagePart,\n MultipartBlobStageStatusResponse,\n} from \"@tearleads/validators/response\";\nimport type { BlobEncryptionPlan } from \"../../data/documents/blob/shared/crypto\";\nimport type {\n BlobAttachmentApi,\n MultipartStageResolvedListener,\n MultipartUploadProgressListener,\n UploadDocumentAttachmentInput,\n} from \"../../data/documents/blob/shared/types\";\nimport {\n assertMultipartStageReplaceable,\n multipartApiFailureMessage,\n multipartStagePath,\n} from \"./multipartStageFailures\";\n\nconst DEFAULT_MULTIPART_UPLOAD_CONCURRENCY = 4;\nconst MAX_MULTIPART_UPLOAD_CONCURRENCY = 4;\nconst MAX_MULTIPART_PART_BYTES = 5 * 1024 * 1024 * 1024;\n\ninterface MultipartPartCommit {\n readonly etag: string;\n readonly partNumber: number;\n}\n\ninterface MultipartPartUploadTask {\n readonly byteLength: number;\n readonly partIndex: number;\n readonly partNumber: number;\n}\n\nfunction pathSegment(value: number | string): string {\n return encodeURIComponent(String(value));\n}\n\nfunction multipartPartPath(input: {\n readonly partNumber: number;\n readonly stageId: string;\n}): string {\n const basePath = `${multipartStagePath(input.stageId)}/parts/${pathSegment(input.partNumber)}`;\n return `${basePath}/bytes`;\n}\n\nasync function sha256BytesHex(bytes: Uint8Array<ArrayBuffer>): Promise<string> {\n return bytesToHex(\n new Uint8Array(await crypto.subtle.digest(\"SHA-256\", bytes)),\n );\n}\n\nfunction normalizeMultipartUploadConcurrency(\n value: number | undefined,\n): number {\n if (value === undefined) {\n return DEFAULT_MULTIPART_UPLOAD_CONCURRENCY;\n }\n if (\n !Number.isInteger(value) ||\n value <= 0 ||\n value > MAX_MULTIPART_UPLOAD_CONCURRENCY\n ) {\n throw new Error(\n `Multipart blob upload concurrency must be between 1 and ${MAX_MULTIPART_UPLOAD_CONCURRENCY}`,\n );\n }\n\n return value;\n}\n\nfunction isMultipartPartCommit(\n part: MultipartPartCommit | undefined,\n): part is MultipartPartCommit {\n return part !== undefined;\n}\n\nasync function uploadMultipartPartTasks(input: {\n readonly apiClient: BlobAttachmentApi;\n readonly completeParts: (MultipartPartCommit | undefined)[];\n readonly concurrency: number;\n readonly encryption: BlobEncryptionPlan;\n readonly onPartUploaded?: (task: MultipartPartUploadTask) => void;\n readonly stageId: string;\n readonly tasks: readonly MultipartPartUploadTask[];\n readonly uploadId: string;\n}): Promise<void> {\n let failed = false;\n let firstFailure: { readonly error: unknown } | undefined;\n let nextTaskIndex = 0;\n\n async function worker(): Promise<void> {\n while (!failed) {\n const task = input.tasks[nextTaskIndex];\n nextTaskIndex += 1;\n if (!task) {\n return;\n }\n\n try {\n const uploaded = await uploadMultipartPartBytes({\n apiClient: input.apiClient,\n encryption: input.encryption,\n stageId: input.stageId,\n task,\n uploadId: input.uploadId,\n });\n if (!uploaded) {\n failed = true;\n throw new Error(\n multipartApiFailureMessage({\n apiClient: input.apiClient,\n fallback: `Multipart blob part ${task.partNumber} upload failed for stage ${input.stageId}.`,\n request: {\n method: \"PUT\",\n path: multipartPartPath({\n partNumber: task.partNumber,\n stageId: input.stageId,\n }),\n },\n }),\n );\n }\n\n input.completeParts[task.partIndex] = {\n etag: uploaded.part.etag,\n partNumber: task.partNumber,\n };\n input.onPartUploaded?.(task);\n } catch (error) {\n // Stop sibling workers from pulling new tasks and firing more uploads\n // once any part rejects. Keep this worker alive long enough for the\n // shared join below to drain uploads siblings already started.\n failed = true;\n firstFailure ??= { error };\n return;\n }\n }\n }\n\n const workerCount = Math.min(input.concurrency, input.tasks.length);\n await Promise.all(Array.from({ length: workerCount }, () => worker()));\n if (firstFailure) {\n throw firstFailure.error;\n }\n}\n\nasync function uploadMultipartPartBytes(input: {\n readonly apiClient: BlobAttachmentApi;\n readonly encryption: BlobEncryptionPlan;\n readonly stageId: string;\n readonly task: MultipartPartUploadTask;\n readonly uploadId: string;\n}): ReturnType<BlobAttachmentApi[\"uploadMultipartBlobPartBytes\"]> {\n const encryptedPartBytes = await input.encryption.encryptPart(\n input.task.partIndex,\n );\n if (encryptedPartBytes.byteLength !== input.task.byteLength) {\n throw new Error(\n `Encrypted blob part ${input.task.partNumber} byte length mismatch: expected ${input.task.byteLength.toLocaleString()}, received ${encryptedPartBytes.byteLength.toLocaleString()}.`,\n );\n }\n\n const uploaded = await input.apiClient.uploadMultipartBlobPartBytes(\n input.stageId,\n input.task.partNumber,\n {\n byteLength: encryptedPartBytes.byteLength,\n encryptedBytes: encryptedPartBytes,\n sha256: await sha256BytesHex(encryptedPartBytes),\n uploadId: input.uploadId,\n },\n );\n if (\n uploaded &&\n (uploaded.stageId !== input.stageId ||\n uploaded.uploadId !== input.uploadId ||\n uploaded.part.partNumber !== input.task.partNumber ||\n uploaded.part.byteLength !== input.task.byteLength)\n ) {\n throw new Error(\n `Multipart blob part ${input.task.partNumber} response does not match its request.`,\n );\n }\n return uploaded;\n}\n\nfunction uploadedPartsByPartNumber(\n parts: readonly MultipartBlobStagePart[],\n): ReadonlyMap<number, MultipartBlobStagePart> {\n return new Map(parts.map((part) => [part.partNumber, part]));\n}\n\nfunction isMultipartStageStatus(\n stage: InitiateMultipartBlobStageResponse | MultipartBlobStageStatusResponse,\n): stage is MultipartBlobStageStatusResponse {\n return \"completed\" in stage && typeof stage.completed === \"boolean\";\n}\n\ninterface MultipartUploadProgressState {\n bytesTotal: number;\n bytesUploaded: number;\n partsCompleted: number;\n partsTotal: number;\n}\n\ninterface MultipartPartPlan {\n completeParts: (MultipartPartCommit | undefined)[];\n progress: MultipartUploadProgressState;\n uploadTasks: MultipartPartUploadTask[];\n}\n\n/**\n * Plans encrypted part indices without materializing their bytes, reusing any\n * already-staged parts and seeding cumulative progress for resumed uploads.\n */\nfunction planMultipartParts(input: {\n encryption: BlobEncryptionPlan;\n uploadedParts: ReadonlyMap<number, MultipartBlobStagePart>;\n}): MultipartPartPlan {\n const { encryption, uploadedParts } = input;\n const completeParts: (MultipartPartCommit | undefined)[] = new Array(\n encryption.partCount,\n );\n const uploadTasks: MultipartPartUploadTask[] = [];\n const progress: MultipartUploadProgressState = {\n bytesTotal: 0,\n bytesUploaded: 0,\n partsCompleted: 0,\n partsTotal: encryption.partCount,\n };\n\n for (let partIndex = 0; partIndex < encryption.partCount; partIndex += 1) {\n const partNumber = partIndex + 1;\n const byteLength = encryption.getPartByteLength(partIndex);\n progress.bytesTotal += byteLength;\n const uploadedPart = uploadedParts.get(partNumber);\n if (uploadedPart?.byteLength === byteLength) {\n completeParts[partIndex] = {\n etag: uploadedPart.etag,\n partNumber,\n };\n progress.partsCompleted += 1;\n progress.bytesUploaded += byteLength;\n continue;\n }\n\n uploadTasks.push({\n byteLength,\n partIndex,\n partNumber,\n });\n }\n\n return { completeParts, progress, uploadTasks };\n}\n\nasync function resolveMultipartStageStatus(input: {\n readonly apiClient: BlobAttachmentApi;\n readonly byteLength: number;\n readonly multipart: NonNullable<UploadDocumentAttachmentInput[\"multipart\"]>;\n readonly organizationId: string;\n readonly onStageUnavailable?:\n | ((stageId: string) => Promise<void>)\n | undefined;\n readonly sha256: string;\n}): Promise<MultipartBlobStageStatusResponse> {\n const resumeStageId = input.multipart.resumeStageId;\n if (resumeStageId) {\n const resumed = await input.apiClient.getMultipartBlobStage(resumeStageId);\n if (!resumed) {\n await assertMultipartStageReplaceable({\n apiClient: input.apiClient,\n onStageUnavailable: input.onStageUnavailable,\n stageId: resumeStageId,\n });\n }\n if (resumed && resumed.stageId !== resumeStageId) {\n throw new Error(\n `Multipart blob resume response does not match stage ${resumeStageId}.`,\n );\n }\n if (resumed) {\n // A successful lookup is authoritative: a metadata mismatch indicates\n // inconsistent persisted state or a bad server response, not proof that\n // the existing stage is safe to abandon.\n if (\n resumed.organizationId !== input.organizationId ||\n resumed.byteLength !== input.byteLength ||\n resumed.sha256 !== input.sha256\n ) {\n throw new Error(\n `Multipart blob resume stage ${resumeStageId} does not match the requested organization or bytes.`,\n );\n }\n return resumed;\n }\n }\n\n const stage = await input.apiClient.initiateMultipartBlobStage({\n organizationId: input.organizationId,\n byteLength: input.byteLength,\n sha256: input.sha256,\n });\n if (!stage) {\n throw new Error(\n multipartApiFailureMessage({\n apiClient: input.apiClient,\n fallback: `Multipart blob stage initiation failed for ${input.byteLength.toLocaleString()} bytes.`,\n request: { method: \"POST\", path: \"/blobs/stages/multipart\" },\n }),\n );\n }\n if (\n stage.organizationId !== input.organizationId ||\n stage.byteLength !== input.byteLength ||\n stage.sha256 !== input.sha256\n ) {\n throw new Error(\n \"Multipart blob stage initiation response does not match its request.\",\n );\n }\n\n return isMultipartStageStatus(stage)\n ? stage\n : {\n ...stage,\n completed: false,\n };\n}\n\nfunction assertMultipartPlanLimits(encryption: BlobEncryptionPlan): void {\n if (encryption.partCount > MAX_BLOB_CHUNK_COUNT) {\n throw new Error(\n `Multipart blob upload would require ${encryption.partCount.toLocaleString()} parts; the maximum is ${MAX_BLOB_CHUNK_COUNT.toLocaleString()} parts.`,\n );\n }\n for (let index = 0; index < encryption.partCount; index += 1) {\n if (encryption.getPartByteLength(index) > MAX_MULTIPART_PART_BYTES) {\n throw new Error(\n `Encrypted blob part ${index + 1} exceeds the 5 GiB multipart part limit.`,\n );\n }\n }\n}\n\nexport async function stageMultipartBlobAttachment(input: {\n readonly apiClient: BlobAttachmentApi;\n readonly encryption: BlobEncryptionPlan;\n readonly multipart: NonNullable<UploadDocumentAttachmentInput[\"multipart\"]>;\n readonly organizationId: string;\n readonly onMultipartProgress?: MultipartUploadProgressListener | undefined;\n readonly onStageResolved?: MultipartStageResolvedListener | undefined;\n readonly onStageUnavailable?:\n | ((stageId: string) => Promise<void>)\n | undefined;\n}): Promise<string | null> {\n if (input.multipart.partSize !== input.encryption.chunkSize) {\n throw new Error(\n \"Multipart part size must match the encryption chunk size exactly.\",\n );\n }\n assertMultipartPlanLimits(input.encryption);\n const status = await resolveMultipartStageStatus({\n apiClient: input.apiClient,\n byteLength: input.encryption.byteLength,\n multipart: input.multipart,\n organizationId: input.organizationId,\n onStageUnavailable: input.onStageUnavailable,\n sha256: input.encryption.sha256,\n });\n // Surface the stage id before any parts upload so the caller can persist it;\n // an upload interrupted mid-flight can then resume this same stage.\n await input.onStageResolved?.({\n partSize: input.encryption.chunkSize,\n stageId: status.stageId,\n });\n if (status.completed) {\n input.onMultipartProgress?.({\n bytesTotal: input.encryption.byteLength,\n bytesUploaded: input.encryption.byteLength,\n partsCompleted: input.encryption.partCount,\n partsTotal: input.encryption.partCount,\n });\n return status.stageId;\n }\n\n const { completeParts, progress, uploadTasks } = planMultipartParts({\n encryption: input.encryption,\n uploadedParts: uploadedPartsByPartNumber(status.uploadedParts),\n });\n\n const reportMultipartProgress = () => {\n input.onMultipartProgress?.({\n bytesTotal: progress.bytesTotal,\n bytesUploaded: progress.bytesUploaded,\n partsCompleted: progress.partsCompleted,\n partsTotal: progress.partsTotal,\n });\n };\n reportMultipartProgress();\n\n await uploadMultipartPartTasks({\n apiClient: input.apiClient,\n completeParts,\n concurrency: normalizeMultipartUploadConcurrency(\n input.multipart.uploadConcurrency,\n ),\n encryption: input.encryption,\n onPartUploaded: (task) => {\n progress.partsCompleted += 1;\n progress.bytesUploaded += task.byteLength;\n reportMultipartProgress();\n },\n stageId: status.stageId,\n tasks: uploadTasks,\n uploadId: status.uploadId,\n });\n const committedParts = completeParts.filter(isMultipartPartCommit);\n if (committedParts.length !== input.encryption.partCount) {\n throw new Error(\n `Multipart blob upload incomplete for stage ${status.stageId}: committed ${committedParts.length.toLocaleString()} of ${input.encryption.partCount.toLocaleString()} parts.`,\n );\n }\n\n const completed = await input.apiClient.completeMultipartBlobStage(\n status.stageId,\n {\n parts: committedParts,\n uploadId: status.uploadId,\n },\n );\n if (!completed) {\n throw new Error(\n multipartApiFailureMessage({\n apiClient: input.apiClient,\n fallback: `Multipart blob stage completion failed for stage ${status.stageId} with ${committedParts.length.toLocaleString()} committed parts.`,\n request: {\n method: \"POST\",\n path: `${multipartStagePath(status.stageId)}/complete`,\n },\n }),\n );\n }\n if (\n completed.organizationId !== input.organizationId ||\n completed.stageId !== status.stageId ||\n completed.byteLength !== input.encryption.byteLength ||\n completed.sha256 !== input.encryption.sha256\n ) {\n throw new Error(\n `Multipart blob stage ${status.stageId} completion response does not match its request.`,\n );\n }\n\n return completed.stageId;\n}\n"]}
1
+ {"version":3,"file":"multipartUpload.js","sourceRoot":"","sources":["multipartUpload.ts"],"names":[],"mappings":"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","sourcesContent":["import { bytesToHex, MAX_BLOB_CHUNK_COUNT } from \"@tearleads/crypto\";\nimport type {\n InitiateMultipartBlobStageResponse,\n MultipartBlobStagePart,\n MultipartBlobStageStatusResponse,\n} from \"@tearleads/validators/response\";\nimport { MAX_MULTIPART_BLOB_PART_BYTES } from \"@tearleads/validators/util\";\nimport type { BlobEncryptionPlan } from \"../../data/documents/blob/shared/crypto\";\nimport type {\n BlobAttachmentApi,\n MultipartStageResolvedListener,\n MultipartUploadProgressListener,\n UploadDocumentAttachmentInput,\n} from \"../../data/documents/blob/shared/types\";\nimport {\n assertMultipartStageReplaceable,\n multipartApiFailureMessage,\n multipartStagePath,\n} from \"./multipartStageFailures\";\n\nconst DEFAULT_MULTIPART_UPLOAD_CONCURRENCY = 4;\nconst MAX_MULTIPART_UPLOAD_CONCURRENCY = 4;\n\ninterface MultipartPartCommit {\n readonly etag: string;\n readonly partNumber: number;\n}\n\ninterface MultipartPartUploadTask {\n readonly byteLength: number;\n readonly partIndex: number;\n readonly partNumber: number;\n}\n\nfunction pathSegment(value: number | string): string {\n return encodeURIComponent(String(value));\n}\n\nfunction multipartPartRequest(input: {\n readonly apiClient: BlobAttachmentApi;\n readonly partNumber: number;\n readonly stageId: string;\n}) {\n const basePath = `${multipartStagePath(input.stageId)}/parts/${pathSegment(input.partNumber)}`;\n const authorization = { method: \"POST\" as const, path: `${basePath}/upload` };\n // A successful authorization clears its previous failure. If a memory-store\n // byte request then fails, its separate transport diagnostic is authoritative.\n return input.apiClient.getRequestFailure?.(authorization)\n ? authorization\n : { method: \"PUT\" as const, path: `${basePath}/bytes` };\n}\n\nasync function sha256BytesHex(bytes: Uint8Array<ArrayBuffer>): Promise<string> {\n return bytesToHex(\n new Uint8Array(await crypto.subtle.digest(\"SHA-256\", bytes)),\n );\n}\n\nfunction normalizeMultipartUploadConcurrency(\n value: number | undefined,\n): number {\n if (value === undefined) {\n return DEFAULT_MULTIPART_UPLOAD_CONCURRENCY;\n }\n if (\n !Number.isInteger(value) ||\n value <= 0 ||\n value > MAX_MULTIPART_UPLOAD_CONCURRENCY\n ) {\n throw new Error(\n `Multipart blob upload concurrency must be between 1 and ${MAX_MULTIPART_UPLOAD_CONCURRENCY}`,\n );\n }\n\n return value;\n}\n\nfunction isMultipartPartCommit(\n part: MultipartPartCommit | undefined,\n): part is MultipartPartCommit {\n return part !== undefined;\n}\n\nasync function uploadMultipartPartTasks(input: {\n readonly apiClient: BlobAttachmentApi;\n readonly completeParts: (MultipartPartCommit | undefined)[];\n readonly concurrency: number;\n readonly encryption: BlobEncryptionPlan;\n readonly onPartUploaded?: (task: MultipartPartUploadTask) => void;\n readonly stageId: string;\n readonly tasks: readonly MultipartPartUploadTask[];\n readonly uploadId: string;\n}): Promise<void> {\n let failed = false;\n let firstFailure: { readonly error: unknown } | undefined;\n let nextTaskIndex = 0;\n\n async function worker(): Promise<void> {\n while (!failed) {\n const task = input.tasks[nextTaskIndex];\n nextTaskIndex += 1;\n if (!task) {\n return;\n }\n\n try {\n const uploaded = await uploadMultipartPartBytes({\n apiClient: input.apiClient,\n encryption: input.encryption,\n stageId: input.stageId,\n task,\n uploadId: input.uploadId,\n });\n if (!uploaded) {\n failed = true;\n throw new Error(\n multipartApiFailureMessage({\n apiClient: input.apiClient,\n fallback: `Multipart blob part ${task.partNumber} upload failed for stage ${input.stageId}.`,\n request: multipartPartRequest({\n apiClient: input.apiClient,\n partNumber: task.partNumber,\n stageId: input.stageId,\n }),\n }),\n );\n }\n\n input.completeParts[task.partIndex] = {\n etag: uploaded.part.etag,\n partNumber: task.partNumber,\n };\n input.onPartUploaded?.(task);\n } catch (error) {\n // Stop sibling workers from pulling new tasks and firing more uploads\n // once any part rejects. Keep this worker alive long enough for the\n // shared join below to drain uploads siblings already started.\n failed = true;\n firstFailure ??= { error };\n return;\n }\n }\n }\n\n const workerCount = Math.min(input.concurrency, input.tasks.length);\n await Promise.all(Array.from({ length: workerCount }, () => worker()));\n if (firstFailure) {\n throw firstFailure.error;\n }\n}\n\nasync function uploadMultipartPartBytes(input: {\n readonly apiClient: BlobAttachmentApi;\n readonly encryption: BlobEncryptionPlan;\n readonly stageId: string;\n readonly task: MultipartPartUploadTask;\n readonly uploadId: string;\n}): ReturnType<BlobAttachmentApi[\"uploadMultipartBlobPartBytes\"]> {\n const encryptedPartBytes = await input.encryption.encryptPart(\n input.task.partIndex,\n );\n if (encryptedPartBytes.byteLength !== input.task.byteLength) {\n throw new Error(\n `Encrypted blob part ${input.task.partNumber} byte length mismatch: expected ${input.task.byteLength.toLocaleString()}, received ${encryptedPartBytes.byteLength.toLocaleString()}.`,\n );\n }\n\n const uploaded = await input.apiClient.uploadMultipartBlobPartBytes(\n input.stageId,\n input.task.partNumber,\n {\n byteLength: encryptedPartBytes.byteLength,\n encryptedBytes: encryptedPartBytes,\n sha256: await sha256BytesHex(encryptedPartBytes),\n uploadId: input.uploadId,\n },\n );\n if (\n uploaded &&\n (uploaded.stageId !== input.stageId ||\n uploaded.uploadId !== input.uploadId ||\n uploaded.part.partNumber !== input.task.partNumber ||\n uploaded.part.byteLength !== input.task.byteLength)\n ) {\n throw new Error(\n `Multipart blob part ${input.task.partNumber} response does not match its request.`,\n );\n }\n return uploaded;\n}\n\nfunction uploadedPartsByPartNumber(\n parts: readonly MultipartBlobStagePart[],\n): ReadonlyMap<number, MultipartBlobStagePart> {\n return new Map(parts.map((part) => [part.partNumber, part]));\n}\n\nfunction isMultipartStageStatus(\n stage: InitiateMultipartBlobStageResponse | MultipartBlobStageStatusResponse,\n): stage is MultipartBlobStageStatusResponse {\n return \"completed\" in stage && typeof stage.completed === \"boolean\";\n}\n\ninterface MultipartUploadProgressState {\n bytesTotal: number;\n bytesUploaded: number;\n partsCompleted: number;\n partsTotal: number;\n}\n\ninterface MultipartPartPlan {\n completeParts: (MultipartPartCommit | undefined)[];\n progress: MultipartUploadProgressState;\n uploadTasks: MultipartPartUploadTask[];\n}\n\n/**\n * Plans encrypted part indices without materializing their bytes, reusing any\n * already-staged parts and seeding cumulative progress for resumed uploads.\n */\nfunction planMultipartParts(input: {\n encryption: BlobEncryptionPlan;\n uploadedParts: ReadonlyMap<number, MultipartBlobStagePart>;\n}): MultipartPartPlan {\n const { encryption, uploadedParts } = input;\n const completeParts: (MultipartPartCommit | undefined)[] = new Array(\n encryption.partCount,\n );\n const uploadTasks: MultipartPartUploadTask[] = [];\n const progress: MultipartUploadProgressState = {\n bytesTotal: 0,\n bytesUploaded: 0,\n partsCompleted: 0,\n partsTotal: encryption.partCount,\n };\n\n for (let partIndex = 0; partIndex < encryption.partCount; partIndex += 1) {\n const partNumber = partIndex + 1;\n const byteLength = encryption.getPartByteLength(partIndex);\n progress.bytesTotal += byteLength;\n const uploadedPart = uploadedParts.get(partNumber);\n if (uploadedPart?.byteLength === byteLength) {\n completeParts[partIndex] = {\n etag: uploadedPart.etag,\n partNumber,\n };\n progress.partsCompleted += 1;\n progress.bytesUploaded += byteLength;\n continue;\n }\n\n uploadTasks.push({\n byteLength,\n partIndex,\n partNumber,\n });\n }\n\n return { completeParts, progress, uploadTasks };\n}\n\nasync function resolveMultipartStageStatus(input: {\n readonly apiClient: BlobAttachmentApi;\n readonly byteLength: number;\n readonly multipart: NonNullable<UploadDocumentAttachmentInput[\"multipart\"]>;\n readonly organizationId: string;\n readonly onStageUnavailable?:\n | ((stageId: string) => Promise<void>)\n | undefined;\n readonly sha256: string;\n}): Promise<MultipartBlobStageStatusResponse> {\n const resumeStageId = input.multipart.resumeStageId;\n if (resumeStageId) {\n const resumed = await input.apiClient.getMultipartBlobStage(resumeStageId);\n if (!resumed) {\n await assertMultipartStageReplaceable({\n apiClient: input.apiClient,\n onStageUnavailable: input.onStageUnavailable,\n stageId: resumeStageId,\n });\n }\n if (resumed && resumed.stageId !== resumeStageId) {\n throw new Error(\n `Multipart blob resume response does not match stage ${resumeStageId}.`,\n );\n }\n if (resumed) {\n // A successful lookup is authoritative: a metadata mismatch indicates\n // inconsistent persisted state or a bad server response, not proof that\n // the existing stage is safe to abandon.\n if (\n resumed.organizationId !== input.organizationId ||\n resumed.byteLength !== input.byteLength ||\n resumed.sha256 !== input.sha256\n ) {\n throw new Error(\n `Multipart blob resume stage ${resumeStageId} does not match the requested organization or bytes.`,\n );\n }\n return resumed;\n }\n }\n\n const stage = await input.apiClient.initiateMultipartBlobStage({\n organizationId: input.organizationId,\n byteLength: input.byteLength,\n sha256: input.sha256,\n });\n if (!stage) {\n throw new Error(\n multipartApiFailureMessage({\n apiClient: input.apiClient,\n fallback: `Multipart blob stage initiation failed for ${input.byteLength.toLocaleString()} bytes.`,\n request: { method: \"POST\", path: \"/blobs/stages/multipart\" },\n }),\n );\n }\n if (\n stage.organizationId !== input.organizationId ||\n stage.byteLength !== input.byteLength ||\n stage.sha256 !== input.sha256\n ) {\n throw new Error(\n \"Multipart blob stage initiation response does not match its request.\",\n );\n }\n\n return isMultipartStageStatus(stage)\n ? stage\n : {\n ...stage,\n completed: false,\n };\n}\n\nfunction assertMultipartPlanLimits(encryption: BlobEncryptionPlan): void {\n if (encryption.partCount > MAX_BLOB_CHUNK_COUNT) {\n throw new Error(\n `Multipart blob upload would require ${encryption.partCount.toLocaleString()} parts; the maximum is ${MAX_BLOB_CHUNK_COUNT.toLocaleString()} parts.`,\n );\n }\n for (let index = 0; index < encryption.partCount; index += 1) {\n if (encryption.getPartByteLength(index) > MAX_MULTIPART_BLOB_PART_BYTES) {\n throw new Error(\n `Encrypted blob part ${index + 1} exceeds the 32 MiB multipart part limit.`,\n );\n }\n }\n}\n\nexport async function stageMultipartBlobAttachment(input: {\n readonly apiClient: BlobAttachmentApi;\n readonly encryption: BlobEncryptionPlan;\n readonly multipart: NonNullable<UploadDocumentAttachmentInput[\"multipart\"]>;\n readonly organizationId: string;\n readonly onMultipartProgress?: MultipartUploadProgressListener | undefined;\n readonly onStageResolved?: MultipartStageResolvedListener | undefined;\n readonly onStageUnavailable?:\n | ((stageId: string) => Promise<void>)\n | undefined;\n}): Promise<string | null> {\n if (input.multipart.partSize !== input.encryption.chunkSize) {\n throw new Error(\n \"Multipart part size must match the encryption chunk size exactly.\",\n );\n }\n assertMultipartPlanLimits(input.encryption);\n const status = await resolveMultipartStageStatus({\n apiClient: input.apiClient,\n byteLength: input.encryption.byteLength,\n multipart: input.multipart,\n organizationId: input.organizationId,\n onStageUnavailable: input.onStageUnavailable,\n sha256: input.encryption.sha256,\n });\n // Surface the stage id before any parts upload so the caller can persist it;\n // an upload interrupted mid-flight can then resume this same stage.\n await input.onStageResolved?.({\n partSize: input.encryption.chunkSize,\n stageId: status.stageId,\n });\n if (status.completed) {\n input.onMultipartProgress?.({\n bytesTotal: input.encryption.byteLength,\n bytesUploaded: input.encryption.byteLength,\n partsCompleted: input.encryption.partCount,\n partsTotal: input.encryption.partCount,\n });\n return status.stageId;\n }\n\n const { completeParts, progress, uploadTasks } = planMultipartParts({\n encryption: input.encryption,\n uploadedParts: uploadedPartsByPartNumber(status.uploadedParts),\n });\n\n const reportMultipartProgress = () => {\n input.onMultipartProgress?.({\n bytesTotal: progress.bytesTotal,\n bytesUploaded: progress.bytesUploaded,\n partsCompleted: progress.partsCompleted,\n partsTotal: progress.partsTotal,\n });\n };\n reportMultipartProgress();\n\n await uploadMultipartPartTasks({\n apiClient: input.apiClient,\n completeParts,\n concurrency: normalizeMultipartUploadConcurrency(\n input.multipart.uploadConcurrency,\n ),\n encryption: input.encryption,\n onPartUploaded: (task) => {\n progress.partsCompleted += 1;\n progress.bytesUploaded += task.byteLength;\n reportMultipartProgress();\n },\n stageId: status.stageId,\n tasks: uploadTasks,\n uploadId: status.uploadId,\n });\n const committedParts = completeParts.filter(isMultipartPartCommit);\n if (committedParts.length !== input.encryption.partCount) {\n throw new Error(\n `Multipart blob upload incomplete for stage ${status.stageId}: committed ${committedParts.length.toLocaleString()} of ${input.encryption.partCount.toLocaleString()} parts.`,\n );\n }\n\n const completed = await input.apiClient.completeMultipartBlobStage(\n status.stageId,\n {\n parts: committedParts,\n uploadId: status.uploadId,\n },\n );\n if (!completed) {\n throw new Error(\n multipartApiFailureMessage({\n apiClient: input.apiClient,\n fallback: `Multipart blob stage completion failed for stage ${status.stageId} with ${committedParts.length.toLocaleString()} committed parts.`,\n request: {\n method: \"POST\",\n path: `${multipartStagePath(status.stageId)}/complete`,\n },\n }),\n );\n }\n if (\n completed.organizationId !== input.organizationId ||\n completed.stageId !== status.stageId ||\n completed.byteLength !== input.encryption.byteLength ||\n completed.sha256 !== input.encryption.sha256\n ) {\n throw new Error(\n `Multipart blob stage ${status.stageId} completion response does not match its request.`,\n );\n }\n\n return completed.stageId;\n}\n"]}