🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@n8n/utils

Package Overview
Dependencies
Maintainers
5
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@n8n/utils - npm Package Compare versions

Comparing version
1.39.0
to
1.40.0
+1
dist/errors/ensure-error.cjs.map
{"version":3,"file":"ensure-error.cjs","names":[],"sources":["../../src/errors/ensure-error.ts"],"sourcesContent":["/** Ensures `error` is an `Error */\nexport function ensureError(error: unknown): Error {\n\treturn error instanceof Error\n\t\t? error\n\t\t: new Error('Error that was not an instance of Error was thrown', {\n\t\t\t\t// We should never throw anything except something that derives from Error\n\t\t\t\tcause: error,\n\t\t\t});\n}\n"],"mappings":";;;AACA,SAAgB,YAAY,OAAuB;CAClD,OAAO,iBAAiB,QACrB,QACA,IAAI,MAAM,sDAAsD,EAEhE,OAAO,MACR,CAAC;AACJ"}
{"version":3,"file":"ensure-error.mjs","names":[],"sources":["../../src/errors/ensure-error.ts"],"sourcesContent":["/** Ensures `error` is an `Error */\nexport function ensureError(error: unknown): Error {\n\treturn error instanceof Error\n\t\t? error\n\t\t: new Error('Error that was not an instance of Error was thrown', {\n\t\t\t\t// We should never throw anything except something that derives from Error\n\t\t\t\tcause: error,\n\t\t\t});\n}\n"],"mappings":";;AACA,SAAgB,YAAY,OAAuB;CAClD,OAAO,iBAAiB,QACrB,QACA,IAAI,MAAM,sDAAsD,EAEhE,OAAO,MACR,CAAC;AACJ"}
{"version":3,"file":"format-pem-block.cjs","names":[],"sources":["../src/format-pem-block.ts"],"sourcesContent":["const PEM_BODY_LINE_LENGTH = 64;\n\nfunction formatCompactPem(pem: string, isPublic: boolean): string | undefined {\n\tconst trimmed = pem.trim();\n\tif ((trimmed.match(/-----BEGIN /g) ?? []).length !== 1) return undefined;\n\n\tconst labelPattern = isPublic ? '[A-Z0-9 ]*PUBLIC KEY' : '[A-Z0-9 ]*PRIVATE KEY|CERTIFICATE';\n\tconst pemMatch = trimmed.match(\n\t\tnew RegExp(`^-----BEGIN (${labelPattern})-----([\\\\s\\\\S]*?)-----END \\\\1-----$`),\n\t);\n\n\tif (!pemMatch) return undefined;\n\n\tconst [, label, body] = pemMatch;\n\tconst normalizedBody = body.replace(/\\\\n/g, '\\n').trim();\n\tconst formattedBody = /\\s/.test(normalizedBody)\n\t\t? normalizedBody.replace(/:\\s+/g, ':').replace(/\\s+/g, '\\n')\n\t\t: (normalizedBody.match(new RegExp(`.{1,${PEM_BODY_LINE_LENGTH}}`, 'g')) ?? []).join('\\n');\n\n\treturn `-----BEGIN ${label}-----\\n${formattedBody}\\n-----END ${label}-----`;\n}\n\n/**\n * Normalize a single PEM-encoded block (private key, public key, or certificate)\n * by collapsing whitespace and wrapping the body at 64 chars. Multi-block PEM\n * chains are returned unchanged.\n *\n * @param pem - The PEM-encoded block to format.\n * @param isPublic - When true, match `PUBLIC KEY` labels instead of the default `PRIVATE KEY` / `CERTIFICATE`.\n * @returns The formatted PEM block.\n */\nexport function formatPemBlock(pem: string, isPublic = false): string {\n\tlet regex = /(PRIVATE KEY|CERTIFICATE)/;\n\tif (isPublic) {\n\t\tregex = /(PUBLIC KEY)/;\n\t}\n\tif (!pem || /\\n/.test(pem)) {\n\t\treturn pem;\n\t}\n\tconst compactPem = formatCompactPem(pem, isPublic);\n\tif (compactPem !== undefined) {\n\t\treturn compactPem;\n\t}\n\n\tlet formattedPem = '';\n\tconst parts = pem.split('-----').filter((item) => item !== '');\n\tparts.forEach((part) => {\n\t\tif (regex.test(part)) {\n\t\t\tformattedPem += `-----${part}-----`;\n\t\t} else {\n\t\t\tconst passRegex = /Proc-Type|DEK-Info/;\n\t\t\tif (passRegex.test(part)) {\n\t\t\t\tpart = part.replace(/:\\s+/g, ':');\n\t\t\t\tformattedPem += part.replace(/\\\\n/g, '\\n').replace(/\\s+/g, '\\n');\n\t\t\t} else {\n\t\t\t\tformattedPem += part.replace(/\\\\n/g, '\\n').replace(/\\s+/g, '\\n');\n\t\t\t}\n\t\t}\n\t});\n\treturn formattedPem;\n}\n"],"mappings":";;AAAA,MAAM,uBAAuB;AAE7B,SAAS,iBAAiB,KAAa,UAAuC;CAC7E,MAAM,UAAU,IAAI,KAAK;CACzB,KAAK,QAAQ,MAAM,cAAc,KAAK,CAAC,EAAA,CAAG,WAAW,GAAG,OAAO,KAAA;CAE/D,MAAM,eAAe,WAAW,yBAAyB;CACzD,MAAM,WAAW,QAAQ,MACxB,IAAI,OAAO,gBAAgB,aAAa,qCAAqC,CAC9E;CAEA,IAAI,CAAC,UAAU,OAAO,KAAA;CAEtB,MAAM,GAAG,OAAO,QAAQ;CACxB,MAAM,iBAAiB,KAAK,QAAQ,QAAQ,IAAI,CAAC,CAAC,KAAK;CAKvD,OAAO,cAAc,MAAM,SAJL,KAAK,KAAK,cAAc,IAC3C,eAAe,QAAQ,SAAS,GAAG,CAAC,CAAC,QAAQ,QAAQ,IAAI,KACxD,eAAe,MAAM,IAAI,OAAO,OAAO,qBAAqB,IAAI,GAAG,CAAC,KAAK,CAAC,EAAA,CAAG,KAAK,IAAI,EAExC,aAAa,MAAM;AACtE;;;;;;;;;;AAWA,SAAgB,eAAe,KAAa,WAAW,OAAe;CACrE,IAAI,QAAQ;CACZ,IAAI,UACH,QAAQ;CAET,IAAI,CAAC,OAAO,KAAK,KAAK,GAAG,GACxB,OAAO;CAER,MAAM,aAAa,iBAAiB,KAAK,QAAQ;CACjD,IAAI,eAAe,KAAA,GAClB,OAAO;CAGR,IAAI,eAAe;CAEnB,IADkB,MAAM,OAAO,CAAC,CAAC,QAAQ,SAAS,SAAS,EACvD,CAAC,CAAC,SAAS,SAAS;EACvB,IAAI,MAAM,KAAK,IAAI,GAClB,gBAAgB,QAAQ,KAAK;OAG7B,IAAI,qBAAU,KAAK,IAAI,GAAG;GACzB,OAAO,KAAK,QAAQ,SAAS,GAAG;GAChC,gBAAgB,KAAK,QAAQ,QAAQ,IAAI,CAAC,CAAC,QAAQ,QAAQ,IAAI;EAChE,OACC,gBAAgB,KAAK,QAAQ,QAAQ,IAAI,CAAC,CAAC,QAAQ,QAAQ,IAAI;CAGlE,CAAC;CACD,OAAO;AACR"}
{"version":3,"file":"format-pem-block.mjs","names":[],"sources":["../src/format-pem-block.ts"],"sourcesContent":["const PEM_BODY_LINE_LENGTH = 64;\n\nfunction formatCompactPem(pem: string, isPublic: boolean): string | undefined {\n\tconst trimmed = pem.trim();\n\tif ((trimmed.match(/-----BEGIN /g) ?? []).length !== 1) return undefined;\n\n\tconst labelPattern = isPublic ? '[A-Z0-9 ]*PUBLIC KEY' : '[A-Z0-9 ]*PRIVATE KEY|CERTIFICATE';\n\tconst pemMatch = trimmed.match(\n\t\tnew RegExp(`^-----BEGIN (${labelPattern})-----([\\\\s\\\\S]*?)-----END \\\\1-----$`),\n\t);\n\n\tif (!pemMatch) return undefined;\n\n\tconst [, label, body] = pemMatch;\n\tconst normalizedBody = body.replace(/\\\\n/g, '\\n').trim();\n\tconst formattedBody = /\\s/.test(normalizedBody)\n\t\t? normalizedBody.replace(/:\\s+/g, ':').replace(/\\s+/g, '\\n')\n\t\t: (normalizedBody.match(new RegExp(`.{1,${PEM_BODY_LINE_LENGTH}}`, 'g')) ?? []).join('\\n');\n\n\treturn `-----BEGIN ${label}-----\\n${formattedBody}\\n-----END ${label}-----`;\n}\n\n/**\n * Normalize a single PEM-encoded block (private key, public key, or certificate)\n * by collapsing whitespace and wrapping the body at 64 chars. Multi-block PEM\n * chains are returned unchanged.\n *\n * @param pem - The PEM-encoded block to format.\n * @param isPublic - When true, match `PUBLIC KEY` labels instead of the default `PRIVATE KEY` / `CERTIFICATE`.\n * @returns The formatted PEM block.\n */\nexport function formatPemBlock(pem: string, isPublic = false): string {\n\tlet regex = /(PRIVATE KEY|CERTIFICATE)/;\n\tif (isPublic) {\n\t\tregex = /(PUBLIC KEY)/;\n\t}\n\tif (!pem || /\\n/.test(pem)) {\n\t\treturn pem;\n\t}\n\tconst compactPem = formatCompactPem(pem, isPublic);\n\tif (compactPem !== undefined) {\n\t\treturn compactPem;\n\t}\n\n\tlet formattedPem = '';\n\tconst parts = pem.split('-----').filter((item) => item !== '');\n\tparts.forEach((part) => {\n\t\tif (regex.test(part)) {\n\t\t\tformattedPem += `-----${part}-----`;\n\t\t} else {\n\t\t\tconst passRegex = /Proc-Type|DEK-Info/;\n\t\t\tif (passRegex.test(part)) {\n\t\t\t\tpart = part.replace(/:\\s+/g, ':');\n\t\t\t\tformattedPem += part.replace(/\\\\n/g, '\\n').replace(/\\s+/g, '\\n');\n\t\t\t} else {\n\t\t\t\tformattedPem += part.replace(/\\\\n/g, '\\n').replace(/\\s+/g, '\\n');\n\t\t\t}\n\t\t}\n\t});\n\treturn formattedPem;\n}\n"],"mappings":";AAAA,MAAM,uBAAuB;AAE7B,SAAS,iBAAiB,KAAa,UAAuC;CAC7E,MAAM,UAAU,IAAI,KAAK;CACzB,KAAK,QAAQ,MAAM,cAAc,KAAK,CAAC,EAAA,CAAG,WAAW,GAAG,OAAO,KAAA;CAE/D,MAAM,eAAe,WAAW,yBAAyB;CACzD,MAAM,WAAW,QAAQ,MACxB,IAAI,OAAO,gBAAgB,aAAa,qCAAqC,CAC9E;CAEA,IAAI,CAAC,UAAU,OAAO,KAAA;CAEtB,MAAM,GAAG,OAAO,QAAQ;CACxB,MAAM,iBAAiB,KAAK,QAAQ,QAAQ,IAAI,CAAC,CAAC,KAAK;CAKvD,OAAO,cAAc,MAAM,SAJL,KAAK,KAAK,cAAc,IAC3C,eAAe,QAAQ,SAAS,GAAG,CAAC,CAAC,QAAQ,QAAQ,IAAI,KACxD,eAAe,MAAM,IAAI,OAAO,OAAO,qBAAqB,IAAI,GAAG,CAAC,KAAK,CAAC,EAAA,CAAG,KAAK,IAAI,EAExC,aAAa,MAAM;AACtE;;;;;;;;;;AAWA,SAAgB,eAAe,KAAa,WAAW,OAAe;CACrE,IAAI,QAAQ;CACZ,IAAI,UACH,QAAQ;CAET,IAAI,CAAC,OAAO,KAAK,KAAK,GAAG,GACxB,OAAO;CAER,MAAM,aAAa,iBAAiB,KAAK,QAAQ;CACjD,IAAI,eAAe,KAAA,GAClB,OAAO;CAGR,IAAI,eAAe;CAEnB,IADkB,MAAM,OAAO,CAAC,CAAC,QAAQ,SAAS,SAAS,EACvD,CAAC,CAAC,SAAS,SAAS;EACvB,IAAI,MAAM,KAAK,IAAI,GAClB,gBAAgB,QAAQ,KAAK;OAG7B,IAAI,qBAAU,KAAK,IAAI,GAAG;GACzB,OAAO,KAAK,QAAQ,SAAS,GAAG;GAChC,gBAAgB,KAAK,QAAQ,QAAQ,IAAI,CAAC,CAAC,QAAQ,QAAQ,IAAI;EAChE,OACC,gBAAgB,KAAK,QAAQ,QAAQ,IAAI,CAAC,CAAC,QAAQ,QAAQ,IAAI;CAGlE,CAAC;CACD,OAAO;AACR"}
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/lazy-import.ts
/**
* Lazily `import()` a dual-published (ESM + CJS) dependency while keeping the
* `require`-condition types the rest of a CommonJS / NodeNext package resolves
* via top-level `import type`.
*
* Under `moduleResolution: NodeNext` a top-level `import type { X } from 'pkg'`
* in a CommonJS module resolves `pkg`'s `require`-condition declarations
* (`.d.cts`), while `await import('pkg')` resolves the `import`-condition
* declarations (`.d.ts`); TypeScript treats the two identically-named types as
* unrelated. Pass the module namespace type (via `import type * as NS`) as `T`
* and the returned value is typed as the same declaration copy the callers use.
*
* @param loader thunk performing the dynamic import, e.g. `() => import('pkg')`
*/
async function lazyImport(loader) {
return await loader();
}
//#endregion
exports.lazyImport = lazyImport;
//# sourceMappingURL=lazy-import.cjs.map
{"version":3,"file":"lazy-import.cjs","names":[],"sources":["../src/lazy-import.ts"],"sourcesContent":["/**\n * Lazily `import()` a dual-published (ESM + CJS) dependency while keeping the\n * `require`-condition types the rest of a CommonJS / NodeNext package resolves\n * via top-level `import type`.\n *\n * Under `moduleResolution: NodeNext` a top-level `import type { X } from 'pkg'`\n * in a CommonJS module resolves `pkg`'s `require`-condition declarations\n * (`.d.cts`), while `await import('pkg')` resolves the `import`-condition\n * declarations (`.d.ts`); TypeScript treats the two identically-named types as\n * unrelated. Pass the module namespace type (via `import type * as NS`) as `T`\n * and the returned value is typed as the same declaration copy the callers use.\n *\n * @param loader thunk performing the dynamic import, e.g. `() => import('pkg')`\n */\nexport async function lazyImport<T>(loader: () => Promise<unknown>): Promise<T> {\n\treturn (await loader()) as T;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAcA,eAAsB,WAAc,QAA4C;CAC/E,OAAQ,MAAM,OAAO;AACtB"}
//#region src/lazy-import.d.ts
declare function lazyImport<T>(loader: () => Promise<unknown>): Promise<T>;
//#endregion
export { lazyImport };
//# sourceMappingURL=lazy-import.d.cts.map
//#region src/lazy-import.d.ts
declare function lazyImport<T>(loader: () => Promise<unknown>): Promise<T>;
//#endregion
export { lazyImport };
//# sourceMappingURL=lazy-import.d.mts.map
//#region src/lazy-import.ts
/**
* Lazily `import()` a dual-published (ESM + CJS) dependency while keeping the
* `require`-condition types the rest of a CommonJS / NodeNext package resolves
* via top-level `import type`.
*
* Under `moduleResolution: NodeNext` a top-level `import type { X } from 'pkg'`
* in a CommonJS module resolves `pkg`'s `require`-condition declarations
* (`.d.cts`), while `await import('pkg')` resolves the `import`-condition
* declarations (`.d.ts`); TypeScript treats the two identically-named types as
* unrelated. Pass the module namespace type (via `import type * as NS`) as `T`
* and the returned value is typed as the same declaration copy the callers use.
*
* @param loader thunk performing the dynamic import, e.g. `() => import('pkg')`
*/
async function lazyImport(loader) {
return await loader();
}
//#endregion
export { lazyImport };
//# sourceMappingURL=lazy-import.mjs.map
{"version":3,"file":"lazy-import.mjs","names":[],"sources":["../src/lazy-import.ts"],"sourcesContent":["/**\n * Lazily `import()` a dual-published (ESM + CJS) dependency while keeping the\n * `require`-condition types the rest of a CommonJS / NodeNext package resolves\n * via top-level `import type`.\n *\n * Under `moduleResolution: NodeNext` a top-level `import type { X } from 'pkg'`\n * in a CommonJS module resolves `pkg`'s `require`-condition declarations\n * (`.d.cts`), while `await import('pkg')` resolves the `import`-condition\n * declarations (`.d.ts`); TypeScript treats the two identically-named types as\n * unrelated. Pass the module namespace type (via `import type * as NS`) as `T`\n * and the returned value is typed as the same declaration copy the callers use.\n *\n * @param loader thunk performing the dynamic import, e.g. `() => import('pkg')`\n */\nexport async function lazyImport<T>(loader: () => Promise<unknown>): Promise<T> {\n\treturn (await loader()) as T;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAcA,eAAsB,WAAc,QAA4C;CAC/E,OAAQ,MAAM,OAAO;AACtB"}
+2
-2

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/assert.ts

@@ -9,5 +9,5 @@ /**

}
//#endregion
exports.assert = assert;
//# sourceMappingURL=assert.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"assert.cjs","names":[],"sources":["../src/assert.ts"],"sourcesContent":["/**\n * Asserts given condition\n */\nexport function assert(condition: unknown, message?: string): asserts condition {\n\tif (!condition) {\n\t\t// eslint-disable-next-line n8n-local-rules/no-plain-errors\n\t\tthrow new Error(message ?? 'Assertion failed');\n\t}\n}\n"],"mappings":";;;;;AAGA,SAAgB,OAAO,WAAoB,SAAqC;AAC/E,KAAI,CAAC,UAEJ,OAAM,IAAI,MAAM,WAAW,mBAAmB"}
{"version":3,"file":"assert.cjs","names":[],"sources":["../src/assert.ts"],"sourcesContent":["/**\n * Asserts given condition\n */\nexport function assert(condition: unknown, message?: string): asserts condition {\n\tif (!condition) {\n\t\t// eslint-disable-next-line n8n-local-rules/no-plain-errors\n\t\tthrow new Error(message ?? 'Assertion failed');\n\t}\n}\n"],"mappings":";;;;;AAGA,SAAgB,OAAO,WAAoB,SAAqC;CAC/E,IAAI,CAAC,WAEJ,MAAM,IAAI,MAAM,WAAW,kBAAkB;AAE/C"}

@@ -8,5 +8,5 @@ //#region src/assert.ts

}
//#endregion
export { assert };
//# sourceMappingURL=assert.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"assert.mjs","names":[],"sources":["../src/assert.ts"],"sourcesContent":["/**\n * Asserts given condition\n */\nexport function assert(condition: unknown, message?: string): asserts condition {\n\tif (!condition) {\n\t\t// eslint-disable-next-line n8n-local-rules/no-plain-errors\n\t\tthrow new Error(message ?? 'Assertion failed');\n\t}\n}\n"],"mappings":";;;;AAGA,SAAgB,OAAO,WAAoB,SAAqC;AAC/E,KAAI,CAAC,UAEJ,OAAM,IAAI,MAAM,WAAW,mBAAmB"}
{"version":3,"file":"assert.mjs","names":[],"sources":["../src/assert.ts"],"sourcesContent":["/**\n * Asserts given condition\n */\nexport function assert(condition: unknown, message?: string): asserts condition {\n\tif (!condition) {\n\t\t// eslint-disable-next-line n8n-local-rules/no-plain-errors\n\t\tthrow new Error(message ?? 'Assertion failed');\n\t}\n}\n"],"mappings":";;;;AAGA,SAAgB,OAAO,WAAoB,SAAqC;CAC/E,IAAI,CAAC,WAEJ,MAAM,IAAI,MAAM,WAAW,kBAAkB;AAE/C"}

@@ -1,4 +0,4 @@

const require_format_pem_block = require('./format-pem-block2.cjs');
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_format_pem_block = require("./format-pem-block.cjs");
let node_crypto = require("node:crypto");
//#region src/client-assertion.ts

@@ -45,6 +45,6 @@ const CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";

}
//#endregion
exports.CLIENT_ASSERTION_TYPE = CLIENT_ASSERTION_TYPE;
exports.buildClientAssertion = buildClientAssertion;
//# sourceMappingURL=client-assertion.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"client-assertion.cjs","names":["parsed: X509Certificate","X509Certificate","formatPemBlock","privateKey: KeyObject"],"sources":["../src/client-assertion.ts"],"sourcesContent":["import {\n\tcreatePrivateKey,\n\tcreateSign,\n\trandomUUID,\n\tX509Certificate,\n\ttype KeyObject,\n} from 'node:crypto';\n\nimport { formatPemBlock } from './format-pem-block';\n\n// private_key_jwt (RFC 7521/7523): the client proves its identity with a JWT\n// signed by its private key instead of a shared secret. The `x5t` header (SHA-1\n// thumbprint of the certificate) tells the server which public key verifies it.\nexport const CLIENT_ASSERTION_TYPE = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer';\n\nconst ASSERTION_TTL_SECONDS = 300;\n\nfunction base64url(input: Buffer | string): string {\n\treturn Buffer.from(input).toString('base64url');\n}\n\nfunction certificateThumbprint(certificate: string): string {\n\tlet parsed: X509Certificate;\n\ttry {\n\t\tparsed = new X509Certificate(formatPemBlock(certificate));\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t'The Certificate field must contain a PEM certificate (-----BEGIN CERTIFICATE-----).',\n\t\t\t{ cause: error },\n\t\t);\n\t}\n\treturn Buffer.from(parsed.fingerprint.replace(/:/g, ''), 'hex').toString('base64url');\n}\n\nexport interface BuildClientAssertionOptions {\n\tclientId: string;\n\t/** Token endpoint; used as the JWT `aud`. */\n\taccessTokenUri: string;\n\t/** RSA private key (PEM). Signing is RS256-only; EC/Ed25519 keys are not supported. */\n\tprivateKey: string;\n\tcertificate: string;\n}\n\nexport function buildClientAssertion(options: BuildClientAssertionOptions): string {\n\tconst now = Math.floor(Date.now() / 1000);\n\tconst header = { alg: 'RS256', typ: 'JWT', x5t: certificateThumbprint(options.certificate) };\n\tconst payload = {\n\t\taud: options.accessTokenUri,\n\t\tiss: options.clientId,\n\t\tsub: options.clientId,\n\t\tjti: randomUUID(),\n\t\tiat: now,\n\t\tnbf: now,\n\t\texp: now + ASSERTION_TTL_SECONDS,\n\t};\n\n\tlet privateKey: KeyObject;\n\ttry {\n\t\tprivateKey = createPrivateKey(formatPemBlock(options.privateKey));\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t'The Private Key field must contain a PEM private key (-----BEGIN PRIVATE KEY-----).',\n\t\t\t{ cause: error },\n\t\t);\n\t}\n\n\t// `createSign('RSA-SHA256')` also signs EC/Ed25519 keys, producing a signature\n\t// that contradicts the pinned `alg: RS256` header. Reject non-RSA keys up front.\n\tif (privateKey.asymmetricKeyType !== 'rsa') {\n\t\tthrow new Error('Certificate authentication requires an RSA private key');\n\t}\n\n\tconst signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}`;\n\tconst signature = createSign('RSA-SHA256').update(signingInput).sign(privateKey);\n\treturn `${signingInput}.${base64url(signature)}`;\n}\n"],"mappings":";;;;AAaA,MAAa,wBAAwB;AAErC,MAAM,wBAAwB;AAE9B,SAAS,UAAU,OAAgC;AAClD,QAAO,OAAO,KAAK,MAAM,CAAC,SAAS,YAAY;;AAGhD,SAAS,sBAAsB,aAA6B;CAC3D,IAAIA;AACJ,KAAI;AACH,WAAS,IAAIC,4BAAgBC,wCAAe,YAAY,CAAC;UACjD,OAAO;AACf,QAAM,IAAI,MACT,uFACA,EAAE,OAAO,OAAO,CAChB;;AAEF,QAAO,OAAO,KAAK,OAAO,YAAY,QAAQ,MAAM,GAAG,EAAE,MAAM,CAAC,SAAS,YAAY;;AAYtF,SAAgB,qBAAqB,SAA8C;CAClF,MAAM,MAAM,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK;CACzC,MAAM,SAAS;EAAE,KAAK;EAAS,KAAK;EAAO,KAAK,sBAAsB,QAAQ,YAAY;EAAE;CAC5F,MAAM,UAAU;EACf,KAAK,QAAQ;EACb,KAAK,QAAQ;EACb,KAAK,QAAQ;EACb,kCAAiB;EACjB,KAAK;EACL,KAAK;EACL,KAAK,MAAM;EACX;CAED,IAAIC;AACJ,KAAI;AACH,iDAA8BD,wCAAe,QAAQ,WAAW,CAAC;UACzD,OAAO;AACf,QAAM,IAAI,MACT,uFACA,EAAE,OAAO,OAAO,CAChB;;AAKF,KAAI,WAAW,sBAAsB,MACpC,OAAM,IAAI,MAAM,yDAAyD;CAG1E,MAAM,eAAe,GAAG,UAAU,KAAK,UAAU,OAAO,CAAC,CAAC,GAAG,UAAU,KAAK,UAAU,QAAQ,CAAC;AAE/F,QAAO,GAAG,aAAa,GAAG,sCADG,aAAa,CAAC,OAAO,aAAa,CAAC,KAAK,WAAW,CAClC"}
{"version":3,"file":"client-assertion.cjs","names":["X509Certificate","formatPemBlock"],"sources":["../src/client-assertion.ts"],"sourcesContent":["import {\n\tcreatePrivateKey,\n\tcreateSign,\n\trandomUUID,\n\tX509Certificate,\n\ttype KeyObject,\n} from 'node:crypto';\n\nimport { formatPemBlock } from './format-pem-block';\n\n// private_key_jwt (RFC 7521/7523): the client proves its identity with a JWT\n// signed by its private key instead of a shared secret. The `x5t` header (SHA-1\n// thumbprint of the certificate) tells the server which public key verifies it.\nexport const CLIENT_ASSERTION_TYPE = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer';\n\nconst ASSERTION_TTL_SECONDS = 300;\n\nfunction base64url(input: Buffer | string): string {\n\treturn Buffer.from(input).toString('base64url');\n}\n\nfunction certificateThumbprint(certificate: string): string {\n\tlet parsed: X509Certificate;\n\ttry {\n\t\tparsed = new X509Certificate(formatPemBlock(certificate));\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t'The Certificate field must contain a PEM certificate (-----BEGIN CERTIFICATE-----).',\n\t\t\t{ cause: error },\n\t\t);\n\t}\n\treturn Buffer.from(parsed.fingerprint.replace(/:/g, ''), 'hex').toString('base64url');\n}\n\nexport interface BuildClientAssertionOptions {\n\tclientId: string;\n\t/** Token endpoint; used as the JWT `aud`. */\n\taccessTokenUri: string;\n\t/** RSA private key (PEM). Signing is RS256-only; EC/Ed25519 keys are not supported. */\n\tprivateKey: string;\n\tcertificate: string;\n}\n\nexport function buildClientAssertion(options: BuildClientAssertionOptions): string {\n\tconst now = Math.floor(Date.now() / 1000);\n\tconst header = { alg: 'RS256', typ: 'JWT', x5t: certificateThumbprint(options.certificate) };\n\tconst payload = {\n\t\taud: options.accessTokenUri,\n\t\tiss: options.clientId,\n\t\tsub: options.clientId,\n\t\tjti: randomUUID(),\n\t\tiat: now,\n\t\tnbf: now,\n\t\texp: now + ASSERTION_TTL_SECONDS,\n\t};\n\n\tlet privateKey: KeyObject;\n\ttry {\n\t\tprivateKey = createPrivateKey(formatPemBlock(options.privateKey));\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t'The Private Key field must contain a PEM private key (-----BEGIN PRIVATE KEY-----).',\n\t\t\t{ cause: error },\n\t\t);\n\t}\n\n\t// `createSign('RSA-SHA256')` also signs EC/Ed25519 keys, producing a signature\n\t// that contradicts the pinned `alg: RS256` header. Reject non-RSA keys up front.\n\tif (privateKey.asymmetricKeyType !== 'rsa') {\n\t\tthrow new Error('Certificate authentication requires an RSA private key');\n\t}\n\n\tconst signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}`;\n\tconst signature = createSign('RSA-SHA256').update(signingInput).sign(privateKey);\n\treturn `${signingInput}.${base64url(signature)}`;\n}\n"],"mappings":";;;;AAaA,MAAa,wBAAwB;AAErC,MAAM,wBAAwB;AAE9B,SAAS,UAAU,OAAgC;CAClD,OAAO,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS,WAAW;AAC/C;AAEA,SAAS,sBAAsB,aAA6B;CAC3D,IAAI;CACJ,IAAI;EACH,SAAS,IAAIA,YAAAA,gBAAgBC,yBAAAA,eAAe,WAAW,CAAC;CACzD,SAAS,OAAO;EACf,MAAM,IAAI,MACT,uFACA,EAAE,OAAO,MAAM,CAChB;CACD;CACA,OAAO,OAAO,KAAK,OAAO,YAAY,QAAQ,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,SAAS,WAAW;AACrF;AAWA,SAAgB,qBAAqB,SAA8C;CAClF,MAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;CACxC,MAAM,SAAS;EAAE,KAAK;EAAS,KAAK;EAAO,KAAK,sBAAsB,QAAQ,WAAW;CAAE;CAC3F,MAAM,UAAU;EACf,KAAK,QAAQ;EACb,KAAK,QAAQ;EACb,KAAK,QAAQ;EACb,MAAA,GAAA,YAAA,WAAA,CAAgB;EAChB,KAAK;EACL,KAAK;EACL,KAAK,MAAM;CACZ;CAEA,IAAI;CACJ,IAAI;EACH,cAAA,GAAA,YAAA,iBAAA,CAA8BA,yBAAAA,eAAe,QAAQ,UAAU,CAAC;CACjE,SAAS,OAAO;EACf,MAAM,IAAI,MACT,uFACA,EAAE,OAAO,MAAM,CAChB;CACD;CAIA,IAAI,WAAW,sBAAsB,OACpC,MAAM,IAAI,MAAM,wDAAwD;CAGzE,MAAM,eAAe,GAAG,UAAU,KAAK,UAAU,MAAM,CAAC,EAAE,GAAG,UAAU,KAAK,UAAU,OAAO,CAAC;CAE9F,OAAO,GAAG,aAAa,GAAG,WAAA,GAAA,YAAA,WAAA,CADG,YAAY,CAAC,CAAC,OAAO,YAAY,CAAC,CAAC,KAAK,UACzB,CAAC;AAC9C"}

@@ -1,4 +0,3 @@

import { t as formatPemBlock } from "./format-pem-block2.mjs";
import { formatPemBlock } from "./format-pem-block.mjs";
import { X509Certificate, createPrivateKey, createSign, randomUUID } from "node:crypto";
//#region src/client-assertion.ts

@@ -45,5 +44,5 @@ const CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";

}
//#endregion
export { CLIENT_ASSERTION_TYPE, buildClientAssertion };
//# sourceMappingURL=client-assertion.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"client-assertion.mjs","names":["parsed: X509Certificate","privateKey: KeyObject"],"sources":["../src/client-assertion.ts"],"sourcesContent":["import {\n\tcreatePrivateKey,\n\tcreateSign,\n\trandomUUID,\n\tX509Certificate,\n\ttype KeyObject,\n} from 'node:crypto';\n\nimport { formatPemBlock } from './format-pem-block';\n\n// private_key_jwt (RFC 7521/7523): the client proves its identity with a JWT\n// signed by its private key instead of a shared secret. The `x5t` header (SHA-1\n// thumbprint of the certificate) tells the server which public key verifies it.\nexport const CLIENT_ASSERTION_TYPE = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer';\n\nconst ASSERTION_TTL_SECONDS = 300;\n\nfunction base64url(input: Buffer | string): string {\n\treturn Buffer.from(input).toString('base64url');\n}\n\nfunction certificateThumbprint(certificate: string): string {\n\tlet parsed: X509Certificate;\n\ttry {\n\t\tparsed = new X509Certificate(formatPemBlock(certificate));\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t'The Certificate field must contain a PEM certificate (-----BEGIN CERTIFICATE-----).',\n\t\t\t{ cause: error },\n\t\t);\n\t}\n\treturn Buffer.from(parsed.fingerprint.replace(/:/g, ''), 'hex').toString('base64url');\n}\n\nexport interface BuildClientAssertionOptions {\n\tclientId: string;\n\t/** Token endpoint; used as the JWT `aud`. */\n\taccessTokenUri: string;\n\t/** RSA private key (PEM). Signing is RS256-only; EC/Ed25519 keys are not supported. */\n\tprivateKey: string;\n\tcertificate: string;\n}\n\nexport function buildClientAssertion(options: BuildClientAssertionOptions): string {\n\tconst now = Math.floor(Date.now() / 1000);\n\tconst header = { alg: 'RS256', typ: 'JWT', x5t: certificateThumbprint(options.certificate) };\n\tconst payload = {\n\t\taud: options.accessTokenUri,\n\t\tiss: options.clientId,\n\t\tsub: options.clientId,\n\t\tjti: randomUUID(),\n\t\tiat: now,\n\t\tnbf: now,\n\t\texp: now + ASSERTION_TTL_SECONDS,\n\t};\n\n\tlet privateKey: KeyObject;\n\ttry {\n\t\tprivateKey = createPrivateKey(formatPemBlock(options.privateKey));\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t'The Private Key field must contain a PEM private key (-----BEGIN PRIVATE KEY-----).',\n\t\t\t{ cause: error },\n\t\t);\n\t}\n\n\t// `createSign('RSA-SHA256')` also signs EC/Ed25519 keys, producing a signature\n\t// that contradicts the pinned `alg: RS256` header. Reject non-RSA keys up front.\n\tif (privateKey.asymmetricKeyType !== 'rsa') {\n\t\tthrow new Error('Certificate authentication requires an RSA private key');\n\t}\n\n\tconst signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}`;\n\tconst signature = createSign('RSA-SHA256').update(signingInput).sign(privateKey);\n\treturn `${signingInput}.${base64url(signature)}`;\n}\n"],"mappings":";;;;AAaA,MAAa,wBAAwB;AAErC,MAAM,wBAAwB;AAE9B,SAAS,UAAU,OAAgC;AAClD,QAAO,OAAO,KAAK,MAAM,CAAC,SAAS,YAAY;;AAGhD,SAAS,sBAAsB,aAA6B;CAC3D,IAAIA;AACJ,KAAI;AACH,WAAS,IAAI,gBAAgB,eAAe,YAAY,CAAC;UACjD,OAAO;AACf,QAAM,IAAI,MACT,uFACA,EAAE,OAAO,OAAO,CAChB;;AAEF,QAAO,OAAO,KAAK,OAAO,YAAY,QAAQ,MAAM,GAAG,EAAE,MAAM,CAAC,SAAS,YAAY;;AAYtF,SAAgB,qBAAqB,SAA8C;CAClF,MAAM,MAAM,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK;CACzC,MAAM,SAAS;EAAE,KAAK;EAAS,KAAK;EAAO,KAAK,sBAAsB,QAAQ,YAAY;EAAE;CAC5F,MAAM,UAAU;EACf,KAAK,QAAQ;EACb,KAAK,QAAQ;EACb,KAAK,QAAQ;EACb,KAAK,YAAY;EACjB,KAAK;EACL,KAAK;EACL,KAAK,MAAM;EACX;CAED,IAAIC;AACJ,KAAI;AACH,eAAa,iBAAiB,eAAe,QAAQ,WAAW,CAAC;UACzD,OAAO;AACf,QAAM,IAAI,MACT,uFACA,EAAE,OAAO,OAAO,CAChB;;AAKF,KAAI,WAAW,sBAAsB,MACpC,OAAM,IAAI,MAAM,yDAAyD;CAG1E,MAAM,eAAe,GAAG,UAAU,KAAK,UAAU,OAAO,CAAC,CAAC,GAAG,UAAU,KAAK,UAAU,QAAQ,CAAC;AAE/F,QAAO,GAAG,aAAa,GAAG,UADR,WAAW,aAAa,CAAC,OAAO,aAAa,CAAC,KAAK,WAAW,CAClC"}
{"version":3,"file":"client-assertion.mjs","names":[],"sources":["../src/client-assertion.ts"],"sourcesContent":["import {\n\tcreatePrivateKey,\n\tcreateSign,\n\trandomUUID,\n\tX509Certificate,\n\ttype KeyObject,\n} from 'node:crypto';\n\nimport { formatPemBlock } from './format-pem-block';\n\n// private_key_jwt (RFC 7521/7523): the client proves its identity with a JWT\n// signed by its private key instead of a shared secret. The `x5t` header (SHA-1\n// thumbprint of the certificate) tells the server which public key verifies it.\nexport const CLIENT_ASSERTION_TYPE = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer';\n\nconst ASSERTION_TTL_SECONDS = 300;\n\nfunction base64url(input: Buffer | string): string {\n\treturn Buffer.from(input).toString('base64url');\n}\n\nfunction certificateThumbprint(certificate: string): string {\n\tlet parsed: X509Certificate;\n\ttry {\n\t\tparsed = new X509Certificate(formatPemBlock(certificate));\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t'The Certificate field must contain a PEM certificate (-----BEGIN CERTIFICATE-----).',\n\t\t\t{ cause: error },\n\t\t);\n\t}\n\treturn Buffer.from(parsed.fingerprint.replace(/:/g, ''), 'hex').toString('base64url');\n}\n\nexport interface BuildClientAssertionOptions {\n\tclientId: string;\n\t/** Token endpoint; used as the JWT `aud`. */\n\taccessTokenUri: string;\n\t/** RSA private key (PEM). Signing is RS256-only; EC/Ed25519 keys are not supported. */\n\tprivateKey: string;\n\tcertificate: string;\n}\n\nexport function buildClientAssertion(options: BuildClientAssertionOptions): string {\n\tconst now = Math.floor(Date.now() / 1000);\n\tconst header = { alg: 'RS256', typ: 'JWT', x5t: certificateThumbprint(options.certificate) };\n\tconst payload = {\n\t\taud: options.accessTokenUri,\n\t\tiss: options.clientId,\n\t\tsub: options.clientId,\n\t\tjti: randomUUID(),\n\t\tiat: now,\n\t\tnbf: now,\n\t\texp: now + ASSERTION_TTL_SECONDS,\n\t};\n\n\tlet privateKey: KeyObject;\n\ttry {\n\t\tprivateKey = createPrivateKey(formatPemBlock(options.privateKey));\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t'The Private Key field must contain a PEM private key (-----BEGIN PRIVATE KEY-----).',\n\t\t\t{ cause: error },\n\t\t);\n\t}\n\n\t// `createSign('RSA-SHA256')` also signs EC/Ed25519 keys, producing a signature\n\t// that contradicts the pinned `alg: RS256` header. Reject non-RSA keys up front.\n\tif (privateKey.asymmetricKeyType !== 'rsa') {\n\t\tthrow new Error('Certificate authentication requires an RSA private key');\n\t}\n\n\tconst signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}`;\n\tconst signature = createSign('RSA-SHA256').update(signingInput).sign(privateKey);\n\treturn `${signingInput}.${base64url(signature)}`;\n}\n"],"mappings":";;;AAaA,MAAa,wBAAwB;AAErC,MAAM,wBAAwB;AAE9B,SAAS,UAAU,OAAgC;CAClD,OAAO,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS,WAAW;AAC/C;AAEA,SAAS,sBAAsB,aAA6B;CAC3D,IAAI;CACJ,IAAI;EACH,SAAS,IAAI,gBAAgB,eAAe,WAAW,CAAC;CACzD,SAAS,OAAO;EACf,MAAM,IAAI,MACT,uFACA,EAAE,OAAO,MAAM,CAChB;CACD;CACA,OAAO,OAAO,KAAK,OAAO,YAAY,QAAQ,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,SAAS,WAAW;AACrF;AAWA,SAAgB,qBAAqB,SAA8C;CAClF,MAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;CACxC,MAAM,SAAS;EAAE,KAAK;EAAS,KAAK;EAAO,KAAK,sBAAsB,QAAQ,WAAW;CAAE;CAC3F,MAAM,UAAU;EACf,KAAK,QAAQ;EACb,KAAK,QAAQ;EACb,KAAK,QAAQ;EACb,KAAK,WAAW;EAChB,KAAK;EACL,KAAK;EACL,KAAK,MAAM;CACZ;CAEA,IAAI;CACJ,IAAI;EACH,aAAa,iBAAiB,eAAe,QAAQ,UAAU,CAAC;CACjE,SAAS,OAAO;EACf,MAAM,IAAI,MACT,uFACA,EAAE,OAAO,MAAM,CAChB;CACD;CAIA,IAAI,WAAW,sBAAsB,OACpC,MAAM,IAAI,MAAM,wDAAwD;CAGzE,MAAM,eAAe,GAAG,UAAU,KAAK,UAAU,MAAM,CAAC,EAAE,GAAG,UAAU,KAAK,UAAU,OAAO,CAAC;CAE9F,OAAO,GAAG,aAAa,GAAG,UADR,WAAW,YAAY,CAAC,CAAC,OAAO,YAAY,CAAC,CAAC,KAAK,UACzB,CAAC;AAC9C"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/create-event-queue.ts

@@ -38,5 +38,5 @@ /**

}
//#endregion
exports.createEventQueue = createEventQueue;
//# sourceMappingURL=create-event-queue.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"create-event-queue.cjs","names":["queue: T[]"],"sources":["../src/create-event-queue.ts"],"sourcesContent":["/**\n * Create an event queue that processes events sequentially.\n *\n * @param processEvent - Async function that processes a single event.\n * @returns A function that enqueues events for processing.\n */\nexport function createEventQueue<T>(processEvent: (event: T) => Promise<void>) {\n\t// The internal queue holding events.\n\tconst queue: T[] = [];\n\n\t// Flag to indicate whether an event is currently being processed.\n\tlet processing = false;\n\n\t/**\n\t * Process the next event in the queue (if not already processing).\n\t */\n\tasync function processNext(): Promise<void> {\n\t\tif (processing || queue.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tprocessing = true;\n\t\tconst currentEvent = queue.shift();\n\n\t\tif (currentEvent !== undefined) {\n\t\t\ttry {\n\t\t\t\tawait processEvent(currentEvent);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('Error processing event:', error);\n\t\t\t}\n\t\t}\n\n\t\tprocessing = false;\n\n\t\t// Recursively process the next event.\n\t\tawait processNext();\n\t}\n\n\t/**\n\t * Enqueue an event and trigger processing.\n\t *\n\t * @param event - The event to enqueue.\n\t */\n\tfunction enqueue(event: T): void {\n\t\tqueue.push(event);\n\t\tvoid processNext();\n\t}\n\n\treturn { enqueue };\n}\n"],"mappings":";;;;;;;;AAMA,SAAgB,iBAAoB,cAA2C;CAE9E,MAAMA,QAAa,EAAE;CAGrB,IAAI,aAAa;;;;CAKjB,eAAe,cAA6B;AAC3C,MAAI,cAAc,MAAM,WAAW,EAClC;AAGD,eAAa;EACb,MAAM,eAAe,MAAM,OAAO;AAElC,MAAI,iBAAiB,OACpB,KAAI;AACH,SAAM,aAAa,aAAa;WACxB,OAAO;AACf,WAAQ,MAAM,2BAA2B,MAAM;;AAIjD,eAAa;AAGb,QAAM,aAAa;;;;;;;CAQpB,SAAS,QAAQ,OAAgB;AAChC,QAAM,KAAK,MAAM;AACjB,EAAK,aAAa;;AAGnB,QAAO,EAAE,SAAS"}
{"version":3,"file":"create-event-queue.cjs","names":[],"sources":["../src/create-event-queue.ts"],"sourcesContent":["/**\n * Create an event queue that processes events sequentially.\n *\n * @param processEvent - Async function that processes a single event.\n * @returns A function that enqueues events for processing.\n */\nexport function createEventQueue<T>(processEvent: (event: T) => Promise<void>) {\n\t// The internal queue holding events.\n\tconst queue: T[] = [];\n\n\t// Flag to indicate whether an event is currently being processed.\n\tlet processing = false;\n\n\t/**\n\t * Process the next event in the queue (if not already processing).\n\t */\n\tasync function processNext(): Promise<void> {\n\t\tif (processing || queue.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tprocessing = true;\n\t\tconst currentEvent = queue.shift();\n\n\t\tif (currentEvent !== undefined) {\n\t\t\ttry {\n\t\t\t\tawait processEvent(currentEvent);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('Error processing event:', error);\n\t\t\t}\n\t\t}\n\n\t\tprocessing = false;\n\n\t\t// Recursively process the next event.\n\t\tawait processNext();\n\t}\n\n\t/**\n\t * Enqueue an event and trigger processing.\n\t *\n\t * @param event - The event to enqueue.\n\t */\n\tfunction enqueue(event: T): void {\n\t\tqueue.push(event);\n\t\tvoid processNext();\n\t}\n\n\treturn { enqueue };\n}\n"],"mappings":";;;;;;;;AAMA,SAAgB,iBAAoB,cAA2C;CAE9E,MAAM,QAAa,CAAC;CAGpB,IAAI,aAAa;;;;CAKjB,eAAe,cAA6B;EAC3C,IAAI,cAAc,MAAM,WAAW,GAClC;EAGD,aAAa;EACb,MAAM,eAAe,MAAM,MAAM;EAEjC,IAAI,iBAAiB,KAAA,GACpB,IAAI;GACH,MAAM,aAAa,YAAY;EAChC,SAAS,OAAO;GACf,QAAQ,MAAM,2BAA2B,KAAK;EAC/C;EAGD,aAAa;EAGb,MAAM,YAAY;CACnB;;;;;;CAOA,SAAS,QAAQ,OAAgB;EAChC,MAAM,KAAK,KAAK;EAChB,YAAiB;CAClB;CAEA,OAAO,EAAE,QAAQ;AAClB"}

@@ -37,5 +37,5 @@ //#region src/create-event-queue.ts

}
//#endregion
export { createEventQueue };
//# sourceMappingURL=create-event-queue.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"create-event-queue.mjs","names":["queue: T[]"],"sources":["../src/create-event-queue.ts"],"sourcesContent":["/**\n * Create an event queue that processes events sequentially.\n *\n * @param processEvent - Async function that processes a single event.\n * @returns A function that enqueues events for processing.\n */\nexport function createEventQueue<T>(processEvent: (event: T) => Promise<void>) {\n\t// The internal queue holding events.\n\tconst queue: T[] = [];\n\n\t// Flag to indicate whether an event is currently being processed.\n\tlet processing = false;\n\n\t/**\n\t * Process the next event in the queue (if not already processing).\n\t */\n\tasync function processNext(): Promise<void> {\n\t\tif (processing || queue.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tprocessing = true;\n\t\tconst currentEvent = queue.shift();\n\n\t\tif (currentEvent !== undefined) {\n\t\t\ttry {\n\t\t\t\tawait processEvent(currentEvent);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('Error processing event:', error);\n\t\t\t}\n\t\t}\n\n\t\tprocessing = false;\n\n\t\t// Recursively process the next event.\n\t\tawait processNext();\n\t}\n\n\t/**\n\t * Enqueue an event and trigger processing.\n\t *\n\t * @param event - The event to enqueue.\n\t */\n\tfunction enqueue(event: T): void {\n\t\tqueue.push(event);\n\t\tvoid processNext();\n\t}\n\n\treturn { enqueue };\n}\n"],"mappings":";;;;;;;AAMA,SAAgB,iBAAoB,cAA2C;CAE9E,MAAMA,QAAa,EAAE;CAGrB,IAAI,aAAa;;;;CAKjB,eAAe,cAA6B;AAC3C,MAAI,cAAc,MAAM,WAAW,EAClC;AAGD,eAAa;EACb,MAAM,eAAe,MAAM,OAAO;AAElC,MAAI,iBAAiB,OACpB,KAAI;AACH,SAAM,aAAa,aAAa;WACxB,OAAO;AACf,WAAQ,MAAM,2BAA2B,MAAM;;AAIjD,eAAa;AAGb,QAAM,aAAa;;;;;;;CAQpB,SAAS,QAAQ,OAAgB;AAChC,QAAM,KAAK,MAAM;AACjB,EAAK,aAAa;;AAGnB,QAAO,EAAE,SAAS"}
{"version":3,"file":"create-event-queue.mjs","names":[],"sources":["../src/create-event-queue.ts"],"sourcesContent":["/**\n * Create an event queue that processes events sequentially.\n *\n * @param processEvent - Async function that processes a single event.\n * @returns A function that enqueues events for processing.\n */\nexport function createEventQueue<T>(processEvent: (event: T) => Promise<void>) {\n\t// The internal queue holding events.\n\tconst queue: T[] = [];\n\n\t// Flag to indicate whether an event is currently being processed.\n\tlet processing = false;\n\n\t/**\n\t * Process the next event in the queue (if not already processing).\n\t */\n\tasync function processNext(): Promise<void> {\n\t\tif (processing || queue.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tprocessing = true;\n\t\tconst currentEvent = queue.shift();\n\n\t\tif (currentEvent !== undefined) {\n\t\t\ttry {\n\t\t\t\tawait processEvent(currentEvent);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('Error processing event:', error);\n\t\t\t}\n\t\t}\n\n\t\tprocessing = false;\n\n\t\t// Recursively process the next event.\n\t\tawait processNext();\n\t}\n\n\t/**\n\t * Enqueue an event and trigger processing.\n\t *\n\t * @param event - The event to enqueue.\n\t */\n\tfunction enqueue(event: T): void {\n\t\tqueue.push(event);\n\t\tvoid processNext();\n\t}\n\n\treturn { enqueue };\n}\n"],"mappings":";;;;;;;AAMA,SAAgB,iBAAoB,cAA2C;CAE9E,MAAM,QAAa,CAAC;CAGpB,IAAI,aAAa;;;;CAKjB,eAAe,cAA6B;EAC3C,IAAI,cAAc,MAAM,WAAW,GAClC;EAGD,aAAa;EACb,MAAM,eAAe,MAAM,MAAM;EAEjC,IAAI,iBAAiB,KAAA,GACpB,IAAI;GACH,MAAM,aAAa,YAAY;EAChC,SAAS,OAAO;GACf,QAAQ,MAAM,2BAA2B,KAAK;EAC/C;EAGD,aAAa;EAGb,MAAM,YAAY;CACnB;;;;;;CAOA,SAAS,QAAQ,OAAgB;EAChC,MAAM,KAAK,KAAK;EAChB,YAAiB;CAClB;CAEA,OAAO,EAAE,QAAQ;AAClB"}

@@ -1,3 +0,10 @@

const require_ensure_error = require('../ensure-error.cjs');
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/errors/ensure-error.ts
/** Ensures `error` is an `Error */
function ensureError(error) {
return error instanceof Error ? error : new Error("Error that was not an instance of Error was thrown", { cause: error });
}
//#endregion
exports.ensureError = ensureError;
exports.ensureError = require_ensure_error.ensureError;
//# sourceMappingURL=ensure-error.cjs.map

@@ -1,3 +0,9 @@

import { t as ensureError } from "../ensure-error.mjs";
//#region src/errors/ensure-error.ts
/** Ensures `error` is an `Error */
function ensureError(error) {
return error instanceof Error ? error : new Error("Error that was not an instance of Error was thrown", { cause: error });
}
//#endregion
export { ensureError };
export { ensureError };
//# sourceMappingURL=ensure-error.mjs.map

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/event-bus.ts

@@ -41,5 +41,5 @@ /**

}
//#endregion
exports.createEventBus = createEventBus;
//# sourceMappingURL=event-bus.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"event-bus.cjs","names":["handler: typeof fn"],"sources":["../src/event-bus.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type CallbackFn = (...args: any[]) => any;\n\ntype Payloads<ListenerMap> = {\n\t[E in keyof ListenerMap]: unknown;\n};\n\ntype Listener<Payload> = (payload: Payload) => void;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface EventBus<ListenerMap extends Payloads<ListenerMap> = Record<string, any>> {\n\ton<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tfn: Listener<ListenerMap[EventName]>,\n\t): void;\n\n\tonce<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tfn: Listener<ListenerMap[EventName]>,\n\t): void;\n\n\toff<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tfn: Listener<ListenerMap[EventName]>,\n\t): void;\n\n\temit<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tevent?: ListenerMap[EventName],\n\t): void;\n}\n\n/**\n * Creates an event bus with the given listener map.\n *\n * @example\n * ```ts\n * const eventBus = createEventBus<{\n * 'user-logged-in': { username: string };\n * 'user-logged-out': never;\n * }>();\n */\nexport function createEventBus<\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tListenerMap extends Payloads<ListenerMap> = Record<string, any>,\n>(): EventBus<ListenerMap> {\n\tconst handlers = new Map<string, CallbackFn[]>();\n\n\treturn {\n\t\ton(eventName, fn) {\n\t\t\tlet eventFns = handlers.get(eventName);\n\t\t\tif (!eventFns) {\n\t\t\t\teventFns = [fn];\n\t\t\t} else {\n\t\t\t\teventFns.push(fn);\n\t\t\t}\n\t\t\thandlers.set(eventName, eventFns);\n\t\t},\n\n\t\tonce(eventName, fn) {\n\t\t\tconst handler: typeof fn = (payload) => {\n\t\t\t\tthis.off(eventName, handler);\n\t\t\t\tfn(payload);\n\t\t\t};\n\t\t\tthis.on(eventName, handler);\n\t\t},\n\n\t\toff(eventName, fn) {\n\t\t\tconst eventFns = handlers.get(eventName);\n\t\t\tif (eventFns) {\n\t\t\t\teventFns.splice(eventFns.indexOf(fn) >>> 0, 1);\n\t\t\t}\n\t\t},\n\n\t\temit(eventName, event) {\n\t\t\tconst eventFns = handlers.get(eventName);\n\t\t\tif (eventFns) {\n\t\t\t\teventFns.slice().forEach((handler) => {\n\t\t\t\t\thandler(event);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;;AA0CA,SAAgB,iBAGW;CAC1B,MAAM,2BAAW,IAAI,KAA2B;AAEhD,QAAO;EACN,GAAG,WAAW,IAAI;GACjB,IAAI,WAAW,SAAS,IAAI,UAAU;AACtC,OAAI,CAAC,SACJ,YAAW,CAAC,GAAG;OAEf,UAAS,KAAK,GAAG;AAElB,YAAS,IAAI,WAAW,SAAS;;EAGlC,KAAK,WAAW,IAAI;GACnB,MAAMA,WAAsB,YAAY;AACvC,SAAK,IAAI,WAAW,QAAQ;AAC5B,OAAG,QAAQ;;AAEZ,QAAK,GAAG,WAAW,QAAQ;;EAG5B,IAAI,WAAW,IAAI;GAClB,MAAM,WAAW,SAAS,IAAI,UAAU;AACxC,OAAI,SACH,UAAS,OAAO,SAAS,QAAQ,GAAG,KAAK,GAAG,EAAE;;EAIhD,KAAK,WAAW,OAAO;GACtB,MAAM,WAAW,SAAS,IAAI,UAAU;AACxC,OAAI,SACH,UAAS,OAAO,CAAC,SAAS,YAAY;AACrC,YAAQ,MAAM;KACb;;EAGJ"}
{"version":3,"file":"event-bus.cjs","names":[],"sources":["../src/event-bus.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type CallbackFn = (...args: any[]) => any;\n\ntype Payloads<ListenerMap> = {\n\t[E in keyof ListenerMap]: unknown;\n};\n\ntype Listener<Payload> = (payload: Payload) => void;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface EventBus<ListenerMap extends Payloads<ListenerMap> = Record<string, any>> {\n\ton<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tfn: Listener<ListenerMap[EventName]>,\n\t): void;\n\n\tonce<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tfn: Listener<ListenerMap[EventName]>,\n\t): void;\n\n\toff<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tfn: Listener<ListenerMap[EventName]>,\n\t): void;\n\n\temit<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tevent?: ListenerMap[EventName],\n\t): void;\n}\n\n/**\n * Creates an event bus with the given listener map.\n *\n * @example\n * ```ts\n * const eventBus = createEventBus<{\n * 'user-logged-in': { username: string };\n * 'user-logged-out': never;\n * }>();\n */\nexport function createEventBus<\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tListenerMap extends Payloads<ListenerMap> = Record<string, any>,\n>(): EventBus<ListenerMap> {\n\tconst handlers = new Map<string, CallbackFn[]>();\n\n\treturn {\n\t\ton(eventName, fn) {\n\t\t\tlet eventFns = handlers.get(eventName);\n\t\t\tif (!eventFns) {\n\t\t\t\teventFns = [fn];\n\t\t\t} else {\n\t\t\t\teventFns.push(fn);\n\t\t\t}\n\t\t\thandlers.set(eventName, eventFns);\n\t\t},\n\n\t\tonce(eventName, fn) {\n\t\t\tconst handler: typeof fn = (payload) => {\n\t\t\t\tthis.off(eventName, handler);\n\t\t\t\tfn(payload);\n\t\t\t};\n\t\t\tthis.on(eventName, handler);\n\t\t},\n\n\t\toff(eventName, fn) {\n\t\t\tconst eventFns = handlers.get(eventName);\n\t\t\tif (eventFns) {\n\t\t\t\teventFns.splice(eventFns.indexOf(fn) >>> 0, 1);\n\t\t\t}\n\t\t},\n\n\t\temit(eventName, event) {\n\t\t\tconst eventFns = handlers.get(eventName);\n\t\t\tif (eventFns) {\n\t\t\t\teventFns.slice().forEach((handler) => {\n\t\t\t\t\thandler(event);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;;AA0CA,SAAgB,iBAGW;CAC1B,MAAM,2BAAW,IAAI,IAA0B;CAE/C,OAAO;EACN,GAAG,WAAW,IAAI;GACjB,IAAI,WAAW,SAAS,IAAI,SAAS;GACrC,IAAI,CAAC,UACJ,WAAW,CAAC,EAAE;QAEd,SAAS,KAAK,EAAE;GAEjB,SAAS,IAAI,WAAW,QAAQ;EACjC;EAEA,KAAK,WAAW,IAAI;GACnB,MAAM,WAAsB,YAAY;IACvC,KAAK,IAAI,WAAW,OAAO;IAC3B,GAAG,OAAO;GACX;GACA,KAAK,GAAG,WAAW,OAAO;EAC3B;EAEA,IAAI,WAAW,IAAI;GAClB,MAAM,WAAW,SAAS,IAAI,SAAS;GACvC,IAAI,UACH,SAAS,OAAO,SAAS,QAAQ,EAAE,MAAM,GAAG,CAAC;EAE/C;EAEA,KAAK,WAAW,OAAO;GACtB,MAAM,WAAW,SAAS,IAAI,SAAS;GACvC,IAAI,UACH,SAAS,MAAM,CAAC,CAAC,SAAS,YAAY;IACrC,QAAQ,KAAK;GACd,CAAC;EAEH;CACD;AACD"}
//#region src/event-bus.d.ts
type CallbackFn = (...args: any[]) => any;
type Payloads<ListenerMap> = { [E in keyof ListenerMap]: unknown };
type Payloads<ListenerMap> = { [E in keyof ListenerMap]: unknown; };
type Listener<Payload> = (payload: Payload) => void;

@@ -5,0 +5,0 @@ interface EventBus<ListenerMap extends Payloads<ListenerMap> = Record<string, any>> {

//#region src/event-bus.d.ts
type CallbackFn = (...args: any[]) => any;
type Payloads<ListenerMap> = { [E in keyof ListenerMap]: unknown };
type Payloads<ListenerMap> = { [E in keyof ListenerMap]: unknown; };
type Listener<Payload> = (payload: Payload) => void;

@@ -5,0 +5,0 @@ interface EventBus<ListenerMap extends Payloads<ListenerMap> = Record<string, any>> {

@@ -40,5 +40,5 @@ //#region src/event-bus.ts

}
//#endregion
export { createEventBus };
//# sourceMappingURL=event-bus.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"event-bus.mjs","names":["handler: typeof fn"],"sources":["../src/event-bus.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type CallbackFn = (...args: any[]) => any;\n\ntype Payloads<ListenerMap> = {\n\t[E in keyof ListenerMap]: unknown;\n};\n\ntype Listener<Payload> = (payload: Payload) => void;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface EventBus<ListenerMap extends Payloads<ListenerMap> = Record<string, any>> {\n\ton<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tfn: Listener<ListenerMap[EventName]>,\n\t): void;\n\n\tonce<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tfn: Listener<ListenerMap[EventName]>,\n\t): void;\n\n\toff<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tfn: Listener<ListenerMap[EventName]>,\n\t): void;\n\n\temit<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tevent?: ListenerMap[EventName],\n\t): void;\n}\n\n/**\n * Creates an event bus with the given listener map.\n *\n * @example\n * ```ts\n * const eventBus = createEventBus<{\n * 'user-logged-in': { username: string };\n * 'user-logged-out': never;\n * }>();\n */\nexport function createEventBus<\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tListenerMap extends Payloads<ListenerMap> = Record<string, any>,\n>(): EventBus<ListenerMap> {\n\tconst handlers = new Map<string, CallbackFn[]>();\n\n\treturn {\n\t\ton(eventName, fn) {\n\t\t\tlet eventFns = handlers.get(eventName);\n\t\t\tif (!eventFns) {\n\t\t\t\teventFns = [fn];\n\t\t\t} else {\n\t\t\t\teventFns.push(fn);\n\t\t\t}\n\t\t\thandlers.set(eventName, eventFns);\n\t\t},\n\n\t\tonce(eventName, fn) {\n\t\t\tconst handler: typeof fn = (payload) => {\n\t\t\t\tthis.off(eventName, handler);\n\t\t\t\tfn(payload);\n\t\t\t};\n\t\t\tthis.on(eventName, handler);\n\t\t},\n\n\t\toff(eventName, fn) {\n\t\t\tconst eventFns = handlers.get(eventName);\n\t\t\tif (eventFns) {\n\t\t\t\teventFns.splice(eventFns.indexOf(fn) >>> 0, 1);\n\t\t\t}\n\t\t},\n\n\t\temit(eventName, event) {\n\t\t\tconst eventFns = handlers.get(eventName);\n\t\t\tif (eventFns) {\n\t\t\t\teventFns.slice().forEach((handler) => {\n\t\t\t\t\thandler(event);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;AA0CA,SAAgB,iBAGW;CAC1B,MAAM,2BAAW,IAAI,KAA2B;AAEhD,QAAO;EACN,GAAG,WAAW,IAAI;GACjB,IAAI,WAAW,SAAS,IAAI,UAAU;AACtC,OAAI,CAAC,SACJ,YAAW,CAAC,GAAG;OAEf,UAAS,KAAK,GAAG;AAElB,YAAS,IAAI,WAAW,SAAS;;EAGlC,KAAK,WAAW,IAAI;GACnB,MAAMA,WAAsB,YAAY;AACvC,SAAK,IAAI,WAAW,QAAQ;AAC5B,OAAG,QAAQ;;AAEZ,QAAK,GAAG,WAAW,QAAQ;;EAG5B,IAAI,WAAW,IAAI;GAClB,MAAM,WAAW,SAAS,IAAI,UAAU;AACxC,OAAI,SACH,UAAS,OAAO,SAAS,QAAQ,GAAG,KAAK,GAAG,EAAE;;EAIhD,KAAK,WAAW,OAAO;GACtB,MAAM,WAAW,SAAS,IAAI,UAAU;AACxC,OAAI,SACH,UAAS,OAAO,CAAC,SAAS,YAAY;AACrC,YAAQ,MAAM;KACb;;EAGJ"}
{"version":3,"file":"event-bus.mjs","names":[],"sources":["../src/event-bus.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type CallbackFn = (...args: any[]) => any;\n\ntype Payloads<ListenerMap> = {\n\t[E in keyof ListenerMap]: unknown;\n};\n\ntype Listener<Payload> = (payload: Payload) => void;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface EventBus<ListenerMap extends Payloads<ListenerMap> = Record<string, any>> {\n\ton<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tfn: Listener<ListenerMap[EventName]>,\n\t): void;\n\n\tonce<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tfn: Listener<ListenerMap[EventName]>,\n\t): void;\n\n\toff<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tfn: Listener<ListenerMap[EventName]>,\n\t): void;\n\n\temit<EventName extends keyof ListenerMap & string>(\n\t\teventName: EventName,\n\t\tevent?: ListenerMap[EventName],\n\t): void;\n}\n\n/**\n * Creates an event bus with the given listener map.\n *\n * @example\n * ```ts\n * const eventBus = createEventBus<{\n * 'user-logged-in': { username: string };\n * 'user-logged-out': never;\n * }>();\n */\nexport function createEventBus<\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tListenerMap extends Payloads<ListenerMap> = Record<string, any>,\n>(): EventBus<ListenerMap> {\n\tconst handlers = new Map<string, CallbackFn[]>();\n\n\treturn {\n\t\ton(eventName, fn) {\n\t\t\tlet eventFns = handlers.get(eventName);\n\t\t\tif (!eventFns) {\n\t\t\t\teventFns = [fn];\n\t\t\t} else {\n\t\t\t\teventFns.push(fn);\n\t\t\t}\n\t\t\thandlers.set(eventName, eventFns);\n\t\t},\n\n\t\tonce(eventName, fn) {\n\t\t\tconst handler: typeof fn = (payload) => {\n\t\t\t\tthis.off(eventName, handler);\n\t\t\t\tfn(payload);\n\t\t\t};\n\t\t\tthis.on(eventName, handler);\n\t\t},\n\n\t\toff(eventName, fn) {\n\t\t\tconst eventFns = handlers.get(eventName);\n\t\t\tif (eventFns) {\n\t\t\t\teventFns.splice(eventFns.indexOf(fn) >>> 0, 1);\n\t\t\t}\n\t\t},\n\n\t\temit(eventName, event) {\n\t\t\tconst eventFns = handlers.get(eventName);\n\t\t\tif (eventFns) {\n\t\t\t\teventFns.slice().forEach((handler) => {\n\t\t\t\t\thandler(event);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;AA0CA,SAAgB,iBAGW;CAC1B,MAAM,2BAAW,IAAI,IAA0B;CAE/C,OAAO;EACN,GAAG,WAAW,IAAI;GACjB,IAAI,WAAW,SAAS,IAAI,SAAS;GACrC,IAAI,CAAC,UACJ,WAAW,CAAC,EAAE;QAEd,SAAS,KAAK,EAAE;GAEjB,SAAS,IAAI,WAAW,QAAQ;EACjC;EAEA,KAAK,WAAW,IAAI;GACnB,MAAM,WAAsB,YAAY;IACvC,KAAK,IAAI,WAAW,OAAO;IAC3B,GAAG,OAAO;GACX;GACA,KAAK,GAAG,WAAW,OAAO;EAC3B;EAEA,IAAI,WAAW,IAAI;GAClB,MAAM,WAAW,SAAS,IAAI,SAAS;GACvC,IAAI,UACH,SAAS,OAAO,SAAS,QAAQ,EAAE,MAAM,GAAG,CAAC;EAE/C;EAEA,KAAK,WAAW,OAAO;GACtB,MAAM,WAAW,SAAS,IAAI,SAAS;GACvC,IAAI,UACH,SAAS,MAAM,CAAC,CAAC,SAAS,YAAY;IACrC,QAAQ,KAAK;GACd,CAAC;EAEH;CACD;AACD"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/files/is-windows-file-path.ts

@@ -9,5 +9,5 @@ /**

}
//#endregion
exports.isWindowsFilePath = isWindowsFilePath;
//# sourceMappingURL=is-windows-file-path.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"is-windows-file-path.cjs","names":[],"sources":["../../src/files/is-windows-file-path.ts"],"sourcesContent":["/**\n * Fast check if file path starts with a windows drive letter, e.g. 'C:/' or 'C:\\\\'\n */\nexport function isWindowsFilePath(str: string) {\n\treturn /^[a-zA-Z]:[\\\\/]/.test(str);\n}\n"],"mappings":";;;;;AAGA,SAAgB,kBAAkB,KAAa;AAC9C,QAAO,kBAAkB,KAAK,IAAI"}
{"version":3,"file":"is-windows-file-path.cjs","names":[],"sources":["../../src/files/is-windows-file-path.ts"],"sourcesContent":["/**\n * Fast check if file path starts with a windows drive letter, e.g. 'C:/' or 'C:\\\\'\n */\nexport function isWindowsFilePath(str: string) {\n\treturn /^[a-zA-Z]:[\\\\/]/.test(str);\n}\n"],"mappings":";;;;;AAGA,SAAgB,kBAAkB,KAAa;CAC9C,OAAO,kBAAkB,KAAK,GAAG;AAClC"}

@@ -8,5 +8,5 @@ //#region src/files/is-windows-file-path.ts

}
//#endregion
export { isWindowsFilePath };
//# sourceMappingURL=is-windows-file-path.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"is-windows-file-path.mjs","names":[],"sources":["../../src/files/is-windows-file-path.ts"],"sourcesContent":["/**\n * Fast check if file path starts with a windows drive letter, e.g. 'C:/' or 'C:\\\\'\n */\nexport function isWindowsFilePath(str: string) {\n\treturn /^[a-zA-Z]:[\\\\/]/.test(str);\n}\n"],"mappings":";;;;AAGA,SAAgB,kBAAkB,KAAa;AAC9C,QAAO,kBAAkB,KAAK,IAAI"}
{"version":3,"file":"is-windows-file-path.mjs","names":[],"sources":["../../src/files/is-windows-file-path.ts"],"sourcesContent":["/**\n * Fast check if file path starts with a windows drive letter, e.g. 'C:/' or 'C:\\\\'\n */\nexport function isWindowsFilePath(str: string) {\n\treturn /^[a-zA-Z]:[\\\\/]/.test(str);\n}\n"],"mappings":";;;;AAGA,SAAgB,kBAAkB,KAAa;CAC9C,OAAO,kBAAkB,KAAK,GAAG;AAClC"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/files/sanitize-filename.ts

@@ -7,3 +7,3 @@ const INVALID_CHARS_REGEX = /[<>:"/\\|?*\u0000-\u001F\u007F-\u009F]/g;

const LEADING_TRAILING_DOTS_SPACES_REGEX = /^[\s.]+|[\s.]+$/g;
const WINDOWS_RESERVED_NAMES = new Set([
const WINDOWS_RESERVED_NAMES = /* @__PURE__ */ new Set([
"CON",

@@ -60,5 +60,5 @@ "PRN",

};
//#endregion
exports.sanitizeFilename = sanitizeFilename;
//# sourceMappingURL=sanitize-filename.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"sanitize-filename.cjs","names":[],"sources":["../../src/files/sanitize-filename.ts"],"sourcesContent":["// Constants definition\n/* eslint-disable no-control-regex */\nconst INVALID_CHARS_REGEX = /[<>:\"/\\\\|?*\\u0000-\\u001F\\u007F-\\u009F]/g;\nconst ZERO_WIDTH_CHARS_REGEX = /[\\u200B-\\u200D\\u2060\\uFEFF]/g;\nconst UNICODE_SPACES_REGEX = /[\\u00A0\\u2000-\\u200A]/g;\nconst LEADING_TRAILING_DOTS_SPACES_REGEX = /^[\\s.]+|[\\s.]+$/g;\n/* eslint-enable no-control-regex */\n\nconst WINDOWS_RESERVED_NAMES = new Set([\n\t'CON',\n\t'PRN',\n\t'AUX',\n\t'NUL',\n\t'COM1',\n\t'COM2',\n\t'COM3',\n\t'COM4',\n\t'COM5',\n\t'COM6',\n\t'COM7',\n\t'COM8',\n\t'COM9',\n\t'LPT1',\n\t'LPT2',\n\t'LPT3',\n\t'LPT4',\n\t'LPT5',\n\t'LPT6',\n\t'LPT7',\n\t'LPT8',\n\t'LPT9',\n]);\n\nconst DEFAULT_FALLBACK_NAME = 'untitled';\nconst MAX_FILENAME_LENGTH = 200;\n\n/**\n * Sanitizes a filename to be compatible with Mac, Linux, and Windows file systems\n *\n * Main features:\n * - Replace invalid characters (e.g. \":\" in hello:world)\n * - Handle Windows reserved names\n * - Limit filename length\n * - Normalize Unicode characters\n *\n * @param filename - The filename to sanitize (without extension)\n * @param maxLength - Maximum filename length (default: 200)\n * @returns A sanitized filename (without extension)\n *\n * @example\n * sanitizeFilename('hello:world') // returns 'hello_world'\n * sanitizeFilename('CON') // returns '_CON'\n * sanitizeFilename('') // returns 'untitled'\n */\nexport const sanitizeFilename = (\n\tfilename: string,\n\tmaxLength: number = MAX_FILENAME_LENGTH,\n): string => {\n\t// Input validation\n\tif (!filename) {\n\t\treturn DEFAULT_FALLBACK_NAME;\n\t}\n\n\tlet baseName = filename\n\t\t.trim()\n\t\t.replace(INVALID_CHARS_REGEX, '_')\n\t\t.replace(ZERO_WIDTH_CHARS_REGEX, '')\n\t\t.replace(UNICODE_SPACES_REGEX, ' ')\n\t\t.replace(LEADING_TRAILING_DOTS_SPACES_REGEX, '');\n\n\t// Handle empty or invalid filenames after cleaning\n\tif (!baseName) {\n\t\tbaseName = DEFAULT_FALLBACK_NAME;\n\t}\n\n\t// Handle Windows reserved names\n\tif (WINDOWS_RESERVED_NAMES.has(baseName.toUpperCase())) {\n\t\tbaseName = `_${baseName}`;\n\t}\n\n\t// Truncate if too long\n\tif (baseName.length > maxLength) {\n\t\tbaseName = baseName.slice(0, maxLength);\n\t}\n\n\treturn baseName;\n};\n"],"mappings":";;AAEA,MAAM,sBAAsB;AAC5B,MAAM,yBAAyB;AAC/B,MAAM,uBAAuB;AAC7B,MAAM,qCAAqC;AAG3C,MAAM,yBAAyB,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;AAEF,MAAM,wBAAwB;AAC9B,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;AAoB5B,MAAa,oBACZ,UACA,YAAoB,wBACR;AAEZ,KAAI,CAAC,SACJ,QAAO;CAGR,IAAI,WAAW,SACb,MAAM,CACN,QAAQ,qBAAqB,IAAI,CACjC,QAAQ,wBAAwB,GAAG,CACnC,QAAQ,sBAAsB,IAAI,CAClC,QAAQ,oCAAoC,GAAG;AAGjD,KAAI,CAAC,SACJ,YAAW;AAIZ,KAAI,uBAAuB,IAAI,SAAS,aAAa,CAAC,CACrD,YAAW,IAAI;AAIhB,KAAI,SAAS,SAAS,UACrB,YAAW,SAAS,MAAM,GAAG,UAAU;AAGxC,QAAO"}
{"version":3,"file":"sanitize-filename.cjs","names":[],"sources":["../../src/files/sanitize-filename.ts"],"sourcesContent":["// Constants definition\n/* eslint-disable no-control-regex */\nconst INVALID_CHARS_REGEX = /[<>:\"/\\\\|?*\\u0000-\\u001F\\u007F-\\u009F]/g;\nconst ZERO_WIDTH_CHARS_REGEX = /[\\u200B-\\u200D\\u2060\\uFEFF]/g;\nconst UNICODE_SPACES_REGEX = /[\\u00A0\\u2000-\\u200A]/g;\nconst LEADING_TRAILING_DOTS_SPACES_REGEX = /^[\\s.]+|[\\s.]+$/g;\n/* eslint-enable no-control-regex */\n\nconst WINDOWS_RESERVED_NAMES = new Set([\n\t'CON',\n\t'PRN',\n\t'AUX',\n\t'NUL',\n\t'COM1',\n\t'COM2',\n\t'COM3',\n\t'COM4',\n\t'COM5',\n\t'COM6',\n\t'COM7',\n\t'COM8',\n\t'COM9',\n\t'LPT1',\n\t'LPT2',\n\t'LPT3',\n\t'LPT4',\n\t'LPT5',\n\t'LPT6',\n\t'LPT7',\n\t'LPT8',\n\t'LPT9',\n]);\n\nconst DEFAULT_FALLBACK_NAME = 'untitled';\nconst MAX_FILENAME_LENGTH = 200;\n\n/**\n * Sanitizes a filename to be compatible with Mac, Linux, and Windows file systems\n *\n * Main features:\n * - Replace invalid characters (e.g. \":\" in hello:world)\n * - Handle Windows reserved names\n * - Limit filename length\n * - Normalize Unicode characters\n *\n * @param filename - The filename to sanitize (without extension)\n * @param maxLength - Maximum filename length (default: 200)\n * @returns A sanitized filename (without extension)\n *\n * @example\n * sanitizeFilename('hello:world') // returns 'hello_world'\n * sanitizeFilename('CON') // returns '_CON'\n * sanitizeFilename('') // returns 'untitled'\n */\nexport const sanitizeFilename = (\n\tfilename: string,\n\tmaxLength: number = MAX_FILENAME_LENGTH,\n): string => {\n\t// Input validation\n\tif (!filename) {\n\t\treturn DEFAULT_FALLBACK_NAME;\n\t}\n\n\tlet baseName = filename\n\t\t.trim()\n\t\t.replace(INVALID_CHARS_REGEX, '_')\n\t\t.replace(ZERO_WIDTH_CHARS_REGEX, '')\n\t\t.replace(UNICODE_SPACES_REGEX, ' ')\n\t\t.replace(LEADING_TRAILING_DOTS_SPACES_REGEX, '');\n\n\t// Handle empty or invalid filenames after cleaning\n\tif (!baseName) {\n\t\tbaseName = DEFAULT_FALLBACK_NAME;\n\t}\n\n\t// Handle Windows reserved names\n\tif (WINDOWS_RESERVED_NAMES.has(baseName.toUpperCase())) {\n\t\tbaseName = `_${baseName}`;\n\t}\n\n\t// Truncate if too long\n\tif (baseName.length > maxLength) {\n\t\tbaseName = baseName.slice(0, maxLength);\n\t}\n\n\treturn baseName;\n};\n"],"mappings":";;AAEA,MAAM,sBAAsB;AAC5B,MAAM,yBAAyB;AAC/B,MAAM,uBAAuB;AAC7B,MAAM,qCAAqC;AAG3C,MAAM,yCAAyB,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC;AAED,MAAM,wBAAwB;AAC9B,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;AAoB5B,MAAa,oBACZ,UACA,YAAoB,wBACR;CAEZ,IAAI,CAAC,UACJ,OAAO;CAGR,IAAI,WAAW,SACb,KAAK,CAAC,CACN,QAAQ,qBAAqB,GAAG,CAAC,CACjC,QAAQ,wBAAwB,EAAE,CAAC,CACnC,QAAQ,sBAAsB,GAAG,CAAC,CAClC,QAAQ,oCAAoC,EAAE;CAGhD,IAAI,CAAC,UACJ,WAAW;CAIZ,IAAI,uBAAuB,IAAI,SAAS,YAAY,CAAC,GACpD,WAAW,IAAI;CAIhB,IAAI,SAAS,SAAS,WACrB,WAAW,SAAS,MAAM,GAAG,SAAS;CAGvC,OAAO;AACR"}

@@ -6,3 +6,3 @@ //#region src/files/sanitize-filename.ts

const LEADING_TRAILING_DOTS_SPACES_REGEX = /^[\s.]+|[\s.]+$/g;
const WINDOWS_RESERVED_NAMES = new Set([
const WINDOWS_RESERVED_NAMES = /* @__PURE__ */ new Set([
"CON",

@@ -59,5 +59,5 @@ "PRN",

};
//#endregion
export { sanitizeFilename };
//# sourceMappingURL=sanitize-filename.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"sanitize-filename.mjs","names":[],"sources":["../../src/files/sanitize-filename.ts"],"sourcesContent":["// Constants definition\n/* eslint-disable no-control-regex */\nconst INVALID_CHARS_REGEX = /[<>:\"/\\\\|?*\\u0000-\\u001F\\u007F-\\u009F]/g;\nconst ZERO_WIDTH_CHARS_REGEX = /[\\u200B-\\u200D\\u2060\\uFEFF]/g;\nconst UNICODE_SPACES_REGEX = /[\\u00A0\\u2000-\\u200A]/g;\nconst LEADING_TRAILING_DOTS_SPACES_REGEX = /^[\\s.]+|[\\s.]+$/g;\n/* eslint-enable no-control-regex */\n\nconst WINDOWS_RESERVED_NAMES = new Set([\n\t'CON',\n\t'PRN',\n\t'AUX',\n\t'NUL',\n\t'COM1',\n\t'COM2',\n\t'COM3',\n\t'COM4',\n\t'COM5',\n\t'COM6',\n\t'COM7',\n\t'COM8',\n\t'COM9',\n\t'LPT1',\n\t'LPT2',\n\t'LPT3',\n\t'LPT4',\n\t'LPT5',\n\t'LPT6',\n\t'LPT7',\n\t'LPT8',\n\t'LPT9',\n]);\n\nconst DEFAULT_FALLBACK_NAME = 'untitled';\nconst MAX_FILENAME_LENGTH = 200;\n\n/**\n * Sanitizes a filename to be compatible with Mac, Linux, and Windows file systems\n *\n * Main features:\n * - Replace invalid characters (e.g. \":\" in hello:world)\n * - Handle Windows reserved names\n * - Limit filename length\n * - Normalize Unicode characters\n *\n * @param filename - The filename to sanitize (without extension)\n * @param maxLength - Maximum filename length (default: 200)\n * @returns A sanitized filename (without extension)\n *\n * @example\n * sanitizeFilename('hello:world') // returns 'hello_world'\n * sanitizeFilename('CON') // returns '_CON'\n * sanitizeFilename('') // returns 'untitled'\n */\nexport const sanitizeFilename = (\n\tfilename: string,\n\tmaxLength: number = MAX_FILENAME_LENGTH,\n): string => {\n\t// Input validation\n\tif (!filename) {\n\t\treturn DEFAULT_FALLBACK_NAME;\n\t}\n\n\tlet baseName = filename\n\t\t.trim()\n\t\t.replace(INVALID_CHARS_REGEX, '_')\n\t\t.replace(ZERO_WIDTH_CHARS_REGEX, '')\n\t\t.replace(UNICODE_SPACES_REGEX, ' ')\n\t\t.replace(LEADING_TRAILING_DOTS_SPACES_REGEX, '');\n\n\t// Handle empty or invalid filenames after cleaning\n\tif (!baseName) {\n\t\tbaseName = DEFAULT_FALLBACK_NAME;\n\t}\n\n\t// Handle Windows reserved names\n\tif (WINDOWS_RESERVED_NAMES.has(baseName.toUpperCase())) {\n\t\tbaseName = `_${baseName}`;\n\t}\n\n\t// Truncate if too long\n\tif (baseName.length > maxLength) {\n\t\tbaseName = baseName.slice(0, maxLength);\n\t}\n\n\treturn baseName;\n};\n"],"mappings":";AAEA,MAAM,sBAAsB;AAC5B,MAAM,yBAAyB;AAC/B,MAAM,uBAAuB;AAC7B,MAAM,qCAAqC;AAG3C,MAAM,yBAAyB,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;AAEF,MAAM,wBAAwB;AAC9B,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;AAoB5B,MAAa,oBACZ,UACA,YAAoB,wBACR;AAEZ,KAAI,CAAC,SACJ,QAAO;CAGR,IAAI,WAAW,SACb,MAAM,CACN,QAAQ,qBAAqB,IAAI,CACjC,QAAQ,wBAAwB,GAAG,CACnC,QAAQ,sBAAsB,IAAI,CAClC,QAAQ,oCAAoC,GAAG;AAGjD,KAAI,CAAC,SACJ,YAAW;AAIZ,KAAI,uBAAuB,IAAI,SAAS,aAAa,CAAC,CACrD,YAAW,IAAI;AAIhB,KAAI,SAAS,SAAS,UACrB,YAAW,SAAS,MAAM,GAAG,UAAU;AAGxC,QAAO"}
{"version":3,"file":"sanitize-filename.mjs","names":[],"sources":["../../src/files/sanitize-filename.ts"],"sourcesContent":["// Constants definition\n/* eslint-disable no-control-regex */\nconst INVALID_CHARS_REGEX = /[<>:\"/\\\\|?*\\u0000-\\u001F\\u007F-\\u009F]/g;\nconst ZERO_WIDTH_CHARS_REGEX = /[\\u200B-\\u200D\\u2060\\uFEFF]/g;\nconst UNICODE_SPACES_REGEX = /[\\u00A0\\u2000-\\u200A]/g;\nconst LEADING_TRAILING_DOTS_SPACES_REGEX = /^[\\s.]+|[\\s.]+$/g;\n/* eslint-enable no-control-regex */\n\nconst WINDOWS_RESERVED_NAMES = new Set([\n\t'CON',\n\t'PRN',\n\t'AUX',\n\t'NUL',\n\t'COM1',\n\t'COM2',\n\t'COM3',\n\t'COM4',\n\t'COM5',\n\t'COM6',\n\t'COM7',\n\t'COM8',\n\t'COM9',\n\t'LPT1',\n\t'LPT2',\n\t'LPT3',\n\t'LPT4',\n\t'LPT5',\n\t'LPT6',\n\t'LPT7',\n\t'LPT8',\n\t'LPT9',\n]);\n\nconst DEFAULT_FALLBACK_NAME = 'untitled';\nconst MAX_FILENAME_LENGTH = 200;\n\n/**\n * Sanitizes a filename to be compatible with Mac, Linux, and Windows file systems\n *\n * Main features:\n * - Replace invalid characters (e.g. \":\" in hello:world)\n * - Handle Windows reserved names\n * - Limit filename length\n * - Normalize Unicode characters\n *\n * @param filename - The filename to sanitize (without extension)\n * @param maxLength - Maximum filename length (default: 200)\n * @returns A sanitized filename (without extension)\n *\n * @example\n * sanitizeFilename('hello:world') // returns 'hello_world'\n * sanitizeFilename('CON') // returns '_CON'\n * sanitizeFilename('') // returns 'untitled'\n */\nexport const sanitizeFilename = (\n\tfilename: string,\n\tmaxLength: number = MAX_FILENAME_LENGTH,\n): string => {\n\t// Input validation\n\tif (!filename) {\n\t\treturn DEFAULT_FALLBACK_NAME;\n\t}\n\n\tlet baseName = filename\n\t\t.trim()\n\t\t.replace(INVALID_CHARS_REGEX, '_')\n\t\t.replace(ZERO_WIDTH_CHARS_REGEX, '')\n\t\t.replace(UNICODE_SPACES_REGEX, ' ')\n\t\t.replace(LEADING_TRAILING_DOTS_SPACES_REGEX, '');\n\n\t// Handle empty or invalid filenames after cleaning\n\tif (!baseName) {\n\t\tbaseName = DEFAULT_FALLBACK_NAME;\n\t}\n\n\t// Handle Windows reserved names\n\tif (WINDOWS_RESERVED_NAMES.has(baseName.toUpperCase())) {\n\t\tbaseName = `_${baseName}`;\n\t}\n\n\t// Truncate if too long\n\tif (baseName.length > maxLength) {\n\t\tbaseName = baseName.slice(0, maxLength);\n\t}\n\n\treturn baseName;\n};\n"],"mappings":";AAEA,MAAM,sBAAsB;AAC5B,MAAM,yBAAyB;AAC/B,MAAM,uBAAuB;AAC7B,MAAM,qCAAqC;AAG3C,MAAM,yCAAyB,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC;AAED,MAAM,wBAAwB;AAC9B,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;AAoB5B,MAAa,oBACZ,UACA,YAAoB,wBACR;CAEZ,IAAI,CAAC,UACJ,OAAO;CAGR,IAAI,WAAW,SACb,KAAK,CAAC,CACN,QAAQ,qBAAqB,GAAG,CAAC,CACjC,QAAQ,wBAAwB,EAAE,CAAC,CACnC,QAAQ,sBAAsB,GAAG,CAAC,CAClC,QAAQ,oCAAoC,EAAE;CAGhD,IAAI,CAAC,UACJ,WAAW;CAIZ,IAAI,uBAAuB,IAAI,SAAS,YAAY,CAAC,GACpD,WAAW,IAAI;CAIhB,IAAI,SAAS,SAAS,WACrB,WAAW,SAAS,MAAM,GAAG,SAAS;CAGvC,OAAO;AACR"}

@@ -1,3 +0,42 @@

const require_format_pem_block = require('./format-pem-block2.cjs');
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/format-pem-block.ts
const PEM_BODY_LINE_LENGTH = 64;
function formatCompactPem(pem, isPublic) {
const trimmed = pem.trim();
if ((trimmed.match(/-----BEGIN /g) ?? []).length !== 1) return void 0;
const labelPattern = isPublic ? "[A-Z0-9 ]*PUBLIC KEY" : "[A-Z0-9 ]*PRIVATE KEY|CERTIFICATE";
const pemMatch = trimmed.match(new RegExp(`^-----BEGIN (${labelPattern})-----([\\s\\S]*?)-----END \\1-----$`));
if (!pemMatch) return void 0;
const [, label, body] = pemMatch;
const normalizedBody = body.replace(/\\n/g, "\n").trim();
return `-----BEGIN ${label}-----\n${/\s/.test(normalizedBody) ? normalizedBody.replace(/:\s+/g, ":").replace(/\s+/g, "\n") : (normalizedBody.match(new RegExp(`.{1,${PEM_BODY_LINE_LENGTH}}`, "g")) ?? []).join("\n")}\n-----END ${label}-----`;
}
/**
* Normalize a single PEM-encoded block (private key, public key, or certificate)
* by collapsing whitespace and wrapping the body at 64 chars. Multi-block PEM
* chains are returned unchanged.
*
* @param pem - The PEM-encoded block to format.
* @param isPublic - When true, match `PUBLIC KEY` labels instead of the default `PRIVATE KEY` / `CERTIFICATE`.
* @returns The formatted PEM block.
*/
function formatPemBlock(pem, isPublic = false) {
let regex = /(PRIVATE KEY|CERTIFICATE)/;
if (isPublic) regex = /(PUBLIC KEY)/;
if (!pem || /\n/.test(pem)) return pem;
const compactPem = formatCompactPem(pem, isPublic);
if (compactPem !== void 0) return compactPem;
let formattedPem = "";
pem.split("-----").filter((item) => item !== "").forEach((part) => {
if (regex.test(part)) formattedPem += `-----${part}-----`;
else if (/Proc-Type|DEK-Info/.test(part)) {
part = part.replace(/:\s+/g, ":");
formattedPem += part.replace(/\\n/g, "\n").replace(/\s+/g, "\n");
} else formattedPem += part.replace(/\\n/g, "\n").replace(/\s+/g, "\n");
});
return formattedPem;
}
//#endregion
exports.formatPemBlock = formatPemBlock;
exports.formatPemBlock = require_format_pem_block.formatPemBlock;
//# sourceMappingURL=format-pem-block.cjs.map

@@ -1,3 +0,41 @@

import { t as formatPemBlock } from "./format-pem-block2.mjs";
//#region src/format-pem-block.ts
const PEM_BODY_LINE_LENGTH = 64;
function formatCompactPem(pem, isPublic) {
const trimmed = pem.trim();
if ((trimmed.match(/-----BEGIN /g) ?? []).length !== 1) return void 0;
const labelPattern = isPublic ? "[A-Z0-9 ]*PUBLIC KEY" : "[A-Z0-9 ]*PRIVATE KEY|CERTIFICATE";
const pemMatch = trimmed.match(new RegExp(`^-----BEGIN (${labelPattern})-----([\\s\\S]*?)-----END \\1-----$`));
if (!pemMatch) return void 0;
const [, label, body] = pemMatch;
const normalizedBody = body.replace(/\\n/g, "\n").trim();
return `-----BEGIN ${label}-----\n${/\s/.test(normalizedBody) ? normalizedBody.replace(/:\s+/g, ":").replace(/\s+/g, "\n") : (normalizedBody.match(new RegExp(`.{1,${PEM_BODY_LINE_LENGTH}}`, "g")) ?? []).join("\n")}\n-----END ${label}-----`;
}
/**
* Normalize a single PEM-encoded block (private key, public key, or certificate)
* by collapsing whitespace and wrapping the body at 64 chars. Multi-block PEM
* chains are returned unchanged.
*
* @param pem - The PEM-encoded block to format.
* @param isPublic - When true, match `PUBLIC KEY` labels instead of the default `PRIVATE KEY` / `CERTIFICATE`.
* @returns The formatted PEM block.
*/
function formatPemBlock(pem, isPublic = false) {
let regex = /(PRIVATE KEY|CERTIFICATE)/;
if (isPublic) regex = /(PUBLIC KEY)/;
if (!pem || /\n/.test(pem)) return pem;
const compactPem = formatCompactPem(pem, isPublic);
if (compactPem !== void 0) return compactPem;
let formattedPem = "";
pem.split("-----").filter((item) => item !== "").forEach((part) => {
if (regex.test(part)) formattedPem += `-----${part}-----`;
else if (/Proc-Type|DEK-Info/.test(part)) {
part = part.replace(/:\s+/g, ":");
formattedPem += part.replace(/\\n/g, "\n").replace(/\s+/g, "\n");
} else formattedPem += part.replace(/\\n/g, "\n").replace(/\s+/g, "\n");
});
return formattedPem;
}
//#endregion
export { formatPemBlock };
export { formatPemBlock };
//# sourceMappingURL=format-pem-block.mjs.map

@@ -1,4 +0,3 @@

let __n8n_constants = require("@n8n/constants");
let nanoid = require("nanoid");
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
let _n8n_constants = require("@n8n/constants");
//#region src/generate-nano-id.ts

@@ -25,6 +24,6 @@ /**

*/
const generateNanoId = (0, nanoid.customAlphabet)(__n8n_constants.NANOID_ALPHABET, 16);
const generateNanoId = (0, require("nanoid").customAlphabet)(_n8n_constants.NANOID_ALPHABET, 16);
//#endregion
exports.generateNanoId = generateNanoId;
//# sourceMappingURL=generate-nano-id.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"generate-nano-id.cjs","names":["NANOID_ALPHABET"],"sources":["../src/generate-nano-id.ts"],"sourcesContent":["import { NANOID_ALPHABET } from '@n8n/constants';\nimport { customAlphabet } from 'nanoid';\n\n/**\n * Generates a unique 16-character nanoid.\n *\n * This is the canonical ID generator used across the entire n8n codebase for:\n * - Workflow IDs\n * - Project IDs\n * - Variable IDs\n * - API Key IDs\n * - And other entity IDs\n *\n * Both frontend and backend MUST use this function to ensure consistency.\n *\n * @returns A 16-character ID\n *\n * @example\n * ```ts\n * const id = generateNanoId();\n * // => 'aBcDeFgHiJkLmNoP' (16 characters)\n * ```\n */\nexport const generateNanoId = customAlphabet(NANOID_ALPHABET, 16);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,4CAAgCA,iCAAiB,GAAG"}
{"version":3,"file":"generate-nano-id.cjs","names":["NANOID_ALPHABET"],"sources":["../src/generate-nano-id.ts"],"sourcesContent":["import { NANOID_ALPHABET } from '@n8n/constants';\nimport { customAlphabet } from 'nanoid';\n\n/**\n * Generates a unique 16-character nanoid.\n *\n * This is the canonical ID generator used across the entire n8n codebase for:\n * - Workflow IDs\n * - Project IDs\n * - Variable IDs\n * - API Key IDs\n * - And other entity IDs\n *\n * Both frontend and backend MUST use this function to ensure consistency.\n *\n * @returns A 16-character ID\n *\n * @example\n * ```ts\n * const id = generateNanoId();\n * // => 'aBcDeFgHiJkLmNoP' (16 characters)\n * ```\n */\nexport const generateNanoId = customAlphabet(NANOID_ALPHABET, 16);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,kBAAA,mBAAA,CAAA,CAAA,eAAA,CAAgCA,eAAAA,iBAAiB,EAAE"}
import { NANOID_ALPHABET } from "@n8n/constants";
import { customAlphabet } from "nanoid";
//#region src/generate-nano-id.ts

@@ -26,5 +25,5 @@ /**

const generateNanoId = customAlphabet(NANOID_ALPHABET, 16);
//#endregion
export { generateNanoId };
//# sourceMappingURL=generate-nano-id.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"generate-nano-id.mjs","names":[],"sources":["../src/generate-nano-id.ts"],"sourcesContent":["import { NANOID_ALPHABET } from '@n8n/constants';\nimport { customAlphabet } from 'nanoid';\n\n/**\n * Generates a unique 16-character nanoid.\n *\n * This is the canonical ID generator used across the entire n8n codebase for:\n * - Workflow IDs\n * - Project IDs\n * - Variable IDs\n * - API Key IDs\n * - And other entity IDs\n *\n * Both frontend and backend MUST use this function to ensure consistency.\n *\n * @returns A 16-character ID\n *\n * @example\n * ```ts\n * const id = generateNanoId();\n * // => 'aBcDeFgHiJkLmNoP' (16 characters)\n * ```\n */\nexport const generateNanoId = customAlphabet(NANOID_ALPHABET, 16);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,iBAAiB,eAAe,iBAAiB,GAAG"}
{"version":3,"file":"generate-nano-id.mjs","names":[],"sources":["../src/generate-nano-id.ts"],"sourcesContent":["import { NANOID_ALPHABET } from '@n8n/constants';\nimport { customAlphabet } from 'nanoid';\n\n/**\n * Generates a unique 16-character nanoid.\n *\n * This is the canonical ID generator used across the entire n8n codebase for:\n * - Workflow IDs\n * - Project IDs\n * - Variable IDs\n * - API Key IDs\n * - And other entity IDs\n *\n * Both frontend and backend MUST use this function to ensure consistency.\n *\n * @returns A 16-character ID\n *\n * @example\n * ```ts\n * const id = generateNanoId();\n * // => 'aBcDeFgHiJkLmNoP' (16 characters)\n * ```\n */\nexport const generateNanoId = customAlphabet(NANOID_ALPHABET, 16);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,iBAAiB,eAAe,iBAAiB,EAAE"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/get-jwt-expiry.ts

@@ -20,5 +20,5 @@ /**

}
//#endregion
exports.getJwtExpiry = getJwtExpiry;
//# sourceMappingURL=get-jwt-expiry.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"get-jwt-expiry.cjs","names":[],"sources":["../src/get-jwt-expiry.ts"],"sourcesContent":["/**\n * Decode the payload of a JWT without verifying the signature.\n * Returns the `exp` claim (seconds since epoch) or undefined.\n *\n * Use only for trusted tokens (e.g. ones we just received from our own proxy)\n * where the goal is scheduling refresh, not authenticating the issuer.\n */\nexport function getJwtExpiry(jwt: string): number | undefined {\n\tconst parts = jwt.split('.');\n\tif (parts.length !== 3) return undefined;\n\ttry {\n\t\tconst payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString()) as {\n\t\t\texp?: number;\n\t\t};\n\t\treturn typeof payload.exp === 'number' ? payload.exp : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"],"mappings":";;;;;;;;;AAOA,SAAgB,aAAa,KAAiC;CAC7D,MAAM,QAAQ,IAAI,MAAM,IAAI;AAC5B,KAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,KAAI;EACH,MAAM,UAAU,KAAK,MAAM,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,UAAU,CAAC;AAGzE,SAAO,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM;SAChD;AACP"}
{"version":3,"file":"get-jwt-expiry.cjs","names":[],"sources":["../src/get-jwt-expiry.ts"],"sourcesContent":["/**\n * Decode the payload of a JWT without verifying the signature.\n * Returns the `exp` claim (seconds since epoch) or undefined.\n *\n * Use only for trusted tokens (e.g. ones we just received from our own proxy)\n * where the goal is scheduling refresh, not authenticating the issuer.\n */\nexport function getJwtExpiry(jwt: string): number | undefined {\n\tconst parts = jwt.split('.');\n\tif (parts.length !== 3) return undefined;\n\ttry {\n\t\tconst payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString()) as {\n\t\t\texp?: number;\n\t\t};\n\t\treturn typeof payload.exp === 'number' ? payload.exp : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"],"mappings":";;;;;;;;;AAOA,SAAgB,aAAa,KAAiC;CAC7D,MAAM,QAAQ,IAAI,MAAM,GAAG;CAC3B,IAAI,MAAM,WAAW,GAAG,OAAO,KAAA;CAC/B,IAAI;EACH,MAAM,UAAU,KAAK,MAAM,OAAO,KAAK,MAAM,IAAI,WAAW,CAAC,CAAC,SAAS,CAAC;EAGxE,OAAO,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM,KAAA;CACxD,QAAQ;EACP;CACD;AACD"}

@@ -19,5 +19,5 @@ //#region src/get-jwt-expiry.ts

}
//#endregion
export { getJwtExpiry };
//# sourceMappingURL=get-jwt-expiry.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"get-jwt-expiry.mjs","names":[],"sources":["../src/get-jwt-expiry.ts"],"sourcesContent":["/**\n * Decode the payload of a JWT without verifying the signature.\n * Returns the `exp` claim (seconds since epoch) or undefined.\n *\n * Use only for trusted tokens (e.g. ones we just received from our own proxy)\n * where the goal is scheduling refresh, not authenticating the issuer.\n */\nexport function getJwtExpiry(jwt: string): number | undefined {\n\tconst parts = jwt.split('.');\n\tif (parts.length !== 3) return undefined;\n\ttry {\n\t\tconst payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString()) as {\n\t\t\texp?: number;\n\t\t};\n\t\treturn typeof payload.exp === 'number' ? payload.exp : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,aAAa,KAAiC;CAC7D,MAAM,QAAQ,IAAI,MAAM,IAAI;AAC5B,KAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,KAAI;EACH,MAAM,UAAU,KAAK,MAAM,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,UAAU,CAAC;AAGzE,SAAO,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM;SAChD;AACP"}
{"version":3,"file":"get-jwt-expiry.mjs","names":[],"sources":["../src/get-jwt-expiry.ts"],"sourcesContent":["/**\n * Decode the payload of a JWT without verifying the signature.\n * Returns the `exp` claim (seconds since epoch) or undefined.\n *\n * Use only for trusted tokens (e.g. ones we just received from our own proxy)\n * where the goal is scheduling refresh, not authenticating the issuer.\n */\nexport function getJwtExpiry(jwt: string): number | undefined {\n\tconst parts = jwt.split('.');\n\tif (parts.length !== 3) return undefined;\n\ttry {\n\t\tconst payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString()) as {\n\t\t\texp?: number;\n\t\t};\n\t\treturn typeof payload.exp === 'number' ? payload.exp : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,aAAa,KAAiC;CAC7D,MAAM,QAAQ,IAAI,MAAM,GAAG;CAC3B,IAAI,MAAM,WAAW,GAAG,OAAO,KAAA;CAC/B,IAAI;EACH,MAAM,UAAU,KAAK,MAAM,OAAO,KAAK,MAAM,IAAI,WAAW,CAAC,CAAC,SAAS,CAAC;EAGxE,OAAO,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM,KAAA;CACxD,QAAQ;EACP;CACD;AACD"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/is-record.ts

@@ -6,5 +6,5 @@ function isRecord(value) {

}
//#endregion
exports.isRecord = isRecord;
//# sourceMappingURL=is-record.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"is-record.cjs","names":[],"sources":["../src/is-record.ts"],"sourcesContent":["export function isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"],"mappings":";;AAAA,SAAgB,SAAS,OAAkD;AAC1E,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM"}
{"version":3,"file":"is-record.cjs","names":[],"sources":["../src/is-record.ts"],"sourcesContent":["export function isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"],"mappings":";;AAAA,SAAgB,SAAS,OAAkD;CAC1E,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC3E"}

@@ -5,5 +5,5 @@ //#region src/is-record.ts

}
//#endregion
export { isRecord };
//# sourceMappingURL=is-record.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"is-record.mjs","names":[],"sources":["../src/is-record.ts"],"sourcesContent":["export function isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"],"mappings":";AAAA,SAAgB,SAAS,OAAkD;AAC1E,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM"}
{"version":3,"file":"is-record.mjs","names":[],"sources":["../src/is-record.ts"],"sourcesContent":["export function isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"],"mappings":";AAAA,SAAgB,SAAS,OAAkD;CAC1E,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC3E"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/number/smart-decimal.ts

@@ -8,5 +8,5 @@ const smartDecimal = (value, decimals = 2) => {

};
//#endregion
exports.smartDecimal = smartDecimal;
//# sourceMappingURL=smart-decimal.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"smart-decimal.cjs","names":[],"sources":["../../src/number/smart-decimal.ts"],"sourcesContent":["export const smartDecimal = (value: number, decimals = 2): number => {\n\t// Check if integer\n\tif (Number.isInteger(value)) {\n\t\treturn value;\n\t}\n\n\t// Check if it has only one decimal place\n\tif (value.toString().split('.')[1].length <= decimals) {\n\t\treturn value;\n\t}\n\n\treturn Number(value.toFixed(decimals));\n};\n"],"mappings":";;AAAA,MAAa,gBAAgB,OAAe,WAAW,MAAc;AAEpE,KAAI,OAAO,UAAU,MAAM,CAC1B,QAAO;AAIR,KAAI,MAAM,UAAU,CAAC,MAAM,IAAI,CAAC,GAAG,UAAU,SAC5C,QAAO;AAGR,QAAO,OAAO,MAAM,QAAQ,SAAS,CAAC"}
{"version":3,"file":"smart-decimal.cjs","names":[],"sources":["../../src/number/smart-decimal.ts"],"sourcesContent":["export const smartDecimal = (value: number, decimals = 2): number => {\n\t// Check if integer\n\tif (Number.isInteger(value)) {\n\t\treturn value;\n\t}\n\n\t// Check if it has only one decimal place\n\tif (value.toString().split('.')[1].length <= decimals) {\n\t\treturn value;\n\t}\n\n\treturn Number(value.toFixed(decimals));\n};\n"],"mappings":";;AAAA,MAAa,gBAAgB,OAAe,WAAW,MAAc;CAEpE,IAAI,OAAO,UAAU,KAAK,GACzB,OAAO;CAIR,IAAI,MAAM,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,UAAU,UAC5C,OAAO;CAGR,OAAO,OAAO,MAAM,QAAQ,QAAQ,CAAC;AACtC"}

@@ -7,5 +7,5 @@ //#region src/number/smart-decimal.ts

};
//#endregion
export { smartDecimal };
//# sourceMappingURL=smart-decimal.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"smart-decimal.mjs","names":[],"sources":["../../src/number/smart-decimal.ts"],"sourcesContent":["export const smartDecimal = (value: number, decimals = 2): number => {\n\t// Check if integer\n\tif (Number.isInteger(value)) {\n\t\treturn value;\n\t}\n\n\t// Check if it has only one decimal place\n\tif (value.toString().split('.')[1].length <= decimals) {\n\t\treturn value;\n\t}\n\n\treturn Number(value.toFixed(decimals));\n};\n"],"mappings":";AAAA,MAAa,gBAAgB,OAAe,WAAW,MAAc;AAEpE,KAAI,OAAO,UAAU,MAAM,CAC1B,QAAO;AAIR,KAAI,MAAM,UAAU,CAAC,MAAM,IAAI,CAAC,GAAG,UAAU,SAC5C,QAAO;AAGR,QAAO,OAAO,MAAM,QAAQ,SAAS,CAAC"}
{"version":3,"file":"smart-decimal.mjs","names":[],"sources":["../../src/number/smart-decimal.ts"],"sourcesContent":["export const smartDecimal = (value: number, decimals = 2): number => {\n\t// Check if integer\n\tif (Number.isInteger(value)) {\n\t\treturn value;\n\t}\n\n\t// Check if it has only one decimal place\n\tif (value.toString().split('.')[1].length <= decimals) {\n\t\treturn value;\n\t}\n\n\treturn Number(value.toFixed(decimals));\n};\n"],"mappings":";AAAA,MAAa,gBAAgB,OAAe,WAAW,MAAc;CAEpE,IAAI,OAAO,UAAU,KAAK,GACzB,OAAO;CAIR,IAAI,MAAM,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,UAAU,UAC5C,OAAO;CAGR,OAAO,OAAO,MAAM,QAAQ,QAAQ,CAAC;AACtC"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/placeholder.ts

@@ -73,3 +73,2 @@ const PLACEHOLDER_SUFFIX = "__>";

}
//#endregion

@@ -82,2 +81,3 @@ exports.extractPlaceholderLabels = extractPlaceholderLabels;

exports.isPlaceholderValue = isPlaceholderValue;
//# sourceMappingURL=placeholder.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"placeholder.cjs","names":["labels: string[]"],"sources":["../src/placeholder.ts"],"sourcesContent":["const PLACEHOLDER_PREFIX = '<__PLACEHOLDER';\nconst PLACEHOLDER_SUFFIX = '__>';\nconst PLACEHOLDER_VALUE_PREFIX = '<__PLACEHOLDER_VALUE__';\n\nconst PLACEHOLDER_REGEX = /<__PLACEHOLDER.*?__>/;\n\nexport interface PlaceholderDetail {\n\tpath: string[];\n\tlabel: string;\n}\n\n/** Check if a value is a placeholder sentinel string (format: `<__PLACEHOLDER_VALUE__hint__>`). */\nexport function isPlaceholderString(value: unknown): boolean {\n\treturn (\n\t\ttypeof value === 'string' &&\n\t\tvalue.startsWith(PLACEHOLDER_VALUE_PREFIX) &&\n\t\tvalue.endsWith(PLACEHOLDER_SUFFIX)\n\t);\n}\n\n/** Recursively check if a value (string, array, or object) contains any placeholder sentinel strings. */\nexport function hasPlaceholderDeep(value: unknown): boolean {\n\tif (typeof value === 'string') return isPlaceholderString(value);\n\tif (Array.isArray(value)) return value.some(hasPlaceholderDeep);\n\tif (value !== null && typeof value === 'object') {\n\t\treturn Object.values(value as Record<string, unknown>).some(hasPlaceholderDeep);\n\t}\n\treturn false;\n}\n\n/** Checks if a value is a placeholder value (matches the placeholder regex pattern). */\nexport function isPlaceholderValue(value: unknown): boolean {\n\tif (typeof value !== 'string') return false;\n\treturn !!value.match(PLACEHOLDER_REGEX);\n}\n\n/**\n * Extracts the label from a single placeholder string.\n * Handles formats like:\n * - <__PLACEHOLDER_VALUE__label__>\n * - <__PLACEHOLDER__: label__>\n */\nfunction extractLabelFromPlaceholder(placeholder: string): string {\n\tlet label = placeholder.slice(PLACEHOLDER_PREFIX.length, -PLACEHOLDER_SUFFIX.length);\n\n\tif (label.startsWith('_VALUE__')) {\n\t\tlabel = label.slice('_VALUE__'.length);\n\t} else if (label.startsWith('__:')) {\n\t\tlabel = label.slice('__:'.length);\n\t} else if (label.startsWith('__')) {\n\t\tlabel = label.slice('__'.length);\n\t}\n\n\treturn label.trim();\n}\n\n/**\n * Extracts all placeholder labels from a string value.\n * Handles both cases where the entire value is a placeholder and where\n * placeholders are embedded within code (e.g., Code node).\n * Returns an array of labels found.\n */\nexport function extractPlaceholderLabels(value: unknown): string[] {\n\tif (typeof value !== 'string') return [];\n\n\tconst labels: string[] = [];\n\tconst regex = new RegExp(PLACEHOLDER_REGEX.source, 'g');\n\tlet match;\n\n\twhile ((match = regex.exec(value)) !== null) {\n\t\tconst label = extractLabelFromPlaceholder(match[0]);\n\t\tif (label.length > 0) {\n\t\t\tlabels.push(label);\n\t\t}\n\t}\n\n\treturn labels;\n}\n\n/**\n * Recursively searches through a value (object, array, or primitive) to find\n * all placeholder values and their paths.\n */\nexport function findPlaceholderDetails(value: unknown, path: string[] = []): PlaceholderDetail[] {\n\tif (typeof value === 'string') {\n\t\tconst labels = extractPlaceholderLabels(value);\n\t\treturn labels.map((label) => ({ path, label }));\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.flatMap((item, index) => findPlaceholderDetails(item, [...path, `[${index}]`]));\n\t}\n\n\tif (value !== null && typeof value === 'object') {\n\t\treturn Object.entries(value).flatMap(([key, nested]) =>\n\t\t\tfindPlaceholderDetails(nested, [...path, key]),\n\t\t);\n\t}\n\n\treturn [];\n}\n\n/**\n * Formats a path array into a dot-notation string for display.\n * Array indices are preserved as [N] without leading dots.\n */\nexport function formatPlaceholderPath(path: string[]): string {\n\tif (path.length === 0) return 'parameters';\n\n\treturn path\n\t\t.map((segment, index) => (segment.startsWith('[') || index === 0 ? segment : `.${segment}`))\n\t\t.join('');\n}\n"],"mappings":";;AACA,MAAM,qBAAqB;AAC3B,MAAM,2BAA2B;AAEjC,MAAM,oBAAoB;;AAQ1B,SAAgB,oBAAoB,OAAyB;AAC5D,QACC,OAAO,UAAU,YACjB,MAAM,WAAW,yBAAyB,IAC1C,MAAM,SAAS,mBAAmB;;;AAKpC,SAAgB,mBAAmB,OAAyB;AAC3D,KAAI,OAAO,UAAU,SAAU,QAAO,oBAAoB,MAAM;AAChE,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,MAAM,KAAK,mBAAmB;AAC/D,KAAI,UAAU,QAAQ,OAAO,UAAU,SACtC,QAAO,OAAO,OAAO,MAAiC,CAAC,KAAK,mBAAmB;AAEhF,QAAO;;;AAIR,SAAgB,mBAAmB,OAAyB;AAC3D,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAO,CAAC,CAAC,MAAM,MAAM,kBAAkB;;;;;;;;AASxC,SAAS,4BAA4B,aAA6B;CACjE,IAAI,QAAQ,YAAY,MAAM,IAA2B,GAA2B;AAEpF,KAAI,MAAM,WAAW,WAAW,CAC/B,SAAQ,MAAM,MAAM,EAAkB;UAC5B,MAAM,WAAW,MAAM,CACjC,SAAQ,MAAM,MAAM,EAAa;UACvB,MAAM,WAAW,KAAK,CAChC,SAAQ,MAAM,MAAM,EAAY;AAGjC,QAAO,MAAM,MAAM;;;;;;;;AASpB,SAAgB,yBAAyB,OAA0B;AAClE,KAAI,OAAO,UAAU,SAAU,QAAO,EAAE;CAExC,MAAMA,SAAmB,EAAE;CAC3B,MAAM,QAAQ,IAAI,OAAO,kBAAkB,QAAQ,IAAI;CACvD,IAAI;AAEJ,SAAQ,QAAQ,MAAM,KAAK,MAAM,MAAM,MAAM;EAC5C,MAAM,QAAQ,4BAA4B,MAAM,GAAG;AACnD,MAAI,MAAM,SAAS,EAClB,QAAO,KAAK,MAAM;;AAIpB,QAAO;;;;;;AAOR,SAAgB,uBAAuB,OAAgB,OAAiB,EAAE,EAAuB;AAChG,KAAI,OAAO,UAAU,SAEpB,QADe,yBAAyB,MAAM,CAChC,KAAK,WAAW;EAAE;EAAM;EAAO,EAAE;AAGhD,KAAI,MAAM,QAAQ,MAAM,CACvB,QAAO,MAAM,SAAS,MAAM,UAAU,uBAAuB,MAAM,CAAC,GAAG,MAAM,IAAI,MAAM,GAAG,CAAC,CAAC;AAG7F,KAAI,UAAU,QAAQ,OAAO,UAAU,SACtC,QAAO,OAAO,QAAQ,MAAM,CAAC,SAAS,CAAC,KAAK,YAC3C,uBAAuB,QAAQ,CAAC,GAAG,MAAM,IAAI,CAAC,CAC9C;AAGF,QAAO,EAAE;;;;;;AAOV,SAAgB,sBAAsB,MAAwB;AAC7D,KAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,QAAO,KACL,KAAK,SAAS,UAAW,QAAQ,WAAW,IAAI,IAAI,UAAU,IAAI,UAAU,IAAI,UAAW,CAC3F,KAAK,GAAG"}
{"version":3,"file":"placeholder.cjs","names":[],"sources":["../src/placeholder.ts"],"sourcesContent":["const PLACEHOLDER_PREFIX = '<__PLACEHOLDER';\nconst PLACEHOLDER_SUFFIX = '__>';\nconst PLACEHOLDER_VALUE_PREFIX = '<__PLACEHOLDER_VALUE__';\n\nconst PLACEHOLDER_REGEX = /<__PLACEHOLDER.*?__>/;\n\nexport interface PlaceholderDetail {\n\tpath: string[];\n\tlabel: string;\n}\n\n/** Check if a value is a placeholder sentinel string (format: `<__PLACEHOLDER_VALUE__hint__>`). */\nexport function isPlaceholderString(value: unknown): boolean {\n\treturn (\n\t\ttypeof value === 'string' &&\n\t\tvalue.startsWith(PLACEHOLDER_VALUE_PREFIX) &&\n\t\tvalue.endsWith(PLACEHOLDER_SUFFIX)\n\t);\n}\n\n/** Recursively check if a value (string, array, or object) contains any placeholder sentinel strings. */\nexport function hasPlaceholderDeep(value: unknown): boolean {\n\tif (typeof value === 'string') return isPlaceholderString(value);\n\tif (Array.isArray(value)) return value.some(hasPlaceholderDeep);\n\tif (value !== null && typeof value === 'object') {\n\t\treturn Object.values(value as Record<string, unknown>).some(hasPlaceholderDeep);\n\t}\n\treturn false;\n}\n\n/** Checks if a value is a placeholder value (matches the placeholder regex pattern). */\nexport function isPlaceholderValue(value: unknown): boolean {\n\tif (typeof value !== 'string') return false;\n\treturn !!value.match(PLACEHOLDER_REGEX);\n}\n\n/**\n * Extracts the label from a single placeholder string.\n * Handles formats like:\n * - <__PLACEHOLDER_VALUE__label__>\n * - <__PLACEHOLDER__: label__>\n */\nfunction extractLabelFromPlaceholder(placeholder: string): string {\n\tlet label = placeholder.slice(PLACEHOLDER_PREFIX.length, -PLACEHOLDER_SUFFIX.length);\n\n\tif (label.startsWith('_VALUE__')) {\n\t\tlabel = label.slice('_VALUE__'.length);\n\t} else if (label.startsWith('__:')) {\n\t\tlabel = label.slice('__:'.length);\n\t} else if (label.startsWith('__')) {\n\t\tlabel = label.slice('__'.length);\n\t}\n\n\treturn label.trim();\n}\n\n/**\n * Extracts all placeholder labels from a string value.\n * Handles both cases where the entire value is a placeholder and where\n * placeholders are embedded within code (e.g., Code node).\n * Returns an array of labels found.\n */\nexport function extractPlaceholderLabels(value: unknown): string[] {\n\tif (typeof value !== 'string') return [];\n\n\tconst labels: string[] = [];\n\tconst regex = new RegExp(PLACEHOLDER_REGEX.source, 'g');\n\tlet match;\n\n\twhile ((match = regex.exec(value)) !== null) {\n\t\tconst label = extractLabelFromPlaceholder(match[0]);\n\t\tif (label.length > 0) {\n\t\t\tlabels.push(label);\n\t\t}\n\t}\n\n\treturn labels;\n}\n\n/**\n * Recursively searches through a value (object, array, or primitive) to find\n * all placeholder values and their paths.\n */\nexport function findPlaceholderDetails(value: unknown, path: string[] = []): PlaceholderDetail[] {\n\tif (typeof value === 'string') {\n\t\tconst labels = extractPlaceholderLabels(value);\n\t\treturn labels.map((label) => ({ path, label }));\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.flatMap((item, index) => findPlaceholderDetails(item, [...path, `[${index}]`]));\n\t}\n\n\tif (value !== null && typeof value === 'object') {\n\t\treturn Object.entries(value).flatMap(([key, nested]) =>\n\t\t\tfindPlaceholderDetails(nested, [...path, key]),\n\t\t);\n\t}\n\n\treturn [];\n}\n\n/**\n * Formats a path array into a dot-notation string for display.\n * Array indices are preserved as [N] without leading dots.\n */\nexport function formatPlaceholderPath(path: string[]): string {\n\tif (path.length === 0) return 'parameters';\n\n\treturn path\n\t\t.map((segment, index) => (segment.startsWith('[') || index === 0 ? segment : `.${segment}`))\n\t\t.join('');\n}\n"],"mappings":";;AACA,MAAM,qBAAqB;AAC3B,MAAM,2BAA2B;AAEjC,MAAM,oBAAoB;;AAQ1B,SAAgB,oBAAoB,OAAyB;CAC5D,OACC,OAAO,UAAU,YACjB,MAAM,WAAW,wBAAwB,KACzC,MAAM,SAAS,kBAAkB;AAEnC;;AAGA,SAAgB,mBAAmB,OAAyB;CAC3D,IAAI,OAAO,UAAU,UAAU,OAAO,oBAAoB,KAAK;CAC/D,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,KAAK,kBAAkB;CAC9D,IAAI,UAAU,QAAQ,OAAO,UAAU,UACtC,OAAO,OAAO,OAAO,KAAgC,CAAC,CAAC,KAAK,kBAAkB;CAE/E,OAAO;AACR;;AAGA,SAAgB,mBAAmB,OAAyB;CAC3D,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,OAAO,CAAC,CAAC,MAAM,MAAM,iBAAiB;AACvC;;;;;;;AAQA,SAAS,4BAA4B,aAA6B;CACjE,IAAI,QAAQ,YAAY,MAAM,IAA2B,EAA0B;CAEnF,IAAI,MAAM,WAAW,UAAU,GAC9B,QAAQ,MAAM,MAAM,CAAiB;MAC/B,IAAI,MAAM,WAAW,KAAK,GAChC,QAAQ,MAAM,MAAM,CAAY;MAC1B,IAAI,MAAM,WAAW,IAAI,GAC/B,QAAQ,MAAM,MAAM,CAAW;CAGhC,OAAO,MAAM,KAAK;AACnB;;;;;;;AAQA,SAAgB,yBAAyB,OAA0B;CAClE,IAAI,OAAO,UAAU,UAAU,OAAO,CAAC;CAEvC,MAAM,SAAmB,CAAC;CAC1B,MAAM,QAAQ,IAAI,OAAO,kBAAkB,QAAQ,GAAG;CACtD,IAAI;CAEJ,QAAQ,QAAQ,MAAM,KAAK,KAAK,OAAO,MAAM;EAC5C,MAAM,QAAQ,4BAA4B,MAAM,EAAE;EAClD,IAAI,MAAM,SAAS,GAClB,OAAO,KAAK,KAAK;CAEnB;CAEA,OAAO;AACR;;;;;AAMA,SAAgB,uBAAuB,OAAgB,OAAiB,CAAC,GAAwB;CAChG,IAAI,OAAO,UAAU,UAEpB,OADe,yBAAyB,KAC5B,CAAC,CAAC,KAAK,WAAW;EAAE;EAAM;CAAM,EAAE;CAG/C,IAAI,MAAM,QAAQ,KAAK,GACtB,OAAO,MAAM,SAAS,MAAM,UAAU,uBAAuB,MAAM,CAAC,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC,CAAC;CAG5F,IAAI,UAAU,QAAQ,OAAO,UAAU,UACtC,OAAO,OAAO,QAAQ,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,YAC3C,uBAAuB,QAAQ,CAAC,GAAG,MAAM,GAAG,CAAC,CAC9C;CAGD,OAAO,CAAC;AACT;;;;;AAMA,SAAgB,sBAAsB,MAAwB;CAC7D,IAAI,KAAK,WAAW,GAAG,OAAO;CAE9B,OAAO,KACL,KAAK,SAAS,UAAW,QAAQ,WAAW,GAAG,KAAK,UAAU,IAAI,UAAU,IAAI,SAAU,CAAC,CAC3F,KAAK,EAAE;AACV"}

@@ -72,5 +72,5 @@ //#region src/placeholder.ts

}
//#endregion
export { extractPlaceholderLabels, findPlaceholderDetails, formatPlaceholderPath, hasPlaceholderDeep, isPlaceholderString, isPlaceholderValue };
//# sourceMappingURL=placeholder.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"placeholder.mjs","names":["labels: string[]"],"sources":["../src/placeholder.ts"],"sourcesContent":["const PLACEHOLDER_PREFIX = '<__PLACEHOLDER';\nconst PLACEHOLDER_SUFFIX = '__>';\nconst PLACEHOLDER_VALUE_PREFIX = '<__PLACEHOLDER_VALUE__';\n\nconst PLACEHOLDER_REGEX = /<__PLACEHOLDER.*?__>/;\n\nexport interface PlaceholderDetail {\n\tpath: string[];\n\tlabel: string;\n}\n\n/** Check if a value is a placeholder sentinel string (format: `<__PLACEHOLDER_VALUE__hint__>`). */\nexport function isPlaceholderString(value: unknown): boolean {\n\treturn (\n\t\ttypeof value === 'string' &&\n\t\tvalue.startsWith(PLACEHOLDER_VALUE_PREFIX) &&\n\t\tvalue.endsWith(PLACEHOLDER_SUFFIX)\n\t);\n}\n\n/** Recursively check if a value (string, array, or object) contains any placeholder sentinel strings. */\nexport function hasPlaceholderDeep(value: unknown): boolean {\n\tif (typeof value === 'string') return isPlaceholderString(value);\n\tif (Array.isArray(value)) return value.some(hasPlaceholderDeep);\n\tif (value !== null && typeof value === 'object') {\n\t\treturn Object.values(value as Record<string, unknown>).some(hasPlaceholderDeep);\n\t}\n\treturn false;\n}\n\n/** Checks if a value is a placeholder value (matches the placeholder regex pattern). */\nexport function isPlaceholderValue(value: unknown): boolean {\n\tif (typeof value !== 'string') return false;\n\treturn !!value.match(PLACEHOLDER_REGEX);\n}\n\n/**\n * Extracts the label from a single placeholder string.\n * Handles formats like:\n * - <__PLACEHOLDER_VALUE__label__>\n * - <__PLACEHOLDER__: label__>\n */\nfunction extractLabelFromPlaceholder(placeholder: string): string {\n\tlet label = placeholder.slice(PLACEHOLDER_PREFIX.length, -PLACEHOLDER_SUFFIX.length);\n\n\tif (label.startsWith('_VALUE__')) {\n\t\tlabel = label.slice('_VALUE__'.length);\n\t} else if (label.startsWith('__:')) {\n\t\tlabel = label.slice('__:'.length);\n\t} else if (label.startsWith('__')) {\n\t\tlabel = label.slice('__'.length);\n\t}\n\n\treturn label.trim();\n}\n\n/**\n * Extracts all placeholder labels from a string value.\n * Handles both cases where the entire value is a placeholder and where\n * placeholders are embedded within code (e.g., Code node).\n * Returns an array of labels found.\n */\nexport function extractPlaceholderLabels(value: unknown): string[] {\n\tif (typeof value !== 'string') return [];\n\n\tconst labels: string[] = [];\n\tconst regex = new RegExp(PLACEHOLDER_REGEX.source, 'g');\n\tlet match;\n\n\twhile ((match = regex.exec(value)) !== null) {\n\t\tconst label = extractLabelFromPlaceholder(match[0]);\n\t\tif (label.length > 0) {\n\t\t\tlabels.push(label);\n\t\t}\n\t}\n\n\treturn labels;\n}\n\n/**\n * Recursively searches through a value (object, array, or primitive) to find\n * all placeholder values and their paths.\n */\nexport function findPlaceholderDetails(value: unknown, path: string[] = []): PlaceholderDetail[] {\n\tif (typeof value === 'string') {\n\t\tconst labels = extractPlaceholderLabels(value);\n\t\treturn labels.map((label) => ({ path, label }));\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.flatMap((item, index) => findPlaceholderDetails(item, [...path, `[${index}]`]));\n\t}\n\n\tif (value !== null && typeof value === 'object') {\n\t\treturn Object.entries(value).flatMap(([key, nested]) =>\n\t\t\tfindPlaceholderDetails(nested, [...path, key]),\n\t\t);\n\t}\n\n\treturn [];\n}\n\n/**\n * Formats a path array into a dot-notation string for display.\n * Array indices are preserved as [N] without leading dots.\n */\nexport function formatPlaceholderPath(path: string[]): string {\n\tif (path.length === 0) return 'parameters';\n\n\treturn path\n\t\t.map((segment, index) => (segment.startsWith('[') || index === 0 ? segment : `.${segment}`))\n\t\t.join('');\n}\n"],"mappings":";AACA,MAAM,qBAAqB;AAC3B,MAAM,2BAA2B;AAEjC,MAAM,oBAAoB;;AAQ1B,SAAgB,oBAAoB,OAAyB;AAC5D,QACC,OAAO,UAAU,YACjB,MAAM,WAAW,yBAAyB,IAC1C,MAAM,SAAS,mBAAmB;;;AAKpC,SAAgB,mBAAmB,OAAyB;AAC3D,KAAI,OAAO,UAAU,SAAU,QAAO,oBAAoB,MAAM;AAChE,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,MAAM,KAAK,mBAAmB;AAC/D,KAAI,UAAU,QAAQ,OAAO,UAAU,SACtC,QAAO,OAAO,OAAO,MAAiC,CAAC,KAAK,mBAAmB;AAEhF,QAAO;;;AAIR,SAAgB,mBAAmB,OAAyB;AAC3D,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAO,CAAC,CAAC,MAAM,MAAM,kBAAkB;;;;;;;;AASxC,SAAS,4BAA4B,aAA6B;CACjE,IAAI,QAAQ,YAAY,MAAM,IAA2B,GAA2B;AAEpF,KAAI,MAAM,WAAW,WAAW,CAC/B,SAAQ,MAAM,MAAM,EAAkB;UAC5B,MAAM,WAAW,MAAM,CACjC,SAAQ,MAAM,MAAM,EAAa;UACvB,MAAM,WAAW,KAAK,CAChC,SAAQ,MAAM,MAAM,EAAY;AAGjC,QAAO,MAAM,MAAM;;;;;;;;AASpB,SAAgB,yBAAyB,OAA0B;AAClE,KAAI,OAAO,UAAU,SAAU,QAAO,EAAE;CAExC,MAAMA,SAAmB,EAAE;CAC3B,MAAM,QAAQ,IAAI,OAAO,kBAAkB,QAAQ,IAAI;CACvD,IAAI;AAEJ,SAAQ,QAAQ,MAAM,KAAK,MAAM,MAAM,MAAM;EAC5C,MAAM,QAAQ,4BAA4B,MAAM,GAAG;AACnD,MAAI,MAAM,SAAS,EAClB,QAAO,KAAK,MAAM;;AAIpB,QAAO;;;;;;AAOR,SAAgB,uBAAuB,OAAgB,OAAiB,EAAE,EAAuB;AAChG,KAAI,OAAO,UAAU,SAEpB,QADe,yBAAyB,MAAM,CAChC,KAAK,WAAW;EAAE;EAAM;EAAO,EAAE;AAGhD,KAAI,MAAM,QAAQ,MAAM,CACvB,QAAO,MAAM,SAAS,MAAM,UAAU,uBAAuB,MAAM,CAAC,GAAG,MAAM,IAAI,MAAM,GAAG,CAAC,CAAC;AAG7F,KAAI,UAAU,QAAQ,OAAO,UAAU,SACtC,QAAO,OAAO,QAAQ,MAAM,CAAC,SAAS,CAAC,KAAK,YAC3C,uBAAuB,QAAQ,CAAC,GAAG,MAAM,IAAI,CAAC,CAC9C;AAGF,QAAO,EAAE;;;;;;AAOV,SAAgB,sBAAsB,MAAwB;AAC7D,KAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,QAAO,KACL,KAAK,SAAS,UAAW,QAAQ,WAAW,IAAI,IAAI,UAAU,IAAI,UAAU,IAAI,UAAW,CAC3F,KAAK,GAAG"}
{"version":3,"file":"placeholder.mjs","names":[],"sources":["../src/placeholder.ts"],"sourcesContent":["const PLACEHOLDER_PREFIX = '<__PLACEHOLDER';\nconst PLACEHOLDER_SUFFIX = '__>';\nconst PLACEHOLDER_VALUE_PREFIX = '<__PLACEHOLDER_VALUE__';\n\nconst PLACEHOLDER_REGEX = /<__PLACEHOLDER.*?__>/;\n\nexport interface PlaceholderDetail {\n\tpath: string[];\n\tlabel: string;\n}\n\n/** Check if a value is a placeholder sentinel string (format: `<__PLACEHOLDER_VALUE__hint__>`). */\nexport function isPlaceholderString(value: unknown): boolean {\n\treturn (\n\t\ttypeof value === 'string' &&\n\t\tvalue.startsWith(PLACEHOLDER_VALUE_PREFIX) &&\n\t\tvalue.endsWith(PLACEHOLDER_SUFFIX)\n\t);\n}\n\n/** Recursively check if a value (string, array, or object) contains any placeholder sentinel strings. */\nexport function hasPlaceholderDeep(value: unknown): boolean {\n\tif (typeof value === 'string') return isPlaceholderString(value);\n\tif (Array.isArray(value)) return value.some(hasPlaceholderDeep);\n\tif (value !== null && typeof value === 'object') {\n\t\treturn Object.values(value as Record<string, unknown>).some(hasPlaceholderDeep);\n\t}\n\treturn false;\n}\n\n/** Checks if a value is a placeholder value (matches the placeholder regex pattern). */\nexport function isPlaceholderValue(value: unknown): boolean {\n\tif (typeof value !== 'string') return false;\n\treturn !!value.match(PLACEHOLDER_REGEX);\n}\n\n/**\n * Extracts the label from a single placeholder string.\n * Handles formats like:\n * - <__PLACEHOLDER_VALUE__label__>\n * - <__PLACEHOLDER__: label__>\n */\nfunction extractLabelFromPlaceholder(placeholder: string): string {\n\tlet label = placeholder.slice(PLACEHOLDER_PREFIX.length, -PLACEHOLDER_SUFFIX.length);\n\n\tif (label.startsWith('_VALUE__')) {\n\t\tlabel = label.slice('_VALUE__'.length);\n\t} else if (label.startsWith('__:')) {\n\t\tlabel = label.slice('__:'.length);\n\t} else if (label.startsWith('__')) {\n\t\tlabel = label.slice('__'.length);\n\t}\n\n\treturn label.trim();\n}\n\n/**\n * Extracts all placeholder labels from a string value.\n * Handles both cases where the entire value is a placeholder and where\n * placeholders are embedded within code (e.g., Code node).\n * Returns an array of labels found.\n */\nexport function extractPlaceholderLabels(value: unknown): string[] {\n\tif (typeof value !== 'string') return [];\n\n\tconst labels: string[] = [];\n\tconst regex = new RegExp(PLACEHOLDER_REGEX.source, 'g');\n\tlet match;\n\n\twhile ((match = regex.exec(value)) !== null) {\n\t\tconst label = extractLabelFromPlaceholder(match[0]);\n\t\tif (label.length > 0) {\n\t\t\tlabels.push(label);\n\t\t}\n\t}\n\n\treturn labels;\n}\n\n/**\n * Recursively searches through a value (object, array, or primitive) to find\n * all placeholder values and their paths.\n */\nexport function findPlaceholderDetails(value: unknown, path: string[] = []): PlaceholderDetail[] {\n\tif (typeof value === 'string') {\n\t\tconst labels = extractPlaceholderLabels(value);\n\t\treturn labels.map((label) => ({ path, label }));\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.flatMap((item, index) => findPlaceholderDetails(item, [...path, `[${index}]`]));\n\t}\n\n\tif (value !== null && typeof value === 'object') {\n\t\treturn Object.entries(value).flatMap(([key, nested]) =>\n\t\t\tfindPlaceholderDetails(nested, [...path, key]),\n\t\t);\n\t}\n\n\treturn [];\n}\n\n/**\n * Formats a path array into a dot-notation string for display.\n * Array indices are preserved as [N] without leading dots.\n */\nexport function formatPlaceholderPath(path: string[]): string {\n\tif (path.length === 0) return 'parameters';\n\n\treturn path\n\t\t.map((segment, index) => (segment.startsWith('[') || index === 0 ? segment : `.${segment}`))\n\t\t.join('');\n}\n"],"mappings":";AACA,MAAM,qBAAqB;AAC3B,MAAM,2BAA2B;AAEjC,MAAM,oBAAoB;;AAQ1B,SAAgB,oBAAoB,OAAyB;CAC5D,OACC,OAAO,UAAU,YACjB,MAAM,WAAW,wBAAwB,KACzC,MAAM,SAAS,kBAAkB;AAEnC;;AAGA,SAAgB,mBAAmB,OAAyB;CAC3D,IAAI,OAAO,UAAU,UAAU,OAAO,oBAAoB,KAAK;CAC/D,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,KAAK,kBAAkB;CAC9D,IAAI,UAAU,QAAQ,OAAO,UAAU,UACtC,OAAO,OAAO,OAAO,KAAgC,CAAC,CAAC,KAAK,kBAAkB;CAE/E,OAAO;AACR;;AAGA,SAAgB,mBAAmB,OAAyB;CAC3D,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,OAAO,CAAC,CAAC,MAAM,MAAM,iBAAiB;AACvC;;;;;;;AAQA,SAAS,4BAA4B,aAA6B;CACjE,IAAI,QAAQ,YAAY,MAAM,IAA2B,EAA0B;CAEnF,IAAI,MAAM,WAAW,UAAU,GAC9B,QAAQ,MAAM,MAAM,CAAiB;MAC/B,IAAI,MAAM,WAAW,KAAK,GAChC,QAAQ,MAAM,MAAM,CAAY;MAC1B,IAAI,MAAM,WAAW,IAAI,GAC/B,QAAQ,MAAM,MAAM,CAAW;CAGhC,OAAO,MAAM,KAAK;AACnB;;;;;;;AAQA,SAAgB,yBAAyB,OAA0B;CAClE,IAAI,OAAO,UAAU,UAAU,OAAO,CAAC;CAEvC,MAAM,SAAmB,CAAC;CAC1B,MAAM,QAAQ,IAAI,OAAO,kBAAkB,QAAQ,GAAG;CACtD,IAAI;CAEJ,QAAQ,QAAQ,MAAM,KAAK,KAAK,OAAO,MAAM;EAC5C,MAAM,QAAQ,4BAA4B,MAAM,EAAE;EAClD,IAAI,MAAM,SAAS,GAClB,OAAO,KAAK,KAAK;CAEnB;CAEA,OAAO;AACR;;;;;AAMA,SAAgB,uBAAuB,OAAgB,OAAiB,CAAC,GAAwB;CAChG,IAAI,OAAO,UAAU,UAEpB,OADe,yBAAyB,KAC5B,CAAC,CAAC,KAAK,WAAW;EAAE;EAAM;CAAM,EAAE;CAG/C,IAAI,MAAM,QAAQ,KAAK,GACtB,OAAO,MAAM,SAAS,MAAM,UAAU,uBAAuB,MAAM,CAAC,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC,CAAC;CAG5F,IAAI,UAAU,QAAQ,OAAO,UAAU,UACtC,OAAO,OAAO,QAAQ,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,YAC3C,uBAAuB,QAAQ,CAAC,GAAG,MAAM,GAAG,CAAC,CAC9C;CAGD,OAAO,CAAC;AACT;;;;;AAMA,SAAgB,sBAAsB,MAAwB;CAC7D,IAAI,KAAK,WAAW,GAAG,OAAO;CAE9B,OAAO,KACL,KAAK,SAAS,UAAW,QAAQ,WAAW,GAAG,KAAK,UAAU,IAAI,UAAU,IAAI,SAAU,CAAC,CAC3F,KAAK,EAAE;AACV"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/promise/deferred-promise.ts

@@ -11,5 +11,5 @@ function createDeferredPromise() {

}
//#endregion
exports.createDeferredPromise = createDeferredPromise;
//# sourceMappingURL=deferred-promise.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"deferred-promise.cjs","names":["deferred: Partial<IDeferredPromise<T>>"],"sources":["../../src/promise/deferred-promise.ts"],"sourcesContent":["type ResolveFn<T> = (result: T | PromiseLike<T>) => void;\ntype RejectFn = (error: Error) => void;\n\nexport interface IDeferredPromise<T> {\n\tpromise: Promise<T>;\n\tresolve: ResolveFn<T>;\n\treject: RejectFn;\n}\n\nexport function createDeferredPromise<T = void>(): IDeferredPromise<T> {\n\tconst deferred: Partial<IDeferredPromise<T>> = {};\n\tdeferred.promise = new Promise<T>((resolve, reject) => {\n\t\tdeferred.resolve = resolve;\n\t\tdeferred.reject = reject;\n\t});\n\treturn deferred as IDeferredPromise<T>;\n}\n"],"mappings":";;AASA,SAAgB,wBAAuD;CACtE,MAAMA,WAAyC,EAAE;AACjD,UAAS,UAAU,IAAI,SAAY,SAAS,WAAW;AACtD,WAAS,UAAU;AACnB,WAAS,SAAS;GACjB;AACF,QAAO"}
{"version":3,"file":"deferred-promise.cjs","names":[],"sources":["../../src/promise/deferred-promise.ts"],"sourcesContent":["type ResolveFn<T> = (result: T | PromiseLike<T>) => void;\ntype RejectFn = (error: Error) => void;\n\nexport interface IDeferredPromise<T> {\n\tpromise: Promise<T>;\n\tresolve: ResolveFn<T>;\n\treject: RejectFn;\n}\n\nexport function createDeferredPromise<T = void>(): IDeferredPromise<T> {\n\tconst deferred: Partial<IDeferredPromise<T>> = {};\n\tdeferred.promise = new Promise<T>((resolve, reject) => {\n\t\tdeferred.resolve = resolve;\n\t\tdeferred.reject = reject;\n\t});\n\treturn deferred as IDeferredPromise<T>;\n}\n"],"mappings":";;AASA,SAAgB,wBAAuD;CACtE,MAAM,WAAyC,CAAC;CAChD,SAAS,UAAU,IAAI,SAAY,SAAS,WAAW;EACtD,SAAS,UAAU;EACnB,SAAS,SAAS;CACnB,CAAC;CACD,OAAO;AACR"}

@@ -10,5 +10,5 @@ //#region src/promise/deferred-promise.ts

}
//#endregion
export { createDeferredPromise };
//# sourceMappingURL=deferred-promise.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"deferred-promise.mjs","names":["deferred: Partial<IDeferredPromise<T>>"],"sources":["../../src/promise/deferred-promise.ts"],"sourcesContent":["type ResolveFn<T> = (result: T | PromiseLike<T>) => void;\ntype RejectFn = (error: Error) => void;\n\nexport interface IDeferredPromise<T> {\n\tpromise: Promise<T>;\n\tresolve: ResolveFn<T>;\n\treject: RejectFn;\n}\n\nexport function createDeferredPromise<T = void>(): IDeferredPromise<T> {\n\tconst deferred: Partial<IDeferredPromise<T>> = {};\n\tdeferred.promise = new Promise<T>((resolve, reject) => {\n\t\tdeferred.resolve = resolve;\n\t\tdeferred.reject = reject;\n\t});\n\treturn deferred as IDeferredPromise<T>;\n}\n"],"mappings":";AASA,SAAgB,wBAAuD;CACtE,MAAMA,WAAyC,EAAE;AACjD,UAAS,UAAU,IAAI,SAAY,SAAS,WAAW;AACtD,WAAS,UAAU;AACnB,WAAS,SAAS;GACjB;AACF,QAAO"}
{"version":3,"file":"deferred-promise.mjs","names":[],"sources":["../../src/promise/deferred-promise.ts"],"sourcesContent":["type ResolveFn<T> = (result: T | PromiseLike<T>) => void;\ntype RejectFn = (error: Error) => void;\n\nexport interface IDeferredPromise<T> {\n\tpromise: Promise<T>;\n\tresolve: ResolveFn<T>;\n\treject: RejectFn;\n}\n\nexport function createDeferredPromise<T = void>(): IDeferredPromise<T> {\n\tconst deferred: Partial<IDeferredPromise<T>> = {};\n\tdeferred.promise = new Promise<T>((resolve, reject) => {\n\t\tdeferred.resolve = resolve;\n\t\tdeferred.reject = reject;\n\t});\n\treturn deferred as IDeferredPromise<T>;\n}\n"],"mappings":";AASA,SAAgB,wBAAuD;CACtE,MAAM,WAAyC,CAAC;CAChD,SAAS,UAAU,IAAI,SAAY,SAAS,WAAW;EACtD,SAAS,UAAU;EACnB,SAAS,SAAS;CACnB,CAAC;CACD,OAAO;AACR"}

@@ -1,3 +0,3 @@

const require_ensure_error = require('./ensure-error.cjs');
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_errors_ensure_error = require("./errors/ensure-error.cjs");
//#region src/result.ts

@@ -22,6 +22,6 @@ const createResultOk = (data) => ({

} catch (e) {
return createResultError(require_ensure_error.ensureError(e));
const error = require_errors_ensure_error.ensureError(e);
return createResultError(error);
}
};
//#endregion

@@ -31,2 +31,3 @@ exports.createResultError = createResultError;

exports.toResult = toResult;
//# sourceMappingURL=result.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"result.cjs","names":["ensureError"],"sources":["../src/result.ts"],"sourcesContent":["import { ensureError } from './errors/ensure-error';\n\nexport type ResultOk<T> = { ok: true; result: T };\nexport type ResultError<E> = { ok: false; error: E };\nexport type Result<T, E> = ResultOk<T> | ResultError<E>;\n\nexport const createResultOk = <T>(data: T): ResultOk<T> => ({\n\tok: true,\n\tresult: data,\n});\n\nexport const createResultError = <E = unknown>(error: E): ResultError<E> => ({\n\tok: false,\n\terror,\n});\n\n/**\n * Executes the given function and converts it to a Result object.\n *\n * @example\n * const result = toResult(() => fs.writeFileSync('file.txt', 'Hello, World!'));\n */\nexport const toResult = <T, E extends Error = Error>(fn: () => T): Result<T, E> => {\n\ttry {\n\t\treturn createResultOk<T>(fn());\n\t} catch (e) {\n\t\tconst error = ensureError(e);\n\t\treturn createResultError<E>(error as E);\n\t}\n};\n"],"mappings":";;;AAMA,MAAa,kBAAqB,UAA0B;CAC3D,IAAI;CACJ,QAAQ;CACR;AAED,MAAa,qBAAkC,WAA8B;CAC5E,IAAI;CACJ;CACA;;;;;;;AAQD,MAAa,YAAwC,OAA8B;AAClF,KAAI;AACH,SAAO,eAAkB,IAAI,CAAC;UACtB,GAAG;AAEX,SAAO,kBADOA,iCAAY,EAAE,CACW"}
{"version":3,"file":"result.cjs","names":["ensureError"],"sources":["../src/result.ts"],"sourcesContent":["import { ensureError } from './errors/ensure-error';\n\nexport type ResultOk<T> = { ok: true; result: T };\nexport type ResultError<E> = { ok: false; error: E };\nexport type Result<T, E> = ResultOk<T> | ResultError<E>;\n\nexport const createResultOk = <T>(data: T): ResultOk<T> => ({\n\tok: true,\n\tresult: data,\n});\n\nexport const createResultError = <E = unknown>(error: E): ResultError<E> => ({\n\tok: false,\n\terror,\n});\n\n/**\n * Executes the given function and converts it to a Result object.\n *\n * @example\n * const result = toResult(() => fs.writeFileSync('file.txt', 'Hello, World!'));\n */\nexport const toResult = <T, E extends Error = Error>(fn: () => T): Result<T, E> => {\n\ttry {\n\t\treturn createResultOk<T>(fn());\n\t} catch (e) {\n\t\tconst error = ensureError(e);\n\t\treturn createResultError<E>(error as E);\n\t}\n};\n"],"mappings":";;;AAMA,MAAa,kBAAqB,UAA0B;CAC3D,IAAI;CACJ,QAAQ;AACT;AAEA,MAAa,qBAAkC,WAA8B;CAC5E,IAAI;CACJ;AACD;;;;;;;AAQA,MAAa,YAAwC,OAA8B;CAClF,IAAI;EACH,OAAO,eAAkB,GAAG,CAAC;CAC9B,SAAS,GAAG;EACX,MAAM,QAAQA,4BAAAA,YAAY,CAAC;EAC3B,OAAO,kBAAqB,KAAU;CACvC;AACD"}

@@ -1,3 +0,2 @@

import { t as ensureError } from "./ensure-error.mjs";
import { ensureError } from "./errors/ensure-error.mjs";
//#region src/result.ts

@@ -22,8 +21,9 @@ const createResultOk = (data) => ({

} catch (e) {
return createResultError(ensureError(e));
const error = ensureError(e);
return createResultError(error);
}
};
//#endregion
export { createResultError, createResultOk, toResult };
//# sourceMappingURL=result.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"result.mjs","names":[],"sources":["../src/result.ts"],"sourcesContent":["import { ensureError } from './errors/ensure-error';\n\nexport type ResultOk<T> = { ok: true; result: T };\nexport type ResultError<E> = { ok: false; error: E };\nexport type Result<T, E> = ResultOk<T> | ResultError<E>;\n\nexport const createResultOk = <T>(data: T): ResultOk<T> => ({\n\tok: true,\n\tresult: data,\n});\n\nexport const createResultError = <E = unknown>(error: E): ResultError<E> => ({\n\tok: false,\n\terror,\n});\n\n/**\n * Executes the given function and converts it to a Result object.\n *\n * @example\n * const result = toResult(() => fs.writeFileSync('file.txt', 'Hello, World!'));\n */\nexport const toResult = <T, E extends Error = Error>(fn: () => T): Result<T, E> => {\n\ttry {\n\t\treturn createResultOk<T>(fn());\n\t} catch (e) {\n\t\tconst error = ensureError(e);\n\t\treturn createResultError<E>(error as E);\n\t}\n};\n"],"mappings":";;;AAMA,MAAa,kBAAqB,UAA0B;CAC3D,IAAI;CACJ,QAAQ;CACR;AAED,MAAa,qBAAkC,WAA8B;CAC5E,IAAI;CACJ;CACA;;;;;;;AAQD,MAAa,YAAwC,OAA8B;AAClF,KAAI;AACH,SAAO,eAAkB,IAAI,CAAC;UACtB,GAAG;AAEX,SAAO,kBADO,YAAY,EAAE,CACW"}
{"version":3,"file":"result.mjs","names":[],"sources":["../src/result.ts"],"sourcesContent":["import { ensureError } from './errors/ensure-error';\n\nexport type ResultOk<T> = { ok: true; result: T };\nexport type ResultError<E> = { ok: false; error: E };\nexport type Result<T, E> = ResultOk<T> | ResultError<E>;\n\nexport const createResultOk = <T>(data: T): ResultOk<T> => ({\n\tok: true,\n\tresult: data,\n});\n\nexport const createResultError = <E = unknown>(error: E): ResultError<E> => ({\n\tok: false,\n\terror,\n});\n\n/**\n * Executes the given function and converts it to a Result object.\n *\n * @example\n * const result = toResult(() => fs.writeFileSync('file.txt', 'Hello, World!'));\n */\nexport const toResult = <T, E extends Error = Error>(fn: () => T): Result<T, E> => {\n\ttry {\n\t\treturn createResultOk<T>(fn());\n\t} catch (e) {\n\t\tconst error = ensureError(e);\n\t\treturn createResultError<E>(error as E);\n\t}\n};\n"],"mappings":";;AAMA,MAAa,kBAAqB,UAA0B;CAC3D,IAAI;CACJ,QAAQ;AACT;AAEA,MAAa,qBAAkC,WAA8B;CAC5E,IAAI;CACJ;AACD;;;;;;;AAQA,MAAa,YAAwC,OAA8B;CAClF,IAAI;EACH,OAAO,eAAkB,GAAG,CAAC;CAC9B,SAAS,GAAG;EACX,MAAM,QAAQ,YAAY,CAAC;EAC3B,OAAO,kBAAqB,KAAU;CACvC;AACD"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/retry.ts

@@ -37,5 +37,5 @@ /**

}
//#endregion
exports.retry = retry;
//# sourceMappingURL=retry.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"retry.cjs","names":[],"sources":["../src/retry.ts"],"sourcesContent":["type RetryFn = () => boolean | Promise<boolean>;\n\n/**\n * A utility that retries a function every `interval` milliseconds\n * until the function returns true or the maximum number of retries is reached.\n *\n * @param fn - A function that returns a boolean or a Promise resolving to a boolean.\n * @param interval - The time interval (in milliseconds) between each retry. Defaults to 1000.\n * @param maxRetries - The maximum number of retry attempts. Defaults to 3.\n * @param backoff - The backoff strategy to use: 'linear', 'exponential', or null.\n * @returns {Promise<boolean>} - A promise that resolves to:\n * - true: If the function returns true before reaching maxRetries.\n * - false: If the function never returns true or if an error occurs.\n */\nexport async function retry(\n\tfn: RetryFn,\n\tinterval: number = 1000,\n\tmaxRetries: number = 3,\n\tbackoff: 'exponential' | 'linear' | null = 'linear',\n): Promise<boolean> {\n\tlet attempt = 0;\n\n\twhile (attempt < maxRetries) {\n\t\tattempt++;\n\t\ttry {\n\t\t\tconst result = await fn();\n\t\t\tif (result) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('Error during retry:', error);\n\t\t\tthrow error;\n\t\t}\n\n\t\t// Wait for the specified interval before the next attempt, if any attempts remain.\n\t\tif (attempt < maxRetries) {\n\t\t\tlet computedInterval = interval;\n\n\t\t\tif (backoff === 'linear') {\n\t\t\t\tcomputedInterval = interval * attempt;\n\t\t\t} else if (backoff === 'exponential') {\n\t\t\t\tcomputedInterval = Math.pow(2, attempt - 1) * interval;\n\t\t\t\tcomputedInterval = Math.min(computedInterval, 30000); // Cap the maximum interval to 30 seconds\n\t\t\t}\n\n\t\t\tawait new Promise<void>((resolve) => setTimeout(resolve, computedInterval));\n\t\t}\n\t}\n\n\treturn false;\n}\n"],"mappings":";;;;;;;;;;;;;;AAcA,eAAsB,MACrB,IACA,WAAmB,KACnB,aAAqB,GACrB,UAA2C,UACxB;CACnB,IAAI,UAAU;AAEd,QAAO,UAAU,YAAY;AAC5B;AACA,MAAI;AAEH,OADe,MAAM,IAAI,CAExB,QAAO;WAEA,OAAO;AACf,WAAQ,MAAM,uBAAuB,MAAM;AAC3C,SAAM;;AAIP,MAAI,UAAU,YAAY;GACzB,IAAI,mBAAmB;AAEvB,OAAI,YAAY,SACf,oBAAmB,WAAW;YACpB,YAAY,eAAe;AACrC,uBAAmB,KAAK,IAAI,GAAG,UAAU,EAAE,GAAG;AAC9C,uBAAmB,KAAK,IAAI,kBAAkB,IAAM;;AAGrD,SAAM,IAAI,SAAe,YAAY,WAAW,SAAS,iBAAiB,CAAC;;;AAI7E,QAAO"}
{"version":3,"file":"retry.cjs","names":[],"sources":["../src/retry.ts"],"sourcesContent":["type RetryFn = () => boolean | Promise<boolean>;\n\n/**\n * A utility that retries a function every `interval` milliseconds\n * until the function returns true or the maximum number of retries is reached.\n *\n * @param fn - A function that returns a boolean or a Promise resolving to a boolean.\n * @param interval - The time interval (in milliseconds) between each retry. Defaults to 1000.\n * @param maxRetries - The maximum number of retry attempts. Defaults to 3.\n * @param backoff - The backoff strategy to use: 'linear', 'exponential', or null.\n * @returns {Promise<boolean>} - A promise that resolves to:\n * - true: If the function returns true before reaching maxRetries.\n * - false: If the function never returns true or if an error occurs.\n */\nexport async function retry(\n\tfn: RetryFn,\n\tinterval: number = 1000,\n\tmaxRetries: number = 3,\n\tbackoff: 'exponential' | 'linear' | null = 'linear',\n): Promise<boolean> {\n\tlet attempt = 0;\n\n\twhile (attempt < maxRetries) {\n\t\tattempt++;\n\t\ttry {\n\t\t\tconst result = await fn();\n\t\t\tif (result) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('Error during retry:', error);\n\t\t\tthrow error;\n\t\t}\n\n\t\t// Wait for the specified interval before the next attempt, if any attempts remain.\n\t\tif (attempt < maxRetries) {\n\t\t\tlet computedInterval = interval;\n\n\t\t\tif (backoff === 'linear') {\n\t\t\t\tcomputedInterval = interval * attempt;\n\t\t\t} else if (backoff === 'exponential') {\n\t\t\t\tcomputedInterval = Math.pow(2, attempt - 1) * interval;\n\t\t\t\tcomputedInterval = Math.min(computedInterval, 30000); // Cap the maximum interval to 30 seconds\n\t\t\t}\n\n\t\t\tawait new Promise<void>((resolve) => setTimeout(resolve, computedInterval));\n\t\t}\n\t}\n\n\treturn false;\n}\n"],"mappings":";;;;;;;;;;;;;;AAcA,eAAsB,MACrB,IACA,WAAmB,KACnB,aAAqB,GACrB,UAA2C,UACxB;CACnB,IAAI,UAAU;CAEd,OAAO,UAAU,YAAY;EAC5B;EACA,IAAI;GAEH,IAAI,MADiB,GAAG,GAEvB,OAAO;EAET,SAAS,OAAO;GACf,QAAQ,MAAM,uBAAuB,KAAK;GAC1C,MAAM;EACP;EAGA,IAAI,UAAU,YAAY;GACzB,IAAI,mBAAmB;GAEvB,IAAI,YAAY,UACf,mBAAmB,WAAW;QACxB,IAAI,YAAY,eAAe;IACrC,mBAAmB,KAAK,IAAI,GAAG,UAAU,CAAC,IAAI;IAC9C,mBAAmB,KAAK,IAAI,kBAAkB,GAAK;GACpD;GAEA,MAAM,IAAI,SAAe,YAAY,WAAW,SAAS,gBAAgB,CAAC;EAC3E;CACD;CAEA,OAAO;AACR"}

@@ -36,5 +36,5 @@ //#region src/retry.ts

}
//#endregion
export { retry };
//# sourceMappingURL=retry.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"retry.mjs","names":[],"sources":["../src/retry.ts"],"sourcesContent":["type RetryFn = () => boolean | Promise<boolean>;\n\n/**\n * A utility that retries a function every `interval` milliseconds\n * until the function returns true or the maximum number of retries is reached.\n *\n * @param fn - A function that returns a boolean or a Promise resolving to a boolean.\n * @param interval - The time interval (in milliseconds) between each retry. Defaults to 1000.\n * @param maxRetries - The maximum number of retry attempts. Defaults to 3.\n * @param backoff - The backoff strategy to use: 'linear', 'exponential', or null.\n * @returns {Promise<boolean>} - A promise that resolves to:\n * - true: If the function returns true before reaching maxRetries.\n * - false: If the function never returns true or if an error occurs.\n */\nexport async function retry(\n\tfn: RetryFn,\n\tinterval: number = 1000,\n\tmaxRetries: number = 3,\n\tbackoff: 'exponential' | 'linear' | null = 'linear',\n): Promise<boolean> {\n\tlet attempt = 0;\n\n\twhile (attempt < maxRetries) {\n\t\tattempt++;\n\t\ttry {\n\t\t\tconst result = await fn();\n\t\t\tif (result) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('Error during retry:', error);\n\t\t\tthrow error;\n\t\t}\n\n\t\t// Wait for the specified interval before the next attempt, if any attempts remain.\n\t\tif (attempt < maxRetries) {\n\t\t\tlet computedInterval = interval;\n\n\t\t\tif (backoff === 'linear') {\n\t\t\t\tcomputedInterval = interval * attempt;\n\t\t\t} else if (backoff === 'exponential') {\n\t\t\t\tcomputedInterval = Math.pow(2, attempt - 1) * interval;\n\t\t\t\tcomputedInterval = Math.min(computedInterval, 30000); // Cap the maximum interval to 30 seconds\n\t\t\t}\n\n\t\t\tawait new Promise<void>((resolve) => setTimeout(resolve, computedInterval));\n\t\t}\n\t}\n\n\treturn false;\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,eAAsB,MACrB,IACA,WAAmB,KACnB,aAAqB,GACrB,UAA2C,UACxB;CACnB,IAAI,UAAU;AAEd,QAAO,UAAU,YAAY;AAC5B;AACA,MAAI;AAEH,OADe,MAAM,IAAI,CAExB,QAAO;WAEA,OAAO;AACf,WAAQ,MAAM,uBAAuB,MAAM;AAC3C,SAAM;;AAIP,MAAI,UAAU,YAAY;GACzB,IAAI,mBAAmB;AAEvB,OAAI,YAAY,SACf,oBAAmB,WAAW;YACpB,YAAY,eAAe;AACrC,uBAAmB,KAAK,IAAI,GAAG,UAAU,EAAE,GAAG;AAC9C,uBAAmB,KAAK,IAAI,kBAAkB,IAAM;;AAGrD,SAAM,IAAI,SAAe,YAAY,WAAW,SAAS,iBAAiB,CAAC;;;AAI7E,QAAO"}
{"version":3,"file":"retry.mjs","names":[],"sources":["../src/retry.ts"],"sourcesContent":["type RetryFn = () => boolean | Promise<boolean>;\n\n/**\n * A utility that retries a function every `interval` milliseconds\n * until the function returns true or the maximum number of retries is reached.\n *\n * @param fn - A function that returns a boolean or a Promise resolving to a boolean.\n * @param interval - The time interval (in milliseconds) between each retry. Defaults to 1000.\n * @param maxRetries - The maximum number of retry attempts. Defaults to 3.\n * @param backoff - The backoff strategy to use: 'linear', 'exponential', or null.\n * @returns {Promise<boolean>} - A promise that resolves to:\n * - true: If the function returns true before reaching maxRetries.\n * - false: If the function never returns true or if an error occurs.\n */\nexport async function retry(\n\tfn: RetryFn,\n\tinterval: number = 1000,\n\tmaxRetries: number = 3,\n\tbackoff: 'exponential' | 'linear' | null = 'linear',\n): Promise<boolean> {\n\tlet attempt = 0;\n\n\twhile (attempt < maxRetries) {\n\t\tattempt++;\n\t\ttry {\n\t\t\tconst result = await fn();\n\t\t\tif (result) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('Error during retry:', error);\n\t\t\tthrow error;\n\t\t}\n\n\t\t// Wait for the specified interval before the next attempt, if any attempts remain.\n\t\tif (attempt < maxRetries) {\n\t\t\tlet computedInterval = interval;\n\n\t\t\tif (backoff === 'linear') {\n\t\t\t\tcomputedInterval = interval * attempt;\n\t\t\t} else if (backoff === 'exponential') {\n\t\t\t\tcomputedInterval = Math.pow(2, attempt - 1) * interval;\n\t\t\t\tcomputedInterval = Math.min(computedInterval, 30000); // Cap the maximum interval to 30 seconds\n\t\t\t}\n\n\t\t\tawait new Promise<void>((resolve) => setTimeout(resolve, computedInterval));\n\t\t}\n\t}\n\n\treturn false;\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,eAAsB,MACrB,IACA,WAAmB,KACnB,aAAqB,GACrB,UAA2C,UACxB;CACnB,IAAI,UAAU;CAEd,OAAO,UAAU,YAAY;EAC5B;EACA,IAAI;GAEH,IAAI,MADiB,GAAG,GAEvB,OAAO;EAET,SAAS,OAAO;GACf,QAAQ,MAAM,uBAAuB,KAAK;GAC1C,MAAM;EACP;EAGA,IAAI,UAAU,YAAY;GACzB,IAAI,mBAAmB;GAEvB,IAAI,YAAY,UACf,mBAAmB,WAAW;QACxB,IAAI,YAAY,eAAe;IACrC,mBAAmB,KAAK,IAAI,GAAG,UAAU,CAAC,IAAI;IAC9C,mBAAmB,KAAK,IAAI,kBAAkB,GAAK;GACpD;GAEA,MAAM,IAAI,SAAe,YAAY,WAAW,SAAS,gBAAgB,CAAC;EAC3E;CACD;CAEA,OAAO;AACR"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/scrub-secrets.ts

@@ -40,3 +40,2 @@ /**

}
//#endregion

@@ -46,2 +45,3 @@ exports.SECRET_KEYS = SECRET_KEYS;

exports.scrubSecretsInText = scrubSecretsInText;
//# sourceMappingURL=scrub-secrets.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"scrub-secrets.cjs","names":["SECRET_VALUE_PATTERNS: readonly RegExp[]"],"sources":["../src/scrub-secrets.ts"],"sourcesContent":["/**\n * Replace common credential patterns in free-form text with `[REDACTED]`.\n *\n * Used before persisting or transmitting user-supplied text (telemetry\n * excerpts, eval report HTML, free-form feedback) where keys/tokens\n * accidentally pasted into prompts or command lines could otherwise leak\n * downstream.\n *\n * Conservative by design: matches well-known prefixed tokens, explicit\n * `key=value` pairs, and quoted JSON/JS-object fields with sensitive\n * names. We don't attempt to redact arbitrary long opaque strings — false\n * positives on file paths, IDs, or base64 payloads would make the output\n * unreadable.\n */\nexport const SECRET_KEYS =\n\t'password|passwd|secret|credentials?|api[_-]?key|authorization|access[_-]?token|refresh[_-]?token|id[_-]?token|session[_-]?token|auth[_-]?token';\n\nexport const SECRET_VALUE_PATTERNS: readonly RegExp[] = [\n\t// PEM private-key blocks (RSA/EC/DSA/OpenSSH/PGP). Whole block, multiline.\n\t/-----BEGIN (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----[\\s\\S]*?-----END (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----/g,\n\t// JWTs: `eyJ<header>.eyJ<payload>.<signature>` (both leading segments are\n\t// base64url of a `{\"` object, which makes this highly distinctive).\n\t/\\beyJ[A-Za-z0-9_-]+\\.eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/g,\n\t// Authorization-header substrings: `Bearer <token>`, `Basic <token>`, `Token <token>`\n\t/\\b(?:Bearer|Basic|Token)\\s+[A-Za-z0-9._~+/=-]{12,}/gi,\n\t// OpenAI / Anthropic API keys\n\t/\\bsk-(?:ant-|proj-)?[A-Za-z0-9_-]{16,}/g,\n\t// Stripe secret/restricted/publishable keys (`sk_live_…`, `rk_test_…`, …)\n\t/\\b(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{16,}/g,\n\t// Google API keys\n\t/\\bAIza[0-9A-Za-z_-]{35}\\b/g,\n\t// Slack tokens (xoxb, xoxp, xoxa, xoxr, xoxs, xoxo)\n\t/\\bxox[abprso]-[A-Za-z0-9-]{10,}/g,\n\t// GitHub tokens (ghp, ghs, gho, ghr, ghu)\n\t/\\bgh[psoru]_[A-Za-z0-9]{20,}/g,\n\t// GitHub fine-grained personal access tokens\n\t/\\bgithub_pat_[A-Za-z0-9_]{22,}/g,\n\t// AWS access key id\n\t/\\bAKIA[0-9A-Z]{16}\\b/g,\n\t// Telegram bot token (`<bot id>:<35-char secret>`, also inside `/bot…/` URLs)\n\t/\\b(?:bot)?\\d{8,10}:[A-Za-z0-9_-]{35}\\b/g,\n\t// Credentials embedded in a URL: `scheme://user:password@` — redact the userinfo.\n\t/(?<=:\\/\\/)[^\\s:/@]+:[^\\s:/@]+(?=@)/g,\n\t// JSON-shaped `\"key\": \"value\"` — matches the quoted field as a whole.\n\t// Run before the loose pattern so nested objects like\n\t// `{\"credentials\": {\"apiKey\": \"...\"}}` don't have the outer key consume\n\t// the inner key on its way to a non-quoted (object) value. The value\n\t// body uses the unrolled JSON-string idiom `(?:[^\"\\\\\\r\\n]|\\\\.)*`: the\n\t// negated class excludes the backslash so a backslash can only be consumed\n\t// by the `\\\\.` escape branch. Keep the two alternatives disjoint (don't\n\t// fold `\\\\` back into the negated class) — that keeps every run of\n\t// backslashes to a single, unambiguous parse, so matching stays fast on any\n\t// input. An escaped quote inside the value (`\"abc\\\"def\"`) still doesn't end\n\t// the match early, via the escape branch. The negative lookahead skips\n\t// values that are already a `[redacted]` / `[REDACTED]` / typed\n\t// `[REDACTED:<type>:<index>]` placeholder so this stays idempotent when\n\t// chained behind upstream object-walking redaction (langsmith trace\n\t// payloads, mcp-browser markers).\n\tnew RegExp(\n\t\t`\"(?:${SECRET_KEYS})\"\\\\s*:\\\\s*\"(?!\\\\[(?:redacted|REDACTED)(?::[^\"\\\\]]*)?\\\\]\")(?:[^\"\\\\\\\\\\\\r\\\\n]|\\\\\\\\.)*\"`,\n\t\t'gi',\n\t),\n\t// JS-object-shaped `'key': 'value'`\n\tnew RegExp(\n\t\t`'(?:${SECRET_KEYS})'\\\\s*:\\\\s*'(?!\\\\[(?:redacted|REDACTED)(?::[^'\\\\]]*)?\\\\]')(?:[^'\\\\\\\\\\\\r\\\\n]|\\\\\\\\.)*'`,\n\t\t'gi',\n\t),\n\t// Generic `password=...` / `api_key=...` / `secret=...` style assignments.\n\t// The negative lookbehind skips a keyword sitting at the `<type>` position of\n\t// an upstream `[REDACTED:<type>:<index>]` marker (e.g. mcp-browser output), so\n\t// the `secret:1]` tail isn't re-matched into a nested `[REDACTED:[REDACTED]`.\n\t// Checking only the `[REDACTED:` prefix suffices: inside a marker a keyword can\n\t// only start a `\\b` match right after that prefix — every other keyword-shaped\n\t// substring is preceded by `_` (snake_case type slug) or a digit, so no word\n\t// boundary opens there. The value lookahead skips values that are already a\n\t// redaction placeholder (bracketed, typed, or URL-safe bare form) — the same\n\t// idempotency convention as the quoted forms.\n\tnew RegExp(\n\t\t`(?<!\\\\[(?:redacted|REDACTED):)\\\\b(?:${SECRET_KEYS})\\\\s*[:=]\\\\s*(?!\\\\[?(?:redacted|REDACTED)\\\\b)\\\\S+`,\n\t\t'gi',\n\t),\n];\n\nexport function scrubSecretsInText(input: string): string {\n\tlet out = input;\n\tfor (const pattern of SECRET_VALUE_PATTERNS) {\n\t\tout = out.replace(pattern, '[REDACTED]');\n\t}\n\treturn out;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAcA,MAAa,cACZ;AAED,MAAaA,wBAA2C;CAEvD;CAGA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAgBA,IAAI,OACH,OAAO,YAAY,uFACnB,KACA;CAED,IAAI,OACH,OAAO,YAAY,uFACnB,KACA;CAWD,IAAI,OACH,uCAAuC,YAAY,oDACnD,KACA;CACD;AAED,SAAgB,mBAAmB,OAAuB;CACzD,IAAI,MAAM;AACV,MAAK,MAAM,WAAW,sBACrB,OAAM,IAAI,QAAQ,SAAS,aAAa;AAEzC,QAAO"}
{"version":3,"file":"scrub-secrets.cjs","names":[],"sources":["../src/scrub-secrets.ts"],"sourcesContent":["/**\n * Replace common credential patterns in free-form text with `[REDACTED]`.\n *\n * Used before persisting or transmitting user-supplied text (telemetry\n * excerpts, eval report HTML, free-form feedback) where keys/tokens\n * accidentally pasted into prompts or command lines could otherwise leak\n * downstream.\n *\n * Conservative by design: matches well-known prefixed tokens, explicit\n * `key=value` pairs, and quoted JSON/JS-object fields with sensitive\n * names. We don't attempt to redact arbitrary long opaque strings — false\n * positives on file paths, IDs, or base64 payloads would make the output\n * unreadable.\n */\nexport const SECRET_KEYS =\n\t'password|passwd|secret|credentials?|api[_-]?key|authorization|access[_-]?token|refresh[_-]?token|id[_-]?token|session[_-]?token|auth[_-]?token';\n\nexport const SECRET_VALUE_PATTERNS: readonly RegExp[] = [\n\t// PEM private-key blocks (RSA/EC/DSA/OpenSSH/PGP). Whole block, multiline.\n\t/-----BEGIN (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----[\\s\\S]*?-----END (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----/g,\n\t// JWTs: `eyJ<header>.eyJ<payload>.<signature>` (both leading segments are\n\t// base64url of a `{\"` object, which makes this highly distinctive).\n\t/\\beyJ[A-Za-z0-9_-]+\\.eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/g,\n\t// Authorization-header substrings: `Bearer <token>`, `Basic <token>`, `Token <token>`\n\t/\\b(?:Bearer|Basic|Token)\\s+[A-Za-z0-9._~+/=-]{12,}/gi,\n\t// OpenAI / Anthropic API keys\n\t/\\bsk-(?:ant-|proj-)?[A-Za-z0-9_-]{16,}/g,\n\t// Stripe secret/restricted/publishable keys (`sk_live_…`, `rk_test_…`, …)\n\t/\\b(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{16,}/g,\n\t// Google API keys\n\t/\\bAIza[0-9A-Za-z_-]{35}\\b/g,\n\t// Slack tokens (xoxb, xoxp, xoxa, xoxr, xoxs, xoxo)\n\t/\\bxox[abprso]-[A-Za-z0-9-]{10,}/g,\n\t// GitHub tokens (ghp, ghs, gho, ghr, ghu)\n\t/\\bgh[psoru]_[A-Za-z0-9]{20,}/g,\n\t// GitHub fine-grained personal access tokens\n\t/\\bgithub_pat_[A-Za-z0-9_]{22,}/g,\n\t// AWS access key id\n\t/\\bAKIA[0-9A-Z]{16}\\b/g,\n\t// Telegram bot token (`<bot id>:<35-char secret>`, also inside `/bot…/` URLs)\n\t/\\b(?:bot)?\\d{8,10}:[A-Za-z0-9_-]{35}\\b/g,\n\t// Credentials embedded in a URL: `scheme://user:password@` — redact the userinfo.\n\t/(?<=:\\/\\/)[^\\s:/@]+:[^\\s:/@]+(?=@)/g,\n\t// JSON-shaped `\"key\": \"value\"` — matches the quoted field as a whole.\n\t// Run before the loose pattern so nested objects like\n\t// `{\"credentials\": {\"apiKey\": \"...\"}}` don't have the outer key consume\n\t// the inner key on its way to a non-quoted (object) value. The value\n\t// body uses the unrolled JSON-string idiom `(?:[^\"\\\\\\r\\n]|\\\\.)*`: the\n\t// negated class excludes the backslash so a backslash can only be consumed\n\t// by the `\\\\.` escape branch. Keep the two alternatives disjoint (don't\n\t// fold `\\\\` back into the negated class) — that keeps every run of\n\t// backslashes to a single, unambiguous parse, so matching stays fast on any\n\t// input. An escaped quote inside the value (`\"abc\\\"def\"`) still doesn't end\n\t// the match early, via the escape branch. The negative lookahead skips\n\t// values that are already a `[redacted]` / `[REDACTED]` / typed\n\t// `[REDACTED:<type>:<index>]` placeholder so this stays idempotent when\n\t// chained behind upstream object-walking redaction (langsmith trace\n\t// payloads, mcp-browser markers).\n\tnew RegExp(\n\t\t`\"(?:${SECRET_KEYS})\"\\\\s*:\\\\s*\"(?!\\\\[(?:redacted|REDACTED)(?::[^\"\\\\]]*)?\\\\]\")(?:[^\"\\\\\\\\\\\\r\\\\n]|\\\\\\\\.)*\"`,\n\t\t'gi',\n\t),\n\t// JS-object-shaped `'key': 'value'`\n\tnew RegExp(\n\t\t`'(?:${SECRET_KEYS})'\\\\s*:\\\\s*'(?!\\\\[(?:redacted|REDACTED)(?::[^'\\\\]]*)?\\\\]')(?:[^'\\\\\\\\\\\\r\\\\n]|\\\\\\\\.)*'`,\n\t\t'gi',\n\t),\n\t// Generic `password=...` / `api_key=...` / `secret=...` style assignments.\n\t// The negative lookbehind skips a keyword sitting at the `<type>` position of\n\t// an upstream `[REDACTED:<type>:<index>]` marker (e.g. mcp-browser output), so\n\t// the `secret:1]` tail isn't re-matched into a nested `[REDACTED:[REDACTED]`.\n\t// Checking only the `[REDACTED:` prefix suffices: inside a marker a keyword can\n\t// only start a `\\b` match right after that prefix — every other keyword-shaped\n\t// substring is preceded by `_` (snake_case type slug) or a digit, so no word\n\t// boundary opens there. The value lookahead skips values that are already a\n\t// redaction placeholder (bracketed, typed, or URL-safe bare form) — the same\n\t// idempotency convention as the quoted forms.\n\tnew RegExp(\n\t\t`(?<!\\\\[(?:redacted|REDACTED):)\\\\b(?:${SECRET_KEYS})\\\\s*[:=]\\\\s*(?!\\\\[?(?:redacted|REDACTED)\\\\b)\\\\S+`,\n\t\t'gi',\n\t),\n];\n\nexport function scrubSecretsInText(input: string): string {\n\tlet out = input;\n\tfor (const pattern of SECRET_VALUE_PATTERNS) {\n\t\tout = out.replace(pattern, '[REDACTED]');\n\t}\n\treturn out;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAcA,MAAa,cACZ;AAED,MAAa,wBAA2C;CAEvD;CAGA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAgBA,IAAI,OACH,OAAO,YAAY,uFACnB,IACD;CAEA,IAAI,OACH,OAAO,YAAY,uFACnB,IACD;CAWA,IAAI,OACH,uCAAuC,YAAY,oDACnD,IACD;AACD;AAEA,SAAgB,mBAAmB,OAAuB;CACzD,IAAI,MAAM;CACV,KAAK,MAAM,WAAW,uBACrB,MAAM,IAAI,QAAQ,SAAS,YAAY;CAExC,OAAO;AACR"}

@@ -39,5 +39,5 @@ //#region src/scrub-secrets.ts

}
//#endregion
export { SECRET_KEYS, SECRET_VALUE_PATTERNS, scrubSecretsInText };
//# sourceMappingURL=scrub-secrets.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"scrub-secrets.mjs","names":["SECRET_VALUE_PATTERNS: readonly RegExp[]"],"sources":["../src/scrub-secrets.ts"],"sourcesContent":["/**\n * Replace common credential patterns in free-form text with `[REDACTED]`.\n *\n * Used before persisting or transmitting user-supplied text (telemetry\n * excerpts, eval report HTML, free-form feedback) where keys/tokens\n * accidentally pasted into prompts or command lines could otherwise leak\n * downstream.\n *\n * Conservative by design: matches well-known prefixed tokens, explicit\n * `key=value` pairs, and quoted JSON/JS-object fields with sensitive\n * names. We don't attempt to redact arbitrary long opaque strings — false\n * positives on file paths, IDs, or base64 payloads would make the output\n * unreadable.\n */\nexport const SECRET_KEYS =\n\t'password|passwd|secret|credentials?|api[_-]?key|authorization|access[_-]?token|refresh[_-]?token|id[_-]?token|session[_-]?token|auth[_-]?token';\n\nexport const SECRET_VALUE_PATTERNS: readonly RegExp[] = [\n\t// PEM private-key blocks (RSA/EC/DSA/OpenSSH/PGP). Whole block, multiline.\n\t/-----BEGIN (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----[\\s\\S]*?-----END (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----/g,\n\t// JWTs: `eyJ<header>.eyJ<payload>.<signature>` (both leading segments are\n\t// base64url of a `{\"` object, which makes this highly distinctive).\n\t/\\beyJ[A-Za-z0-9_-]+\\.eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/g,\n\t// Authorization-header substrings: `Bearer <token>`, `Basic <token>`, `Token <token>`\n\t/\\b(?:Bearer|Basic|Token)\\s+[A-Za-z0-9._~+/=-]{12,}/gi,\n\t// OpenAI / Anthropic API keys\n\t/\\bsk-(?:ant-|proj-)?[A-Za-z0-9_-]{16,}/g,\n\t// Stripe secret/restricted/publishable keys (`sk_live_…`, `rk_test_…`, …)\n\t/\\b(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{16,}/g,\n\t// Google API keys\n\t/\\bAIza[0-9A-Za-z_-]{35}\\b/g,\n\t// Slack tokens (xoxb, xoxp, xoxa, xoxr, xoxs, xoxo)\n\t/\\bxox[abprso]-[A-Za-z0-9-]{10,}/g,\n\t// GitHub tokens (ghp, ghs, gho, ghr, ghu)\n\t/\\bgh[psoru]_[A-Za-z0-9]{20,}/g,\n\t// GitHub fine-grained personal access tokens\n\t/\\bgithub_pat_[A-Za-z0-9_]{22,}/g,\n\t// AWS access key id\n\t/\\bAKIA[0-9A-Z]{16}\\b/g,\n\t// Telegram bot token (`<bot id>:<35-char secret>`, also inside `/bot…/` URLs)\n\t/\\b(?:bot)?\\d{8,10}:[A-Za-z0-9_-]{35}\\b/g,\n\t// Credentials embedded in a URL: `scheme://user:password@` — redact the userinfo.\n\t/(?<=:\\/\\/)[^\\s:/@]+:[^\\s:/@]+(?=@)/g,\n\t// JSON-shaped `\"key\": \"value\"` — matches the quoted field as a whole.\n\t// Run before the loose pattern so nested objects like\n\t// `{\"credentials\": {\"apiKey\": \"...\"}}` don't have the outer key consume\n\t// the inner key on its way to a non-quoted (object) value. The value\n\t// body uses the unrolled JSON-string idiom `(?:[^\"\\\\\\r\\n]|\\\\.)*`: the\n\t// negated class excludes the backslash so a backslash can only be consumed\n\t// by the `\\\\.` escape branch. Keep the two alternatives disjoint (don't\n\t// fold `\\\\` back into the negated class) — that keeps every run of\n\t// backslashes to a single, unambiguous parse, so matching stays fast on any\n\t// input. An escaped quote inside the value (`\"abc\\\"def\"`) still doesn't end\n\t// the match early, via the escape branch. The negative lookahead skips\n\t// values that are already a `[redacted]` / `[REDACTED]` / typed\n\t// `[REDACTED:<type>:<index>]` placeholder so this stays idempotent when\n\t// chained behind upstream object-walking redaction (langsmith trace\n\t// payloads, mcp-browser markers).\n\tnew RegExp(\n\t\t`\"(?:${SECRET_KEYS})\"\\\\s*:\\\\s*\"(?!\\\\[(?:redacted|REDACTED)(?::[^\"\\\\]]*)?\\\\]\")(?:[^\"\\\\\\\\\\\\r\\\\n]|\\\\\\\\.)*\"`,\n\t\t'gi',\n\t),\n\t// JS-object-shaped `'key': 'value'`\n\tnew RegExp(\n\t\t`'(?:${SECRET_KEYS})'\\\\s*:\\\\s*'(?!\\\\[(?:redacted|REDACTED)(?::[^'\\\\]]*)?\\\\]')(?:[^'\\\\\\\\\\\\r\\\\n]|\\\\\\\\.)*'`,\n\t\t'gi',\n\t),\n\t// Generic `password=...` / `api_key=...` / `secret=...` style assignments.\n\t// The negative lookbehind skips a keyword sitting at the `<type>` position of\n\t// an upstream `[REDACTED:<type>:<index>]` marker (e.g. mcp-browser output), so\n\t// the `secret:1]` tail isn't re-matched into a nested `[REDACTED:[REDACTED]`.\n\t// Checking only the `[REDACTED:` prefix suffices: inside a marker a keyword can\n\t// only start a `\\b` match right after that prefix — every other keyword-shaped\n\t// substring is preceded by `_` (snake_case type slug) or a digit, so no word\n\t// boundary opens there. The value lookahead skips values that are already a\n\t// redaction placeholder (bracketed, typed, or URL-safe bare form) — the same\n\t// idempotency convention as the quoted forms.\n\tnew RegExp(\n\t\t`(?<!\\\\[(?:redacted|REDACTED):)\\\\b(?:${SECRET_KEYS})\\\\s*[:=]\\\\s*(?!\\\\[?(?:redacted|REDACTED)\\\\b)\\\\S+`,\n\t\t'gi',\n\t),\n];\n\nexport function scrubSecretsInText(input: string): string {\n\tlet out = input;\n\tfor (const pattern of SECRET_VALUE_PATTERNS) {\n\t\tout = out.replace(pattern, '[REDACTED]');\n\t}\n\treturn out;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAcA,MAAa,cACZ;AAED,MAAaA,wBAA2C;CAEvD;CAGA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAgBA,IAAI,OACH,OAAO,YAAY,uFACnB,KACA;CAED,IAAI,OACH,OAAO,YAAY,uFACnB,KACA;CAWD,IAAI,OACH,uCAAuC,YAAY,oDACnD,KACA;CACD;AAED,SAAgB,mBAAmB,OAAuB;CACzD,IAAI,MAAM;AACV,MAAK,MAAM,WAAW,sBACrB,OAAM,IAAI,QAAQ,SAAS,aAAa;AAEzC,QAAO"}
{"version":3,"file":"scrub-secrets.mjs","names":[],"sources":["../src/scrub-secrets.ts"],"sourcesContent":["/**\n * Replace common credential patterns in free-form text with `[REDACTED]`.\n *\n * Used before persisting or transmitting user-supplied text (telemetry\n * excerpts, eval report HTML, free-form feedback) where keys/tokens\n * accidentally pasted into prompts or command lines could otherwise leak\n * downstream.\n *\n * Conservative by design: matches well-known prefixed tokens, explicit\n * `key=value` pairs, and quoted JSON/JS-object fields with sensitive\n * names. We don't attempt to redact arbitrary long opaque strings — false\n * positives on file paths, IDs, or base64 payloads would make the output\n * unreadable.\n */\nexport const SECRET_KEYS =\n\t'password|passwd|secret|credentials?|api[_-]?key|authorization|access[_-]?token|refresh[_-]?token|id[_-]?token|session[_-]?token|auth[_-]?token';\n\nexport const SECRET_VALUE_PATTERNS: readonly RegExp[] = [\n\t// PEM private-key blocks (RSA/EC/DSA/OpenSSH/PGP). Whole block, multiline.\n\t/-----BEGIN (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----[\\s\\S]*?-----END (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----/g,\n\t// JWTs: `eyJ<header>.eyJ<payload>.<signature>` (both leading segments are\n\t// base64url of a `{\"` object, which makes this highly distinctive).\n\t/\\beyJ[A-Za-z0-9_-]+\\.eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/g,\n\t// Authorization-header substrings: `Bearer <token>`, `Basic <token>`, `Token <token>`\n\t/\\b(?:Bearer|Basic|Token)\\s+[A-Za-z0-9._~+/=-]{12,}/gi,\n\t// OpenAI / Anthropic API keys\n\t/\\bsk-(?:ant-|proj-)?[A-Za-z0-9_-]{16,}/g,\n\t// Stripe secret/restricted/publishable keys (`sk_live_…`, `rk_test_…`, …)\n\t/\\b(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{16,}/g,\n\t// Google API keys\n\t/\\bAIza[0-9A-Za-z_-]{35}\\b/g,\n\t// Slack tokens (xoxb, xoxp, xoxa, xoxr, xoxs, xoxo)\n\t/\\bxox[abprso]-[A-Za-z0-9-]{10,}/g,\n\t// GitHub tokens (ghp, ghs, gho, ghr, ghu)\n\t/\\bgh[psoru]_[A-Za-z0-9]{20,}/g,\n\t// GitHub fine-grained personal access tokens\n\t/\\bgithub_pat_[A-Za-z0-9_]{22,}/g,\n\t// AWS access key id\n\t/\\bAKIA[0-9A-Z]{16}\\b/g,\n\t// Telegram bot token (`<bot id>:<35-char secret>`, also inside `/bot…/` URLs)\n\t/\\b(?:bot)?\\d{8,10}:[A-Za-z0-9_-]{35}\\b/g,\n\t// Credentials embedded in a URL: `scheme://user:password@` — redact the userinfo.\n\t/(?<=:\\/\\/)[^\\s:/@]+:[^\\s:/@]+(?=@)/g,\n\t// JSON-shaped `\"key\": \"value\"` — matches the quoted field as a whole.\n\t// Run before the loose pattern so nested objects like\n\t// `{\"credentials\": {\"apiKey\": \"...\"}}` don't have the outer key consume\n\t// the inner key on its way to a non-quoted (object) value. The value\n\t// body uses the unrolled JSON-string idiom `(?:[^\"\\\\\\r\\n]|\\\\.)*`: the\n\t// negated class excludes the backslash so a backslash can only be consumed\n\t// by the `\\\\.` escape branch. Keep the two alternatives disjoint (don't\n\t// fold `\\\\` back into the negated class) — that keeps every run of\n\t// backslashes to a single, unambiguous parse, so matching stays fast on any\n\t// input. An escaped quote inside the value (`\"abc\\\"def\"`) still doesn't end\n\t// the match early, via the escape branch. The negative lookahead skips\n\t// values that are already a `[redacted]` / `[REDACTED]` / typed\n\t// `[REDACTED:<type>:<index>]` placeholder so this stays idempotent when\n\t// chained behind upstream object-walking redaction (langsmith trace\n\t// payloads, mcp-browser markers).\n\tnew RegExp(\n\t\t`\"(?:${SECRET_KEYS})\"\\\\s*:\\\\s*\"(?!\\\\[(?:redacted|REDACTED)(?::[^\"\\\\]]*)?\\\\]\")(?:[^\"\\\\\\\\\\\\r\\\\n]|\\\\\\\\.)*\"`,\n\t\t'gi',\n\t),\n\t// JS-object-shaped `'key': 'value'`\n\tnew RegExp(\n\t\t`'(?:${SECRET_KEYS})'\\\\s*:\\\\s*'(?!\\\\[(?:redacted|REDACTED)(?::[^'\\\\]]*)?\\\\]')(?:[^'\\\\\\\\\\\\r\\\\n]|\\\\\\\\.)*'`,\n\t\t'gi',\n\t),\n\t// Generic `password=...` / `api_key=...` / `secret=...` style assignments.\n\t// The negative lookbehind skips a keyword sitting at the `<type>` position of\n\t// an upstream `[REDACTED:<type>:<index>]` marker (e.g. mcp-browser output), so\n\t// the `secret:1]` tail isn't re-matched into a nested `[REDACTED:[REDACTED]`.\n\t// Checking only the `[REDACTED:` prefix suffices: inside a marker a keyword can\n\t// only start a `\\b` match right after that prefix — every other keyword-shaped\n\t// substring is preceded by `_` (snake_case type slug) or a digit, so no word\n\t// boundary opens there. The value lookahead skips values that are already a\n\t// redaction placeholder (bracketed, typed, or URL-safe bare form) — the same\n\t// idempotency convention as the quoted forms.\n\tnew RegExp(\n\t\t`(?<!\\\\[(?:redacted|REDACTED):)\\\\b(?:${SECRET_KEYS})\\\\s*[:=]\\\\s*(?!\\\\[?(?:redacted|REDACTED)\\\\b)\\\\S+`,\n\t\t'gi',\n\t),\n];\n\nexport function scrubSecretsInText(input: string): string {\n\tlet out = input;\n\tfor (const pattern of SECRET_VALUE_PATTERNS) {\n\t\tout = out.replace(pattern, '[REDACTED]');\n\t}\n\treturn out;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAcA,MAAa,cACZ;AAED,MAAa,wBAA2C;CAEvD;CAGA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAgBA,IAAI,OACH,OAAO,YAAY,uFACnB,IACD;CAEA,IAAI,OACH,OAAO,YAAY,uFACnB,IACD;CAWA,IAAI,OACH,uCAAuC,YAAY,oDACnD,IACD;AACD;AAEA,SAAgB,mBAAmB,OAAuB;CACzD,IAAI,MAAM;CACV,KAAK,MAAM,WAAW,uBACrB,MAAM,IAAI,QAAQ,SAAS,YAAY;CAExC,OAAO;AACR"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/search/re-rank-search-results.ts

@@ -17,5 +17,5 @@ function reRankSearchResults(searchResults, additionalFactors) {

}
//#endregion
exports.reRankSearchResults = reRankSearchResults;
//# sourceMappingURL=re-rank-search-results.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"re-rank-search-results.cjs","names":[],"sources":["../../src/search/re-rank-search-results.ts"],"sourcesContent":["export function reRankSearchResults<T extends { key: string }>(\n\tsearchResults: Array<{ score: number; item: T }>,\n\tadditionalFactors: Record<string, Record<string, number>>,\n): Array<{ score: number; item: T }> {\n\treturn searchResults\n\t\t.map(({ score, item }) => {\n\t\t\t// For each additional factor, we check if it exists for the item and type,\n\t\t\t// and if so, we add the score to the item's score.\n\t\t\tconst additionalScore = Object.entries(additionalFactors).reduce((acc, [_, factorScores]) => {\n\t\t\t\tconst factorScore = factorScores[item.key];\n\t\t\t\tif (factorScore) {\n\t\t\t\t\treturn acc + factorScore;\n\t\t\t\t}\n\n\t\t\t\treturn acc;\n\t\t\t}, 0);\n\n\t\t\treturn {\n\t\t\t\tscore: score + additionalScore,\n\t\t\t\titem,\n\t\t\t};\n\t\t})\n\t\t.sort((a, b) => {\n\t\t\treturn b.score - a.score;\n\t\t});\n}\n"],"mappings":";;AAAA,SAAgB,oBACf,eACA,mBACoC;AACpC,QAAO,cACL,KAAK,EAAE,OAAO,WAAW;AAYzB,SAAO;GACN,OAAO,QAVgB,OAAO,QAAQ,kBAAkB,CAAC,QAAQ,KAAK,CAAC,GAAG,kBAAkB;IAC5F,MAAM,cAAc,aAAa,KAAK;AACtC,QAAI,YACH,QAAO,MAAM;AAGd,WAAO;MACL,EAAE;GAIJ;GACA;GACA,CACD,MAAM,GAAG,MAAM;AACf,SAAO,EAAE,QAAQ,EAAE;GAClB"}
{"version":3,"file":"re-rank-search-results.cjs","names":[],"sources":["../../src/search/re-rank-search-results.ts"],"sourcesContent":["export function reRankSearchResults<T extends { key: string }>(\n\tsearchResults: Array<{ score: number; item: T }>,\n\tadditionalFactors: Record<string, Record<string, number>>,\n): Array<{ score: number; item: T }> {\n\treturn searchResults\n\t\t.map(({ score, item }) => {\n\t\t\t// For each additional factor, we check if it exists for the item and type,\n\t\t\t// and if so, we add the score to the item's score.\n\t\t\tconst additionalScore = Object.entries(additionalFactors).reduce((acc, [_, factorScores]) => {\n\t\t\t\tconst factorScore = factorScores[item.key];\n\t\t\t\tif (factorScore) {\n\t\t\t\t\treturn acc + factorScore;\n\t\t\t\t}\n\n\t\t\t\treturn acc;\n\t\t\t}, 0);\n\n\t\t\treturn {\n\t\t\t\tscore: score + additionalScore,\n\t\t\t\titem,\n\t\t\t};\n\t\t})\n\t\t.sort((a, b) => {\n\t\t\treturn b.score - a.score;\n\t\t});\n}\n"],"mappings":";;AAAA,SAAgB,oBACf,eACA,mBACoC;CACpC,OAAO,cACL,KAAK,EAAE,OAAO,WAAW;EAYzB,OAAO;GACN,OAAO,QAVgB,OAAO,QAAQ,iBAAiB,CAAC,CAAC,QAAQ,KAAK,CAAC,GAAG,kBAAkB;IAC5F,MAAM,cAAc,aAAa,KAAK;IACtC,IAAI,aACH,OAAO,MAAM;IAGd,OAAO;GACR,GAAG,CAG2B;GAC7B;EACD;CACD,CAAC,CAAC,CACD,MAAM,GAAG,MAAM;EACf,OAAO,EAAE,QAAQ,EAAE;CACpB,CAAC;AACH"}

@@ -16,5 +16,5 @@ //#region src/search/re-rank-search-results.ts

}
//#endregion
export { reRankSearchResults };
//# sourceMappingURL=re-rank-search-results.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"re-rank-search-results.mjs","names":[],"sources":["../../src/search/re-rank-search-results.ts"],"sourcesContent":["export function reRankSearchResults<T extends { key: string }>(\n\tsearchResults: Array<{ score: number; item: T }>,\n\tadditionalFactors: Record<string, Record<string, number>>,\n): Array<{ score: number; item: T }> {\n\treturn searchResults\n\t\t.map(({ score, item }) => {\n\t\t\t// For each additional factor, we check if it exists for the item and type,\n\t\t\t// and if so, we add the score to the item's score.\n\t\t\tconst additionalScore = Object.entries(additionalFactors).reduce((acc, [_, factorScores]) => {\n\t\t\t\tconst factorScore = factorScores[item.key];\n\t\t\t\tif (factorScore) {\n\t\t\t\t\treturn acc + factorScore;\n\t\t\t\t}\n\n\t\t\t\treturn acc;\n\t\t\t}, 0);\n\n\t\t\treturn {\n\t\t\t\tscore: score + additionalScore,\n\t\t\t\titem,\n\t\t\t};\n\t\t})\n\t\t.sort((a, b) => {\n\t\t\treturn b.score - a.score;\n\t\t});\n}\n"],"mappings":";AAAA,SAAgB,oBACf,eACA,mBACoC;AACpC,QAAO,cACL,KAAK,EAAE,OAAO,WAAW;AAYzB,SAAO;GACN,OAAO,QAVgB,OAAO,QAAQ,kBAAkB,CAAC,QAAQ,KAAK,CAAC,GAAG,kBAAkB;IAC5F,MAAM,cAAc,aAAa,KAAK;AACtC,QAAI,YACH,QAAO,MAAM;AAGd,WAAO;MACL,EAAE;GAIJ;GACA;GACA,CACD,MAAM,GAAG,MAAM;AACf,SAAO,EAAE,QAAQ,EAAE;GAClB"}
{"version":3,"file":"re-rank-search-results.mjs","names":[],"sources":["../../src/search/re-rank-search-results.ts"],"sourcesContent":["export function reRankSearchResults<T extends { key: string }>(\n\tsearchResults: Array<{ score: number; item: T }>,\n\tadditionalFactors: Record<string, Record<string, number>>,\n): Array<{ score: number; item: T }> {\n\treturn searchResults\n\t\t.map(({ score, item }) => {\n\t\t\t// For each additional factor, we check if it exists for the item and type,\n\t\t\t// and if so, we add the score to the item's score.\n\t\t\tconst additionalScore = Object.entries(additionalFactors).reduce((acc, [_, factorScores]) => {\n\t\t\t\tconst factorScore = factorScores[item.key];\n\t\t\t\tif (factorScore) {\n\t\t\t\t\treturn acc + factorScore;\n\t\t\t\t}\n\n\t\t\t\treturn acc;\n\t\t\t}, 0);\n\n\t\t\treturn {\n\t\t\t\tscore: score + additionalScore,\n\t\t\t\titem,\n\t\t\t};\n\t\t})\n\t\t.sort((a, b) => {\n\t\t\treturn b.score - a.score;\n\t\t});\n}\n"],"mappings":";AAAA,SAAgB,oBACf,eACA,mBACoC;CACpC,OAAO,cACL,KAAK,EAAE,OAAO,WAAW;EAYzB,OAAO;GACN,OAAO,QAVgB,OAAO,QAAQ,iBAAiB,CAAC,CAAC,QAAQ,KAAK,CAAC,GAAG,kBAAkB;IAC5F,MAAM,cAAc,aAAa,KAAK;IACtC,IAAI,aACH,OAAO,MAAM;IAGd,OAAO;GACR,GAAG,CAG2B;GAC7B;EACD;CACD,CAAC,CAAC,CACD,MAAM,GAAG,MAAM;EACf,OAAO,EAAE,QAAQ,EAAE;CACpB,CAAC;AACH"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/search/sublime-search.ts

@@ -179,6 +179,6 @@ const SEQUENTIAL_BONUS = 60;

}
//#endregion
exports.DEFAULT_KEYS = DEFAULT_KEYS;
exports.sublimeSearch = sublimeSearch;
//# sourceMappingURL=sublime-search.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"sublime-search.cjs","names":["bestRecursiveMatches: number[]","recursiveMatches: number[]","results: Array<{ score: number; item: T }>","itemMatchScore: number | undefined","result: { score: number; item: T }"],"sources":["../../src/search/sublime-search.ts"],"sourcesContent":["/*\n * Constants and utility functions used for searching for node types in node creator component\n * based on https://github.com/forrestthewoods/lib_fts/blob/master/code/fts_fuzzy_match.js\n */\n\nconst SEQUENTIAL_BONUS = 60; // bonus for adjacent matches\nconst SEPARATOR_BONUS = 38; // bonus if match occurs after a separator\nconst CAMEL_BONUS = 30; // bonus if match is uppercase and prev is lower\nconst FIRST_LETTER_BONUS = 15; // bonus if the first letter is matched\n\nconst LEADING_LETTER_PENALTY = -20; // penalty applied for every letter in str before the first match\nconst MAX_LEADING_LETTER_PENALTY = -200; // maximum penalty for leading letters\nconst UNMATCHED_LETTER_PENALTY = -2.5;\n\nexport const DEFAULT_KEYS = [\n\t{ key: 'properties.displayName', weight: 1.3 },\n\t{ key: 'properties.codex.alias', weight: 1 },\n];\n\n/**\n * Returns true if each character in pattern is found sequentially within target\n * @param {*} pattern string\n * @param {*} target string\n */\nfunction fuzzyMatchSimple(pattern: string, target: string): boolean {\n\tlet patternIdx = 0;\n\tlet strIdx = 0;\n\n\twhile (patternIdx < pattern.length && strIdx < target.length) {\n\t\tconst patternChar = pattern.charAt(patternIdx).toLowerCase();\n\t\tconst targetChar = target.charAt(strIdx).toLowerCase();\n\t\tif (patternChar === targetChar) {\n\t\t\tpatternIdx++;\n\t\t}\n\t\t++strIdx;\n\t}\n\n\treturn pattern.length !== 0 && target.length !== 0 && patternIdx === pattern.length;\n}\n\nfunction fuzzyMatchRecursive(\n\tpattern: string,\n\ttarget: string,\n\tpatternCurIndex: number,\n\ttargetCurrIndex: number,\n\ttargetMatches: null | number[],\n\tmatches: number[],\n\tmaxMatches: number,\n\tnextMatch: number,\n\trecursionCount: number,\n\trecursionLimit: number,\n): { matched: boolean; outScore: number } {\n\tlet outScore = 0;\n\n\t// Return if recursion limit is reached.\n\tif (++recursionCount >= recursionLimit) {\n\t\treturn { matched: false, outScore };\n\t}\n\n\t// Return if we reached ends of strings.\n\tif (patternCurIndex === pattern.length || targetCurrIndex === target.length) {\n\t\treturn { matched: false, outScore };\n\t}\n\n\t// Recursion params\n\tlet recursiveMatch = false;\n\tlet bestRecursiveMatches: number[] = [];\n\tlet bestRecursiveScore = 0;\n\n\t// Loop through pattern and str looking for a match.\n\tlet firstMatch = true;\n\twhile (patternCurIndex < pattern.length && targetCurrIndex < target.length) {\n\t\t// Match found.\n\t\tif (pattern[patternCurIndex].toLowerCase() === target[targetCurrIndex].toLowerCase()) {\n\t\t\tif (nextMatch >= maxMatches) {\n\t\t\t\treturn { matched: false, outScore };\n\t\t\t}\n\n\t\t\tif (firstMatch && targetMatches) {\n\t\t\t\tmatches = [...targetMatches];\n\t\t\t\tfirstMatch = false;\n\t\t\t}\n\n\t\t\tconst recursiveMatches: number[] = [];\n\t\t\tconst recursiveResult = fuzzyMatchRecursive(\n\t\t\t\tpattern,\n\t\t\t\ttarget,\n\t\t\t\tpatternCurIndex,\n\t\t\t\ttargetCurrIndex + 1,\n\t\t\t\tmatches,\n\t\t\t\trecursiveMatches,\n\t\t\t\tmaxMatches,\n\t\t\t\tnextMatch,\n\t\t\t\trecursionCount,\n\t\t\t\trecursionLimit,\n\t\t\t);\n\n\t\t\tconst recursiveScore = recursiveResult.outScore;\n\t\t\tif (recursiveResult.matched) {\n\t\t\t\t// Pick best recursive score.\n\t\t\t\tif (!recursiveMatch || recursiveScore > bestRecursiveScore) {\n\t\t\t\t\tbestRecursiveMatches = [...recursiveMatches];\n\t\t\t\t\tbestRecursiveScore = recursiveScore;\n\t\t\t\t}\n\t\t\t\trecursiveMatch = true;\n\t\t\t}\n\n\t\t\tmatches[nextMatch++] = targetCurrIndex;\n\t\t\t++patternCurIndex;\n\t\t}\n\t\t++targetCurrIndex;\n\t}\n\n\tconst matched = patternCurIndex === pattern.length;\n\n\tif (matched) {\n\t\toutScore = 100;\n\n\t\t// Apply leading letter penalty (if not n8n-prefixed)\n\t\tif (!target.toLowerCase().startsWith('n8n')) {\n\t\t\tlet penalty = LEADING_LETTER_PENALTY * matches[0];\n\t\t\tpenalty = penalty < MAX_LEADING_LETTER_PENALTY ? MAX_LEADING_LETTER_PENALTY : penalty;\n\t\t\toutScore += penalty;\n\t\t}\n\n\t\t//Apply unmatched penalty\n\t\tconst unmatched = target.length - nextMatch;\n\t\toutScore += UNMATCHED_LETTER_PENALTY * unmatched;\n\n\t\t// Apply ordering bonuses\n\t\tfor (let i = 0; i < nextMatch; i++) {\n\t\t\tconst currIdx = matches[i];\n\n\t\t\tif (i > 0) {\n\t\t\t\tconst prevIdx = matches[i - 1];\n\t\t\t\tif (currIdx === prevIdx + 1) {\n\t\t\t\t\toutScore += SEQUENTIAL_BONUS;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check for bonuses based on neighbor character value.\n\t\t\tif (currIdx > 0) {\n\t\t\t\t// Camel case\n\t\t\t\tconst neighbor = target[currIdx - 1];\n\t\t\t\tconst curr = target[currIdx];\n\t\t\t\tif (neighbor !== neighbor.toUpperCase() && curr !== curr.toLowerCase()) {\n\t\t\t\t\toutScore += CAMEL_BONUS;\n\t\t\t\t}\n\t\t\t\tconst isNeighbourSeparator = neighbor === '_' || neighbor === ' ';\n\t\t\t\tif (isNeighbourSeparator) {\n\t\t\t\t\toutScore += SEPARATOR_BONUS;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// First letter\n\t\t\t\toutScore += FIRST_LETTER_BONUS;\n\t\t\t}\n\t\t}\n\n\t\t// Return best result\n\t\tif (recursiveMatch && (!matched || bestRecursiveScore > outScore)) {\n\t\t\t// Recursive score is better than \"this\"\n\t\t\tmatches = [...bestRecursiveMatches];\n\t\t\toutScore = bestRecursiveScore;\n\t\t\treturn { matched: true, outScore };\n\t\t} else if (matched) {\n\t\t\t// \"this\" score is better than recursive\n\t\t\treturn { matched: true, outScore };\n\t\t} else {\n\t\t\treturn { matched: false, outScore };\n\t\t}\n\t}\n\treturn { matched: false, outScore };\n}\n\n/**\n * Does a fuzzy search to find pattern inside a string.\n * @param {*} pattern string pattern to search for\n * @param {*} target string string which is being searched\n * @returns [boolean, number] a boolean which tells if pattern was\n * found or not and a search score\n */\nfunction fuzzyMatch(pattern: string, target: string): { matched: boolean; outScore: number } {\n\tconst recursionCount = 0;\n\tconst recursionLimit = 5;\n\tconst matches: number[] = [];\n\tconst maxMatches = 256;\n\n\treturn fuzzyMatchRecursive(\n\t\tpattern,\n\t\ttarget,\n\t\t0 /* patternCurIndex */,\n\t\t0 /* strCurrIndex */,\n\t\tnull /* srcMatces */,\n\t\tmatches,\n\t\tmaxMatches,\n\t\t0 /* nextMatch */,\n\t\trecursionCount,\n\t\trecursionLimit,\n\t);\n}\n\n// prop = 'key'\n// prop = 'key1.key2'\n// prop = ['key1', 'key2']\nfunction getValue<T extends object>(obj: T, prop: string): unknown {\n\tif (obj.hasOwnProperty(prop)) {\n\t\treturn obj[prop as keyof T];\n\t}\n\n\tconst segments = prop.split('.');\n\n\tlet result = obj;\n\tlet i = 0;\n\twhile (result && i < segments.length) {\n\t\tconst key = segments[i] as keyof T;\n\t\tresult = result[key] as T;\n\t\ti++;\n\t}\n\treturn result;\n}\n\nfunction scoreSearchValue(filter: string, value: string, weight: number): number | undefined {\n\tif (!fuzzyMatchSimple(filter, value)) return undefined;\n\n\tconst match = fuzzyMatch(filter, value);\n\tif (!match.matched) return undefined;\n\n\treturn match.outScore * weight;\n}\n\nexport function sublimeSearch<T extends object>(\n\tfilter: string,\n\tdata: readonly T[],\n\tkeys: Array<{ key: string; weight: number }> = DEFAULT_KEYS,\n\tlimit?: number,\n): Array<{ score: number; item: T }> {\n\tconst results: Array<{ score: number; item: T }> = [];\n\n\tfor (const item of data) {\n\t\tlet itemMatchScore: number | undefined;\n\n\t\tfor (const { key, weight } of keys) {\n\t\t\tconst value = getValue(item, key);\n\t\t\tif (Array.isArray(value)) {\n\t\t\t\tfor (const entry of value) {\n\t\t\t\t\tif (typeof entry !== 'string') continue;\n\n\t\t\t\t\tconst score = scoreSearchValue(filter, entry, weight);\n\t\t\t\t\tif (score !== undefined && (itemMatchScore === undefined || score > itemMatchScore)) {\n\t\t\t\t\t\titemMatchScore = score;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (typeof value === 'string') {\n\t\t\t\tconst score = scoreSearchValue(filter, value, weight);\n\t\t\t\tif (score !== undefined && (itemMatchScore === undefined || score > itemMatchScore)) {\n\t\t\t\t\titemMatchScore = score;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (itemMatchScore !== undefined) {\n\t\t\tconst result: { score: number; item: T } = {\n\t\t\t\tscore: itemMatchScore,\n\t\t\t\titem,\n\t\t\t};\n\n\t\t\tif (limit === undefined || results.length < limit) {\n\t\t\t\tresults.push(result);\n\t\t\t} else {\n\t\t\t\tlet lowestIndex = 0;\n\t\t\t\tlet lowestScore = results[0].score;\n\t\t\t\tfor (let i = 1; i < results.length; i++) {\n\t\t\t\t\tif (results[i].score < lowestScore) {\n\t\t\t\t\t\tlowestIndex = i;\n\t\t\t\t\t\tlowestScore = results[i].score;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (result.score > lowestScore) {\n\t\t\t\t\tresults[lowestIndex] = result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tresults.sort((a, b) => {\n\t\treturn b.score - a.score;\n\t});\n\n\treturn results;\n}\n"],"mappings":"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"}
{"version":3,"file":"sublime-search.cjs","names":[],"sources":["../../src/search/sublime-search.ts"],"sourcesContent":["/*\n * Constants and utility functions used for searching for node types in node creator component\n * based on https://github.com/forrestthewoods/lib_fts/blob/master/code/fts_fuzzy_match.js\n */\n\nconst SEQUENTIAL_BONUS = 60; // bonus for adjacent matches\nconst SEPARATOR_BONUS = 38; // bonus if match occurs after a separator\nconst CAMEL_BONUS = 30; // bonus if match is uppercase and prev is lower\nconst FIRST_LETTER_BONUS = 15; // bonus if the first letter is matched\n\nconst LEADING_LETTER_PENALTY = -20; // penalty applied for every letter in str before the first match\nconst MAX_LEADING_LETTER_PENALTY = -200; // maximum penalty for leading letters\nconst UNMATCHED_LETTER_PENALTY = -2.5;\n\nexport const DEFAULT_KEYS = [\n\t{ key: 'properties.displayName', weight: 1.3 },\n\t{ key: 'properties.codex.alias', weight: 1 },\n];\n\n/**\n * Returns true if each character in pattern is found sequentially within target\n * @param {*} pattern string\n * @param {*} target string\n */\nfunction fuzzyMatchSimple(pattern: string, target: string): boolean {\n\tlet patternIdx = 0;\n\tlet strIdx = 0;\n\n\twhile (patternIdx < pattern.length && strIdx < target.length) {\n\t\tconst patternChar = pattern.charAt(patternIdx).toLowerCase();\n\t\tconst targetChar = target.charAt(strIdx).toLowerCase();\n\t\tif (patternChar === targetChar) {\n\t\t\tpatternIdx++;\n\t\t}\n\t\t++strIdx;\n\t}\n\n\treturn pattern.length !== 0 && target.length !== 0 && patternIdx === pattern.length;\n}\n\nfunction fuzzyMatchRecursive(\n\tpattern: string,\n\ttarget: string,\n\tpatternCurIndex: number,\n\ttargetCurrIndex: number,\n\ttargetMatches: null | number[],\n\tmatches: number[],\n\tmaxMatches: number,\n\tnextMatch: number,\n\trecursionCount: number,\n\trecursionLimit: number,\n): { matched: boolean; outScore: number } {\n\tlet outScore = 0;\n\n\t// Return if recursion limit is reached.\n\tif (++recursionCount >= recursionLimit) {\n\t\treturn { matched: false, outScore };\n\t}\n\n\t// Return if we reached ends of strings.\n\tif (patternCurIndex === pattern.length || targetCurrIndex === target.length) {\n\t\treturn { matched: false, outScore };\n\t}\n\n\t// Recursion params\n\tlet recursiveMatch = false;\n\tlet bestRecursiveMatches: number[] = [];\n\tlet bestRecursiveScore = 0;\n\n\t// Loop through pattern and str looking for a match.\n\tlet firstMatch = true;\n\twhile (patternCurIndex < pattern.length && targetCurrIndex < target.length) {\n\t\t// Match found.\n\t\tif (pattern[patternCurIndex].toLowerCase() === target[targetCurrIndex].toLowerCase()) {\n\t\t\tif (nextMatch >= maxMatches) {\n\t\t\t\treturn { matched: false, outScore };\n\t\t\t}\n\n\t\t\tif (firstMatch && targetMatches) {\n\t\t\t\tmatches = [...targetMatches];\n\t\t\t\tfirstMatch = false;\n\t\t\t}\n\n\t\t\tconst recursiveMatches: number[] = [];\n\t\t\tconst recursiveResult = fuzzyMatchRecursive(\n\t\t\t\tpattern,\n\t\t\t\ttarget,\n\t\t\t\tpatternCurIndex,\n\t\t\t\ttargetCurrIndex + 1,\n\t\t\t\tmatches,\n\t\t\t\trecursiveMatches,\n\t\t\t\tmaxMatches,\n\t\t\t\tnextMatch,\n\t\t\t\trecursionCount,\n\t\t\t\trecursionLimit,\n\t\t\t);\n\n\t\t\tconst recursiveScore = recursiveResult.outScore;\n\t\t\tif (recursiveResult.matched) {\n\t\t\t\t// Pick best recursive score.\n\t\t\t\tif (!recursiveMatch || recursiveScore > bestRecursiveScore) {\n\t\t\t\t\tbestRecursiveMatches = [...recursiveMatches];\n\t\t\t\t\tbestRecursiveScore = recursiveScore;\n\t\t\t\t}\n\t\t\t\trecursiveMatch = true;\n\t\t\t}\n\n\t\t\tmatches[nextMatch++] = targetCurrIndex;\n\t\t\t++patternCurIndex;\n\t\t}\n\t\t++targetCurrIndex;\n\t}\n\n\tconst matched = patternCurIndex === pattern.length;\n\n\tif (matched) {\n\t\toutScore = 100;\n\n\t\t// Apply leading letter penalty (if not n8n-prefixed)\n\t\tif (!target.toLowerCase().startsWith('n8n')) {\n\t\t\tlet penalty = LEADING_LETTER_PENALTY * matches[0];\n\t\t\tpenalty = penalty < MAX_LEADING_LETTER_PENALTY ? MAX_LEADING_LETTER_PENALTY : penalty;\n\t\t\toutScore += penalty;\n\t\t}\n\n\t\t//Apply unmatched penalty\n\t\tconst unmatched = target.length - nextMatch;\n\t\toutScore += UNMATCHED_LETTER_PENALTY * unmatched;\n\n\t\t// Apply ordering bonuses\n\t\tfor (let i = 0; i < nextMatch; i++) {\n\t\t\tconst currIdx = matches[i];\n\n\t\t\tif (i > 0) {\n\t\t\t\tconst prevIdx = matches[i - 1];\n\t\t\t\tif (currIdx === prevIdx + 1) {\n\t\t\t\t\toutScore += SEQUENTIAL_BONUS;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check for bonuses based on neighbor character value.\n\t\t\tif (currIdx > 0) {\n\t\t\t\t// Camel case\n\t\t\t\tconst neighbor = target[currIdx - 1];\n\t\t\t\tconst curr = target[currIdx];\n\t\t\t\tif (neighbor !== neighbor.toUpperCase() && curr !== curr.toLowerCase()) {\n\t\t\t\t\toutScore += CAMEL_BONUS;\n\t\t\t\t}\n\t\t\t\tconst isNeighbourSeparator = neighbor === '_' || neighbor === ' ';\n\t\t\t\tif (isNeighbourSeparator) {\n\t\t\t\t\toutScore += SEPARATOR_BONUS;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// First letter\n\t\t\t\toutScore += FIRST_LETTER_BONUS;\n\t\t\t}\n\t\t}\n\n\t\t// Return best result\n\t\tif (recursiveMatch && (!matched || bestRecursiveScore > outScore)) {\n\t\t\t// Recursive score is better than \"this\"\n\t\t\tmatches = [...bestRecursiveMatches];\n\t\t\toutScore = bestRecursiveScore;\n\t\t\treturn { matched: true, outScore };\n\t\t} else if (matched) {\n\t\t\t// \"this\" score is better than recursive\n\t\t\treturn { matched: true, outScore };\n\t\t} else {\n\t\t\treturn { matched: false, outScore };\n\t\t}\n\t}\n\treturn { matched: false, outScore };\n}\n\n/**\n * Does a fuzzy search to find pattern inside a string.\n * @param {*} pattern string pattern to search for\n * @param {*} target string string which is being searched\n * @returns [boolean, number] a boolean which tells if pattern was\n * found or not and a search score\n */\nfunction fuzzyMatch(pattern: string, target: string): { matched: boolean; outScore: number } {\n\tconst recursionCount = 0;\n\tconst recursionLimit = 5;\n\tconst matches: number[] = [];\n\tconst maxMatches = 256;\n\n\treturn fuzzyMatchRecursive(\n\t\tpattern,\n\t\ttarget,\n\t\t0 /* patternCurIndex */,\n\t\t0 /* strCurrIndex */,\n\t\tnull /* srcMatces */,\n\t\tmatches,\n\t\tmaxMatches,\n\t\t0 /* nextMatch */,\n\t\trecursionCount,\n\t\trecursionLimit,\n\t);\n}\n\n// prop = 'key'\n// prop = 'key1.key2'\n// prop = ['key1', 'key2']\nfunction getValue<T extends object>(obj: T, prop: string): unknown {\n\tif (obj.hasOwnProperty(prop)) {\n\t\treturn obj[prop as keyof T];\n\t}\n\n\tconst segments = prop.split('.');\n\n\tlet result = obj;\n\tlet i = 0;\n\twhile (result && i < segments.length) {\n\t\tconst key = segments[i] as keyof T;\n\t\tresult = result[key] as T;\n\t\ti++;\n\t}\n\treturn result;\n}\n\nfunction scoreSearchValue(filter: string, value: string, weight: number): number | undefined {\n\tif (!fuzzyMatchSimple(filter, value)) return undefined;\n\n\tconst match = fuzzyMatch(filter, value);\n\tif (!match.matched) return undefined;\n\n\treturn match.outScore * weight;\n}\n\nexport function sublimeSearch<T extends object>(\n\tfilter: string,\n\tdata: readonly T[],\n\tkeys: Array<{ key: string; weight: number }> = DEFAULT_KEYS,\n\tlimit?: number,\n): Array<{ score: number; item: T }> {\n\tconst results: Array<{ score: number; item: T }> = [];\n\n\tfor (const item of data) {\n\t\tlet itemMatchScore: number | undefined;\n\n\t\tfor (const { key, weight } of keys) {\n\t\t\tconst value = getValue(item, key);\n\t\t\tif (Array.isArray(value)) {\n\t\t\t\tfor (const entry of value) {\n\t\t\t\t\tif (typeof entry !== 'string') continue;\n\n\t\t\t\t\tconst score = scoreSearchValue(filter, entry, weight);\n\t\t\t\t\tif (score !== undefined && (itemMatchScore === undefined || score > itemMatchScore)) {\n\t\t\t\t\t\titemMatchScore = score;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (typeof value === 'string') {\n\t\t\t\tconst score = scoreSearchValue(filter, value, weight);\n\t\t\t\tif (score !== undefined && (itemMatchScore === undefined || score > itemMatchScore)) {\n\t\t\t\t\titemMatchScore = score;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (itemMatchScore !== undefined) {\n\t\t\tconst result: { score: number; item: T } = {\n\t\t\t\tscore: itemMatchScore,\n\t\t\t\titem,\n\t\t\t};\n\n\t\t\tif (limit === undefined || results.length < limit) {\n\t\t\t\tresults.push(result);\n\t\t\t} else {\n\t\t\t\tlet lowestIndex = 0;\n\t\t\t\tlet lowestScore = results[0].score;\n\t\t\t\tfor (let i = 1; i < results.length; i++) {\n\t\t\t\t\tif (results[i].score < lowestScore) {\n\t\t\t\t\t\tlowestIndex = i;\n\t\t\t\t\t\tlowestScore = results[i].score;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (result.score > lowestScore) {\n\t\t\t\t\tresults[lowestIndex] = result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tresults.sort((a, b) => {\n\t\treturn b.score - a.score;\n\t});\n\n\treturn results;\n}\n"],"mappings":"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"}

@@ -178,5 +178,5 @@ //#region src/search/sublime-search.ts

}
//#endregion
export { DEFAULT_KEYS, sublimeSearch };
//# sourceMappingURL=sublime-search.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"sublime-search.mjs","names":["bestRecursiveMatches: number[]","recursiveMatches: number[]","results: Array<{ score: number; item: T }>","itemMatchScore: number | undefined","result: { score: number; item: T }"],"sources":["../../src/search/sublime-search.ts"],"sourcesContent":["/*\n * Constants and utility functions used for searching for node types in node creator component\n * based on https://github.com/forrestthewoods/lib_fts/blob/master/code/fts_fuzzy_match.js\n */\n\nconst SEQUENTIAL_BONUS = 60; // bonus for adjacent matches\nconst SEPARATOR_BONUS = 38; // bonus if match occurs after a separator\nconst CAMEL_BONUS = 30; // bonus if match is uppercase and prev is lower\nconst FIRST_LETTER_BONUS = 15; // bonus if the first letter is matched\n\nconst LEADING_LETTER_PENALTY = -20; // penalty applied for every letter in str before the first match\nconst MAX_LEADING_LETTER_PENALTY = -200; // maximum penalty for leading letters\nconst UNMATCHED_LETTER_PENALTY = -2.5;\n\nexport const DEFAULT_KEYS = [\n\t{ key: 'properties.displayName', weight: 1.3 },\n\t{ key: 'properties.codex.alias', weight: 1 },\n];\n\n/**\n * Returns true if each character in pattern is found sequentially within target\n * @param {*} pattern string\n * @param {*} target string\n */\nfunction fuzzyMatchSimple(pattern: string, target: string): boolean {\n\tlet patternIdx = 0;\n\tlet strIdx = 0;\n\n\twhile (patternIdx < pattern.length && strIdx < target.length) {\n\t\tconst patternChar = pattern.charAt(patternIdx).toLowerCase();\n\t\tconst targetChar = target.charAt(strIdx).toLowerCase();\n\t\tif (patternChar === targetChar) {\n\t\t\tpatternIdx++;\n\t\t}\n\t\t++strIdx;\n\t}\n\n\treturn pattern.length !== 0 && target.length !== 0 && patternIdx === pattern.length;\n}\n\nfunction fuzzyMatchRecursive(\n\tpattern: string,\n\ttarget: string,\n\tpatternCurIndex: number,\n\ttargetCurrIndex: number,\n\ttargetMatches: null | number[],\n\tmatches: number[],\n\tmaxMatches: number,\n\tnextMatch: number,\n\trecursionCount: number,\n\trecursionLimit: number,\n): { matched: boolean; outScore: number } {\n\tlet outScore = 0;\n\n\t// Return if recursion limit is reached.\n\tif (++recursionCount >= recursionLimit) {\n\t\treturn { matched: false, outScore };\n\t}\n\n\t// Return if we reached ends of strings.\n\tif (patternCurIndex === pattern.length || targetCurrIndex === target.length) {\n\t\treturn { matched: false, outScore };\n\t}\n\n\t// Recursion params\n\tlet recursiveMatch = false;\n\tlet bestRecursiveMatches: number[] = [];\n\tlet bestRecursiveScore = 0;\n\n\t// Loop through pattern and str looking for a match.\n\tlet firstMatch = true;\n\twhile (patternCurIndex < pattern.length && targetCurrIndex < target.length) {\n\t\t// Match found.\n\t\tif (pattern[patternCurIndex].toLowerCase() === target[targetCurrIndex].toLowerCase()) {\n\t\t\tif (nextMatch >= maxMatches) {\n\t\t\t\treturn { matched: false, outScore };\n\t\t\t}\n\n\t\t\tif (firstMatch && targetMatches) {\n\t\t\t\tmatches = [...targetMatches];\n\t\t\t\tfirstMatch = false;\n\t\t\t}\n\n\t\t\tconst recursiveMatches: number[] = [];\n\t\t\tconst recursiveResult = fuzzyMatchRecursive(\n\t\t\t\tpattern,\n\t\t\t\ttarget,\n\t\t\t\tpatternCurIndex,\n\t\t\t\ttargetCurrIndex + 1,\n\t\t\t\tmatches,\n\t\t\t\trecursiveMatches,\n\t\t\t\tmaxMatches,\n\t\t\t\tnextMatch,\n\t\t\t\trecursionCount,\n\t\t\t\trecursionLimit,\n\t\t\t);\n\n\t\t\tconst recursiveScore = recursiveResult.outScore;\n\t\t\tif (recursiveResult.matched) {\n\t\t\t\t// Pick best recursive score.\n\t\t\t\tif (!recursiveMatch || recursiveScore > bestRecursiveScore) {\n\t\t\t\t\tbestRecursiveMatches = [...recursiveMatches];\n\t\t\t\t\tbestRecursiveScore = recursiveScore;\n\t\t\t\t}\n\t\t\t\trecursiveMatch = true;\n\t\t\t}\n\n\t\t\tmatches[nextMatch++] = targetCurrIndex;\n\t\t\t++patternCurIndex;\n\t\t}\n\t\t++targetCurrIndex;\n\t}\n\n\tconst matched = patternCurIndex === pattern.length;\n\n\tif (matched) {\n\t\toutScore = 100;\n\n\t\t// Apply leading letter penalty (if not n8n-prefixed)\n\t\tif (!target.toLowerCase().startsWith('n8n')) {\n\t\t\tlet penalty = LEADING_LETTER_PENALTY * matches[0];\n\t\t\tpenalty = penalty < MAX_LEADING_LETTER_PENALTY ? MAX_LEADING_LETTER_PENALTY : penalty;\n\t\t\toutScore += penalty;\n\t\t}\n\n\t\t//Apply unmatched penalty\n\t\tconst unmatched = target.length - nextMatch;\n\t\toutScore += UNMATCHED_LETTER_PENALTY * unmatched;\n\n\t\t// Apply ordering bonuses\n\t\tfor (let i = 0; i < nextMatch; i++) {\n\t\t\tconst currIdx = matches[i];\n\n\t\t\tif (i > 0) {\n\t\t\t\tconst prevIdx = matches[i - 1];\n\t\t\t\tif (currIdx === prevIdx + 1) {\n\t\t\t\t\toutScore += SEQUENTIAL_BONUS;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check for bonuses based on neighbor character value.\n\t\t\tif (currIdx > 0) {\n\t\t\t\t// Camel case\n\t\t\t\tconst neighbor = target[currIdx - 1];\n\t\t\t\tconst curr = target[currIdx];\n\t\t\t\tif (neighbor !== neighbor.toUpperCase() && curr !== curr.toLowerCase()) {\n\t\t\t\t\toutScore += CAMEL_BONUS;\n\t\t\t\t}\n\t\t\t\tconst isNeighbourSeparator = neighbor === '_' || neighbor === ' ';\n\t\t\t\tif (isNeighbourSeparator) {\n\t\t\t\t\toutScore += SEPARATOR_BONUS;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// First letter\n\t\t\t\toutScore += FIRST_LETTER_BONUS;\n\t\t\t}\n\t\t}\n\n\t\t// Return best result\n\t\tif (recursiveMatch && (!matched || bestRecursiveScore > outScore)) {\n\t\t\t// Recursive score is better than \"this\"\n\t\t\tmatches = [...bestRecursiveMatches];\n\t\t\toutScore = bestRecursiveScore;\n\t\t\treturn { matched: true, outScore };\n\t\t} else if (matched) {\n\t\t\t// \"this\" score is better than recursive\n\t\t\treturn { matched: true, outScore };\n\t\t} else {\n\t\t\treturn { matched: false, outScore };\n\t\t}\n\t}\n\treturn { matched: false, outScore };\n}\n\n/**\n * Does a fuzzy search to find pattern inside a string.\n * @param {*} pattern string pattern to search for\n * @param {*} target string string which is being searched\n * @returns [boolean, number] a boolean which tells if pattern was\n * found or not and a search score\n */\nfunction fuzzyMatch(pattern: string, target: string): { matched: boolean; outScore: number } {\n\tconst recursionCount = 0;\n\tconst recursionLimit = 5;\n\tconst matches: number[] = [];\n\tconst maxMatches = 256;\n\n\treturn fuzzyMatchRecursive(\n\t\tpattern,\n\t\ttarget,\n\t\t0 /* patternCurIndex */,\n\t\t0 /* strCurrIndex */,\n\t\tnull /* srcMatces */,\n\t\tmatches,\n\t\tmaxMatches,\n\t\t0 /* nextMatch */,\n\t\trecursionCount,\n\t\trecursionLimit,\n\t);\n}\n\n// prop = 'key'\n// prop = 'key1.key2'\n// prop = ['key1', 'key2']\nfunction getValue<T extends object>(obj: T, prop: string): unknown {\n\tif (obj.hasOwnProperty(prop)) {\n\t\treturn obj[prop as keyof T];\n\t}\n\n\tconst segments = prop.split('.');\n\n\tlet result = obj;\n\tlet i = 0;\n\twhile (result && i < segments.length) {\n\t\tconst key = segments[i] as keyof T;\n\t\tresult = result[key] as T;\n\t\ti++;\n\t}\n\treturn result;\n}\n\nfunction scoreSearchValue(filter: string, value: string, weight: number): number | undefined {\n\tif (!fuzzyMatchSimple(filter, value)) return undefined;\n\n\tconst match = fuzzyMatch(filter, value);\n\tif (!match.matched) return undefined;\n\n\treturn match.outScore * weight;\n}\n\nexport function sublimeSearch<T extends object>(\n\tfilter: string,\n\tdata: readonly T[],\n\tkeys: Array<{ key: string; weight: number }> = DEFAULT_KEYS,\n\tlimit?: number,\n): Array<{ score: number; item: T }> {\n\tconst results: Array<{ score: number; item: T }> = [];\n\n\tfor (const item of data) {\n\t\tlet itemMatchScore: number | undefined;\n\n\t\tfor (const { key, weight } of keys) {\n\t\t\tconst value = getValue(item, key);\n\t\t\tif (Array.isArray(value)) {\n\t\t\t\tfor (const entry of value) {\n\t\t\t\t\tif (typeof entry !== 'string') continue;\n\n\t\t\t\t\tconst score = scoreSearchValue(filter, entry, weight);\n\t\t\t\t\tif (score !== undefined && (itemMatchScore === undefined || score > itemMatchScore)) {\n\t\t\t\t\t\titemMatchScore = score;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (typeof value === 'string') {\n\t\t\t\tconst score = scoreSearchValue(filter, value, weight);\n\t\t\t\tif (score !== undefined && (itemMatchScore === undefined || score > itemMatchScore)) {\n\t\t\t\t\titemMatchScore = score;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (itemMatchScore !== undefined) {\n\t\t\tconst result: { score: number; item: T } = {\n\t\t\t\tscore: itemMatchScore,\n\t\t\t\titem,\n\t\t\t};\n\n\t\t\tif (limit === undefined || results.length < limit) {\n\t\t\t\tresults.push(result);\n\t\t\t} else {\n\t\t\t\tlet lowestIndex = 0;\n\t\t\t\tlet lowestScore = results[0].score;\n\t\t\t\tfor (let i = 1; i < results.length; i++) {\n\t\t\t\t\tif (results[i].score < lowestScore) {\n\t\t\t\t\t\tlowestIndex = i;\n\t\t\t\t\t\tlowestScore = results[i].score;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (result.score > lowestScore) {\n\t\t\t\t\tresults[lowestIndex] = result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tresults.sort((a, b) => {\n\t\treturn b.score - a.score;\n\t});\n\n\treturn results;\n}\n"],"mappings":"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"}
{"version":3,"file":"sublime-search.mjs","names":[],"sources":["../../src/search/sublime-search.ts"],"sourcesContent":["/*\n * Constants and utility functions used for searching for node types in node creator component\n * based on https://github.com/forrestthewoods/lib_fts/blob/master/code/fts_fuzzy_match.js\n */\n\nconst SEQUENTIAL_BONUS = 60; // bonus for adjacent matches\nconst SEPARATOR_BONUS = 38; // bonus if match occurs after a separator\nconst CAMEL_BONUS = 30; // bonus if match is uppercase and prev is lower\nconst FIRST_LETTER_BONUS = 15; // bonus if the first letter is matched\n\nconst LEADING_LETTER_PENALTY = -20; // penalty applied for every letter in str before the first match\nconst MAX_LEADING_LETTER_PENALTY = -200; // maximum penalty for leading letters\nconst UNMATCHED_LETTER_PENALTY = -2.5;\n\nexport const DEFAULT_KEYS = [\n\t{ key: 'properties.displayName', weight: 1.3 },\n\t{ key: 'properties.codex.alias', weight: 1 },\n];\n\n/**\n * Returns true if each character in pattern is found sequentially within target\n * @param {*} pattern string\n * @param {*} target string\n */\nfunction fuzzyMatchSimple(pattern: string, target: string): boolean {\n\tlet patternIdx = 0;\n\tlet strIdx = 0;\n\n\twhile (patternIdx < pattern.length && strIdx < target.length) {\n\t\tconst patternChar = pattern.charAt(patternIdx).toLowerCase();\n\t\tconst targetChar = target.charAt(strIdx).toLowerCase();\n\t\tif (patternChar === targetChar) {\n\t\t\tpatternIdx++;\n\t\t}\n\t\t++strIdx;\n\t}\n\n\treturn pattern.length !== 0 && target.length !== 0 && patternIdx === pattern.length;\n}\n\nfunction fuzzyMatchRecursive(\n\tpattern: string,\n\ttarget: string,\n\tpatternCurIndex: number,\n\ttargetCurrIndex: number,\n\ttargetMatches: null | number[],\n\tmatches: number[],\n\tmaxMatches: number,\n\tnextMatch: number,\n\trecursionCount: number,\n\trecursionLimit: number,\n): { matched: boolean; outScore: number } {\n\tlet outScore = 0;\n\n\t// Return if recursion limit is reached.\n\tif (++recursionCount >= recursionLimit) {\n\t\treturn { matched: false, outScore };\n\t}\n\n\t// Return if we reached ends of strings.\n\tif (patternCurIndex === pattern.length || targetCurrIndex === target.length) {\n\t\treturn { matched: false, outScore };\n\t}\n\n\t// Recursion params\n\tlet recursiveMatch = false;\n\tlet bestRecursiveMatches: number[] = [];\n\tlet bestRecursiveScore = 0;\n\n\t// Loop through pattern and str looking for a match.\n\tlet firstMatch = true;\n\twhile (patternCurIndex < pattern.length && targetCurrIndex < target.length) {\n\t\t// Match found.\n\t\tif (pattern[patternCurIndex].toLowerCase() === target[targetCurrIndex].toLowerCase()) {\n\t\t\tif (nextMatch >= maxMatches) {\n\t\t\t\treturn { matched: false, outScore };\n\t\t\t}\n\n\t\t\tif (firstMatch && targetMatches) {\n\t\t\t\tmatches = [...targetMatches];\n\t\t\t\tfirstMatch = false;\n\t\t\t}\n\n\t\t\tconst recursiveMatches: number[] = [];\n\t\t\tconst recursiveResult = fuzzyMatchRecursive(\n\t\t\t\tpattern,\n\t\t\t\ttarget,\n\t\t\t\tpatternCurIndex,\n\t\t\t\ttargetCurrIndex + 1,\n\t\t\t\tmatches,\n\t\t\t\trecursiveMatches,\n\t\t\t\tmaxMatches,\n\t\t\t\tnextMatch,\n\t\t\t\trecursionCount,\n\t\t\t\trecursionLimit,\n\t\t\t);\n\n\t\t\tconst recursiveScore = recursiveResult.outScore;\n\t\t\tif (recursiveResult.matched) {\n\t\t\t\t// Pick best recursive score.\n\t\t\t\tif (!recursiveMatch || recursiveScore > bestRecursiveScore) {\n\t\t\t\t\tbestRecursiveMatches = [...recursiveMatches];\n\t\t\t\t\tbestRecursiveScore = recursiveScore;\n\t\t\t\t}\n\t\t\t\trecursiveMatch = true;\n\t\t\t}\n\n\t\t\tmatches[nextMatch++] = targetCurrIndex;\n\t\t\t++patternCurIndex;\n\t\t}\n\t\t++targetCurrIndex;\n\t}\n\n\tconst matched = patternCurIndex === pattern.length;\n\n\tif (matched) {\n\t\toutScore = 100;\n\n\t\t// Apply leading letter penalty (if not n8n-prefixed)\n\t\tif (!target.toLowerCase().startsWith('n8n')) {\n\t\t\tlet penalty = LEADING_LETTER_PENALTY * matches[0];\n\t\t\tpenalty = penalty < MAX_LEADING_LETTER_PENALTY ? MAX_LEADING_LETTER_PENALTY : penalty;\n\t\t\toutScore += penalty;\n\t\t}\n\n\t\t//Apply unmatched penalty\n\t\tconst unmatched = target.length - nextMatch;\n\t\toutScore += UNMATCHED_LETTER_PENALTY * unmatched;\n\n\t\t// Apply ordering bonuses\n\t\tfor (let i = 0; i < nextMatch; i++) {\n\t\t\tconst currIdx = matches[i];\n\n\t\t\tif (i > 0) {\n\t\t\t\tconst prevIdx = matches[i - 1];\n\t\t\t\tif (currIdx === prevIdx + 1) {\n\t\t\t\t\toutScore += SEQUENTIAL_BONUS;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check for bonuses based on neighbor character value.\n\t\t\tif (currIdx > 0) {\n\t\t\t\t// Camel case\n\t\t\t\tconst neighbor = target[currIdx - 1];\n\t\t\t\tconst curr = target[currIdx];\n\t\t\t\tif (neighbor !== neighbor.toUpperCase() && curr !== curr.toLowerCase()) {\n\t\t\t\t\toutScore += CAMEL_BONUS;\n\t\t\t\t}\n\t\t\t\tconst isNeighbourSeparator = neighbor === '_' || neighbor === ' ';\n\t\t\t\tif (isNeighbourSeparator) {\n\t\t\t\t\toutScore += SEPARATOR_BONUS;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// First letter\n\t\t\t\toutScore += FIRST_LETTER_BONUS;\n\t\t\t}\n\t\t}\n\n\t\t// Return best result\n\t\tif (recursiveMatch && (!matched || bestRecursiveScore > outScore)) {\n\t\t\t// Recursive score is better than \"this\"\n\t\t\tmatches = [...bestRecursiveMatches];\n\t\t\toutScore = bestRecursiveScore;\n\t\t\treturn { matched: true, outScore };\n\t\t} else if (matched) {\n\t\t\t// \"this\" score is better than recursive\n\t\t\treturn { matched: true, outScore };\n\t\t} else {\n\t\t\treturn { matched: false, outScore };\n\t\t}\n\t}\n\treturn { matched: false, outScore };\n}\n\n/**\n * Does a fuzzy search to find pattern inside a string.\n * @param {*} pattern string pattern to search for\n * @param {*} target string string which is being searched\n * @returns [boolean, number] a boolean which tells if pattern was\n * found or not and a search score\n */\nfunction fuzzyMatch(pattern: string, target: string): { matched: boolean; outScore: number } {\n\tconst recursionCount = 0;\n\tconst recursionLimit = 5;\n\tconst matches: number[] = [];\n\tconst maxMatches = 256;\n\n\treturn fuzzyMatchRecursive(\n\t\tpattern,\n\t\ttarget,\n\t\t0 /* patternCurIndex */,\n\t\t0 /* strCurrIndex */,\n\t\tnull /* srcMatces */,\n\t\tmatches,\n\t\tmaxMatches,\n\t\t0 /* nextMatch */,\n\t\trecursionCount,\n\t\trecursionLimit,\n\t);\n}\n\n// prop = 'key'\n// prop = 'key1.key2'\n// prop = ['key1', 'key2']\nfunction getValue<T extends object>(obj: T, prop: string): unknown {\n\tif (obj.hasOwnProperty(prop)) {\n\t\treturn obj[prop as keyof T];\n\t}\n\n\tconst segments = prop.split('.');\n\n\tlet result = obj;\n\tlet i = 0;\n\twhile (result && i < segments.length) {\n\t\tconst key = segments[i] as keyof T;\n\t\tresult = result[key] as T;\n\t\ti++;\n\t}\n\treturn result;\n}\n\nfunction scoreSearchValue(filter: string, value: string, weight: number): number | undefined {\n\tif (!fuzzyMatchSimple(filter, value)) return undefined;\n\n\tconst match = fuzzyMatch(filter, value);\n\tif (!match.matched) return undefined;\n\n\treturn match.outScore * weight;\n}\n\nexport function sublimeSearch<T extends object>(\n\tfilter: string,\n\tdata: readonly T[],\n\tkeys: Array<{ key: string; weight: number }> = DEFAULT_KEYS,\n\tlimit?: number,\n): Array<{ score: number; item: T }> {\n\tconst results: Array<{ score: number; item: T }> = [];\n\n\tfor (const item of data) {\n\t\tlet itemMatchScore: number | undefined;\n\n\t\tfor (const { key, weight } of keys) {\n\t\t\tconst value = getValue(item, key);\n\t\t\tif (Array.isArray(value)) {\n\t\t\t\tfor (const entry of value) {\n\t\t\t\t\tif (typeof entry !== 'string') continue;\n\n\t\t\t\t\tconst score = scoreSearchValue(filter, entry, weight);\n\t\t\t\t\tif (score !== undefined && (itemMatchScore === undefined || score > itemMatchScore)) {\n\t\t\t\t\t\titemMatchScore = score;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (typeof value === 'string') {\n\t\t\t\tconst score = scoreSearchValue(filter, value, weight);\n\t\t\t\tif (score !== undefined && (itemMatchScore === undefined || score > itemMatchScore)) {\n\t\t\t\t\titemMatchScore = score;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (itemMatchScore !== undefined) {\n\t\t\tconst result: { score: number; item: T } = {\n\t\t\t\tscore: itemMatchScore,\n\t\t\t\titem,\n\t\t\t};\n\n\t\t\tif (limit === undefined || results.length < limit) {\n\t\t\t\tresults.push(result);\n\t\t\t} else {\n\t\t\t\tlet lowestIndex = 0;\n\t\t\t\tlet lowestScore = results[0].score;\n\t\t\t\tfor (let i = 1; i < results.length; i++) {\n\t\t\t\t\tif (results[i].score < lowestScore) {\n\t\t\t\t\t\tlowestIndex = i;\n\t\t\t\t\t\tlowestScore = results[i].score;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (result.score > lowestScore) {\n\t\t\t\t\tresults[lowestIndex] = result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tresults.sort((a, b) => {\n\t\treturn b.score - a.score;\n\t});\n\n\treturn results;\n}\n"],"mappings":"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"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/sort/sort-by-property.ts

@@ -10,5 +10,5 @@ const sortByProperty = (property, arr, order = "asc") => arr.sort((a, b) => {

});
//#endregion
exports.sortByProperty = sortByProperty;
//# sourceMappingURL=sort-by-property.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"sort-by-property.cjs","names":[],"sources":["../../src/sort/sort-by-property.ts"],"sourcesContent":["export const sortByProperty = <T>(\n\tproperty: keyof T,\n\tarr: T[],\n\torder: 'asc' | 'desc' = 'asc',\n): T[] =>\n\tarr.sort((a, b) => {\n\t\tconst result = String(a[property]).localeCompare(String(b[property]), undefined, {\n\t\t\tnumeric: true,\n\t\t\tsensitivity: 'base',\n\t\t});\n\t\treturn order === 'asc' ? result : -result;\n\t});\n"],"mappings":";;AAAA,MAAa,kBACZ,UACA,KACA,QAAwB,UAExB,IAAI,MAAM,GAAG,MAAM;CAClB,MAAM,SAAS,OAAO,EAAE,UAAU,CAAC,cAAc,OAAO,EAAE,UAAU,EAAE,QAAW;EAChF,SAAS;EACT,aAAa;EACb,CAAC;AACF,QAAO,UAAU,QAAQ,SAAS,CAAC;EAClC"}
{"version":3,"file":"sort-by-property.cjs","names":[],"sources":["../../src/sort/sort-by-property.ts"],"sourcesContent":["export const sortByProperty = <T>(\n\tproperty: keyof T,\n\tarr: T[],\n\torder: 'asc' | 'desc' = 'asc',\n): T[] =>\n\tarr.sort((a, b) => {\n\t\tconst result = String(a[property]).localeCompare(String(b[property]), undefined, {\n\t\t\tnumeric: true,\n\t\t\tsensitivity: 'base',\n\t\t});\n\t\treturn order === 'asc' ? result : -result;\n\t});\n"],"mappings":";;AAAA,MAAa,kBACZ,UACA,KACA,QAAwB,UAExB,IAAI,MAAM,GAAG,MAAM;CAClB,MAAM,SAAS,OAAO,EAAE,SAAS,CAAC,CAAC,cAAc,OAAO,EAAE,SAAS,GAAG,KAAA,GAAW;EAChF,SAAS;EACT,aAAa;CACd,CAAC;CACD,OAAO,UAAU,QAAQ,SAAS,CAAC;AACpC,CAAC"}
//#region src/sort/sort-by-property.d.ts
declare const sortByProperty: <T>(property: keyof T, arr: T[], order?: "asc" | "desc") => T[];
declare const sortByProperty: <T>(property: keyof T, arr: T[], order?: 'asc' | 'desc') => T[];
//#endregion
export { sortByProperty };
//# sourceMappingURL=sort-by-property.d.cts.map
//#region src/sort/sort-by-property.d.ts
declare const sortByProperty: <T>(property: keyof T, arr: T[], order?: "asc" | "desc") => T[];
declare const sortByProperty: <T>(property: keyof T, arr: T[], order?: 'asc' | 'desc') => T[];
//#endregion
export { sortByProperty };
//# sourceMappingURL=sort-by-property.d.mts.map

@@ -9,5 +9,5 @@ //#region src/sort/sort-by-property.ts

});
//#endregion
export { sortByProperty };
//# sourceMappingURL=sort-by-property.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"sort-by-property.mjs","names":[],"sources":["../../src/sort/sort-by-property.ts"],"sourcesContent":["export const sortByProperty = <T>(\n\tproperty: keyof T,\n\tarr: T[],\n\torder: 'asc' | 'desc' = 'asc',\n): T[] =>\n\tarr.sort((a, b) => {\n\t\tconst result = String(a[property]).localeCompare(String(b[property]), undefined, {\n\t\t\tnumeric: true,\n\t\t\tsensitivity: 'base',\n\t\t});\n\t\treturn order === 'asc' ? result : -result;\n\t});\n"],"mappings":";AAAA,MAAa,kBACZ,UACA,KACA,QAAwB,UAExB,IAAI,MAAM,GAAG,MAAM;CAClB,MAAM,SAAS,OAAO,EAAE,UAAU,CAAC,cAAc,OAAO,EAAE,UAAU,EAAE,QAAW;EAChF,SAAS;EACT,aAAa;EACb,CAAC;AACF,QAAO,UAAU,QAAQ,SAAS,CAAC;EAClC"}
{"version":3,"file":"sort-by-property.mjs","names":[],"sources":["../../src/sort/sort-by-property.ts"],"sourcesContent":["export const sortByProperty = <T>(\n\tproperty: keyof T,\n\tarr: T[],\n\torder: 'asc' | 'desc' = 'asc',\n): T[] =>\n\tarr.sort((a, b) => {\n\t\tconst result = String(a[property]).localeCompare(String(b[property]), undefined, {\n\t\t\tnumeric: true,\n\t\t\tsensitivity: 'base',\n\t\t});\n\t\treturn order === 'asc' ? result : -result;\n\t});\n"],"mappings":";AAAA,MAAa,kBACZ,UACA,KACA,QAAwB,UAExB,IAAI,MAAM,GAAG,MAAM;CAClB,MAAM,SAAS,OAAO,EAAE,SAAS,CAAC,CAAC,cAAc,OAAO,EAAE,SAAS,GAAG,KAAA,GAAW;EAChF,SAAS;EACT,aAAa;CACd,CAAC;CACD,OAAO,UAAU,QAAQ,SAAS,CAAC;AACpC,CAAC"}

@@ -1,2 +0,2 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/string/truncate.ts

@@ -29,6 +29,6 @@ const truncate = (text, length = 30) => text.length > length ? text.slice(0, length) + "..." : text;

}
//#endregion
exports.truncate = truncate;
exports.truncateBeforeLast = truncateBeforeLast;
//# sourceMappingURL=truncate.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"truncate.cjs","names":["chars: string[]"],"sources":["../../src/string/truncate.ts"],"sourcesContent":["export const truncate = (text: string, length = 30): string =>\n\ttext.length > length ? text.slice(0, length) + '...' : text;\n\n/**\n * Replace part of given text with ellipsis following the rules below:\n *\n * - Remove chars just before the last word, as long as the last word is between\n * minLastWordLength and 15 chars\n * - Otherwise preserve the last `lastCharsLength` chars and remove chars before that\n */\nexport function truncateBeforeLast(\n\ttext: string,\n\tmaxLength: number,\n\tlastCharsLength: number = 5,\n\tminLastWordLength: number = 1,\n): string {\n\tconst chars: string[] = [];\n\n\tconst segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });\n\n\tfor (const { segment } of segmenter.segment(text)) {\n\t\tchars.push(segment);\n\t}\n\n\tif (chars.length <= maxLength) {\n\t\treturn text;\n\t}\n\n\tconst lastWhitespaceIndex = chars.findLastIndex((ch) => ch.match(/^\\s+$/));\n\tconst lastWordIndex = lastWhitespaceIndex + 1;\n\tconst lastWord = chars.slice(lastWordIndex);\n\tconst ellipsis = '…';\n\tconst ellipsisLength = ellipsis.length;\n\n\tif (lastWord.length >= minLastWordLength && lastWord.length < 15) {\n\t\tconst charsToRemove = chars.length - maxLength + ellipsisLength;\n\t\tconst indexBeforeLastWord = lastWordIndex;\n\t\tconst keepLength = indexBeforeLastWord - charsToRemove;\n\n\t\tif (keepLength > 0) {\n\t\t\treturn (\n\t\t\t\tchars.slice(0, keepLength).join('') + ellipsis + chars.slice(indexBeforeLastWord).join('')\n\t\t\t);\n\t\t}\n\t}\n\n\tif (lastCharsLength < 1) {\n\t\treturn chars.slice(0, maxLength).join('') + ellipsis;\n\t}\n\n\treturn (\n\t\tchars.slice(0, maxLength - lastCharsLength - ellipsisLength).join('') +\n\t\tellipsis +\n\t\tchars.slice(-lastCharsLength).join('')\n\t);\n}\n"],"mappings":";;AAAA,MAAa,YAAY,MAAc,SAAS,OAC/C,KAAK,SAAS,SAAS,KAAK,MAAM,GAAG,OAAO,GAAG,QAAQ;;;;;;;;AASxD,SAAgB,mBACf,MACA,WACA,kBAA0B,GAC1B,oBAA4B,GACnB;CACT,MAAMA,QAAkB,EAAE;CAE1B,MAAM,YAAY,IAAI,KAAK,UAAU,QAAW,EAAE,aAAa,YAAY,CAAC;AAE5E,MAAK,MAAM,EAAE,aAAa,UAAU,QAAQ,KAAK,CAChD,OAAM,KAAK,QAAQ;AAGpB,KAAI,MAAM,UAAU,UACnB,QAAO;CAIR,MAAM,gBADsB,MAAM,eAAe,OAAO,GAAG,MAAM,QAAQ,CAAC,GAC9B;CAC5C,MAAM,WAAW,MAAM,MAAM,cAAc;CAC3C,MAAM,WAAW;CACjB,MAAM,iBAAiB;AAEvB,KAAI,SAAS,UAAU,qBAAqB,SAAS,SAAS,IAAI;EACjE,MAAM,gBAAgB,MAAM,SAAS,YAAY;EACjD,MAAM,sBAAsB;EAC5B,MAAM,aAAa,sBAAsB;AAEzC,MAAI,aAAa,EAChB,QACC,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,GAAG,GAAG,WAAW,MAAM,MAAM,oBAAoB,CAAC,KAAK,GAAG;;AAK7F,KAAI,kBAAkB,EACrB,QAAO,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,GAAG,GAAG;AAG7C,QACC,MAAM,MAAM,GAAG,YAAY,kBAAkB,eAAe,CAAC,KAAK,GAAG,GACrE,WACA,MAAM,MAAM,CAAC,gBAAgB,CAAC,KAAK,GAAG"}
{"version":3,"file":"truncate.cjs","names":[],"sources":["../../src/string/truncate.ts"],"sourcesContent":["export const truncate = (text: string, length = 30): string =>\n\ttext.length > length ? text.slice(0, length) + '...' : text;\n\n/**\n * Replace part of given text with ellipsis following the rules below:\n *\n * - Remove chars just before the last word, as long as the last word is between\n * minLastWordLength and 15 chars\n * - Otherwise preserve the last `lastCharsLength` chars and remove chars before that\n */\nexport function truncateBeforeLast(\n\ttext: string,\n\tmaxLength: number,\n\tlastCharsLength: number = 5,\n\tminLastWordLength: number = 1,\n): string {\n\tconst chars: string[] = [];\n\n\tconst segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });\n\n\tfor (const { segment } of segmenter.segment(text)) {\n\t\tchars.push(segment);\n\t}\n\n\tif (chars.length <= maxLength) {\n\t\treturn text;\n\t}\n\n\tconst lastWhitespaceIndex = chars.findLastIndex((ch) => ch.match(/^\\s+$/));\n\tconst lastWordIndex = lastWhitespaceIndex + 1;\n\tconst lastWord = chars.slice(lastWordIndex);\n\tconst ellipsis = '…';\n\tconst ellipsisLength = ellipsis.length;\n\n\tif (lastWord.length >= minLastWordLength && lastWord.length < 15) {\n\t\tconst charsToRemove = chars.length - maxLength + ellipsisLength;\n\t\tconst indexBeforeLastWord = lastWordIndex;\n\t\tconst keepLength = indexBeforeLastWord - charsToRemove;\n\n\t\tif (keepLength > 0) {\n\t\t\treturn (\n\t\t\t\tchars.slice(0, keepLength).join('') + ellipsis + chars.slice(indexBeforeLastWord).join('')\n\t\t\t);\n\t\t}\n\t}\n\n\tif (lastCharsLength < 1) {\n\t\treturn chars.slice(0, maxLength).join('') + ellipsis;\n\t}\n\n\treturn (\n\t\tchars.slice(0, maxLength - lastCharsLength - ellipsisLength).join('') +\n\t\tellipsis +\n\t\tchars.slice(-lastCharsLength).join('')\n\t);\n}\n"],"mappings":";;AAAA,MAAa,YAAY,MAAc,SAAS,OAC/C,KAAK,SAAS,SAAS,KAAK,MAAM,GAAG,MAAM,IAAI,QAAQ;;;;;;;;AASxD,SAAgB,mBACf,MACA,WACA,kBAA0B,GAC1B,oBAA4B,GACnB;CACT,MAAM,QAAkB,CAAC;CAEzB,MAAM,YAAY,IAAI,KAAK,UAAU,KAAA,GAAW,EAAE,aAAa,WAAW,CAAC;CAE3E,KAAK,MAAM,EAAE,aAAa,UAAU,QAAQ,IAAI,GAC/C,MAAM,KAAK,OAAO;CAGnB,IAAI,MAAM,UAAU,WACnB,OAAO;CAIR,MAAM,gBADsB,MAAM,eAAe,OAAO,GAAG,MAAM,OAAO,CAChC,IAAI;CAC5C,MAAM,WAAW,MAAM,MAAM,aAAa;CAC1C,MAAM,WAAW;CACjB,MAAM,iBAAiB;CAEvB,IAAI,SAAS,UAAU,qBAAqB,SAAS,SAAS,IAAI;EACjE,MAAM,gBAAgB,MAAM,SAAS,YAAY;EACjD,MAAM,sBAAsB;EAC5B,MAAM,aAAa,sBAAsB;EAEzC,IAAI,aAAa,GAChB,OACC,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,KAAK,EAAE,IAAI,WAAW,MAAM,MAAM,mBAAmB,CAAC,CAAC,KAAK,EAAE;CAG5F;CAEA,IAAI,kBAAkB,GACrB,OAAO,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,KAAK,EAAE,IAAI;CAG7C,OACC,MAAM,MAAM,GAAG,YAAY,kBAAkB,cAAc,CAAC,CAAC,KAAK,EAAE,IACpE,WACA,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC,KAAK,EAAE;AAEvC"}

@@ -28,5 +28,5 @@ //#region src/string/truncate.ts

}
//#endregion
export { truncate, truncateBeforeLast };
//# sourceMappingURL=truncate.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"truncate.mjs","names":["chars: string[]"],"sources":["../../src/string/truncate.ts"],"sourcesContent":["export const truncate = (text: string, length = 30): string =>\n\ttext.length > length ? text.slice(0, length) + '...' : text;\n\n/**\n * Replace part of given text with ellipsis following the rules below:\n *\n * - Remove chars just before the last word, as long as the last word is between\n * minLastWordLength and 15 chars\n * - Otherwise preserve the last `lastCharsLength` chars and remove chars before that\n */\nexport function truncateBeforeLast(\n\ttext: string,\n\tmaxLength: number,\n\tlastCharsLength: number = 5,\n\tminLastWordLength: number = 1,\n): string {\n\tconst chars: string[] = [];\n\n\tconst segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });\n\n\tfor (const { segment } of segmenter.segment(text)) {\n\t\tchars.push(segment);\n\t}\n\n\tif (chars.length <= maxLength) {\n\t\treturn text;\n\t}\n\n\tconst lastWhitespaceIndex = chars.findLastIndex((ch) => ch.match(/^\\s+$/));\n\tconst lastWordIndex = lastWhitespaceIndex + 1;\n\tconst lastWord = chars.slice(lastWordIndex);\n\tconst ellipsis = '…';\n\tconst ellipsisLength = ellipsis.length;\n\n\tif (lastWord.length >= minLastWordLength && lastWord.length < 15) {\n\t\tconst charsToRemove = chars.length - maxLength + ellipsisLength;\n\t\tconst indexBeforeLastWord = lastWordIndex;\n\t\tconst keepLength = indexBeforeLastWord - charsToRemove;\n\n\t\tif (keepLength > 0) {\n\t\t\treturn (\n\t\t\t\tchars.slice(0, keepLength).join('') + ellipsis + chars.slice(indexBeforeLastWord).join('')\n\t\t\t);\n\t\t}\n\t}\n\n\tif (lastCharsLength < 1) {\n\t\treturn chars.slice(0, maxLength).join('') + ellipsis;\n\t}\n\n\treturn (\n\t\tchars.slice(0, maxLength - lastCharsLength - ellipsisLength).join('') +\n\t\tellipsis +\n\t\tchars.slice(-lastCharsLength).join('')\n\t);\n}\n"],"mappings":";AAAA,MAAa,YAAY,MAAc,SAAS,OAC/C,KAAK,SAAS,SAAS,KAAK,MAAM,GAAG,OAAO,GAAG,QAAQ;;;;;;;;AASxD,SAAgB,mBACf,MACA,WACA,kBAA0B,GAC1B,oBAA4B,GACnB;CACT,MAAMA,QAAkB,EAAE;CAE1B,MAAM,YAAY,IAAI,KAAK,UAAU,QAAW,EAAE,aAAa,YAAY,CAAC;AAE5E,MAAK,MAAM,EAAE,aAAa,UAAU,QAAQ,KAAK,CAChD,OAAM,KAAK,QAAQ;AAGpB,KAAI,MAAM,UAAU,UACnB,QAAO;CAIR,MAAM,gBADsB,MAAM,eAAe,OAAO,GAAG,MAAM,QAAQ,CAAC,GAC9B;CAC5C,MAAM,WAAW,MAAM,MAAM,cAAc;CAC3C,MAAM,WAAW;CACjB,MAAM,iBAAiB;AAEvB,KAAI,SAAS,UAAU,qBAAqB,SAAS,SAAS,IAAI;EACjE,MAAM,gBAAgB,MAAM,SAAS,YAAY;EACjD,MAAM,sBAAsB;EAC5B,MAAM,aAAa,sBAAsB;AAEzC,MAAI,aAAa,EAChB,QACC,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,GAAG,GAAG,WAAW,MAAM,MAAM,oBAAoB,CAAC,KAAK,GAAG;;AAK7F,KAAI,kBAAkB,EACrB,QAAO,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,GAAG,GAAG;AAG7C,QACC,MAAM,MAAM,GAAG,YAAY,kBAAkB,eAAe,CAAC,KAAK,GAAG,GACrE,WACA,MAAM,MAAM,CAAC,gBAAgB,CAAC,KAAK,GAAG"}
{"version":3,"file":"truncate.mjs","names":[],"sources":["../../src/string/truncate.ts"],"sourcesContent":["export const truncate = (text: string, length = 30): string =>\n\ttext.length > length ? text.slice(0, length) + '...' : text;\n\n/**\n * Replace part of given text with ellipsis following the rules below:\n *\n * - Remove chars just before the last word, as long as the last word is between\n * minLastWordLength and 15 chars\n * - Otherwise preserve the last `lastCharsLength` chars and remove chars before that\n */\nexport function truncateBeforeLast(\n\ttext: string,\n\tmaxLength: number,\n\tlastCharsLength: number = 5,\n\tminLastWordLength: number = 1,\n): string {\n\tconst chars: string[] = [];\n\n\tconst segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });\n\n\tfor (const { segment } of segmenter.segment(text)) {\n\t\tchars.push(segment);\n\t}\n\n\tif (chars.length <= maxLength) {\n\t\treturn text;\n\t}\n\n\tconst lastWhitespaceIndex = chars.findLastIndex((ch) => ch.match(/^\\s+$/));\n\tconst lastWordIndex = lastWhitespaceIndex + 1;\n\tconst lastWord = chars.slice(lastWordIndex);\n\tconst ellipsis = '…';\n\tconst ellipsisLength = ellipsis.length;\n\n\tif (lastWord.length >= minLastWordLength && lastWord.length < 15) {\n\t\tconst charsToRemove = chars.length - maxLength + ellipsisLength;\n\t\tconst indexBeforeLastWord = lastWordIndex;\n\t\tconst keepLength = indexBeforeLastWord - charsToRemove;\n\n\t\tif (keepLength > 0) {\n\t\t\treturn (\n\t\t\t\tchars.slice(0, keepLength).join('') + ellipsis + chars.slice(indexBeforeLastWord).join('')\n\t\t\t);\n\t\t}\n\t}\n\n\tif (lastCharsLength < 1) {\n\t\treturn chars.slice(0, maxLength).join('') + ellipsis;\n\t}\n\n\treturn (\n\t\tchars.slice(0, maxLength - lastCharsLength - ellipsisLength).join('') +\n\t\tellipsis +\n\t\tchars.slice(-lastCharsLength).join('')\n\t);\n}\n"],"mappings":";AAAA,MAAa,YAAY,MAAc,SAAS,OAC/C,KAAK,SAAS,SAAS,KAAK,MAAM,GAAG,MAAM,IAAI,QAAQ;;;;;;;;AASxD,SAAgB,mBACf,MACA,WACA,kBAA0B,GAC1B,oBAA4B,GACnB;CACT,MAAM,QAAkB,CAAC;CAEzB,MAAM,YAAY,IAAI,KAAK,UAAU,KAAA,GAAW,EAAE,aAAa,WAAW,CAAC;CAE3E,KAAK,MAAM,EAAE,aAAa,UAAU,QAAQ,IAAI,GAC/C,MAAM,KAAK,OAAO;CAGnB,IAAI,MAAM,UAAU,WACnB,OAAO;CAIR,MAAM,gBADsB,MAAM,eAAe,OAAO,GAAG,MAAM,OAAO,CAChC,IAAI;CAC5C,MAAM,WAAW,MAAM,MAAM,aAAa;CAC1C,MAAM,WAAW;CACjB,MAAM,iBAAiB;CAEvB,IAAI,SAAS,UAAU,qBAAqB,SAAS,SAAS,IAAI;EACjE,MAAM,gBAAgB,MAAM,SAAS,YAAY;EACjD,MAAM,sBAAsB;EAC5B,MAAM,aAAa,sBAAsB;EAEzC,IAAI,aAAa,GAChB,OACC,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,KAAK,EAAE,IAAI,WAAW,MAAM,MAAM,mBAAmB,CAAC,CAAC,KAAK,EAAE;CAG5F;CAEA,IAAI,kBAAkB,GACrB,OAAO,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,KAAK,EAAE,IAAI;CAG7C,OACC,MAAM,MAAM,GAAG,YAAY,kBAAkB,cAAc,CAAC,CAAC,KAAK,EAAE,IACpE,WACA,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC,KAAK,EAAE;AAEvC"}

@@ -1,1 +0,1 @@

export { };
export {};
{
"name": "@n8n/utils",
"type": "module",
"version": "1.39.0",
"version": "1.40.0",
"files": [

@@ -31,3 +31,3 @@ "dist",

"nanoid": "3.3.8",
"@n8n/constants": "0.31.0"
"@n8n/constants": "0.32.0"
},

@@ -37,9 +37,9 @@ "devDependencies": {

"@testing-library/user-event": "^14.6.1",
"tsdown": "^0.16.5",
"typescript": "6.0.2",
"tsdown": "^0.22.8",
"typescript": "7.0.2",
"vite": "^8.0.2",
"vitest": "^4.1.9",
"@n8n/eslint-config": "0.0.1",
"@n8n/vitest-config": "1.18.0",
"@n8n/typescript-config": "1.9.0"
"@n8n/typescript-config": "1.9.0",
"@n8n/vitest-config": "1.19.0",
"@n8n/eslint-config": "0.0.1"
},

@@ -46,0 +46,0 @@ "license": "SEE LICENSE IN LICENSE.md",

//#region src/errors/ensure-error.ts
/** Ensures `error` is an `Error */
function ensureError(error) {
return error instanceof Error ? error : new Error("Error that was not an instance of Error was thrown", { cause: error });
}
//#endregion
Object.defineProperty(exports, 'ensureError', {
enumerable: true,
get: function () {
return ensureError;
}
});
//# sourceMappingURL=ensure-error.cjs.map
{"version":3,"file":"ensure-error.cjs","names":[],"sources":["../src/errors/ensure-error.ts"],"sourcesContent":["/** Ensures `error` is an `Error */\nexport function ensureError(error: unknown): Error {\n\treturn error instanceof Error\n\t\t? error\n\t\t: new Error('Error that was not an instance of Error was thrown', {\n\t\t\t\t// We should never throw anything except something that derives from Error\n\t\t\t\tcause: error,\n\t\t\t});\n}\n"],"mappings":";;;AACA,SAAgB,YAAY,OAAuB;AAClD,QAAO,iBAAiB,QACrB,QACA,IAAI,MAAM,sDAAsD,EAEhE,OAAO,OACP,CAAC"}
//#region src/errors/ensure-error.ts
/** Ensures `error` is an `Error */
function ensureError(error) {
return error instanceof Error ? error : new Error("Error that was not an instance of Error was thrown", { cause: error });
}
//#endregion
export { ensureError as t };
//# sourceMappingURL=ensure-error.mjs.map
{"version":3,"file":"ensure-error.mjs","names":[],"sources":["../src/errors/ensure-error.ts"],"sourcesContent":["/** Ensures `error` is an `Error */\nexport function ensureError(error: unknown): Error {\n\treturn error instanceof Error\n\t\t? error\n\t\t: new Error('Error that was not an instance of Error was thrown', {\n\t\t\t\t// We should never throw anything except something that derives from Error\n\t\t\t\tcause: error,\n\t\t\t});\n}\n"],"mappings":";;AACA,SAAgB,YAAY,OAAuB;AAClD,QAAO,iBAAiB,QACrB,QACA,IAAI,MAAM,sDAAsD,EAEhE,OAAO,OACP,CAAC"}
//#region src/format-pem-block.ts
const PEM_BODY_LINE_LENGTH = 64;
function formatCompactPem(pem, isPublic) {
const trimmed = pem.trim();
if ((trimmed.match(/-----BEGIN /g) ?? []).length !== 1) return void 0;
const labelPattern = isPublic ? "[A-Z0-9 ]*PUBLIC KEY" : "[A-Z0-9 ]*PRIVATE KEY|CERTIFICATE";
const pemMatch = trimmed.match(/* @__PURE__ */ new RegExp(`^-----BEGIN (${labelPattern})-----([\\s\\S]*?)-----END \\1-----$`));
if (!pemMatch) return void 0;
const [, label, body] = pemMatch;
const normalizedBody = body.replace(/\\n/g, "\n").trim();
return `-----BEGIN ${label}-----\n${/\s/.test(normalizedBody) ? normalizedBody.replace(/:\s+/g, ":").replace(/\s+/g, "\n") : (normalizedBody.match(new RegExp(`.{1,${PEM_BODY_LINE_LENGTH}}`, "g")) ?? []).join("\n")}\n-----END ${label}-----`;
}
/**
* Normalize a single PEM-encoded block (private key, public key, or certificate)
* by collapsing whitespace and wrapping the body at 64 chars. Multi-block PEM
* chains are returned unchanged.
*
* @param pem - The PEM-encoded block to format.
* @param isPublic - When true, match `PUBLIC KEY` labels instead of the default `PRIVATE KEY` / `CERTIFICATE`.
* @returns The formatted PEM block.
*/
function formatPemBlock(pem, isPublic = false) {
let regex = /(PRIVATE KEY|CERTIFICATE)/;
if (isPublic) regex = /(PUBLIC KEY)/;
if (!pem || /\n/.test(pem)) return pem;
const compactPem = formatCompactPem(pem, isPublic);
if (compactPem !== void 0) return compactPem;
let formattedPem = "";
pem.split("-----").filter((item) => item !== "").forEach((part) => {
if (regex.test(part)) formattedPem += `-----${part}-----`;
else if (/Proc-Type|DEK-Info/.test(part)) {
part = part.replace(/:\s+/g, ":");
formattedPem += part.replace(/\\n/g, "\n").replace(/\s+/g, "\n");
} else formattedPem += part.replace(/\\n/g, "\n").replace(/\s+/g, "\n");
});
return formattedPem;
}
//#endregion
Object.defineProperty(exports, 'formatPemBlock', {
enumerable: true,
get: function () {
return formatPemBlock;
}
});
//# sourceMappingURL=format-pem-block2.cjs.map
{"version":3,"file":"format-pem-block2.cjs","names":[],"sources":["../src/format-pem-block.ts"],"sourcesContent":["const PEM_BODY_LINE_LENGTH = 64;\n\nfunction formatCompactPem(pem: string, isPublic: boolean): string | undefined {\n\tconst trimmed = pem.trim();\n\tif ((trimmed.match(/-----BEGIN /g) ?? []).length !== 1) return undefined;\n\n\tconst labelPattern = isPublic ? '[A-Z0-9 ]*PUBLIC KEY' : '[A-Z0-9 ]*PRIVATE KEY|CERTIFICATE';\n\tconst pemMatch = trimmed.match(\n\t\tnew RegExp(`^-----BEGIN (${labelPattern})-----([\\\\s\\\\S]*?)-----END \\\\1-----$`),\n\t);\n\n\tif (!pemMatch) return undefined;\n\n\tconst [, label, body] = pemMatch;\n\tconst normalizedBody = body.replace(/\\\\n/g, '\\n').trim();\n\tconst formattedBody = /\\s/.test(normalizedBody)\n\t\t? normalizedBody.replace(/:\\s+/g, ':').replace(/\\s+/g, '\\n')\n\t\t: (normalizedBody.match(new RegExp(`.{1,${PEM_BODY_LINE_LENGTH}}`, 'g')) ?? []).join('\\n');\n\n\treturn `-----BEGIN ${label}-----\\n${formattedBody}\\n-----END ${label}-----`;\n}\n\n/**\n * Normalize a single PEM-encoded block (private key, public key, or certificate)\n * by collapsing whitespace and wrapping the body at 64 chars. Multi-block PEM\n * chains are returned unchanged.\n *\n * @param pem - The PEM-encoded block to format.\n * @param isPublic - When true, match `PUBLIC KEY` labels instead of the default `PRIVATE KEY` / `CERTIFICATE`.\n * @returns The formatted PEM block.\n */\nexport function formatPemBlock(pem: string, isPublic = false): string {\n\tlet regex = /(PRIVATE KEY|CERTIFICATE)/;\n\tif (isPublic) {\n\t\tregex = /(PUBLIC KEY)/;\n\t}\n\tif (!pem || /\\n/.test(pem)) {\n\t\treturn pem;\n\t}\n\tconst compactPem = formatCompactPem(pem, isPublic);\n\tif (compactPem !== undefined) {\n\t\treturn compactPem;\n\t}\n\n\tlet formattedPem = '';\n\tconst parts = pem.split('-----').filter((item) => item !== '');\n\tparts.forEach((part) => {\n\t\tif (regex.test(part)) {\n\t\t\tformattedPem += `-----${part}-----`;\n\t\t} else {\n\t\t\tconst passRegex = /Proc-Type|DEK-Info/;\n\t\t\tif (passRegex.test(part)) {\n\t\t\t\tpart = part.replace(/:\\s+/g, ':');\n\t\t\t\tformattedPem += part.replace(/\\\\n/g, '\\n').replace(/\\s+/g, '\\n');\n\t\t\t} else {\n\t\t\t\tformattedPem += part.replace(/\\\\n/g, '\\n').replace(/\\s+/g, '\\n');\n\t\t\t}\n\t\t}\n\t});\n\treturn formattedPem;\n}\n"],"mappings":";;AAAA,MAAM,uBAAuB;AAE7B,SAAS,iBAAiB,KAAa,UAAuC;CAC7E,MAAM,UAAU,IAAI,MAAM;AAC1B,MAAK,QAAQ,MAAM,eAAe,IAAI,EAAE,EAAE,WAAW,EAAG,QAAO;CAE/D,MAAM,eAAe,WAAW,yBAAyB;CACzD,MAAM,WAAW,QAAQ,sBACxB,IAAI,OAAO,gBAAgB,aAAa,sCAAsC,CAC9E;AAED,KAAI,CAAC,SAAU,QAAO;CAEtB,MAAM,GAAG,OAAO,QAAQ;CACxB,MAAM,iBAAiB,KAAK,QAAQ,QAAQ,KAAK,CAAC,MAAM;AAKxD,QAAO,cAAc,MAAM,SAJL,KAAK,KAAK,eAAe,GAC5C,eAAe,QAAQ,SAAS,IAAI,CAAC,QAAQ,QAAQ,KAAK,IACzD,eAAe,MAAM,IAAI,OAAO,OAAO,qBAAqB,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,KAAK,CAEzC,aAAa,MAAM;;;;;;;;;;;AAYtE,SAAgB,eAAe,KAAa,WAAW,OAAe;CACrE,IAAI,QAAQ;AACZ,KAAI,SACH,SAAQ;AAET,KAAI,CAAC,OAAO,KAAK,KAAK,IAAI,CACzB,QAAO;CAER,MAAM,aAAa,iBAAiB,KAAK,SAAS;AAClD,KAAI,eAAe,OAClB,QAAO;CAGR,IAAI,eAAe;AAEnB,CADc,IAAI,MAAM,QAAQ,CAAC,QAAQ,SAAS,SAAS,GAAG,CACxD,SAAS,SAAS;AACvB,MAAI,MAAM,KAAK,KAAK,CACnB,iBAAgB,QAAQ,KAAK;WAEX,qBACJ,KAAK,KAAK,EAAE;AACzB,UAAO,KAAK,QAAQ,SAAS,IAAI;AACjC,mBAAgB,KAAK,QAAQ,QAAQ,KAAK,CAAC,QAAQ,QAAQ,KAAK;QAEhE,iBAAgB,KAAK,QAAQ,QAAQ,KAAK,CAAC,QAAQ,QAAQ,KAAK;GAGjE;AACF,QAAO"}
//#region src/format-pem-block.ts
const PEM_BODY_LINE_LENGTH = 64;
function formatCompactPem(pem, isPublic) {
const trimmed = pem.trim();
if ((trimmed.match(/-----BEGIN /g) ?? []).length !== 1) return void 0;
const labelPattern = isPublic ? "[A-Z0-9 ]*PUBLIC KEY" : "[A-Z0-9 ]*PRIVATE KEY|CERTIFICATE";
const pemMatch = trimmed.match(/* @__PURE__ */ new RegExp(`^-----BEGIN (${labelPattern})-----([\\s\\S]*?)-----END \\1-----$`));
if (!pemMatch) return void 0;
const [, label, body] = pemMatch;
const normalizedBody = body.replace(/\\n/g, "\n").trim();
return `-----BEGIN ${label}-----\n${/\s/.test(normalizedBody) ? normalizedBody.replace(/:\s+/g, ":").replace(/\s+/g, "\n") : (normalizedBody.match(new RegExp(`.{1,${PEM_BODY_LINE_LENGTH}}`, "g")) ?? []).join("\n")}\n-----END ${label}-----`;
}
/**
* Normalize a single PEM-encoded block (private key, public key, or certificate)
* by collapsing whitespace and wrapping the body at 64 chars. Multi-block PEM
* chains are returned unchanged.
*
* @param pem - The PEM-encoded block to format.
* @param isPublic - When true, match `PUBLIC KEY` labels instead of the default `PRIVATE KEY` / `CERTIFICATE`.
* @returns The formatted PEM block.
*/
function formatPemBlock(pem, isPublic = false) {
let regex = /(PRIVATE KEY|CERTIFICATE)/;
if (isPublic) regex = /(PUBLIC KEY)/;
if (!pem || /\n/.test(pem)) return pem;
const compactPem = formatCompactPem(pem, isPublic);
if (compactPem !== void 0) return compactPem;
let formattedPem = "";
pem.split("-----").filter((item) => item !== "").forEach((part) => {
if (regex.test(part)) formattedPem += `-----${part}-----`;
else if (/Proc-Type|DEK-Info/.test(part)) {
part = part.replace(/:\s+/g, ":");
formattedPem += part.replace(/\\n/g, "\n").replace(/\s+/g, "\n");
} else formattedPem += part.replace(/\\n/g, "\n").replace(/\s+/g, "\n");
});
return formattedPem;
}
//#endregion
export { formatPemBlock as t };
//# sourceMappingURL=format-pem-block2.mjs.map
{"version":3,"file":"format-pem-block2.mjs","names":[],"sources":["../src/format-pem-block.ts"],"sourcesContent":["const PEM_BODY_LINE_LENGTH = 64;\n\nfunction formatCompactPem(pem: string, isPublic: boolean): string | undefined {\n\tconst trimmed = pem.trim();\n\tif ((trimmed.match(/-----BEGIN /g) ?? []).length !== 1) return undefined;\n\n\tconst labelPattern = isPublic ? '[A-Z0-9 ]*PUBLIC KEY' : '[A-Z0-9 ]*PRIVATE KEY|CERTIFICATE';\n\tconst pemMatch = trimmed.match(\n\t\tnew RegExp(`^-----BEGIN (${labelPattern})-----([\\\\s\\\\S]*?)-----END \\\\1-----$`),\n\t);\n\n\tif (!pemMatch) return undefined;\n\n\tconst [, label, body] = pemMatch;\n\tconst normalizedBody = body.replace(/\\\\n/g, '\\n').trim();\n\tconst formattedBody = /\\s/.test(normalizedBody)\n\t\t? normalizedBody.replace(/:\\s+/g, ':').replace(/\\s+/g, '\\n')\n\t\t: (normalizedBody.match(new RegExp(`.{1,${PEM_BODY_LINE_LENGTH}}`, 'g')) ?? []).join('\\n');\n\n\treturn `-----BEGIN ${label}-----\\n${formattedBody}\\n-----END ${label}-----`;\n}\n\n/**\n * Normalize a single PEM-encoded block (private key, public key, or certificate)\n * by collapsing whitespace and wrapping the body at 64 chars. Multi-block PEM\n * chains are returned unchanged.\n *\n * @param pem - The PEM-encoded block to format.\n * @param isPublic - When true, match `PUBLIC KEY` labels instead of the default `PRIVATE KEY` / `CERTIFICATE`.\n * @returns The formatted PEM block.\n */\nexport function formatPemBlock(pem: string, isPublic = false): string {\n\tlet regex = /(PRIVATE KEY|CERTIFICATE)/;\n\tif (isPublic) {\n\t\tregex = /(PUBLIC KEY)/;\n\t}\n\tif (!pem || /\\n/.test(pem)) {\n\t\treturn pem;\n\t}\n\tconst compactPem = formatCompactPem(pem, isPublic);\n\tif (compactPem !== undefined) {\n\t\treturn compactPem;\n\t}\n\n\tlet formattedPem = '';\n\tconst parts = pem.split('-----').filter((item) => item !== '');\n\tparts.forEach((part) => {\n\t\tif (regex.test(part)) {\n\t\t\tformattedPem += `-----${part}-----`;\n\t\t} else {\n\t\t\tconst passRegex = /Proc-Type|DEK-Info/;\n\t\t\tif (passRegex.test(part)) {\n\t\t\t\tpart = part.replace(/:\\s+/g, ':');\n\t\t\t\tformattedPem += part.replace(/\\\\n/g, '\\n').replace(/\\s+/g, '\\n');\n\t\t\t} else {\n\t\t\t\tformattedPem += part.replace(/\\\\n/g, '\\n').replace(/\\s+/g, '\\n');\n\t\t\t}\n\t\t}\n\t});\n\treturn formattedPem;\n}\n"],"mappings":";AAAA,MAAM,uBAAuB;AAE7B,SAAS,iBAAiB,KAAa,UAAuC;CAC7E,MAAM,UAAU,IAAI,MAAM;AAC1B,MAAK,QAAQ,MAAM,eAAe,IAAI,EAAE,EAAE,WAAW,EAAG,QAAO;CAE/D,MAAM,eAAe,WAAW,yBAAyB;CACzD,MAAM,WAAW,QAAQ,sBACxB,IAAI,OAAO,gBAAgB,aAAa,sCAAsC,CAC9E;AAED,KAAI,CAAC,SAAU,QAAO;CAEtB,MAAM,GAAG,OAAO,QAAQ;CACxB,MAAM,iBAAiB,KAAK,QAAQ,QAAQ,KAAK,CAAC,MAAM;AAKxD,QAAO,cAAc,MAAM,SAJL,KAAK,KAAK,eAAe,GAC5C,eAAe,QAAQ,SAAS,IAAI,CAAC,QAAQ,QAAQ,KAAK,IACzD,eAAe,MAAM,IAAI,OAAO,OAAO,qBAAqB,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,KAAK,CAEzC,aAAa,MAAM;;;;;;;;;;;AAYtE,SAAgB,eAAe,KAAa,WAAW,OAAe;CACrE,IAAI,QAAQ;AACZ,KAAI,SACH,SAAQ;AAET,KAAI,CAAC,OAAO,KAAK,KAAK,IAAI,CACzB,QAAO;CAER,MAAM,aAAa,iBAAiB,KAAK,SAAS;AAClD,KAAI,eAAe,OAClB,QAAO;CAGR,IAAI,eAAe;AAEnB,CADc,IAAI,MAAM,QAAQ,CAAC,QAAQ,SAAS,SAAS,GAAG,CACxD,SAAS,SAAS;AACvB,MAAI,MAAM,KAAK,KAAK,CACnB,iBAAgB,QAAQ,KAAK;WAEX,qBACJ,KAAK,KAAK,EAAE;AACzB,UAAO,KAAK,QAAQ,SAAS,IAAI;AACjC,mBAAgB,KAAK,QAAQ,QAAQ,KAAK,CAAC,QAAQ,QAAQ,KAAK;QAEhE,iBAAgB,KAAK,QAAQ,QAAQ,KAAK,CAAC,QAAQ,QAAQ,KAAK;GAGjE;AACF,QAAO"}