@n8n/utils 1.37.0 → 1.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assert.cjs +11 -2
- package/dist/assert.cjs.map +1 -0
- package/dist/assert.d.cts +5 -2
- package/dist/assert.d.mts +5 -2
- package/dist/assert.mjs +10 -2
- package/dist/assert.mjs.map +1 -0
- package/dist/client-assertion.cjs +49 -0
- package/dist/client-assertion.cjs.map +1 -0
- package/dist/client-assertion.d.cts +12 -0
- package/dist/client-assertion.d.mts +12 -0
- package/dist/client-assertion.mjs +48 -0
- package/dist/client-assertion.mjs.map +1 -0
- package/dist/create-event-queue.cjs +40 -2
- package/dist/create-event-queue.cjs.map +1 -0
- package/dist/create-event-queue.d.cts +7 -2
- package/dist/create-event-queue.d.mts +7 -2
- package/dist/create-event-queue.mjs +39 -2
- package/dist/create-event-queue.mjs.map +1 -0
- package/dist/ensure-error.cjs +15 -0
- package/dist/ensure-error.cjs.map +1 -0
- package/dist/ensure-error.mjs +9 -0
- package/dist/ensure-error.mjs.map +1 -0
- package/dist/errors/ensure-error.cjs +3 -0
- package/dist/errors/ensure-error.d.cts +5 -0
- package/dist/errors/ensure-error.d.mts +5 -0
- package/dist/errors/ensure-error.mjs +3 -0
- package/dist/event-bus.cjs +43 -2
- package/dist/event-bus.cjs.map +1 -0
- package/dist/event-bus.d.cts +14 -2
- package/dist/event-bus.d.mts +14 -2
- package/dist/event-bus.mjs +42 -2
- package/dist/event-bus.mjs.map +1 -0
- package/dist/files/is-windows-file-path.cjs +11 -2
- package/dist/files/is-windows-file-path.cjs.map +1 -0
- package/dist/files/is-windows-file-path.d.cts +5 -2
- package/dist/files/is-windows-file-path.d.mts +5 -2
- package/dist/files/is-windows-file-path.mjs +10 -2
- package/dist/files/is-windows-file-path.mjs.map +1 -0
- package/dist/files/sanitize-filename.cjs +61 -2
- package/dist/files/sanitize-filename.cjs.map +1 -0
- package/dist/files/sanitize-filename.d.cts +5 -2
- package/dist/files/sanitize-filename.d.mts +5 -2
- package/dist/files/sanitize-filename.mjs +60 -2
- package/dist/files/sanitize-filename.mjs.map +1 -0
- package/dist/format-pem-block.d.cts +5 -2
- package/dist/format-pem-block.d.mts +5 -2
- package/dist/generate-nano-id.cjs +28 -2
- package/dist/generate-nano-id.cjs.map +1 -0
- package/dist/generate-nano-id.d.cts +5 -2
- package/dist/generate-nano-id.d.mts +5 -2
- package/dist/generate-nano-id.mjs +28 -2
- package/dist/generate-nano-id.mjs.map +1 -0
- package/dist/get-jwt-expiry.cjs +22 -2
- package/dist/get-jwt-expiry.cjs.map +1 -0
- package/dist/get-jwt-expiry.d.cts +5 -2
- package/dist/get-jwt-expiry.d.mts +5 -2
- package/dist/get-jwt-expiry.mjs +21 -2
- package/dist/get-jwt-expiry.mjs.map +1 -0
- package/dist/is-record.cjs +8 -2
- package/dist/is-record.cjs.map +1 -0
- package/dist/is-record.d.cts +5 -2
- package/dist/is-record.d.mts +5 -2
- package/dist/is-record.mjs +7 -2
- package/dist/is-record.mjs.map +1 -0
- package/dist/number/smart-decimal.cjs +10 -2
- package/dist/number/smart-decimal.cjs.map +1 -0
- package/dist/number/smart-decimal.d.cts +5 -2
- package/dist/number/smart-decimal.d.mts +5 -2
- package/dist/number/smart-decimal.mjs +9 -2
- package/dist/number/smart-decimal.mjs.map +1 -0
- package/dist/placeholder.cjs +80 -7
- package/dist/placeholder.cjs.map +1 -0
- package/dist/placeholder.d.cts +14 -2
- package/dist/placeholder.d.mts +14 -2
- package/dist/placeholder.mjs +74 -2
- package/dist/placeholder.mjs.map +1 -0
- package/dist/promise/deferred-promise.cjs +14 -0
- package/dist/promise/deferred-promise.cjs.map +1 -0
- package/dist/promise/deferred-promise.d.cts +12 -0
- package/dist/promise/deferred-promise.d.mts +12 -0
- package/dist/promise/deferred-promise.mjs +13 -0
- package/dist/promise/deferred-promise.mjs.map +1 -0
- package/dist/result.cjs +30 -0
- package/dist/result.cjs.map +1 -0
- package/dist/result.d.cts +16 -0
- package/dist/result.d.mts +16 -0
- package/dist/result.mjs +28 -0
- package/dist/result.mjs.map +1 -0
- package/dist/retry.cjs +39 -2
- package/dist/retry.cjs.map +1 -0
- package/dist/retry.d.cts +6 -2
- package/dist/retry.d.mts +6 -2
- package/dist/retry.mjs +38 -2
- package/dist/retry.mjs.map +1 -0
- package/dist/scrub-secrets.cjs +44 -4
- package/dist/scrub-secrets.cjs.map +1 -0
- package/dist/scrub-secrets.d.cts +7 -2
- package/dist/scrub-secrets.d.mts +7 -2
- package/dist/scrub-secrets.mjs +41 -2
- package/dist/scrub-secrets.mjs.map +1 -0
- package/dist/search/re-rank-search-results.cjs +19 -2
- package/dist/search/re-rank-search-results.cjs.map +1 -0
- package/dist/search/re-rank-search-results.d.cts +13 -2
- package/dist/search/re-rank-search-results.d.mts +13 -2
- package/dist/search/re-rank-search-results.mjs +18 -2
- package/dist/search/re-rank-search-results.mjs.map +1 -0
- package/dist/search/sublime-search.cjs +182 -3
- package/dist/search/sublime-search.cjs.map +1 -0
- package/dist/search/sublime-search.d.cts +15 -2
- package/dist/search/sublime-search.d.mts +15 -2
- package/dist/search/sublime-search.mjs +180 -2
- package/dist/search/sublime-search.mjs.map +1 -0
- package/dist/sort/sort-by-property.cjs +12 -2
- package/dist/sort/sort-by-property.cjs.map +1 -0
- package/dist/sort/sort-by-property.d.cts +5 -2
- package/dist/sort/sort-by-property.d.mts +5 -2
- package/dist/sort/sort-by-property.mjs +11 -2
- package/dist/sort/sort-by-property.mjs.map +1 -0
- package/dist/string/truncate.cjs +32 -3
- package/dist/string/truncate.cjs.map +1 -0
- package/dist/string/truncate.d.cts +6 -2
- package/dist/string/truncate.d.mts +6 -2
- package/dist/string/truncate.mjs +30 -2
- package/dist/string/truncate.mjs.map +1 -0
- package/dist/types.d.cts +5 -2
- package/dist/types.d.mts +5 -2
- package/package.json +12 -13
- package/dist/assert2.cjs +0 -17
- package/dist/assert2.cjs.map +0 -1
- package/dist/assert2.d.cts +0 -5
- package/dist/assert2.d.mts +0 -5
- package/dist/assert2.mjs +0 -11
- package/dist/assert2.mjs.map +0 -1
- package/dist/create-event-queue2.cjs +0 -46
- package/dist/create-event-queue2.cjs.map +0 -1
- package/dist/create-event-queue2.d.cts +0 -7
- package/dist/create-event-queue2.d.mts +0 -7
- package/dist/create-event-queue2.mjs +0 -40
- package/dist/create-event-queue2.mjs.map +0 -1
- package/dist/event-bus2.cjs +0 -49
- package/dist/event-bus2.cjs.map +0 -1
- package/dist/event-bus2.d.cts +0 -14
- package/dist/event-bus2.d.mts +0 -14
- package/dist/event-bus2.mjs +0 -43
- package/dist/event-bus2.mjs.map +0 -1
- package/dist/format-pem-block2.d.cts +0 -5
- package/dist/format-pem-block2.d.mts +0 -5
- package/dist/generate-nano-id2.cjs +0 -34
- package/dist/generate-nano-id2.cjs.map +0 -1
- package/dist/generate-nano-id2.d.cts +0 -5
- package/dist/generate-nano-id2.d.mts +0 -5
- package/dist/generate-nano-id2.mjs +0 -29
- package/dist/generate-nano-id2.mjs.map +0 -1
- package/dist/get-jwt-expiry2.cjs +0 -28
- package/dist/get-jwt-expiry2.cjs.map +0 -1
- package/dist/get-jwt-expiry2.d.cts +0 -5
- package/dist/get-jwt-expiry2.d.mts +0 -5
- package/dist/get-jwt-expiry2.mjs +0 -22
- package/dist/get-jwt-expiry2.mjs.map +0 -1
- package/dist/index.cjs +0 -44
- package/dist/index.d.cts +0 -19
- package/dist/index.d.mts +0 -19
- package/dist/index.mjs +0 -19
- package/dist/is-record2.cjs +0 -14
- package/dist/is-record2.cjs.map +0 -1
- package/dist/is-record2.d.cts +0 -5
- package/dist/is-record2.d.mts +0 -5
- package/dist/is-record2.mjs +0 -8
- package/dist/is-record2.mjs.map +0 -1
- package/dist/is-windows-file-path.cjs +0 -17
- package/dist/is-windows-file-path.cjs.map +0 -1
- package/dist/is-windows-file-path.d.cts +0 -5
- package/dist/is-windows-file-path.d.mts +0 -5
- package/dist/is-windows-file-path.mjs +0 -11
- package/dist/is-windows-file-path.mjs.map +0 -1
- package/dist/placeholder2.cjs +0 -111
- package/dist/placeholder2.cjs.map +0 -1
- package/dist/placeholder2.d.cts +0 -14
- package/dist/placeholder2.d.mts +0 -14
- package/dist/placeholder2.mjs +0 -75
- package/dist/placeholder2.mjs.map +0 -1
- package/dist/re-rank-search-results.cjs +0 -25
- package/dist/re-rank-search-results.cjs.map +0 -1
- package/dist/re-rank-search-results.d.cts +0 -13
- package/dist/re-rank-search-results.d.mts +0 -13
- package/dist/re-rank-search-results.mjs +0 -19
- package/dist/re-rank-search-results.mjs.map +0 -1
- package/dist/retry2.cjs +0 -45
- package/dist/retry2.cjs.map +0 -1
- package/dist/retry2.d.cts +0 -6
- package/dist/retry2.d.mts +0 -6
- package/dist/retry2.mjs +0 -39
- package/dist/retry2.mjs.map +0 -1
- package/dist/sanitize-filename.cjs +0 -67
- package/dist/sanitize-filename.cjs.map +0 -1
- package/dist/sanitize-filename.d.cts +0 -5
- package/dist/sanitize-filename.d.mts +0 -5
- package/dist/sanitize-filename.mjs +0 -61
- package/dist/sanitize-filename.mjs.map +0 -1
- package/dist/scrub-secrets2.cjs +0 -59
- package/dist/scrub-secrets2.cjs.map +0 -1
- package/dist/scrub-secrets2.d.cts +0 -7
- package/dist/scrub-secrets2.d.mts +0 -7
- package/dist/scrub-secrets2.mjs +0 -41
- package/dist/scrub-secrets2.mjs.map +0 -1
- package/dist/smart-decimal.cjs +0 -16
- package/dist/smart-decimal.cjs.map +0 -1
- package/dist/smart-decimal.d.cts +0 -5
- package/dist/smart-decimal.d.mts +0 -5
- package/dist/smart-decimal.mjs +0 -10
- package/dist/smart-decimal.mjs.map +0 -1
- package/dist/sort-by-property.cjs +0 -18
- package/dist/sort-by-property.cjs.map +0 -1
- package/dist/sort-by-property.d.cts +0 -5
- package/dist/sort-by-property.d.mts +0 -5
- package/dist/sort-by-property.mjs +0 -12
- package/dist/sort-by-property.mjs.map +0 -1
- package/dist/sublime-search.cjs +0 -193
- package/dist/sublime-search.cjs.map +0 -1
- package/dist/sublime-search.d.cts +0 -15
- package/dist/sublime-search.d.mts +0 -15
- package/dist/sublime-search.mjs +0 -181
- package/dist/sublime-search.mjs.map +0 -1
- package/dist/truncate.cjs +0 -43
- package/dist/truncate.cjs.map +0 -1
- package/dist/truncate.d.cts +0 -6
- package/dist/truncate.d.mts +0 -6
- package/dist/truncate.mjs +0 -31
- package/dist/truncate.mjs.map +0 -1
- package/dist/types2.d.cts +0 -5
- package/dist/types2.d.mts +0 -5
package/dist/assert.cjs
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
-
const require_assert = require('./assert2.cjs');
|
|
2
1
|
|
|
3
|
-
|
|
2
|
+
//#region src/assert.ts
|
|
3
|
+
/**
|
|
4
|
+
* Asserts given condition
|
|
5
|
+
*/
|
|
6
|
+
function assert(condition, message) {
|
|
7
|
+
if (!condition) throw new Error(message ?? "Assertion failed");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
exports.assert = assert;
|
|
12
|
+
//# sourceMappingURL=assert.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
package/dist/assert.d.cts
CHANGED
package/dist/assert.d.mts
CHANGED
package/dist/assert.mjs
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/assert.ts
|
|
2
|
+
/**
|
|
3
|
+
* Asserts given condition
|
|
4
|
+
*/
|
|
5
|
+
function assert(condition, message) {
|
|
6
|
+
if (!condition) throw new Error(message ?? "Assertion failed");
|
|
7
|
+
}
|
|
2
8
|
|
|
3
|
-
|
|
9
|
+
//#endregion
|
|
10
|
+
export { assert };
|
|
11
|
+
//# sourceMappingURL=assert.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const require_format_pem_block = require('./format-pem-block2.cjs');
|
|
2
|
+
let node_crypto = require("node:crypto");
|
|
3
|
+
|
|
4
|
+
//#region src/client-assertion.ts
|
|
5
|
+
const CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
|
|
6
|
+
const ASSERTION_TTL_SECONDS = 300;
|
|
7
|
+
function base64url(input) {
|
|
8
|
+
return Buffer.from(input).toString("base64url");
|
|
9
|
+
}
|
|
10
|
+
function certificateThumbprint(certificate) {
|
|
11
|
+
let parsed;
|
|
12
|
+
try {
|
|
13
|
+
parsed = new node_crypto.X509Certificate(require_format_pem_block.formatPemBlock(certificate));
|
|
14
|
+
} catch (error) {
|
|
15
|
+
throw new Error("The Certificate field must contain a PEM certificate (-----BEGIN CERTIFICATE-----).", { cause: error });
|
|
16
|
+
}
|
|
17
|
+
return Buffer.from(parsed.fingerprint.replace(/:/g, ""), "hex").toString("base64url");
|
|
18
|
+
}
|
|
19
|
+
function buildClientAssertion(options) {
|
|
20
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
21
|
+
const header = {
|
|
22
|
+
alg: "RS256",
|
|
23
|
+
typ: "JWT",
|
|
24
|
+
x5t: certificateThumbprint(options.certificate)
|
|
25
|
+
};
|
|
26
|
+
const payload = {
|
|
27
|
+
aud: options.accessTokenUri,
|
|
28
|
+
iss: options.clientId,
|
|
29
|
+
sub: options.clientId,
|
|
30
|
+
jti: (0, node_crypto.randomUUID)(),
|
|
31
|
+
iat: now,
|
|
32
|
+
nbf: now,
|
|
33
|
+
exp: now + ASSERTION_TTL_SECONDS
|
|
34
|
+
};
|
|
35
|
+
let privateKey;
|
|
36
|
+
try {
|
|
37
|
+
privateKey = (0, node_crypto.createPrivateKey)(require_format_pem_block.formatPemBlock(options.privateKey));
|
|
38
|
+
} catch (error) {
|
|
39
|
+
throw new Error("The Private Key field must contain a PEM private key (-----BEGIN PRIVATE KEY-----).", { cause: error });
|
|
40
|
+
}
|
|
41
|
+
if (privateKey.asymmetricKeyType !== "rsa") throw new Error("Certificate authentication requires an RSA private key");
|
|
42
|
+
const signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}`;
|
|
43
|
+
return `${signingInput}.${base64url((0, node_crypto.createSign)("RSA-SHA256").update(signingInput).sign(privateKey))}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
47
|
+
exports.CLIENT_ASSERTION_TYPE = CLIENT_ASSERTION_TYPE;
|
|
48
|
+
exports.buildClientAssertion = buildClientAssertion;
|
|
49
|
+
//# sourceMappingURL=client-assertion.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/client-assertion.d.ts
|
|
2
|
+
declare const CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
|
|
3
|
+
interface BuildClientAssertionOptions {
|
|
4
|
+
clientId: string;
|
|
5
|
+
accessTokenUri: string;
|
|
6
|
+
privateKey: string;
|
|
7
|
+
certificate: string;
|
|
8
|
+
}
|
|
9
|
+
declare function buildClientAssertion(options: BuildClientAssertionOptions): string;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { BuildClientAssertionOptions, CLIENT_ASSERTION_TYPE, buildClientAssertion };
|
|
12
|
+
//# sourceMappingURL=client-assertion.d.cts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/client-assertion.d.ts
|
|
2
|
+
declare const CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
|
|
3
|
+
interface BuildClientAssertionOptions {
|
|
4
|
+
clientId: string;
|
|
5
|
+
accessTokenUri: string;
|
|
6
|
+
privateKey: string;
|
|
7
|
+
certificate: string;
|
|
8
|
+
}
|
|
9
|
+
declare function buildClientAssertion(options: BuildClientAssertionOptions): string;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { BuildClientAssertionOptions, CLIENT_ASSERTION_TYPE, buildClientAssertion };
|
|
12
|
+
//# sourceMappingURL=client-assertion.d.mts.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { t as formatPemBlock } from "./format-pem-block2.mjs";
|
|
2
|
+
import { X509Certificate, createPrivateKey, createSign, randomUUID } from "node:crypto";
|
|
3
|
+
|
|
4
|
+
//#region src/client-assertion.ts
|
|
5
|
+
const CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
|
|
6
|
+
const ASSERTION_TTL_SECONDS = 300;
|
|
7
|
+
function base64url(input) {
|
|
8
|
+
return Buffer.from(input).toString("base64url");
|
|
9
|
+
}
|
|
10
|
+
function certificateThumbprint(certificate) {
|
|
11
|
+
let parsed;
|
|
12
|
+
try {
|
|
13
|
+
parsed = new X509Certificate(formatPemBlock(certificate));
|
|
14
|
+
} catch (error) {
|
|
15
|
+
throw new Error("The Certificate field must contain a PEM certificate (-----BEGIN CERTIFICATE-----).", { cause: error });
|
|
16
|
+
}
|
|
17
|
+
return Buffer.from(parsed.fingerprint.replace(/:/g, ""), "hex").toString("base64url");
|
|
18
|
+
}
|
|
19
|
+
function buildClientAssertion(options) {
|
|
20
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
21
|
+
const header = {
|
|
22
|
+
alg: "RS256",
|
|
23
|
+
typ: "JWT",
|
|
24
|
+
x5t: certificateThumbprint(options.certificate)
|
|
25
|
+
};
|
|
26
|
+
const payload = {
|
|
27
|
+
aud: options.accessTokenUri,
|
|
28
|
+
iss: options.clientId,
|
|
29
|
+
sub: options.clientId,
|
|
30
|
+
jti: randomUUID(),
|
|
31
|
+
iat: now,
|
|
32
|
+
nbf: now,
|
|
33
|
+
exp: now + ASSERTION_TTL_SECONDS
|
|
34
|
+
};
|
|
35
|
+
let privateKey;
|
|
36
|
+
try {
|
|
37
|
+
privateKey = createPrivateKey(formatPemBlock(options.privateKey));
|
|
38
|
+
} catch (error) {
|
|
39
|
+
throw new Error("The Private Key field must contain a PEM private key (-----BEGIN PRIVATE KEY-----).", { cause: error });
|
|
40
|
+
}
|
|
41
|
+
if (privateKey.asymmetricKeyType !== "rsa") throw new Error("Certificate authentication requires an RSA private key");
|
|
42
|
+
const signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}`;
|
|
43
|
+
return `${signingInput}.${base64url(createSign("RSA-SHA256").update(signingInput).sign(privateKey))}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
47
|
+
export { CLIENT_ASSERTION_TYPE, buildClientAssertion };
|
|
48
|
+
//# sourceMappingURL=client-assertion.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -1,3 +1,41 @@
|
|
|
1
|
-
const require_create_event_queue = require('./create-event-queue2.cjs');
|
|
2
1
|
|
|
3
|
-
|
|
2
|
+
//#region src/create-event-queue.ts
|
|
3
|
+
/**
|
|
4
|
+
* Create an event queue that processes events sequentially.
|
|
5
|
+
*
|
|
6
|
+
* @param processEvent - Async function that processes a single event.
|
|
7
|
+
* @returns A function that enqueues events for processing.
|
|
8
|
+
*/
|
|
9
|
+
function createEventQueue(processEvent) {
|
|
10
|
+
const queue = [];
|
|
11
|
+
let processing = false;
|
|
12
|
+
/**
|
|
13
|
+
* Process the next event in the queue (if not already processing).
|
|
14
|
+
*/
|
|
15
|
+
async function processNext() {
|
|
16
|
+
if (processing || queue.length === 0) return;
|
|
17
|
+
processing = true;
|
|
18
|
+
const currentEvent = queue.shift();
|
|
19
|
+
if (currentEvent !== void 0) try {
|
|
20
|
+
await processEvent(currentEvent);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error("Error processing event:", error);
|
|
23
|
+
}
|
|
24
|
+
processing = false;
|
|
25
|
+
await processNext();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Enqueue an event and trigger processing.
|
|
29
|
+
*
|
|
30
|
+
* @param event - The event to enqueue.
|
|
31
|
+
*/
|
|
32
|
+
function enqueue(event) {
|
|
33
|
+
queue.push(event);
|
|
34
|
+
processNext();
|
|
35
|
+
}
|
|
36
|
+
return { enqueue };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
exports.createEventQueue = createEventQueue;
|
|
41
|
+
//# sourceMappingURL=create-event-queue.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//#region src/create-event-queue.d.ts
|
|
2
|
+
declare function createEventQueue<T>(processEvent: (event: T) => Promise<void>): {
|
|
3
|
+
enqueue: (event: T) => void;
|
|
4
|
+
};
|
|
5
|
+
//#endregion
|
|
6
|
+
export { createEventQueue };
|
|
7
|
+
//# sourceMappingURL=create-event-queue.d.cts.map
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//#region src/create-event-queue.d.ts
|
|
2
|
+
declare function createEventQueue<T>(processEvent: (event: T) => Promise<void>): {
|
|
3
|
+
enqueue: (event: T) => void;
|
|
4
|
+
};
|
|
5
|
+
//#endregion
|
|
6
|
+
export { createEventQueue };
|
|
7
|
+
//# sourceMappingURL=create-event-queue.d.mts.map
|
|
@@ -1,3 +1,40 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/create-event-queue.ts
|
|
2
|
+
/**
|
|
3
|
+
* Create an event queue that processes events sequentially.
|
|
4
|
+
*
|
|
5
|
+
* @param processEvent - Async function that processes a single event.
|
|
6
|
+
* @returns A function that enqueues events for processing.
|
|
7
|
+
*/
|
|
8
|
+
function createEventQueue(processEvent) {
|
|
9
|
+
const queue = [];
|
|
10
|
+
let processing = false;
|
|
11
|
+
/**
|
|
12
|
+
* Process the next event in the queue (if not already processing).
|
|
13
|
+
*/
|
|
14
|
+
async function processNext() {
|
|
15
|
+
if (processing || queue.length === 0) return;
|
|
16
|
+
processing = true;
|
|
17
|
+
const currentEvent = queue.shift();
|
|
18
|
+
if (currentEvent !== void 0) try {
|
|
19
|
+
await processEvent(currentEvent);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
console.error("Error processing event:", error);
|
|
22
|
+
}
|
|
23
|
+
processing = false;
|
|
24
|
+
await processNext();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Enqueue an event and trigger processing.
|
|
28
|
+
*
|
|
29
|
+
* @param event - The event to enqueue.
|
|
30
|
+
*/
|
|
31
|
+
function enqueue(event) {
|
|
32
|
+
queue.push(event);
|
|
33
|
+
processNext();
|
|
34
|
+
}
|
|
35
|
+
return { enqueue };
|
|
36
|
+
}
|
|
2
37
|
|
|
3
|
-
|
|
38
|
+
//#endregion
|
|
39
|
+
export { createEventQueue };
|
|
40
|
+
//# sourceMappingURL=create-event-queue.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/errors/ensure-error.ts
|
|
3
|
+
/** Ensures `error` is an `Error */
|
|
4
|
+
function ensureError(error) {
|
|
5
|
+
return error instanceof Error ? error : new Error("Error that was not an instance of Error was thrown", { cause: error });
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
//#endregion
|
|
9
|
+
Object.defineProperty(exports, 'ensureError', {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function () {
|
|
12
|
+
return ensureError;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
//# sourceMappingURL=ensure-error.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/errors/ensure-error.ts
|
|
2
|
+
/** Ensures `error` is an `Error */
|
|
3
|
+
function ensureError(error) {
|
|
4
|
+
return error instanceof Error ? error : new Error("Error that was not an instance of Error was thrown", { cause: error });
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
//#endregion
|
|
8
|
+
export { ensureError as t };
|
|
9
|
+
//# sourceMappingURL=ensure-error.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"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"}
|
package/dist/event-bus.cjs
CHANGED
|
@@ -1,3 +1,44 @@
|
|
|
1
|
-
const require_event_bus = require('./event-bus2.cjs');
|
|
2
1
|
|
|
3
|
-
|
|
2
|
+
//#region src/event-bus.ts
|
|
3
|
+
/**
|
|
4
|
+
* Creates an event bus with the given listener map.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const eventBus = createEventBus<{
|
|
9
|
+
* 'user-logged-in': { username: string };
|
|
10
|
+
* 'user-logged-out': never;
|
|
11
|
+
* }>();
|
|
12
|
+
*/
|
|
13
|
+
function createEventBus() {
|
|
14
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
15
|
+
return {
|
|
16
|
+
on(eventName, fn) {
|
|
17
|
+
let eventFns = handlers.get(eventName);
|
|
18
|
+
if (!eventFns) eventFns = [fn];
|
|
19
|
+
else eventFns.push(fn);
|
|
20
|
+
handlers.set(eventName, eventFns);
|
|
21
|
+
},
|
|
22
|
+
once(eventName, fn) {
|
|
23
|
+
const handler = (payload) => {
|
|
24
|
+
this.off(eventName, handler);
|
|
25
|
+
fn(payload);
|
|
26
|
+
};
|
|
27
|
+
this.on(eventName, handler);
|
|
28
|
+
},
|
|
29
|
+
off(eventName, fn) {
|
|
30
|
+
const eventFns = handlers.get(eventName);
|
|
31
|
+
if (eventFns) eventFns.splice(eventFns.indexOf(fn) >>> 0, 1);
|
|
32
|
+
},
|
|
33
|
+
emit(eventName, event) {
|
|
34
|
+
const eventFns = handlers.get(eventName);
|
|
35
|
+
if (eventFns) eventFns.slice().forEach((handler) => {
|
|
36
|
+
handler(event);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
exports.createEventBus = createEventBus;
|
|
44
|
+
//# sourceMappingURL=event-bus.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
package/dist/event-bus.d.cts
CHANGED
|
@@ -1,2 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//#region src/event-bus.d.ts
|
|
2
|
+
type CallbackFn = (...args: any[]) => any;
|
|
3
|
+
type Payloads<ListenerMap> = { [E in keyof ListenerMap]: unknown };
|
|
4
|
+
type Listener<Payload> = (payload: Payload) => void;
|
|
5
|
+
interface EventBus<ListenerMap extends Payloads<ListenerMap> = Record<string, any>> {
|
|
6
|
+
on<EventName extends keyof ListenerMap & string>(eventName: EventName, fn: Listener<ListenerMap[EventName]>): void;
|
|
7
|
+
once<EventName extends keyof ListenerMap & string>(eventName: EventName, fn: Listener<ListenerMap[EventName]>): void;
|
|
8
|
+
off<EventName extends keyof ListenerMap & string>(eventName: EventName, fn: Listener<ListenerMap[EventName]>): void;
|
|
9
|
+
emit<EventName extends keyof ListenerMap & string>(eventName: EventName, event?: ListenerMap[EventName]): void;
|
|
10
|
+
}
|
|
11
|
+
declare function createEventBus<ListenerMap extends Payloads<ListenerMap> = Record<string, any>>(): EventBus<ListenerMap>;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { CallbackFn, EventBus, createEventBus };
|
|
14
|
+
//# sourceMappingURL=event-bus.d.cts.map
|
package/dist/event-bus.d.mts
CHANGED
|
@@ -1,2 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//#region src/event-bus.d.ts
|
|
2
|
+
type CallbackFn = (...args: any[]) => any;
|
|
3
|
+
type Payloads<ListenerMap> = { [E in keyof ListenerMap]: unknown };
|
|
4
|
+
type Listener<Payload> = (payload: Payload) => void;
|
|
5
|
+
interface EventBus<ListenerMap extends Payloads<ListenerMap> = Record<string, any>> {
|
|
6
|
+
on<EventName extends keyof ListenerMap & string>(eventName: EventName, fn: Listener<ListenerMap[EventName]>): void;
|
|
7
|
+
once<EventName extends keyof ListenerMap & string>(eventName: EventName, fn: Listener<ListenerMap[EventName]>): void;
|
|
8
|
+
off<EventName extends keyof ListenerMap & string>(eventName: EventName, fn: Listener<ListenerMap[EventName]>): void;
|
|
9
|
+
emit<EventName extends keyof ListenerMap & string>(eventName: EventName, event?: ListenerMap[EventName]): void;
|
|
10
|
+
}
|
|
11
|
+
declare function createEventBus<ListenerMap extends Payloads<ListenerMap> = Record<string, any>>(): EventBus<ListenerMap>;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { CallbackFn, EventBus, createEventBus };
|
|
14
|
+
//# sourceMappingURL=event-bus.d.mts.map
|
package/dist/event-bus.mjs
CHANGED
|
@@ -1,3 +1,43 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/event-bus.ts
|
|
2
|
+
/**
|
|
3
|
+
* Creates an event bus with the given listener map.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* const eventBus = createEventBus<{
|
|
8
|
+
* 'user-logged-in': { username: string };
|
|
9
|
+
* 'user-logged-out': never;
|
|
10
|
+
* }>();
|
|
11
|
+
*/
|
|
12
|
+
function createEventBus() {
|
|
13
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
14
|
+
return {
|
|
15
|
+
on(eventName, fn) {
|
|
16
|
+
let eventFns = handlers.get(eventName);
|
|
17
|
+
if (!eventFns) eventFns = [fn];
|
|
18
|
+
else eventFns.push(fn);
|
|
19
|
+
handlers.set(eventName, eventFns);
|
|
20
|
+
},
|
|
21
|
+
once(eventName, fn) {
|
|
22
|
+
const handler = (payload) => {
|
|
23
|
+
this.off(eventName, handler);
|
|
24
|
+
fn(payload);
|
|
25
|
+
};
|
|
26
|
+
this.on(eventName, handler);
|
|
27
|
+
},
|
|
28
|
+
off(eventName, fn) {
|
|
29
|
+
const eventFns = handlers.get(eventName);
|
|
30
|
+
if (eventFns) eventFns.splice(eventFns.indexOf(fn) >>> 0, 1);
|
|
31
|
+
},
|
|
32
|
+
emit(eventName, event) {
|
|
33
|
+
const eventFns = handlers.get(eventName);
|
|
34
|
+
if (eventFns) eventFns.slice().forEach((handler) => {
|
|
35
|
+
handler(event);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
2
40
|
|
|
3
|
-
|
|
41
|
+
//#endregion
|
|
42
|
+
export { createEventBus };
|
|
43
|
+
//# sourceMappingURL=event-bus.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
-
const require_is_windows_file_path = require('../is-windows-file-path.cjs');
|
|
2
1
|
|
|
3
|
-
|
|
2
|
+
//#region src/files/is-windows-file-path.ts
|
|
3
|
+
/**
|
|
4
|
+
* Fast check if file path starts with a windows drive letter, e.g. 'C:/' or 'C:\\'
|
|
5
|
+
*/
|
|
6
|
+
function isWindowsFilePath(str) {
|
|
7
|
+
return /^[a-zA-Z]:[\\/]/.test(str);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
exports.isWindowsFilePath = isWindowsFilePath;
|
|
12
|
+
//# sourceMappingURL=is-windows-file-path.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//#region src/files/is-windows-file-path.d.ts
|
|
2
|
+
declare function isWindowsFilePath(str: string): boolean;
|
|
3
|
+
//#endregion
|
|
4
|
+
export { isWindowsFilePath };
|
|
5
|
+
//# sourceMappingURL=is-windows-file-path.d.cts.map
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//#region src/files/is-windows-file-path.d.ts
|
|
2
|
+
declare function isWindowsFilePath(str: string): boolean;
|
|
3
|
+
//#endregion
|
|
4
|
+
export { isWindowsFilePath };
|
|
5
|
+
//# sourceMappingURL=is-windows-file-path.d.mts.map
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/files/is-windows-file-path.ts
|
|
2
|
+
/**
|
|
3
|
+
* Fast check if file path starts with a windows drive letter, e.g. 'C:/' or 'C:\\'
|
|
4
|
+
*/
|
|
5
|
+
function isWindowsFilePath(str) {
|
|
6
|
+
return /^[a-zA-Z]:[\\/]/.test(str);
|
|
7
|
+
}
|
|
2
8
|
|
|
3
|
-
|
|
9
|
+
//#endregion
|
|
10
|
+
export { isWindowsFilePath };
|
|
11
|
+
//# sourceMappingURL=is-windows-file-path.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|