@panorama-industries/effect-vercel-blob 0.0.0-stage → 0.2.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.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -2
  3. package/dist/client.d.ts +8 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +8 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/contracts/blob-client.d.ts +67 -0
  8. package/dist/contracts/blob-client.d.ts.map +1 -0
  9. package/dist/contracts/blob-client.js +11 -0
  10. package/dist/contracts/blob-client.js.map +1 -0
  11. package/dist/contracts/blob-config.d.ts +114 -0
  12. package/dist/contracts/blob-config.d.ts.map +1 -0
  13. package/dist/contracts/blob-config.js +7 -0
  14. package/dist/contracts/blob-config.js.map +1 -0
  15. package/dist/contracts/blob-domain.d.ts +336 -0
  16. package/dist/contracts/blob-domain.d.ts.map +1 -0
  17. package/dist/contracts/blob-domain.js +152 -0
  18. package/dist/contracts/blob-domain.js.map +1 -0
  19. package/dist/contracts/blob-errors.d.ts +125 -0
  20. package/dist/contracts/blob-errors.d.ts.map +1 -0
  21. package/dist/contracts/blob-errors.js +114 -0
  22. package/dist/contracts/blob-errors.js.map +1 -0
  23. package/dist/contracts/blob-signed-urls.d.ts +83 -0
  24. package/dist/contracts/blob-signed-urls.d.ts.map +1 -0
  25. package/dist/contracts/blob-signed-urls.js +10 -0
  26. package/dist/contracts/blob-signed-urls.js.map +1 -0
  27. package/dist/contracts/blob-store.d.ts +153 -0
  28. package/dist/contracts/blob-store.d.ts.map +1 -0
  29. package/dist/contracts/blob-store.js +15 -0
  30. package/dist/contracts/blob-store.js.map +1 -0
  31. package/dist/contracts/blob-uploads.d.ts +101 -0
  32. package/dist/contracts/blob-uploads.d.ts.map +1 -0
  33. package/dist/contracts/blob-uploads.js +17 -0
  34. package/dist/contracts/blob-uploads.js.map +1 -0
  35. package/dist/implementation/blob-client-live.d.ts +37 -0
  36. package/dist/implementation/blob-client-live.d.ts.map +1 -0
  37. package/dist/implementation/blob-client-live.js +213 -0
  38. package/dist/implementation/blob-client-live.js.map +1 -0
  39. package/dist/implementation/blob-config-live.d.ts +49 -0
  40. package/dist/implementation/blob-config-live.d.ts.map +1 -0
  41. package/dist/implementation/blob-config-live.js +82 -0
  42. package/dist/implementation/blob-config-live.js.map +1 -0
  43. package/dist/implementation/blob-live.d.ts +16 -0
  44. package/dist/implementation/blob-live.d.ts.map +1 -0
  45. package/dist/implementation/blob-live.js +16 -0
  46. package/dist/implementation/blob-live.js.map +1 -0
  47. package/dist/implementation/blob-signed-urls-live.d.ts +12 -0
  48. package/dist/implementation/blob-signed-urls-live.d.ts.map +1 -0
  49. package/dist/implementation/blob-signed-urls-live.js +92 -0
  50. package/dist/implementation/blob-signed-urls-live.js.map +1 -0
  51. package/dist/implementation/blob-store-live.d.ts +18 -0
  52. package/dist/implementation/blob-store-live.d.ts.map +1 -0
  53. package/dist/implementation/blob-store-live.js +364 -0
  54. package/dist/implementation/blob-store-live.js.map +1 -0
  55. package/dist/implementation/blob-uploads-live.d.ts +11 -0
  56. package/dist/implementation/blob-uploads-live.d.ts.map +1 -0
  57. package/dist/implementation/blob-uploads-live.js +218 -0
  58. package/dist/implementation/blob-uploads-live.js.map +1 -0
  59. package/dist/index.d.ts +15 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +15 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/internal/blob-errors.d.ts +79 -0
  64. package/dist/internal/blob-errors.d.ts.map +1 -0
  65. package/dist/internal/blob-errors.js +196 -0
  66. package/dist/internal/blob-errors.js.map +1 -0
  67. package/dist/internal/blob-request.d.ts +255 -0
  68. package/dist/internal/blob-request.d.ts.map +1 -0
  69. package/dist/internal/blob-request.js +291 -0
  70. package/dist/internal/blob-request.js.map +1 -0
  71. package/dist/internal/callback.d.ts +70 -0
  72. package/dist/internal/callback.d.ts.map +1 -0
  73. package/dist/internal/callback.js +141 -0
  74. package/dist/internal/callback.js.map +1 -0
  75. package/dist/internal/client-token.d.ts +65 -0
  76. package/dist/internal/client-token.d.ts.map +1 -0
  77. package/dist/internal/client-token.js +80 -0
  78. package/dist/internal/client-token.js.map +1 -0
  79. package/dist/internal/env.d.ts +34 -0
  80. package/dist/internal/env.d.ts.map +1 -0
  81. package/dist/internal/env.js +61 -0
  82. package/dist/internal/env.js.map +1 -0
  83. package/dist/internal/multipart.d.ts +110 -0
  84. package/dist/internal/multipart.d.ts.map +1 -0
  85. package/dist/internal/multipart.js +290 -0
  86. package/dist/internal/multipart.js.map +1 -0
  87. package/dist/internal/presign.d.ts +123 -0
  88. package/dist/internal/presign.d.ts.map +1 -0
  89. package/dist/internal/presign.js +345 -0
  90. package/dist/internal/presign.js.map +1 -0
  91. package/dist/internal/store-id.d.ts +38 -0
  92. package/dist/internal/store-id.d.ts.map +1 -0
  93. package/dist/internal/store-id.js +54 -0
  94. package/dist/internal/store-id.js.map +1 -0
  95. package/dist/internal/urls.d.ts +26 -0
  96. package/dist/internal/urls.d.ts.map +1 -0
  97. package/dist/internal/urls.js +33 -0
  98. package/dist/internal/urls.js.map +1 -0
  99. package/dist/internal/wire.d.ts +55 -0
  100. package/dist/internal/wire.d.ts.map +1 -0
  101. package/dist/internal/wire.js +64 -0
  102. package/dist/internal/wire.js.map +1 -0
  103. package/dist/internal/write-headers.d.ts +56 -0
  104. package/dist/internal/write-headers.d.ts.map +1 -0
  105. package/dist/internal/write-headers.js +82 -0
  106. package/dist/internal/write-headers.js.map +1 -0
  107. package/dist/testing/index.d.ts +2 -0
  108. package/dist/testing/index.d.ts.map +1 -0
  109. package/dist/testing/index.js +2 -0
  110. package/dist/testing/index.js.map +1 -0
  111. package/dist/testing/test-blob-store.d.ts +134 -0
  112. package/dist/testing/test-blob-store.d.ts.map +1 -0
  113. package/dist/testing/test-blob-store.js +718 -0
  114. package/dist/testing/test-blob-store.js.map +1 -0
  115. package/package.json +65 -3
  116. package/src/client.ts +11 -0
  117. package/src/contracts/blob-client.ts +121 -0
  118. package/src/contracts/blob-config.ts +64 -0
  119. package/src/contracts/blob-domain.ts +304 -0
  120. package/src/contracts/blob-errors.ts +161 -0
  121. package/src/contracts/blob-signed-urls.ts +112 -0
  122. package/src/contracts/blob-store.ts +258 -0
  123. package/src/contracts/blob-uploads.ts +151 -0
  124. package/src/implementation/blob-client-live.ts +387 -0
  125. package/src/implementation/blob-config-live.ts +145 -0
  126. package/src/implementation/blob-live.ts +30 -0
  127. package/src/implementation/blob-signed-urls-live.ts +121 -0
  128. package/src/implementation/blob-store-live.ts +528 -0
  129. package/src/implementation/blob-uploads-live.ts +326 -0
  130. package/src/index.ts +18 -0
  131. package/src/internal/blob-errors.ts +325 -0
  132. package/src/internal/blob-request.ts +617 -0
  133. package/src/internal/callback.ts +200 -0
  134. package/src/internal/client-token.ts +132 -0
  135. package/src/internal/env.ts +128 -0
  136. package/src/internal/multipart.ts +526 -0
  137. package/src/internal/presign.ts +477 -0
  138. package/src/internal/store-id.ts +69 -0
  139. package/src/internal/urls.ts +42 -0
  140. package/src/internal/wire.ts +80 -0
  141. package/src/internal/write-headers.ts +118 -0
  142. package/src/testing/index.ts +1 -0
  143. package/src/testing/test-blob-store.ts +1136 -0
