@putdotio/sdk 9.1.8 → 9.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.
package/README.md CHANGED
@@ -29,11 +29,14 @@ npm install @putdotio/sdk
29
29
 
30
30
  ## Quick Start
31
31
 
32
+ `userAccessToken` in these examples is an already-issued user token from your app or auth flow.
33
+ The SDK itself can be constructed without a token.
34
+
32
35
  ```ts
33
36
  import { createPutioSdkPromiseClient } from "@putdotio/sdk";
34
37
 
35
38
  const sdk = createPutioSdkPromiseClient({
36
- accessToken: process.env.PUTIO_TOKEN,
39
+ accessToken: userAccessToken,
37
40
  });
38
41
 
39
42
  const account = await sdk.account.getInfo({
@@ -46,7 +49,13 @@ The SDK can also be created without a default token:
46
49
  ```ts
47
50
  const sdk = createPutioSdkPromiseClient();
48
51
 
49
- const validation = await sdk.auth.validateToken(process.env.PUTIO_TOKEN!);
52
+ const validation = await sdk.auth.validateToken(tokenToCheck);
53
+ const login = await sdk.auth.login({
54
+ clientId,
55
+ clientSecret,
56
+ password,
57
+ username,
58
+ });
50
59
  ```
51
60
 
52
61
  ## Utilities
@@ -70,7 +79,12 @@ const duration = secondsToReadableDuration(444);
70
79
 
71
80
  ```ts
72
81
  import { Effect } from "effect";
73
- import { createPutioSdkEffectClient, makePutioSdkLiveLayer } from "@putdotio/sdk";
82
+ import {
83
+ PutioSdk,
84
+ createPutioSdkEffectClient,
85
+ makePutioSdkLiveClientLayer,
86
+ makePutioSdkLiveLayer,
87
+ } from "@putdotio/sdk";
74
88
 
75
89
  const sdk = createPutioSdkEffectClient();
76
90
 
@@ -79,17 +93,29 @@ const program = sdk.files
79
93
  per_page: 20,
80
94
  total: 1,
81
95
  })
82
- .pipe(Effect.provide(makePutioSdkLiveLayer({ accessToken: process.env.PUTIO_TOKEN! })));
96
+ .pipe(Effect.provide(makePutioSdkLiveLayer({ accessToken: userAccessToken })));
83
97
 
84
98
  const result = await Effect.runPromise(program);
85
99
  ```
86
100
 
101
+ Effect workflows can also depend on the SDK as a service:
102
+
103
+ ```ts
104
+ const serviceProgram = Effect.gen(function* () {
105
+ const sdk = yield* PutioSdk;
106
+ return yield* sdk.files.list(0, { per_page: 20 });
107
+ }).pipe(Effect.provide(makePutioSdkLiveClientLayer({ accessToken: userAccessToken })));
108
+ ```
109
+
110
+ `makePutioSdkLiveClientLayer(...)` provides the SDK service, SDK config, and default fetch-backed `HttpClient`.
87
111
  `makePutioSdkLiveLayer(...)` provides both the SDK config and the default fetch-backed `HttpClient`.
88
112
  Use `makePutioSdkLayer(...)` only when you want to supply your own `HttpClient` service.
89
113
 
90
114
  ## Side-By-Side Usage
91
115
 
92
- Both client styles expose the same domain surface:
116
+ Both client styles expose the same domain surface. The Promise client also exposes
117
+ `dispose()` for runtime teardown and `files.createUploadFormData(...)` for pure
118
+ FormData construction.
93
119
 
94
120
  ```ts
95
121
  promiseClient.files.list(0, { per_page: 20 });
@@ -169,13 +195,13 @@ Promise consumers receive tagged SDK error objects:
169
195
 
170
196
  ```ts
171
197
  import {
172
- PutioOperationError,
173
- PutioRateLimitError,
174
198
  createPutioSdkPromiseClient,
199
+ isPutioOperationError,
200
+ isPutioRateLimitError,
175
201
  } from "@putdotio/sdk";
176
202
 
177
203
  const sdk = createPutioSdkPromiseClient({
178
- accessToken: process.env.PUTIO_TOKEN,
204
+ accessToken: userAccessToken,
179
205
  });
180
206
 
181
207
  try {
@@ -184,13 +210,13 @@ try {
184
210
  parent_id: 0,
185
211
  });
186
212
  } catch (error) {
187
- if (error instanceof PutioOperationError) {
213
+ if (isPutioOperationError(error)) {
188
214
  if (error.operation === "createFolder") {
189
215
  console.log(error.body.error_type);
190
216
  }
191
217
  }
192
218
 
193
- if (error instanceof PutioRateLimitError) {
219
+ if (isPutioRateLimitError(error)) {
194
220
  console.log(error.retryAfter);
195
221
  }
196
222
  }
@@ -200,25 +226,24 @@ Effect consumers keep errors in the typed error channel instead of throwing:
200
226
 
201
227
  ```ts
202
228
  import { Effect } from "effect";
203
- import { createPutioSdkEffectClient, makePutioSdkLiveLayer } from "@putdotio/sdk";
229
+ import { PutioSdk, makePutioSdkLiveClientLayer } from "@putdotio/sdk";
204
230
 
205
- const sdk = createPutioSdkEffectClient();
206
-
207
- const handled = sdk.files
208
- .createFolder({
231
+ const handled = Effect.gen(function* () {
232
+ const sdk = yield* PutioSdk;
233
+ return yield* sdk.files.createFolder({
209
234
  name: "",
210
235
  parent_id: 0,
211
- })
212
- .pipe(
213
- Effect.catchTag("PutioOperationError", (error) => {
214
- if (error.operation === "createFolder") {
215
- return Effect.succeed(error.body.error_type);
216
- }
217
-
218
- return Effect.fail(error);
219
- }),
220
- Effect.provide(makePutioSdkLiveLayer({ accessToken: process.env.PUTIO_TOKEN! })),
221
- );
236
+ });
237
+ }).pipe(
238
+ Effect.catchTag("PutioOperationError", (error) => {
239
+ if (error.operation === "createFolder") {
240
+ return Effect.succeed(error.body.error_type);
241
+ }
242
+
243
+ return Effect.fail(error);
244
+ }),
245
+ Effect.provide(makePutioSdkLiveClientLayer({ accessToken: userAccessToken })),
246
+ );
222
247
  ```
223
248
 
224
249
  ## Direct File Access
@@ -262,10 +287,9 @@ The Effect client also works well when you want the canonical typed API:
262
287
  ```ts
