@reasonabletech/utils 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/object.js ADDED
@@ -0,0 +1,48 @@
1
+ // src/object.ts
2
+ function includeIf(key, value) {
3
+ return value !== void 0 ? { [key]: value } : {};
4
+ }
5
+ function includeIfDefined(obj) {
6
+ const result = {};
7
+ for (const [key, value] of Object.entries(obj)) {
8
+ if (value !== void 0) {
9
+ result[key] = value;
10
+ }
11
+ }
12
+ return result;
13
+ }
14
+ function omitUndefined(obj) {
15
+ return includeIfDefined(obj);
16
+ }
17
+ function conditionalProps(conditions) {
18
+ const result = {};
19
+ for (const [condition, props] of Object.entries(conditions)) {
20
+ if (condition === "true") {
21
+ Object.assign(result, props);
22
+ }
23
+ }
24
+ return result;
25
+ }
26
+ function pick(obj, keys) {
27
+ const result = {};
28
+ for (const key of keys) {
29
+ if (key in obj) {
30
+ result[key] = obj[key];
31
+ }
32
+ }
33
+ return result;
34
+ }
35
+ function omit(obj, keys) {
36
+ const result = {};
37
+ const keysSet = new Set(keys);
38
+ for (const [key, value] of Object.entries(obj)) {
39
+ if (!keysSet.has(key)) {
40
+ result[key] = value;
41
+ }
42
+ }
43
+ return result;
44
+ }
45
+
46
+ export { conditionalProps, includeIf, includeIfDefined, omit, omitUndefined, pick };
47
+ //# sourceMappingURL=object.js.map
48
+ //# sourceMappingURL=object.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/object.ts"],"names":[],"mappings":";AAgGO,SAAS,SAAA,CACd,KACA,KAAA,EACyB;AACzB,EAAA,OAAO,KAAA,KAAU,SAAY,EAAE,CAAC,GAAG,GAAG,KAAA,KAAU,EAAC;AACnD;AA2CO,SAAS,iBACd,GAAA,EACyB;AACzB,EAAA,MAAM,SAAkC,EAAC;AACzC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,EAAG;AAC9C,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,IAChB;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AA0CO,SAAS,cACd,GAAA,EACyB;AACzB,EAAA,OAAO,iBAAiB,GAAG,CAAA;AAC7B;AAwCO,SAAS,iBACd,UAAA,EACyB;AACzB,EAAA,MAAM,SAAkC,EAAC;AACzC,EAAA,KAAA,MAAW,CAAC,SAAA,EAAW,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AAC3D,IAAA,IAAI,cAAc,MAAA,EAAQ;AACxB,MAAA,MAAA,CAAO,MAAA,CAAO,QAAQ,KAAK,CAAA;AAAA,IAC7B;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAkCO,SAAS,IAAA,CACd,KACA,IAAA,EACY;AACZ,EAAA,MAAM,SAAS,EAAC;AAChB,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,IAAI,OAAO,GAAA,EAAK;AACd,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,GAAA,CAAI,GAAG,CAAA;AAAA,IACvB;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAyCO,SAAS,IAAA,CACd,KACA,IAAA,EACY;AACZ,EAAA,MAAM,SAAS,EAAC;AAChB,EAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,IAAI,CAAA;AAC5B,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,EAAG;AAC9C,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,GAAQ,CAAA,EAAG;AAC1B,MAAC,MAAA,CAAmC,GAAG,CAAA,GAAI,KAAA;AAAA,IAC7C;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT","file":"object.js","sourcesContent":["/**\n * Object utility functions for handling exactOptionalPropertyTypes and clean object construction\n *\n * These utilities are designed to work with TypeScript's strict mode and exactOptionalPropertyTypes\n * configuration, which prevents assigning undefined to optional properties. They provide clean,\n * type-safe ways to construct objects with conditional properties.\n *\n * ## Key Use Cases\n *\n * 1. **exactOptionalPropertyTypes compliance** - When you cannot assign undefined to optional properties\n * 2. **Clean object construction** - Building objects with conditional properties based on runtime values\n * 3. **API response formatting** - Creating response objects that omit undefined fields\n * 4. **Configuration objects** - Building config objects where some properties may not be defined\n *\n * ## Examples\n *\n * ### Basic Conditional Properties\n * ```typescript\n * // Instead of this (fails with exactOptionalPropertyTypes):\n * const badObj = {\n * name: \"test\",\n * description: undefined, // ❌ Error: undefined not assignable to optional property\n * };\n *\n * // Use this:\n * const goodObj = {\n * name: \"test\",\n * ...includeIf(\"description\", maybeDescription),\n * };\n * ```\n *\n * ### Multiple Conditional Properties\n * ```typescript\n * const config = {\n * host: \"localhost\",\n * port: 3000,\n * ...includeIfDefined({\n * ssl: enableSsl ? { cert: certPath, key: keyPath } : undefined,\n * auth: authConfig, // may be undefined\n * timeout: customTimeout, // may be undefined\n * }),\n * };\n * ```\n *\n * ### API Response Building\n * ```typescript\n * function buildApiResponse(user: User) {\n * return {\n * id: user.id,\n * name: user.name,\n * ...includeIf(\"email\", user.email), // only include if user has email\n * ...includeIf(\"avatar\", user.avatarUrl), // only include if user has avatar\n * ...includeIf(\"lastSeen\", user.lastSeenAt ? lastSeenAt.toISOString()), // convert and include if exists\n * };\n * }\n * ```\n * @module object\n * @since 1.0.0\n */\n\n/**\n * Conditionally includes a property in an object if the value is not undefined.\n * This is useful for exactOptionalPropertyTypes compliance where you cannot assign undefined to optional properties.\n * @param key - The property key to conditionally include\n * @param value - The value to include, or undefined to omit the property\n * @returns An empty object if value is undefined, otherwise an object with the key-value pair\n * @example Basic usage\n * ```typescript\n * const obj = {\n * required : \"value\",\n * ...includeIf(\"optional\", maybeUndefinedValue),\n * };\n * // If maybeUndefinedValue is \"hello\": { required: \"value\", optional: \"hello\" }\n * // If maybeUndefinedValue is undefined: { required: \"value\" }\n * ```\n * @example API response building\n * ```typescript\n * function createUserResponse(user: User) {\n * return {\n * id: user.id,\n * name: user.name,\n * ...includeIf(\"email\", user.email),\n * ...includeIf(\"avatar\", user.avatar ? avatar.url),\n * ...includeIf(\"lastLogin\", user.lastLoginAt?.toISOString()),\n * };\n * }\n * ```\n * @example Billing service usage (real project example)\n * ```typescript\n * return {\n * amount : pricing.amount,\n * ...includeIf(\"setupFee\", pricing.setupFee),\n * ...includeIf(\"savings\", calculatedSavings),\n * };\n * ```\n */\nexport function includeIf<K extends string, V>(\n key: K,\n value: V | undefined,\n): Record<string, unknown> {\n return value !== undefined ? { [key]: value } : {};\n}\n\n/**\n * Conditionally includes multiple properties from an object, omitting any with undefined values.\n * This creates a new object with only the defined properties.\n * @param obj - Object containing key-value pairs where values may be undefined\n * @returns New object containing only the properties where values are not undefined\n * @example Basic usage\n * ```typescript\n * const obj = {\n * required: \"value\",\n * ...includeIfDefined({\n * optional1: maybeUndefined1, // included only if not undefined\n * optional2: maybeUndefined2, // included only if not undefined\n * }),\n * };\n * ```\n * @example Configuration object building\n * ```typescript\n * const config = {\n * host: \"localhost\",\n * port: 3000,\n * ...includeIfDefined({\n * ssl: sslEnabled ? sslEnabled.sslConfig : undefined,\n * auth: authConfig, // may be undefined\n * timeout: userTimeout, // may be undefined\n * retries: retryCount, // may be undefined\n * }),\n * };\n * ```\n * @example Form data processing\n * ```typescript\n * const formData = {\n * name: data.name,\n * email: data.email,\n * ...includeIfDefined({\n * phone: data.phone ? phone.trim() || undefined,\n * company : data.company?.trim() || undefined,\n * website: data.website ? website.startsWith('http') ? data.website : undefined,\n * }),\n * };\n * ```\n */\nexport function includeIfDefined<T extends Record<string, unknown>>(\n obj: T,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Omits properties with undefined values from an object.\n * This is useful for cleaning up objects before assignment when using exactOptionalPropertyTypes.\n * Note: This only removes undefined values, not other falsy values like null, 0, \"\", or false.\n * @param obj - The object to clean of undefined properties\n * @returns New object with undefined properties removed\n * @example Basic cleanup\n * ```typescript\n * const cleanObj = omitUndefined({\n * a: \"defined\",\n * b: undefined, // ❌ removed\n * c: null, // ✅ preserved (null ≠ undefined)\n * d: 0, // ✅ preserved (falsy but defined)\n * e: \"\", // ✅ preserved (falsy but defined)\n * f: false, // ✅ preserved (falsy but defined)\n * });\n * // Result: { a: \"defined\", c: null, d: 0, e: \"\", f: false }\n * ```\n * @example API data cleaning\n * ```typescript\n * function sanitizeApiResponse(rawData: any) {\n * return omitUndefined({\n * id: rawData.id,\n * name: rawData.name,\n * description: rawData.description, // may be undefined\n * metadata: rawData.metadata, // may be undefined\n * createdAt: rawData.created_at,\n * });\n * }\n * ```\n * @example Before database save\n * ```typescript\n * const userUpdate = omitUndefined({\n * name: formData.name,\n * email: formData.email,\n * avatar: formData.avatar, // only update if provided\n * settings: formData.settings, // only update if provided\n * });\n * ```\n */\nexport function omitUndefined<T extends Record<string, unknown>>(\n obj: T,\n): Record<string, unknown> {\n return includeIfDefined(obj);\n}\n\n/**\n * Creates an object with conditional properties based on boolean conditions.\n * Each condition is checked and only truthy conditions include their corresponding properties.\n * @param conditions - Object where keys are boolean conditions (as strings) and values are objects to include\n * @returns Object containing properties from all truthy conditions\n * @example Basic conditional properties\n * ```typescript\n * const obj = {\n * always: \"included\",\n * ...conditionalProps({\n * [String(isEnabled)]: { feature: \"enabled\" },\n * [String(hasPermission)]: { admin: true },\n * }),\n * };\n * ```\n * @example Feature flags\n * ```typescript\n * const config = {\n * baseUrl: \"https://api.example.com\",\n * ...conditionalProps({\n * [String(enableLogging)]: { logging: { level: \"debug\" } },\n * [String(enableMetrics)]: { metrics: { endpoint: \"/metrics\" } },\n * [String(enableAuth)]: { auth: { provider: \"oauth\" } },\n * }),\n * };\n * ```\n * @example User permission-based UI\n * ```typescript\n * const uiConfig = {\n * showProfile: true,\n * ...conditionalProps({\n * [String(user.isAdmin)]: { showAdminPanel: true },\n * [String(user.isPremium)]: { showPremiumFeatures: true },\n * [String(user.canEdit)]: { showEditTools: true },\n * }),\n * };\n * ```\n */\nexport function conditionalProps(\n conditions: Record<string, Record<string, unknown>>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [condition, props] of Object.entries(conditions)) {\n if (condition === \"true\") {\n Object.assign(result, props);\n }\n }\n return result;\n}\n\n/**\n * Type-safe way to pick properties from an object, with undefined handling.\n * Unlike Lodash pick, this preserves exact types and handles undefined values correctly.\n * Only includes properties that exist in the source object.\n * @param obj - The source object to pick properties from\n * @param keys - Array of keys to pick from the object\n * @returns New object containing only the specified properties\n * @example Basic property picking\n * ```typescript\n * const user = { id: 1, name: \"John\", email: \"john@example.com\", password: \"secret\" };\n * const publicUser = pick(user, ['id', 'name', 'email']);\n * // Result: { id: 1, name: \"John\", email: \"john@example.com\" }\n * ```\n * @example API response filtering\n * ```typescript\n * function createPublicProfile(fullUser: FullUser) {\n * return pick(fullUser, [\n * 'id',\n * 'username',\n * 'displayName',\n * 'avatar',\n * 'joinedAt'\n * ]);\n * }\n * ```\n * @example Configuration subset\n * ```typescript\n * const fullConfig = { host: \"localhost\", port: 3000, ssl: true, debug: true, secret: \"xxx\" };\n * const clientConfig = pick(fullConfig, ['host', 'port', 'ssl']);\n * // Result: { host: \"localhost\", port: 3000, ssl: true }\n * ```\n */\nexport function pick<T extends Record<string, unknown>, K extends keyof T>(\n obj: T,\n keys: readonly K[],\n): Pick<T, K> {\n const result = {} as Pick<T, K>;\n for (const key of keys) {\n if (key in obj) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n\n/**\n * Type-safe way to omit properties from an object, with undefined handling.\n * Unlike Lodash omit, this preserves exact types and handles undefined values correctly.\n * Creates a new object excluding the specified properties.\n * @param obj - The source object to omit properties from\n * @param keys - Array of keys to omit from the object\n * @returns New object with the specified properties removed\n * @example Remove sensitive data\n * ```typescript\n * const user = { id: 1, name: \"John\", email: \"john@example.com\", password: \"secret\", ssn: \"xxx\" };\n * const safeUser = omit(user, ['password', 'ssn']);\n * // Result: { id: 1, name: \"John\", email: \"john@example.com\" }\n * ```\n * @example Remove internal properties\n * ```typescript\n * function toApiResponse(internalObj: InternalUser) {\n * return omit(internalObj, [\n * '_id',\n * '_version',\n * '_internal',\n * 'hashedPassword',\n * 'secretKey'\n * ]);\n * }\n * ```\n * @example Configuration sanitization\n * ```typescript\n * const fullConfig = {\n * host: \"localhost\",\n * port: 3000,\n * ssl: true,\n * debug: true,\n * apiSecret: \"xxx\",\n * dbPassword: \"yyy\"\n * };\n * const publicConfig = omit(fullConfig, ['apiSecret', 'dbPassword']);\n * // Result: { host: \"localhost\", port: 3000, ssl: true, debug: true }\n * ```\n */\nexport function omit<T extends Record<string, unknown>, K extends keyof T>(\n obj: T,\n keys: readonly K[],\n): Omit<T, K> {\n const result = {} as Omit<T, K>;\n const keysSet = new Set(keys);\n for (const [key, value] of Object.entries(obj)) {\n if (!keysSet.has(key as K)) {\n (result as Record<string, unknown>)[key] = value;\n }\n }\n return result;\n}\n"]}
package/dist/result.js ADDED
@@ -0,0 +1,80 @@
1
+ // src/result.ts
2
+ function ok(value) {
3
+ return { success: true, value };
4
+ }
5
+ function err(error) {
6
+ return { success: false, error };
7
+ }
8
+ function isSuccess(result) {
9
+ return result.success;
10
+ }
11
+ function isFailure(result) {
12
+ return !result.success;
13
+ }
14
+ async function fromPromise(promise) {
15
+ try {
16
+ const value = await promise;
17
+ return ok(value);
18
+ } catch (error) {
19
+ return err(error instanceof Error ? error : new Error(String(error)));
20
+ }
21
+ }
22
+ function map(result, fn) {
23
+ if (result.success) {
24
+ return ok(fn(result.value));
25
+ }
26
+ return result;
27
+ }
28
+ function mapErr(result, fn) {
29
+ if (!result.success) {
30
+ return err(fn(result.error));
31
+ }
32
+ return ok(result.value);
33
+ }
34
+ function andThen(result, fn) {
35
+ if (result.success) {
36
+ return fn(result.value);
37
+ }
38
+ return result;
39
+ }
40
+ function orElse(result, fn) {
41
+ if (!result.success) {
42
+ return fn(result.error);
43
+ }
44
+ return result;
45
+ }
46
+ function unwrap(result) {
47
+ if (result.success) {
48
+ return result.value;
49
+ }
50
+ if (result.error instanceof Error) {
51
+ throw result.error;
52
+ }
53
+ throw new Error(String(result.error));
54
+ }
55
+ function unwrapOr(result, defaultValue) {
56
+ if (result.success) {
57
+ return result.value;
58
+ }
59
+ return defaultValue;
60
+ }
61
+ function unwrapOrElse(result, fn) {
62
+ if (result.success) {
63
+ return result.value;
64
+ }
65
+ return fn(result.error);
66
+ }
67
+ function combine(results) {
68
+ const values = [];
69
+ for (const result of results) {
70
+ if (!result.success) {
71
+ return result;
72
+ }
73
+ values.push(result.value);
74
+ }
75
+ return ok(values);
76
+ }
77
+
78
+ export { andThen, combine, err, fromPromise, isFailure, isSuccess, map, mapErr, ok, orElse, unwrap, unwrapOr, unwrapOrElse };
79
+ //# sourceMappingURL=result.js.map
80
+ //# sourceMappingURL=result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/result.ts"],"names":[],"mappings":";AAmCO,SAAS,GAAiB,KAAA,EAAgC;AAC/D,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,KAAA,EAAyB;AACnD;AAOO,SAAS,IAA0B,KAAA,EAAwB;AAChE,EAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAM;AACjC;AAOO,SAAS,UACd,MAAA,EACsB;AACtB,EAAA,OAAO,MAAA,CAAO,OAAA;AAChB;AAOO,SAAS,UACd,MAAA,EACsB;AACtB,EAAA,OAAO,CAAC,MAAA,CAAO,OAAA;AACjB;AAOA,eAAsB,YACpB,OAAA,EAC2B;AAC3B,EAAA,IAAI;AACF,IAAA,MAAM,QAAQ,MAAM,OAAA;AACpB,IAAA,OAAO,GAAG,KAAK,CAAA;AAAA,EACjB,SAAS,KAAA,EAAO;AACd,IAAA,OAAO,GAAA,CAAI,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAC,CAAA;AAAA,EACtE;AACF;AAQO,SAAS,GAAA,CACd,QACA,EAAA,EACc;AACd,EAAA,IAAI,OAAO,OAAA,EAAS;AAClB,IAAA,OAAO,EAAA,CAAG,EAAA,CAAG,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EAC5B;AACA,EAAA,OAAO,MAAA;AACT;AAQO,SAAS,MAAA,CACd,QACA,EAAA,EACc;AACd,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,OAAO,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EAC7B;AACA,EAAA,OAAO,EAAA,CAAG,OAAO,KAAK,CAAA;AACxB;AAQO,SAAS,OAAA,CACd,QACA,EAAA,EACc;AACd,EAAA,IAAI,OAAO,OAAA,EAAS;AAClB,IAAA,OAAO,EAAA,CAAG,OAAO,KAAK,CAAA;AAAA,EACxB;AACA,EAAA,OAAO,MAAA;AACT;AAQO,SAAS,MAAA,CACd,QACA,EAAA,EACc;AACd,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,OAAO,EAAA,CAAG,OAAO,KAAK,CAAA;AAAA,EACxB;AACA,EAAA,OAAO,MAAA;AACT;AAQO,SAAS,OAAqB,MAAA,EAAmC;AACtE,EAAA,IAAI,OAAO,OAAA,EAAS;AAClB,IAAA,OAAO,MAAA,CAAO,KAAA;AAAA,EAChB;AACA,EAAA,IAAI,MAAA,CAAO,iBAAiB,KAAA,EAAO;AACjC,IAAA,MAAM,MAAA,CAAO,KAAA;AAAA,EACf;AACA,EAAA,MAAM,IAAI,KAAA,CAAM,MAAA,CAAO,MAAA,CAAO,KAAK,CAAC,CAAA;AACtC;AAQO,SAAS,QAAA,CACd,QACA,YAAA,EACG;AACH,EAAA,IAAI,OAAO,OAAA,EAAS;AAClB,IAAA,OAAO,MAAA,CAAO,KAAA;AAAA,EAChB;AACA,EAAA,OAAO,YAAA;AACT;AAQO,SAAS,YAAA,CACd,QACA,EAAA,EACG;AACH,EAAA,IAAI,OAAO,OAAA,EAAS;AAClB,IAAA,OAAO,MAAA,CAAO,KAAA;AAAA,EAChB;AACA,EAAA,OAAO,EAAA,CAAG,OAAO,KAAK,CAAA;AACxB;AAQO,SAAS,QACd,OAAA,EACgB;AAChB,EAAA,MAAM,SAAc,EAAC;AACrB,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,MAAA,CAAO,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA,EAC1B;AACA,EAAA,OAAO,GAAG,MAAM,CAAA;AAClB","file":"result.js","sourcesContent":["/**\n * Represents a successful Result with a value.\n * Can be used for type narrowing in tests and assertions.\n */\nexport interface Success<T> {\n success: true;\n value: T;\n error?: undefined;\n}\n\n/**\n * Represents a failed Result with an error.\n * Can be used for type narrowing in tests and assertions.\n */\nexport interface Failure<E> {\n success: false;\n error: E;\n value?: undefined;\n}\n\n/**\n * A simplified Result type inspired by Rust's Result.\n *\n * This type represents either a successful value (ok) or an error (err).\n * It is used for consistent error handling across the `@reasonabletech` platform.\n */\nexport type Result<T, E = Error> = Success<T> | Failure<E>;\n\n/**\n * Creates a successful Result.\n * @param value - Optional value to wrap in a successful Result\n * @returns A successful Result containing the value\n */\nexport function ok<T, E = Error>(value: T): Result<T, E>;\nexport function ok<E = Error>(): Result<void, E>;\nexport function ok<T, E = Error>(value?: T): Result<T | void, E> {\n return { success: true, value: value as T | void };\n}\n\n/**\n * Creates an error Result.\n * @param error The error to wrap in an error Result\n * @returns An error Result containing the error\n */\nexport function err<T = never, E = Error>(error: E): Result<T, E> {\n return { success: false, error };\n}\n\n/**\n * Type guard to check if a Result is successful.\n * @param result The Result to check\n * @returns True if the Result is successful\n */\nexport function isSuccess<T, E = Error>(\n result: Readonly<Result<T, E>>,\n): result is Success<T> {\n return result.success;\n}\n\n/**\n * Type guard to check if a Result is an error.\n * @param result The Result to check\n * @returns True if the Result is an error\n */\nexport function isFailure<T, E = Error>(\n result: Readonly<Result<T, E>>,\n): result is Failure<E> {\n return !result.success;\n}\n\n/**\n * Wraps a Promise to return a Result.\n * @param promise The Promise to wrap\n * @returns A Promise that resolves to a Result\n */\nexport async function fromPromise<T>(\n promise: Promise<T>,\n): Promise<Result<T, Error>> {\n try {\n const value = await promise;\n return ok(value);\n } catch (error) {\n return err(error instanceof Error ? error : new Error(String(error)));\n }\n}\n\n/**\n * Maps a successful Result to a new Result with a transformed value.\n * @param result The Result to map\n * @param fn The function to apply to the value\n * @returns A new Result with the transformed value or the original error\n */\nexport function map<T, U, E = Error>(\n result: Readonly<Result<T, E>>,\n fn: (value: T) => U,\n): Result<U, E> {\n if (result.success) {\n return ok(fn(result.value));\n }\n return result as Result<U, E>;\n}\n\n/**\n * Maps an error Result to a new Result with a transformed error.\n * @param result The Result to map\n * @param fn The function to apply to the error\n * @returns A new Result with the transformed error or the original value\n */\nexport function mapErr<T, E = Error, F = Error>(\n result: Readonly<Result<T, E>>,\n fn: (error: E) => F,\n): Result<T, F> {\n if (!result.success) {\n return err(fn(result.error));\n }\n return ok(result.value);\n}\n\n/**\n * Chains a function that returns a Result after a successful Result.\n * @param result The Result to chain\n * @param fn The function to apply to the value that returns a Result\n * @returns The Result returned by the function or the original error\n */\nexport function andThen<T, U, E = Error>(\n result: Readonly<Result<T, E>>,\n fn: (value: T) => Result<U, E>,\n): Result<U, E> {\n if (result.success) {\n return fn(result.value);\n }\n return result as Result<U, E>;\n}\n\n/**\n * Applies a fallback function to an error Result.\n * @param result The Result to check\n * @param fn The function to apply to the error that returns a Result\n * @returns The original Result if successful, or the Result returned by the function\n */\nexport function orElse<T, E = Error, F = Error>(\n result: Readonly<Result<T, E>>,\n fn: (error: E) => Result<T, F>,\n): Result<T, F> {\n if (!result.success) {\n return fn(result.error);\n }\n return result as unknown as Result<T, F>;\n}\n\n/**\n * Unwraps a Result, returning the value or throwing the error.\n * @param result The Result to unwrap\n * @returns The value if the Result is successful\n * @throws {Error} The error if the Result is an error\n */\nexport function unwrap<T, E = Error>(result: Readonly<Result<T, E>>): T {\n if (result.success) {\n return result.value;\n }\n if (result.error instanceof Error) {\n throw result.error;\n }\n throw new Error(String(result.error));\n}\n\n/**\n * Unwraps a Result, returning the value or a default value.\n * @param result The Result to unwrap\n * @param defaultValue The default value to return if the Result is an error\n * @returns The value if the Result is successful, or the default value\n */\nexport function unwrapOr<T, E = Error>(\n result: Readonly<Result<T, E>>,\n defaultValue: T,\n): T {\n if (result.success) {\n return result.value;\n }\n return defaultValue;\n}\n\n/**\n * Unwraps a Result, returning the value or computing a default value from the error.\n * @param result The Result to unwrap\n * @param fn The function to compute the default value from the error\n * @returns The value if the Result is successful, or the computed default value\n */\nexport function unwrapOrElse<T, E = Error>(\n result: Readonly<Result<T, E>>,\n fn: (error: E) => T,\n): T {\n if (result.success) {\n return result.value;\n }\n return fn(result.error);\n}\n\n/**\n * Combines an array of Results into a single Result containing an array of values.\n * If any Result is an error, returns the first error.\n * @param results Array of Results to combine\n * @returns A Result containing an array of values or the first error\n */\nexport function combine<T, E = Error>(\n results: ReadonlyArray<Result<T, E>>,\n): Result<T[], E> {\n const values: T[] = [];\n for (const result of results) {\n if (!result.success) {\n return result as Result<T[], E>;\n }\n values.push(result.value);\n }\n return ok(values);\n}\n"]}
package/dist/retry.js ADDED
@@ -0,0 +1,76 @@
1
+ // src/retry.ts
2
+ var DEFAULT_RETRY_OPTIONS = {
3
+ maxAttempts: 3,
4
+ initialDelay: 1e3,
5
+ maxDelay: 3e4,
6
+ backoffMultiplier: 2,
7
+ jitterFactor: 0.1,
8
+ shouldRetry: () => true
9
+ };
10
+ function calculateDelay(attempt, options) {
11
+ const exponentialDelay = options.initialDelay * Math.pow(options.backoffMultiplier, attempt - 1);
12
+ const cappedDelay = Math.min(exponentialDelay, options.maxDelay);
13
+ const jitter = cappedDelay * options.jitterFactor * Math.random();
14
+ return Math.round(cappedDelay + jitter);
15
+ }
16
+ async function sleep(ms) {
17
+ await new Promise((resolve) => setTimeout(resolve, ms));
18
+ }
19
+ async function retry(operation, options = {}) {
20
+ const config = { ...DEFAULT_RETRY_OPTIONS, ...options };
21
+ let lastError;
22
+ let actualAttempts = 0;
23
+ for (let attempt = 1; attempt <= config.maxAttempts; attempt++) {
24
+ actualAttempts = attempt;
25
+ try {
26
+ const result = await operation();
27
+ return {
28
+ success: true,
29
+ value: result,
30
+ attempts: attempt
31
+ };
32
+ } catch (error) {
33
+ lastError = error;
34
+ if (config.onError !== void 0) {
35
+ await config.onError(error, attempt);
36
+ }
37
+ if (attempt >= config.maxAttempts || !config.shouldRetry(error, attempt)) {
38
+ break;
39
+ }
40
+ const delay = config.getDelay !== void 0 ? config.getDelay(attempt, error) : calculateDelay(attempt, config);
41
+ await sleep(delay);
42
+ }
43
+ }
44
+ return {
45
+ success: false,
46
+ error: lastError,
47
+ attempts: actualAttempts
48
+ };
49
+ }
50
+ async function retryWithPolling(operation, maxAttempts, interval, shouldRetry = () => true) {
51
+ return await retry(operation, {
52
+ maxAttempts,
53
+ initialDelay: interval,
54
+ maxDelay: interval,
55
+ backoffMultiplier: 1,
56
+ // No backoff
57
+ jitterFactor: 0,
58
+ // No jitter for consistent polling
59
+ shouldRetry
60
+ });
61
+ }
62
+ async function retryWithBackoff(operation, maxRetries = 3, baseDelay = 1e3) {
63
+ const result = await retry(operation, {
64
+ maxAttempts: maxRetries + 1,
65
+ // Convert retries to attempts
66
+ initialDelay: baseDelay
67
+ });
68
+ if (result.success) {
69
+ return result.value;
70
+ }
71
+ throw result.error;
72
+ }
73
+
74
+ export { retry, retryWithBackoff, retryWithPolling, sleep };
75
+ //# sourceMappingURL=retry.js.map
76
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/retry.ts"],"names":[],"mappings":"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","file":"retry.js","sourcesContent":["/**\n * Retry utility functions for the `@reasonabletech` platform\n */\n\n/**\n * Core retry configuration fields that have default values\n */\ninterface RetryConfigDefaults {\n /**\n * Maximum number of attempts (including the initial attempt)\n * @default 3\n */\n maxAttempts: number;\n /**\n * Initial delay in milliseconds before the first retry\n * @default 1000\n */\n initialDelay: number;\n /**\n * Maximum delay in milliseconds between retries\n * @default 30000\n */\n maxDelay: number;\n /**\n * Multiplier for exponential backoff\n * @default 2\n */\n backoffMultiplier: number;\n /**\n * Jitter factor (0-1) to add randomness to delays\n * @default 0.1\n */\n jitterFactor: number;\n /**\n * Function to determine if an error should trigger a retry\n * @default () => true (always retry)\n */\n shouldRetry: (error: unknown, attempt: number) => boolean;\n}\n\n/**\n * Optional callback hooks for retry operations\n */\ninterface RetryCallbacks {\n /**\n * Callback invoked when an attempt fails (before retry decision).\n * Use this for logging, running interceptors, or other side effects.\n */\n onError?: (error: unknown, attempt: number) => void | Promise<void>;\n\n /**\n * Custom delay calculator that overrides the default exponential backoff.\n * Useful when the error contains retry timing hints (e.g., Retry-After header).\n */\n getDelay?: (attempt: number, error: unknown) => number;\n}\n\n/**\n * Resolved configuration after applying defaults\n */\ntype ResolvedRetryConfig = RetryConfigDefaults & RetryCallbacks;\n\n/**\n * Configuration options for retry operations (all fields optional for user input)\n * @example\n * ```typescript\n * const result = await retry(() => fetchData(), {\n * maxAttempts: 5,\n * initialDelay: 500,\n * onError: (error, attempt) => console.log(`Attempt ${attempt} failed`),\n * });\n * ```\n */\nexport interface RetryOptions\n extends Partial<RetryConfigDefaults>,\n RetryCallbacks {}\n\n/**\n * Result of a retry operation\n */\nexport interface RetryResult<T> {\n /** Whether the operation succeeded */\n success: boolean;\n /** The result value if successful */\n value?: T;\n /** The final error if all attempts failed */\n error?: unknown;\n /** Number of attempts made */\n attempts: number;\n}\n\n/**\n * Default retry configuration\n */\nconst DEFAULT_RETRY_OPTIONS: RetryConfigDefaults = {\n maxAttempts: 3,\n initialDelay: 1000,\n maxDelay: 30000,\n backoffMultiplier: 2,\n jitterFactor: 0.1,\n shouldRetry: () => true,\n};\n\n/**\n * Calculate delay with exponential backoff and jitter\n * @param attempt - Current attempt number (1-based)\n * @param options - Retry configuration options\n * @returns Delay in milliseconds\n */\nfunction calculateDelay(attempt: number, options: RetryConfigDefaults): number {\n const exponentialDelay =\n options.initialDelay * Math.pow(options.backoffMultiplier, attempt - 1);\n const cappedDelay = Math.min(exponentialDelay, options.maxDelay);\n\n // Add jitter to prevent thundering herd\n const jitter = cappedDelay * options.jitterFactor * Math.random();\n return Math.round(cappedDelay + jitter);\n}\n\n/**\n * Sleep for the specified number of milliseconds\n * @param ms - Milliseconds to sleep\n * @returns Promise that resolves after the delay\n */\nexport async function sleep(ms: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Retry an async operation with exponential backoff and jitter\n * @param operation - The async operation to retry\n * @param options - Retry configuration options\n * @returns Promise resolving to retry result\n * @example\n * ```typescript\n * // Basic retry with defaults (3 attempts, 1s initial delay)\n * const result = await retry(() => fetchData());\n *\n * // Custom configuration with error callback\n * const result = await retry(() => apiClient.post('/users', userData), {\n * maxAttempts: 5,\n * initialDelay: 500,\n * onError: (error, attempt) => {\n * logger.warn('API', `Attempt ${attempt} failed`, { error });\n * },\n * });\n *\n * // Use server-provided Retry-After hint\n * const result = await retry(() => rateLimitedApi.call(), {\n * getDelay: (attempt, error) => {\n * if (error instanceof ApiError && error.retryAfter) {\n * return error.retryAfter; // Use server-provided delay\n * }\n * return 1000 * Math.pow(2, attempt - 1); // Fallback to exponential\n * },\n * });\n * ```\n */\nexport async function retry<T>(\n operation: () => Promise<T>,\n options: RetryOptions = {},\n): Promise<RetryResult<T>> {\n const config: ResolvedRetryConfig = { ...DEFAULT_RETRY_OPTIONS, ...options };\n let lastError: unknown;\n let actualAttempts = 0;\n\n for (let attempt = 1; attempt <= config.maxAttempts; attempt++) {\n actualAttempts = attempt;\n try {\n const result = await operation();\n return {\n success: true,\n value: result,\n attempts: attempt,\n };\n } catch (error) {\n lastError = error;\n\n // Invoke onError callback if provided\n if (config.onError !== undefined) {\n await config.onError(error, attempt);\n }\n\n // Don't retry if we've reached max attempts or if shouldRetry says no\n if (\n attempt >= config.maxAttempts ||\n !config.shouldRetry(error, attempt)\n ) {\n break;\n }\n\n // Calculate delay: use custom getDelay if provided, otherwise default calculation\n const delay =\n config.getDelay !== undefined\n ? config.getDelay(attempt, error)\n : calculateDelay(attempt, config);\n\n await sleep(delay);\n }\n }\n\n return {\n success: false,\n error: lastError,\n attempts: actualAttempts,\n };\n}\n\n/**\n * Retry an operation with polling (fixed interval, no exponential backoff)\n * @param operation - The async operation to retry\n * @param maxAttempts - Maximum number of attempts\n * @param interval - Fixed interval between attempts in milliseconds\n * @param shouldRetry - Function to determine if retry should continue\n * @returns Promise resolving to retry result\n */\nexport async function retryWithPolling<T>(\n operation: () => Promise<T>,\n maxAttempts: number,\n interval: number,\n shouldRetry: (error: unknown, attempt: number) => boolean = () => true,\n): Promise<RetryResult<T>> {\n return await retry(operation, {\n maxAttempts,\n initialDelay: interval,\n maxDelay: interval,\n backoffMultiplier: 1, // No backoff\n jitterFactor: 0, // No jitter for consistent polling\n shouldRetry,\n });\n}\n\n/**\n * Retry an operation with exponential backoff (simplified interface)\n * This function throws on failure instead of returning a result object.\n * @param operation - The async operation to retry\n * @param maxRetries - Maximum number of retries (attempts after the first try, default: 3)\n * @param baseDelay - Base delay in milliseconds (default: 1000)\n * @returns Promise resolving to the operation's result\n * @throws {unknown} The last error if all attempts fail\n * @example\n * ```typescript\n * // Retry up to 3 times with exponential backoff\n * const result = await retryWithBackoff(() => fetchData(), 3, 500);\n *\n * // Use default retries (3) and delay (1000ms)\n * const user = await retryWithBackoff(() => createUser(userData));\n * ```\n */\nexport async function retryWithBackoff<T>(\n operation: () => Promise<T>,\n maxRetries: number = 3,\n baseDelay: number = 1000,\n): Promise<T> {\n const result = await retry(operation, {\n maxAttempts: maxRetries + 1, // Convert retries to attempts\n initialDelay: baseDelay,\n });\n\n if (result.success) {\n return result.value as T;\n }\n\n // Throw the error to match the simpler interface\n throw result.error;\n}\n"]}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Async utility functions for the `@reasonabletech` platform
3
+ */
4
+ /**
5
+ * Execute an array of async transform functions sequentially, piping the result
6
+ * of each function to the next.
7
+ *
8
+ * This is useful for patterns like request/response interceptors where each
9
+ * function must transform the result of the previous one in order.
10
+ * @param initial - The initial value to pass to the first function
11
+ * @param fns - Array of async transform functions to execute in order
12
+ * @returns Promise resolving to the final transformed value
13
+ * @example
14
+ * ```typescript
15
+ * // Request interceptor pipeline
16
+ * const finalConfig = await pipeAsync(initialConfig, [
17
+ * async (config) => ({ ...config, headers: { ...config.headers, 'X-Request-Id': id } }),
18
+ * async (config) => ({ ...config, timestamp: Date.now() }),
19
+ * ]);
20
+ *
21
+ * // Response interceptor pipeline
22
+ * const finalResponse = await pipeAsync(response, responseInterceptors);
23
+ * ```
24
+ */
25
+ export declare function pipeAsync<T>(initial: T, fns: ReadonlyArray<(value: T) => T | Promise<T>>): Promise<T>;
26
+ /**
27
+ * Execute an array of async functions sequentially, collecting all results.
28
+ *
29
+ * Unlike Promise.all which runs in parallel, this ensures each function
30
+ * completes before the next one starts.
31
+ * @param fns - Array of async functions to execute in order
32
+ * @returns Promise resolving to array of results in the same order
33
+ * @example
34
+ * ```typescript
35
+ * const results = await runSequentially([
36
+ * () => fetchUser(1),
37
+ * () => fetchUser(2),
38
+ * () => fetchUser(3),
39
+ * ]);
40
+ * ```
41
+ */
42
+ export declare function runSequentially<T>(fns: ReadonlyArray<() => T | Promise<T>>): Promise<T[]>;
43
+ //# sourceMappingURL=async.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async.d.ts","sourceRoot":"","sources":["../../src/async.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,OAAO,EAAE,CAAC,EACV,GAAG,EAAE,aAAa,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAC/C,OAAO,CAAC,CAAC,CAAC,CAMZ;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,GAAG,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GACvC,OAAO,CAAC,CAAC,EAAE,CAAC,CAcd"}
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Date/Time Utility Functions
3
+ *
4
+ * This module provides standardized date/time handling utilities for the `@reasonabletech` platform.
5
+ * It ensures consistent use of Date objects internally while providing standard conversions
6
+ * when required by specifications or APIs.
7
+ *
8
+ * Key principles:
9
+ * - Use Date objects for all internal date/time representations
10
+ * - Only convert to strings/numbers when required by external specs/APIs
11
+ * - Provide clear, descriptive function names
12
+ * - Handle edge cases gracefully
13
+ */
14
+ /**
15
+ * Converts a Date object to Unix timestamp (seconds since epoch)
16
+ * @param date - The Date object to convert
17
+ * @returns Unix timestamp in seconds
18
+ */
19
+ export declare function dateToUnixTimestamp(date: Date): number;
20
+ /**
21
+ * Converts a Unix timestamp (seconds since epoch) to a Date object
22
+ * @param timestamp - Unix timestamp in seconds
23
+ * @returns Date object
24
+ */
25
+ export declare function unixTimestampToDate(timestamp: number): Date;
26
+ /**
27
+ * Converts a Date object to ISO string
28
+ * @param date - The Date object to convert
29
+ * @returns ISO string representation
30
+ */
31
+ export declare function dateToISOString(date: Date): string;
32
+ /**
33
+ * Converts an ISO string to a Date object
34
+ * @param isoString - ISO string representation
35
+ * @returns Date object
36
+ */
37
+ export declare function isoStringToDate(isoString: string): Date;
38
+ /**
39
+ * Checks if a Date object represents a time in the past
40
+ * @param date - The Date object to check
41
+ * @returns true if the date is in the past
42
+ */
43
+ export declare function isDateInPast(date: Date): boolean;
44
+ /**
45
+ * Checks if a Date object represents a time in the future
46
+ * @param date - The Date object to check
47
+ * @returns true if the date is in the future
48
+ */
49
+ export declare function isDateInFuture(date: Date): boolean;
50
+ /**
51
+ * Adds seconds to a Date object
52
+ * @param date - The base Date object
53
+ * @param seconds - Number of seconds to add
54
+ * @returns New Date object with added seconds
55
+ */
56
+ export declare function addSeconds(date: Date, seconds: number): Date;
57
+ /**
58
+ * Subtracts seconds from a Date object
59
+ * @param date - The base Date object
60
+ * @param seconds - Number of seconds to subtract
61
+ * @returns New Date object with subtracted seconds
62
+ */
63
+ export declare function subtractSeconds(date: Date, seconds: number): Date;
64
+ /**
65
+ * Adds minutes to a Date object
66
+ * @param date - The base Date object
67
+ * @param minutes - Number of minutes to add
68
+ * @returns New Date object with added minutes
69
+ */
70
+ export declare function addMinutes(date: Date, minutes: number): Date;
71
+ /**
72
+ * Subtracts minutes from a Date object
73
+ * @param date - The base Date object
74
+ * @param minutes - Number of minutes to subtract
75
+ * @returns New Date object with subtracted minutes
76
+ */
77
+ export declare function subtractMinutes(date: Date, minutes: number): Date;
78
+ /**
79
+ * Adds hours to a Date object
80
+ * @param date - The base Date object
81
+ * @param hours - Number of hours to add
82
+ * @returns New Date object with added hours
83
+ */
84
+ export declare function addHours(date: Date, hours: number): Date;
85
+ /**
86
+ * Subtracts hours from a Date object
87
+ * @param date - The base Date object
88
+ * @param hours - Number of hours to subtract
89
+ * @returns New Date object with subtracted hours
90
+ */
91
+ export declare function subtractHours(date: Date, hours: number): Date;
92
+ /**
93
+ * Adds days to a Date object
94
+ * @param date - The base Date object
95
+ * @param days - Number of days to add
96
+ * @returns New Date object with added days
97
+ */
98
+ export declare function addDays(date: Date, days: number): Date;
99
+ /**
100
+ * Subtracts days from a Date object
101
+ * @param date - The base Date object
102
+ * @param days - Number of days to subtract
103
+ * @returns New Date object with subtracted days
104
+ */
105
+ export declare function subtractDays(date: Date, days: number): Date;
106
+ /**
107
+ * Gets the current Date object
108
+ * @returns Current Date object
109
+ */
110
+ export declare function now(): Date;
111
+ /**
112
+ * Converts a Date | string union to a Date object
113
+ * This is a utility to help with migration from Date | string patterns
114
+ * @param dateOrString - Date object or ISO string
115
+ * @returns Date object
116
+ */
117
+ export declare function normalizeToDate(dateOrString: Date | string): Date;
118
+ /**
119
+ * Calculates the difference between two dates in seconds
120
+ * @param laterDate - The later date
121
+ * @param earlierDate - The earlier date
122
+ * @returns Difference in seconds (positive if laterDate is after earlierDate)
123
+ */
124
+ export declare function diffInSeconds(laterDate: Date, earlierDate: Date): number;
125
+ /**
126
+ * Calculates the difference between two dates in minutes
127
+ * @param laterDate - The later date
128
+ * @param earlierDate - The earlier date
129
+ * @returns Difference in minutes (positive if laterDate is after earlierDate)
130
+ */
131
+ export declare function diffInMinutes(laterDate: Date, earlierDate: Date): number;
132
+ /**
133
+ * Calculates the difference between two dates in hours
134
+ * @param laterDate - The later date
135
+ * @param earlierDate - The earlier date
136
+ * @returns Difference in hours (positive if laterDate is after earlierDate)
137
+ */
138
+ export declare function diffInHours(laterDate: Date, earlierDate: Date): number;
139
+ /**
140
+ * Calculates the difference between two dates in days
141
+ * @param laterDate - The later date
142
+ * @param earlierDate - The earlier date
143
+ * @returns Difference in days (positive if laterDate is after earlierDate)
144
+ */
145
+ export declare function diffInDays(laterDate: Date, earlierDate: Date): number;
146
+ /**
147
+ * Checks if two dates represent the same day (ignoring time)
148
+ * Uses UTC to avoid timezone issues
149
+ * @param date1 - First date
150
+ * @param date2 - Second date
151
+ * @returns true if both dates represent the same calendar day in UTC
152
+ */
153
+ export declare function isSameDay(date1: Date, date2: Date): boolean;
154
+ /**
155
+ * Formats a date as YYYY-MM-DD
156
+ * @param date - The date to format
157
+ * @returns Date string in YYYY-MM-DD format
158
+ */
159
+ export declare function formatDateISO(date: Date): string;
160
+ /**
161
+ * Formats a date as HH:MM:SS
162
+ * @param date - The date to format
163
+ * @returns Time string in HH:MM:SS format
164
+ */
165
+ export declare function formatTimeISO(date: Date): string;
166
+ //# sourceMappingURL=datetime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datetime.d.ts","sourceRoot":"","sources":["../../src/datetime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAElD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAElD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAE7D;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED;;;GAGG;AACH,wBAAgB,GAAG,IAAI,IAAI,CAE1B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAKjE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,GAAG,MAAM,CAExE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,GAAG,MAAM,CAExE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,GAAG,MAAM,CAEtE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,GAAG,MAAM,CAErE;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,OAAO,CAM3D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAGhD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAKhD"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Shared utility functions and types for the `@reasonabletech` platform
3
+ */
4
+ export type { Result, Success, Failure } from "./result.js";
5
+ export { ok, err, isSuccess, isFailure, unwrap, unwrapOr, unwrapOrElse, map, mapErr, andThen, orElse, combine, fromPromise, } from "./result.js";
6
+ export { now, dateToISOString, dateToUnixTimestamp, unixTimestampToDate, isoStringToDate, normalizeToDate, formatDateISO, formatTimeISO, addSeconds, addMinutes, addHours, addDays, subtractSeconds, subtractMinutes, subtractHours, subtractDays, diffInSeconds, diffInMinutes, diffInHours, diffInDays, isSameDay, isDateInPast, isDateInFuture, } from "./datetime.js";
7
+ export { pick, omit, omitUndefined, conditionalProps, includeIf, includeIfDefined, } from "./object.js";
8
+ export { capitalize, truncateString, isEmptyString, isNonEmptyString, encodeBase64Url, decodeBase64Url, isValidBase64Url, getErrorMessage, } from "./string.js";
9
+ export type { RetryOptions, RetryResult } from "./retry.js";
10
+ export { sleep, retry, retryWithBackoff, retryWithPolling } from "./retry.js";
11
+ export { pipeAsync, runSequentially } from "./async.js";
12
+ export { isPresent } from "./type-guards.js";
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,EAAE,EACF,GAAG,EACH,SAAS,EACT,SAAS,EACT,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,GAAG,EACH,MAAM,EACN,OAAO,EACP,MAAM,EACN,OAAO,EACP,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,GAAG,EACH,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,aAAa,EACb,aAAa,EACb,UAAU,EACV,UAAU,EACV,QAAQ,EACR,OAAO,EACP,eAAe,EACf,eAAe,EACf,aAAa,EACb,YAAY,EACZ,aAAa,EACb,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,YAAY,EACZ,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,IAAI,EACJ,IAAI,EACJ,aAAa,EACb,gBAAgB,EAChB,SAAS,EACT,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,UAAU,EACV,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9E,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC"}