@unisource/sdk 0.4.0 → 0.7.0

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.
package/dist/index.d.mts CHANGED
@@ -3,14 +3,30 @@ import { z } from "zod";
3
3
  //#region src/primitives.d.ts
4
4
  declare const nonEmptyString: z.ZodString;
5
5
  declare const positiveInt: z.ZodNumber;
6
+ declare const nonNegativeInt: z.ZodNumber;
6
7
  declare const unixTimestamp: z.ZodNumber;
7
8
  declare const FILES_DEFAULT_LIMIT = 25;
8
9
  declare const FILES_MAX_LIMIT = 100;
10
+ /**
11
+ * Storage backend a file lives on.
12
+ * - 'r2' — Cloudflare R2 via presigned PUT / multipart
13
+ * - 'appwrite' — Appwrite Storage via direct browser SDK upload
14
+ *
15
+ * `recommendedUploadDestinationSchema` adds the meta-value 'hybrid' which is
16
+ * only valid as a service-wide setting (the upload manager picks r2/appwrite
17
+ * per-file based on size).
18
+ */
9
19
  declare const uploadDestinationSchema: z.ZodEnum<{
10
20
  appwrite: "appwrite";
11
21
  r2: "r2";
12
22
  }>;
13
23
  type UploadDestination = z.infer<typeof uploadDestinationSchema>;