263
288
  import { useQuery } from "@tanstack/react-query";
264
289
  import { Effect } from "effect";
265
- import { createPutioSdkEffectClient, makePutioSdkLiveLayer } from "@putdotio/sdk";
290
+ import { PutioSdk, makePutioSdkLiveClientLayer } from "@putdotio/sdk";
266
291
 
267
- const sdk = createPutioSdkEffectClient();
268
- const sdkLayer = makePutioSdkLiveLayer({
292
+ const sdkLayer = makePutioSdkLiveClientLayer({
269
293
  accessToken: token,
270
294
  });
271
295
 
@@ -273,21 +297,26 @@ export const useFiles = (parentId: number) =>
273
297
  useQuery({
274
298
  queryKey: ["files", parentId],
275
299
  queryFn: () =>
276
- Effect.runPromise(sdk.files.list(parentId, { per_page: 50 }).pipe(Effect.provide(sdkLayer))),
300
+ Effect.runPromise(
301
+ Effect.gen(function* () {
302
+ const sdk = yield* PutioSdk;
303
+ return yield* sdk.files.list(parentId, { per_page: 50 });
304
+ }).pipe(Effect.provide(sdkLayer)),
305
+ ),
277
306
  });
278
307
  ```
279
308
 
280
309
  ## Docs
281
310
 
282
- - [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md) for package shape and boundaries
283
- - [docs/TESTING.md](./docs/TESTING.md) for local and live verification
284
- - [docs/READINESS.md](./docs/READINESS.md) for domain readiness
285
- - [docs/RELEASE.md](./docs/RELEASE.md) for release automation
286
- - [SECURITY.md](./SECURITY.md) for private-first vulnerability disclosure
311
+ - [Architecture](./docs/ARCHITECTURE.md) for package shape and boundaries
312
+ - [Testing](./docs/TESTING.md) for local and live verification
313
+ - [Readiness](./docs/READINESS.md) for domain readiness
314
+ - [Distribution](./docs/DISTRIBUTION.md) for release automation
315
+ - [Security](./SECURITY.md) for private-first vulnerability disclosure
287
316
 
288
317
  ## Contributing
289
318
 
290
- Contributor setup, validation, and live-test workflow live in [CONTRIBUTING.md](./CONTRIBUTING.md).
319
+ Contributor setup, validation, and live-test workflow live in [Contributing](./CONTRIBUTING.md).
291
320
 
292
321
  ## License
293
322
 
@@ -1,10 +1,10 @@
1
1
  import { Context, Data, Effect, Layer, Option, Schema } from "effect";
2
- import { FetchHttpClient, Headers, HttpClient, HttpClientRequest, HttpClientResponse } from "@effect/platform";
2
+ import { FetchHttpClient, Headers, HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http";
3
3
  //#region src/core/errors.ts
4
4
  const PutioErrorEnvelopeSchema = Schema.Struct({
5
5
  error_message: Schema.optional(Schema.String),
6
6
  error_type: Schema.optional(Schema.String),
7
- status_code: Schema.optional(Schema.Number.pipe(Schema.int())),
7
+ status_code: Schema.optional(Schema.Int),
8
8
  details: Schema.optional(Schema.Unknown)
9
9
  });
10
10
  const isKnownContractMatch = (contract, error) => {
@@ -16,6 +16,16 @@ const isKnownContractMatch = (contract, error) => {
16
16
  return false;
17
17
  };
18
18
  const isMatchableApiError = (error) => error._tag === "PutioApiError" || error._tag === "PutioAuthError";
19
+ const isRecord = (value) => typeof value === "object" && value !== null;
20
+ const hasOptionalString = (record, key) => !(key in record) || record[key] === void 0 || typeof record[key] === "string";
21
+ const hasOptionalInteger = (record, key) => !(key in record) || record[key] === void 0 || typeof record[key] === "number" && Number.isInteger(record[key]);
22
+ const isKnownOperationErrorContract = (value) => isRecord(value) && (typeof value.errorType === "string" || typeof value.statusCode === "number") && hasOptionalString(value, "errorType") && hasOptionalInteger(value, "statusCode");
23
+ const isOperationReason = (value) => {
24
+ if (!isRecord(value)) return false;
25
+ if (value.kind === "error_type") return typeof value.errorType === "string";
26
+ if (value.kind === "status_code") return typeof value.statusCode === "number";
27
+ return false;
28
+ };
19
29
  function toOperationReason(contract) {
20
30
  if (contract.errorType !== void 0) return {
21
31
  kind: "error_type",
@@ -29,12 +39,30 @@ function toOperationReason(contract) {
29
39
  var PutioTransportError = class extends Data.TaggedError("PutioTransportError") {};
30
40
  var PutioConfigurationError = class extends Data.TaggedError("PutioConfigurationError") {};
31
41
  var PutioValidationError = class extends Data.TaggedError("PutioValidationError") {};
32
- var PutioApiError = class extends Data.TaggedError("PutioApiError") {};
33
- var PutioAuthError = class extends Data.TaggedError("PutioAuthError") {};
34
- var PutioRateLimitError = class extends Data.TaggedError("PutioRateLimitError") {};
42
+ const PutioResponseErrorFields = {
43
+ status: Schema.Int,
44
+ body: PutioErrorEnvelopeSchema
45
+ };
46
+ var PutioApiError = class extends Schema.TaggedErrorClass()("PutioApiError", { ...PutioResponseErrorFields }) {};
47
+ var PutioAuthError = class extends Schema.TaggedErrorClass()("PutioAuthError", { ...PutioResponseErrorFields }) {};
48
+ var PutioRateLimitError = class extends Schema.TaggedErrorClass()("PutioRateLimitError", {
49
+ ...PutioResponseErrorFields,
50
+ action: Schema.optional(Schema.String),
51
+ id: Schema.optional(Schema.String),
52
+ limit: Schema.optional(Schema.String),
53
+ remaining: Schema.optional(Schema.String),
54
+ retryAfter: Schema.optional(Schema.String),
55
+ reset: Schema.optional(Schema.String)
56
+ }) {};
35
57
  var PutioOperationError = class extends Data.TaggedError("PutioOperationError") {};
36
58
  const definePutioOperationErrorSpec = (spec) => spec;
37
- const decodePutioErrorEnvelope = Schema.decodeUnknown(PutioErrorEnvelopeSchema);
59
+ const decodePutioErrorEnvelope = Schema.decodeUnknownEffect(PutioErrorEnvelopeSchema);
60
+ const isPutioErrorEnvelope = (value) => isRecord(value) && hasOptionalString(value, "error_message") && hasOptionalString(value, "error_type") && hasOptionalInteger(value, "status_code");
61
+ const hasStatusAndBody = (value, tag) => isRecord(value) && value._tag === tag && typeof value.status === "number" && isPutioErrorEnvelope(value.body);
62
+ const isPutioApiError = (value) => hasStatusAndBody(value, "PutioApiError");
63
+ const isPutioAuthError = (value) => hasStatusAndBody(value, "PutioAuthError");
64
+ const isPutioRateLimitError = (value) => hasStatusAndBody(value, "PutioRateLimitError") && isRecord(value) && hasOptionalString(value, "action") && hasOptionalString(value, "id") && hasOptionalString(value, "limit") && hasOptionalString(value, "remaining") && hasOptionalString(value, "retryAfter") && hasOptionalString(value, "reset");
65
+ const isPutioOperationError = (value) => isRecord(value) && value._tag === "PutioOperationError" && isPutioErrorEnvelope(value.body) && isKnownOperationErrorContract(value.contract) && typeof value.domain === "string" && typeof value.operation === "string" && isOperationReason(value.reason) && typeof value.status === "number";
38
66
  const fallbackPutioErrorEnvelope = (status) => ({
39
67
  error_message: `put.io API request failed with status ${status}`,
40
68
  status_code: status
@@ -94,7 +122,7 @@ const DEFAULT_PUTIO_UPLOAD_BASE_URL = "https://upload.put.io";
94
122
  const DEFAULT_PUTIO_WEB_APP_URL = "https://app.put.io";
95
123
  //#endregion
96
124
  //#region src/core/http.ts
97
- var PutioSdkConfig = class extends Context.Tag("PutioSdkConfig")() {};
125
+ var PutioSdkConfig = class extends Context.Service()("PutioSdkConfig") {};
98
126
  const makePutioSdkConfig = (config) => ({
99
127
  accessToken: config.accessToken,
100
128
  baseUrl: config.baseUrl ?? "https://api.put.io",
@@ -103,13 +131,20 @@ const makePutioSdkConfig = (config) => ({
103
131
  });
104
132
  const makePutioSdkLayer = (config) => Layer.succeed(PutioSdkConfig, makePutioSdkConfig(config));
105
133
  const makePutioSdkLiveLayer = (config) => Layer.mergeAll(makePutioSdkLayer(config), FetchHttpClient.layer);
134
+ const encodePathSegment = (value) => encodeURIComponent(String(value));
135
+ const absoluteUrlPattern = /^(?:[a-z][a-z\d+.-]*:|\/\/)/i;
136
+ const normalizeApiPath = (path) => {
137
+ if (absoluteUrlPattern.test(path)) throw mapConfigurationError("SDK API request paths must be relative to the configured baseUrl");
138
+ return path.startsWith("/") ? path : `/${path}`;
139
+ };
106
140
  const buildPutioUrl = (baseUrl, path, query) => {
107
- const url = new URL(path, baseUrl);
141
+ const url = new URL(normalizeApiPath(path), baseUrl);
108
142
  if (query) {
109
143
  for (const [key, value] of Object.entries(query)) if (value !== void 0 && value !== null) url.searchParams.set(key, String(value));
110
144
  }
111
145
  return url.toString();
112
146
  };
147
+ const mapUrlBuildError = (cause) => cause instanceof PutioConfigurationError ? cause : mapConfigurationError(cause);
113
148
  const OkResponseSchema = Schema.Struct({ status: Schema.Literal("OK") });
114
149
  const isSuccessStatus = (status) => status >= 200 && status < 300;
115
150
  const decodeSuccessJson = (schema, response) => HttpClientResponse.schemaBodyJson(schema)(response).pipe(Effect.mapError(mapDecodeErrorToValidationError));
@@ -157,7 +192,10 @@ const makeRequest = (url, options, authorization) => Effect.gen(function* () {
157
192
  const executeRequest = (options) => Effect.gen(function* () {
158
193
  const config = yield* PutioSdkConfig;
159
194
  const authorization = yield* resolveAuthorization(config, options.auth);
160
- const request = yield* makeRequest(buildPutioUrl(options.baseUrl ?? config.baseUrl ?? "https://api.put.io", options.path, options.query), options, authorization);
195
+ const request = yield* makeRequest(yield* Effect.try({
196
+ try: () => buildPutioUrl(options.baseUrl ?? config.baseUrl ?? "https://api.put.io", options.path, options.query),
197
+ catch: mapUrlBuildError
198
+ }), options, authorization);
161
199
  return yield* HttpClient.execute(request).pipe(Effect.mapError(mapTransportError));
162
200
  });
163
201
  const requestJson = (schema, options) => executeRequest(options).pipe(Effect.flatMap((response) => isSuccessStatus(response.status) ? decodeSuccessJson(schema, response) : decodeFailure(response, response.headers).pipe(Effect.flatMap(Effect.fail))));
@@ -177,6 +215,6 @@ const toCursorSelectionForm = (selection, idsFieldName) => {
177
215
  };
178
216
  };
179
217
  //#endregion
180
- export { mapDecodeErrorToValidationError as A, PutioTransportError as C, fallbackPutioErrorEnvelope as D, definePutioOperationErrorSpec as E, parseErrorBody as M, responseRateLimitHeaders as N, makeResponseError as O, withOperationErrors as P, PutioRateLimitError as S, decodePutioErrorEnvelope as T, PutioApiError as _, buildPutioUrl as a, PutioErrorEnvelopeSchema as b, makePutioSdkLiveLayer as c, requestVoid as d, selectJsonField as f, DEFAULT_PUTIO_WEB_APP_URL as g, DEFAULT_PUTIO_UPLOAD_BASE_URL as h, PutioSdkConfig as i, mapTransportError as j, mapConfigurationError as k, requestArrayBuffer as l, DEFAULT_PUTIO_API_BASE_URL as m, toCursorSelectionForm as n, makePutioSdkConfig as o, selectJsonFields as p, OkResponseSchema as r, makePutioSdkLayer as s, joinCsv as t, requestJson as u, PutioAuthError as v, PutioValidationError as w, PutioOperationError as x, PutioConfigurationError as y };
218
+ export { isPutioAuthError as A, withOperationErrors as B, PutioRateLimitError as C, definePutioOperationErrorSpec as D, decodePutioErrorEnvelope as E, mapConfigurationError as F, mapDecodeErrorToValidationError as I, mapTransportError as L, isPutioOperationError as M, isPutioRateLimitError as N, fallbackPutioErrorEnvelope as O, makeResponseError as P, parseErrorBody as R, PutioOperationError as S, PutioValidationError as T, DEFAULT_PUTIO_WEB_APP_URL as _, buildPutioUrl as a, PutioConfigurationError as b, makePutioSdkLayer as c, requestJson as d, requestVoid as f, DEFAULT_PUTIO_UPLOAD_BASE_URL as g, DEFAULT_PUTIO_API_BASE_URL as h, PutioSdkConfig as i, isPutioErrorEnvelope as j, isPutioApiError as k, makePutioSdkLiveLayer as l, selectJsonFields as m, toCursorSelectionForm as n, encodePathSegment as o, selectJsonField as p, OkResponseSchema as r, makePutioSdkConfig as s, joinCsv as t, requestArrayBuffer as u, PutioApiError as v, PutioTransportError as w, PutioErrorEnvelopeSchema as x, PutioAuthError as y, responseRateLimitHeaders as z };
181
219
 
182
- //# sourceMappingURL=forms-BoZMwEUj.js.map
220
+ //# sourceMappingURL=forms-NEv3jqmj.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forms-NEv3jqmj.js","names":[],"sources":["../src/core/errors.ts","../src/core/defaults.ts","../src/core/http.ts","../src/core/forms.ts"],"sourcesContent":["import { Data, Effect, Option, Schema } from \"effect\";\nimport { Headers } from \"effect/unstable/http\";\n\nexport const PutioErrorEnvelopeSchema = Schema.Struct({\n error_message: Schema.optional(Schema.String),\n error_type: Schema.optional(Schema.String),\n status_code: Schema.optional(Schema.Int),\n details: Schema.optional(Schema.Unknown),\n});\n\nexport type PutioErrorEnvelope = Schema.Schema.Type<typeof PutioErrorEnvelopeSchema>;\n\nexport interface PutioKnownErrorContract<\n TType extends string = string,\n TStatus extends number = number,\n> {\n readonly errorType?: TType;\n readonly statusCode?: TStatus;\n}\n\ntype ContractErrorType<TContract extends PutioKnownErrorContract> =\n TContract extends PutioKnownErrorContract<infer TType, number> ? TType : never;\n\ntype ContractStatusCode<TContract extends PutioKnownErrorContract> =\n TContract extends PutioKnownErrorContract<string, infer TStatus> ? TStatus : never;\n\nexport type PutioTypedErrorEnvelope<TContract extends PutioKnownErrorContract> = Omit<\n PutioErrorEnvelope,\n \"error_message\" | \"error_type\" | \"status_code\"\n> & {\n readonly error_message?: string;\n readonly error_type?: [ContractErrorType<TContract>] extends [never]\n ? string\n : ContractErrorType<TContract>;\n readonly status_code?: [ContractStatusCode<TContract>] extends [never]\n ? number\n : ContractStatusCode<TContract>;\n};\n\nexport interface PutioOperationErrorSpec<\n TDomain extends string = string,\n TOperation extends string = string,\n TContracts extends ReadonlyArray<PutioKnownErrorContract> =\n ReadonlyArray<PutioKnownErrorContract>,\n> {\n readonly domain: TDomain;\n readonly operation: TOperation;\n readonly knownErrors: TContracts;\n}\n\ntype OperationContractOf<TSpec extends PutioOperationErrorSpec> = Extract<\n TSpec[\"knownErrors\"][number],\n PutioKnownOperationErrorContract\n>;\n\ntype OperationContractOfParts<\n TDomain extends string,\n TOperation extends string,\n TContracts extends ReadonlyArray<PutioKnownErrorContract>,\n> = OperationContractOf<PutioOperationErrorSpec<TDomain, TOperation, TContracts>>;\n\ntype PutioOperationErrorReason<TContract extends PutioKnownErrorContract> = TContract extends {\n readonly errorType: infer TType extends string;\n}\n ? {\n readonly kind: \"error_type\";\n readonly errorType: TType;\n }\n : TContract extends { readonly statusCode: infer TStatus extends number }\n ? {\n readonly kind: \"status_code\";\n readonly statusCode: TStatus;\n }\n : never;\n\nexport type PutioKnownOperationErrorContract =\n | {\n readonly errorType: string;\n readonly statusCode?: number;\n }\n | {\n readonly errorType?: undefined;\n readonly statusCode: number;\n };\n\nconst isKnownContractMatch = <TContract extends PutioKnownErrorContract>(\n contract: TContract,\n error: PutioApiError | PutioAuthError,\n): contract is Extract<TContract, PutioKnownOperationErrorContract> => {\n if (contract.errorType !== undefined) {\n if (error.body.error_type !== contract.errorType) {\n return false;\n }\n\n return contract.statusCode === undefined || error.status === contract.statusCode;\n }\n\n if (contract.statusCode !== undefined) {\n return error.status === contract.statusCode;\n }\n\n return false;\n};\n\nconst isMatchableApiError = (error: PutioSdkError): error is PutioApiError | PutioAuthError =>\n error._tag === \"PutioApiError\" || error._tag === \"PutioAuthError\";\n\nconst isRecord = (value: unknown): value is Readonly<Record<string, unknown>> =>\n typeof value === \"object\" && value !== null;\n\nconst hasOptionalString = (record: Readonly<Record<string, unknown>>, key: string): boolean =>\n !(key in record) || record[key] === undefined || typeof record[key] === \"string\";\n\nconst hasOptionalInteger = (record: Readonly<Record<string, unknown>>, key: string): boolean =>\n !(key in record) ||\n record[key] === undefined ||\n (typeof record[key] === \"number\" && Number.isInteger(record[key]));\n\nconst isKnownOperationErrorContract = (value: unknown): value is PutioKnownOperationErrorContract =>\n isRecord(value) &&\n (typeof value.errorType === \"string\" || typeof value.statusCode === \"number\") &&\n hasOptionalString(value, \"errorType\") &&\n hasOptionalInteger(value, \"statusCode\");\n\nconst isOperationReason = (\n value: unknown,\n): value is PutioOperationErrorReason<PutioKnownOperationErrorContract> => {\n if (!isRecord(value)) {\n return false;\n }\n\n if (value.kind === \"error_type\") {\n return typeof value.errorType === \"string\";\n }\n\n if (value.kind === \"status_code\") {\n return typeof value.statusCode === \"number\";\n }\n\n return false;\n};\n\nfunction toOperationReason<TContract extends PutioKnownOperationErrorContract>(\n contract: TContract,\n): PutioOperationErrorReason<TContract> {\n if (contract.errorType !== undefined) {\n return {\n kind: \"error_type\",\n errorType: contract.errorType,\n } as PutioOperationErrorReason<TContract>;\n }\n\n return {\n kind: \"status_code\",\n statusCode: contract.statusCode,\n } as PutioOperationErrorReason<TContract>;\n}\n\nexport class PutioTransportError extends Data.TaggedError(\"PutioTransportError\")<{\n readonly cause: unknown;\n}> {}\n\nexport class PutioConfigurationError extends Data.TaggedError(\"PutioConfigurationError\")<{\n readonly cause: unknown;\n}> {}\n\nexport class PutioValidationError extends Data.TaggedError(\"PutioValidationError\")<{\n readonly cause: unknown;\n}> {}\n\nconst PutioResponseErrorFields = {\n status: Schema.Int,\n body: PutioErrorEnvelopeSchema,\n};\n\nexport class PutioApiError extends Schema.TaggedErrorClass<PutioApiError>()(\"PutioApiError\", {\n ...PutioResponseErrorFields,\n}) {}\n\nexport class PutioAuthError extends Schema.TaggedErrorClass<PutioAuthError>()(\"PutioAuthError\", {\n ...PutioResponseErrorFields,\n}) {}\n\nexport class PutioRateLimitError extends Schema.TaggedErrorClass<PutioRateLimitError>()(\n \"PutioRateLimitError\",\n {\n ...PutioResponseErrorFields,\n action: Schema.optional(Schema.String),\n id: Schema.optional(Schema.String),\n limit: Schema.optional(Schema.String),\n remaining: Schema.optional(Schema.String),\n retryAfter: Schema.optional(Schema.String),\n reset: Schema.optional(Schema.String),\n },\n) {}\n\nexport class PutioOperationError<\n TDomain extends string,\n TOperation extends string,\n TContract extends PutioKnownOperationErrorContract,\n> extends Data.TaggedError(\"PutioOperationError\")<{\n readonly body: PutioTypedErrorEnvelope<TContract>;\n readonly contract: TContract;\n readonly domain: TDomain;\n readonly operation: TOperation;\n readonly reason: PutioOperationErrorReason<TContract>;\n readonly status: number;\n}> {}\n\nexport type PutioSdkError =\n | PutioConfigurationError\n | PutioTransportError\n | PutioValidationError\n | PutioApiError\n | PutioAuthError\n | PutioRateLimitError;\n\nexport type PutioUnhandledSdkError =\n | PutioConfigurationError\n | PutioTransportError\n | PutioValidationError\n | PutioApiError\n | PutioAuthError\n | PutioRateLimitError;\n\nexport type PutioOperationErrorFromSpec<TSpec extends PutioOperationErrorSpec> =\n PutioOperationError<TSpec[\"domain\"], TSpec[\"operation\"], OperationContractOf<TSpec>>;\n\nexport type PutioOperationFailure<TSpec extends PutioOperationErrorSpec> =\n | PutioUnhandledSdkError\n | PutioOperationErrorFromSpec<TSpec>;\n\nexport type AnyPutioOperationError = PutioOperationError<\n string,\n string,\n PutioKnownOperationErrorContract\n>;\n\nexport const definePutioOperationErrorSpec = <\n const TDomain extends string,\n const TOperation extends string,\n const TContracts extends ReadonlyArray<PutioKnownErrorContract>,\n>(\n spec: PutioOperationErrorSpec<TDomain, TOperation, TContracts>,\n) => spec;\n\nexport const decodePutioErrorEnvelope = Schema.decodeUnknownEffect(PutioErrorEnvelopeSchema);\n\nexport const isPutioErrorEnvelope = (value: unknown): value is PutioErrorEnvelope =>\n isRecord(value) &&\n hasOptionalString(value, \"error_message\") &&\n hasOptionalString(value, \"error_type\") &&\n hasOptionalInteger(value, \"status_code\");\n\nconst hasStatusAndBody = <TTag extends string>(\n value: unknown,\n tag: TTag,\n): value is {\n readonly _tag: TTag;\n readonly body: PutioErrorEnvelope;\n readonly status: number;\n} =>\n isRecord(value) &&\n value._tag === tag &&\n typeof value.status === \"number\" &&\n isPutioErrorEnvelope(value.body);\n\nexport const isPutioApiError = (value: unknown): value is PutioApiError =>\n hasStatusAndBody(value, \"PutioApiError\");\n\nexport const isPutioAuthError = (value: unknown): value is PutioAuthError =>\n hasStatusAndBody(value, \"PutioAuthError\");\n\nexport const isPutioRateLimitError = (value: unknown): value is PutioRateLimitError =>\n hasStatusAndBody(value, \"PutioRateLimitError\") &&\n isRecord(value) &&\n hasOptionalString(value, \"action\") &&\n hasOptionalString(value, \"id\") &&\n hasOptionalString(value, \"limit\") &&\n hasOptionalString(value, \"remaining\") &&\n hasOptionalString(value, \"retryAfter\") &&\n hasOptionalString(value, \"reset\");\n\nexport const isPutioOperationError = (value: unknown): value is AnyPutioOperationError =>\n isRecord(value) &&\n value._tag === \"PutioOperationError\" &&\n isPutioErrorEnvelope(value.body) &&\n isKnownOperationErrorContract(value.contract) &&\n typeof value.domain === \"string\" &&\n typeof value.operation === \"string\" &&\n isOperationReason(value.reason) &&\n typeof value.status === \"number\";\n\nexport const fallbackPutioErrorEnvelope = (status: number): PutioErrorEnvelope => ({\n error_message: `put.io API request failed with status ${status}`,\n status_code: status,\n});\n\nexport const responseRateLimitHeaders = (headers: Headers.Headers) => ({\n action: Option.getOrUndefined(Headers.get(headers, \"x-ratelimit-action\")),\n id: Option.getOrUndefined(Headers.get(headers, \"x-ratelimit-id\")),\n limit: Option.getOrUndefined(Headers.get(headers, \"x-ratelimit-limit\")),\n remaining: Option.getOrUndefined(Headers.get(headers, \"x-ratelimit-remaining\")),\n retryAfter: Option.getOrUndefined(Headers.get(headers, \"retry-after\")),\n reset: Option.getOrUndefined(Headers.get(headers, \"x-ratelimit-reset\")),\n});\n\nexport const mapDecodeErrorToValidationError = (cause: unknown) =>\n new PutioValidationError({ cause });\n\nexport const mapConfigurationError = (cause: unknown) => new PutioConfigurationError({ cause });\n\nexport const mapTransportError = (cause: unknown) => new PutioTransportError({ cause });\n\nexport const makeResponseError = (\n status: number,\n headers: Headers.Headers,\n body: PutioErrorEnvelope,\n): PutioSdkError => {\n if (status === 429) {\n return new PutioRateLimitError({\n status,\n body,\n ...responseRateLimitHeaders(headers),\n });\n }\n\n if (status === 401 || status === 403) {\n return new PutioAuthError({ status, body });\n }\n\n return new PutioApiError({ status, body });\n};\n\nexport const parseErrorBody = (status: number, json: unknown) =>\n decodePutioErrorEnvelope(json).pipe(\n Effect.orElseSucceed(() => fallbackPutioErrorEnvelope(status)),\n );\n\nexport function withOperationErrors<\n A,\n E extends PutioSdkError,\n R,\n const TDomain extends string,\n const TOperation extends string,\n const TContracts extends ReadonlyArray<PutioKnownErrorContract>,\n>(\n effect: Effect.Effect<A, E, R>,\n spec: PutioOperationErrorSpec<TDomain, TOperation, TContracts>,\n): Effect.Effect<\n A,\n | E\n | PutioOperationError<\n TDomain,\n TOperation,\n OperationContractOfParts<TDomain, TOperation, TContracts>\n >,\n R\n>;\nexport function withOperationErrors<\n const TDomain extends string,\n const TOperation extends string,\n const TContracts extends ReadonlyArray<PutioKnownErrorContract>,\n>(\n spec: PutioOperationErrorSpec<TDomain, TOperation, TContracts>,\n): <A, E extends PutioSdkError, R>(\n effect: Effect.Effect<A, E, R>,\n) => Effect.Effect<\n A,\n | E\n | PutioOperationError<\n TDomain,\n TOperation,\n OperationContractOfParts<TDomain, TOperation, TContracts>\n >,\n R\n>;\nexport function withOperationErrors<\n A,\n E extends PutioSdkError,\n R,\n const TDomain extends string,\n const TOperation extends string,\n const TContracts extends ReadonlyArray<PutioKnownErrorContract>,\n>(\n effectOrSpec: Effect.Effect<A, E, R> | PutioOperationErrorSpec<TDomain, TOperation, TContracts>,\n maybeSpec?: PutioOperationErrorSpec<TDomain, TOperation, TContracts>,\n):\n | Effect.Effect<\n A,\n | E\n | PutioOperationError<\n TDomain,\n TOperation,\n OperationContractOfParts<TDomain, TOperation, TContracts>\n >,\n R\n >\n | (<A2, E2 extends PutioSdkError, R2>(\n effect: Effect.Effect<A2, E2, R2>,\n ) => Effect.Effect<\n A2,\n | E2\n | PutioOperationError<\n TDomain,\n TOperation,\n OperationContractOfParts<TDomain, TOperation, TContracts>\n >,\n R2\n >) {\n if (maybeSpec === undefined) {\n const spec = effectOrSpec as PutioOperationErrorSpec<TDomain, TOperation, TContracts>;\n\n return <A2, E2 extends PutioSdkError, R2>(effect: Effect.Effect<A2, E2, R2>) =>\n withOperationErrors(effect, spec);\n }\n\n const effect = effectOrSpec as Effect.Effect<A, E, R>;\n const spec = maybeSpec;\n\n return effect.pipe(\n Effect.mapError((error) => {\n if (!isMatchableApiError(error)) {\n return error;\n }\n\n const contract = spec.knownErrors.find((candidate) => isKnownContractMatch(candidate, error));\n\n if (!contract) {\n return error;\n }\n\n return new PutioOperationError({\n body: error.body as PutioTypedErrorEnvelope<\n OperationContractOfParts<TDomain, TOperation, TContracts>\n >,\n contract,\n domain: spec.domain,\n operation: spec.operation,\n reason: toOperationReason(contract),\n status: error.status,\n });\n }),\n );\n}\n","export const DEFAULT_PUTIO_API_BASE_URL = \"https://api.put.io\";\nexport const DEFAULT_PUTIO_UPLOAD_BASE_URL = \"https://upload.put.io\";\nexport const DEFAULT_PUTIO_WEB_APP_URL = \"https://app.put.io\";\n","import { Context, Effect, Layer, Schema } from \"effect\";\nimport {\n FetchHttpClient,\n Headers,\n HttpClient,\n HttpClientRequest,\n HttpClientResponse,\n} from \"effect/unstable/http\";\n\nimport {\n DEFAULT_PUTIO_API_BASE_URL,\n DEFAULT_PUTIO_UPLOAD_BASE_URL,\n DEFAULT_PUTIO_WEB_APP_URL,\n} from \"./defaults.js\";\nimport {\n fallbackPutioErrorEnvelope,\n makeResponseError,\n mapConfigurationError,\n mapDecodeErrorToValidationError,\n mapTransportError,\n parseErrorBody,\n PutioConfigurationError,\n type PutioSdkError,\n} from \"./errors.js\";\n\nexport type PutioQueryValue = string | number | boolean | null | undefined;\n\nexport type PutioQuery = Readonly<Record<string, PutioQueryValue>>;\n\nexport type PutioPathSegment = string | number | boolean;\n\nexport interface PutioSdkConfigShape {\n readonly accessToken?: string;\n readonly baseUrl?: string | URL;\n readonly uploadBaseUrl?: string | URL;\n readonly webAppUrl?: string | URL;\n}\n\nexport class PutioSdkConfig extends Context.Service<PutioSdkConfig, PutioSdkConfigShape>()(\n \"PutioSdkConfig\",\n) {}\n\nexport type PutioSdkContext = PutioSdkConfig | HttpClient.HttpClient;\n\nexport const makePutioSdkConfig = (config: PutioSdkConfigShape): PutioSdkConfigShape => ({\n accessToken: config.accessToken,\n baseUrl: config.baseUrl ?? DEFAULT_PUTIO_API_BASE_URL,\n uploadBaseUrl: config.uploadBaseUrl ?? DEFAULT_PUTIO_UPLOAD_BASE_URL,\n webAppUrl: config.webAppUrl ?? DEFAULT_PUTIO_WEB_APP_URL,\n});\n\nexport const makePutioSdkLayer = (config: PutioSdkConfigShape) =>\n Layer.succeed(PutioSdkConfig, makePutioSdkConfig(config));\n\nexport const makePutioSdkLiveLayer = (config: PutioSdkConfigShape) =>\n Layer.mergeAll(makePutioSdkLayer(config), FetchHttpClient.layer);\n\nexport const encodePathSegment = (value: PutioPathSegment): string =>\n encodeURIComponent(String(value));\n\nconst absoluteUrlPattern = /^(?:[a-z][a-z\\d+.-]*:|\\/\\/)/i;\n\nconst normalizeApiPath = (path: string): string => {\n if (absoluteUrlPattern.test(path)) {\n throw mapConfigurationError(\"SDK API request paths must be relative to the configured baseUrl\");\n }\n\n return path.startsWith(\"/\") ? path : `/${path}`;\n};\n\nexport const buildPutioUrl = (baseUrl: string | URL, path: string, query?: PutioQuery): string => {\n const url = new URL(normalizeApiPath(path), baseUrl);\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n return url.toString();\n};\n\nconst mapUrlBuildError = (cause: unknown) =>\n cause instanceof PutioConfigurationError ? cause : mapConfigurationError(cause);\n\nexport const OkResponseSchema = Schema.Struct({\n status: Schema.Literal(\"OK\"),\n});\n\nexport type PutioAuth =\n | { readonly type: \"config-token\" }\n | { readonly type: \"token\"; readonly token: string }\n | { readonly type: \"basic\"; readonly username: string; readonly password: string }\n | { readonly type: \"none\" };\n\ntype PutioRequestBody =\n | { readonly type: \"none\" }\n | { readonly type: \"json\"; readonly value: unknown }\n | { readonly type: \"form\"; readonly value: Record<string, unknown> }\n | { readonly type: \"form-data\"; readonly value: FormData };\n\ninterface PutioRequestOptions {\n readonly method: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n readonly path: string;\n readonly baseUrl?: string | URL;\n readonly query?: PutioQuery;\n readonly headers?: Headers.Input;\n readonly auth?: PutioAuth;\n readonly body?: PutioRequestBody;\n}\n\nconst isSuccessStatus = (status: number) => status >= 200 && status < 300;\n\nconst decodeSuccessJson = <S extends Schema.Top>(\n schema: S,\n response: HttpClientResponse.HttpClientResponse,\n) =>\n HttpClientResponse.schemaBodyJson(schema)(response).pipe(\n Effect.mapError(mapDecodeErrorToValidationError),\n );\n\nconst decodeFailure = (response: HttpClientResponse.HttpClientResponse, headers: Headers.Headers) =>\n response.json.pipe(\n Effect.flatMap((json) => parseErrorBody(response.status, json)),\n Effect.orElseSucceed(() => fallbackPutioErrorEnvelope(response.status)),\n Effect.map((body) => makeResponseError(response.status, headers, body)),\n );\n\nconst toBasicAuthorization = (username: string, password: string) => {\n if (typeof globalThis.btoa === \"function\") {\n return `Basic ${globalThis.btoa(`${username}:${password}`)}`;\n }\n\n throw mapConfigurationError(\n \"This runtime does not provide btoa(), so Basic auth cannot be encoded safely\",\n );\n};\n\nconst resolveAuthorization = (\n config: PutioSdkConfigShape,\n auth: PutioAuth | undefined,\n): Effect.Effect<string | undefined, PutioSdkError> => {\n const resolvedAuth = auth ?? { type: \"config-token\" as const };\n\n switch (resolvedAuth.type) {\n case \"none\":\n return Effect.succeed(undefined);\n case \"token\":\n return Effect.succeed(`Token ${resolvedAuth.token}`);\n case \"basic\":\n return Effect.try({\n try: () => toBasicAuthorization(resolvedAuth.username, resolvedAuth.password),\n catch: mapConfigurationError,\n });\n case \"config-token\":\n if (!config.accessToken) {\n return Effect.fail(\n mapConfigurationError(\n \"This endpoint requires an access token, but PutioSdkConfig.accessToken is missing\",\n ),\n );\n }\n\n return Effect.succeed(`Token ${config.accessToken}`);\n }\n};\n\nconst normalizeFormValue = (value: unknown): string => {\n if (value === null || value === undefined) {\n return \"\";\n }\n\n if (typeof value === \"string\") {\n return value;\n }\n\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n\n return JSON.stringify(value);\n};\n\nconst withBody = (\n request: HttpClientRequest.HttpClientRequest,\n body: PutioRequestBody,\n): Effect.Effect<HttpClientRequest.HttpClientRequest, PutioSdkError> => {\n switch (body.type) {\n case \"none\":\n return Effect.succeed(request);\n case \"json\":\n return HttpClientRequest.bodyJson(request, body.value).pipe(\n Effect.mapError(mapDecodeErrorToValidationError),\n );\n case \"form\":\n return Effect.succeed(\n HttpClientRequest.bodyUrlParams(\n request,\n Object.fromEntries(\n Object.entries(body.value).flatMap(([key, value]) =>\n value === undefined ? [] : [[key, normalizeFormValue(value)]],\n ),\n ),\n ),\n );\n case \"form-data\":\n return Effect.succeed(HttpClientRequest.bodyFormData(request, body.value));\n }\n};\n\nconst makeRequest = (url: string, options: PutioRequestOptions, authorization?: string) =>\n Effect.gen(function* () {\n const headers = authorization\n ? Headers.set(Headers.fromInput(options.headers), \"authorization\", authorization)\n : Headers.fromInput(options.headers);\n\n const body = options.body ?? { type: \"none\" as const };\n const request = HttpClientRequest.make(options.method)(url, {\n acceptJson: true,\n headers,\n });\n\n return yield* withBody(request, body);\n });\n\nconst executeRequest = (options: PutioRequestOptions) =>\n Effect.gen(function* () {\n const config = yield* PutioSdkConfig;\n const authorization = yield* resolveAuthorization(config, options.auth);\n const url = yield* Effect.try({\n try: () =>\n buildPutioUrl(\n options.baseUrl ?? config.baseUrl ?? DEFAULT_PUTIO_API_BASE_URL,\n options.path,\n options.query,\n ),\n catch: mapUrlBuildError,\n });\n const request = yield* makeRequest(url, options, authorization);\n\n return yield* HttpClient.execute(request).pipe(Effect.mapError(mapTransportError));\n });\n\nexport const requestJson = <S extends Schema.Top>(\n schema: S,\n options: PutioRequestOptions,\n): Effect.Effect<S[\"Type\"], PutioSdkError, PutioSdkContext | S[\"DecodingServices\"]> =>\n executeRequest(options).pipe(\n Effect.flatMap((response) =>\n isSuccessStatus(response.status)\n ? decodeSuccessJson(schema, response)\n : decodeFailure(response, response.headers).pipe(Effect.flatMap(Effect.fail)),\n ),\n );\n\nexport const selectJsonField =\n <K extends string>(field: K) =>\n <A extends { readonly [P in K]: unknown }, E, R>(\n effect: Effect.Effect<A, E, R>,\n ): Effect.Effect<A[K], E, R> =>\n effect.pipe(Effect.map((value) => value[field]));\n\nexport const selectJsonFields =\n <const K extends readonly string[]>(...fields: K) =>\n <A extends { readonly [P in K[number]]: unknown }, E, R>(\n effect: Effect.Effect<A, E, R>,\n ): Effect.Effect<Pick<A, K[number]>, E, R> =>\n effect.pipe(\n Effect.map(\n (value) =>\n Object.fromEntries(fields.map((field) => [field, value[field as K[number]]])) as Pick<\n A,\n K[number]\n >,\n ),\n );\n\nexport const requestArrayBuffer = (\n options: PutioRequestOptions,\n): Effect.Effect<Uint8Array, PutioSdkError, PutioSdkContext> =>\n executeRequest(options).pipe(\n Effect.flatMap((response) =>\n isSuccessStatus(response.status)\n ? response.arrayBuffer.pipe(\n Effect.mapError(mapTransportError),\n Effect.map((buffer) => new Uint8Array(buffer)),\n )\n : decodeFailure(response, response.headers).pipe(Effect.flatMap(Effect.fail)),\n ),\n );\n\nexport const requestVoid = (\n options: PutioRequestOptions,\n): Effect.Effect<void, PutioSdkError, PutioSdkContext> =>\n executeRequest(options).pipe(\n Effect.flatMap((response) =>\n isSuccessStatus(response.status)\n ? Effect.void\n : decodeFailure(response, response.headers).pipe(Effect.flatMap(Effect.fail)),\n ),\n );\n","type CsvValue = string | number;\n\nexport interface CursorSelectionInput<TValue extends CsvValue = number> {\n readonly cursor?: string;\n readonly excludeIds?: ReadonlyArray<TValue>;\n readonly ids?: ReadonlyArray<TValue>;\n}\n\nexport const joinCsv = <TValue extends CsvValue>(\n values: ReadonlyArray<TValue> | undefined,\n): string | undefined => (values && values.length > 0 ? values.join(\",\") : undefined);\n\nexport const toCursorSelectionForm = <\n TValue extends CsvValue,\n const TIdsFieldName extends string = \"file_ids\",\n>(\n selection: CursorSelectionInput<TValue>,\n idsFieldName?: TIdsFieldName,\n): {\n readonly cursor?: string;\n readonly exclude_ids?: string;\n} & Record<TIdsFieldName, string | undefined> => {\n const resolvedIdsFieldName = (idsFieldName ?? \"file_ids\") as TIdsFieldName;\n\n return {\n cursor: selection.cursor,\n exclude_ids: joinCsv(selection.excludeIds),\n [resolvedIdsFieldName]: joinCsv(selection.ids),\n } as {\n readonly cursor?: string;\n readonly exclude_ids?: string;\n } & Record<TIdsFieldName, string | undefined>;\n};\n"],"mappings":"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"}