@putdotio/sdk 11.2.1 → 11.4.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 +7 -0
- package/dist/{forms-bd8oHsdi.js → forms-C7FIvCRP.js} +4 -3
- package/dist/{forms-bd8oHsdi.js.map → forms-C7FIvCRP.js.map} +1 -1
- package/dist/{index-NRI1PBEe.d.ts → index-RtmdAkA_.d.ts} +127 -58
- package/dist/index.d.ts +2 -2
- package/dist/index.js +64 -7
- package/dist/index.js.map +1 -1
- package/dist/utilities.d.ts +1 -1
- package/dist/utilities.js +8 -8
- package/dist/utilities.js.map +1 -1
- package/package.json +5 -5
package/dist/utilities.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Am as PutioErrorEnvelope, Dm as PutioApiError, Nm as PutioKnownOperationErrorContract, Om as PutioAuthError, Pm as PutioOperationError, Rm as PutioRateLimitError, zo as FileBroad } from "./index-RtmdAkA_.js";
|
|
2
2
|
//#region src/utilities/date.d.ts
|
|
3
3
|
declare const ensureUTC: (date?: unknown) => string;
|
|
4
4
|
declare const toTimeAgo: (date?: unknown) => string;
|
package/dist/utilities.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { F as isPutioErrorEnvelope, o as buildPutioUrl, s as encodePathSegment, t as joinCsv } from "./forms-C7FIvCRP.js";
|
|
2
2
|
import { Predicate } from "effect";
|
|
3
3
|
//#region src/utilities/date.ts
|
|
4
4
|
const LONG_DATE_FORMATTER = new Intl.DateTimeFormat("en-US", {
|
|
@@ -16,17 +16,17 @@ const ensureDate = (value) => {
|
|
|
16
16
|
};
|
|
17
17
|
const toRelativeUnit = (secondsDelta) => {
|
|
18
18
|
const absoluteSeconds = Math.abs(secondsDelta);
|
|
19
|
-
if (absoluteSeconds >=
|
|
19
|
+
if (absoluteSeconds >= 31536e3) return {
|
|
20
20
|
unit: "year",
|
|
21
|
-
value: Math.round(secondsDelta /
|
|
21
|
+
value: Math.round(secondsDelta / 31536e3)
|
|
22
22
|
};
|
|
23
|
-
if (absoluteSeconds >=
|
|
23
|
+
if (absoluteSeconds >= 2592e3) return {
|
|
24
24
|
unit: "month",
|
|
25
|
-
value: Math.round(secondsDelta /
|
|
25
|
+
value: Math.round(secondsDelta / 2592e3)
|
|
26
26
|
};
|
|
27
|
-
if (absoluteSeconds >=
|
|
27
|
+
if (absoluteSeconds >= 86400) return {
|
|
28
28
|
unit: "day",
|
|
29
|
-
value: Math.round(secondsDelta /
|
|
29
|
+
value: Math.round(secondsDelta / 86400)
|
|
30
30
|
};
|
|
31
31
|
if (absoluteSeconds >= 3600) return {
|
|
32
32
|
unit: "hour",
|
|
@@ -63,7 +63,7 @@ const daysDiff = (date1, date2) => {
|
|
|
63
63
|
const day2 = ensureDate(date2);
|
|
64
64
|
const utcDay1 = Date.UTC(day1.getUTCFullYear(), day1.getUTCMonth(), day1.getUTCDate());
|
|
65
65
|
const utcDay2 = Date.UTC(day2.getUTCFullYear(), day2.getUTCMonth(), day2.getUTCDate());
|
|
66
|
-
return Math.abs(Math.round((utcDay2 - utcDay1) /
|
|
66
|
+
return Math.abs(Math.round((utcDay2 - utcDay1) / 864e5));
|
|
67
67
|
};
|
|
68
68
|
const daysDiffFromNow = (date = null) => {
|
|
69
69
|
if (!date) return 0;
|
package/dist/utilities.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utilities.js","names":[],"sources":["../src/utilities/date.ts","../src/utilities/duration.ts","../src/utilities/file-render-type.ts","../src/utilities/file-size.ts","../src/utilities/file-url-provider.ts","../src/utilities/localized-error.ts","../src/utilities/string.ts"],"sourcesContent":["const LONG_DATE_FORMATTER = new Intl.DateTimeFormat(\"en-US\", {\n dateStyle: \"long\",\n timeZone: \"UTC\",\n});\n\nconst RELATIVE_TIME_FORMATTER = new Intl.RelativeTimeFormat(\"en\", {\n numeric: \"always\",\n});\n\nconst ensureDate = (value: unknown): Date => {\n if (value instanceof Date) {\n return value;\n }\n\n if (typeof value === \"string\") {\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) {\n return new Date(`${value}T00:00:00.000Z`);\n }\n\n return new Date(value.endsWith(\"Z\") ? value : `${value}Z`);\n }\n\n return new Date();\n};\n\nconst toRelativeUnit = (secondsDelta: number) => {\n const absoluteSeconds = Math.abs(secondsDelta);\n\n if (absoluteSeconds >= 60 * 60 * 24 * 365) {\n return { unit: \"year\" as const, value: Math.round(secondsDelta / (60 * 60 * 24 * 365)) };\n }\n\n if (absoluteSeconds >= 60 * 60 * 24 * 30) {\n return { unit: \"month\" as const, value: Math.round(secondsDelta / (60 * 60 * 24 * 30)) };\n }\n\n if (absoluteSeconds >= 60 * 60 * 24) {\n return { unit: \"day\" as const, value: Math.round(secondsDelta / (60 * 60 * 24)) };\n }\n\n if (absoluteSeconds >= 60 * 60) {\n return { unit: \"hour\" as const, value: Math.round(secondsDelta / (60 * 60)) };\n }\n\n if (absoluteSeconds >= 60) {\n return { unit: \"minute\" as const, value: Math.round(secondsDelta / 60) };\n }\n\n return { unit: \"second\" as const, value: Math.round(secondsDelta) };\n};\n\nexport const ensureUTC = (date: unknown = null): string => ensureDate(date).toISOString();\n\nexport const toTimeAgo = (date: unknown = null): string => {\n if (!date) {\n return \"N/A\";\n }\n\n const target = ensureDate(date);\n const secondsDelta = Math.round((target.getTime() - Date.now()) / 1000);\n const { unit, value } = toRelativeUnit(secondsDelta);\n return RELATIVE_TIME_FORMATTER.format(value, unit);\n};\n\nexport const formatDate = (\n date: unknown = null,\n format: \"LL\" | Intl.DateTimeFormatOptions = \"LL\",\n): string => {\n if (!date) {\n return \"N/A\";\n }\n\n const normalizedDate = ensureDate(date);\n\n if (format === \"LL\") {\n return LONG_DATE_FORMATTER.format(normalizedDate);\n }\n\n return new Intl.DateTimeFormat(\"en-US\", {\n timeZone: \"UTC\",\n ...format,\n }).format(normalizedDate);\n};\n\nexport const daysDiff = (date1: unknown, date2: unknown): number => {\n const day1 = ensureDate(date1);\n const day2 = ensureDate(date2);\n\n const utcDay1 = Date.UTC(day1.getUTCFullYear(), day1.getUTCMonth(), day1.getUTCDate());\n const utcDay2 = Date.UTC(day2.getUTCFullYear(), day2.getUTCMonth(), day2.getUTCDate());\n\n return Math.abs(Math.round((utcDay2 - utcDay1) / (1000 * 60 * 60 * 24)));\n};\n\nexport const daysDiffFromNow = (date: unknown = null): number => {\n if (!date) {\n return 0;\n }\n\n return daysDiff(date, new Date());\n};\n\nexport const getUnixTimestamp = (date: unknown): number =>\n Math.floor(ensureDate(date).getTime() / 1000);\n","const normalizeNumber = (value: unknown): number => (typeof value === \"number\" ? value : 0);\n\nconst formatPadded = (value: number): string => String(value).padStart(2, \"0\");\n\nexport const secondsToDuration = (seconds: unknown): string => {\n const normalizedSeconds = Math.floor(normalizeNumber(seconds));\n\n if (normalizedSeconds <= 0) {\n return \"00:00\";\n }\n\n const days = Math.floor(normalizedSeconds / 86_400);\n const hours = Math.floor((normalizedSeconds % 86_400) / 3_600);\n const minutes = Math.floor((normalizedSeconds % 3_600) / 60);\n const remainingSeconds = normalizedSeconds % 60;\n\n if (days > 0) {\n return [days, hours, minutes, remainingSeconds].map(formatPadded).join(\":\");\n }\n\n if (normalizedSeconds >= 3_600) {\n return [Math.floor(normalizedSeconds / 3_600), minutes, remainingSeconds]\n .map(formatPadded)\n .join(\":\");\n }\n\n return [minutes, remainingSeconds].map(formatPadded).join(\":\");\n};\n\nexport const secondsToReadableDuration = (seconds: unknown): string => {\n const normalizedSeconds = Math.floor(normalizeNumber(seconds));\n\n if (normalizedSeconds <= 0) {\n return \"N/A\";\n }\n\n if (normalizedSeconds < 60) {\n return `${normalizedSeconds} s`;\n }\n\n if (normalizedSeconds >= 86_400) {\n const days = Math.floor(normalizedSeconds / 86_400);\n const roundedHours = Math.round((normalizedSeconds - days * 86_400) / 3_600);\n\n if (roundedHours === 24) {\n return `${days + 1}d`;\n }\n\n return roundedHours > 0 ? `${days}d ${roundedHours}h` : `${days}d`;\n }\n\n if (normalizedSeconds >= 3_600) {\n const hours = Math.floor(normalizedSeconds / 3_600);\n const roundedMinutes = Math.round((normalizedSeconds - hours * 3_600) / 60);\n return roundedMinutes > 0 ? `${hours}h ${roundedMinutes}m` : `${hours}h`;\n }\n\n const roundedMinutes = Math.round(normalizedSeconds / 60);\n const remainingSeconds = normalizedSeconds - roundedMinutes * 60;\n return remainingSeconds > 0 ? `${roundedMinutes}m ${remainingSeconds}s` : `${roundedMinutes}m`;\n};\n","import type { FileBroad } from \"../domains/files.js\";\n\nexport type FileRenderType =\n | \"archive\"\n | \"audio\"\n | \"epub\"\n | \"folder\"\n | \"image\"\n | \"other\"\n | \"pdf\"\n | \"text\"\n | \"text/markdown\"\n | \"video\";\n\nexport type FileRenderTypeInput = Pick<FileBroad, \"content_type\" | \"extension\" | \"file_type\">;\n\nexport const getFileRenderType = (file: FileRenderTypeInput): FileRenderType => {\n const { content_type, extension, file_type } = file;\n\n if (typeof content_type !== \"string\") {\n return \"other\";\n }\n\n if (content_type === \"application/x-directory\") {\n return \"folder\";\n }\n\n if (content_type.startsWith(\"audio\") || file_type === \"AUDIO\") {\n return \"audio\";\n }\n\n if (content_type.startsWith(\"video\")) {\n return \"video\";\n }\n\n if (content_type.startsWith(\"image\")) {\n return \"image\";\n }\n\n if (content_type === \"application/pdf\") {\n return \"pdf\";\n }\n\n if (content_type === \"application/epub+zip\") {\n return \"epub\";\n }\n\n if (content_type === \"application/zip\" || content_type === \"application/x-rar\") {\n return \"archive\";\n }\n\n if (\n content_type.startsWith(\"text\") ||\n content_type.startsWith(\"application/x-subrip\") ||\n file_type === \"TEXT\"\n ) {\n if (content_type.endsWith(\"/markdown\") || extension === \"md\") {\n return \"text/markdown\";\n }\n\n return \"text\";\n }\n\n return \"other\";\n};\n","export interface HumanFileSizeOptions {\n readonly decimals?: number;\n readonly unitSeparator?: string;\n}\n\nconst FILE_SIZE_UNITS = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"] as const;\n\nexport const toHumanFileSize = (\n fileSizeInBytes: string | number,\n options: HumanFileSizeOptions = {},\n): string => {\n const { decimals = 1, unitSeparator = \" \" } = options;\n const parsed =\n typeof fileSizeInBytes === \"string\" ? Number.parseInt(fileSizeInBytes, 10) : fileSizeInBytes;\n\n if (!Number.isFinite(parsed) || parsed <= 0) {\n return `0${unitSeparator}B`;\n }\n\n const exponent = Math.min(\n Math.floor(Math.log(parsed) / Math.log(1024)),\n FILE_SIZE_UNITS.length - 1,\n );\n const normalized = parsed / 1024 ** exponent;\n const fractionDigits = normalized % 1 === 0 ? 0 : decimals;\n\n return `${normalized.toFixed(fractionDigits)}${unitSeparator}${FILE_SIZE_UNITS[exponent]}`;\n};\n","import { joinCsv } from \"../core/forms.js\";\nimport { buildPutioUrl, encodePathSegment } from \"../core/http.js\";\nimport type { FileBroad } from \"../domains/files.js\";\nimport { getFileRenderType, type FileRenderTypeInput } from \"./file-render-type.js\";\n\nexport type FileUrlProviderInput = Pick<\n FileBroad,\n \"content_type\" | \"extension\" | \"file_type\" | \"id\" | \"is_mp4_available\"\n>;\n\nconst normalizeApiBaseUrl = (apiURL: string): string =>\n apiURL.endsWith(\"/v2\") ? apiURL.slice(0, -3) : apiURL;\n\nconst isVideoFile = (file: FileRenderTypeInput): boolean => getFileRenderType(file) === \"video\";\n\nexport class FileURLProvider {\n readonly apiURL: string;\n\n readonly token: string;\n\n readonly baseURL: string;\n\n constructor(apiURL: string, token: string) {\n this.baseURL = normalizeApiBaseUrl(apiURL);\n this.apiURL = `${this.baseURL}/v2`;\n this.token = token;\n }\n\n getDownloadURL(fileOrFileId: FileUrlProviderInput | number): string | null {\n if (typeof fileOrFileId === \"number\") {\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(fileOrFileId)}/download`, {\n oauth_token: this.token,\n });\n }\n\n if (fileOrFileId.file_type === \"FOLDER\") {\n return null;\n }\n\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(fileOrFileId.id)}/download`, {\n oauth_token: this.token,\n });\n }\n\n getHLSStreamURL(\n file: FileUrlProviderInput,\n params: {\n readonly maxSubtitleCount?: number;\n readonly playOriginal?: boolean;\n readonly subtitleLanguages?: ReadonlyArray<string>;\n } = {},\n ): string | null {\n if (!isVideoFile(file)) {\n return null;\n }\n\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(file.id)}/hls/media.m3u8`, {\n max_subtitle_count: params.maxSubtitleCount,\n oauth_token: this.token,\n original: params.playOriginal ? 1 : undefined,\n subtitle_languages: joinCsv(params.subtitleLanguages),\n });\n }\n\n getMP4DownloadURL(file: FileUrlProviderInput): string | null {\n if (!isVideoFile(file) || !file.is_mp4_available) {\n return null;\n }\n\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(file.id)}/mp4/download`, {\n oauth_token: this.token,\n });\n }\n\n getMP4StreamURL(file: FileUrlProviderInput): string | null {\n if (!isVideoFile(file) || !file.is_mp4_available) {\n return null;\n }\n\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(file.id)}/mp4/stream`, {\n oauth_token: this.token,\n });\n }\n\n getStreamURL(file: FileUrlProviderInput): string | null {\n switch (getFileRenderType(file)) {\n case \"audio\":\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(file.id)}/stream.mp3`, {\n oauth_token: this.token,\n });\n case \"video\":\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(file.id)}/stream`, {\n oauth_token: this.token,\n });\n default:\n return null;\n }\n }\n\n getXSPFURL(file: FileUrlProviderInput): string | null {\n if (!isVideoFile(file)) {\n return null;\n }\n\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(file.id)}/xspf`, {\n oauth_token: this.token,\n });\n }\n}\n","import { Predicate } from \"effect\";\n\nimport {\n PutioApiError,\n PutioAuthError,\n type PutioErrorEnvelope,\n isPutioErrorEnvelope,\n PutioOperationError,\n PutioRateLimitError,\n type PutioKnownOperationErrorContract,\n} from \"../core/errors.js\";\n\nexport type LocalizedErrorRecoverySuggestionTypeInstruction = {\n readonly type: \"instruction\";\n readonly description: string;\n};\n\nexport type LocalizedErrorRecoverySuggestionTypeAction = {\n readonly type: \"action\";\n readonly description: string;\n readonly trigger: {\n readonly label: string;\n readonly callback: () => void;\n };\n};\n\nexport type LocalizedErrorRecoverySuggestionTypeCaptcha = {\n readonly type: \"captcha\";\n readonly description: string;\n};\n\nexport type LocalizedErrorRecoverySuggestion =\n | LocalizedErrorRecoverySuggestionTypeInstruction\n | LocalizedErrorRecoverySuggestionTypeAction\n | LocalizedErrorRecoverySuggestionTypeCaptcha;\n\nexport interface LocalizedErrorParams {\n readonly message: string;\n readonly recoverySuggestion: LocalizedErrorRecoverySuggestion;\n readonly underlyingError: unknown;\n readonly meta?: Record<string, unknown>;\n}\n\nexport class LocalizedError extends Error {\n readonly recoverySuggestion: LocalizedErrorRecoverySuggestion;\n\n readonly underlyingError: unknown;\n\n readonly meta: Record<string, unknown>;\n\n constructor(params: LocalizedErrorParams) {\n super(params.message);\n this.name = \"LocalizedError\";\n this.recoverySuggestion = params.recoverySuggestion;\n this.underlyingError = params.underlyingError;\n this.meta = params.meta ?? {};\n }\n}\n\ntype StatusAndBodyError =\n | PutioApiError\n | PutioAuthError\n | PutioRateLimitError\n | PutioOperationError<string, string, PutioKnownOperationErrorContract>;\n\nexport type PutioLocalizableError = {\n readonly _tag?: string;\n readonly body: PutioErrorEnvelope;\n readonly status?: number;\n};\n\nexport type PutioErrorWithBody = StatusAndBodyError;\n\nconst isLocalizablePutioErrorEnvelope = (value: unknown): value is PutioErrorEnvelope =>\n Predicate.isObject(value) &&\n (\"status_code\" in value || \"error_type\" in value || \"error_message\" in value) &&\n isPutioErrorEnvelope(value);\n\nconst isPutioErrorWithBody = (value: unknown): value is PutioLocalizableError =>\n Predicate.isObject(value) && \"body\" in value && isPutioErrorEnvelope(value.body);\n\nconst normalizePutioError = (\n error: PutioErrorEnvelope | PutioLocalizableError,\n): PutioLocalizableError => {\n if (isLocalizablePutioErrorEnvelope(error)) {\n return {\n _tag: \"PutioErrorEnvelope\",\n body: error,\n status: error.status_code,\n };\n }\n\n return error;\n};\n\nexport type LocalizeErrorFn<E> = (\n error: E,\n) => Pick<LocalizedErrorParams, \"message\" | \"recoverySuggestion\" | \"meta\">;\n\nexport type APIErrorByStatusCodeLocalizer = {\n readonly kind: \"api_status_code\";\n readonly status_code: number;\n readonly localize: LocalizeErrorFn<PutioLocalizableError>;\n};\n\nexport type APIErrorByErrorTypeLocalizer = {\n readonly kind: \"api_error_type\";\n readonly error_type: string;\n readonly localize: LocalizeErrorFn<PutioLocalizableError>;\n};\n\nexport type MatchConditionLocalizer<E> = {\n readonly kind: \"match_condition\";\n readonly match: (error: E) => boolean;\n readonly localize: LocalizeErrorFn<E>;\n};\n\nexport type GenericErrorLocalizer = {\n readonly kind: \"generic\";\n readonly localize: LocalizeErrorFn<unknown>;\n};\n\nexport type ErrorLocalizer<E> =\n | APIErrorByStatusCodeLocalizer\n | APIErrorByErrorTypeLocalizer\n | MatchConditionLocalizer<E>\n | GenericErrorLocalizer;\n\nexport type ErrorLocalizerFn = (error: unknown) => LocalizedError;\n\nexport const isErrorLocalizer = (fn: unknown): fn is ErrorLocalizerFn => {\n try {\n return typeof fn === \"function\" && fn(new Error(\"test\")) instanceof LocalizedError;\n } catch {\n return false;\n }\n};\n\nexport const createLocalizeError =\n <GlobalError>(globalLocalizers: ReadonlyArray<ErrorLocalizer<GlobalError>>) =>\n <ScopedError extends GlobalError>(\n error: ScopedError,\n scopedLocalizers: ReadonlyArray<ErrorLocalizer<ScopedError>> = [],\n ): LocalizedError => {\n const localizers = [...scopedLocalizers, ...globalLocalizers];\n\n if (isPutioErrorWithBody(error) || isLocalizablePutioErrorEnvelope(error)) {\n const apiError = normalizePutioError(error);\n\n const byErrorType = localizers.find(\n (localizer): localizer is APIErrorByErrorTypeLocalizer =>\n localizer.kind === \"api_error_type\" && localizer.error_type === apiError.body.error_type,\n );\n\n if (byErrorType) {\n return new LocalizedError({\n underlyingError: apiError,\n ...byErrorType.localize(apiError),\n });\n }\n\n const byMatchCondition = localizers.find(\n (localizer): localizer is MatchConditionLocalizer<ScopedError> =>\n localizer.kind === \"match_condition\" && localizer.match(error),\n );\n\n if (byMatchCondition) {\n return new LocalizedError({\n underlyingError: error,\n ...byMatchCondition.localize(error),\n });\n }\n\n const byStatusCode = localizers.find(\n (localizer): localizer is APIErrorByStatusCodeLocalizer =>\n localizer.kind === \"api_status_code\" &&\n localizer.status_code === apiError.body.status_code,\n );\n\n if (byStatusCode) {\n return new LocalizedError({\n underlyingError: apiError,\n ...byStatusCode.localize(apiError),\n });\n }\n }\n\n const byMatchCondition = localizers.find(\n (localizer): localizer is MatchConditionLocalizer<ScopedError> =>\n localizer.kind === \"match_condition\" && localizer.match(error),\n );\n\n if (byMatchCondition) {\n return new LocalizedError({\n underlyingError: error,\n ...byMatchCondition.localize(error),\n });\n }\n\n const genericLocalizer = localizers.find(\n (localizer): localizer is GenericErrorLocalizer => localizer.kind === \"generic\",\n );\n\n if (genericLocalizer) {\n return new LocalizedError({\n underlyingError: error,\n ...genericLocalizer.localize(error),\n });\n }\n\n throw new Error(`No localizer found for error: ${String(error)}`);\n };\n","export const dotsToSpaces = (input: string): string => input.split(\".\").join(\" \");\n\nexport const truncate = (\n input: string,\n options: {\n readonly length: number;\n readonly ellipsis?: string;\n },\n): string => {\n const { ellipsis = \"...\", length } = options;\n\n if (input.length <= length) {\n return input;\n }\n\n return `${input.slice(0, length)}${ellipsis}`;\n};\n\nexport const truncateMiddle = (\n input: string,\n options: {\n readonly frontLength: number;\n readonly backLength: number;\n readonly ellipsis?: string;\n },\n): string => {\n const { backLength, ellipsis = \"...\", frontLength } = options;\n const preservedLength = frontLength + backLength;\n\n if (input.length <= preservedLength) {\n return input;\n }\n\n return `${input.slice(0, frontLength)}${ellipsis}${input.slice(input.length - backLength)}`;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utilities.js","names":[],"sources":["../src/utilities/date.ts","../src/utilities/duration.ts","../src/utilities/file-render-type.ts","../src/utilities/file-size.ts","../src/utilities/file-url-provider.ts","../src/utilities/localized-error.ts","../src/utilities/string.ts"],"sourcesContent":["const LONG_DATE_FORMATTER = new Intl.DateTimeFormat(\"en-US\", {\n dateStyle: \"long\",\n timeZone: \"UTC\",\n});\n\nconst RELATIVE_TIME_FORMATTER = new Intl.RelativeTimeFormat(\"en\", {\n numeric: \"always\",\n});\n\nconst ensureDate = (value: unknown): Date => {\n if (value instanceof Date) {\n return value;\n }\n\n if (typeof value === \"string\") {\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) {\n return new Date(`${value}T00:00:00.000Z`);\n }\n\n return new Date(value.endsWith(\"Z\") ? value : `${value}Z`);\n }\n\n return new Date();\n};\n\nconst toRelativeUnit = (secondsDelta: number) => {\n const absoluteSeconds = Math.abs(secondsDelta);\n\n if (absoluteSeconds >= 60 * 60 * 24 * 365) {\n return { unit: \"year\" as const, value: Math.round(secondsDelta / (60 * 60 * 24 * 365)) };\n }\n\n if (absoluteSeconds >= 60 * 60 * 24 * 30) {\n return { unit: \"month\" as const, value: Math.round(secondsDelta / (60 * 60 * 24 * 30)) };\n }\n\n if (absoluteSeconds >= 60 * 60 * 24) {\n return { unit: \"day\" as const, value: Math.round(secondsDelta / (60 * 60 * 24)) };\n }\n\n if (absoluteSeconds >= 60 * 60) {\n return { unit: \"hour\" as const, value: Math.round(secondsDelta / (60 * 60)) };\n }\n\n if (absoluteSeconds >= 60) {\n return { unit: \"minute\" as const, value: Math.round(secondsDelta / 60) };\n }\n\n return { unit: \"second\" as const, value: Math.round(secondsDelta) };\n};\n\nexport const ensureUTC = (date: unknown = null): string => ensureDate(date).toISOString();\n\nexport const toTimeAgo = (date: unknown = null): string => {\n if (!date) {\n return \"N/A\";\n }\n\n const target = ensureDate(date);\n const secondsDelta = Math.round((target.getTime() - Date.now()) / 1000);\n const { unit, value } = toRelativeUnit(secondsDelta);\n return RELATIVE_TIME_FORMATTER.format(value, unit);\n};\n\nexport const formatDate = (\n date: unknown = null,\n format: \"LL\" | Intl.DateTimeFormatOptions = \"LL\",\n): string => {\n if (!date) {\n return \"N/A\";\n }\n\n const normalizedDate = ensureDate(date);\n\n if (format === \"LL\") {\n return LONG_DATE_FORMATTER.format(normalizedDate);\n }\n\n return new Intl.DateTimeFormat(\"en-US\", {\n timeZone: \"UTC\",\n ...format,\n }).format(normalizedDate);\n};\n\nexport const daysDiff = (date1: unknown, date2: unknown): number => {\n const day1 = ensureDate(date1);\n const day2 = ensureDate(date2);\n\n const utcDay1 = Date.UTC(day1.getUTCFullYear(), day1.getUTCMonth(), day1.getUTCDate());\n const utcDay2 = Date.UTC(day2.getUTCFullYear(), day2.getUTCMonth(), day2.getUTCDate());\n\n return Math.abs(Math.round((utcDay2 - utcDay1) / (1000 * 60 * 60 * 24)));\n};\n\nexport const daysDiffFromNow = (date: unknown = null): number => {\n if (!date) {\n return 0;\n }\n\n return daysDiff(date, new Date());\n};\n\nexport const getUnixTimestamp = (date: unknown): number =>\n Math.floor(ensureDate(date).getTime() / 1000);\n","const normalizeNumber = (value: unknown): number => (typeof value === \"number\" ? value : 0);\n\nconst formatPadded = (value: number): string => String(value).padStart(2, \"0\");\n\nexport const secondsToDuration = (seconds: unknown): string => {\n const normalizedSeconds = Math.floor(normalizeNumber(seconds));\n\n if (normalizedSeconds <= 0) {\n return \"00:00\";\n }\n\n const days = Math.floor(normalizedSeconds / 86_400);\n const hours = Math.floor((normalizedSeconds % 86_400) / 3_600);\n const minutes = Math.floor((normalizedSeconds % 3_600) / 60);\n const remainingSeconds = normalizedSeconds % 60;\n\n if (days > 0) {\n return [days, hours, minutes, remainingSeconds].map(formatPadded).join(\":\");\n }\n\n if (normalizedSeconds >= 3_600) {\n return [Math.floor(normalizedSeconds / 3_600), minutes, remainingSeconds]\n .map(formatPadded)\n .join(\":\");\n }\n\n return [minutes, remainingSeconds].map(formatPadded).join(\":\");\n};\n\nexport const secondsToReadableDuration = (seconds: unknown): string => {\n const normalizedSeconds = Math.floor(normalizeNumber(seconds));\n\n if (normalizedSeconds <= 0) {\n return \"N/A\";\n }\n\n if (normalizedSeconds < 60) {\n return `${normalizedSeconds} s`;\n }\n\n if (normalizedSeconds >= 86_400) {\n const days = Math.floor(normalizedSeconds / 86_400);\n const roundedHours = Math.round((normalizedSeconds - days * 86_400) / 3_600);\n\n if (roundedHours === 24) {\n return `${days + 1}d`;\n }\n\n return roundedHours > 0 ? `${days}d ${roundedHours}h` : `${days}d`;\n }\n\n if (normalizedSeconds >= 3_600) {\n const hours = Math.floor(normalizedSeconds / 3_600);\n const roundedMinutes = Math.round((normalizedSeconds - hours * 3_600) / 60);\n return roundedMinutes > 0 ? `${hours}h ${roundedMinutes}m` : `${hours}h`;\n }\n\n const roundedMinutes = Math.round(normalizedSeconds / 60);\n const remainingSeconds = normalizedSeconds - roundedMinutes * 60;\n return remainingSeconds > 0 ? `${roundedMinutes}m ${remainingSeconds}s` : `${roundedMinutes}m`;\n};\n","import type { FileBroad } from \"../domains/files.js\";\n\nexport type FileRenderType =\n | \"archive\"\n | \"audio\"\n | \"epub\"\n | \"folder\"\n | \"image\"\n | \"other\"\n | \"pdf\"\n | \"text\"\n | \"text/markdown\"\n | \"video\";\n\nexport type FileRenderTypeInput = Pick<FileBroad, \"content_type\" | \"extension\" | \"file_type\">;\n\nexport const getFileRenderType = (file: FileRenderTypeInput): FileRenderType => {\n const { content_type, extension, file_type } = file;\n\n if (typeof content_type !== \"string\") {\n return \"other\";\n }\n\n if (content_type === \"application/x-directory\") {\n return \"folder\";\n }\n\n if (content_type.startsWith(\"audio\") || file_type === \"AUDIO\") {\n return \"audio\";\n }\n\n if (content_type.startsWith(\"video\")) {\n return \"video\";\n }\n\n if (content_type.startsWith(\"image\")) {\n return \"image\";\n }\n\n if (content_type === \"application/pdf\") {\n return \"pdf\";\n }\n\n if (content_type === \"application/epub+zip\") {\n return \"epub\";\n }\n\n if (content_type === \"application/zip\" || content_type === \"application/x-rar\") {\n return \"archive\";\n }\n\n if (\n content_type.startsWith(\"text\") ||\n content_type.startsWith(\"application/x-subrip\") ||\n file_type === \"TEXT\"\n ) {\n if (content_type.endsWith(\"/markdown\") || extension === \"md\") {\n return \"text/markdown\";\n }\n\n return \"text\";\n }\n\n return \"other\";\n};\n","export interface HumanFileSizeOptions {\n readonly decimals?: number;\n readonly unitSeparator?: string;\n}\n\nconst FILE_SIZE_UNITS = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"] as const;\n\nexport const toHumanFileSize = (\n fileSizeInBytes: string | number,\n options: HumanFileSizeOptions = {},\n): string => {\n const { decimals = 1, unitSeparator = \" \" } = options;\n const parsed =\n typeof fileSizeInBytes === \"string\" ? Number.parseInt(fileSizeInBytes, 10) : fileSizeInBytes;\n\n if (!Number.isFinite(parsed) || parsed <= 0) {\n return `0${unitSeparator}B`;\n }\n\n const exponent = Math.min(\n Math.floor(Math.log(parsed) / Math.log(1024)),\n FILE_SIZE_UNITS.length - 1,\n );\n const normalized = parsed / 1024 ** exponent;\n const fractionDigits = normalized % 1 === 0 ? 0 : decimals;\n\n return `${normalized.toFixed(fractionDigits)}${unitSeparator}${FILE_SIZE_UNITS[exponent]}`;\n};\n","import { joinCsv } from \"../core/forms.js\";\nimport { buildPutioUrl, encodePathSegment } from \"../core/http.js\";\nimport type { FileBroad } from \"../domains/files.js\";\nimport { getFileRenderType, type FileRenderTypeInput } from \"./file-render-type.js\";\n\nexport type FileUrlProviderInput = Pick<\n FileBroad,\n \"content_type\" | \"extension\" | \"file_type\" | \"id\" | \"is_mp4_available\"\n>;\n\nconst normalizeApiBaseUrl = (apiURL: string): string =>\n apiURL.endsWith(\"/v2\") ? apiURL.slice(0, -3) : apiURL;\n\nconst isVideoFile = (file: FileRenderTypeInput): boolean => getFileRenderType(file) === \"video\";\n\nexport class FileURLProvider {\n readonly apiURL: string;\n\n readonly token: string;\n\n readonly baseURL: string;\n\n constructor(apiURL: string, token: string) {\n this.baseURL = normalizeApiBaseUrl(apiURL);\n this.apiURL = `${this.baseURL}/v2`;\n this.token = token;\n }\n\n getDownloadURL(fileOrFileId: FileUrlProviderInput | number): string | null {\n if (typeof fileOrFileId === \"number\") {\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(fileOrFileId)}/download`, {\n oauth_token: this.token,\n });\n }\n\n if (fileOrFileId.file_type === \"FOLDER\") {\n return null;\n }\n\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(fileOrFileId.id)}/download`, {\n oauth_token: this.token,\n });\n }\n\n getHLSStreamURL(\n file: FileUrlProviderInput,\n params: {\n readonly maxSubtitleCount?: number;\n readonly playOriginal?: boolean;\n readonly subtitleLanguages?: ReadonlyArray<string>;\n } = {},\n ): string | null {\n if (!isVideoFile(file)) {\n return null;\n }\n\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(file.id)}/hls/media.m3u8`, {\n max_subtitle_count: params.maxSubtitleCount,\n oauth_token: this.token,\n original: params.playOriginal ? 1 : undefined,\n subtitle_languages: joinCsv(params.subtitleLanguages),\n });\n }\n\n getMP4DownloadURL(file: FileUrlProviderInput): string | null {\n if (!isVideoFile(file) || !file.is_mp4_available) {\n return null;\n }\n\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(file.id)}/mp4/download`, {\n oauth_token: this.token,\n });\n }\n\n getMP4StreamURL(file: FileUrlProviderInput): string | null {\n if (!isVideoFile(file) || !file.is_mp4_available) {\n return null;\n }\n\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(file.id)}/mp4/stream`, {\n oauth_token: this.token,\n });\n }\n\n getStreamURL(file: FileUrlProviderInput): string | null {\n switch (getFileRenderType(file)) {\n case \"audio\":\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(file.id)}/stream.mp3`, {\n oauth_token: this.token,\n });\n case \"video\":\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(file.id)}/stream`, {\n oauth_token: this.token,\n });\n default:\n return null;\n }\n }\n\n getXSPFURL(file: FileUrlProviderInput): string | null {\n if (!isVideoFile(file)) {\n return null;\n }\n\n return buildPutioUrl(this.baseURL, `/v2/files/${encodePathSegment(file.id)}/xspf`, {\n oauth_token: this.token,\n });\n }\n}\n","import { Predicate } from \"effect\";\n\nimport {\n PutioApiError,\n PutioAuthError,\n type PutioErrorEnvelope,\n isPutioErrorEnvelope,\n PutioOperationError,\n PutioRateLimitError,\n type PutioKnownOperationErrorContract,\n} from \"../core/errors.js\";\n\nexport type LocalizedErrorRecoverySuggestionTypeInstruction = {\n readonly type: \"instruction\";\n readonly description: string;\n};\n\nexport type LocalizedErrorRecoverySuggestionTypeAction = {\n readonly type: \"action\";\n readonly description: string;\n readonly trigger: {\n readonly label: string;\n readonly callback: () => void;\n };\n};\n\nexport type LocalizedErrorRecoverySuggestionTypeCaptcha = {\n readonly type: \"captcha\";\n readonly description: string;\n};\n\nexport type LocalizedErrorRecoverySuggestion =\n | LocalizedErrorRecoverySuggestionTypeInstruction\n | LocalizedErrorRecoverySuggestionTypeAction\n | LocalizedErrorRecoverySuggestionTypeCaptcha;\n\nexport interface LocalizedErrorParams {\n readonly message: string;\n readonly recoverySuggestion: LocalizedErrorRecoverySuggestion;\n readonly underlyingError: unknown;\n readonly meta?: Record<string, unknown>;\n}\n\nexport class LocalizedError extends Error {\n readonly recoverySuggestion: LocalizedErrorRecoverySuggestion;\n\n readonly underlyingError: unknown;\n\n readonly meta: Record<string, unknown>;\n\n constructor(params: LocalizedErrorParams) {\n super(params.message);\n this.name = \"LocalizedError\";\n this.recoverySuggestion = params.recoverySuggestion;\n this.underlyingError = params.underlyingError;\n this.meta = params.meta ?? {};\n }\n}\n\ntype StatusAndBodyError =\n | PutioApiError\n | PutioAuthError\n | PutioRateLimitError\n | PutioOperationError<string, string, PutioKnownOperationErrorContract>;\n\nexport type PutioLocalizableError = {\n readonly _tag?: string;\n readonly body: PutioErrorEnvelope;\n readonly status?: number;\n};\n\nexport type PutioErrorWithBody = StatusAndBodyError;\n\nconst isLocalizablePutioErrorEnvelope = (value: unknown): value is PutioErrorEnvelope =>\n Predicate.isObject(value) &&\n (\"status_code\" in value || \"error_type\" in value || \"error_message\" in value) &&\n isPutioErrorEnvelope(value);\n\nconst isPutioErrorWithBody = (value: unknown): value is PutioLocalizableError =>\n Predicate.isObject(value) && \"body\" in value && isPutioErrorEnvelope(value.body);\n\nconst normalizePutioError = (\n error: PutioErrorEnvelope | PutioLocalizableError,\n): PutioLocalizableError => {\n if (isLocalizablePutioErrorEnvelope(error)) {\n return {\n _tag: \"PutioErrorEnvelope\",\n body: error,\n status: error.status_code,\n };\n }\n\n return error;\n};\n\nexport type LocalizeErrorFn<E> = (\n error: E,\n) => Pick<LocalizedErrorParams, \"message\" | \"recoverySuggestion\" | \"meta\">;\n\nexport type APIErrorByStatusCodeLocalizer = {\n readonly kind: \"api_status_code\";\n readonly status_code: number;\n readonly localize: LocalizeErrorFn<PutioLocalizableError>;\n};\n\nexport type APIErrorByErrorTypeLocalizer = {\n readonly kind: \"api_error_type\";\n readonly error_type: string;\n readonly localize: LocalizeErrorFn<PutioLocalizableError>;\n};\n\nexport type MatchConditionLocalizer<E> = {\n readonly kind: \"match_condition\";\n readonly match: (error: E) => boolean;\n readonly localize: LocalizeErrorFn<E>;\n};\n\nexport type GenericErrorLocalizer = {\n readonly kind: \"generic\";\n readonly localize: LocalizeErrorFn<unknown>;\n};\n\nexport type ErrorLocalizer<E> =\n | APIErrorByStatusCodeLocalizer\n | APIErrorByErrorTypeLocalizer\n | MatchConditionLocalizer<E>\n | GenericErrorLocalizer;\n\nexport type ErrorLocalizerFn = (error: unknown) => LocalizedError;\n\nexport const isErrorLocalizer = (fn: unknown): fn is ErrorLocalizerFn => {\n try {\n return typeof fn === \"function\" && fn(new Error(\"test\")) instanceof LocalizedError;\n } catch {\n return false;\n }\n};\n\nexport const createLocalizeError =\n <GlobalError>(globalLocalizers: ReadonlyArray<ErrorLocalizer<GlobalError>>) =>\n <ScopedError extends GlobalError>(\n error: ScopedError,\n scopedLocalizers: ReadonlyArray<ErrorLocalizer<ScopedError>> = [],\n ): LocalizedError => {\n const localizers = [...scopedLocalizers, ...globalLocalizers];\n\n if (isPutioErrorWithBody(error) || isLocalizablePutioErrorEnvelope(error)) {\n const apiError = normalizePutioError(error);\n\n const byErrorType = localizers.find(\n (localizer): localizer is APIErrorByErrorTypeLocalizer =>\n localizer.kind === \"api_error_type\" && localizer.error_type === apiError.body.error_type,\n );\n\n if (byErrorType) {\n return new LocalizedError({\n underlyingError: apiError,\n ...byErrorType.localize(apiError),\n });\n }\n\n const byMatchCondition = localizers.find(\n (localizer): localizer is MatchConditionLocalizer<ScopedError> =>\n localizer.kind === \"match_condition\" && localizer.match(error),\n );\n\n if (byMatchCondition) {\n return new LocalizedError({\n underlyingError: error,\n ...byMatchCondition.localize(error),\n });\n }\n\n const byStatusCode = localizers.find(\n (localizer): localizer is APIErrorByStatusCodeLocalizer =>\n localizer.kind === \"api_status_code\" &&\n localizer.status_code === apiError.body.status_code,\n );\n\n if (byStatusCode) {\n return new LocalizedError({\n underlyingError: apiError,\n ...byStatusCode.localize(apiError),\n });\n }\n }\n\n const byMatchCondition = localizers.find(\n (localizer): localizer is MatchConditionLocalizer<ScopedError> =>\n localizer.kind === \"match_condition\" && localizer.match(error),\n );\n\n if (byMatchCondition) {\n return new LocalizedError({\n underlyingError: error,\n ...byMatchCondition.localize(error),\n });\n }\n\n const genericLocalizer = localizers.find(\n (localizer): localizer is GenericErrorLocalizer => localizer.kind === \"generic\",\n );\n\n if (genericLocalizer) {\n return new LocalizedError({\n underlyingError: error,\n ...genericLocalizer.localize(error),\n });\n }\n\n throw new Error(`No localizer found for error: ${String(error)}`);\n };\n","export const dotsToSpaces = (input: string): string => input.split(\".\").join(\" \");\n\nexport const truncate = (\n input: string,\n options: {\n readonly length: number;\n readonly ellipsis?: string;\n },\n): string => {\n const { ellipsis = \"...\", length } = options;\n\n if (input.length <= length) {\n return input;\n }\n\n return `${input.slice(0, length)}${ellipsis}`;\n};\n\nexport const truncateMiddle = (\n input: string,\n options: {\n readonly frontLength: number;\n readonly backLength: number;\n readonly ellipsis?: string;\n },\n): string => {\n const { backLength, ellipsis = \"...\", frontLength } = options;\n const preservedLength = frontLength + backLength;\n\n if (input.length <= preservedLength) {\n return input;\n }\n\n return `${input.slice(0, frontLength)}${ellipsis}${input.slice(input.length - backLength)}`;\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@putdotio/sdk",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.4.0",
|
|
4
4
|
"description": "Effect-first TypeScript SDK for the put.io API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"effect",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"lint:unused:prod": "vp pack && knip --production --no-gitignore",
|
|
49
49
|
"prepack": "vp pack",
|
|
50
50
|
"secrets:setup": "bash ./scripts/secrets-setup.sh",
|
|
51
|
-
"secrets:clean": "rm -f .env.local .env.local.* .env.local.swp",
|
|
51
|
+
"secrets:clean": "rm -f .env.live-tokens .env.local .env.local.* .env.local.swp",
|
|
52
52
|
"test": "vp test --passWithNoTests",
|
|
53
53
|
"test:compat": "node ./scripts/test-compat-node.ts && node ./scripts/test-compat-browser.ts && node ./scripts/test-compat-bun.ts",
|
|
54
54
|
"test:compat:browser": "node ./scripts/test-compat-browser.ts",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"test:compat:bun": "node ./scripts/test-compat-bun.ts",
|
|
57
57
|
"test:compat:node": "node ./scripts/test-compat-node.ts",
|
|
58
58
|
"test:live": "vp pack && vp test run --config vitest.live.config.ts",
|
|
59
|
-
"test:live:
|
|
59
|
+
"test:live:targets": "vp pack && node ./scripts/test-live-targets.ts",
|
|
60
60
|
"validate:routes": "vp pack && vp run validate:routes:packed",
|
|
61
61
|
"validate:routes:packed": "node ./scripts/validate-route-matrix.ts",
|
|
62
62
|
"verify": "vp check . && vp run lint:package && knip && knip --production --no-gitignore && vp run validate:routes:packed && vp test run --coverage --passWithNoTests"
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"vitest": "catalog:"
|
|
78
78
|
},
|
|
79
79
|
"engines": {
|
|
80
|
-
"node": ">=24.
|
|
80
|
+
"node": ">=24.19.0"
|
|
81
81
|
},
|
|
82
|
-
"packageManager": "pnpm@
|
|
82
|
+
"packageManager": "pnpm@12.0.0"
|
|
83
83
|
}
|