24
+ declare const recommendedUploadDestinationSchema: z.ZodEnum<{
25
+ appwrite: "appwrite";
26
+ hybrid: "hybrid";
27
+ r2: "r2";
28
+ }>;
29
+ type RecommendedUploadDestination = z.infer<typeof recommendedUploadDestinationSchema>;
14
30
  declare const uploadStatusSchema: z.ZodEnum<{
15
31
  completed: "completed";
16
32
  failed: "failed";
@@ -333,6 +349,7 @@ declare const fileRestoreResponseSchema: z.ZodObject<{
333
349
  id: z.ZodString;
334
350
  }, z.core.$strip>;
335
351
  type FileRestoreResponse = z.infer<typeof fileRestoreResponseSchema>;
352
+ /** SDK4: filename hard-capped to 255 to match backend Zod validation. */
336
353
  declare const fileUpdateRequestSchema: z.ZodObject<{
337
354
  filename: z.ZodString;
338
355
  }, z.core.$strip>;
@@ -477,6 +494,7 @@ declare const serviceSchema: z.ZodObject<{
477
494
  max_file_size_bytes: z.ZodNumber;
478
495
  recommended_upload_destination: z.ZodOptional<z.ZodEnum<{
479
496
  appwrite: "appwrite";
497
+ hybrid: "hybrid";
480
498
  r2: "r2";
481
499
  }>>;
482
500
  created_at: z.ZodNumber;
@@ -491,6 +509,7 @@ declare const serviceDetailResponseSchema: z.ZodObject<{
491
509
  max_file_size_bytes: z.ZodNumber;
492
510
  recommended_upload_destination: z.ZodOptional<z.ZodEnum<{
493
511
  appwrite: "appwrite";
512
+ hybrid: "hybrid";
494
513
  r2: "r2";
495
514
  }>>;
496
515
  created_at: z.ZodNumber;
@@ -511,6 +530,7 @@ declare const adminServiceUpdateResponseSchema: z.ZodObject<{
511
530
  max_file_size_bytes: z.ZodNumber;
512
531
  recommended_upload_destination: z.ZodOptional<z.ZodEnum<{
513
532
  appwrite: "appwrite";
533
+ hybrid: "hybrid";
514
534
  r2: "r2";
515
535
  }>>;
516
536
  created_at: z.ZodNumber;
@@ -525,6 +545,7 @@ type AdminServiceUpdateResponse = z.infer<typeof adminServiceUpdateResponseSchem
525
545
  declare const adminServiceSettingsRequestSchema: z.ZodObject<{
526
546
  recommended_upload_destination: z.ZodOptional<z.ZodEnum<{
527
547
  appwrite: "appwrite";
548
+ hybrid: "hybrid";
528
549
  r2: "r2";
529
550
  }>>;
530
551
  }, z.core.$strip>;
@@ -538,6 +559,7 @@ declare const adminServiceSettingsResponseSchema: z.ZodObject<{
538
559
  max_file_size_bytes: z.ZodNumber;
539
560
  recommended_upload_destination: z.ZodOptional<z.ZodEnum<{
540
561
  appwrite: "appwrite";
562
+ hybrid: "hybrid";
541
563
  r2: "r2";
542
564
  }>>;
543
565
  created_at: z.ZodNumber;
@@ -873,6 +895,75 @@ declare const releaseUploadFailResponseSchema: z.ZodObject<{
873
895
  status: z.ZodLiteral<"failed">;
874
896
  }, z.core.$strip>;
875
897
  type ReleaseUploadFailResponse = z.infer<typeof releaseUploadFailResponseSchema>;
898
+ declare const releaseMultipartCreateRequestSchema: z.ZodObject<{
899
+ name: z.ZodString;
900
+ filename: z.ZodString;
901
+ mime_type: z.ZodOptional<z.ZodString>;
902
+ tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
903
+ notes: z.ZodOptional<z.ZodNullable<z.ZodString>>;
904
+ force_update: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
905
+ }, z.core.$strip>;
906
+ type ReleaseMultipartCreateRequest = z.input<typeof releaseMultipartCreateRequestSchema>;
907
+ declare const releaseMultipartCreateResponseSchema: z.ZodObject<{
908
+ upload_id: z.ZodString;
909
+ r2_upload_id: z.ZodString;
910
+ key: z.ZodString;
911
+ bucket: z.ZodString;
912
+ expires_at: z.ZodNumber;
913
+ }, z.core.$strip>;
914
+ type ReleaseMultipartCreateResponse = z.infer<typeof releaseMultipartCreateResponseSchema>;
915
+ declare const releaseMultipartSignPartQuerySchema: z.ZodObject<{
916
+ upload_id: z.ZodString;
917
+ part_number: z.ZodCoercedNumber<unknown>;
918
+ }, z.core.$strip>;
919
+ type ReleaseMultipartSignPartQuery = z.input<typeof releaseMultipartSignPartQuerySchema>;
920
+ declare const releaseMultipartSignPartResponseSchema: z.ZodObject<{
921
+ url: z.ZodString;
922
+ expires_at: z.ZodNumber;
923
+ }, z.core.$strip>;
924
+ type ReleaseMultipartSignPartResponse = z.infer<typeof releaseMultipartSignPartResponseSchema>;
925
+ declare const releaseMultipartListPartsQuerySchema: z.ZodObject<{
926
+ upload_id: z.ZodString;
927
+ }, z.core.$strip>;
928
+ type ReleaseMultipartListPartsQuery = z.input<typeof releaseMultipartListPartsQuerySchema>;
929
+ declare const releaseMultipartPartSchema: z.ZodObject<{
930
+ PartNumber: z.ZodNumber;
931
+ ETag: z.ZodString;
932
+ Size: z.ZodNumber;
933
+ }, z.core.$strip>;
934
+ type ReleaseMultipartPart = z.infer<typeof releaseMultipartPartSchema>;
935
+ declare const releaseMultipartListPartsResponseSchema: z.ZodObject<{
936
+ parts: z.ZodArray<z.ZodObject<{
937
+ PartNumber: z.ZodNumber;
938
+ ETag: z.ZodString;
939
+ Size: z.ZodNumber;
940
+ }, z.core.$strip>>;
941
+ }, z.core.$strip>;
942
+ type ReleaseMultipartListPartsResponse = z.infer<typeof releaseMultipartListPartsResponseSchema>;
943
+ declare const releaseMultipartCompleteRequestSchema: z.ZodObject<{
944
+ upload_id: z.ZodString;
945
+ parts: z.ZodArray<z.ZodObject<{
946
+ PartNumber: z.ZodNumber;
947
+ ETag: z.ZodString;
948
+ }, z.core.$strip>>;
949
+ }, z.core.$strip>;
950
+ type ReleaseMultipartCompleteRequest = z.input<typeof releaseMultipartCompleteRequestSchema>;
951
+ declare const releaseMultipartCompleteResponseSchema: z.ZodObject<{
952
+ success: z.ZodLiteral<true>;
953
+ release_id: z.ZodString;
954
+ status: z.ZodLiteral<"completed">;
955
+ }, z.core.$strip>;
956
+ type ReleaseMultipartCompleteResponse = z.infer<typeof releaseMultipartCompleteResponseSchema>;
957
+ declare const releaseMultipartAbortRequestSchema: z.ZodObject<{
958
+ upload_id: z.ZodString;
959
+ }, z.core.$strip>;
960
+ type ReleaseMultipartAbortRequest = z.input<typeof releaseMultipartAbortRequestSchema>;
961
+ declare const releaseMultipartAbortResponseSchema: z.ZodObject<{
962
+ success: z.ZodLiteral<true>;
963
+ release_id: z.ZodString;
964
+ status: z.ZodLiteral<"failed">;
965
+ }, z.core.$strip>;
966
+ type ReleaseMultipartAbortResponse = z.infer<typeof releaseMultipartAbortResponseSchema>;
876
967
  declare const releasesListQuerySchema: z.ZodObject<{
877
968
  limit: z.ZodOptional<z.ZodNumber>;
878
969
  cursor: z.ZodOptional<z.ZodString>;
@@ -956,6 +1047,28 @@ declare const releaseSyncResponseSchema: z.ZodObject<{
956
1047
  }, z.core.$strip>>;
957
1048
  }, z.core.$strip>;
958
1049
  type ReleaseSyncResponse = z.infer<typeof releaseSyncResponseSchema>;
1050
+ /**
1051
+ * Response of `GET /app/releases/latest?channel=...` — used by client apps to
1052
+ * discover the most recent completed release for a given distribution channel
1053
+ * (e.g. `stable`, `beta`). Includes a short-lived presigned download URL.
1054
+ */
1055
+ declare const appReleaseLatestQuerySchema: z.ZodObject<{
1056
+ channel: z.ZodDefault<z.ZodOptional<z.ZodString>>;
1057
+ }, z.core.$strip>;
1058
+ type AppReleaseLatestQuery = z.input<typeof appReleaseLatestQuerySchema>;
1059
+ declare const appReleaseLatestResponseSchema: z.ZodObject<{
1060
+ id: z.ZodString;
1061
+ name: z.ZodString;
1062
+ size: z.ZodNumber;
1063
+ r2_key: z.ZodString;
1064
+ tags: z.ZodArray<z.ZodString>;
1065
+ notes: z.ZodNullable<z.ZodString>;
1066
+ force_update: z.ZodBoolean;
1067
+ created_at: z.ZodString;
1068
+ download_url: z.ZodString;
1069
+ download_url_expires_at: z.ZodNumber;
1070
+ }, z.core.$strip>;
1071
+ type AppReleaseLatestResponse = z.infer<typeof appReleaseLatestResponseSchema>;
959
1072
  //#endregion
960
1073
  //#region src/shareLinks.d.ts
961
1074
  declare const shareLinkSchema: z.ZodObject<{
@@ -1209,7 +1322,14 @@ declare class UnisourceClient {
1209
1322
  upload: {
1210
1323
  /** Initiate a release upload — returns a presigned PUT URL */init: (body: ReleaseUploadInitRequest, signal?: AbortSignal) => Promise<ReleaseUploadInitResponse>; /** Confirm that a release object was successfully uploaded */
1211
1324
  complete: (body: ReleaseUploadCompleteRequest, signal?: AbortSignal) => Promise<ReleaseUploadCompleteResponse>; /** Mark a release upload as failed */
1212
- fail: (releaseId: string, signal?: AbortSignal) => Promise<ReleaseUploadFailResponse>;
1325
+ fail: (releaseId: string, signal?: AbortSignal) => Promise<ReleaseUploadFailResponse>; /** Multipart upload helpers — direct browser → R2 via S3 presigned URLs */
1326
+ multipart: {
1327
+ /** Create a multipart release upload — returns the R2 UploadId + storage key */create: (body: ReleaseMultipartCreateRequest, signal?: AbortSignal) => Promise<ReleaseMultipartCreateResponse>; /** Short-lived presigned PUT URL for a single part */
1328
+ signPart: (uploadId: string, partNumber: number, signal?: AbortSignal) => Promise<ReleaseMultipartSignPartResponse>; /** List parts already uploaded — feeds Golden Retriever's resume logic */
1329
+ listParts: (uploadId: string, signal?: AbortSignal) => Promise<ReleaseMultipartListPartsResponse>; /** Finalize the multipart upload — backend reads object size from R2 (no client size). */
1330
+ complete: (body: ReleaseMultipartCompleteRequest, signal?: AbortSignal) => Promise<ReleaseMultipartCompleteResponse>; /** Abort an in-flight multipart upload and mark the release as failed */
1331
+ abort: (uploadId: string, signal?: AbortSignal) => Promise<ReleaseMultipartAbortResponse>;
1332
+ };
1213
1333
  }; /** List releases for the configured service */
1214
1334
  list: (query?: ReleasesListQuery, signal?: AbortSignal) => Promise<ReleasesListResponse>; /** Get a single release */
1215
1335
  get: (releaseId: string, signal?: AbortSignal) => Promise<ReleaseDTO>; /** Get the latest completed release */
@@ -1224,6 +1344,7 @@ declare class UnisourceClient {
1224
1344
  updateServiceSettings: (body: AdminServiceSettingsRequest, signal?: AbortSignal) => Promise<AdminServiceSettingsResponse>; /** Get real-time storage usage for the service */
1225
1345
  usage: (signal?: AbortSignal) => Promise<ServiceUsageResponse>; /** List all uploads (pending/completed/failed) for this service */
1226
1346
  listUploads: (query?: {
1347
+ destination?: UploadDestination;
1227
1348
  status?: UploadStatus;
1228
1349
  cursor?: string;
1229
1350
  limit?: number;
@@ -1273,6 +1394,16 @@ declare class UnisourceClient {
1273
1394
  get: (id: string, signal?: AbortSignal) => Promise<ShareLinkDetailResponse>; /** Delete a share link */
1274
1395
  delete: (id: string, signal?: AbortSignal) => Promise<ShareLinkDeleteResponse>;
1275
1396
  };
1397
+ readonly app: {
1398
+ releases: {
1399
+ /**
1400
+ * Get the latest completed release for a channel (e.g. `stable`, `beta`).
1401
+ * Backed by `GET /app/releases/latest`. Returns the release metadata plus
1402
+ * a short-lived presigned download URL.
1403
+ */
1404
+ latest: (channel?: string, signal?: AbortSignal) => Promise<AppReleaseLatestResponse>;
1405
+ };
1406
+ };
1276
1407
  }
1277
1408
  //#endregion
1278
- export { type AdminServiceSettingsRequest, type AdminServiceSettingsResponse, type AdminServiceUpdateRequest, type AdminServiceUpdateResponse, type AdminUser, type AdminUserListResponse, type AdminUserPasswordResetRequest, type AdminUserPasswordResetResponse, type AdminUserRoleUpdateRequest, type AdminUserStorageLimitUpdateRequest, type AdminUserUpdateRequest, type AdminUserUpdateResponse, type ApiError, type AuditEvent, type AuditEventAction, type AuditLogListQuery, type AuditLogListResponse, FILES_DEFAULT_LIMIT, FILES_MAX_LIMIT, type FileDeleteResponse, type FileDownloadUrlResponse, type FileMoveRequest, type FileRecord, type FileRecordDetailResponse, type FileRecordsListQuery, type FileRecordsListResponse, type FileRestoreResponse, type FileUpdateRequest, type FileUpdateResponse, type Folder, type FolderCreateRequest, type FolderCreateResponse, type FolderDeleteResponse, type FolderDetailResponse, type FolderListQuery, type FolderListResponse, type FolderRestoreResponse, type FolderUpdateRequest, type FolderUpdateResponse, MainStorageDeleteResponse, MainStorageDetailResponse, MainStorageFile, MainStorageListQuery, MainStorageListResponse, MainStorageRenameRequest, MainStorageRenameResponse, MainStorageRestoreResponse, type MultipartAbortRequest, type MultipartAbortResponse, type MultipartCompleteRequest, type MultipartCompleteResponse, type MultipartCreateRequest, type MultipartCreateResponse, type MultipartListPartsQuery, type MultipartListPartsResponse, type MultipartPart, type MultipartSignPartQuery, type MultipartSignPartResponse, type PublicFileAccessResponse, type PublicFileLockedResponse, type ReleaseDTO, type ReleaseDeleteResponse, type ReleaseSyncManifest, type ReleaseSyncRequest, type ReleaseSyncResponse, type ReleaseSyncResult, type ReleaseUpdateRequest, type ReleaseUploadCompleteRequest, type ReleaseUploadCompleteResponse, type ReleaseUploadFailResponse, type ReleaseUploadInitRequest, type ReleaseUploadInitResponse, type ReleasesListQuery, type ReleasesListResponse, type Service, type ServiceDetailResponse, type ServiceUsageResponse, type ShareLink, type ShareLinkCreateRequest, type ShareLinkCreateResponse, type ShareLinkDeleteResponse, type ShareLinkDetailResponse, type ShareLinkListResponse, type ShareLinkUpdateRequest, type ShareLinkUpdateResponse, type SharesCreateRequest, UnisourceClient, type UnisourceClientConfig, UnisourceError, UnisourceNetworkError, type UploadAppwriteInitRequest, type UploadAppwriteInitResponse, type UploadCompleteResponse, type UploadDestination, type UploadFailResponse, type UploadLifecycleRequest, type UploadR2InitRequest, type UploadR2InitResponse, type UploadRecord, type UploadRecordDetailResponse, type UploadStatus, type UploadType, type UploadsListResponse, adminServiceSettingsRequestSchema, adminServiceSettingsResponseSchema, adminServiceUpdateRequestSchema, adminServiceUpdateResponseSchema, adminUserListResponseSchema, adminUserPasswordResetRequestSchema, adminUserPasswordResetResponseSchema, adminUserRoleUpdateRequestSchema, adminUserSchema, adminUserStorageLimitUpdateRequestSchema, adminUserUpdateRequestSchema, adminUserUpdateResponseSchema, apiErrorSchema, auditEventActionSchema, auditEventSchema, auditLogListQuerySchema, auditLogListResponseSchema, fileDeleteResponseSchema, fileDownloadUrlResponseSchema, fileMoveRequestSchema, fileRecordDetailResponseSchema, fileRecordSchema, fileRecordsListQuerySchema, fileRecordsListResponseSchema, fileRestoreResponseSchema, fileUpdateRequestSchema, fileUpdateResponseSchema, folderCreateRequestSchema, folderCreateResponseSchema, folderDeleteResponseSchema, folderDetailResponseSchema, folderListQuerySchema, folderListResponseSchema, folderRestoreResponseSchema, folderSchema, folderUpdateRequestSchema, folderUpdateResponseSchema, getPublicFileInfo, mainStorageDeleteResponseSchema, mainStorageDetailResponseSchema, mainStorageFileSchema, mainStorageListQuerySchema, mainStorageListResponseSchema, mainStorageRenameRequestSchema, mainStorageRenameResponseSchema, mainStorageRestoreResponseSchema, multipartAbortRequestSchema, multipartAbortResponseSchema, multipartCompleteRequestSchema, multipartCompleteResponseSchema, multipartCreateRequestSchema, multipartCreateResponseSchema, multipartListPartsQuerySchema, multipartListPartsResponseSchema, multipartPartSchema, multipartSignPartQuerySchema, multipartSignPartResponseSchema, nonEmptyString, positiveInt, publicFileAccessResponseSchema, publicFileLockedResponseSchema, releaseDTOSchema, releaseDeleteResponseSchema, releaseSyncManifestSchema, releaseSyncRequestSchema, releaseSyncResponseSchema, releaseSyncResultSchema, releaseUpdateRequestSchema, releaseUploadCompleteRequestSchema, releaseUploadCompleteResponseSchema, releaseUploadFailResponseSchema, releaseUploadInitRequestSchema, releaseUploadInitResponseSchema, releasesListQuerySchema, releasesListResponseSchema, serviceDetailResponseSchema, serviceSchema, serviceUsageResponseSchema, shareLinkCreateRequestSchema, shareLinkCreateResponseSchema, shareLinkDeleteResponseSchema, shareLinkDetailResponseSchema, shareLinkListResponseSchema, shareLinkSchema, shareLinkUpdateRequestSchema, shareLinkUpdateResponseSchema, sharesCreateRequestSchema, unixTimestamp, unlockPublicFile, uploadAppwriteInitRequestSchema, uploadAppwriteInitResponseSchema, uploadCompleteResponseSchema, uploadDestinationSchema, uploadFailResponseSchema, uploadLifecycleRequestSchema, uploadR2InitRequestSchema, uploadR2InitResponseSchema, uploadRecordDetailResponseSchema, uploadRecordSchema, uploadStatusSchema, uploadTypeSchema, uploadsListResponseSchema };
1409
+ export { type AdminServiceSettingsRequest, type AdminServiceSettingsResponse, type AdminServiceUpdateRequest, type AdminServiceUpdateResponse, type AdminUser, type AdminUserListResponse, type AdminUserPasswordResetRequest, type AdminUserPasswordResetResponse, type AdminUserRoleUpdateRequest, type AdminUserStorageLimitUpdateRequest, type AdminUserUpdateRequest, type AdminUserUpdateResponse, type ApiError, type AppReleaseLatestQuery, type AppReleaseLatestResponse, type AuditEvent, type AuditEventAction, type AuditLogListQuery, type AuditLogListResponse, FILES_DEFAULT_LIMIT, FILES_MAX_LIMIT, type FileDeleteResponse, type FileDownloadUrlResponse, type FileMoveRequest, type FileRecord, type FileRecordDetailResponse, type FileRecordsListQuery, type FileRecordsListResponse, type FileRestoreResponse, type FileUpdateRequest, type FileUpdateResponse, type Folder, type FolderCreateRequest, type FolderCreateResponse, type FolderDeleteResponse, type FolderDetailResponse, type FolderListQuery, type FolderListResponse, type FolderRestoreResponse, type FolderUpdateRequest, type FolderUpdateResponse, MainStorageDeleteResponse, MainStorageDetailResponse, MainStorageFile, MainStorageListQuery, MainStorageListResponse, MainStorageRenameRequest, MainStorageRenameResponse, MainStorageRestoreResponse, type MultipartAbortRequest, type MultipartAbortResponse, type MultipartCompleteRequest, type MultipartCompleteResponse, type MultipartCreateRequest, type MultipartCreateResponse, type MultipartListPartsQuery, type MultipartListPartsResponse, type MultipartPart, type MultipartSignPartQuery, type MultipartSignPartResponse, type PublicFileAccessResponse, type PublicFileLockedResponse, type RecommendedUploadDestination, type ReleaseDTO, type ReleaseDeleteResponse, type ReleaseMultipartAbortRequest, type ReleaseMultipartAbortResponse, type ReleaseMultipartCompleteRequest, type ReleaseMultipartCompleteResponse, type ReleaseMultipartCreateRequest, type ReleaseMultipartCreateResponse, type ReleaseMultipartListPartsQuery, type ReleaseMultipartListPartsResponse, type ReleaseMultipartPart, type ReleaseMultipartSignPartQuery, type ReleaseMultipartSignPartResponse, type ReleaseSyncManifest, type ReleaseSyncRequest, type ReleaseSyncResponse, type ReleaseSyncResult, type ReleaseUpdateRequest, type ReleaseUploadCompleteRequest, type ReleaseUploadCompleteResponse, type ReleaseUploadFailResponse, type ReleaseUploadInitRequest, type ReleaseUploadInitResponse, type ReleasesListQuery, type ReleasesListResponse, type Service, type ServiceDetailResponse, type ServiceUsageResponse, type ShareLink, type ShareLinkCreateRequest, type ShareLinkCreateResponse, type ShareLinkDeleteResponse, type ShareLinkDetailResponse, type ShareLinkListResponse, type ShareLinkUpdateRequest, type ShareLinkUpdateResponse, type SharesCreateRequest, UnisourceClient, type UnisourceClientConfig, UnisourceError, UnisourceNetworkError, type UploadAppwriteInitRequest, type UploadAppwriteInitResponse, type UploadCompleteResponse, type UploadDestination, type UploadFailResponse, type UploadLifecycleRequest, type UploadR2InitRequest, type UploadR2InitResponse, type UploadRecord, type UploadRecordDetailResponse, type UploadStatus, type UploadType, type UploadsListResponse, adminServiceSettingsRequestSchema, adminServiceSettingsResponseSchema, adminServiceUpdateRequestSchema, adminServiceUpdateResponseSchema, adminUserListResponseSchema, adminUserPasswordResetRequestSchema, adminUserPasswordResetResponseSchema, adminUserRoleUpdateRequestSchema, adminUserSchema, adminUserStorageLimitUpdateRequestSchema, adminUserUpdateRequestSchema, adminUserUpdateResponseSchema, apiErrorSchema, appReleaseLatestQuerySchema, appReleaseLatestResponseSchema, auditEventActionSchema, auditEventSchema, auditLogListQuerySchema, auditLogListResponseSchema, fileDeleteResponseSchema, fileDownloadUrlResponseSchema, fileMoveRequestSchema, fileRecordDetailResponseSchema, fileRecordSchema, fileRecordsListQuerySchema, fileRecordsListResponseSchema, fileRestoreResponseSchema, fileUpdateRequestSchema, fileUpdateResponseSchema, folderCreateRequestSchema, folderCreateResponseSchema, folderDeleteResponseSchema, folderDetailResponseSchema, folderListQuerySchema, folderListResponseSchema, folderRestoreResponseSchema, folderSchema, folderUpdateRequestSchema, folderUpdateResponseSchema, getPublicFileInfo, mainStorageDeleteResponseSchema, mainStorageDetailResponseSchema, mainStorageFileSchema, mainStorageListQuerySchema, mainStorageListResponseSchema, mainStorageRenameRequestSchema, mainStorageRenameResponseSchema, mainStorageRestoreResponseSchema, multipartAbortRequestSchema, multipartAbortResponseSchema, multipartCompleteRequestSchema, multipartCompleteResponseSchema, multipartCreateRequestSchema, multipartCreateResponseSchema, multipartListPartsQuerySchema, multipartListPartsResponseSchema, multipartPartSchema, multipartSignPartQuerySchema, multipartSignPartResponseSchema, nonEmptyString, nonNegativeInt, positiveInt, publicFileAccessResponseSchema, publicFileLockedResponseSchema, recommendedUploadDestinationSchema, releaseDTOSchema, releaseDeleteResponseSchema, releaseMultipartAbortRequestSchema, releaseMultipartAbortResponseSchema, releaseMultipartCompleteRequestSchema, releaseMultipartCompleteResponseSchema, releaseMultipartCreateRequestSchema, releaseMultipartCreateResponseSchema, releaseMultipartListPartsQuerySchema, releaseMultipartListPartsResponseSchema, releaseMultipartPartSchema, releaseMultipartSignPartQuerySchema, releaseMultipartSignPartResponseSchema, releaseSyncManifestSchema, releaseSyncRequestSchema, releaseSyncResponseSchema, releaseSyncResultSchema, releaseUpdateRequestSchema, releaseUploadCompleteRequestSchema, releaseUploadCompleteResponseSchema, releaseUploadFailResponseSchema, releaseUploadInitRequestSchema, releaseUploadInitResponseSchema, releasesListQuerySchema, releasesListResponseSchema, serviceDetailResponseSchema, serviceSchema, serviceUsageResponseSchema, shareLinkCreateRequestSchema, shareLinkCreateResponseSchema, shareLinkDeleteResponseSchema, shareLinkDetailResponseSchema, shareLinkListResponseSchema, shareLinkSchema, shareLinkUpdateRequestSchema, shareLinkUpdateResponseSchema, sharesCreateRequestSchema, unixTimestamp, unlockPublicFile, uploadAppwriteInitRequestSchema, uploadAppwriteInitResponseSchema, uploadCompleteResponseSchema, uploadDestinationSchema, uploadFailResponseSchema, uploadLifecycleRequestSchema, uploadR2InitRequestSchema, uploadR2InitResponseSchema, uploadRecordDetailResponseSchema, uploadRecordSchema, uploadStatusSchema, uploadTypeSchema, uploadsListResponseSchema };
package/dist/index.mjs CHANGED
@@ -2,10 +2,25 @@ import { z } from "zod";
2
2
  //#region src/primitives.ts
3
3
  const nonEmptyString = z.string().trim().min(1);
4
4
  const positiveInt = z.number().int().positive();
5
+ const nonNegativeInt = z.number().int().nonnegative();
5
6
  const unixTimestamp = z.number().int().nonnegative();
6
7
  const FILES_DEFAULT_LIMIT = 25;
7
8
  const FILES_MAX_LIMIT = 100;
9
+ /**
10
+ * Storage backend a file lives on.
11
+ * - 'r2' — Cloudflare R2 via presigned PUT / multipart
12
+ * - 'appwrite' — Appwrite Storage via direct browser SDK upload
13
+ *
14
+ * `recommendedUploadDestinationSchema` adds the meta-value 'hybrid' which is
15
+ * only valid as a service-wide setting (the upload manager picks r2/appwrite
16
+ * per-file based on size).
17
+ */
8
18
  const uploadDestinationSchema = z.enum(["r2", "appwrite"]);
19
+ const recommendedUploadDestinationSchema = z.enum([
20
+ "r2",
21
+ "appwrite",
22
+ "hybrid"
23
+ ]);
9
24
  const uploadStatusSchema = z.enum([
10
25
  "pending",
11
26
  "completed",
@@ -137,7 +152,7 @@ const fileRecordSchema = z.object({
137
152
  folder_id: nonEmptyString.nullable(),
138
153
  upload_id: nonEmptyString.nullable(),
139
154
  filename: nonEmptyString,
140
- size: positiveInt,
155
+ size: nonNegativeInt,
141
156
  mime_type: nonEmptyString,
142
157
  storage_destination: uploadDestinationSchema,
143
158
  is_trashed: z.boolean(),
@@ -173,7 +188,8 @@ const fileRestoreResponseSchema = z.object({
173
188
  success: z.literal(true),
174
189
  id: nonEmptyString
175
190
  });
176
- const fileUpdateRequestSchema = z.object({ filename: nonEmptyString });
191
+ /** SDK4: filename hard-capped to 255 to match backend Zod validation. */
192
+ const fileUpdateRequestSchema = z.object({ filename: z.string().trim().min(1).max(255) });
177
193
  const fileUpdateResponseSchema = z.object({ file: fileRecordSchema });
178
194
  //#endregion
179
195
  //#region src/folders.ts
@@ -232,7 +248,7 @@ const serviceSchema = z.object({
232
248
  max_storage_bytes: positiveInt,
233
249
  current_used_bytes: z.number().int().nonnegative(),
234
250
  max_file_size_bytes: positiveInt,
235
- recommended_upload_destination: uploadDestinationSchema.optional(),
251
+ recommended_upload_destination: recommendedUploadDestinationSchema.optional(),
236
252
  created_at: unixTimestamp
237
253
  });
238
254
  const serviceDetailResponseSchema = z.object({ service: serviceSchema });
@@ -246,7 +262,7 @@ const adminServiceUpdateResponseSchema = serviceDetailResponseSchema;
246
262
  * can flip the recommended default upload destination per service without
247
263
  * disturbing quota-related fields.
248
264
  */
249
- const adminServiceSettingsRequestSchema = z.object({ recommended_upload_destination: uploadDestinationSchema.optional() }).refine((v) => v.recommended_upload_destination !== void 0, { message: "At least one setting must be provided" });
265
+ const adminServiceSettingsRequestSchema = z.object({ recommended_upload_destination: recommendedUploadDestinationSchema.optional() }).refine((v) => v.recommended_upload_destination !== void 0, { message: "At least one setting must be provided" });
250
266
  const adminServiceSettingsResponseSchema = serviceDetailResponseSchema;
251
267
  const serviceUsageResponseSchema = z.object({
252
268
  service_id: nonEmptyString,
@@ -409,6 +425,46 @@ const releaseUploadFailResponseSchema = z.object({
409
425
  release_id: nonEmptyString,
410
426
  status: z.literal("failed")
411
427
  });
428
+ const releaseMultipartCreateRequestSchema = z.object({
429
+ name: releaseNameSchema,
430
+ filename: releaseFilenameSchema,
431
+ mime_type: nonEmptyString.optional(),
432
+ tags: releaseTagsSchema.optional().default([]),
433
+ notes: releaseNotesSchema,
434
+ force_update: z.boolean().optional().default(false)
435
+ });
436
+ const releaseMultipartCreateResponseSchema = z.object({
437
+ upload_id: nonEmptyString,
438
+ r2_upload_id: nonEmptyString,
439
+ key: nonEmptyString,
440
+ bucket: nonEmptyString,
441
+ expires_at: positiveInt
442
+ });
443
+ const releaseMultipartSignPartQuerySchema = z.object({
444
+ upload_id: releaseIdSchema,
445
+ part_number: z.coerce.number().int().min(1).max(1e4)
446
+ });
447
+ const releaseMultipartSignPartResponseSchema = z.object({
448
+ url: z.string().url(),
449
+ expires_at: positiveInt
450
+ });
451
+ const releaseMultipartListPartsQuerySchema = z.object({ upload_id: releaseIdSchema });
452
+ const releaseMultipartPartSchema = z.object({
453
+ PartNumber: z.number().int().min(1).max(1e4),
454
+ ETag: nonEmptyString,
455
+ Size: z.number().int().nonnegative()
456
+ });
457
+ const releaseMultipartListPartsResponseSchema = z.object({ parts: z.array(releaseMultipartPartSchema) });
458
+ const releaseMultipartCompleteRequestSchema = z.object({
459
+ upload_id: releaseIdSchema,
460
+ parts: z.array(z.object({
461
+ PartNumber: z.number().int().min(1).max(1e4),
462
+ ETag: nonEmptyString
463
+ })).min(1)
464
+ });
465
+ const releaseMultipartCompleteResponseSchema = releaseUploadCompleteResponseSchema;
466
+ const releaseMultipartAbortRequestSchema = z.object({ upload_id: releaseIdSchema });
467
+ const releaseMultipartAbortResponseSchema = releaseUploadFailResponseSchema;
412
468
  const releasesListQuerySchema = z.object({
413
469
  limit: z.number().int().positive().max(100).optional(),
414
470
  cursor: nonEmptyString.optional()
@@ -446,6 +502,24 @@ const releaseSyncResponseSchema = z.object({
446
502
  synced: z.number().int().nonnegative(),
447
503
  results: z.array(releaseSyncResultSchema)
448
504
  });
505
+ /**
506
+ * Response of `GET /app/releases/latest?channel=...` — used by client apps to
507
+ * discover the most recent completed release for a given distribution channel
508
+ * (e.g. `stable`, `beta`). Includes a short-lived presigned download URL.
509
+ */
510
+ const appReleaseLatestQuerySchema = z.object({ channel: nonEmptyString.optional().default("stable") });
511
+ const appReleaseLatestResponseSchema = z.object({
512
+ id: nonEmptyString,
513
+ name: nonEmptyString,
514
+ size: z.number().int().nonnegative(),
515
+ r2_key: nonEmptyString,
516
+ tags: z.array(nonEmptyString),
517
+ notes: z.string().nullable(),
518
+ force_update: z.boolean(),
519
+ created_at: nonEmptyString,
520
+ download_url: z.string().url(),
521
+ download_url_expires_at: positiveInt
522
+ });
449
523
  //#endregion
450
524
  //#region src/shareLinks.ts
451
525
  const shareLinkSchema = z.object({
@@ -738,7 +812,32 @@ var UnisourceClient = class {
738
812
  fail: (releaseId, signal) => apiRequest(this.config, "POST", "/releases/upload/fail", {
739
813
  body: { release_id: releaseId },
740
814
  signal
741
- })
815
+ }),
816
+ multipart: {
817
+ create: (body, signal) => apiRequest(this.config, "POST", "/releases/upload/multipart/create", {
818
+ body,
819
+ signal
820
+ }),
821
+ signPart: (uploadId, partNumber, signal) => apiRequest(this.config, "GET", "/releases/upload/multipart/sign-part", {
822
+ query: {
823
+ upload_id: uploadId,
824
+ part_number: partNumber
825
+ },
826
+ signal
827
+ }),
828
+ listParts: (uploadId, signal) => apiRequest(this.config, "GET", "/releases/upload/multipart/list-parts", {
829
+ query: { upload_id: uploadId },
830
+ signal
831
+ }),
832
+ complete: (body, signal) => apiRequest(this.config, "POST", "/releases/upload/multipart/complete", {
833
+ body,
834
+ signal
835
+ }),
836
+ abort: (uploadId, signal) => apiRequest(this.config, "DELETE", "/releases/upload/multipart/abort", {
837
+ body: { upload_id: uploadId },
838
+ signal
839
+ })
840
+ }
742
841
  },
743
842
  list: (query, signal) => apiRequest(this.config, "GET", "/releases", {
744
843
  query,
@@ -844,6 +943,10 @@ var UnisourceClient = class {
844
943
  get: (id, signal) => apiRequest(this.config, "GET", `/shares/${id}`, { signal }),
845
944
  delete: (id, signal) => apiRequest(this.config, "DELETE", `/shares/${id}`, { signal })
846
945
  };
946
+ app = { releases: { latest: (channel = "stable", signal) => apiRequest(this.config, "GET", "/app/releases/latest", {
947
+ query: { channel },
948
+ signal
949
+ }) } };
847
950
  };
848
951
  //#endregion
849
- export { FILES_DEFAULT_LIMIT, FILES_MAX_LIMIT, UnisourceClient, UnisourceError, UnisourceNetworkError, adminServiceSettingsRequestSchema, adminServiceSettingsResponseSchema, adminServiceUpdateRequestSchema, adminServiceUpdateResponseSchema, adminUserListResponseSchema, adminUserPasswordResetRequestSchema, adminUserPasswordResetResponseSchema, adminUserRoleUpdateRequestSchema, adminUserSchema, adminUserStorageLimitUpdateRequestSchema, adminUserUpdateRequestSchema, adminUserUpdateResponseSchema, apiErrorSchema, auditEventActionSchema, auditEventSchema, auditLogListQuerySchema, auditLogListResponseSchema, fileDeleteResponseSchema, fileDownloadUrlResponseSchema, fileMoveRequestSchema, fileRecordDetailResponseSchema, fileRecordSchema, fileRecordsListQuerySchema, fileRecordsListResponseSchema, fileRestoreResponseSchema, fileUpdateRequestSchema, fileUpdateResponseSchema, folderCreateRequestSchema, folderCreateResponseSchema, folderDeleteResponseSchema, folderDetailResponseSchema, folderListQuerySchema, folderListResponseSchema, folderRestoreResponseSchema, folderSchema, folderUpdateRequestSchema, folderUpdateResponseSchema, getPublicFileInfo, mainStorageDeleteResponseSchema, mainStorageDetailResponseSchema, mainStorageFileSchema, mainStorageListQuerySchema, mainStorageListResponseSchema, mainStorageRenameRequestSchema, mainStorageRenameResponseSchema, mainStorageRestoreResponseSchema, multipartAbortRequestSchema, multipartAbortResponseSchema, multipartCompleteRequestSchema, multipartCompleteResponseSchema, multipartCreateRequestSchema, multipartCreateResponseSchema, multipartListPartsQuerySchema, multipartListPartsResponseSchema, multipartPartSchema, multipartSignPartQuerySchema, multipartSignPartResponseSchema, nonEmptyString, positiveInt, publicFileAccessResponseSchema, publicFileLockedResponseSchema, releaseDTOSchema, releaseDeleteResponseSchema, releaseSyncManifestSchema, releaseSyncRequestSchema, releaseSyncResponseSchema, releaseSyncResultSchema, releaseUpdateRequestSchema, releaseUploadCompleteRequestSchema, releaseUploadCompleteResponseSchema, releaseUploadFailResponseSchema, releaseUploadInitRequestSchema, releaseUploadInitResponseSchema, releasesListQuerySchema, releasesListResponseSchema, serviceDetailResponseSchema, serviceSchema, serviceUsageResponseSchema, shareLinkCreateRequestSchema, shareLinkCreateResponseSchema, shareLinkDeleteResponseSchema, shareLinkDetailResponseSchema, shareLinkListResponseSchema, shareLinkSchema, shareLinkUpdateRequestSchema, shareLinkUpdateResponseSchema, sharesCreateRequestSchema, unixTimestamp, unlockPublicFile, uploadAppwriteInitRequestSchema, uploadAppwriteInitResponseSchema, uploadCompleteResponseSchema, uploadDestinationSchema, uploadFailResponseSchema, uploadLifecycleRequestSchema, uploadR2InitRequestSchema, uploadR2InitResponseSchema, uploadRecordDetailResponseSchema, uploadRecordSchema, uploadStatusSchema, uploadTypeSchema, uploadsListResponseSchema };
952
+ export { FILES_DEFAULT_LIMIT, FILES_MAX_LIMIT, UnisourceClient, UnisourceError, UnisourceNetworkError, adminServiceSettingsRequestSchema, adminServiceSettingsResponseSchema, adminServiceUpdateRequestSchema, adminServiceUpdateResponseSchema, adminUserListResponseSchema, adminUserPasswordResetRequestSchema, adminUserPasswordResetResponseSchema, adminUserRoleUpdateRequestSchema, adminUserSchema, adminUserStorageLimitUpdateRequestSchema, adminUserUpdateRequestSchema, adminUserUpdateResponseSchema, apiErrorSchema, appReleaseLatestQuerySchema, appReleaseLatestResponseSchema, auditEventActionSchema, auditEventSchema, auditLogListQuerySchema, auditLogListResponseSchema, fileDeleteResponseSchema, fileDownloadUrlResponseSchema, fileMoveRequestSchema, fileRecordDetailResponseSchema, fileRecordSchema, fileRecordsListQuerySchema, fileRecordsListResponseSchema, fileRestoreResponseSchema, fileUpdateRequestSchema, fileUpdateResponseSchema, folderCreateRequestSchema, folderCreateResponseSchema, folderDeleteResponseSchema, folderDetailResponseSchema, folderListQuerySchema, folderListResponseSchema, folderRestoreResponseSchema, folderSchema, folderUpdateRequestSchema, folderUpdateResponseSchema, getPublicFileInfo, mainStorageDeleteResponseSchema, mainStorageDetailResponseSchema, mainStorageFileSchema, mainStorageListQuerySchema, mainStorageListResponseSchema, mainStorageRenameRequestSchema, mainStorageRenameResponseSchema, mainStorageRestoreResponseSchema, multipartAbortRequestSchema, multipartAbortResponseSchema, multipartCompleteRequestSchema, multipartCompleteResponseSchema, multipartCreateRequestSchema, multipartCreateResponseSchema, multipartListPartsQuerySchema, multipartListPartsResponseSchema, multipartPartSchema, multipartSignPartQuerySchema, multipartSignPartResponseSchema, nonEmptyString, nonNegativeInt, positiveInt, publicFileAccessResponseSchema, publicFileLockedResponseSchema, recommendedUploadDestinationSchema, releaseDTOSchema, releaseDeleteResponseSchema, releaseMultipartAbortRequestSchema, releaseMultipartAbortResponseSchema, releaseMultipartCompleteRequestSchema, releaseMultipartCompleteResponseSchema, releaseMultipartCreateRequestSchema, releaseMultipartCreateResponseSchema, releaseMultipartListPartsQuerySchema, releaseMultipartListPartsResponseSchema, releaseMultipartPartSchema, releaseMultipartSignPartQuerySchema, releaseMultipartSignPartResponseSchema, releaseSyncManifestSchema, releaseSyncRequestSchema, releaseSyncResponseSchema, releaseSyncResultSchema, releaseUpdateRequestSchema, releaseUploadCompleteRequestSchema, releaseUploadCompleteResponseSchema, releaseUploadFailResponseSchema, releaseUploadInitRequestSchema, releaseUploadInitResponseSchema, releasesListQuerySchema, releasesListResponseSchema, serviceDetailResponseSchema, serviceSchema, serviceUsageResponseSchema, shareLinkCreateRequestSchema, shareLinkCreateResponseSchema, shareLinkDeleteResponseSchema, shareLinkDetailResponseSchema, shareLinkListResponseSchema, shareLinkSchema, shareLinkUpdateRequestSchema, shareLinkUpdateResponseSchema, sharesCreateRequestSchema, unixTimestamp, unlockPublicFile, uploadAppwriteInitRequestSchema, uploadAppwriteInitResponseSchema, uploadCompleteResponseSchema, uploadDestinationSchema, uploadFailResponseSchema, uploadLifecycleRequestSchema, uploadR2InitRequestSchema, uploadR2InitResponseSchema, uploadRecordDetailResponseSchema, uploadRecordSchema, uploadStatusSchema, uploadTypeSchema, uploadsListResponseSchema };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@unisource/sdk",
3
3
  "private": false,
4
4
  "type": "module",
5
- "version": "0.4.0",
5
+ "version": "0.7.0",
6
6
  "description": "Wspolne kontrakty danych dla backendu i frontendu UniSource.",
7
7
  "license": "MIT",
8
8
  "publishConfig": {
package/src/client.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ApiError, UploadStatus } from './primitives';
1
+ import type { ApiError, UploadDestination, UploadStatus } from './primitives';
2
2
  import type {
3
3
  UploadR2InitRequest,
4
4
  UploadR2InitResponse,
@@ -90,6 +90,14 @@ import type {
90
90
  ReleaseDeleteResponse,
91
91
  ReleaseSyncRequest,
92
92
  ReleaseSyncResponse,
93
+ ReleaseMultipartCreateRequest,
94
+ ReleaseMultipartCreateResponse,
95
+ ReleaseMultipartSignPartResponse,
96
+ ReleaseMultipartListPartsResponse,
97
+ ReleaseMultipartCompleteRequest,
98
+ ReleaseMultipartCompleteResponse,
99
+ ReleaseMultipartAbortResponse,
100
+ AppReleaseLatestResponse,
93
101
  } from './releases';
94
102
 
95
103
  // ─── SDK Error classes ────────────────────────────────────────────────────────
@@ -412,6 +420,38 @@ export class UnisourceClient {
412
420
  /** Mark a release upload as failed */
413
421
  fail: (releaseId: string, signal?: AbortSignal): Promise<ReleaseUploadFailResponse> =>
414
422
  apiRequest(this.config, 'POST', '/releases/upload/fail', { body: { release_id: releaseId }, signal }),
423
+
424
+ /** Multipart upload helpers — direct browser → R2 via S3 presigned URLs */
425
+ multipart: {
426
+ /** Create a multipart release upload — returns the R2 UploadId + storage key */
427
+ create: (body: ReleaseMultipartCreateRequest, signal?: AbortSignal): Promise<ReleaseMultipartCreateResponse> =>
428
+ apiRequest(this.config, 'POST', '/releases/upload/multipart/create', { body, signal }),
429
+
430
+ /** Short-lived presigned PUT URL for a single part */
431
+ signPart: (uploadId: string, partNumber: number, signal?: AbortSignal): Promise<ReleaseMultipartSignPartResponse> =>
432
+ apiRequest(this.config, 'GET', '/releases/upload/multipart/sign-part', {
433
+ query: { upload_id: uploadId, part_number: partNumber },
434
+ signal,
435
+ }),
436
+
437
+ /** List parts already uploaded — feeds Golden Retriever's resume logic */
438
+ listParts: (uploadId: string, signal?: AbortSignal): Promise<ReleaseMultipartListPartsResponse> =>
439
+ apiRequest(this.config, 'GET', '/releases/upload/multipart/list-parts', {
440
+ query: { upload_id: uploadId },
441
+ signal,
442
+ }),
443
+
444
+ /** Finalize the multipart upload — backend reads object size from R2 (no client size). */
445
+ complete: (body: ReleaseMultipartCompleteRequest, signal?: AbortSignal): Promise<ReleaseMultipartCompleteResponse> =>
446
+ apiRequest(this.config, 'POST', '/releases/upload/multipart/complete', { body, signal }),
447
+
448
+ /** Abort an in-flight multipart upload and mark the release as failed */
449
+ abort: (uploadId: string, signal?: AbortSignal): Promise<ReleaseMultipartAbortResponse> =>
450
+ apiRequest(this.config, 'DELETE', '/releases/upload/multipart/abort', {
451
+ body: { upload_id: uploadId },
452
+ signal,
453
+ }),
454
+ },
415
455
  },
416
456
 
417
457
  /** List releases for the configured service */
@@ -462,7 +502,10 @@ export class UnisourceClient {
462
502
  apiRequest(this.config, 'GET', '/admin/service/usage', { signal }),
463
503
 
464
504
  /** List all uploads (pending/completed/failed) for this service */
465
- listUploads: (query?: { status?: UploadStatus; cursor?: string; limit?: number }, signal?: AbortSignal): Promise<UploadsListResponse> =>
505
+ listUploads: (
506
+ query?: { destination?: UploadDestination; status?: UploadStatus; cursor?: string; limit?: number },
507
+ signal?: AbortSignal
508
+ ): Promise<UploadsListResponse> =>
466
509
  apiRequest(this.config, 'GET', '/admin/files', { query, signal }),
467
510
 
468
511
  /** Get a single upload for this service */
@@ -583,4 +626,21 @@ export class UnisourceClient {
583
626
  delete: (id: string, signal?: AbortSignal): Promise<ShareLinkDeleteResponse> =>
584
627
  apiRequest(this.config, 'DELETE', `/shares/${id}`, { signal }),
585
628
  };
629
+
630
+ // ─── App-facing endpoints (/app/*) — public release distribution ──────────────
631
+
632
+ readonly app = {
633
+ releases: {
634
+ /**
635
+ * Get the latest completed release for a channel (e.g. `stable`, `beta`).
636
+ * Backed by `GET /app/releases/latest`. Returns the release metadata plus
637
+ * a short-lived presigned download URL.
638
+ */
639
+ latest: (
640
+ channel: string = 'stable',
641
+ signal?: AbortSignal
642
+ ): Promise<AppReleaseLatestResponse> =>
643
+ apiRequest(this.config, 'GET', '/app/releases/latest', { query: { channel }, signal }),
644
+ },
645
+ };
586
646
  }
@@ -1,5 +1,12 @@
1
1
  import { z } from 'zod';
2
- import { nonEmptyString, positiveInt, uploadDestinationSchema, FILES_DEFAULT_LIMIT, FILES_MAX_LIMIT } from './primitives';
2
+ import {
3
+ nonEmptyString,
4
+ nonNegativeInt,
5
+ positiveInt,
6
+ uploadDestinationSchema,
7
+ FILES_DEFAULT_LIMIT,
8
+ FILES_MAX_LIMIT,
9
+ } from './primitives';
3
10
 
4
11
  // ─── User-facing file record ──────────────────────────────────────────────────
5
12
 
@@ -14,7 +21,8 @@ export const fileRecordSchema = z.object({
14
21
  folder_id: nonEmptyString.nullable(),
15
22
  upload_id: nonEmptyString.nullable(),
16
23
  filename: nonEmptyString,
17
- size: positiveInt,
24
+ /** SDK6: zero-byte uploads are valid (e.g. placeholders). */
25
+ size: nonNegativeInt,
18
26
  mime_type: nonEmptyString,
19
27
  storage_destination: uploadDestinationSchema,
20
28
  is_trashed: z.boolean(),
@@ -88,8 +96,9 @@ export type FileRestoreResponse = z.infer<typeof fileRestoreResponseSchema>;
88
96
 
89
97
  // ─── Update (rename) ──────────────────────────────────────────────────────────
90
98
 
99
+ /** SDK4: filename hard-capped to 255 to match backend Zod validation. */
91
100
  export const fileUpdateRequestSchema = z.object({
92
- filename: nonEmptyString,
101
+ filename: z.string().trim().min(1).max(255),
93
102
  });
94
103
  export type FileUpdateRequest = z.infer<typeof fileUpdateRequestSchema>;
95
104
 
package/src/index.ts CHANGED
@@ -2,14 +2,21 @@
2
2
  export {
3
3
  nonEmptyString,
4
4
  positiveInt,
5
+ nonNegativeInt,
5
6
  unixTimestamp,
6
7
  uploadDestinationSchema,
8
+ recommendedUploadDestinationSchema,
7
9
  uploadStatusSchema,
8
10
  apiErrorSchema,
9
11
  FILES_DEFAULT_LIMIT,
10
12
  FILES_MAX_LIMIT,
11
13
  } from './primitives';
12
- export type { UploadDestination, UploadStatus, ApiError } from './primitives';
14
+ export type {
15
+ UploadDestination,
16
+ RecommendedUploadDestination,
17
+ UploadStatus,
18
+ ApiError,
19
+ } from './primitives';
13
20
 
14
21
 
15
22
  // ─── Upload ───────────────────────────────────────────────────────────────────
@@ -177,6 +184,19 @@ export {
177
184
  releaseSyncRequestSchema,
178
185
  releaseSyncResultSchema,
179
186
  releaseSyncResponseSchema,
187
+ releaseMultipartCreateRequestSchema,
188
+ releaseMultipartCreateResponseSchema,
189
+ releaseMultipartSignPartQuerySchema,
190
+ releaseMultipartSignPartResponseSchema,
191
+ releaseMultipartListPartsQuerySchema,
192
+ releaseMultipartListPartsResponseSchema,
193
+ releaseMultipartPartSchema,
194
+ releaseMultipartCompleteRequestSchema,
195
+ releaseMultipartCompleteResponseSchema,
196
+ releaseMultipartAbortRequestSchema,
197
+ releaseMultipartAbortResponseSchema,
198
+ appReleaseLatestQuerySchema,
199
+ appReleaseLatestResponseSchema,
180
200
  } from './releases';
181
201
  export type {
182
202
  ReleaseDTO,
@@ -193,6 +213,19 @@ export type {
193
213
  ReleaseSyncRequest,
194
214
  ReleaseSyncResult,
195
215
  ReleaseSyncResponse,
216
+ ReleaseMultipartCreateRequest,
217
+ ReleaseMultipartCreateResponse,
218
+ ReleaseMultipartSignPartQuery,
219
+ ReleaseMultipartSignPartResponse,
220
+ ReleaseMultipartListPartsQuery,
221
+ ReleaseMultipartListPartsResponse,
222
+ ReleaseMultipartPart,
223
+ ReleaseMultipartCompleteRequest,
224
+ ReleaseMultipartCompleteResponse,
225
+ ReleaseMultipartAbortRequest,
226
+ ReleaseMultipartAbortResponse,
227
+ AppReleaseLatestQuery,
228
+ AppReleaseLatestResponse,
196
229
  } from './releases';
197
230
 
198
231
  // ─── Share Links ─────────────────────────────────────────────────────────────
package/src/primitives.ts CHANGED
@@ -4,6 +4,7 @@ import { z } from 'zod';
4
4
 
5
5
  export const nonEmptyString = z.string().trim().min(1);
6
6
  export const positiveInt = z.number().int().positive();
7
+ export const nonNegativeInt = z.number().int().nonnegative();
7
8
  export const unixTimestamp = z.number().int().nonnegative();
8
9
 
9
10
  // ─── Pagination constants ─────────────────────────────────────────────────────
@@ -13,9 +14,21 @@ export const FILES_MAX_LIMIT = 100;
13
14
 
14
15
  // ─── Upload Destination ──────────────────────────────────────────────────────
15
16
 
17
+ /**
18
+ * Storage backend a file lives on.
19
+ * - 'r2' — Cloudflare R2 via presigned PUT / multipart
20
+ * - 'appwrite' — Appwrite Storage via direct browser SDK upload
21
+ *
22
+ * `recommendedUploadDestinationSchema` adds the meta-value 'hybrid' which is
23
+ * only valid as a service-wide setting (the upload manager picks r2/appwrite
24
+ * per-file based on size).
25
+ */
16
26
  export const uploadDestinationSchema = z.enum(['r2', 'appwrite']);
17
27
  export type UploadDestination = z.infer<typeof uploadDestinationSchema>;
18
28
 
29
+ export const recommendedUploadDestinationSchema = z.enum(['r2', 'appwrite', 'hybrid']);
30
+ export type RecommendedUploadDestination = z.infer<typeof recommendedUploadDestinationSchema>;
31
+
19
32
  // ─── Upload Status ────────────────────────────────────────────────────────────
20
33
 
21
34
  export const uploadStatusSchema = z.enum(['pending', 'completed', 'failed']);
package/src/releases.ts CHANGED
@@ -64,6 +64,84 @@ export const releaseUploadFailResponseSchema = z.object({
64
64
  });
65
65
  export type ReleaseUploadFailResponse = z.infer<typeof releaseUploadFailResponseSchema>;
66
66
 
67
+ // ─── Multipart Upload Lifecycle ──────────────────────────────────────────────
68
+
69
+ export const releaseMultipartCreateRequestSchema = z.object({
70
+ name: releaseNameSchema,
71
+ filename: releaseFilenameSchema,
72
+ /** Defaults server-side to `application/octet-stream` when omitted. */
73
+ mime_type: nonEmptyString.optional(),
74
+ tags: releaseTagsSchema.optional().default([]),
75
+ notes: releaseNotesSchema,
76
+ force_update: z.boolean().optional().default(false),
77
+ });
78
+ export type ReleaseMultipartCreateRequest = z.input<typeof releaseMultipartCreateRequestSchema>;
79
+
80
+ export const releaseMultipartCreateResponseSchema = z.object({
81
+ /** UniSource release id — the same id is used for sign/list/complete/abort. */
82
+ upload_id: nonEmptyString,
83
+ /** S3 (R2) multipart UploadId returned by CreateMultipartUpload. */
84
+ r2_upload_id: nonEmptyString,
85
+ /** R2 object key the parts are being uploaded against. */
86
+ key: nonEmptyString,
87
+ bucket: nonEmptyString,
88
+ expires_at: positiveInt,
89
+ });
90
+ export type ReleaseMultipartCreateResponse = z.infer<typeof releaseMultipartCreateResponseSchema>;
91
+
92
+ export const releaseMultipartSignPartQuerySchema = z.object({
93
+ upload_id: releaseIdSchema,
94
+ part_number: z.coerce.number().int().min(1).max(10_000),
95
+ });
96
+ export type ReleaseMultipartSignPartQuery = z.input<typeof releaseMultipartSignPartQuerySchema>;
97
+
98
+ export const releaseMultipartSignPartResponseSchema = z.object({
99
+ url: z.string().url(),
100
+ expires_at: positiveInt,
101
+ });
102
+ export type ReleaseMultipartSignPartResponse = z.infer<typeof releaseMultipartSignPartResponseSchema>;
103
+
104
+ export const releaseMultipartListPartsQuerySchema = z.object({
105
+ upload_id: releaseIdSchema,
106
+ });
107
+ export type ReleaseMultipartListPartsQuery = z.input<typeof releaseMultipartListPartsQuerySchema>;
108
+
109
+ export const releaseMultipartPartSchema = z.object({
110
+ PartNumber: z.number().int().min(1).max(10_000),
111
+ ETag: nonEmptyString,
112
+ Size: z.number().int().nonnegative(),
113
+ });
114
+ export type ReleaseMultipartPart = z.infer<typeof releaseMultipartPartSchema>;
115
+
116
+ export const releaseMultipartListPartsResponseSchema = z.object({
117
+ parts: z.array(releaseMultipartPartSchema),
118
+ });
119
+ export type ReleaseMultipartListPartsResponse = z.infer<typeof releaseMultipartListPartsResponseSchema>;
120
+
121
+ export const releaseMultipartCompleteRequestSchema = z.object({
122
+ upload_id: releaseIdSchema,
123
+ parts: z
124
+ .array(
125
+ z.object({
126
+ PartNumber: z.number().int().min(1).max(10_000),
127
+ ETag: nonEmptyString,
128
+ })
129
+ )
130
+ .min(1),
131
+ });
132
+ export type ReleaseMultipartCompleteRequest = z.input<typeof releaseMultipartCompleteRequestSchema>;
133
+
134
+ export const releaseMultipartCompleteResponseSchema = releaseUploadCompleteResponseSchema;
135
+ export type ReleaseMultipartCompleteResponse = z.infer<typeof releaseMultipartCompleteResponseSchema>;
136
+
137
+ export const releaseMultipartAbortRequestSchema = z.object({
138
+ upload_id: releaseIdSchema,
139
+ });
140
+ export type ReleaseMultipartAbortRequest = z.input<typeof releaseMultipartAbortRequestSchema>;
141
+
142
+ export const releaseMultipartAbortResponseSchema = releaseUploadFailResponseSchema;
143
+ export type ReleaseMultipartAbortResponse = z.infer<typeof releaseMultipartAbortResponseSchema>;
144
+
67
145
  // ─── List ───────────────────────────────────────────────────────────────────
68
146
 
69
147
  export const releasesListQuerySchema = z.object({
@@ -130,3 +208,29 @@ export const releaseSyncResponseSchema = z.object({
130
208
  results: z.array(releaseSyncResultSchema),
131
209
  });
132
210
  export type ReleaseSyncResponse = z.infer<typeof releaseSyncResponseSchema>;
211
+
212
+ // ─── App-facing /app/releases/latest ─────────────────────────────────────────
213
+
214
+ /**
215
+ * Response of `GET /app/releases/latest?channel=...` — used by client apps to
216
+ * discover the most recent completed release for a given distribution channel
217
+ * (e.g. `stable`, `beta`). Includes a short-lived presigned download URL.
218
+ */
219
+ export const appReleaseLatestQuerySchema = z.object({
220
+ channel: nonEmptyString.optional().default('stable'),
221
+ });
222
+ export type AppReleaseLatestQuery = z.input<typeof appReleaseLatestQuerySchema>;
223
+
224
+ export const appReleaseLatestResponseSchema = z.object({
225
+ id: nonEmptyString,
226
+ name: nonEmptyString,
227
+ size: z.number().int().nonnegative(),
228
+ r2_key: nonEmptyString,
229
+ tags: z.array(nonEmptyString),
230
+ notes: z.string().nullable(),
231
+ force_update: z.boolean(),
232
+ created_at: nonEmptyString,
233
+ download_url: z.string().url(),
234
+ download_url_expires_at: positiveInt,
235
+ });
236
+ export type AppReleaseLatestResponse = z.infer<typeof appReleaseLatestResponseSchema>;
package/src/services.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { nonEmptyString, positiveInt, unixTimestamp, uploadDestinationSchema } from './primitives';
2
+ import { nonEmptyString, positiveInt, recommendedUploadDestinationSchema, unixTimestamp } from './primitives';
3
3
 
4
4
  // ─── Service record ───────────────────────────────────────────────────────────
5
5
 
@@ -10,7 +10,7 @@ export const serviceSchema = z.object({
10
10
  max_storage_bytes: positiveInt,
11
11
  current_used_bytes: z.number().int().nonnegative(),
12
12
  max_file_size_bytes: positiveInt,
13
- recommended_upload_destination: uploadDestinationSchema.optional(),
13
+ recommended_upload_destination: recommendedUploadDestinationSchema.optional(),
14
14
  created_at: unixTimestamp,
15
15
  });
16
16
  export type Service = z.infer<typeof serviceSchema>;
@@ -43,7 +43,7 @@ export type AdminServiceUpdateResponse = z.infer<typeof adminServiceUpdateRespon
43
43
  */
44
44
  export const adminServiceSettingsRequestSchema = z
45
45
  .object({
46
- recommended_upload_destination: uploadDestinationSchema.optional(),
46
+ recommended_upload_destination: recommendedUploadDestinationSchema.optional(),
47
47
  })
48
48
  .refine((v) => v.recommended_upload_destination !== undefined, {
49
49
  message: 'At least one setting must be provided',