@willbooster/shared-lib 10.18.0 → 10.19.1
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/crypto.cjs +2 -0
- package/dist/crypto.cjs.map +1 -0
- package/dist/crypto.d.ts +11 -0
- package/dist/crypto.js +2 -0
- package/dist/crypto.js.map +1 -0
- package/dist/error.cjs +1 -1
- package/dist/error.cjs.map +1 -1
- package/dist/error.d.ts +3 -3
- package/dist/error.js +1 -1
- package/dist/error.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/dist/crypto.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";async function e(e){let t=typeof e==`string`?new TextEncoder().encode(e):new Uint8Array(e),n=new Uint8Array(await crypto.subtle.digest(`SHA-256`,t));return Array.from(n,e=>e.toString(16).padStart(2,`0`)).join(``)}async function t(e,t){let[r,i]=await Promise.all([n(e),n(t)]),a=0;for(let e=0;e<r.length;e++)a|=(r[e]??0)^(i[e]??0);return a===0}async function n(e){let t=new Uint16Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n);return new Uint8Array(await crypto.subtle.digest(`SHA-256`,t))}exports.sha256HexAsync=e,exports.timingSafeEqualStringAsync=t;
|
|
2
|
+
//# sourceMappingURL=crypto.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.cjs","names":[],"sources":["../src/crypto.ts"],"sourcesContent":["/**\n * Answers the SHA-256 hex digest of `data` (a string is encoded as UTF-8) with WebCrypto, so it runs in browsers and\n * Cloudflare Workers; the result equals Node.js's `createHash('sha256').update(data).digest('hex')`.\n */\nexport async function sha256HexAsync(data: string | Uint8Array): Promise<string> {\n // Copying into a fresh `ArrayBuffer` also accepts a `SharedArrayBuffer`-backed view, which WebCrypto rejects.\n const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : new Uint8Array(data);\n const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', bytes));\n return Array.from(digest, (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\n/**\n * Compares strings, e.g. a received API key against the expected one, with WebCrypto, so it runs in browsers and\n * Cloudflare Workers. Neither a length check nor an early exit reveals where they differ; only hashing each string\n * takes time proportional to its length, as in `shared-lib-node`'s `timingSafeEqualString`.\n */\nexport async function timingSafeEqualStringAsync(actual: string, expected: string): Promise<boolean> {\n // Hashing gives equal-length inputs, so the loop below needs no length check and never exits early.\n const [actualDigest, expectedDigest] = await Promise.all([digestCodeUnits(actual), digestCodeUnits(expected)]);\n let difference = 0;\n for (let i = 0; i < actualDigest.length; i++) {\n difference |= (actualDigest[i] ?? 0) ^ (expectedDigest[i] ?? 0);\n }\n return difference === 0;\n}\n\nasync function digestCodeUnits(text: string): Promise<Uint8Array> {\n // UTF-16 keeps every code unit, while UTF-8 would turn distinct lone surrogates into the same U+FFFD.\n const codeUnits = new Uint16Array(text.length);\n for (let i = 0; i < text.length; i++) {\n // oxlint-disable-next-line unicorn/prefer-code-point -- a code point would merge a surrogate pair into one value.\n codeUnits[i] = text.charCodeAt(i);\n }\n return new Uint8Array(await crypto.subtle.digest('SHA-256', codeUnits));\n}\n"],"mappings":"aAIA,eAAsB,EAAe,EAA4C,CAE/E,IAAM,EAAQ,OAAO,GAAS,SAAW,IAAI,YAAY,CAAC,CAAC,OAAO,CAAI,EAAI,IAAI,WAAW,CAAI,EACvF,EAAS,IAAI,WAAW,MAAM,OAAO,OAAO,OAAO,UAAW,CAAK,CAAC,EAC1E,OAAO,MAAM,KAAK,EAAS,GAAS,EAAK,SAAS,EAAE,CAAC,CAAC,SAAS,EAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CACjF,CAOA,eAAsB,EAA2B,EAAgB,EAAoC,CAEnG,GAAM,CAAC,EAAc,GAAkB,MAAM,QAAQ,IAAI,CAAC,EAAgB,CAAM,EAAG,EAAgB,CAAQ,CAAC,CAAC,EACzG,EAAa,EACjB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAa,OAAQ,IACvC,IAAe,EAAa,IAAM,IAAM,EAAe,IAAM,GAE/D,OAAO,IAAe,CACxB,CAEA,eAAe,EAAgB,EAAmC,CAEhE,IAAM,EAAY,IAAI,YAAY,EAAK,MAAM,EAC7C,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAQ,IAE/B,EAAU,GAAK,EAAK,WAAW,CAAC,EAElC,OAAO,IAAI,WAAW,MAAM,OAAO,OAAO,OAAO,UAAW,CAAS,CAAC,CACxE"}
|
package/dist/crypto.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Answers the SHA-256 hex digest of `data` (a string is encoded as UTF-8) with WebCrypto, so it runs in browsers and
|
|
3
|
+
* Cloudflare Workers; the result equals Node.js's `createHash('sha256').update(data).digest('hex')`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function sha256HexAsync(data: string | Uint8Array): Promise<string>;
|
|
6
|
+
/**
|
|
7
|
+
* Compares strings, e.g. a received API key against the expected one, with WebCrypto, so it runs in browsers and
|
|
8
|
+
* Cloudflare Workers. Neither a length check nor an early exit reveals where they differ; only hashing each string
|
|
9
|
+
* takes time proportional to its length, as in `shared-lib-node`'s `timingSafeEqualString`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function timingSafeEqualStringAsync(actual: string, expected: string): Promise<boolean>;
|
package/dist/crypto.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
async function e(e){let t=typeof e==`string`?new TextEncoder().encode(e):new Uint8Array(e),n=new Uint8Array(await crypto.subtle.digest(`SHA-256`,t));return Array.from(n,e=>e.toString(16).padStart(2,`0`)).join(``)}async function t(e,t){let[r,i]=await Promise.all([n(e),n(t)]),a=0;for(let e=0;e<r.length;e++)a|=(r[e]??0)^(i[e]??0);return a===0}async function n(e){let t=new Uint16Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n);return new Uint8Array(await crypto.subtle.digest(`SHA-256`,t))}export{e as sha256HexAsync,t as timingSafeEqualStringAsync};
|
|
2
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","names":[],"sources":["../src/crypto.ts"],"sourcesContent":["/**\n * Answers the SHA-256 hex digest of `data` (a string is encoded as UTF-8) with WebCrypto, so it runs in browsers and\n * Cloudflare Workers; the result equals Node.js's `createHash('sha256').update(data).digest('hex')`.\n */\nexport async function sha256HexAsync(data: string | Uint8Array): Promise<string> {\n // Copying into a fresh `ArrayBuffer` also accepts a `SharedArrayBuffer`-backed view, which WebCrypto rejects.\n const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : new Uint8Array(data);\n const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', bytes));\n return Array.from(digest, (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\n/**\n * Compares strings, e.g. a received API key against the expected one, with WebCrypto, so it runs in browsers and\n * Cloudflare Workers. Neither a length check nor an early exit reveals where they differ; only hashing each string\n * takes time proportional to its length, as in `shared-lib-node`'s `timingSafeEqualString`.\n */\nexport async function timingSafeEqualStringAsync(actual: string, expected: string): Promise<boolean> {\n // Hashing gives equal-length inputs, so the loop below needs no length check and never exits early.\n const [actualDigest, expectedDigest] = await Promise.all([digestCodeUnits(actual), digestCodeUnits(expected)]);\n let difference = 0;\n for (let i = 0; i < actualDigest.length; i++) {\n difference |= (actualDigest[i] ?? 0) ^ (expectedDigest[i] ?? 0);\n }\n return difference === 0;\n}\n\nasync function digestCodeUnits(text: string): Promise<Uint8Array> {\n // UTF-16 keeps every code unit, while UTF-8 would turn distinct lone surrogates into the same U+FFFD.\n const codeUnits = new Uint16Array(text.length);\n for (let i = 0; i < text.length; i++) {\n // oxlint-disable-next-line unicorn/prefer-code-point -- a code point would merge a surrogate pair into one value.\n codeUnits[i] = text.charCodeAt(i);\n }\n return new Uint8Array(await crypto.subtle.digest('SHA-256', codeUnits));\n}\n"],"mappings":"AAIA,eAAsB,EAAe,EAA4C,CAE/E,IAAM,EAAQ,OAAO,GAAS,SAAW,IAAI,YAAY,CAAC,CAAC,OAAO,CAAI,EAAI,IAAI,WAAW,CAAI,EACvF,EAAS,IAAI,WAAW,MAAM,OAAO,OAAO,OAAO,UAAW,CAAK,CAAC,EAC1E,OAAO,MAAM,KAAK,EAAS,GAAS,EAAK,SAAS,EAAE,CAAC,CAAC,SAAS,EAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CACjF,CAOA,eAAsB,EAA2B,EAAgB,EAAoC,CAEnG,GAAM,CAAC,EAAc,GAAkB,MAAM,QAAQ,IAAI,CAAC,EAAgB,CAAM,EAAG,EAAgB,CAAQ,CAAC,CAAC,EACzG,EAAa,EACjB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAa,OAAQ,IACvC,IAAe,EAAa,IAAM,IAAM,EAAe,IAAM,GAE/D,OAAO,IAAe,CACxB,CAEA,eAAe,EAAgB,EAAmC,CAEhE,IAAM,EAAY,IAAI,YAAY,EAAK,MAAM,EAC7C,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAQ,IAE/B,EAAU,GAAK,EAAK,WAAW,CAAC,EAElC,OAAO,IAAI,WAAW,MAAM,OAAO,OAAO,OAAO,UAAW,CAAS,CAAC,CACxE"}
|
package/dist/error.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";const e=require("./sleep.cjs");function t(e){return e instanceof Error?e:Error(typeof e==`string`?e:i(()=>JSON.stringify(e))??i(()=>String(e)))}function n(e){return i(()=>e instanceof Error?e.message:String(e))??i(()=>Object.prototype.toString.call(e))??`Unknown error`}function r(e,t){return typeof e==`object`&&!!e&&`code`in e&&e.code===t}function i(e){try{return e()}catch{}}function a(e){try{return e()}catch(e){if(r(e,`ENOENT`))return;throw e}}async function o(e){try{return await e()}catch{}}async function s(e){try{return await e()}catch(e){if(r(e,`ENOENT`))return;throw e}}async function c(t,{beforeRetry:n,handleError:r,retryCount:i=3,retryLogger:a,shouldRetry:o,getSleepMilliseconds:s,sleepMilliseconds:c=0,updateSleepMilliseconds:l}={}){let u=0;for(;;)try{return await t(u)}catch(t){if(await r?.(t),u++,u>=i||o&&!o(t))throw t;let d=s?.(t,c)??c;d>0&&await e.sleep(d),l&&(c=l(c)),a?.(`Retry due to: ${t}
|
|
1
|
+
"use strict";const e=require("./sleep.cjs");function t(e){return e instanceof Error?e:Error(typeof e==`string`?e:i(()=>JSON.stringify(e))??i(()=>String(e)))}function n(e,t){return i(()=>e instanceof Error?e.message:t??String(e))??t??i(()=>Object.prototype.toString.call(e))??`Unknown error`}function r(e,t){return typeof e==`object`&&!!e&&`code`in e&&e.code===t}function i(e){try{return e()}catch{}}function a(e){try{return e()}catch(e){if(r(e,`ENOENT`))return;throw e}}async function o(e){try{return await e()}catch{}}async function s(e){try{return await e()}catch(e){if(r(e,`ENOENT`))return;throw e}}async function c(t,{beforeRetry:n,handleError:r,retryCount:i=3,retryLogger:a,shouldRetry:o,getSleepMilliseconds:s,sleepMilliseconds:c=0,updateSleepMilliseconds:l}={}){let u=0;for(;;)try{return await t(u)}catch(t){if(await r?.(t),u++,u>=i||o&&!o(t))throw t;let d=s?.(t,c)??c;d>0&&await e.sleep(d),l&&(c=l(c)),a?.(`Retry due to: ${t}
|
|
2
2
|
${t instanceof Error?`---
|
|
3
3
|
`+(t.stack??``):``}`),await n?.(t)}}exports.errorify=t,exports.getErrorMessage=n,exports.hasErrorCode=r,exports.ignoreEnoent=a,exports.ignoreEnoentAsync=s,exports.ignoreError=i,exports.ignoreErrorAsync=o,exports.withRetry=c;
|
|
4
4
|
//# sourceMappingURL=error.cjs.map
|
package/dist/error.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.cjs","names":["sleep"],"sources":["../src/error.ts"],"sourcesContent":["import { sleep } from './sleep.js';\n\n/**\n * Convert an object to an error.\n * @param obj The object to convert.\n */\nexport function errorify(obj: unknown): Error {\n if (obj instanceof Error) return obj;\n if (typeof obj === 'string') return new Error(obj);\n // `JSON.stringify` answers `undefined` for `undefined`, a symbol and a function, and throws\n // on a bigint or a cycle; `new Error(undefined)` has an empty message, which would drop the\n // only diagnostic a caller has about such a thrown value. Neither representation may throw\n // out of here: this runs in a catch block, where it would replace the error it converts.\n return new Error(ignoreError(() => JSON.stringify(obj)) ?? ignoreError(() => String(obj)));\n}\n\n/**\n * Returns the message of a thrown `Error
|
|
1
|
+
{"version":3,"file":"error.cjs","names":["sleep"],"sources":["../src/error.ts"],"sourcesContent":["import { sleep } from './sleep.js';\n\n/**\n * Convert an object to an error.\n * @param obj The object to convert.\n */\nexport function errorify(obj: unknown): Error {\n if (obj instanceof Error) return obj;\n if (typeof obj === 'string') return new Error(obj);\n // `JSON.stringify` answers `undefined` for `undefined`, a symbol and a function, and throws\n // on a bigint or a cycle; `new Error(undefined)` has an empty message, which would drop the\n // only diagnostic a caller has about such a thrown value. Neither representation may throw\n // out of here: this runs in a catch block, where it would replace the error it converts.\n return new Error(ignoreError(() => JSON.stringify(obj)) ?? ignoreError(() => String(obj)));\n}\n\n/**\n * Returns the message of a thrown `Error`; for any other thrown value, `fallback` if given, or else its string form.\n * `fallback` is also returned when reading the message throws. Never throws, so it is safe to call in a catch block.\n */\nexport function getErrorMessage(error: unknown, fallback?: string): string {\n // `String` throws for an object without a prototype, and even `instanceof`, a `message` getter, and\n // `Object.prototype.toString` throw for a proxy or object whose traps or getters throw.\n return (\n ignoreError(() => (error instanceof Error ? error.message : (fallback ?? String(error)))) ??\n fallback ??\n ignoreError(() => Object.prototype.toString.call(error)) ??\n 'Unknown error'\n );\n}\n\n/** Whether a thrown value carries the given `code`, such as a Node.js errno code (`ENOENT`, `EEXIST`, ...). */\nexport function hasErrorCode<C extends string>(error: unknown, code: C): error is { code: C } {\n return typeof error === 'object' && error !== null && 'code' in error && error.code === code;\n}\n\nexport function ignoreError<T>(fn: () => T): T | undefined {\n try {\n return fn();\n } catch {\n // do nothing\n }\n}\n\nexport function ignoreEnoent<T>(fn: () => T): T | undefined {\n try {\n return fn();\n } catch (error) {\n if (hasErrorCode(error, 'ENOENT')) return;\n throw error;\n }\n}\n\nexport async function ignoreErrorAsync<T>(fn: () => Promise<T>): Promise<T | undefined> {\n try {\n return await fn();\n } catch {\n // do nothing\n }\n}\n\nexport async function ignoreEnoentAsync<T>(fn: () => Promise<T>): Promise<T | undefined> {\n try {\n return await fn();\n } catch (error) {\n if (hasErrorCode(error, 'ENOENT')) return;\n throw error;\n }\n}\n\nexport interface RetryOptions {\n beforeRetry?: (error: unknown) => Promise<void>;\n handleError?: (error: unknown) => Promise<void>;\n /**\n * The maximum number of total attempts, including the initial attempt.\n * For example, `retryCount: 3` runs the function at most 3 times: 1 initial attempt and up to 2 retries.\n */\n retryCount?: number;\n retryLogger?: (message: string) => void;\n shouldRetry?: (error: unknown) => boolean;\n /**\n * Decides how long to wait before retrying after `error`, given the backoff `sleepMilliseconds` it would otherwise wait,\n * e.g. `(error, ms) => Math.max(ms, retryAtOf(error) - Date.now())` to honor a retry time sent by a server.\n * It does not affect the backoff that `updateSleepMilliseconds` advances.\n */\n getSleepMilliseconds?: (error: unknown, sleepMilliseconds: number) => number;\n sleepMilliseconds?: number;\n updateSleepMilliseconds?: (sleepMilliseconds: number) => number;\n}\n\n/**\n * Retry the given function.\n * @param func The function to retry.\n * @param beforeRetry The function to call immediately before retrying.\n * @param handleError The function to call when an error occurs.\n * @param retryCount The maximum number of total attempts, including the initial attempt.\n * @param retryLogger The function to log retrying.\n * @param sleepMilliseconds The number of milliseconds to sleep before retrying.\n * @param updateSleepMilliseconds The function to update sleep milliseconds after each retry.\n */\nexport async function withRetry<T>(\n func: (failedCount: number) => T | Promise<T>,\n {\n beforeRetry,\n handleError,\n retryCount = 3,\n retryLogger,\n shouldRetry,\n getSleepMilliseconds,\n sleepMilliseconds = 0,\n updateSleepMilliseconds,\n }: RetryOptions = {}\n): Promise<T> {\n let failedCount = 0;\n for (;;) {\n try {\n return await func(failedCount);\n } catch (error) {\n await handleError?.(error);\n failedCount++;\n if (failedCount >= retryCount) {\n throw error;\n }\n if (shouldRetry && !shouldRetry(error)) {\n throw error;\n }\n const currentSleepMilliseconds = getSleepMilliseconds?.(error, sleepMilliseconds) ?? sleepMilliseconds;\n if (currentSleepMilliseconds > 0) {\n await sleep(currentSleepMilliseconds);\n }\n if (updateSleepMilliseconds) {\n sleepMilliseconds = updateSleepMilliseconds(sleepMilliseconds);\n }\n retryLogger?.(`Retry due to: ${error}\n${error instanceof Error ? '---\\n' + (error.stack ?? '') : ''}`);\n await beforeRetry?.(error);\n }\n }\n}\n"],"mappings":"4CAMA,SAAgB,EAAS,EAAqB,CAO5C,OANI,aAAe,MAAc,EACO,MAApC,OAAO,GAAQ,SAA2B,EAK7B,MAAkB,KAAK,UAAU,CAAG,CAAC,GAAK,MAAkB,OAAO,CAAG,CAAC,CALvC,CAMnD,CAMA,SAAgB,EAAgB,EAAgB,EAA2B,CAGzE,OACE,MAAmB,aAAiB,MAAQ,EAAM,QAAW,GAAY,OAAO,CAAK,CAAG,GACxF,GACA,MAAkB,OAAO,UAAU,SAAS,KAAK,CAAK,CAAC,GACvD,eAEJ,CAGA,SAAgB,EAA+B,EAAgB,EAA+B,CAC5F,OAAO,OAAO,GAAU,YAAY,GAAkB,SAAU,GAAS,EAAM,OAAS,CAC1F,CAEA,SAAgB,EAAe,EAA4B,CACzD,GAAI,CACF,OAAO,EAAG,CACZ,MAAQ,CAER,CACF,CAEA,SAAgB,EAAgB,EAA4B,CAC1D,GAAI,CACF,OAAO,EAAG,CACZ,OAAS,EAAO,CACd,GAAI,EAAa,EAAO,QAAQ,EAAG,OACnC,MAAM,CACR,CACF,CAEA,eAAsB,EAAoB,EAA8C,CACtF,GAAI,CACF,OAAO,MAAM,EAAG,CAClB,MAAQ,CAER,CACF,CAEA,eAAsB,EAAqB,EAA8C,CACvF,GAAI,CACF,OAAO,MAAM,EAAG,CAClB,OAAS,EAAO,CACd,GAAI,EAAa,EAAO,QAAQ,EAAG,OACnC,MAAM,CACR,CACF,CAgCA,eAAsB,EACpB,EACA,CACE,cACA,cACA,aAAa,EACb,cACA,cACA,uBACA,oBAAoB,EACpB,2BACgB,CAAC,EACP,CACZ,IAAI,EAAc,EAClB,OACE,GAAI,CACF,OAAO,MAAM,EAAK,CAAW,CAC/B,OAAS,EAAO,CAMd,GALA,MAAM,IAAc,CAAK,EACzB,IACI,GAAe,GAGf,GAAe,CAAC,EAAY,CAAK,EACnC,MAAM,EAER,IAAM,EAA2B,IAAuB,EAAO,CAAiB,GAAK,EACjF,EAA2B,GAC7B,MAAMA,EAAAA,MAAM,CAAwB,EAElC,IACF,EAAoB,EAAwB,CAAiB,GAE/D,IAAc,iBAAiB,EAAM;EACzC,aAAiB,MAAQ;GAAW,EAAM,OAAS,IAAM,IAAI,EACzD,MAAM,IAAc,CAAK,CAC3B,CAEJ"}
|
package/dist/error.d.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export declare function errorify(obj: unknown): Error;
|
|
6
6
|
/**
|
|
7
|
-
* Returns the message of a thrown `Error
|
|
8
|
-
* Never throws, so it is safe to call in a catch block.
|
|
7
|
+
* Returns the message of a thrown `Error`; for any other thrown value, `fallback` if given, or else its string form.
|
|
8
|
+
* `fallback` is also returned when reading the message throws. Never throws, so it is safe to call in a catch block.
|
|
9
9
|
*/
|
|
10
|
-
export declare function getErrorMessage(error: unknown): string;
|
|
10
|
+
export declare function getErrorMessage(error: unknown, fallback?: string): string;
|
|
11
11
|
/** Whether a thrown value carries the given `code`, such as a Node.js errno code (`ENOENT`, `EEXIST`, ...). */
|
|
12
12
|
export declare function hasErrorCode<C extends string>(error: unknown, code: C): error is {
|
|
13
13
|
code: C;
|
package/dist/error.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{sleep as e}from"./sleep.js";function t(e){return e instanceof Error?e:Error(typeof e==`string`?e:i(()=>JSON.stringify(e))??i(()=>String(e)))}function n(e){return i(()=>e instanceof Error?e.message:String(e))??i(()=>Object.prototype.toString.call(e))??`Unknown error`}function r(e,t){return typeof e==`object`&&!!e&&`code`in e&&e.code===t}function i(e){try{return e()}catch{}}function a(e){try{return e()}catch(e){if(r(e,`ENOENT`))return;throw e}}async function o(e){try{return await e()}catch{}}async function s(e){try{return await e()}catch(e){if(r(e,`ENOENT`))return;throw e}}async function c(t,{beforeRetry:n,handleError:r,retryCount:i=3,retryLogger:a,shouldRetry:o,getSleepMilliseconds:s,sleepMilliseconds:c=0,updateSleepMilliseconds:l}={}){let u=0;for(;;)try{return await t(u)}catch(t){if(await r?.(t),u++,u>=i||o&&!o(t))throw t;let d=s?.(t,c)??c;d>0&&await e(d),l&&(c=l(c)),a?.(`Retry due to: ${t}
|
|
1
|
+
import{sleep as e}from"./sleep.js";function t(e){return e instanceof Error?e:Error(typeof e==`string`?e:i(()=>JSON.stringify(e))??i(()=>String(e)))}function n(e,t){return i(()=>e instanceof Error?e.message:t??String(e))??t??i(()=>Object.prototype.toString.call(e))??`Unknown error`}function r(e,t){return typeof e==`object`&&!!e&&`code`in e&&e.code===t}function i(e){try{return e()}catch{}}function a(e){try{return e()}catch(e){if(r(e,`ENOENT`))return;throw e}}async function o(e){try{return await e()}catch{}}async function s(e){try{return await e()}catch(e){if(r(e,`ENOENT`))return;throw e}}async function c(t,{beforeRetry:n,handleError:r,retryCount:i=3,retryLogger:a,shouldRetry:o,getSleepMilliseconds:s,sleepMilliseconds:c=0,updateSleepMilliseconds:l}={}){let u=0;for(;;)try{return await t(u)}catch(t){if(await r?.(t),u++,u>=i||o&&!o(t))throw t;let d=s?.(t,c)??c;d>0&&await e(d),l&&(c=l(c)),a?.(`Retry due to: ${t}
|
|
2
2
|
${t instanceof Error?`---
|
|
3
3
|
`+(t.stack??``):``}`),await n?.(t)}}export{t as errorify,n as getErrorMessage,r as hasErrorCode,a as ignoreEnoent,s as ignoreEnoentAsync,i as ignoreError,o as ignoreErrorAsync,c as withRetry};
|
|
4
4
|
//# sourceMappingURL=error.js.map
|
package/dist/error.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","names":[],"sources":["../src/error.ts"],"sourcesContent":["import { sleep } from './sleep.js';\n\n/**\n * Convert an object to an error.\n * @param obj The object to convert.\n */\nexport function errorify(obj: unknown): Error {\n if (obj instanceof Error) return obj;\n if (typeof obj === 'string') return new Error(obj);\n // `JSON.stringify` answers `undefined` for `undefined`, a symbol and a function, and throws\n // on a bigint or a cycle; `new Error(undefined)` has an empty message, which would drop the\n // only diagnostic a caller has about such a thrown value. Neither representation may throw\n // out of here: this runs in a catch block, where it would replace the error it converts.\n return new Error(ignoreError(() => JSON.stringify(obj)) ?? ignoreError(() => String(obj)));\n}\n\n/**\n * Returns the message of a thrown `Error
|
|
1
|
+
{"version":3,"file":"error.js","names":[],"sources":["../src/error.ts"],"sourcesContent":["import { sleep } from './sleep.js';\n\n/**\n * Convert an object to an error.\n * @param obj The object to convert.\n */\nexport function errorify(obj: unknown): Error {\n if (obj instanceof Error) return obj;\n if (typeof obj === 'string') return new Error(obj);\n // `JSON.stringify` answers `undefined` for `undefined`, a symbol and a function, and throws\n // on a bigint or a cycle; `new Error(undefined)` has an empty message, which would drop the\n // only diagnostic a caller has about such a thrown value. Neither representation may throw\n // out of here: this runs in a catch block, where it would replace the error it converts.\n return new Error(ignoreError(() => JSON.stringify(obj)) ?? ignoreError(() => String(obj)));\n}\n\n/**\n * Returns the message of a thrown `Error`; for any other thrown value, `fallback` if given, or else its string form.\n * `fallback` is also returned when reading the message throws. Never throws, so it is safe to call in a catch block.\n */\nexport function getErrorMessage(error: unknown, fallback?: string): string {\n // `String` throws for an object without a prototype, and even `instanceof`, a `message` getter, and\n // `Object.prototype.toString` throw for a proxy or object whose traps or getters throw.\n return (\n ignoreError(() => (error instanceof Error ? error.message : (fallback ?? String(error)))) ??\n fallback ??\n ignoreError(() => Object.prototype.toString.call(error)) ??\n 'Unknown error'\n );\n}\n\n/** Whether a thrown value carries the given `code`, such as a Node.js errno code (`ENOENT`, `EEXIST`, ...). */\nexport function hasErrorCode<C extends string>(error: unknown, code: C): error is { code: C } {\n return typeof error === 'object' && error !== null && 'code' in error && error.code === code;\n}\n\nexport function ignoreError<T>(fn: () => T): T | undefined {\n try {\n return fn();\n } catch {\n // do nothing\n }\n}\n\nexport function ignoreEnoent<T>(fn: () => T): T | undefined {\n try {\n return fn();\n } catch (error) {\n if (hasErrorCode(error, 'ENOENT')) return;\n throw error;\n }\n}\n\nexport async function ignoreErrorAsync<T>(fn: () => Promise<T>): Promise<T | undefined> {\n try {\n return await fn();\n } catch {\n // do nothing\n }\n}\n\nexport async function ignoreEnoentAsync<T>(fn: () => Promise<T>): Promise<T | undefined> {\n try {\n return await fn();\n } catch (error) {\n if (hasErrorCode(error, 'ENOENT')) return;\n throw error;\n }\n}\n\nexport interface RetryOptions {\n beforeRetry?: (error: unknown) => Promise<void>;\n handleError?: (error: unknown) => Promise<void>;\n /**\n * The maximum number of total attempts, including the initial attempt.\n * For example, `retryCount: 3` runs the function at most 3 times: 1 initial attempt and up to 2 retries.\n */\n retryCount?: number;\n retryLogger?: (message: string) => void;\n shouldRetry?: (error: unknown) => boolean;\n /**\n * Decides how long to wait before retrying after `error`, given the backoff `sleepMilliseconds` it would otherwise wait,\n * e.g. `(error, ms) => Math.max(ms, retryAtOf(error) - Date.now())` to honor a retry time sent by a server.\n * It does not affect the backoff that `updateSleepMilliseconds` advances.\n */\n getSleepMilliseconds?: (error: unknown, sleepMilliseconds: number) => number;\n sleepMilliseconds?: number;\n updateSleepMilliseconds?: (sleepMilliseconds: number) => number;\n}\n\n/**\n * Retry the given function.\n * @param func The function to retry.\n * @param beforeRetry The function to call immediately before retrying.\n * @param handleError The function to call when an error occurs.\n * @param retryCount The maximum number of total attempts, including the initial attempt.\n * @param retryLogger The function to log retrying.\n * @param sleepMilliseconds The number of milliseconds to sleep before retrying.\n * @param updateSleepMilliseconds The function to update sleep milliseconds after each retry.\n */\nexport async function withRetry<T>(\n func: (failedCount: number) => T | Promise<T>,\n {\n beforeRetry,\n handleError,\n retryCount = 3,\n retryLogger,\n shouldRetry,\n getSleepMilliseconds,\n sleepMilliseconds = 0,\n updateSleepMilliseconds,\n }: RetryOptions = {}\n): Promise<T> {\n let failedCount = 0;\n for (;;) {\n try {\n return await func(failedCount);\n } catch (error) {\n await handleError?.(error);\n failedCount++;\n if (failedCount >= retryCount) {\n throw error;\n }\n if (shouldRetry && !shouldRetry(error)) {\n throw error;\n }\n const currentSleepMilliseconds = getSleepMilliseconds?.(error, sleepMilliseconds) ?? sleepMilliseconds;\n if (currentSleepMilliseconds > 0) {\n await sleep(currentSleepMilliseconds);\n }\n if (updateSleepMilliseconds) {\n sleepMilliseconds = updateSleepMilliseconds(sleepMilliseconds);\n }\n retryLogger?.(`Retry due to: ${error}\n${error instanceof Error ? '---\\n' + (error.stack ?? '') : ''}`);\n await beforeRetry?.(error);\n }\n }\n}\n"],"mappings":"mCAMA,SAAgB,EAAS,EAAqB,CAO5C,OANI,aAAe,MAAc,EACO,MAApC,OAAO,GAAQ,SAA2B,EAK7B,MAAkB,KAAK,UAAU,CAAG,CAAC,GAAK,MAAkB,OAAO,CAAG,CAAC,CALvC,CAMnD,CAMA,SAAgB,EAAgB,EAAgB,EAA2B,CAGzE,OACE,MAAmB,aAAiB,MAAQ,EAAM,QAAW,GAAY,OAAO,CAAK,CAAG,GACxF,GACA,MAAkB,OAAO,UAAU,SAAS,KAAK,CAAK,CAAC,GACvD,eAEJ,CAGA,SAAgB,EAA+B,EAAgB,EAA+B,CAC5F,OAAO,OAAO,GAAU,YAAY,GAAkB,SAAU,GAAS,EAAM,OAAS,CAC1F,CAEA,SAAgB,EAAe,EAA4B,CACzD,GAAI,CACF,OAAO,EAAG,CACZ,MAAQ,CAER,CACF,CAEA,SAAgB,EAAgB,EAA4B,CAC1D,GAAI,CACF,OAAO,EAAG,CACZ,OAAS,EAAO,CACd,GAAI,EAAa,EAAO,QAAQ,EAAG,OACnC,MAAM,CACR,CACF,CAEA,eAAsB,EAAoB,EAA8C,CACtF,GAAI,CACF,OAAO,MAAM,EAAG,CAClB,MAAQ,CAER,CACF,CAEA,eAAsB,EAAqB,EAA8C,CACvF,GAAI,CACF,OAAO,MAAM,EAAG,CAClB,OAAS,EAAO,CACd,GAAI,EAAa,EAAO,QAAQ,EAAG,OACnC,MAAM,CACR,CACF,CAgCA,eAAsB,EACpB,EACA,CACE,cACA,cACA,aAAa,EACb,cACA,cACA,uBACA,oBAAoB,EACpB,2BACgB,CAAC,EACP,CACZ,IAAI,EAAc,EAClB,OACE,GAAI,CACF,OAAO,MAAM,EAAK,CAAW,CAC/B,OAAS,EAAO,CAMd,GALA,MAAM,IAAc,CAAK,EACzB,IACI,GAAe,GAGf,GAAe,CAAC,EAAY,CAAK,EACnC,MAAM,EAER,IAAM,EAA2B,IAAuB,EAAO,CAAiB,GAAK,EACjF,EAA2B,GAC7B,MAAM,EAAM,CAAwB,EAElC,IACF,EAAoB,EAAwB,CAAiB,GAE/D,IAAc,iBAAiB,EAAM;EACzC,aAAiB,MAAQ;GAAW,EAAM,OAAS,IAAM,IAAI,EACzD,MAAM,IAAc,CAAK,CAC3B,CAEJ"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./appEnv.cjs"),t=require("./array.cjs"),n=require("./assert.cjs"),r=require("./concurrency.cjs"),i=require("./
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./appEnv.cjs"),t=require("./array.cjs"),n=require("./assert.cjs"),r=require("./concurrency.cjs"),i=require("./crypto.cjs"),a=require("./githubTemplates.cjs"),o=require("./sleep.cjs"),s=require("./error.cjs"),c=require("./filePath.cjs"),l=require("./formatIsoDate.cjs"),u=require("./github.cjs"),d=require("./http.cjs"),f=require("./foreignCjk.cjs"),p=require("./humanize.cjs"),m=require("./mail.cjs"),h=require("./object.cjs"),g=require("./markdown.cjs"),_=require("./parseIsoDate.cjs"),v=require("./parseCommandLineArgs.cjs"),y=require("./number.cjs"),b=require("./text.cjs"),x=require("./prompt.cjs"),S=require("./promptFormatters.cjs"),C=require("./shuffle.cjs"),w=require("./recoverJson.cjs"),T=require("./sqlite.cjs"),E=require("./testingRules.cjs"),D=require("./throttledFetch.cjs"),O=require("./timeout.cjs"),k=require("./url.cjs"),A=require("./yaml.cjs"),j=require("./zenkaku.cjs");exports.BUG_ISSUE_SECTIONS=a.BUG_ISSUE_SECTIONS,exports.CHANGE_ISSUE_SECTIONS=a.CHANGE_ISSUE_SECTIONS,exports.ISSUE_TEMPLATE_RULES=a.ISSUE_TEMPLATE_RULES,exports.PULL_REQUEST_BODY_RULES=a.PULL_REQUEST_BODY_RULES,exports.PULL_REQUEST_REQUIREMENTS_RULES=a.PULL_REQUEST_REQUIREMENTS_RULES,exports.PULL_REQUEST_SECTIONS=a.PULL_REQUEST_SECTIONS,exports.TEST_WRITING_RULES=E.TEST_WRITING_RULES,exports.chunk=t.chunk,exports.clamp=y.clamp,exports.createThrottledFetch=D.createThrottledFetch,exports.detectForeignCjkInJapanese=f.detectForeignCjkInJapanese,exports.ensureTruthy=n.ensureTruthy,exports.errorify=s.errorify,exports.escapeHtml=b.escapeHtml,exports.escapeLikePattern=T.escapeLikePattern,exports.escapePromptTag=x.escapePromptTag,exports.escapeRegExp=b.escapeRegExp,exports.extractCodeBlocks=g.extractCodeBlocks,exports.extractIfSingleOutermostCodeBlock=g.extractIfSingleOutermostCodeBlock,exports.extractSections=g.extractSections,exports.extractTaggedCodeBlock=g.extractTaggedCodeBlock,exports.findForeignCjkCharactersInJapanese=f.findForeignCjkCharactersInJapanese,exports.forEachConcurrently=r.forEachConcurrently,exports.formatDuration=p.formatDuration,exports.formatElapsedTimeInJapanese=p.formatElapsedTimeInJapanese,exports.formatFilesForPrompt=S.formatFilesForPrompt,exports.formatIsoDateInTimeZone=l.formatIsoDateInTimeZone,exports.formatMessagesForPrompt=S.formatMessagesForPrompt,exports.formatPrompt=x.formatPrompt,exports.getAppEnv=e.getAppEnv,exports.getConnectionLevelSqlitePragmas=T.getConnectionLevelSqlitePragmas,exports.getErrorMessage=s.getErrorMessage,exports.getFileExtension=c.getFileExtension,exports.getFormString=d.getFormString,exports.getPersistentSqlitePragmas=T.getPersistentSqlitePragmas,exports.getSafeRedirectPath=k.getSafeRedirectPath,exports.hasErrorCode=s.hasErrorCode,exports.humanizeNumber=p.humanizeNumber,exports.ignoreEnoent=s.ignoreEnoent,exports.ignoreEnoentAsync=s.ignoreEnoentAsync,exports.ignoreError=s.ignoreError,exports.ignoreErrorAsync=s.ignoreErrorAsync,exports.isRecord=h.isRecord,exports.mailTemplates=m.mailTemplates,exports.mapConcurrently=r.mapConcurrently,exports.omitUndefined=h.omitUndefined,exports.parseBearerToken=d.parseBearerToken,exports.parseCommandLineArgs=v.parseCommandLineArgs,exports.parseGitHubRepositoryFullName=u.parseGitHubRepositoryFullName,exports.parseIsoDate=_.parseIsoDate,exports.parseMarkdownSections=g.parseMarkdownSections,exports.parsePositiveInteger=y.parsePositiveInteger,exports.quoteForShell=b.quoteForShell,exports.raceWithTimeout=O.raceWithTimeout,exports.recoverJson=w.recoverJson,exports.renderSectionChecklist=a.renderSectionChecklist,exports.renderSectionTemplate=a.renderSectionTemplate,exports.serializeForPrompt=x.serializeForPrompt,exports.serializeForPromptInTag=x.serializeForPromptInTag,exports.sha256HexAsync=i.sha256HexAsync,exports.shuffle=C.shuffle,exports.shuffleWithSeed=C.shuffleWithSeed,exports.sleep=o.sleep,exports.timingSafeEqualStringAsync=i.timingSafeEqualStringAsync,exports.toCodeBlock=b.toCodeBlock,exports.toTildeCodeBlock=b.toTildeCodeBlock,exports.truncate=b.truncate,exports.truncateForPrompt=x.truncateForPrompt,exports.withRetry=s.withRetry,exports.yamlStringifyOptions=A.yamlStringifyOptions,exports.zenkakuAlphanumericalsToHankaku=j.zenkakuAlphanumericalsToHankaku;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { getAppEnv } from './appEnv.js';
|
|
|
2
2
|
export { chunk } from './array.js';
|
|
3
3
|
export { ensureTruthy } from './assert.js';
|
|
4
4
|
export { forEachConcurrently, mapConcurrently } from './concurrency.js';
|
|
5
|
+
export { sha256HexAsync, timingSafeEqualStringAsync } from './crypto.js';
|
|
5
6
|
export { BUG_ISSUE_SECTIONS, CHANGE_ISSUE_SECTIONS, ISSUE_TEMPLATE_RULES, PULL_REQUEST_BODY_RULES, PULL_REQUEST_REQUIREMENTS_RULES, PULL_REQUEST_SECTIONS, renderSectionChecklist, renderSectionTemplate, } from './githubTemplates.js';
|
|
6
7
|
export { errorify, getErrorMessage, hasErrorCode, ignoreError, ignoreEnoent, ignoreErrorAsync, ignoreEnoentAsync, withRetry, } from './error.js';
|
|
7
8
|
export { getFileExtension } from './filePath.js';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getAppEnv as e}from"./appEnv.js";import{chunk as t}from"./array.js";import{ensureTruthy as n}from"./assert.js";import{forEachConcurrently as r,mapConcurrently as i}from"./concurrency.js";import{
|
|
1
|
+
import{getAppEnv as e}from"./appEnv.js";import{chunk as t}from"./array.js";import{ensureTruthy as n}from"./assert.js";import{forEachConcurrently as r,mapConcurrently as i}from"./concurrency.js";import{sha256HexAsync as a,timingSafeEqualStringAsync as o}from"./crypto.js";import{BUG_ISSUE_SECTIONS as s,CHANGE_ISSUE_SECTIONS as c,ISSUE_TEMPLATE_RULES as l,PULL_REQUEST_BODY_RULES as u,PULL_REQUEST_REQUIREMENTS_RULES as d,PULL_REQUEST_SECTIONS as f,renderSectionChecklist as p,renderSectionTemplate as m}from"./githubTemplates.js";import{sleep as h}from"./sleep.js";import{errorify as g,getErrorMessage as _,hasErrorCode as v,ignoreEnoent as y,ignoreEnoentAsync as b,ignoreError as x,ignoreErrorAsync as S,withRetry as C}from"./error.js";import{getFileExtension as w}from"./filePath.js";import{formatIsoDateInTimeZone as T}from"./formatIsoDate.js";import{parseGitHubRepositoryFullName as E}from"./github.js";import{getFormString as D,parseBearerToken as O}from"./http.js";import{detectForeignCjkInJapanese as k,findForeignCjkCharactersInJapanese as A}from"./foreignCjk.js";import{formatDuration as j,formatElapsedTimeInJapanese as M,humanizeNumber as N}from"./humanize.js";import{mailTemplates as P}from"./mail.js";import{isRecord as F,omitUndefined as I}from"./object.js";import{extractCodeBlocks as L,extractIfSingleOutermostCodeBlock as R,extractSections as z,extractTaggedCodeBlock as B,parseMarkdownSections as V}from"./markdown.js";import{parseIsoDate as H}from"./parseIsoDate.js";import{parseCommandLineArgs as U}from"./parseCommandLineArgs.js";import{clamp as W,parsePositiveInteger as G}from"./number.js";import{escapeHtml as K,escapeRegExp as q,quoteForShell as J,toCodeBlock as Y,toTildeCodeBlock as X,truncate as Z}from"./text.js";import{escapePromptTag as Q,formatPrompt as $,serializeForPrompt as ee,serializeForPromptInTag as te,truncateForPrompt as ne}from"./prompt.js";import{formatFilesForPrompt as re,formatMessagesForPrompt as ie}from"./promptFormatters.js";import{shuffle as ae,shuffleWithSeed as oe}from"./shuffle.js";import{recoverJson as se}from"./recoverJson.js";import{escapeLikePattern as ce,getConnectionLevelSqlitePragmas as le,getPersistentSqlitePragmas as ue}from"./sqlite.js";import{TEST_WRITING_RULES as de}from"./testingRules.js";import{createThrottledFetch as fe}from"./throttledFetch.js";import{raceWithTimeout as pe}from"./timeout.js";import{getSafeRedirectPath as me}from"./url.js";import{yamlStringifyOptions as he}from"./yaml.js";import{zenkakuAlphanumericalsToHankaku as ge}from"./zenkaku.js";export{s as BUG_ISSUE_SECTIONS,c as CHANGE_ISSUE_SECTIONS,l as ISSUE_TEMPLATE_RULES,u as PULL_REQUEST_BODY_RULES,d as PULL_REQUEST_REQUIREMENTS_RULES,f as PULL_REQUEST_SECTIONS,de as TEST_WRITING_RULES,t as chunk,W as clamp,fe as createThrottledFetch,k as detectForeignCjkInJapanese,n as ensureTruthy,g as errorify,K as escapeHtml,ce as escapeLikePattern,Q as escapePromptTag,q as escapeRegExp,L as extractCodeBlocks,R as extractIfSingleOutermostCodeBlock,z as extractSections,B as extractTaggedCodeBlock,A as findForeignCjkCharactersInJapanese,r as forEachConcurrently,j as formatDuration,M as formatElapsedTimeInJapanese,re as formatFilesForPrompt,T as formatIsoDateInTimeZone,ie as formatMessagesForPrompt,$ as formatPrompt,e as getAppEnv,le as getConnectionLevelSqlitePragmas,_ as getErrorMessage,w as getFileExtension,D as getFormString,ue as getPersistentSqlitePragmas,me as getSafeRedirectPath,v as hasErrorCode,N as humanizeNumber,y as ignoreEnoent,b as ignoreEnoentAsync,x as ignoreError,S as ignoreErrorAsync,F as isRecord,P as mailTemplates,i as mapConcurrently,I as omitUndefined,O as parseBearerToken,U as parseCommandLineArgs,E as parseGitHubRepositoryFullName,H as parseIsoDate,V as parseMarkdownSections,G as parsePositiveInteger,J as quoteForShell,pe as raceWithTimeout,se as recoverJson,p as renderSectionChecklist,m as renderSectionTemplate,ee as serializeForPrompt,te as serializeForPromptInTag,a as sha256HexAsync,ae as shuffle,oe as shuffleWithSeed,h as sleep,o as timingSafeEqualStringAsync,Y as toCodeBlock,X as toTildeCodeBlock,Z as truncate,ne as truncateForPrompt,C as withRetry,he as yamlStringifyOptions,ge as zenkakuAlphanumericalsToHankaku};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@willbooster/shared-lib",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.19.1",
|
|
4
4
|
"description": "Shared library for WillBooster projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@types/node": "26.6.2",
|
|
51
51
|
"@willbooster/oxfmt-config": "1.2.2",
|
|
52
52
|
"@willbooster/oxlint-config": "1.4.8",
|
|
53
|
-
"@willbooster/wb": "22.
|
|
53
|
+
"@willbooster/wb": "22.13.3",
|
|
54
54
|
"build-ts": "21.0.19",
|
|
55
55
|
"oxfmt": "0.68.0",
|
|
56
56
|
"oxlint": "1.83.0",
|