@@ -0,0 +1,123 @@
1
+ import { Effect, Option, Schema } from "effect";
2
+ import type { BlobAccess, DelegationOperation, StoreId } from "../contracts/blob-domain.ts";
3
+ import type { PresignOptions, SigningToken } from "../contracts/blob-signed-urls.ts";
4
+ import { PresignedUrlPayload } from "../contracts/blob-domain.ts";
5
+ import { BlobPresignFailed } from "../contracts/blob-errors.ts";
6
+ /** Signed expiry of one URL, when earlier than the delegation's. */
7
+ export declare const presignQueryValidUntil = "vercel-blob-valid-until";
8
+ /** Largest upload a presigned `put` accepts. */
9
+ export declare const presignQueryMaximumSize = "vercel-blob-maximum-size-in-bytes";
10
+ /** Media types a presigned `put` accepts, sorted and comma-separated. */
11
+ export declare const presignQueryAllowedContentTypes = "vercel-blob-allowed-content-types";
12
+ /** `true`/`false`. */
13
+ export declare const presignQueryAddRandomSuffix = "vercel-blob-add-random-suffix";
14
+ /** `true`/`false`. */
15
+ export declare const presignQueryAllowOverwrite = "vercel-blob-allow-overwrite";
16
+ /** Seconds. */
17
+ export declare const presignQueryCacheControlMaxAge = "vercel-blob-cache-control-max-age";
18
+ /** ETag a presigned `put` or `delete` requires. */
19
+ export declare const presignQueryIfMatch = "vercel-blob-if-match";
20
+ /** Where the store sends `blob.upload-completed`. */
21
+ export declare const presignQueryCallbackUrl = "vercel-blob-callback-url";
22
+ /** `tokenPayload` of the upload-completed callback. */
23
+ export declare const presignQueryCallbackTokenPayload = "vercel-blob-callback-token-payload";
24
+ /** Every signed constraint, in UTF-8 order, as the SDK's `PRESIGN_CANONICAL_QUERY_KEYS`. */
25
+ export declare const presignCanonicalQueryKeys: readonly ["vercel-blob-add-random-suffix", "vercel-blob-allow-overwrite", "vercel-blob-allowed-content-types", "vercel-blob-cache-control-max-age", "vercel-blob-callback-token-payload", "vercel-blob-callback-url", "vercel-blob-if-match", "vercel-blob-maximum-size-in-bytes", "vercel-blob-valid-until"];
26
+ /** Longest `onUploadCompleted.callbackUrl` a presigned URL may carry. */
27
+ export declare const maximumPresignCallbackUrlLength = 4096;
28
+ /** Longest `onUploadCompleted.tokenPayload` a presigned URL may carry. */
29
+ export declare const maximumPresignCallbackTokenPayloadLength = 8192;
30
+ /** Largest `cacheControlMaxAge` a presigned URL may carry: one year, in seconds. */
31
+ export declare const maximumPresignCacheControlMaxAge: number;
32
+ /** One signed query parameter. */
33
+ export type PresignQueryEntry = readonly [key: string, value: string];
34
+ /** What a delegation token's payload constrains, as the SDK reads it for presigning. */
35
+ export declare const DelegationScope: Schema.Struct<{
36
+ readonly pathname: Schema.optionalKey<Schema.String>;
37
+ readonly operations: Schema.optionalKey<Schema.$Array<Schema.String>>;
38
+ /** Epoch milliseconds. */
39
+ readonly validUntil: Schema.optionalKey<Schema.Number>;
40
+ readonly maximumSizeInBytes: Schema.optionalKey<Schema.Number>;
41
+ readonly allowedContentTypes: Schema.optionalKey<Schema.$Array<Schema.String>>;
42
+ }>;
43
+ /** What a delegation token's payload constrains. */
44
+ export type DelegationScope = typeof DelegationScope.Type;
45
+ /**
46
+ * Read the scope of a delegation token: the base64url JSON before its first `.`. Standard base64
47
+ * characters and padding are accepted, as the SDK's decoder accepts them.
48
+ *
49
+ * @returns None when the token has no `.` or the segment is not base64url JSON of an object.
50
+ */
51
+ export declare const delegationScope: (delegationToken: string) => Option.Option<DelegationScope>;
52
+ /**
53
+ * The string a presigned URL's signature covers, as the SDK's `canonicalString`: `operation=…`,
54
+ * `pathname=…` and every non-empty signed entry as `key=value`, sorted bytewise and joined by `\n`.
55
+ */
56
+ export declare const canonicalString: (pathname: string, entries: ReadonlyArray<PresignQueryEntry>, operation: DelegationOperation) => string;
57
+ /** HMAC-SHA256 of `data` keyed by `secret` (both UTF-8), as unpadded base64url. */
58
+ export declare const hmacSha256Base64Url: (secret: string, data: string) => Effect.Effect<string, never, never>;
59
+ /** Signed constraints of one presigned URL, in epoch milliseconds and seconds as on the wire. */
60
+ export interface PresignUrlConstraints {
61
+ readonly validUntil?: number | undefined;
62
+ readonly allowedContentTypes?: ReadonlyArray<string> | undefined;
63
+ readonly maximumSizeInBytes?: number | undefined;
64
+ readonly addRandomSuffix?: boolean | undefined;
65
+ readonly allowOverwrite?: boolean | undefined;
66
+ readonly cacheControlMaxAge?: number | undefined;
67
+ readonly ifMatch?: string | undefined;
68
+ readonly onUploadCompleted?: {
69
+ readonly callbackUrl: string;
70
+ readonly tokenPayload?: string | null | undefined;
71
+ } | undefined;
72
+ }
73
+ /** What the delegation allows, as the SDK's `DelegationScopeForPresign`. */
74
+ export interface PresignDelegation {
75
+ /** Epoch milliseconds; none when the delegation states no expiry. */
76
+ readonly validUntil: number | undefined;
77
+ readonly maximumSizeInBytes?: number | undefined;
78
+ readonly allowedContentTypes?: ReadonlyArray<string> | undefined;
79
+ }
80
+ /**
81
+ * The signed query entries of one presigned URL, as the SDK's `buildPresignCanonicalQueryEntries`,
82
+ * in the same order. `vercel-blob-valid-until` is left out when it equals the delegation's expiry;
83
+ * `get` and `head` sign only the expiry, `delete` also `ifMatch`, and `put` every constraint after
84
+ * checking that each one only narrows the delegation's.
85
+ */
86
+ export declare const presignCanonicalQueryEntries: (args: {
87
+ readonly operation: DelegationOperation;
88
+ readonly delegation: PresignDelegation;
89
+ readonly urlOptions: PresignUrlConstraints;
90
+ readonly now: number;
91
+ }) => Effect.Effect<PresignQueryEntry[], BlobPresignFailed, never>;
92
+ /**
93
+ * Sign one request with a signed token, as the SDK's `presign`: check the delegation's pathname,
94
+ * expiry and operations, build the signed query entries, and HMAC their canonical string with the
95
+ * client signing token.
96
+ *
97
+ * @param now - Current time in epoch milliseconds.
98
+ * @returns The payload, or `BlobPresignFailed` with the SDK's message.
99
+ */
100
+ export declare const presignPayload: (token: SigningToken, options: PresignOptions, now: number) => Effect.Effect<PresignedUrlPayload, BlobPresignFailed, never>;
101
+ /** `url` with the payload's params, `vercel-blob-delegation` and `vercel-blob-signature` set. */
102
+ export declare const withPresignedParams: (url: URL, payload: PresignedUrlPayload) => URL;
103
+ /**
104
+ * The presigned URL of a `get` or `head`, as the SDK's `buildPresignedGetUrl`: a blob URL is used
105
+ * as is, a pathname is resolved under the delegation's store (`blobBaseUrl`); `cache=0` (unsigned)
106
+ * is added for a private `get` with `useCache: false`.
107
+ *
108
+ * @returns None when the delegation token carries no valid store id, which the SDK requires even
109
+ * for a blob URL.
110
+ */
111
+ export declare const presignedBlobUrl: (args: {
112
+ readonly pathnameOrUrl: string;
113
+ readonly payload: PresignedUrlPayload;
114
+ readonly access: BlobAccess;
115
+ readonly useCache: boolean | undefined;
116
+ readonly blobBaseUrl: (storeId: StoreId, access: BlobAccess) => URL;
117
+ }) => Option.Option<URL>;
118
+ /**
119
+ * The presigned URL of a `put` or `delete`, as the SDK's `buildPresignedPutUrl`: the Blob API's
120
+ * `/?pathname=…` (trailing slashes of `apiUrl` removed) plus the payload's params.
121
+ */
122
+ export declare const presignedApiUrl: (apiUrl: URL, pathname: string, payload: PresignedUrlPayload) => URL;
123
+ //# sourceMappingURL=presign.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presign.d.ts","sourceRoot":"","sources":["../../src/internal/presign.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,EAAE,MAAM,EAAoB,MAAM,EAAE,MAAM,QAAQ,CAAC;AAG5E,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAC5F,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAErF,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAUhE,oEAAoE;AACpE,eAAO,MAAM,sBAAsB,4BAA4B,CAAC;AAChE,gDAAgD;AAChD,eAAO,MAAM,uBAAuB,sCAAsC,CAAC;AAC3E,yEAAyE;AACzE,eAAO,MAAM,+BAA+B,sCAAsC,CAAC;AACnF,sBAAsB;AACtB,eAAO,MAAM,2BAA2B,kCAAkC,CAAC;AAC3E,sBAAsB;AACtB,eAAO,MAAM,0BAA0B,gCAAgC,CAAC;AACxE,eAAe;AACf,eAAO,MAAM,8BAA8B,sCAAsC,CAAC;AAClF,mDAAmD;AACnD,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAC1D,qDAAqD;AACrD,eAAO,MAAM,uBAAuB,6BAA6B,CAAC;AAClE,uDAAuD;AACvD,eAAO,MAAM,gCAAgC,uCAAuC,CAAC;AAErF,4FAA4F;AAC5F,eAAO,MAAM,yBAAyB,+SAU5B,CAAC;AAEX,yEAAyE;AACzE,eAAO,MAAM,+BAA+B,OAAO,CAAC;AAEpD,0EAA0E;AAC1E,eAAO,MAAM,wCAAwC,OAAO,CAAC;AAE7D,oFAAoF;AACpF,eAAO,MAAM,gCAAgC,QAAqB,CAAC;AASnE,kCAAkC;AAClC,MAAM,MAAM,iBAAiB,GAAG,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAEtE,wFAAwF;AACxF,eAAO,MAAM,eAAe;;;IAG1B,0BAA0B;;;;EAI1B,CAAC;AAEH,oDAAoD;AACpD,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAC;AAI1D;;;;;GAKG;AACH,eAAO,MAAM,eAAe,oBAAqB,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,eAAe,CAWtF,CAAC;AAkBF;;;GAGG;AACH,eAAO,MAAM,eAAe,aAChB,MAAM,WACP,aAAa,CAAC,iBAAiB,CAAC,aAC9B,mBAAmB,KAC7B,MASF,CAAC;AAEF,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,uEAc9B,CAAC;AAIH,iGAAiG;AACjG,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IACjE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,iBAAiB,CAAC,EACvB;QAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;KAAE,GACnF,SAAS,CAAC;CACf;AAED,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;CAClE;AAiGD;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B;wBACnB,mBAAmB;yBAClB,iBAAiB;yBACjB,qBAAqB;kBAC5B,MAAM;kEAsDpB,CAAC;AAoCH;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,6HA2CzB,CAAC;AAEH,iGAAiG;AACjG,eAAO,MAAM,mBAAmB,QAAS,GAAG,WAAW,mBAAmB,KAAG,GAQ5E,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,SAAU;IACrC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,KAAK,GAAG,CAAC;CACrE,KAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CASjB,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,eAAe,WAClB,GAAG,YACD,MAAM,WACP,mBAAmB,KAC3B,GAMF,CAAC"}
@@ -0,0 +1,345 @@
1
+ import { DateTime, Effect, Option, Redacted, Result, Schema } from "effect";
2
+ import { Base64Url } from "effect/encoding";
3
+ import { PresignedUrlPayload } from "../contracts/blob-domain.js";
4
+ import { BlobPresignFailed } from "../contracts/blob-errors.js";
5
+ import { storeIdFromDelegationToken } from "./store-id.js";
6
+ import { blobUrl, isUrl } from "./urls.js";
7
+ /*
8
+ * Presigned URLs, ported from the SDK's `signed-token.ts` (`presign`, `presignUrl`,
9
+ * `canonicalString`) and `presign-query-params.ts`. The canonical string and query entries must
10
+ * stay aligned with the Blob API and proxy that verify them.
11
+ */
12
+ /** Signed expiry of one URL, when earlier than the delegation's. */
13
+ export const presignQueryValidUntil = "vercel-blob-valid-until";
14
+ /** Largest upload a presigned `put` accepts. */
15
+ export const presignQueryMaximumSize = "vercel-blob-maximum-size-in-bytes";
16
+ /** Media types a presigned `put` accepts, sorted and comma-separated. */
17
+ export const presignQueryAllowedContentTypes = "vercel-blob-allowed-content-types";
18
+ /** `true`/`false`. */
19
+ export const presignQueryAddRandomSuffix = "vercel-blob-add-random-suffix";
20
+ /** `true`/`false`. */
21
+ export const presignQueryAllowOverwrite = "vercel-blob-allow-overwrite";
22
+ /** Seconds. */
23
+ export const presignQueryCacheControlMaxAge = "vercel-blob-cache-control-max-age";
24
+ /** ETag a presigned `put` or `delete` requires. */
25
+ export const presignQueryIfMatch = "vercel-blob-if-match";
26
+ /** Where the store sends `blob.upload-completed`. */
27
+ export const presignQueryCallbackUrl = "vercel-blob-callback-url";
28
+ /** `tokenPayload` of the upload-completed callback. */
29
+ export const presignQueryCallbackTokenPayload = "vercel-blob-callback-token-payload";
30
+ /** Every signed constraint, in UTF-8 order, as the SDK's `PRESIGN_CANONICAL_QUERY_KEYS`. */
31
+ export const presignCanonicalQueryKeys = [
32
+ presignQueryAddRandomSuffix,
33
+ presignQueryAllowOverwrite,
34
+ presignQueryAllowedContentTypes,
35
+ presignQueryCacheControlMaxAge,
36
+ presignQueryCallbackTokenPayload,
37
+ presignQueryCallbackUrl,
38
+ presignQueryIfMatch,
39
+ presignQueryMaximumSize,
40
+ presignQueryValidUntil,
41
+ ];
42
+ /** Longest `onUploadCompleted.callbackUrl` a presigned URL may carry. */
43
+ export const maximumPresignCallbackUrlLength = 4096;
44
+ /** Longest `onUploadCompleted.tokenPayload` a presigned URL may carry. */
45
+ export const maximumPresignCallbackTokenPayloadLength = 8192;
46
+ /** Largest `cacheControlMaxAge` a presigned URL may carry: one year, in seconds. */
47
+ export const maximumPresignCacheControlMaxAge = 365 * 24 * 60 * 60;
48
+ const maximumIfMatchLength = 256;
49
+ // oxlint-disable-next-line no-control-regex -- control characters are what it rejects
50
+ const ifMatchControlCharacters = /[\x00-\x1f\x7f]/;
51
+ const label = "presignUrl";
52
+ /** What a delegation token's payload constrains, as the SDK reads it for presigning. */
53
+ export const DelegationScope = Schema.Struct({
54
+ pathname: Schema.optionalKey(Schema.String),
55
+ operations: Schema.optionalKey(Schema.Array(Schema.String)),
56
+ /** Epoch milliseconds. */
57
+ validUntil: Schema.optionalKey(Schema.Number),
58
+ maximumSizeInBytes: Schema.optionalKey(Schema.Number),
59
+ allowedContentTypes: Schema.optionalKey(Schema.Array(Schema.String)),
60
+ });
61
+ const decodeScope = Schema.decodeUnknownOption(Schema.fromJsonString(DelegationScope));
62
+ /**
63
+ * Read the scope of a delegation token: the base64url JSON before its first `.`. Standard base64
64
+ * characters and padding are accepted, as the SDK's decoder accepts them.
65
+ *
66
+ * @returns None when the token has no `.` or the segment is not base64url JSON of an object.
67
+ */
68
+ export const delegationScope = (delegationToken) => {
69
+ const dot = delegationToken.indexOf(".");
70
+ if (dot < 0) {
71
+ return Option.none();
72
+ }
73
+ const segment = delegationToken
74
+ .slice(0, dot)
75
+ .replace(/\+/g, "-")
76
+ .replace(/\//g, "_")
77
+ .replace(/=+$/, "");
78
+ return Result.getSuccess(Base64Url.decodeString(segment)).pipe(Option.flatMap(decodeScope));
79
+ };
80
+ const utf8 = new TextEncoder();
81
+ /** Bytewise UTF-8 order, as the SDK's `compareUtf8` (Go string order). */
82
+ const compareUtf8 = (a, b) => {
83
+ const left = utf8.encode(a);
84
+ const right = utf8.encode(b);
85
+ const length = Math.min(left.length, right.length);
86
+ for (let i = 0; i < length; i++) {
87
+ const difference = left[i] - right[i];
88
+ if (difference !== 0) {
89
+ return difference;
90
+ }
91
+ }
92
+ return left.length - right.length;
93
+ };
94
+ /**
95
+ * The string a presigned URL's signature covers, as the SDK's `canonicalString`: `operation=…`,
96
+ * `pathname=…` and every non-empty signed entry as `key=value`, sorted bytewise and joined by `\n`.
97
+ */
98
+ export const canonicalString = (pathname, entries, operation) => {
99
+ const lines = [`operation=${operation}`, `pathname=${pathname}`];
100
+ for (const key of presignCanonicalQueryKeys) {
101
+ const value = entries.find(([entry]) => entry === key)?.[1];
102
+ if (value) {
103
+ lines.push(`${key}=${value}`);
104
+ }
105
+ }
106
+ return lines.sort(compareUtf8).join("\n");
107
+ };
108
+ /** HMAC-SHA256 of `data` keyed by `secret` (both UTF-8), as unpadded base64url. */
109
+ export const hmacSha256Base64Url = Effect.fnUntraced(function* (secret, data) {
110
+ const key = yield* Effect.promise(() => globalThis.crypto.subtle.importKey("raw", utf8.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]));
111
+ const signature = yield* Effect.promise(() => globalThis.crypto.subtle.sign("HMAC", key, utf8.encode(data)));
112
+ return Base64Url.encode(new Uint8Array(signature));
113
+ });
114
+ const failed = (message) => Effect.fail(new BlobPresignFailed({ message }));
115
+ const contentTypeAllowed = (contentType, allowed) => {
116
+ const [type] = contentType.split("/");
117
+ return allowed.includes(contentType) || (type ? allowed.includes(`${type}/*`) : false);
118
+ };
119
+ /**
120
+ * The URL's expiry, as the SDK's `resolvePresignUrlValidUntilMs`: the requested one capped to the
121
+ * delegation's, which must be after `now`. A delegation without an expiry and no requested one
122
+ * yields `NaN`, as in the SDK, which then signs no expiry.
123
+ */
124
+ const resolveValidUntil = (delegationValidUntil, requested, now) => {
125
+ let until = Math.trunc(requested ?? delegationValidUntil ?? Number.NaN);
126
+ if (delegationValidUntil !== undefined && Number.isFinite(delegationValidUntil)) {
127
+ until = Math.min(until, Math.trunc(delegationValidUntil));
128
+ }
129
+ if (until <= now) {
130
+ return failed(`${label}: resolved URL expiry is not after the current time; issue a new delegation token or pass a later validUntil.`);
131
+ }
132
+ return Effect.succeed(until);
133
+ };
134
+ const validateUploadConstraints = Effect.fnUntraced(function* (options, delegation) {
135
+ const allowed = delegation.allowedContentTypes;
136
+ if (options.allowedContentTypes?.length && allowed?.length) {
137
+ for (const contentType of options.allowedContentTypes) {
138
+ if (!contentTypeAllowed(contentType, allowed)) {
139
+ return yield* failed(`${label}: allowedContentTypes entry "${contentType}" is not permitted by the delegation token.`);
140
+ }
141
+ }
142
+ }
143
+ if (options.maximumSizeInBytes !== undefined &&
144
+ delegation.maximumSizeInBytes !== undefined &&
145
+ options.maximumSizeInBytes > delegation.maximumSizeInBytes) {
146
+ return yield* failed(`${label}: maximumSizeInBytes must be ≤ delegation (${String(delegation.maximumSizeInBytes)}).`);
147
+ }
148
+ const maxAge = options.cacheControlMaxAge;
149
+ if (maxAge !== undefined &&
150
+ (!Number.isInteger(maxAge) || maxAge < 0 || maxAge > maximumPresignCacheControlMaxAge)) {
151
+ return yield* failed(`${label}: cacheControlMaxAge must be an integer between 0 and ${maximumPresignCacheControlMaxAge}.`);
152
+ }
153
+ const ifMatch = options.ifMatch;
154
+ if (ifMatch !== undefined) {
155
+ if (ifMatch.length === 0) {
156
+ return yield* failed(`${label}: ifMatch must be a non-empty string.`);
157
+ }
158
+ if (ifMatch.length > maximumIfMatchLength) {
159
+ return yield* failed(`${label}: ifMatch is too long.`);
160
+ }
161
+ if (ifMatchControlCharacters.test(ifMatch)) {
162
+ return yield* failed(`${label}: ifMatch contains disallowed control characters.`);
163
+ }
164
+ }
165
+ const callback = options.onUploadCompleted;
166
+ if (callback !== undefined) {
167
+ if (callback.callbackUrl.length === 0) {
168
+ return yield* failed(`${label}: onUploadCompleted.callbackUrl must be a non-empty string.`);
169
+ }
170
+ if (callback.callbackUrl.length > maximumPresignCallbackUrlLength) {
171
+ return yield* failed(`${label}: onUploadCompleted.callbackUrl is too long.`);
172
+ }
173
+ if (!URL.canParse(callback.callbackUrl)) {
174
+ return yield* failed(`${label}: onUploadCompleted.callbackUrl must be a valid URL.`);
175
+ }
176
+ if (callback.tokenPayload !== undefined &&
177
+ callback.tokenPayload !== null &&
178
+ callback.tokenPayload.length > maximumPresignCallbackTokenPayloadLength) {
179
+ return yield* failed(`${label}: onUploadCompleted.tokenPayload is too long.`);
180
+ }
181
+ }
182
+ });
183
+ const sortedCsv = (types) => [...types].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).join(",");
184
+ /**
185
+ * The signed query entries of one presigned URL, as the SDK's `buildPresignCanonicalQueryEntries`,
186
+ * in the same order. `vercel-blob-valid-until` is left out when it equals the delegation's expiry;
187
+ * `get` and `head` sign only the expiry, `delete` also `ifMatch`, and `put` every constraint after
188
+ * checking that each one only narrows the delegation's.
189
+ */
190
+ export const presignCanonicalQueryEntries = Effect.fnUntraced(function* (args) {
191
+ const { operation, delegation, urlOptions, now } = args;
192
+ const until = yield* resolveValidUntil(delegation.validUntil, urlOptions.validUntil, now);
193
+ const entries = [];
194
+ if (until < Math.trunc(delegation.validUntil ?? Number.NaN)) {
195
+ entries.push([presignQueryValidUntil, String(until)]);
196
+ }
197
+ if (operation === "delete") {
198
+ if (urlOptions.ifMatch !== undefined) {
199
+ entries.push([presignQueryIfMatch, urlOptions.ifMatch]);
200
+ }
201
+ return entries;
202
+ }
203
+ if (operation !== "put") {
204
+ return entries;
205
+ }
206
+ yield* validateUploadConstraints(urlOptions, delegation);
207
+ if (urlOptions.allowedContentTypes !== undefined) {
208
+ const csv = sortedCsv(urlOptions.allowedContentTypes);
209
+ if (csv.length > 16_384) {
210
+ return yield* failed(`${label}: allowedContentTypes query value is too long.`);
211
+ }
212
+ entries.push([presignQueryAllowedContentTypes, csv]);
213
+ }
214
+ if (urlOptions.maximumSizeInBytes !== undefined) {
215
+ entries.push([presignQueryMaximumSize, String(Math.trunc(urlOptions.maximumSizeInBytes))]);
216
+ }
217
+ if (urlOptions.addRandomSuffix !== undefined) {
218
+ entries.push([presignQueryAddRandomSuffix, urlOptions.addRandomSuffix ? "true" : "false"]);
219
+ }
220
+ if (urlOptions.allowOverwrite !== undefined) {
221
+ entries.push([presignQueryAllowOverwrite, urlOptions.allowOverwrite ? "true" : "false"]);
222
+ }
223
+ if (urlOptions.cacheControlMaxAge !== undefined) {
224
+ entries.push([
225
+ presignQueryCacheControlMaxAge,
226
+ String(Math.trunc(urlOptions.cacheControlMaxAge)),
227
+ ]);
228
+ }
229
+ if (urlOptions.ifMatch !== undefined) {
230
+ entries.push([presignQueryIfMatch, urlOptions.ifMatch]);
231
+ }
232
+ if (urlOptions.onUploadCompleted !== undefined) {
233
+ const { callbackUrl, tokenPayload } = urlOptions.onUploadCompleted;
234
+ entries.push([presignQueryCallbackUrl, callbackUrl]);
235
+ if (tokenPayload !== undefined && tokenPayload !== null && tokenPayload !== "") {
236
+ entries.push([presignQueryCallbackTokenPayload, tokenPayload]);
237
+ }
238
+ }
239
+ return entries;
240
+ });
241
+ const epochMillis = (value) => value === undefined ? undefined : DateTime.toEpochMillis(value);
242
+ /** The signed constraints of {@link PresignOptions}, in wire units. */
243
+ const urlConstraints = (options) => {
244
+ const validUntil = epochMillis(options.validUntil);
245
+ switch (options.operation) {
246
+ case "get":
247
+ case "head":
248
+ return { validUntil };
249
+ case "delete":
250
+ return { validUntil, ifMatch: options.ifMatch };
251
+ case "put":
252
+ return {
253
+ validUntil,
254
+ allowedContentTypes: options.allowedContentTypes,
255
+ maximumSizeInBytes: options.maximumSizeInBytes,
256
+ addRandomSuffix: options.addRandomSuffix,
257
+ allowOverwrite: options.allowOverwrite,
258
+ cacheControlMaxAge: options.cacheControlMaxAge,
259
+ ifMatch: options.ifMatch,
260
+ onUploadCompleted: options.onUploadCompleted,
261
+ };
262
+ }
263
+ };
264
+ const operationNotDelegated = {
265
+ get: 'The delegation token is not valid for `GET` requests. Include `"get"` in `operations` when calling `issueSignedToken`.',
266
+ head: 'The delegation token is not valid for `HEAD` requests. Include `"head"` in `operations` when calling `issueSignedToken`.',
267
+ put: 'The delegation token is not valid for presigned write requests. Include `"put"` in `operations` when calling `issueSignedToken`.',
268
+ delete: 'The delegation token is not valid for presigned delete requests. Include `"delete"` in `operations` when calling `issueSignedToken`.',
269
+ };
270
+ /**
271
+ * Sign one request with a signed token, as the SDK's `presign`: check the delegation's pathname,
272
+ * expiry and operations, build the signed query entries, and HMAC their canonical string with the
273
+ * client signing token.
274
+ *
275
+ * @param now - Current time in epoch milliseconds.
276
+ * @returns The payload, or `BlobPresignFailed` with the SDK's message.
277
+ */
278
+ export const presignPayload = Effect.fnUntraced(function* (token, options, now) {
279
+ const clientSigningToken = Redacted.value(token.clientSigningToken);
280
+ if (!clientSigningToken || !token.delegationToken) {
281
+ return yield* failed("`clientSigningToken` and `delegationToken` from `issueSignedToken` are required.");
282
+ }
283
+ const scope = delegationScope(token.delegationToken);
284
+ if (Option.isNone(scope)) {
285
+ return yield* failed("Invalid or unreadable `delegationToken` payload.");
286
+ }
287
+ const { pathname, validUntil, operations, maximumSizeInBytes, allowedContentTypes } = scope.value;
288
+ if (pathname && pathname !== "*" && options.pathname !== pathname) {
289
+ return yield* failed(`Blob path does not match the signed token scope; expected \`${pathname}\`, got \`${options.pathname}\`.`);
290
+ }
291
+ if (validUntil !== undefined && Number.isFinite(validUntil) && now > validUntil) {
292
+ return yield* failed("The signed delegation has expired; issue a new token first.");
293
+ }
294
+ if (!operations?.includes(options.operation)) {
295
+ return yield* failed(operationNotDelegated[options.operation]);
296
+ }
297
+ const entries = yield* presignCanonicalQueryEntries({
298
+ operation: options.operation,
299
+ delegation: { validUntil, maximumSizeInBytes, allowedContentTypes },
300
+ urlOptions: urlConstraints(options),
301
+ now,
302
+ });
303
+ const signature = yield* hmacSha256Base64Url(clientSigningToken, canonicalString(options.pathname, entries, options.operation));
304
+ return new PresignedUrlPayload({
305
+ delegationToken: token.delegationToken,
306
+ signature,
307
+ params: Object.fromEntries(entries),
308
+ });
309
+ });
310
+ /** `url` with the payload's params, `vercel-blob-delegation` and `vercel-blob-signature` set. */
311
+ export const withPresignedParams = (url, payload) => {
312
+ const result = new URL(url);
313
+ for (const [key, value] of Object.entries(payload.params)) {
314
+ result.searchParams.set(key, value);
315
+ }
316
+ result.searchParams.set("vercel-blob-delegation", payload.delegationToken);
317
+ result.searchParams.set("vercel-blob-signature", payload.signature);
318
+ return result;
319
+ };
320
+ /**
321
+ * The presigned URL of a `get` or `head`, as the SDK's `buildPresignedGetUrl`: a blob URL is used
322
+ * as is, a pathname is resolved under the delegation's store (`blobBaseUrl`); `cache=0` (unsigned)
323
+ * is added for a private `get` with `useCache: false`.
324
+ *
325
+ * @returns None when the delegation token carries no valid store id, which the SDK requires even
326
+ * for a blob URL.
327
+ */
328
+ export const presignedBlobUrl = (args) => Option.map(storeIdFromDelegationToken(args.payload.delegationToken), (storeId) => {
329
+ const url = isUrl(args.pathnameOrUrl)
330
+ ? new URL(args.pathnameOrUrl)
331
+ : blobUrl(args.blobBaseUrl(storeId, args.access), args.pathnameOrUrl);
332
+ if (args.useCache === false && args.access === "private") {
333
+ url.searchParams.set("cache", "0");
334
+ }
335
+ return withPresignedParams(url, args.payload);
336
+ });
337
+ /**
338
+ * The presigned URL of a `put` or `delete`, as the SDK's `buildPresignedPutUrl`: the Blob API's
339
+ * `/?pathname=…` (trailing slashes of `apiUrl` removed) plus the payload's params.
340
+ */
341
+ export const presignedApiUrl = (apiUrl, pathname, payload) => {
342
+ const base = apiUrl.href.replace(/\/+$/, "");
343
+ return withPresignedParams(new URL(`${base}/?${new URLSearchParams({ pathname }).toString()}`), payload);
344
+ };
345
+ //# sourceMappingURL=presign.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presign.js","sourceRoot":"","sources":["../../src/internal/presign.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { Option } from "effect";
2
+ import { StoreId } from "../contracts/blob-domain.ts";
3
+ /**
4
+ * Strip the optional `store_` prefix from a store id. `BLOB_STORE_ID` (as written by
5
+ * `vercel env pull`) and the `storeId` option accept `store_<id>` or `<id>`; the API wants the bare
6
+ * id, case preserved.
7
+ */
8
+ export declare const normalizeStoreId: (storeId: string) => string;
9
+ /**
10
+ * Validate a store id given in either form (`store_<id>` or `<id>`).
11
+ *
12
+ * @returns The bare id, or none when it is empty or contains whitespace or `_`.
13
+ */
14
+ export declare const parseStoreId: (storeId: string) => Option.Option<StoreId>;
15
+ /**
16
+ * The store id embedded in a read-write token (`vercel_blob_rw_<storeId>_<secret>`): the fourth
17
+ * `_`-separated segment, as the SDK's `parseStoreIdFromReadWriteToken`.
18
+ *
19
+ * @returns None when the token has no valid fourth segment.
20
+ */
21
+ export declare const storeIdFromReadWriteToken: (token: string) => Option.Option<StoreId>;
22
+ /**
23
+ * The store id embedded in a client token (`vercel_blob_client_<storeId>_<payload>`). The SDK reads
24
+ * it with the same fourth-segment rule as read-write tokens.
25
+ */
26
+ export declare const storeIdFromClientToken: (token: string) => Option.Option<StoreId>;
27
+ /**
28
+ * Read the store id from a delegation token, the public half of a signed token that every presigned
29
+ * URL carries in `vercel-blob-delegation`. The token's payload is the base64url JSON before the first
30
+ * `.`; its `storeId` field is returned without the `store_` prefix.
31
+ *
32
+ * Works in browsers, so a client can address the right store from a presigned payload alone.
33
+ *
34
+ * @returns None when the token has no `.`, its payload is not base64url JSON, or it has no
35
+ * non-empty `storeId` string that is a valid store id.
36
+ */
37
+ export declare const storeIdFromDelegationToken: (delegationToken: string) => Option.Option<StoreId>;
38
+ //# sourceMappingURL=store-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-id.d.ts","sourceRoot":"","sources":["../../src/internal/store-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAkB,MAAM,QAAQ,CAAC;AAGhD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAItD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,YAAa,MAAM,KAAG,MACsB,CAAC;AAE1E;;;;GAIG;AACH,eAAO,MAAM,YAAY,YAAa,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAC1B,CAAC;AAE3C;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,UAAW,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CACH,CAAC;AAE7E;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,CAClD,CAAC;AAM5B;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B,oBAAqB,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAezF,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { Option, Result, Schema } from "effect";
2
+ import { Base64Url } from "effect/encoding";
3
+ import { StoreId } from "../contracts/blob-domain.js";
4
+ const decodeStoreId = Schema.decodeUnknownOption(StoreId);
5
+ /**
6
+ * Strip the optional `store_` prefix from a store id. `BLOB_STORE_ID` (as written by
7
+ * `vercel env pull`) and the `storeId` option accept `store_<id>` or `<id>`; the API wants the bare
8
+ * id, case preserved.
9
+ */
10
+ export const normalizeStoreId = (storeId) => storeId.startsWith("store_") ? storeId.slice("store_".length) : storeId;
11
+ /**
12
+ * Validate a store id given in either form (`store_<id>` or `<id>`).
13
+ *
14
+ * @returns The bare id, or none when it is empty or contains whitespace or `_`.
15
+ */
16
+ export const parseStoreId = (storeId) => decodeStoreId(normalizeStoreId(storeId));
17
+ /**
18
+ * The store id embedded in a read-write token (`vercel_blob_rw_<storeId>_<secret>`): the fourth
19
+ * `_`-separated segment, as the SDK's `parseStoreIdFromReadWriteToken`.
20
+ *
21
+ * @returns None when the token has no valid fourth segment.
22
+ */
23
+ export const storeIdFromReadWriteToken = (token) => Option.flatMap(Option.fromUndefinedOr(token.split("_")[3]), decodeStoreId);
24
+ /**
25
+ * The store id embedded in a client token (`vercel_blob_client_<storeId>_<payload>`). The SDK reads
26
+ * it with the same fourth-segment rule as read-write tokens.
27
+ */
28
+ export const storeIdFromClientToken = storeIdFromReadWriteToken;
29
+ const DelegationPayload = Schema.fromJsonString(Schema.Struct({ storeId: Schema.NonEmptyString }));
30
+ const decodeDelegationPayload = Schema.decodeUnknownOption(DelegationPayload);
31
+ /**
32
+ * Read the store id from a delegation token, the public half of a signed token that every presigned
33
+ * URL carries in `vercel-blob-delegation`. The token's payload is the base64url JSON before the first
34
+ * `.`; its `storeId` field is returned without the `store_` prefix.
35
+ *
36
+ * Works in browsers, so a client can address the right store from a presigned payload alone.
37
+ *
38
+ * @returns None when the token has no `.`, its payload is not base64url JSON, or it has no
39
+ * non-empty `storeId` string that is a valid store id.
40
+ */
41
+ export const storeIdFromDelegationToken = (delegationToken) => {
42
+ const dot = delegationToken.indexOf(".");
43
+ if (dot < 0) {
44
+ return Option.none();
45
+ }
46
+ // The SDK's decoder also accepts standard base64 characters; normalize them to base64url.
47
+ const segment = delegationToken
48
+ .slice(0, dot)
49
+ .replace(/\+/g, "-")
50
+ .replace(/\//g, "_")
51
+ .replace(/=+$/, "");
52
+ return Result.getSuccess(Base64Url.decodeString(segment)).pipe(Option.flatMap(decodeDelegationPayload), Option.flatMap((payload) => parseStoreId(payload.storeId)));
53
+ };
54
+ //# sourceMappingURL=store-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-id.js","sourceRoot":"","sources":["../../src/internal/store-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAEtD,MAAM,aAAa,GAAG,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAE1D;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAe,EAAU,EAAE,CAC1D,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AAE1E;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAe,EAA0B,EAAE,CACtE,aAAa,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,KAAa,EAA0B,EAAE,CACjF,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;AAE7E;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GACjC,yBAAyB,CAAC;AAE5B,MAAM,iBAAiB,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;AAEnG,MAAM,uBAAuB,GAAG,MAAM,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;AAE9E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,eAAuB,EAA0B,EAAE;IAC5F,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QACZ,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IACD,0FAA0F;IAC1F,MAAM,OAAO,GAAG,eAAe;SAC5B,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;SACb,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtB,OAAO,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAC5D,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,EACvC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAC3D,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { BlobAccess, StoreId } from "../contracts/blob-domain.ts";
2
+ /** The production Blob API, used unless `VERCEL_BLOB_API_URL` or an option overrides it. */
3
+ export declare const defaultApiUrl = "https://vercel.com/api/blob";
4
+ /** Where a store serves its blobs: `https://<storeId>.<access>.blob.vercel-storage.com/`. */
5
+ export declare const defaultBlobBaseUrl: (storeId: StoreId, access: BlobAccess) => URL;
6
+ /**
7
+ * The URL of the blob at `pathname` under a store's base URL (`BlobConfig.blobBaseUrl`), as the
8
+ * SDK's `constructBlobUrl`: the pathname is appended as is, so URL syntax in it (`?`, `#`) keeps its
9
+ * URL meaning exactly as with the SDK.
10
+ */
11
+ export declare const blobUrl: (baseUrl: URL, pathname: string) => URL;
12
+ /** True for strings the SDK treats as URLs rather than pathnames (`http://` or `https://`). */
13
+ export declare const isUrl: (urlOrPathname: string) => boolean;
14
+ /**
15
+ * Whether `get` may send credentials to `url`: hosts under `.blob.vercel-storage.com`, and, when
16
+ * the API URL is overridden (an emulator or a test server), that API URL's origin.
17
+ *
18
+ * @param apiUrl - The configured API URL; the production default allows no extra origin.
19
+ */
20
+ export declare const isAllowedBlobUrl: (url: URL, apiUrl: URL) => boolean;
21
+ /**
22
+ * The URL that makes browsers download a blob instead of displaying it: the blob URL with
23
+ * `download=1` in its query.
24
+ */
25
+ export declare const downloadUrl: (url: URL | string) => URL;
26
+ //# sourceMappingURL=urls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urls.d.ts","sourceRoot":"","sources":["../../src/internal/urls.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAEvE,4FAA4F;AAC5F,eAAO,MAAM,aAAa,gCAAgC,CAAC;AAE3D,6FAA6F;AAC7F,eAAO,MAAM,kBAAkB,YAAa,OAAO,UAAU,UAAU,KAAG,GACR,CAAC;AAEnE;;;;GAIG;AACH,eAAO,MAAM,OAAO,YAAa,GAAG,YAAY,MAAM,KAAG,GAGxD,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,KAAK,kBAAmB,MAAM,KAAG,OAC+B,CAAC;AAE9E;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,QAAS,GAAG,UAAU,GAAG,KAAG,OAEsB,CAAC;AAEhF;;;GAGG;AACH,eAAO,MAAM,WAAW,QAAS,GAAG,GAAG,MAAM,KAAG,GAI/C,CAAC"}