From 5f6277f9f318c6a475b13308cd8feb15aaf39a87 Mon Sep 17 00:00:00 2001 From: EmberIsReal Date: Sun, 2 Nov 2025 09:05:22 +0300 Subject: [PATCH 01/13] chore: fix typo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ffcf18f..848ff26 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ The library is type-safe, supports immutable flag operations, and provides human npm install bitwise-flag # npm yarn add bitwise-flag # yarn pnpm add bitwise-flag # pnpm -ban add bitwise-flag # bun +bun add bitwise-flag # bun ``` --- From e501c83f1aeeab0b3a672bbf755eab3237a8b369 Mon Sep 17 00:00:00 2001 From: EmberIsReal Date: Sun, 2 Nov 2025 10:52:58 +0300 Subject: [PATCH 02/13] tests: add unit tests --- lib/Flag.test.ts | 192 +++++++++++++++++++++++++++++++++++++++ lib/FlagRegistry.test.ts | 155 +++++++++++++++++++++++++++++++ package.json | 3 +- tsconfig.json | 5 +- 4 files changed, 353 insertions(+), 2 deletions(-) create mode 100644 lib/Flag.test.ts create mode 100644 lib/FlagRegistry.test.ts diff --git a/lib/Flag.test.ts b/lib/Flag.test.ts new file mode 100644 index 0000000..51c9440 --- /dev/null +++ b/lib/Flag.test.ts @@ -0,0 +1,192 @@ +import { describe, expect, it } from "bun:test"; + +import { Flag } from "./Flag"; +import { FlagsRegistry } from "./FlagRegistry"; + +describe("Flag", () => { + const flagKeys = [ + "__FLAG_A__", // 1 bit + "__FLAG_B__", // 2 bits + "__FLAG_C__", // 4 bits + "__FLAG_D__", // 8 bits + ] as const; + const registry = FlagsRegistry.from(...flagKeys); + + describe("constructor()", () => { + it("should create flag with valid value", () => { + // __FLAG_A__ | __FLAG_D__ = 1 | 8 = 9 + const flag = new Flag(registry, 9n); + + expect(flag.value).toBe(9n); + }); + + it("should throw error for negative value", () => { + expect(() => { + new Flag(registry, -1n); + }).toThrow("Flag value cannot be negative: -1"); + }); + + it("should throw error for value with unknown flags", () => { + // only defined flags or theirs combinations + + expect(() => { + new Flag(registry, 16n); + }).toThrow("Flag value contains unknown flags"); + }); + }); + + describe("isEmpty()", () => { + it("should return true for empty flag", () => { + const emptyFlag = registry.empty(); + + expect(emptyFlag.isEmpty()).toBeTrue(); + }); + + it("should return false for non-empty flag", () => { + const nonEmptyFlag = registry.combine("__FLAG_A__", "__FLAG_C__"); + + expect(nonEmptyFlag.isEmpty()).toBeFalse(); + }); + }); + + describe("has()", () => { + const flagAD = registry.combine("__FLAG_A__", "__FLAG_D__"); + + it("should return true for set flags", () => { + expect(flagAD.has("__FLAG_A__")).toBeTrue(); + expect(flagAD.has("__FLAG_D__")).toBeTrue(); + }); + + it("should return false for unset flags", () => { + expect(flagAD.has("__FLAG_B__")).toBeFalse(); + expect(flagAD.has("__FLAG_C__")).toBeFalse(); + }); + + it("should return false for non-existent flag", () => { + // @ts-expect-error this flag is not exist + expect(flagAD.has("__NON_EXISTENT_FLAG__")).toBeFalse(); + }); + }); + + describe("add()", () => { + const flagB = registry.combine("__FLAG_B__"); + + it("should add flag to existing combination", () => { + const flagAB = flagB.add("__FLAG_A__"); + + expect(flagAB.value).toBe(3n); + expect(flagAB.has("__FLAG_A__")).toBeTrue(); + expect(flagAB.has("__FLAG_B__")).toBeTrue(); + }); + + it("should return same instance if flag already exists", () => { + const sameFlag = flagB.add("__FLAG_B__"); + + expect(flagB).toBe(sameFlag); + }); + + it("should throw error when adding non-existent flag", () => { + expect(() => { + // @ts-expect-error this flag is not exist + flagB.add("__NON_EXISTENT_FLAG__"); + }).toThrow("Flag with key __NON_EXISTENT_FLAG__ is not found."); + }); + + it("should be immutable - original flag unchanged", () => { + const originalValue = flagB.value; + flagB.add("__FLAG_C__"); + + expect(flagB.value).toBe(originalValue); + expect(flagB.has("__FLAG_C__")).toBeFalse(); + }); + }); + + describe("remove()", () => { + const flagBC = registry.combine("__FLAG_B__", "__FLAG_C__"); + + it("should remove flag from combination", () => { + const flagC = flagBC.remove("__FLAG_B__"); + + expect(flagC.value).toBe(4n); + expect(flagC.has("__FLAG_C__")).toBeTrue(); + expect(flagC.has("__FLAG_B__")).toBeFalse(); + }); + + it("should return same instance if flag not present", () => { + const sameFlag = flagBC.remove("__FLAG_D__"); + + expect(flagBC).toBe(sameFlag); + }); + + it("should throw error when removing non-existent flag", () => { + expect(() => { + // @ts-expect-error this flag is not exist + flagBC.remove("__NON_EXISTENT_FLAG__"); + }).toThrow("Flag with key __NON_EXISTENT_FLAG__ is not found."); + }); + + it("should be immutable - original flag unchanged", () => { + const originalValue = flagBC.value; + flagBC.remove("__FLAG_B__"); + + expect(flagBC.value).toBe(originalValue); + expect(flagBC.has("__FLAG_B__")).toBeTrue(); + }); + }); + + describe("toString()", () => { + it("should return correct string representation for empty flag", () => { + const emptyFlag = registry.empty(); + + expect(emptyFlag.toString()).toBe("Flag(EMPTY_FLAG: 0)"); + }); + + it("should return correct string representation for single flag", () => { + const flagA = registry.combine("__FLAG_A__"); + + expect(flagA.toString()).toBe("Flag([__FLAG_A__]: 1)"); + }); + + it("should return correct string representation for multiple flags", () => { + const flagAB = registry.combine("__FLAG_A__", "__FLAG_B__"); + + expect(flagAB.toString()).toBe("Flag([__FLAG_A__+__FLAG_B__]: 3)"); + }); + }); + + describe("alias", () => { + it("should return EMPTY_FLAG for empty flag", () => { + const emptyFlag = registry.empty(); + + expect(emptyFlag.alias).toBe("EMPTY_FLAG"); + }); + + it("should return formatted string for single flag", () => { + const flagA = registry.combine("__FLAG_A__"); + + expect(flagA.alias).toBe("[__FLAG_A__]"); + }); + + it("should return formatted string for multiple flags", () => { + const flagBD = registry.combine("__FLAG_B__", "__FLAG_D__"); + + expect(flagBD.alias).toBe("[__FLAG_B__+__FLAG_D__]"); + }); + + it("should cache the alias value", () => { + const flagACD = registry.combine( + "__FLAG_A__", + "__FLAG_C__", + "__FLAG_D__" + ); + + // @ts-expect-error access to a private field, before caching + expect(flagACD._alias).toBeNull(); + + flagACD.alias; + + // @ts-expect-error access to a private field, after caching + expect(flagACD._alias).toBe(flagACD.alias); + }); + }); +}); diff --git a/lib/FlagRegistry.test.ts b/lib/FlagRegistry.test.ts new file mode 100644 index 0000000..e780c63 --- /dev/null +++ b/lib/FlagRegistry.test.ts @@ -0,0 +1,155 @@ +import { beforeEach, describe, expect, it } from "bun:test"; + +import { FlagsRegistry } from "./FlagRegistry"; + +describe("FlagRegistry", () => { + let registry: FlagsRegistry; + + const flagKeys = [ + "__FLAG_A__", // 1 bit + "__FLAG_B__", // 2 bits + "__FLAG_C__", // 4 bits + "__FLAG_D__", // 8 bits + ] as const; + + type FlagKeysArray = typeof flagKeys; + type FlagKeysType = FlagKeysArray[number]; + + beforeEach(() => { + registry = FlagsRegistry.from(...flagKeys); + }); + + it("should handle many flags without bit overflow", () => { + const manyFlags = Array.from({ length: 100 }, (_, i) => `__FLAG_${i}__`); + const registry = FlagsRegistry.from(...manyFlags); + + // should be able to combine all flags + const allFlags = registry.combine(...manyFlags); + + // each flag should be set + manyFlags.forEach((flag) => { + expect(allFlags.has(flag)).toBe(true); + }); + }); + + it("should work with empty registry", () => { + const emptyRegistry = FlagsRegistry.from(); + + expect(Array.from(emptyRegistry.keys())).toEqual([]); + expect(emptyRegistry.empty().isEmpty()).toBe(true); + + // combining no flags should work + const emptyFlag = emptyRegistry.combine(); + expect(emptyFlag.isEmpty()).toBe(true); + }); + + describe("static from()", () => { + it("should create registry with unique flags", () => { + const registry = FlagsRegistry.from("A", "B", "C", "A"); + const keys = Array.from(registry.keys()); + + expect(keys).toEqual(["A", "B", "C"]); + }); + + it("should assign correct bit values to flags", () => { + const registry = FlagsRegistry.from( + "__FLAG_1__", + "__FLAG_2__", + "__FLAG_3__" + ); + + expect(registry.get("__FLAG_1__")).toBe(1n); + expect(registry.get("__FLAG_2__")).toBe(2n); + expect(registry.get("__FLAG_3__")).toBe(4n); + }); + }); + + describe("get()", () => { + it("should return correct value for existing flag", () => { + expect(registry.get("__FLAG_A__")).toBe(1n); + expect(registry.get("__FLAG_B__")).toBe(2n); + expect(registry.get("__FLAG_C__")).toBe(4n); + expect(registry.get("__FLAG_D__")).toBe(8n); + }); + + it("should return undefined for non-existent flag", () => { + // @ts-expect-error this flag is not exist + expect(registry.get("__NON_EXISTENT_FLAG__")).toBeUndefined(); + }); + + it("should combine flags correctly", () => { + const emptyFlag = registry.combine(); + const flagA = registry.combine("__FLAG_A__"); + const flagBC = registry.combine("__FLAG_B__", "__FLAG_C__"); + const flagDAB = registry.combine( + "__FLAG_D__", + "__FLAG_A__", + "__FLAG_B__" + ); + const flagABCD = registry.combine( + "__FLAG_A__", + "__FLAG_B__", + "__FLAG_C__", + "__FLAG_D__" + ); + + expect(emptyFlag.value).toBe(0n); + expect(flagA.value).toBe(1n); + expect(flagBC.value).toBe(6n); + expect(flagDAB.value).toBe(11n); + expect(flagABCD.value).toBe(15n); + }); + + it("should throw error when combining non-existent flag", () => { + expect(() => { + registry.combine( + "__FLAG_A__", + "__FLAG_B__", + // @ts-expect-error this flag is not exist + "__NON_EXISTENT_FLAG__", + "__FLAG_D__" + ); + }).toThrow("Flag with key __NON_EXISTENT_FLAG__ is not found."); + }); + }); + + describe("empty()", () => { + it("should return empty flag", () => { + const emptyFlag = registry.empty(); + + expect(emptyFlag.value).toBe(0n); + expect(emptyFlag.isEmpty()).toBe(true); + }); + }); + + describe("iterators", () => { + describe("keys()", () => { + it("should return all flag names", () => { + const keys = Array.from(registry.keys()) as unknown as FlagKeysArray; + + expect(keys).toEqual(flagKeys); + }); + }); + + describe("values()", () => { + it("should return all flag values", () => { + const values = Array.from(registry.values()); + + expect(values).toEqual([1n, 2n, 4n, 8n]); + }); + }); + + describe("entries()", () => { + it("should return all key-value pairs", () => { + const entries = Array.from(registry.entries()); + + expect(entries).toEqual([ + ["__FLAG_A__", 1n], + ["__FLAG_B__", 2n], + ["__FLAG_C__", 4n], + ["__FLAG_D__", 8n], + ]); + }); + }); + }); +}); diff --git a/package.json b/package.json index 9270f61..e3eb3d4 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ }, "author": "Ember", "scripts": { - "build": "bunup" + "build": "bunup", + "tests": "bun test" }, "devDependencies": { "@types/bun": "^1.3.1", diff --git a/tsconfig.json b/tsconfig.json index 1192eb8..bd24074 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,5 +22,8 @@ "noUnusedLocals": false, "noUnusedParameters": false, "noPropertyAccessFromIndexSignature": false, - } + }, + "exclude": [ + "./lib/**/*.test.ts" + ] } \ No newline at end of file From b285de091023154943a43584204c20052d6014b1 Mon Sep 17 00:00:00 2001 From: EmberIsReal Date: Sun, 2 Nov 2025 11:01:38 +0300 Subject: [PATCH 03/13] fix(Flag): change checking flag presence order --- lib/Flag.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Flag.ts b/lib/Flag.ts index 553eb10..1131e8b 100644 --- a/lib/Flag.ts +++ b/lib/Flag.ts @@ -51,14 +51,14 @@ export class Flag implements IFlag { } remove(flagName: TFlags): IFlag { - if (!this.has(flagName)) return this; - const value = this.context.get(flagName); if (!value) { throw new Error(`Flag with key ${String(flagName)} is not found.`); } + if (!this.has(flagName)) return this; + const extractedValue = this.value & ~value; return new Flag(this.context, extractedValue); From 7caf8de95921e827d10e2b3ada9ff63a6b00456a Mon Sep 17 00:00:00 2001 From: EmberIsReal Date: Sun, 2 Nov 2025 11:19:45 +0300 Subject: [PATCH 04/13] fix(FlagRegistry): change combine's return type --- lib/FlagRegistry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FlagRegistry.ts b/lib/FlagRegistry.ts index ee51e5c..184ff7c 100644 --- a/lib/FlagRegistry.ts +++ b/lib/FlagRegistry.ts @@ -39,7 +39,7 @@ export class FlagsRegistry return new Flag(this, 0n); } - combine(...flagKeys: TFlags[]): Flag { + combine(...flagKeys: TFlags[]): IFlag { const value = flagKeys.reduce((acc, key) => { const flagValue = this.get(key); From e643db70c87c8f0ca88f456de423bce0b493042a Mon Sep 17 00:00:00 2001 From: EmberIsReal Date: Sun, 2 Nov 2025 11:20:06 +0300 Subject: [PATCH 05/13] fix(IFlag): add alias property --- lib/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/types.ts b/lib/types.ts index b89f804..0bd30c5 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -2,6 +2,7 @@ export type FlagKey = string; export interface IFlag { readonly value: bigint; + readonly alias: string; isEmpty(): boolean; has(flagName: TFlags): boolean; From 4600b08d96bed40cec8098f14ba3f602ba7c8e93 Mon Sep 17 00:00:00 2001 From: EmberIsReal Date: Sun, 2 Nov 2025 11:21:24 +0300 Subject: [PATCH 06/13] chore: upgrade to 1.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e3eb3d4..91e0d65 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bitwise-flag", - "version": "1.0.0", + "version": "1.0.1", "type": "module", "license": "MIT", "files": [ From 2386fe88ff9c6b29d61e3b0764758ea87380c3ed Mon Sep 17 00:00:00 2001 From: EmberIsReal Date: Sun, 2 Nov 2025 14:56:08 +0300 Subject: [PATCH 07/13] feat(Flag): add bulk operations --- README.md | 4 ++-- lib/Flag.test.ts | 35 +++++++++++++++++++++++------------ lib/Flag.ts | 36 ++++++++++++++++++++++-------------- lib/types.ts | 4 ++-- 4 files changed, 49 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 848ff26..0f81c87 100644 --- a/README.md +++ b/README.md @@ -106,8 +106,8 @@ Represents a bitwise combination of flags from a registry. All operations are im |--------|-------------|------------|---------|--------| | `isEmpty()` | Checks if no flags are set. | None. | `boolean` | None. | | `has(flagName: TFlags)` | Tests if a specific flag is set in this combination. | `flagName`: The flag key. | `boolean` | None. | -| `add(flagName: TFlags)` | Adds a flag to the combination (idempotent if already set). Returns a new `Flag`. | `flagName`: The flag key. | `Flag` | `Error` if the key is not registered. | -| `remove(flagName: TFlags)` | Removes a flag from the combination (idempotent if not set). Returns a new `Flag`. | `flagName`: The flag key. | `Flag` | `Error` if the key is not registered. | +| `add(...flagNames: TFlags[])` | Adds flags to the combination (idempotent if already set). Returns `IFlag`. | `flagNames`: The flag keys. | `IFlag` | `Error` if the key is not registered. | +| `remove(...flagNames: TFlags[])` | Removes flags from the combination (idempotent if not set). Returns `IFlag`. | `flagNames`: The flag keys. | `IFlag` | `Error` if the key is not registered. | | `toString()` | Returns a string representation including the alias and raw value. | None. | `string` | None. | | `alias` (getter) | Computed human-readable alias (e.g., `"[READ+WRITE]"` or `"EMPTY_FLAG"`) | None. | `string` | None. | diff --git a/lib/Flag.test.ts b/lib/Flag.test.ts index 51c9440..43dcee6 100644 --- a/lib/Flag.test.ts +++ b/lib/Flag.test.ts @@ -79,6 +79,16 @@ describe("Flag", () => { expect(flagAB.has("__FLAG_B__")).toBeTrue(); }); + it("should add multiple flags to existing combination", () => { + const flagBCD = flagB.add("__FLAG_C__", "__FLAG_D__"); + + // __FLAG_B__ | __FLAG_C__ | __FLAG_D__ = 2 | 4 | 8 = 14 + expect(flagBCD.value).toBe(14n); + expect(flagBCD.has("__FLAG_B__")).toBeTrue(); + expect(flagBCD.has("__FLAG_C__")).toBeTrue(); + expect(flagBCD.has("__FLAG_D__")).toBeTrue(); + }); + it("should return same instance if flag already exists", () => { const sameFlag = flagB.add("__FLAG_B__"); @@ -102,35 +112,36 @@ describe("Flag", () => { }); describe("remove()", () => { - const flagBC = registry.combine("__FLAG_B__", "__FLAG_C__"); + const flagBCD = registry.combine("__FLAG_B__", "__FLAG_C__", "__FLAG_D__"); it("should remove flag from combination", () => { - const flagC = flagBC.remove("__FLAG_B__"); + const flagCD = flagBCD.remove("__FLAG_B__"); - expect(flagC.value).toBe(4n); - expect(flagC.has("__FLAG_C__")).toBeTrue(); - expect(flagC.has("__FLAG_B__")).toBeFalse(); + // __FLAG_C__ | __FLAG_D__ = 4 | 8 = 12 + expect(flagCD.value).toBe(12n); + expect(flagCD.has("__FLAG_C__")).toBeTrue(); + expect(flagCD.has("__FLAG_B__")).toBeFalse(); }); it("should return same instance if flag not present", () => { - const sameFlag = flagBC.remove("__FLAG_D__"); + const sameFlag = flagBCD.remove("__FLAG_A__"); - expect(flagBC).toBe(sameFlag); + expect(flagBCD).toBe(sameFlag); }); it("should throw error when removing non-existent flag", () => { expect(() => { // @ts-expect-error this flag is not exist - flagBC.remove("__NON_EXISTENT_FLAG__"); + flagBCD.remove("__NON_EXISTENT_FLAG__"); }).toThrow("Flag with key __NON_EXISTENT_FLAG__ is not found."); }); it("should be immutable - original flag unchanged", () => { - const originalValue = flagBC.value; - flagBC.remove("__FLAG_B__"); + const originalValue = flagBCD.value; + flagBCD.remove("__FLAG_B__"); - expect(flagBC.value).toBe(originalValue); - expect(flagBC.has("__FLAG_B__")).toBeTrue(); + expect(flagBCD.value).toBe(originalValue); + expect(flagBCD.has("__FLAG_B__")).toBeTrue(); }); }); diff --git a/lib/Flag.ts b/lib/Flag.ts index 1131e8b..32f872a 100644 --- a/lib/Flag.ts +++ b/lib/Flag.ts @@ -36,30 +36,38 @@ export class Flag implements IFlag { return !!(this.value & value); } - add(flagName: TFlags): IFlag { - if (this.has(flagName)) return this; + add(...flagNames: TFlags[]): IFlag { + const combinedValue = flagNames.reduce((acc, name) => { + if (this.has(name)) return acc; - const value = this.context.get(flagName); + const value = this.context.get(name); - if (!value) { - throw new Error(`Flag with key ${String(flagName)} is not found.`); - } + if (!value) { + throw new Error(`Flag with key ${String(name)} is not found.`); + } + + return acc | value; + }, this.value); - const combinedValue = this.value | value; + if (combinedValue === this.value) return this; return new Flag(this.context, combinedValue); } - remove(flagName: TFlags): IFlag { - const value = this.context.get(flagName); + remove(...flagNames: TFlags[]): IFlag { + const extractedValue = flagNames.reduce((acc, name) => { + const value = this.context.get(name); - if (!value) { - throw new Error(`Flag with key ${String(flagName)} is not found.`); - } + if (!value) { + throw new Error(`Flag with key ${String(name)} is not found.`); + } + + if (!this.has(name)) return acc; - if (!this.has(flagName)) return this; + return acc & ~value; + }, this.value); - const extractedValue = this.value & ~value; + if (extractedValue === this.value) return this; return new Flag(this.context, extractedValue); } diff --git a/lib/types.ts b/lib/types.ts index 0bd30c5..f711b7a 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -7,8 +7,8 @@ export interface IFlag { isEmpty(): boolean; has(flagName: TFlags): boolean; - add(flagName: TFlags): IFlag; - remove(flagName: TFlags): IFlag; + add(...flagNames: TFlags[]): IFlag; + remove(...flagNames: TFlags[]): IFlag; toString(): string; } From 47b2f6435f0ee727a8fca518fdfc92e5139e4c41 Mon Sep 17 00:00:00 2001 From: EmberIsReal Date: Mon, 3 Nov 2025 11:43:52 +0300 Subject: [PATCH 08/13] feat(FlagRegistry): add parse method --- lib/FlagRegistry.test.ts | 64 ++++++++++++++++++++++++++++++++++++++++ lib/FlagRegistry.ts | 17 +++++++++++ lib/types.ts | 4 +++ 3 files changed, 85 insertions(+) diff --git a/lib/FlagRegistry.test.ts b/lib/FlagRegistry.test.ts index e780c63..389d52d 100644 --- a/lib/FlagRegistry.test.ts +++ b/lib/FlagRegistry.test.ts @@ -122,6 +122,70 @@ describe("FlagRegistry", () => { }); }); + describe("parse", () => { + it("should parse number values", () => { + const flagA = registry.parse(1); // decimal + const flagCD = registry.parse(0b1100); // binary + const flagBC = registry.parse(0x6); // hex + const flagBCD = registry.parse(0o16); // octal + + expect(flagA.has("__FLAG_A__")).toBeTrue(); + + expect(flagCD.has("__FLAG_C__")).toBeTrue(); + expect(flagCD.has("__FLAG_D__")).toBeTrue(); + + expect(flagBC.has("__FLAG_B__")).toBeTrue(); + expect(flagBC.has("__FLAG_C__")).toBeTrue(); + + expect(flagBCD.has("__FLAG_B__")).toBeTrue(); + expect(flagBCD.has("__FLAG_C__")).toBeTrue(); + expect(flagBCD.has("__FLAG_D__")).toBeTrue(); + }); + + it("should parse bigint values", () => { + const flagA = registry.parse(1n); // decimal + const flagCD = registry.parse(0b1100n); // binary + const flagBC = registry.parse(0x6n); // hex + const flagBCD = registry.parse(0o16n); // octal + + expect(flagA.has("__FLAG_A__")).toBeTrue(); + + expect(flagCD.has("__FLAG_C__")).toBeTrue(); + expect(flagCD.has("__FLAG_D__")).toBeTrue(); + + expect(flagBC.has("__FLAG_B__")).toBeTrue(); + expect(flagBC.has("__FLAG_C__")).toBeTrue(); + + expect(flagBCD.has("__FLAG_B__")).toBeTrue(); + expect(flagBCD.has("__FLAG_C__")).toBeTrue(); + expect(flagBCD.has("__FLAG_D__")).toBeTrue(); + }); + + it("should parse string values", () => { + const flagA = registry.parse("1", 10); // decimal + const flagCD = registry.parse("1100", 2); // binary + const flagBC = registry.parse("6", 16); // hex + const flagBCD = registry.parse("16", 8); // octal + const flagACD = registry.parse("111", 3); // any other radix from 2 to 32 (ex.: ternary) + + expect(flagA.has("__FLAG_A__")).toBeTrue(); + + expect(flagCD.has("__FLAG_C__")).toBeTrue(); + expect(flagCD.has("__FLAG_D__")).toBeTrue(); + + expect(flagBC.has("__FLAG_B__")).toBeTrue(); + expect(flagBC.has("__FLAG_C__")).toBeTrue(); + + expect(flagBCD.has("__FLAG_B__")).toBeTrue(); + expect(flagBCD.has("__FLAG_C__")).toBeTrue(); + expect(flagBCD.has("__FLAG_D__")).toBeTrue(); + + expect(flagACD.has("__FLAG_A__")).toBeTrue(); + expect(flagACD.has("__FLAG_C__")).toBeTrue(); + expect(flagACD.has("__FLAG_D__")).toBeTrue(); + }); + }); + describe("iterators", () => { describe("keys()", () => { it("should return all flag names", () => { diff --git a/lib/FlagRegistry.ts b/lib/FlagRegistry.ts index 184ff7c..433d367 100644 --- a/lib/FlagRegistry.ts +++ b/lib/FlagRegistry.ts @@ -39,6 +39,23 @@ export class FlagsRegistry return new Flag(this, 0n); } + parse(value: number): IFlag; + parse(value: bigint): IFlag; + parse(value: string, radix?: number): IFlag; + parse(value: string | number | bigint, radix?: number): IFlag { + if (typeof value === "bigint") return new Flag(this, value); + + if (typeof value === "number") return new Flag(this, BigInt(value)); + + const parsedValue = parseInt(value, radix); + + if (isNaN(parsedValue)) { + throw new Error(`Cannot parse value ${value} with radix ${radix ?? 10}.`); + } + + return new Flag(this, BigInt(parsedValue)); + } + combine(...flagKeys: TFlags[]): IFlag { const value = flagKeys.reduce((acc, key) => { const flagValue = this.get(key); diff --git a/lib/types.ts b/lib/types.ts index f711b7a..1c39b4f 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -22,4 +22,8 @@ export interface IFlagsRegistry { entries(): MapIterator<[TFlags, bigint]>; empty(): IFlag; + + parse(value: number): IFlag; + parse(value: bigint): IFlag; + parse(value: string, radix?: number): IFlag; } From 94083218f0dae614673b11ddb59023a2871900af Mon Sep 17 00:00:00 2001 From: EmberIsReal Date: Mon, 3 Nov 2025 12:53:24 +0300 Subject: [PATCH 09/13] chore: update README.md for 1.1.0 --- README.md | 80 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 0f81c87..42443eb 100644 --- a/README.md +++ b/README.md @@ -16,39 +16,48 @@ bun add bitwise-flag # bun ``` --- + ### How to use + ```ts import { FlagsRegistry } from "bitwise-flag"; // create a flag registry const permissionRegistry = FlagsRegistry.from("READ", "WRITE", "EXECUTE"); -// create an empty flag +// create an empty flag const noPermissions = permissionRegistry.empty(); console.log(noPermissions.isEmpty()); // true console.log(noPermissions.toString()); // Flag(EMPTY_FLAG: 0) // combine flags to create a new flag -const readWrite = permissionsRegistry.combine('READ', 'WRITE'); +const readWrite = permissionsRegistry.combine("READ", "WRITE"); console.log(readWrite.toString()); // Flag([READ+WRITE]: 3) +// parse numeric values to create flags +const fromNumber = permissionRegistry.parse(5); // READ + EXECUTE +const fromHex = permissionRegistry.parse("3", 16); // READ + WRITE +const fromBinary = permissionRegistry.parse("101", 2); // READ + EXECUTE + // check for flags -const userPermissions = permissionsRegistry.combine('READ', 'EXECUTE'); +const userPermissions = permissionsRegistry.combine("READ", "EXECUTE"); -console.log(userPermissions.has('READ')); // true -console.log(userPermissions.has('WRITE')); // false -console.log(userPermissions.has('EXECUTE')); // true +console.log(userPermissions.has("READ")); // true +console.log(userPermissions.has("WRITE")); // false +console.log(userPermissions.has("EXECUTE")); // true ``` ### Flag opeations + Flag's instances are immutable. Thats means all operations return new instances. For example: + ```ts const readWrite = permissionsRegistry.combine("READ", "WRITE"); // add execute flag const fullPermissions = readWrite.add("EXECUTE"); console.log(readWrite.has("EXECUTE")); // false -console.log(fullPermissions.has("EXECUTE")) // true +console.log(fullPermissions.has("EXECUTE")); // true // remove read flag const read = readWrite.remove("WRITE"); @@ -56,7 +65,6 @@ console.log(readWrite.has("WRITE")); // true console.log(read.has("WRITE")); // false ``` - ## API Reference ### Class: `FlagsRegistry` @@ -65,29 +73,32 @@ Manages a collection of flag keys and their corresponding bitmask values. Use th #### Static Methods -| Method | Description | Parameters | Returns | Throws | -|--------|-------------|------------|---------|--------| -| `FlagsRegistry.from(...flagKeys: TFlags[])` | Creates a new registry instance from an array of flag keys. Automatically deduplicates keys and assigns sequential bit positions (starting from bit 0). | `flagKeys`: Array of string keys. | `FlagsRegistry` | None. | +| Method | Description | Parameters | Returns | Throws | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ----------------------- | ------ | +| `FlagsRegistry.from(...flagKeys: TFlags[])` | Creates a new registry instance from an array of flag keys. Automatically deduplicates keys and assigns sequential bit positions (starting from bit 0). | `flagKeys`: Array of string keys. | `FlagsRegistry` | None. | **Example:** + ```typescript -const registry = FlagsRegistry.from('READ', 'WRITE', 'READ'); // Deduplicates 'READ' +const registry = FlagsRegistry.from("READ", "WRITE", "READ"); // Deduplicates 'READ' ``` #### Instance Methods -| Method | Description | Parameters | Returns | Throws | -|--------|-------------|------------|---------|--------| -| `keys()` | Returns an iterator over all flag keys. | None. | `MapIterator` | None. | -| `values()` | Returns an iterator over all bit values. | None. | `MapIterator` | None. | -| `entries()` | Returns an iterator over key-bit pairs. | None. | `MapIterator<[TFlags, bigint]>` | None. | -| `get(flagName: TFlags)` | Retrieves the bitmask value for a specific flag key. | `flagName`: The flag key. | `bigint \| undefined` | None. | -| `empty()` | Creates an empty flag instance (value `0n`). | None. | `Flag` | None. | -| `combine(...flagKeys: TFlags[])` | Combines the specified flag keys into a new `Flag` instance by bitwise OR-ing their values. | `flagKeys`: Array of flag keys to combine. | `Flag` | `Error` if any key is not registered. | +| Method | Description | Parameters | Returns | Throws | +| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------- | ---------------------------------------- | +| `keys()` | Returns an iterator over all flag keys. | None. | `MapIterator` | None. | +| `values()` | Returns an iterator over all bit values. | None. | `MapIterator` | None. | +| `entries()` | Returns an iterator over key-bit pairs. | None. | `MapIterator<[TFlags, bigint]>` | None. | +| `get(flagName: TFlags)` | Retrieves the bitmask value for a specific flag key. | `flagName`: The flag key. | `bigint \| undefined` | None. | +| `empty()` | Creates an empty flag instance (value `0n`). | None. | `IFlag` | None. | +| `parse(value: string \| number \| bigint, radix?: string)` | Creates a flag from a value. If value is string, do **NOT** use prefixes like: `0x` or `0b`, like in JS. | `value` - source value; `radix` - base of value. Use if `value` is string. By default, equals to 10. | `IFlag` | `Error` if string value can't be parsed. | +| `combine(...flagKeys: TFlags[])` | Combines the specified flag keys into a new `Flag` instance by bitwise OR-ing their values. | `flagKeys`: Array of flag keys to combine. | `IFlag` | `Error` if any key is not registered. | **Example:** + ```typescript -const combined = registry.combine('READ', 'WRITE'); // Value: 3n (0b11) +const combined = registry.combine("READ", "WRITE"); // Value: 3n (0b11) ``` ### Class: `Flag` @@ -96,26 +107,27 @@ Represents a bitwise combination of flags from a registry. All operations are im #### Properties -| Property | Description | Type | -|----------|-------------|------| -| `value` | The raw `BigInt` representing the combined bitmask. Read-only. | `bigint` | +| Property | Description | Type | +| -------- | -------------------------------------------------------------- | -------- | +| `value` | The raw `BigInt` representing the combined bitmask. Read-only. | `bigint` | #### Methods -| Method | Description | Parameters | Returns | Throws | -|--------|-------------|------------|---------|--------| -| `isEmpty()` | Checks if no flags are set. | None. | `boolean` | None. | -| `has(flagName: TFlags)` | Tests if a specific flag is set in this combination. | `flagName`: The flag key. | `boolean` | None. | -| `add(...flagNames: TFlags[])` | Adds flags to the combination (idempotent if already set). Returns `IFlag`. | `flagNames`: The flag keys. | `IFlag` | `Error` if the key is not registered. | +| Method | Description | Parameters | Returns | Throws | +| -------------------------------- | ---------------------------------------------------------------------------- | --------------------------- | --------------- | ------------------------------------- | +| `isEmpty()` | Checks if no flags are set. | None. | `boolean` | None. | +| `has(flagName: TFlags)` | Tests if a specific flag is set in this combination. | `flagName`: The flag key. | `boolean` | None. | +| `add(...flagNames: TFlags[])` | Adds flags to the combination (idempotent if already set). Returns `IFlag`. | `flagNames`: The flag keys. | `IFlag` | `Error` if the key is not registered. | | `remove(...flagNames: TFlags[])` | Removes flags from the combination (idempotent if not set). Returns `IFlag`. | `flagNames`: The flag keys. | `IFlag` | `Error` if the key is not registered. | -| `toString()` | Returns a string representation including the alias and raw value. | None. | `string` | None. | -| `alias` (getter) | Computed human-readable alias (e.g., `"[READ+WRITE]"` or `"EMPTY_FLAG"`) | None. | `string` | None. | +| `toString()` | Returns a string representation including the alias and raw value. | None. | `string` | None. | +| `alias` (getter) | Computed human-readable alias (e.g., `"[READ+WRITE]"` or `"EMPTY_FLAG"`) | None. | `string` | None. | **Validation Note:** The constructor (internal) validates that the value only uses known bits from the registry and is non-negative. Unknown bits or negative values throw an `Error`. **Example:** + ```typescript -const flag = registry.combine('READ'); -console.log(flag.has('READ')); // true -console.log(flag.add('WRITE').alias); // "[READ+WRITE]" +const flag = registry.combine("READ"); +console.log(flag.has("READ")); // true +console.log(flag.add("WRITE").alias); // "[READ+WRITE]" ``` From 615f0fc158b44799d0e057115cd5b51edd25c974 Mon Sep 17 00:00:00 2001 From: EmberIsReal Date: Mon, 3 Nov 2025 12:54:39 +0300 Subject: [PATCH 10/13] chore: set repository --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index 91e0d65..1b62063 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,10 @@ "./LICENSE.md", "dist" ], + "repository": { + "type": "git", + "url": "https://github.com/ThatsEmbarrassing/bitwise-flag" + }, "main": "./dist/index.cjs", "module": "./dist/index.js", "types": "./dist/index.d.ts", From d1ed4ecd57f32f34e3a6ae23477928a4b6d25ab5 Mon Sep 17 00:00:00 2001 From: EmberIsReal Date: Mon, 3 Nov 2025 12:55:02 +0300 Subject: [PATCH 11/13] chore: upgrade to 1.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b62063..61a7a4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bitwise-flag", - "version": "1.0.1", + "version": "1.1.0", "type": "module", "license": "MIT", "files": [ From b260d2562d3ab46487c7157098ff4d559c657c6b Mon Sep 17 00:00:00 2001 From: EmberIsReal Date: Mon, 3 Nov 2025 14:12:40 +0300 Subject: [PATCH 12/13] style: add eslint --- bun.lock | 246 +++++++++++++++++++++++++++++++++++++++++++++- eslint.config.mjs | 28 ++++++ package.json | 12 ++- 3 files changed, 282 insertions(+), 4 deletions(-) create mode 100644 eslint.config.mjs diff --git a/bun.lock b/bun.lock index 5cf0bcd..50307c2 100644 --- a/bun.lock +++ b/bun.lock @@ -4,11 +4,15 @@ "": { "name": "sandbox", "devDependencies": { + "@eslint/js": "^9.39.0", + "@stylistic/eslint-plugin": "^5.5.0", "@types/bun": "^1.3.1", "bunup": "^0.15.13", + "eslint": "^9.39.0", + "typescript-eslint": "^8.46.2", }, "peerDependencies": { - "typescript": "^5.0.0", + "typescript": "^5.9.3", }, }, }, @@ -31,8 +35,40 @@ "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], + + "@eslint/config-array": ["@eslint/config-array@0.21.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="], + + "@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="], + + "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], + + "@eslint/js": ["@eslint/js@9.39.0", "", {}, "sha512-BIhe0sW91JGPiaF1mOuPy5v8NflqfjIcDNpC+LbW9f609WVRX1rArrhi6Z2ymvrAry9jw+5POTj4t2t62o8Bmw=="], + + "@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="], + + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], + + "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.7", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" } }, "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw=="], + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + "@oxc-minify/binding-android-arm64": ["@oxc-minify/binding-android-arm64@0.93.0", "", { "os": "android", "cpu": "arm64" }, "sha512-N3j/JoK4hXwQbnyOJoEltM8MEkddWV3XtfYimO6jsMjr5R6QdauKaSVeQHO/lSezB7SFkrMPqr6X7tBfghHiXA=="], "@oxc-minify/binding-darwin-arm64": ["@oxc-minify/binding-darwin-arm64@0.93.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kLJJe7uBE+a9ql6eLGAtJ1g1LuEXi4aHbsiu342wGe+wRieSPi/Cx0aeDsQjdetwK5mqJWjWS2FO/n03jiw+IQ=="], @@ -131,26 +167,156 @@ "@oxc-transform/binding-win32-x64-msvc": ["@oxc-transform/binding-win32-x64-msvc@0.93.0", "", { "os": "win32", "cpu": "x64" }, "sha512-6QN3DEaEw3eWioWEFRgNsTvYq8czYSnpkjB2za+/WdLN0g5FzOl2ZEfNiPrBWIPnSmjUmDWtWVWcSjwY7fX5/Q=="], + "@stylistic/eslint-plugin": ["@stylistic/eslint-plugin@5.5.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.0", "@typescript-eslint/types": "^8.46.1", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "estraverse": "^5.3.0", "picomatch": "^4.0.3" }, "peerDependencies": { "eslint": ">=9.0.0" } }, "sha512-IeZF+8H0ns6prg4VrkhgL+yrvDXWDH2cKchrbh80ejG9dQgZWp10epHMbgRuQvgchLII/lfh6Xn3lu6+6L86Hw=="], + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], "@types/bun": ["@types/bun@1.3.1", "", { "dependencies": { "bun-types": "1.3.1" } }, "sha512-4jNMk2/K9YJtfqwoAa28c8wK+T7nvJFOjxI4h/7sORWcypRNxBpr+TPNaCfVWq70tLCJsqoFwcf0oI0JU/fvMQ=="], + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + "@types/node": ["@types/node@24.9.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA=="], "@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.46.2", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/type-utils": "8.46.2", "@typescript-eslint/utils": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.46.2", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.46.2", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/types": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g=="], + + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.46.2", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.46.2", "@typescript-eslint/types": "^8.46.2", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg=="], + + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.46.2", "", { "dependencies": { "@typescript-eslint/types": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2" } }, "sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA=="], + + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.46.2", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag=="], + + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.46.2", "", { "dependencies": { "@typescript-eslint/types": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2", "@typescript-eslint/utils": "8.46.2", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA=="], + + "@typescript-eslint/types": ["@typescript-eslint/types@8.46.2", "", {}, "sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ=="], + + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.46.2", "", { "dependencies": { "@typescript-eslint/project-service": "8.46.2", "@typescript-eslint/tsconfig-utils": "8.46.2", "@typescript-eslint/types": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ=="], + + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.46.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/types": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.46.2", "", { "dependencies": { "@typescript-eslint/types": "8.46.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w=="], + + "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + "bun-types": ["bun-types@1.3.1", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="], "bunup": ["bunup@0.15.13", "", { "dependencies": { "@bunup/dts": "^0.14.36", "@bunup/shared": "0.15.7", "chokidar": "^4.0.3", "coffi": "^0.1.37", "lightningcss": "^1.30.2", "picocolors": "^1.1.1", "tinyexec": "^1.0.1", "tree-kill": "^1.2.2", "zlye": "^0.4.4" }, "peerDependencies": { "typescript": "latest" }, "optionalPeers": ["typescript"], "bin": { "bunup": "dist/cli/index.js" } }, "sha512-i3kHvNkkT4aELlDoFVrwVwwJaKYqrWSbU+MikkRuH8W5A9bhGBtp1beeJ0Umxleas2u3rMiK+cfFbo5ouYs8eA=="], + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], "coffi": ["coffi@0.1.37", "", { "dependencies": { "strip-json-comments": "^5.0.3" } }, "sha512-ewO5Xis7sw7g54yI/3lJ/nNV90Er4ZnENeDORZjrs58T70MmwKFLZgevraNCz+RmB4KDKsYT1ui1wDB36iPWqQ=="], + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@9.39.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.39.0", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-iy2GE3MHrYTL5lrCtMZ0X1KLEKKUjmK0kzwcnefhR66txcEmXZD2YWgR5GNdcEwkNx3a0siYkSvl0vIC+Svjmg=="], + + "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], + + "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], + + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + + "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + "lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="], "lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="], @@ -175,32 +341,110 @@ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="], + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + + "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + "oxc-minify": ["oxc-minify@0.93.0", "", { "optionalDependencies": { "@oxc-minify/binding-android-arm64": "0.93.0", "@oxc-minify/binding-darwin-arm64": "0.93.0", "@oxc-minify/binding-darwin-x64": "0.93.0", "@oxc-minify/binding-freebsd-x64": "0.93.0", "@oxc-minify/binding-linux-arm-gnueabihf": "0.93.0", "@oxc-minify/binding-linux-arm-musleabihf": "0.93.0", "@oxc-minify/binding-linux-arm64-gnu": "0.93.0", "@oxc-minify/binding-linux-arm64-musl": "0.93.0", "@oxc-minify/binding-linux-riscv64-gnu": "0.93.0", "@oxc-minify/binding-linux-s390x-gnu": "0.93.0", "@oxc-minify/binding-linux-x64-gnu": "0.93.0", "@oxc-minify/binding-linux-x64-musl": "0.93.0", "@oxc-minify/binding-wasm32-wasi": "0.93.0", "@oxc-minify/binding-win32-arm64-msvc": "0.93.0", "@oxc-minify/binding-win32-x64-msvc": "0.93.0" } }, "sha512-pwMjOGN/I+cfLVkSmECcVHROKwECNVAXCT5h/29S4f0aArIUh3CQnix1yYy7MTQ3yThNuGANjjE9jWJyT43Vbw=="], "oxc-resolver": ["oxc-resolver@11.12.0", "", { "optionalDependencies": { "@oxc-resolver/binding-android-arm-eabi": "11.12.0", "@oxc-resolver/binding-android-arm64": "11.12.0", "@oxc-resolver/binding-darwin-arm64": "11.12.0", "@oxc-resolver/binding-darwin-x64": "11.12.0", "@oxc-resolver/binding-freebsd-x64": "11.12.0", "@oxc-resolver/binding-linux-arm-gnueabihf": "11.12.0", "@oxc-resolver/binding-linux-arm-musleabihf": "11.12.0", "@oxc-resolver/binding-linux-arm64-gnu": "11.12.0", "@oxc-resolver/binding-linux-arm64-musl": "11.12.0", "@oxc-resolver/binding-linux-ppc64-gnu": "11.12.0", "@oxc-resolver/binding-linux-riscv64-gnu": "11.12.0", "@oxc-resolver/binding-linux-riscv64-musl": "11.12.0", "@oxc-resolver/binding-linux-s390x-gnu": "11.12.0", "@oxc-resolver/binding-linux-x64-gnu": "11.12.0", "@oxc-resolver/binding-linux-x64-musl": "11.12.0", "@oxc-resolver/binding-wasm32-wasi": "11.12.0", "@oxc-resolver/binding-win32-arm64-msvc": "11.12.0", "@oxc-resolver/binding-win32-ia32-msvc": "11.12.0", "@oxc-resolver/binding-win32-x64-msvc": "11.12.0" } }, "sha512-zmS2q2txiB+hS2u0aiIwmvITIJN8c8ThlWoWB762Wx5nUw8WBlttp0rzt8nnuP1cGIq9YJ7sGxfsgokm+SQk5Q=="], "oxc-transform": ["oxc-transform@0.93.0", "", { "optionalDependencies": { "@oxc-transform/binding-android-arm64": "0.93.0", "@oxc-transform/binding-darwin-arm64": "0.93.0", "@oxc-transform/binding-darwin-x64": "0.93.0", "@oxc-transform/binding-freebsd-x64": "0.93.0", "@oxc-transform/binding-linux-arm-gnueabihf": "0.93.0", "@oxc-transform/binding-linux-arm-musleabihf": "0.93.0", "@oxc-transform/binding-linux-arm64-gnu": "0.93.0", "@oxc-transform/binding-linux-arm64-musl": "0.93.0", "@oxc-transform/binding-linux-riscv64-gnu": "0.93.0", "@oxc-transform/binding-linux-s390x-gnu": "0.93.0", "@oxc-transform/binding-linux-x64-gnu": "0.93.0", "@oxc-transform/binding-linux-x64-musl": "0.93.0", "@oxc-transform/binding-wasm32-wasi": "0.93.0", "@oxc-transform/binding-win32-arm64-msvc": "0.93.0", "@oxc-transform/binding-win32-x64-msvc": "0.93.0" } }, "sha512-QCwM2nMAWf4hEBehLVA2apllxdmmWLb5M0in9HwC2boaaFbP0QntbLy4hfRZGur2KKyEBErZbH9S5NYX8eHslg=="], + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="], "strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="], + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], + "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], + "ts-import-resolver": ["ts-import-resolver@0.1.23", "", { "peerDependencies": { "typescript": ">=4.5.0" }, "optionalPeers": ["typescript"] }, "sha512-282pgr6j6aOvP3P2I6XugDxdBobkpdMmdbWjRjGl5gjPI1p0+oTNGDh1t924t75kRlyIkF65DiwhSIUysmyHQA=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + "typescript-eslint": ["typescript-eslint@8.46.2", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.46.2", "@typescript-eslint/parser": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2", "@typescript-eslint/utils": "8.46.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg=="], + "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + "zlye": ["zlye@0.4.4", "", { "dependencies": { "picocolors": "^1.1.1" }, "peerDependencies": { "typescript": ">=4.5.0" }, "optionalPeers": ["typescript"] }, "sha512-fwpeC841X3ElOLYRMKXbwX29pitNrsm6nRNvEhDMrRXDl3BhR2i03Bkr0GNrpyYgZJuEzUsBylXAYzgGPXXOCQ=="], + + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@eslint/eslintrc/strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], } } diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..95512ff --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,28 @@ +import eslint from "@eslint/js"; + +import { defineConfig, globalIgnores } from "eslint/config"; +import tseslint from "typescript-eslint"; + +import stylistic from "@stylistic/eslint-plugin"; + +export default defineConfig( + eslint.configs.recommended, + tseslint.configs.recommended, + { + plugins: { + "@stylistic": stylistic, + }, + rules: { + "no-unused-vars": "off", + "@stylistic/quotes": ["error", "double"], + "@stylistic/always-multiline": ["error", "always-multiline"], + "@typescript-eslint/consistent-type-imports": "error", + "@typescript-eslint/no-unused-vars": [ + "error", + { varsIgnorePattern: "_", argsIgnorePattern: "_" }, + ], + }, + }, + globalIgnores(["dist/**/*"], "Ignore build directory"), + globalIgnores(["**/*.test.*"], "Ignore test files") +); diff --git a/package.json b/package.json index 61a7a4c..cd13b03 100644 --- a/package.json +++ b/package.json @@ -33,13 +33,19 @@ "author": "Ember", "scripts": { "build": "bunup", - "tests": "bun test" + "tests": "bun test", + "lint": "eslint", + "lint:fix": "eslint --fix" }, "devDependencies": { + "@eslint/js": "^9.39.0", + "@stylistic/eslint-plugin": "^5.5.0", "@types/bun": "^1.3.1", - "bunup": "^0.15.13" + "bunup": "^0.15.13", + "eslint": "^9.39.0", + "typescript-eslint": "^8.46.2" }, "peerDependencies": { - "typescript": "^5.0.0" + "typescript": "^5.9.3" } } From 9e2d3ac9fb2221ba40203d180e3556eab97c99e6 Mon Sep 17 00:00:00 2001 From: EmberIsReal Date: Tue, 4 Nov 2025 09:18:17 +0300 Subject: [PATCH 13/13] docs: add typedoc --- README.md | 71 +- bun.lock | 53 + docs/.nojekyll | 1 + docs/assets/26e93147f10415a0ed4a.svg | 6 + docs/assets/75c9471662e97ee24f29.svg | 7 + docs/assets/db90e4df2373980c497d.svg | 9 + docs/assets/hierarchy-theme.js | 1 + docs/assets/hierarchy.css | 1 + docs/assets/hierarchy.js | 1 + docs/assets/highlight.css | 85 + docs/assets/icons.js | 18 + docs/assets/icons.svg | 1 + docs/assets/main.js | 60 + docs/assets/navigation.js | 1 + docs/assets/search.js | 1 + docs/assets/style.css | 1633 ++++++++++++++++++ docs/classes/Flag.Flag.html | 112 ++ docs/classes/FlagRegistry.FlagsRegistry.html | 101 ++ docs/hierarchy.html | 39 + docs/index.html | 53 + docs/interfaces/index.IFlag.html | 86 + docs/interfaces/index.IFlagsRegistry.html | 75 + docs/modules.html | 39 + docs/modules/Flag.html | 39 + docs/modules/FlagRegistry.html | 39 + docs/modules/index.html | 39 + docs/types/index.FlagKey.html | 40 + eslint.config.mjs | 1 + lib/Flag.ts | 116 ++ lib/FlagRegistry.ts | 129 ++ lib/types.ts | 127 ++ package.json | 7 +- typedoc.json | 21 + 33 files changed, 2942 insertions(+), 70 deletions(-) create mode 100644 docs/.nojekyll create mode 100644 docs/assets/26e93147f10415a0ed4a.svg create mode 100644 docs/assets/75c9471662e97ee24f29.svg create mode 100644 docs/assets/db90e4df2373980c497d.svg create mode 100644 docs/assets/hierarchy-theme.js create mode 100644 docs/assets/hierarchy.css create mode 100644 docs/assets/hierarchy.js create mode 100644 docs/assets/highlight.css create mode 100644 docs/assets/icons.js create mode 100644 docs/assets/icons.svg create mode 100644 docs/assets/main.js create mode 100644 docs/assets/navigation.js create mode 100644 docs/assets/search.js create mode 100644 docs/assets/style.css create mode 100644 docs/classes/Flag.Flag.html create mode 100644 docs/classes/FlagRegistry.FlagsRegistry.html create mode 100644 docs/hierarchy.html create mode 100644 docs/index.html create mode 100644 docs/interfaces/index.IFlag.html create mode 100644 docs/interfaces/index.IFlagsRegistry.html create mode 100644 docs/modules.html create mode 100644 docs/modules/Flag.html create mode 100644 docs/modules/FlagRegistry.html create mode 100644 docs/modules/index.html create mode 100644 docs/types/index.FlagKey.html create mode 100644 typedoc.json diff --git a/README.md b/README.md index 42443eb..436c1d6 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ const fromHex = permissionRegistry.parse("3", 16); // READ + WRITE const fromBinary = permissionRegistry.parse("101", 2); // READ + EXECUTE // check for flags -const userPermissions = permissionsRegistry.combine("READ", "EXECUTE"); +const userPermissions = permissionRegistry.combine("READ", "EXECUTE"); console.log(userPermissions.has("READ")); // true console.log(userPermissions.has("WRITE")); // false @@ -52,7 +52,7 @@ console.log(userPermissions.has("EXECUTE")); // true Flag's instances are immutable. Thats means all operations return new instances. For example: ```ts -const readWrite = permissionsRegistry.combine("READ", "WRITE"); +const readWrite = permissionRegistry.combine("READ", "WRITE"); // add execute flag const fullPermissions = readWrite.add("EXECUTE"); @@ -64,70 +64,3 @@ const read = readWrite.remove("WRITE"); console.log(readWrite.has("WRITE")); // true console.log(read.has("WRITE")); // false ``` - -## API Reference - -### Class: `FlagsRegistry` - -Manages a collection of flag keys and their corresponding bitmask values. Use this to define and retrieve flag bit positions. - -#### Static Methods - -| Method | Description | Parameters | Returns | Throws | -| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ----------------------- | ------ | -| `FlagsRegistry.from(...flagKeys: TFlags[])` | Creates a new registry instance from an array of flag keys. Automatically deduplicates keys and assigns sequential bit positions (starting from bit 0). | `flagKeys`: Array of string keys. | `FlagsRegistry` | None. | - -**Example:** - -```typescript -const registry = FlagsRegistry.from("READ", "WRITE", "READ"); // Deduplicates 'READ' -``` - -#### Instance Methods - -| Method | Description | Parameters | Returns | Throws | -| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------- | ---------------------------------------- | -| `keys()` | Returns an iterator over all flag keys. | None. | `MapIterator` | None. | -| `values()` | Returns an iterator over all bit values. | None. | `MapIterator` | None. | -| `entries()` | Returns an iterator over key-bit pairs. | None. | `MapIterator<[TFlags, bigint]>` | None. | -| `get(flagName: TFlags)` | Retrieves the bitmask value for a specific flag key. | `flagName`: The flag key. | `bigint \| undefined` | None. | -| `empty()` | Creates an empty flag instance (value `0n`). | None. | `IFlag` | None. | -| `parse(value: string \| number \| bigint, radix?: string)` | Creates a flag from a value. If value is string, do **NOT** use prefixes like: `0x` or `0b`, like in JS. | `value` - source value; `radix` - base of value. Use if `value` is string. By default, equals to 10. | `IFlag` | `Error` if string value can't be parsed. | -| `combine(...flagKeys: TFlags[])` | Combines the specified flag keys into a new `Flag` instance by bitwise OR-ing their values. | `flagKeys`: Array of flag keys to combine. | `IFlag` | `Error` if any key is not registered. | - -**Example:** - -```typescript -const combined = registry.combine("READ", "WRITE"); // Value: 3n (0b11) -``` - -### Class: `Flag` - -Represents a bitwise combination of flags from a registry. All operations are immutable, returning new instances. - -#### Properties - -| Property | Description | Type | -| -------- | -------------------------------------------------------------- | -------- | -| `value` | The raw `BigInt` representing the combined bitmask. Read-only. | `bigint` | - -#### Methods - -| Method | Description | Parameters | Returns | Throws | -| -------------------------------- | ---------------------------------------------------------------------------- | --------------------------- | --------------- | ------------------------------------- | -| `isEmpty()` | Checks if no flags are set. | None. | `boolean` | None. | -| `has(flagName: TFlags)` | Tests if a specific flag is set in this combination. | `flagName`: The flag key. | `boolean` | None. | -| `add(...flagNames: TFlags[])` | Adds flags to the combination (idempotent if already set). Returns `IFlag`. | `flagNames`: The flag keys. | `IFlag` | `Error` if the key is not registered. | -| `remove(...flagNames: TFlags[])` | Removes flags from the combination (idempotent if not set). Returns `IFlag`. | `flagNames`: The flag keys. | `IFlag` | `Error` if the key is not registered. | -| `toString()` | Returns a string representation including the alias and raw value. | None. | `string` | None. | -| `alias` (getter) | Computed human-readable alias (e.g., `"[READ+WRITE]"` or `"EMPTY_FLAG"`) | None. | `string` | None. | - -**Validation Note:** The constructor (internal) validates that the value only uses known bits from the registry and is non-negative. Unknown bits or negative values throw an `Error`. - -**Example:** - -```typescript -const flag = registry.combine("READ"); -console.log(flag.has("READ")); // true -console.log(flag.add("WRITE").alias); // "[READ+WRITE]" -``` diff --git a/bun.lock b/bun.lock index 50307c2..ddc8b77 100644 --- a/bun.lock +++ b/bun.lock @@ -9,6 +9,9 @@ "@types/bun": "^1.3.1", "bunup": "^0.15.13", "eslint": "^9.39.0", + "typedoc": "^0.28.14", + "typedoc-plugin-extras": "^4.0.1", + "typedoc-theme-hierarchy": "^6.0.0", "typescript-eslint": "^8.46.2", }, "peerDependencies": { @@ -53,6 +56,8 @@ "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="], + "@gerrit0/mini-shiki": ["@gerrit0/mini-shiki@3.14.0", "", { "dependencies": { "@shikijs/engine-oniguruma": "^3.14.0", "@shikijs/langs": "^3.14.0", "@shikijs/themes": "^3.14.0", "@shikijs/types": "^3.14.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-c5X8fwPLOtUS8TVdqhynz9iV0GlOtFUT1ppXYzUUlEXe4kbZ/mvMT8wXoT8kCwUka+zsiloq7sD3pZ3+QVTuNQ=="], + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], @@ -167,6 +172,16 @@ "@oxc-transform/binding-win32-x64-msvc": ["@oxc-transform/binding-win32-x64-msvc@0.93.0", "", { "os": "win32", "cpu": "x64" }, "sha512-6QN3DEaEw3eWioWEFRgNsTvYq8czYSnpkjB2za+/WdLN0g5FzOl2ZEfNiPrBWIPnSmjUmDWtWVWcSjwY7fX5/Q=="], + "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.14.0", "", { "dependencies": { "@shikijs/types": "3.14.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-TNcYTYMbJyy+ZjzWtt0bG5y4YyMIWC2nyePz+CFMWqm+HnZZyy9SWMgo8Z6KBJVIZnx8XUXS8U2afO6Y0g1Oug=="], + + "@shikijs/langs": ["@shikijs/langs@3.14.0", "", { "dependencies": { "@shikijs/types": "3.14.0" } }, "sha512-DIB2EQY7yPX1/ZH7lMcwrK5pl+ZkP/xoSpUzg9YC8R+evRCCiSQ7yyrvEyBsMnfZq4eBzLzBlugMyTAf13+pzg=="], + + "@shikijs/themes": ["@shikijs/themes@3.14.0", "", { "dependencies": { "@shikijs/types": "3.14.0" } }, "sha512-fAo/OnfWckNmv4uBoUu6dSlkcBc+SA1xzj5oUSaz5z3KqHtEbUypg/9xxgJARtM6+7RVm0Q6Xnty41xA1ma1IA=="], + + "@shikijs/types": ["@shikijs/types@3.14.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-bQGgC6vrY8U/9ObG1Z/vTro+uclbjjD/uG58RvfxKZVD5p9Yc1ka3tVyEFy7BNJLzxuWyHH5NWynP9zZZS59eQ=="], + + "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], + "@stylistic/eslint-plugin": ["@stylistic/eslint-plugin@5.5.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.0", "@typescript-eslint/types": "^8.46.1", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "estraverse": "^5.3.0", "picomatch": "^4.0.3" }, "peerDependencies": { "eslint": ">=9.0.0" } }, "sha512-IeZF+8H0ns6prg4VrkhgL+yrvDXWDH2cKchrbh80ejG9dQgZWp10epHMbgRuQvgchLII/lfh6Xn3lu6+6L86Hw=="], "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], @@ -175,12 +190,16 @@ "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], "@types/node": ["@types/node@24.9.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA=="], "@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="], + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.46.2", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/type-utils": "8.46.2", "@typescript-eslint/utils": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.46.2", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w=="], "@typescript-eslint/parser": ["@typescript-eslint/parser@8.46.2", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/types": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g=="], @@ -245,6 +264,8 @@ "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], "eslint": ["eslint@9.39.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.39.0", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-iy2GE3MHrYTL5lrCtMZ0X1KLEKKUjmK0kzwcnefhR66txcEmXZD2YWgR5GNdcEwkNx3a0siYkSvl0vIC+Svjmg=="], @@ -283,10 +304,14 @@ "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + "fs-extra": ["fs-extra@11.1.1", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ=="], + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], "globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], @@ -313,6 +338,8 @@ "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], @@ -341,10 +368,18 @@ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="], + "linkify-it": ["linkify-it@5.0.0", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ=="], + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + "lunr": ["lunr@2.3.9", "", {}, "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow=="], + + "markdown-it": ["markdown-it@14.1.0", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", "linkify-it": "^5.0.0", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg=="], + + "mdurl": ["mdurl@2.0.0", "", {}, "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="], + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], @@ -381,6 +416,8 @@ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + "punycode.js": ["punycode.js@2.3.1", "", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="], + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], @@ -417,18 +454,30 @@ "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + "typedoc": ["typedoc@0.28.14", "", { "dependencies": { "@gerrit0/mini-shiki": "^3.12.0", "lunr": "^2.3.9", "markdown-it": "^14.1.0", "minimatch": "^9.0.5", "yaml": "^2.8.1" }, "peerDependencies": { "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x" }, "bin": { "typedoc": "bin/typedoc" } }, "sha512-ftJYPvpVfQvFzpkoSfHLkJybdA/geDJ8BGQt/ZnkkhnBYoYW6lBgPQXu6vqLxO4X75dA55hX8Af847H5KXlEFA=="], + + "typedoc-plugin-extras": ["typedoc-plugin-extras@4.0.1", "", { "peerDependencies": { "typedoc": "0.27.x || 0.28.x" } }, "sha512-ab3T37ukHCwBjwBJpAcWdxy/XAaLdUyy5pwbgF9WDqCRN0DTJmJPLew9Kv6qrx5qnxiyfe6F4Og+PUp15kJWLw=="], + + "typedoc-theme-hierarchy": ["typedoc-theme-hierarchy@6.0.0", "", { "dependencies": { "fs-extra": "11.1.1" }, "peerDependencies": { "typedoc": "^0.28.0" } }, "sha512-SSPqM0HnFyyYoNexmH8FHIkoKvd3Xg6KZsutrDCcYgm2mtVGGHLFKuqAaVKtKWbPq7xW61OIxvVrTQQi6dtXTw=="], + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], "typescript-eslint": ["typescript-eslint@8.46.2", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.46.2", "@typescript-eslint/parser": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2", "@typescript-eslint/utils": "8.46.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg=="], + "uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="], + "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + "yaml": ["yaml@2.8.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw=="], + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], "zlye": ["zlye@0.4.4", "", { "dependencies": { "picocolors": "^1.1.1" }, "peerDependencies": { "typescript": ">=4.5.0" }, "optionalPeers": ["typescript"] }, "sha512-fwpeC841X3ElOLYRMKXbwX29pitNrsm6nRNvEhDMrRXDl3BhR2i03Bkr0GNrpyYgZJuEzUsBylXAYzgGPXXOCQ=="], @@ -445,6 +494,10 @@ "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "typedoc/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "typedoc/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], } } diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000..e2ac661 --- /dev/null +++ b/docs/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/assets/26e93147f10415a0ed4a.svg b/docs/assets/26e93147f10415a0ed4a.svg new file mode 100644 index 0000000..09d06a6 --- /dev/null +++ b/docs/assets/26e93147f10415a0ed4a.svg @@ -0,0 +1,6 @@ + + +TypeScript logo + + + diff --git a/docs/assets/75c9471662e97ee24f29.svg b/docs/assets/75c9471662e97ee24f29.svg new file mode 100644 index 0000000..a8c3280 --- /dev/null +++ b/docs/assets/75c9471662e97ee24f29.svg @@ -0,0 +1,7 @@ + + + + + + diff --git a/docs/assets/db90e4df2373980c497d.svg b/docs/assets/db90e4df2373980c497d.svg new file mode 100644 index 0000000..074613e --- /dev/null +++ b/docs/assets/db90e4df2373980c497d.svg @@ -0,0 +1,9 @@ + + + + + + + diff --git a/docs/assets/hierarchy-theme.js b/docs/assets/hierarchy-theme.js new file mode 100644 index 0000000..39f4bd4 --- /dev/null +++ b/docs/assets/hierarchy-theme.js @@ -0,0 +1 @@ +(()=>{"use strict";class t{openedPathLsKey="opened-path-state";openedPaths=[];constructor(){const t=localStorage.getItem("opened-path-state");this.openedPaths=t?JSON.parse(t):[]}addOpenedPath(t){this.openedPaths.push(t),this.updateState()}removeOpenedPath(t){this.openedPaths=this.openedPaths.filter((e=>e!==t)),this.updateState()}getOpenedPaths(){return this.openedPaths}updateState(){localStorage.setItem(this.openedPathLsKey,JSON.stringify(this.openedPaths))}}(new class{stateManager=new t;titleSelector=".js-category-title";listSelector=".js-category-list";init(){this.addListeners(),this.initSaved(),this.openCurrentPath()}openPathAndSave(t){this.openPath(t),this.stateManager.addOpenedPath(t)}openPath(t){const e=document.querySelector(`${this.listSelector}[data-id="${t}"]`);e&&(e.classList.add("_open"),e.parentNode?.querySelector(this.titleSelector)?.classList.add("_open"))}closePath(t){const e=document.querySelector(`${this.listSelector}[data-id="${t}"]`);e&&(e.classList.remove("_open"),e.parentNode?.querySelector(this.titleSelector)?.classList.remove("_open"),this.stateManager.removeOpenedPath(t))}closePathWithChildren(t){this.closePath(t);const e=document.querySelector(`${this.listSelector}[data-id="${t}"]`);if(!e)return;const s=e.querySelectorAll(this.listSelector);for(const t of s)this.closePath(t.dataset.id||"")}togglePath(t){const e=document.querySelector(`${this.listSelector}[data-id="${t}"]`);e&&(e.classList.contains("_open")?this.closePathWithChildren(t):this.openPathAndSave(t))}addListeners(){const t=document.querySelectorAll('.js-category-title:not([data-id="root"])');for(const e of t)e.addEventListener("click",(()=>{const t=e.dataset.id||"";this.togglePath(t)}));this.addExpandListener(),this.addCollapseListener(),this.addTargetListener()}addExpandListener(){document.querySelector(".js-tree-expand")?.addEventListener("click",(()=>{const t=document.querySelectorAll(this.listSelector);for(const e of t){const t=e.dataset.id||"";this.openPathAndSave(t)}}))}addCollapseListener(){document.querySelector(".js-tree-collapse")?.addEventListener("click",(()=>{const t=document.querySelectorAll(this.listSelector);for(const e of t){const t=e.dataset.id||"";this.closePath(t)}}))}addTargetListener(){document.querySelector(".js-tree-target")?.addEventListener("click",(()=>{this.openCurrentPath()?.scrollIntoView()}))}initSaved(){const t=this.stateManager.getOpenedPaths();for(const e of t)this.openPath(e)}openCurrentPath(){const t=window.location.pathname.split("/"),e=`/${t[t.length-2]||""}/${t[t.length-1]||""}`,s=document.querySelector(`.js-category-link[data-id="${e}"]`);if(!s)return null;s.classList.add("_active");let o=s.closest(this.listSelector);for(;o;){const t=o.dataset.id||"";this.openPath(t),o=o.parentNode.closest(this.listSelector)}return s}}).init()})(); \ No newline at end of file diff --git a/docs/assets/hierarchy.css b/docs/assets/hierarchy.css new file mode 100644 index 0000000..d3e55a5 --- /dev/null +++ b/docs/assets/hierarchy.css @@ -0,0 +1 @@ +.tree{background:var(--color-panel);margin-top:20px}.tree-config{display:flex;gap:8px;justify-content:end;padding:8px}.tree-config__button{align-items:center;background-color:transparent;border:0;color:var(--color-toolbar-text);cursor:pointer;display:flex;height:20px;justify-content:center;opacity:.8;padding:0;width:20px}.tree-config__button:hover{opacity:.9}.tree-content{color:var(--color-text);font-size:.85rem;font-weight:400;line-height:1.5;padding:0 20px 20px;position:relative}.tree-content span{font-size:13px;letter-spacing:.4px}.tree-content ul{list-style:none;margin:0;padding-left:5px}.tree-content ul li{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding-bottom:5px;padding-left:15px;padding-top:5px;position:relative}.tree-content ul li:before{height:1px;margin:auto;top:15px;width:10px}.tree-content ul li:after,.tree-content ul li:before{background-color:#666;content:"";left:0;position:absolute}.tree-content ul li:after{bottom:0;height:100%;top:0;width:1px}.tree-content ul li:last-child:after{height:15px}.tree-content ul a{cursor:pointer}.category:not([data-id=root]){display:none}.category:not([data-id=root])._open{display:block}.category__title{color:var(--color-text-aside);cursor:pointer}.category__link,.category__title{align-items:center;display:flex;flex-shrink:0;text-decoration:none}a.category__link:hover,a.category__title:hover{text-decoration:underline}.category__title._open .category__folder{background:url(db90e4df2373980c497d.svg)}.category__folder{background:url(75c9471662e97ee24f29.svg);display:inline-block;flex-shrink:0;height:15px;margin-right:6px;width:15px}.category__link._active{color:inherit}.category__link--ts:before{background-image:url(26e93147f10415a0ed4a.svg);content:"";display:inline-block;flex-shrink:0;height:15px;margin:0 7px 2px 0;vertical-align:middle;width:15px} \ No newline at end of file diff --git a/docs/assets/hierarchy.js b/docs/assets/hierarchy.js new file mode 100644 index 0000000..4332dce --- /dev/null +++ b/docs/assets/hierarchy.js @@ -0,0 +1 @@ +window.hierarchyData = "eJyFj80KwjAQhN9lzrHFBkPJAwhevUoPod1qMKaQjaBI3l1iqfiD9rKHnZn9dm4IwxAZeqeUqGUjEKh31EY7eIa+QebhzYmgsXZmD4Gj9R30sqoFzsFBo3WGmbjMevEYh3hyEKMAjcjdIqcW4yIJyOrjLm9pbzmG6xxg8hVvqXmiUi/EzVuVaqUmkvWRQm9a4tL6ji7F5m+fpz2LB+u6QB56J5skUMtP4HfHWfJ8wV8vVE1K6Q7s5p4x" \ No newline at end of file diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css new file mode 100644 index 0000000..b4f2686 --- /dev/null +++ b/docs/assets/highlight.css @@ -0,0 +1,85 @@ +:root { + --light-hl-0: #795E26; + --dark-hl-0: #DCDCAA; + --light-hl-1: #000000; + --dark-hl-1: #D4D4D4; + --light-hl-2: #A31515; + --dark-hl-2: #CE9178; + --light-hl-3: #008000; + --dark-hl-3: #6A9955; + --light-hl-4: #AF00DB; + --dark-hl-4: #CE92A4; + --light-hl-5: #001080; + --dark-hl-5: #9CDCFE; + --light-hl-6: #0000FF; + --dark-hl-6: #569CD6; + --light-hl-7: #0070C1; + --dark-hl-7: #4FC1FF; + --light-hl-8: #098658; + --dark-hl-8: #B5CEA8; + --light-code-background: #FFFFFF; + --dark-code-background: #1E1E1E; +} + +@media (prefers-color-scheme: light) { :root { + --hl-0: var(--light-hl-0); + --hl-1: var(--light-hl-1); + --hl-2: var(--light-hl-2); + --hl-3: var(--light-hl-3); + --hl-4: var(--light-hl-4); + --hl-5: var(--light-hl-5); + --hl-6: var(--light-hl-6); + --hl-7: var(--light-hl-7); + --hl-8: var(--light-hl-8); + --code-background: var(--light-code-background); +} } + +@media (prefers-color-scheme: dark) { :root { + --hl-0: var(--dark-hl-0); + --hl-1: var(--dark-hl-1); + --hl-2: var(--dark-hl-2); + --hl-3: var(--dark-hl-3); + --hl-4: var(--dark-hl-4); + --hl-5: var(--dark-hl-5); + --hl-6: var(--dark-hl-6); + --hl-7: var(--dark-hl-7); + --hl-8: var(--dark-hl-8); + --code-background: var(--dark-code-background); +} } + +:root[data-theme='light'] { + --hl-0: var(--light-hl-0); + --hl-1: var(--light-hl-1); + --hl-2: var(--light-hl-2); + --hl-3: var(--light-hl-3); + --hl-4: var(--light-hl-4); + --hl-5: var(--light-hl-5); + --hl-6: var(--light-hl-6); + --hl-7: var(--light-hl-7); + --hl-8: var(--light-hl-8); + --code-background: var(--light-code-background); +} + +:root[data-theme='dark'] { + --hl-0: var(--dark-hl-0); + --hl-1: var(--dark-hl-1); + --hl-2: var(--dark-hl-2); + --hl-3: var(--dark-hl-3); + --hl-4: var(--dark-hl-4); + --hl-5: var(--dark-hl-5); + --hl-6: var(--dark-hl-6); + --hl-7: var(--dark-hl-7); + --hl-8: var(--dark-hl-8); + --code-background: var(--dark-code-background); +} + +.hl-0 { color: var(--hl-0); } +.hl-1 { color: var(--hl-1); } +.hl-2 { color: var(--hl-2); } +.hl-3 { color: var(--hl-3); } +.hl-4 { color: var(--hl-4); } +.hl-5 { color: var(--hl-5); } +.hl-6 { color: var(--hl-6); } +.hl-7 { color: var(--hl-7); } +.hl-8 { color: var(--hl-8); } +pre, code { background: var(--code-background); } diff --git a/docs/assets/icons.js b/docs/assets/icons.js new file mode 100644 index 0000000..58882d7 --- /dev/null +++ b/docs/assets/icons.js @@ -0,0 +1,18 @@ +(function() { + addIcons(); + function addIcons() { + if (document.readyState === "loading") return document.addEventListener("DOMContentLoaded", addIcons); + const svg = document.body.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg")); + svg.innerHTML = `MMNEPVFCICPMFPCPTTAAATR`; + svg.style.display = "none"; + if (location.protocol === "file:") updateUseElements(); + } + + function updateUseElements() { + document.querySelectorAll("use").forEach(el => { + if (el.getAttribute("href").includes("#icon-")) { + el.setAttribute("href", el.getAttribute("href").replace(/.*#/, "#")); + } + }); + } +})() \ No newline at end of file diff --git a/docs/assets/icons.svg b/docs/assets/icons.svg new file mode 100644 index 0000000..50ad579 --- /dev/null +++ b/docs/assets/icons.svg @@ -0,0 +1 @@ +MMNEPVFCICPMFPCPTTAAATR \ No newline at end of file diff --git a/docs/assets/main.js b/docs/assets/main.js new file mode 100644 index 0000000..64b80ab --- /dev/null +++ b/docs/assets/main.js @@ -0,0 +1,60 @@ +"use strict"; +window.translations={"copy":"Copy","copied":"Copied!","normally_hidden":"This member is normally hidden due to your filter settings.","hierarchy_expand":"Expand","hierarchy_collapse":"Collapse","folder":"Folder","search_index_not_available":"The search index is not available","search_no_results_found_for_0":"No results found for {0}","kind_1":"Project","kind_2":"Module","kind_4":"Namespace","kind_8":"Enumeration","kind_16":"Enumeration Member","kind_32":"Variable","kind_64":"Function","kind_128":"Class","kind_256":"Interface","kind_512":"Constructor","kind_1024":"Property","kind_2048":"Method","kind_4096":"Call Signature","kind_8192":"Index Signature","kind_16384":"Constructor Signature","kind_32768":"Parameter","kind_65536":"Type Literal","kind_131072":"Type Parameter","kind_262144":"Accessor","kind_524288":"Get Signature","kind_1048576":"Set Signature","kind_2097152":"Type Alias","kind_4194304":"Reference","kind_8388608":"Document"}; +"use strict";(()=>{var Ke=Object.create;var he=Object.defineProperty;var Ge=Object.getOwnPropertyDescriptor;var Ze=Object.getOwnPropertyNames;var Xe=Object.getPrototypeOf,Ye=Object.prototype.hasOwnProperty;var et=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var tt=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ze(e))!Ye.call(t,i)&&i!==n&&he(t,i,{get:()=>e[i],enumerable:!(r=Ge(e,i))||r.enumerable});return t};var nt=(t,e,n)=>(n=t!=null?Ke(Xe(t)):{},tt(e||!t||!t.__esModule?he(n,"default",{value:t,enumerable:!0}):n,t));var ye=et((me,ge)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=(function(e){return function(n){e.console&&console.warn&&console.warn(n)}})(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var d=t.utils.clone(n)||{};d.position=[a,l],d.index=s.length,s.push(new t.Token(r.slice(a,o),d))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. +`,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(oc?d+=2:a==c&&(n+=r[l+1]*i[d+1],l+=2,d+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var c=s.node.edges["*"];else{var c=new t.TokenSet;s.node.edges["*"]=c}if(s.str.length==0&&(c.final=!0),i.push({node:c,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}s.str.length==1&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var d=s.str.charAt(0),f=s.str.charAt(1),p;f in s.node.edges?p=s.node.edges[f]:(p=new t.TokenSet,s.node.edges[f]=p),s.str.length==1&&(p.final=!0),i.push({node:p,editsRemaining:s.editsRemaining-1,str:d+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),c=0;c1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},(function(e,n){typeof define=="function"&&define.amd?define(n):typeof me=="object"?ge.exports=n():e.lunr=n()})(this,function(){return t})})()});var M,G={getItem(){return null},setItem(){}},K;try{K=localStorage,M=K}catch{K=G,M=G}var S={getItem:t=>M.getItem(t),setItem:(t,e)=>M.setItem(t,e),disableWritingLocalStorage(){M=G},disable(){localStorage.clear(),M=G},enable(){M=K}};window.TypeDoc||={disableWritingLocalStorage(){S.disableWritingLocalStorage()},disableLocalStorage:()=>{S.disable()},enableLocalStorage:()=>{S.enable()}};window.translations||={copy:"Copy",copied:"Copied!",normally_hidden:"This member is normally hidden due to your filter settings.",hierarchy_expand:"Expand",hierarchy_collapse:"Collapse",search_index_not_available:"The search index is not available",search_no_results_found_for_0:"No results found for {0}",folder:"Folder",kind_1:"Project",kind_2:"Module",kind_4:"Namespace",kind_8:"Enumeration",kind_16:"Enumeration Member",kind_32:"Variable",kind_64:"Function",kind_128:"Class",kind_256:"Interface",kind_512:"Constructor",kind_1024:"Property",kind_2048:"Method",kind_4096:"Call Signature",kind_8192:"Index Signature",kind_16384:"Constructor Signature",kind_32768:"Parameter",kind_65536:"Type Literal",kind_131072:"Type Parameter",kind_262144:"Accessor",kind_524288:"Get Signature",kind_1048576:"Set Signature",kind_2097152:"Type Alias",kind_4194304:"Reference",kind_8388608:"Document"};var pe=[];function X(t,e){pe.push({selector:e,constructor:t})}var Z=class{alwaysVisibleMember=null;constructor(){this.createComponents(document.body),this.ensureFocusedElementVisible(),this.listenForCodeCopies(),window.addEventListener("hashchange",()=>this.ensureFocusedElementVisible()),document.body.style.display||(this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}createComponents(e){pe.forEach(n=>{e.querySelectorAll(n.selector).forEach(r=>{r.dataset.hasInstance||(new n.constructor({el:r,app:this}),r.dataset.hasInstance=String(!0))})})}filterChanged(){this.ensureFocusedElementVisible()}showPage(){document.body.style.display&&(document.body.style.removeProperty("display"),this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}scrollToHash(){if(location.hash){let e=document.getElementById(location.hash.substring(1));if(!e)return;e.scrollIntoView({behavior:"instant",block:"start"})}}ensureActivePageVisible(){let e=document.querySelector(".tsd-navigation .current"),n=e?.parentElement;for(;n&&!n.classList.contains(".tsd-navigation");)n instanceof HTMLDetailsElement&&(n.open=!0),n=n.parentElement;if(e&&!rt(e)){let r=e.getBoundingClientRect().top-document.documentElement.clientHeight/4;document.querySelector(".site-menu").scrollTop=r,document.querySelector(".col-sidebar").scrollTop=r}}updateIndexVisibility(){let e=document.querySelector(".tsd-index-content"),n=e?.open;e&&(e.open=!0),document.querySelectorAll(".tsd-index-section").forEach(r=>{r.style.display="block";let i=Array.from(r.querySelectorAll(".tsd-index-link")).every(s=>s.offsetParent==null);r.style.display=i?"none":"block"}),e&&(e.open=n)}ensureFocusedElementVisible(){if(this.alwaysVisibleMember&&(this.alwaysVisibleMember.classList.remove("always-visible"),this.alwaysVisibleMember.firstElementChild.remove(),this.alwaysVisibleMember=null),!location.hash)return;let e=document.getElementById(location.hash.substring(1));if(!e)return;let n=e.parentElement;for(;n&&n.tagName!=="SECTION";)n=n.parentElement;if(!n)return;let r=n.offsetParent==null,i=n;for(;i!==document.body;)i instanceof HTMLDetailsElement&&(i.open=!0),i=i.parentElement;if(n.offsetParent==null){this.alwaysVisibleMember=n,n.classList.add("always-visible");let s=document.createElement("p");s.classList.add("warning"),s.textContent=window.translations.normally_hidden,n.prepend(s)}r&&e.scrollIntoView()}listenForCodeCopies(){document.querySelectorAll("pre > button").forEach(e=>{let n;e.addEventListener("click",()=>{e.previousElementSibling instanceof HTMLElement&&navigator.clipboard.writeText(e.previousElementSibling.innerText.trim()),e.textContent=window.translations.copied,e.classList.add("visible"),clearTimeout(n),n=setTimeout(()=>{e.classList.remove("visible"),n=setTimeout(()=>{e.textContent=window.translations.copy},100)},1e3)})})}};function rt(t){let e=t.getBoundingClientRect(),n=Math.max(document.documentElement.clientHeight,window.innerHeight);return!(e.bottom<0||e.top-n>=0)}var fe=(t,e=100)=>{let n;return()=>{clearTimeout(n),n=setTimeout(()=>t(),e)}};var Ie=nt(ye(),1);async function R(t){let e=Uint8Array.from(atob(t),s=>s.charCodeAt(0)),r=new Blob([e]).stream().pipeThrough(new DecompressionStream("deflate")),i=await new Response(r).text();return JSON.parse(i)}var Y="closing",ae="tsd-overlay";function it(){let t=Math.abs(window.innerWidth-document.documentElement.clientWidth);document.body.style.overflow="hidden",document.body.style.paddingRight=`${t}px`}function st(){document.body.style.removeProperty("overflow"),document.body.style.removeProperty("padding-right")}function xe(t,e){t.addEventListener("animationend",()=>{t.classList.contains(Y)&&(t.classList.remove(Y),document.getElementById(ae)?.remove(),t.close(),st())}),t.addEventListener("cancel",n=>{n.preventDefault(),ve(t)}),e?.closeOnClick&&document.addEventListener("click",n=>{t.open&&!t.contains(n.target)&&ve(t)},!0)}function Ee(t){if(t.open)return;let e=document.createElement("div");e.id=ae,document.body.appendChild(e),t.showModal(),it()}function ve(t){if(!t.open)return;document.getElementById(ae)?.classList.add(Y),t.classList.add(Y)}var I=class{el;app;constructor(e){this.el=e.el,this.app=e.app}};var be=document.head.appendChild(document.createElement("style"));be.dataset.for="filters";var le={};function we(t){for(let e of t.split(/\s+/))if(le.hasOwnProperty(e)&&!le[e])return!0;return!1}var ee=class extends I{key;value;constructor(e){super(e),this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),be.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; } +`,this.app.updateIndexVisibility()}fromLocalStorage(){let e=S.getItem(this.key);return e?e==="true":this.el.checked}setLocalStorage(e){S.setItem(this.key,e.toString()),this.value=e,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),le[`tsd-is-${this.el.name}`]=this.value,this.app.filterChanged(),this.app.updateIndexVisibility()}};var Le=0;async function Se(t,e){if(!window.searchData)return;let n=await R(window.searchData);t.data=n,t.index=Ie.Index.load(n.index),e.innerHTML=""}function _e(){let t=document.getElementById("tsd-search-trigger"),e=document.getElementById("tsd-search"),n=document.getElementById("tsd-search-input"),r=document.getElementById("tsd-search-results"),i=document.getElementById("tsd-search-script"),s=document.getElementById("tsd-search-status");if(!(t&&e&&n&&r&&i&&s))throw new Error("Search controls missing");let o={base:document.documentElement.dataset.base};o.base.endsWith("/")||(o.base+="/"),i.addEventListener("error",()=>{let a=window.translations.search_index_not_available;Pe(s,a)}),i.addEventListener("load",()=>{Se(o,s)}),Se(o,s),ot({trigger:t,searchEl:e,results:r,field:n,status:s},o)}function ot(t,e){let{field:n,results:r,searchEl:i,status:s,trigger:o}=t;xe(i,{closeOnClick:!0});function a(){Ee(i),n.setSelectionRange(0,n.value.length)}o.addEventListener("click",a),n.addEventListener("input",fe(()=>{at(r,n,s,e)},200)),n.addEventListener("keydown",l=>{if(r.childElementCount===0||l.ctrlKey||l.metaKey||l.altKey)return;let d=n.getAttribute("aria-activedescendant"),f=d?document.getElementById(d):null;if(f){let p=!1,v=!1;switch(l.key){case"Home":case"End":case"ArrowLeft":case"ArrowRight":v=!0;break;case"ArrowDown":case"ArrowUp":p=l.shiftKey;break}(p||v)&&ke(n)}if(!l.shiftKey)switch(l.key){case"Enter":f?.querySelector("a")?.click();break;case"ArrowUp":Te(r,n,f,-1),l.preventDefault();break;case"ArrowDown":Te(r,n,f,1),l.preventDefault();break}});function c(){ke(n)}n.addEventListener("change",c),n.addEventListener("blur",c),n.addEventListener("click",c),document.body.addEventListener("keydown",l=>{if(l.altKey||l.metaKey||l.shiftKey)return;let d=l.ctrlKey&&l.key==="k",f=!l.ctrlKey&&!ut()&&l.key==="/";(d||f)&&(l.preventDefault(),a())})}function at(t,e,n,r){if(!r.index||!r.data)return;t.innerHTML="",n.innerHTML="",Le+=1;let i=e.value.trim(),s;if(i){let a=i.split(" ").map(c=>c.length?`*${c}*`:"").join(" ");s=r.index.search(a).filter(({ref:c})=>{let l=r.data.rows[Number(c)].classes;return!l||!we(l)})}else s=[];if(s.length===0&&i){let a=window.translations.search_no_results_found_for_0.replace("{0}",` "${te(i)}" `);Pe(n,a);return}for(let a=0;ac.score-a.score);let o=Math.min(10,s.length);for(let a=0;a`,f=Ce(c.name,i);globalThis.DEBUG_SEARCH_WEIGHTS&&(f+=` (score: ${s[a].score.toFixed(2)})`),c.parent&&(f=` + ${Ce(c.parent,i)}.${f}`);let p=document.createElement("li");p.id=`tsd-search:${Le}-${a}`,p.role="option",p.ariaSelected="false",p.classList.value=c.classes??"";let v=document.createElement("a");v.tabIndex=-1,v.href=r.base+c.url,v.innerHTML=d+`${f}`,p.append(v),t.appendChild(p)}}function Te(t,e,n,r){let i;if(r===1?i=n?.nextElementSibling||t.firstElementChild:i=n?.previousElementSibling||t.lastElementChild,i!==n){if(!i||i.role!=="option"){console.error("Option missing");return}i.ariaSelected="true",i.scrollIntoView({behavior:"smooth",block:"nearest"}),e.setAttribute("aria-activedescendant",i.id),n?.setAttribute("aria-selected","false")}}function ke(t){let e=t.getAttribute("aria-activedescendant");(e?document.getElementById(e):null)?.setAttribute("aria-selected","false"),t.setAttribute("aria-activedescendant","")}function Ce(t,e){if(e==="")return t;let n=t.toLocaleLowerCase(),r=e.toLocaleLowerCase(),i=[],s=0,o=n.indexOf(r);for(;o!=-1;)i.push(te(t.substring(s,o)),`${te(t.substring(o,o+r.length))}`),s=o+r.length,o=n.indexOf(r,s);return i.push(te(t.substring(s))),i.join("")}var lt={"&":"&","<":"<",">":">","'":"'",'"':"""};function te(t){return t.replace(/[&<>"'"]/g,e=>lt[e])}function Pe(t,e){t.innerHTML=e?`
${e}
`:""}var ct=["button","checkbox","file","hidden","image","radio","range","reset","submit"];function ut(){let t=document.activeElement;return t?t.isContentEditable||t.tagName==="TEXTAREA"||t.tagName==="SEARCH"?!0:t.tagName==="INPUT"&&!ct.includes(t.type):!1}var D="mousedown",Me="mousemove",$="mouseup",ne={x:0,y:0},Qe=!1,ce=!1,dt=!1,F=!1,Oe=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(Oe?"is-mobile":"not-mobile");Oe&&"ontouchstart"in document.documentElement&&(dt=!0,D="touchstart",Me="touchmove",$="touchend");document.addEventListener(D,t=>{ce=!0,F=!1;let e=D=="touchstart"?t.targetTouches[0]:t;ne.y=e.pageY||0,ne.x=e.pageX||0});document.addEventListener(Me,t=>{if(ce&&!F){let e=D=="touchstart"?t.targetTouches[0]:t,n=ne.x-(e.pageX||0),r=ne.y-(e.pageY||0);F=Math.sqrt(n*n+r*r)>10}});document.addEventListener($,()=>{ce=!1});document.addEventListener("click",t=>{Qe&&(t.preventDefault(),t.stopImmediatePropagation(),Qe=!1)});var re=class extends I{active;className;constructor(e){super(e),this.className=this.el.dataset.toggle||"",this.el.addEventListener($,n=>this.onPointerUp(n)),this.el.addEventListener("click",n=>n.preventDefault()),document.addEventListener(D,n=>this.onDocumentPointerDown(n)),document.addEventListener($,n=>this.onDocumentPointerUp(n))}setActive(e){if(this.active==e)return;this.active=e,document.documentElement.classList.toggle("has-"+this.className,e),this.el.classList.toggle("active",e);let n=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(n),setTimeout(()=>document.documentElement.classList.remove(n),500)}onPointerUp(e){F||(this.setActive(!0),e.preventDefault())}onDocumentPointerDown(e){if(this.active){if(e.target.closest(".col-sidebar, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(e){if(!F&&this.active&&e.target.closest(".col-sidebar")){let n=e.target.closest("a");if(n){let r=window.location.href;r.indexOf("#")!=-1&&(r=r.substring(0,r.indexOf("#"))),n.href.substring(0,r.length)==r&&setTimeout(()=>this.setActive(!1),250)}}}};var ue=new Map,de=class{open;accordions=[];key;constructor(e,n){this.key=e,this.open=n}add(e){this.accordions.push(e),e.open=this.open,e.addEventListener("toggle",()=>{this.toggle(e.open)})}toggle(e){for(let n of this.accordions)n.open=e;S.setItem(this.key,e.toString())}},ie=class extends I{constructor(e){super(e);let n=this.el.querySelector("summary"),r=n.querySelector("a");r&&r.addEventListener("click",()=>{location.assign(r.href)});let i=`tsd-accordion-${n.dataset.key??n.textContent.trim().replace(/\s+/g,"-").toLowerCase()}`,s;if(ue.has(i))s=ue.get(i);else{let o=S.getItem(i),a=o?o==="true":this.el.open;s=new de(i,a),ue.set(i,s)}s.add(this.el)}};function He(t){let e=S.getItem("tsd-theme")||"os";t.value=e,Ae(e),t.addEventListener("change",()=>{S.setItem("tsd-theme",t.value),Ae(t.value)})}function Ae(t){document.documentElement.dataset.theme=t}var se;function Ne(){let t=document.getElementById("tsd-nav-script");t&&(t.addEventListener("load",Re),Re())}async function Re(){let t=document.getElementById("tsd-nav-container");if(!t||!window.navigationData)return;let e=await R(window.navigationData);se=document.documentElement.dataset.base,se.endsWith("/")||(se+="/"),t.innerHTML="";for(let n of e)Be(n,t,[]);window.app.createComponents(t),window.app.showPage(),window.app.ensureActivePageVisible()}function Be(t,e,n){let r=e.appendChild(document.createElement("li"));if(t.children){let i=[...n,t.text],s=r.appendChild(document.createElement("details"));s.className=t.class?`${t.class} tsd-accordion`:"tsd-accordion";let o=s.appendChild(document.createElement("summary"));o.className="tsd-accordion-summary",o.dataset.key=i.join("$"),o.innerHTML='',De(t,o);let a=s.appendChild(document.createElement("div"));a.className="tsd-accordion-details";let c=a.appendChild(document.createElement("ul"));c.className="tsd-nested-navigation";for(let l of t.children)Be(l,c,i)}else De(t,r,t.class)}function De(t,e,n){if(t.path){let r=e.appendChild(document.createElement("a"));if(r.href=se+t.path,n&&(r.className=n),location.pathname===r.pathname&&!r.href.includes("#")&&(r.classList.add("current"),r.ariaCurrent="page"),t.kind){let i=window.translations[`kind_${t.kind}`].replaceAll('"',""");r.innerHTML=``}r.appendChild(Fe(t.text,document.createElement("span")))}else{let r=e.appendChild(document.createElement("span")),i=window.translations.folder.replaceAll('"',""");r.innerHTML=``,r.appendChild(Fe(t.text,document.createElement("span")))}}function Fe(t,e){let n=t.split(/(?<=[^A-Z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<=[_-])(?=[^_-])/);for(let r=0;r{let i=r.target;for(;i.parentElement&&i.parentElement.tagName!="LI";)i=i.parentElement;i.dataset.dropdown&&(i.dataset.dropdown=String(i.dataset.dropdown!=="true"))});let t=new Map,e=new Set;for(let r of document.querySelectorAll(".tsd-full-hierarchy [data-refl]")){let i=r.querySelector("ul");t.has(r.dataset.refl)?e.add(r.dataset.refl):i&&t.set(r.dataset.refl,i)}for(let r of e)n(r);function n(r){let i=t.get(r).cloneNode(!0);i.querySelectorAll("[id]").forEach(s=>{s.removeAttribute("id")}),i.querySelectorAll("[data-dropdown]").forEach(s=>{s.dataset.dropdown="false"});for(let s of document.querySelectorAll(`[data-refl="${r}"]`)){let o=gt(),a=s.querySelector("ul");s.insertBefore(o,a),o.dataset.dropdown=String(!!a),a||s.appendChild(i.cloneNode(!0))}}}function pt(){let t=document.getElementById("tsd-hierarchy-script");t&&(t.addEventListener("load",Ve),Ve())}async function Ve(){let t=document.querySelector(".tsd-panel.tsd-hierarchy:has(h4 a)");if(!t||!window.hierarchyData)return;let e=+t.dataset.refl,n=await R(window.hierarchyData),r=t.querySelector("ul"),i=document.createElement("ul");if(i.classList.add("tsd-hierarchy"),ft(i,n,e),r.querySelectorAll("li").length==i.querySelectorAll("li").length)return;let s=document.createElement("span");s.classList.add("tsd-hierarchy-toggle"),s.textContent=window.translations.hierarchy_expand,t.querySelector("h4 a")?.insertAdjacentElement("afterend",s),s.insertAdjacentText("beforebegin",", "),s.addEventListener("click",()=>{s.textContent===window.translations.hierarchy_expand?(r.insertAdjacentElement("afterend",i),r.remove(),s.textContent=window.translations.hierarchy_collapse):(i.insertAdjacentElement("afterend",r),i.remove(),s.textContent=window.translations.hierarchy_expand)})}function ft(t,e,n){let r=e.roots.filter(i=>mt(e,i,n));for(let i of r)t.appendChild(je(e,i,n))}function je(t,e,n,r=new Set){if(r.has(e))return;r.add(e);let i=t.reflections[e],s=document.createElement("li");if(s.classList.add("tsd-hierarchy-item"),e===n){let o=s.appendChild(document.createElement("span"));o.textContent=i.name,o.classList.add("tsd-hierarchy-target")}else{for(let a of i.uniqueNameParents||[]){let c=t.reflections[a],l=s.appendChild(document.createElement("a"));l.textContent=c.name,l.href=oe+c.url,l.className=c.class+" tsd-signature-type",s.append(document.createTextNode("."))}let o=s.appendChild(document.createElement("a"));o.textContent=t.reflections[e].name,o.href=oe+i.url,o.className=i.class+" tsd-signature-type"}if(i.children){let o=s.appendChild(document.createElement("ul"));o.classList.add("tsd-hierarchy");for(let a of i.children){let c=je(t,a,n,r);c&&o.appendChild(c)}}return r.delete(e),s}function mt(t,e,n){if(e===n)return!0;let r=new Set,i=[t.reflections[e]];for(;i.length;){let s=i.pop();if(!r.has(s)){r.add(s);for(let o of s.children||[]){if(o===n)return!0;i.push(t.reflections[o])}}}return!1}function gt(){let t=document.createElementNS("http://www.w3.org/2000/svg","svg");return t.setAttribute("width","20"),t.setAttribute("height","20"),t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","none"),t.innerHTML='',t}X(re,"a[data-toggle]");X(ie,".tsd-accordion");X(ee,".tsd-filter-item input[type=checkbox]");var qe=document.getElementById("tsd-theme");qe&&He(qe);var yt=new Z;Object.defineProperty(window,"app",{value:yt});_e();Ne();$e();"virtualKeyboard"in navigator&&(navigator.virtualKeyboard.overlaysContent=!0);})(); +/*! Bundled license information: + +lunr/lunr.js: + (** + * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 + * Copyright (C) 2020 Oliver Nightingale + * @license MIT + *) + (*! + * lunr.utils + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Set + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.tokenizer + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Pipeline + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Vector + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.stemmer + * Copyright (C) 2020 Oliver Nightingale + * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt + *) + (*! + * lunr.stopWordFilter + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.trimmer + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.TokenSet + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Index + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Builder + * Copyright (C) 2020 Oliver Nightingale + *) +*/ diff --git a/docs/assets/navigation.js b/docs/assets/navigation.js new file mode 100644 index 0000000..8a2de95 --- /dev/null +++ b/docs/assets/navigation.js @@ -0,0 +1 @@ +window.navigationData = "eJyNkEEOgjAQRe8ybhsFBBUOYELcuSUsGijQWJC0NYGY3t2ggpSCYTvz/8ubiZ4gSSMhgDPDOSCosSwggPKePhgRu266LWTJAMGNVikEDoKkoCzlpIIgWqgnDAvR102G7ZxUrJBWvpKcCsnbeYd+u9pFmLyx1MDTsv8taZWSxtR7j1d5hfqTaCUJz3AyMMKZb3uHkUG4cNk8aeEsHdkFL2TEkm09YL7LSd/yj7bnTBgzVuaDNlmX5L/kh+javru3XBWr+AWBj9y+" \ No newline at end of file diff --git a/docs/assets/search.js b/docs/assets/search.js new file mode 100644 index 0000000..3abc172 --- /dev/null +++ b/docs/assets/search.js @@ -0,0 +1 @@ +window.searchData = "eJytmU1v4zYQhv8LcyW8nqG+7PsWCHprgV4Eo3BtJRFiW4akpA2M/PeCMiVyRFKisjltIPN9Z0Q+HI64N1ZX/zZsm9/Ya3k5si1ydtmfC7Zlv532z4yzt/rEtuxcHd9ORfNDPly9tOcT4+xw2jdN0bAtY5+81wNmbgc1+u7gseHsuq+LS9trtW0MOrFDdWna+u3QVvWM+wMd6o+0GoWDNUZDvPf96a2Yi9QPCo+BCUKko+xP5b6Zi9IPWhBlHekF2R+PsxG6IV/0f5l/g5dfyb9sfp6v7cdcjLIp1LAvxqmLc/U+u+TDqC9Gaas/27q8zG2Rh7Zq+nELIpFd+EfxXDZt/eHcz/2Pi/Z1Y1ma2Q+WZOj8jh9MPVN2qM7/lBf3ykzEfNC6+dhU78uk8II4lcc8lwuzuLR1Wbg33WQeg+67Mnku2sVZ3DXflcFr8bF8IpTou3K47utmOZ296ruy6M6i5XMxyL4rj6e6Oi/OQol+JQd9XlyOxX9WzeueThY7jJPB45F0MeWlLeqn/WGweZxvZe5ZeJoLeuxP2M+c/cbwsD5mKtR0M+MO5W00Jt9potsICPMSOHVTTUdAmHHbMRVqrvcICDfqPqaizbQgAcGsJmQq3Gwn4gk43k528+COGtg5jDfYZMsQEmm2X3ApwzqFoPDBCC1uEMLCz3QHSxIw+4Kg4FNNwZLApB0IijzZCywJTbuAoNjTLcCS4KPDPyj6zMk/G36TQkw/OH4vNPLtx3WIrn5btp8j2ERiHc18f9jH+8OTHFjrgZPhdlz9tb2x96JuyurCtgxXYrVhnD2VxekoL0ruSXBZV85Sz9mxOrx1f+7UsL8KeeEgB99H/1gznq85pqsUk92O5724+6F70HvoJ50QfEKwhECEyHgOXOAqExERoiVEIhSM5+iKKCyhIMKI8Vy4hJEljIgwZjyPXMLYEsZEmDCexy5hYgkTIkwZzxOXMLWEKRFmjOepS5hZwowIN4znmUu4sYQbCoDkYeNaSLDZgRE8Eglw4+PghwIEHUHgFNsMAYUIJBrgxAhsjoCCBBIPcKIENktAYQKJCDhxApsnoECBxAScSIHNFFCoQKICTqzA5gooWCBxASdaYLMFFC6QyEDmhMTmCyhgKJkBJ2FoE4aUMJTM4NoptgnDUYlCX8VAR5GigKG3TKHNF1K+MPIVHLTxQooXxr6agzZdSOnCxFd20IYLKVyY+ioP2mwhZQszX/FBGy2kaKGEBd0HiY0WUrTE2ltChI2WoGgJ8JYQYaMlKFoCvSVE2GyJ0QkovCVEOA5BCpeIvCVE2HQJSpeIvSVE2HgJipdIvCVE2HwJypeQyCC61lnYgAkKmMi854ywCVOPum7rvajb4vh477ry/H5tcGN/qz5s6PhuLGbb2ydnGMl/P3X31T0dGjD5mwymrkq0k9BOkXLCIKfhQ1B7AWgzwLtOrAPdjP+OMhy1YVhW6vvQcEAjJ6FygjCv/mPPcDOmC9R8ibDMnrrLMm211k7ruyQsK+nzWpB3ROMdRRrsott/bbUx3i9s5UZfEsZcGW8IoOYqC/PsbjoNq8yw2gRZdB/LhoOxY0BtGSGCnF7ohom1UaI2TBzkU44JQGOCMGzxS+9so7lVwqZI3QEbk2SsPoat/nCpp10SbZKqCUqCvO63DEY6xlSDmmsRVubUpYHhZWQFKi0Rtm79TaI2S7VXpt4wbNfpW0JtZqC9UWZhm0RdRRsIGFVAOYUR3l9yGNNlvCKodxQBq7jj7Fpei5M8GLb57vPzfxMJqXc="; \ No newline at end of file diff --git a/docs/assets/style.css b/docs/assets/style.css new file mode 100644 index 0000000..5ba5a2a --- /dev/null +++ b/docs/assets/style.css @@ -0,0 +1,1633 @@ +@layer typedoc { + :root { + --dim-toolbar-contents-height: 2.5rem; + --dim-toolbar-border-bottom-width: 1px; + --dim-header-height: calc( + var(--dim-toolbar-border-bottom-width) + + var(--dim-toolbar-contents-height) + ); + + /* 0rem For mobile; unit is required for calculation in `calc` */ + --dim-container-main-margin-y: 0rem; + + --dim-footer-height: 3.5rem; + + --modal-animation-duration: 0.2s; + } + + :root { + /* Light */ + --light-color-background: #f2f4f8; + --light-color-background-secondary: #eff0f1; + /* Not to be confused with [:active](https://developer.mozilla.org/en-US/docs/Web/CSS/:active) */ + --light-color-background-active: #d6d8da; + --light-color-background-warning: #e6e600; + --light-color-warning-text: #222; + --light-color-accent: #c5c7c9; + --light-color-active-menu-item: var(--light-color-background-active); + --light-color-text: #222; + --light-color-contrast-text: #000; + --light-color-text-aside: #5e5e5e; + + --light-color-icon-background: var(--light-color-background); + --light-color-icon-text: var(--light-color-text); + + --light-color-comment-tag-text: var(--light-color-text); + --light-color-comment-tag: var(--light-color-background); + + --light-color-link: #1f70c2; + --light-color-focus-outline: #3584e4; + + --light-color-ts-keyword: #056bd6; + --light-color-ts-project: #b111c9; + --light-color-ts-module: var(--light-color-ts-project); + --light-color-ts-namespace: var(--light-color-ts-project); + --light-color-ts-enum: #7e6f15; + --light-color-ts-enum-member: var(--light-color-ts-enum); + --light-color-ts-variable: #4760ec; + --light-color-ts-function: #572be7; + --light-color-ts-class: #1f70c2; + --light-color-ts-interface: #108024; + --light-color-ts-constructor: var(--light-color-ts-class); + --light-color-ts-property: #9f5f30; + --light-color-ts-method: #be3989; + --light-color-ts-reference: #ff4d82; + --light-color-ts-call-signature: var(--light-color-ts-method); + --light-color-ts-index-signature: var(--light-color-ts-property); + --light-color-ts-constructor-signature: var( + --light-color-ts-constructor + ); + --light-color-ts-parameter: var(--light-color-ts-variable); + /* type literal not included as links will never be generated to it */ + --light-color-ts-type-parameter: #a55c0e; + --light-color-ts-accessor: #c73c3c; + --light-color-ts-get-signature: var(--light-color-ts-accessor); + --light-color-ts-set-signature: var(--light-color-ts-accessor); + --light-color-ts-type-alias: #d51270; + /* reference not included as links will be colored with the kind that it points to */ + --light-color-document: #000000; + + --light-color-alert-note: #0969d9; + --light-color-alert-tip: #1a7f37; + --light-color-alert-important: #8250df; + --light-color-alert-warning: #9a6700; + --light-color-alert-caution: #cf222e; + + --light-external-icon: url("data:image/svg+xml;utf8,"); + --light-color-scheme: light; + } + + :root { + /* Dark */ + --dark-color-background: #2b2e33; + --dark-color-background-secondary: #1e2024; + /* Not to be confused with [:active](https://developer.mozilla.org/en-US/docs/Web/CSS/:active) */ + --dark-color-background-active: #5d5d6a; + --dark-color-background-warning: #bebe00; + --dark-color-warning-text: #222; + --dark-color-accent: #9096a2; + --dark-color-active-menu-item: var(--dark-color-background-active); + --dark-color-text: #f5f5f5; + --dark-color-contrast-text: #ffffff; + --dark-color-text-aside: #dddddd; + + --dark-color-icon-background: var(--dark-color-background-secondary); + --dark-color-icon-text: var(--dark-color-text); + + --dark-color-comment-tag-text: var(--dark-color-text); + --dark-color-comment-tag: var(--dark-color-background); + + --dark-color-link: #00aff4; + --dark-color-focus-outline: #4c97f2; + + --dark-color-ts-keyword: #3399ff; + --dark-color-ts-project: #e358ff; + --dark-color-ts-module: var(--dark-color-ts-project); + --dark-color-ts-namespace: var(--dark-color-ts-project); + --dark-color-ts-enum: #f4d93e; + --dark-color-ts-enum-member: var(--dark-color-ts-enum); + --dark-color-ts-variable: #798dff; + --dark-color-ts-function: #a280ff; + --dark-color-ts-class: #8ac4ff; + --dark-color-ts-interface: #6cff87; + --dark-color-ts-constructor: var(--dark-color-ts-class); + --dark-color-ts-property: #ff984d; + --dark-color-ts-method: #ff4db8; + --dark-color-ts-reference: #ff4d82; + --dark-color-ts-call-signature: var(--dark-color-ts-method); + --dark-color-ts-index-signature: var(--dark-color-ts-property); + --dark-color-ts-constructor-signature: var(--dark-color-ts-constructor); + --dark-color-ts-parameter: var(--dark-color-ts-variable); + /* type literal not included as links will never be generated to it */ + --dark-color-ts-type-parameter: #e07d13; + --dark-color-ts-accessor: #ff6060; + --dark-color-ts-get-signature: var(--dark-color-ts-accessor); + --dark-color-ts-set-signature: var(--dark-color-ts-accessor); + --dark-color-ts-type-alias: #ff6492; + /* reference not included as links will be colored with the kind that it points to */ + --dark-color-document: #ffffff; + + --dark-color-alert-note: #0969d9; + --dark-color-alert-tip: #1a7f37; + --dark-color-alert-important: #8250df; + --dark-color-alert-warning: #9a6700; + --dark-color-alert-caution: #cf222e; + + --dark-external-icon: url("data:image/svg+xml;utf8,"); + --dark-color-scheme: dark; + } + + @media (prefers-color-scheme: light) { + :root { + --color-background: var(--light-color-background); + --color-background-secondary: var( + --light-color-background-secondary + ); + --color-background-active: var(--light-color-background-active); + --color-background-warning: var(--light-color-background-warning); + --color-warning-text: var(--light-color-warning-text); + --color-accent: var(--light-color-accent); + --color-active-menu-item: var(--light-color-active-menu-item); + --color-text: var(--light-color-text); + --color-contrast-text: var(--light-color-contrast-text); + --color-text-aside: var(--light-color-text-aside); + + --color-icon-background: var(--light-color-icon-background); + --color-icon-text: var(--light-color-icon-text); + + --color-comment-tag-text: var(--light-color-text); + --color-comment-tag: var(--light-color-background); + + --color-link: var(--light-color-link); + --color-focus-outline: var(--light-color-focus-outline); + + --color-ts-keyword: var(--light-color-ts-keyword); + --color-ts-project: var(--light-color-ts-project); + --color-ts-module: var(--light-color-ts-module); + --color-ts-namespace: var(--light-color-ts-namespace); + --color-ts-enum: var(--light-color-ts-enum); + --color-ts-enum-member: var(--light-color-ts-enum-member); + --color-ts-variable: var(--light-color-ts-variable); + --color-ts-function: var(--light-color-ts-function); + --color-ts-class: var(--light-color-ts-class); + --color-ts-interface: var(--light-color-ts-interface); + --color-ts-constructor: var(--light-color-ts-constructor); + --color-ts-property: var(--light-color-ts-property); + --color-ts-method: var(--light-color-ts-method); + --color-ts-reference: var(--light-color-ts-reference); + --color-ts-call-signature: var(--light-color-ts-call-signature); + --color-ts-index-signature: var(--light-color-ts-index-signature); + --color-ts-constructor-signature: var( + --light-color-ts-constructor-signature + ); + --color-ts-parameter: var(--light-color-ts-parameter); + --color-ts-type-parameter: var(--light-color-ts-type-parameter); + --color-ts-accessor: var(--light-color-ts-accessor); + --color-ts-get-signature: var(--light-color-ts-get-signature); + --color-ts-set-signature: var(--light-color-ts-set-signature); + --color-ts-type-alias: var(--light-color-ts-type-alias); + --color-document: var(--light-color-document); + + --color-alert-note: var(--light-color-alert-note); + --color-alert-tip: var(--light-color-alert-tip); + --color-alert-important: var(--light-color-alert-important); + --color-alert-warning: var(--light-color-alert-warning); + --color-alert-caution: var(--light-color-alert-caution); + + --external-icon: var(--light-external-icon); + --color-scheme: var(--light-color-scheme); + } + } + + @media (prefers-color-scheme: dark) { + :root { + --color-background: var(--dark-color-background); + --color-background-secondary: var( + --dark-color-background-secondary + ); + --color-background-active: var(--dark-color-background-active); + --color-background-warning: var(--dark-color-background-warning); + --color-warning-text: var(--dark-color-warning-text); + --color-accent: var(--dark-color-accent); + --color-active-menu-item: var(--dark-color-active-menu-item); + --color-text: var(--dark-color-text); + --color-contrast-text: var(--dark-color-contrast-text); + --color-text-aside: var(--dark-color-text-aside); + + --color-icon-background: var(--dark-color-icon-background); + --color-icon-text: var(--dark-color-icon-text); + + --color-comment-tag-text: var(--dark-color-text); + --color-comment-tag: var(--dark-color-background); + + --color-link: var(--dark-color-link); + --color-focus-outline: var(--dark-color-focus-outline); + + --color-ts-keyword: var(--dark-color-ts-keyword); + --color-ts-project: var(--dark-color-ts-project); + --color-ts-module: var(--dark-color-ts-module); + --color-ts-namespace: var(--dark-color-ts-namespace); + --color-ts-enum: var(--dark-color-ts-enum); + --color-ts-enum-member: var(--dark-color-ts-enum-member); + --color-ts-variable: var(--dark-color-ts-variable); + --color-ts-function: var(--dark-color-ts-function); + --color-ts-class: var(--dark-color-ts-class); + --color-ts-interface: var(--dark-color-ts-interface); + --color-ts-constructor: var(--dark-color-ts-constructor); + --color-ts-property: var(--dark-color-ts-property); + --color-ts-method: var(--dark-color-ts-method); + --color-ts-reference: var(--dark-color-ts-reference); + --color-ts-call-signature: var(--dark-color-ts-call-signature); + --color-ts-index-signature: var(--dark-color-ts-index-signature); + --color-ts-constructor-signature: var( + --dark-color-ts-constructor-signature + ); + --color-ts-parameter: var(--dark-color-ts-parameter); + --color-ts-type-parameter: var(--dark-color-ts-type-parameter); + --color-ts-accessor: var(--dark-color-ts-accessor); + --color-ts-get-signature: var(--dark-color-ts-get-signature); + --color-ts-set-signature: var(--dark-color-ts-set-signature); + --color-ts-type-alias: var(--dark-color-ts-type-alias); + --color-document: var(--dark-color-document); + + --color-alert-note: var(--dark-color-alert-note); + --color-alert-tip: var(--dark-color-alert-tip); + --color-alert-important: var(--dark-color-alert-important); + --color-alert-warning: var(--dark-color-alert-warning); + --color-alert-caution: var(--dark-color-alert-caution); + + --external-icon: var(--dark-external-icon); + --color-scheme: var(--dark-color-scheme); + } + } + + :root[data-theme="light"] { + --color-background: var(--light-color-background); + --color-background-secondary: var(--light-color-background-secondary); + --color-background-active: var(--light-color-background-active); + --color-background-warning: var(--light-color-background-warning); + --color-warning-text: var(--light-color-warning-text); + --color-icon-background: var(--light-color-icon-background); + --color-accent: var(--light-color-accent); + --color-active-menu-item: var(--light-color-active-menu-item); + --color-text: var(--light-color-text); + --color-contrast-text: var(--light-color-contrast-text); + --color-text-aside: var(--light-color-text-aside); + --color-icon-text: var(--light-color-icon-text); + + --color-comment-tag-text: var(--light-color-text); + --color-comment-tag: var(--light-color-background); + + --color-link: var(--light-color-link); + --color-focus-outline: var(--light-color-focus-outline); + + --color-ts-keyword: var(--light-color-ts-keyword); + --color-ts-project: var(--light-color-ts-project); + --color-ts-module: var(--light-color-ts-module); + --color-ts-namespace: var(--light-color-ts-namespace); + --color-ts-enum: var(--light-color-ts-enum); + --color-ts-enum-member: var(--light-color-ts-enum-member); + --color-ts-variable: var(--light-color-ts-variable); + --color-ts-function: var(--light-color-ts-function); + --color-ts-class: var(--light-color-ts-class); + --color-ts-interface: var(--light-color-ts-interface); + --color-ts-constructor: var(--light-color-ts-constructor); + --color-ts-property: var(--light-color-ts-property); + --color-ts-method: var(--light-color-ts-method); + --color-ts-reference: var(--light-color-ts-reference); + --color-ts-call-signature: var(--light-color-ts-call-signature); + --color-ts-index-signature: var(--light-color-ts-index-signature); + --color-ts-constructor-signature: var( + --light-color-ts-constructor-signature + ); + --color-ts-parameter: var(--light-color-ts-parameter); + --color-ts-type-parameter: var(--light-color-ts-type-parameter); + --color-ts-accessor: var(--light-color-ts-accessor); + --color-ts-get-signature: var(--light-color-ts-get-signature); + --color-ts-set-signature: var(--light-color-ts-set-signature); + --color-ts-type-alias: var(--light-color-ts-type-alias); + --color-document: var(--light-color-document); + + --color-note: var(--light-color-note); + --color-tip: var(--light-color-tip); + --color-important: var(--light-color-important); + --color-warning: var(--light-color-warning); + --color-caution: var(--light-color-caution); + + --external-icon: var(--light-external-icon); + --color-scheme: var(--light-color-scheme); + } + + :root[data-theme="dark"] { + --color-background: var(--dark-color-background); + --color-background-secondary: var(--dark-color-background-secondary); + --color-background-active: var(--dark-color-background-active); + --color-background-warning: var(--dark-color-background-warning); + --color-warning-text: var(--dark-color-warning-text); + --color-icon-background: var(--dark-color-icon-background); + --color-accent: var(--dark-color-accent); + --color-active-menu-item: var(--dark-color-active-menu-item); + --color-text: var(--dark-color-text); + --color-contrast-text: var(--dark-color-contrast-text); + --color-text-aside: var(--dark-color-text-aside); + --color-icon-text: var(--dark-color-icon-text); + + --color-comment-tag-text: var(--dark-color-text); + --color-comment-tag: var(--dark-color-background); + + --color-link: var(--dark-color-link); + --color-focus-outline: var(--dark-color-focus-outline); + + --color-ts-keyword: var(--dark-color-ts-keyword); + --color-ts-project: var(--dark-color-ts-project); + --color-ts-module: var(--dark-color-ts-module); + --color-ts-namespace: var(--dark-color-ts-namespace); + --color-ts-enum: var(--dark-color-ts-enum); + --color-ts-enum-member: var(--dark-color-ts-enum-member); + --color-ts-variable: var(--dark-color-ts-variable); + --color-ts-function: var(--dark-color-ts-function); + --color-ts-class: var(--dark-color-ts-class); + --color-ts-interface: var(--dark-color-ts-interface); + --color-ts-constructor: var(--dark-color-ts-constructor); + --color-ts-property: var(--dark-color-ts-property); + --color-ts-method: var(--dark-color-ts-method); + --color-ts-reference: var(--dark-color-ts-reference); + --color-ts-call-signature: var(--dark-color-ts-call-signature); + --color-ts-index-signature: var(--dark-color-ts-index-signature); + --color-ts-constructor-signature: var( + --dark-color-ts-constructor-signature + ); + --color-ts-parameter: var(--dark-color-ts-parameter); + --color-ts-type-parameter: var(--dark-color-ts-type-parameter); + --color-ts-accessor: var(--dark-color-ts-accessor); + --color-ts-get-signature: var(--dark-color-ts-get-signature); + --color-ts-set-signature: var(--dark-color-ts-set-signature); + --color-ts-type-alias: var(--dark-color-ts-type-alias); + --color-document: var(--dark-color-document); + + --color-note: var(--dark-color-note); + --color-tip: var(--dark-color-tip); + --color-important: var(--dark-color-important); + --color-warning: var(--dark-color-warning); + --color-caution: var(--dark-color-caution); + + --external-icon: var(--dark-external-icon); + --color-scheme: var(--dark-color-scheme); + } + + html { + color-scheme: var(--color-scheme); + @media (prefers-reduced-motion: no-preference) { + scroll-behavior: smooth; + } + } + + *:focus-visible, + .tsd-accordion-summary:focus-visible svg { + outline: 2px solid var(--color-focus-outline); + } + + .always-visible, + .always-visible .tsd-signatures { + display: inherit !important; + } + + h1, + h2, + h3, + h4, + h5, + h6 { + line-height: 1.2; + } + + h1 { + font-size: 1.875rem; + margin: 0.67rem 0; + } + + h2 { + font-size: 1.5rem; + margin: 0.83rem 0; + } + + h3 { + font-size: 1.25rem; + margin: 1rem 0; + } + + h4 { + font-size: 1.05rem; + margin: 1.33rem 0; + } + + h5 { + font-size: 1rem; + margin: 1.5rem 0; + } + + h6 { + font-size: 0.875rem; + margin: 2.33rem 0; + } + + dl, + menu, + ol, + ul { + margin: 1em 0; + } + + dd { + margin: 0 0 0 34px; + } + + .container { + max-width: 1700px; + padding: 0 2rem; + } + + /* Footer */ + footer { + border-top: 1px solid var(--color-accent); + padding-top: 1rem; + padding-bottom: 1rem; + max-height: var(--dim-footer-height); + } + footer > p { + margin: 0 1em; + } + + .container-main { + margin: var(--dim-container-main-margin-y) auto; + /* toolbar, footer, margin */ + min-height: calc( + 100svh - var(--dim-header-height) - var(--dim-footer-height) - + 2 * var(--dim-container-main-margin-y) + ); + } + + @keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } + } + @keyframes fade-out { + from { + opacity: 1; + visibility: visible; + } + to { + opacity: 0; + } + } + @keyframes pop-in-from-right { + from { + transform: translate(100%, 0); + } + to { + transform: translate(0, 0); + } + } + @keyframes pop-out-to-right { + from { + transform: translate(0, 0); + visibility: visible; + } + to { + transform: translate(100%, 0); + } + } + body { + background: var(--color-background); + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", + Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; + font-size: 16px; + color: var(--color-text); + margin: 0; + } + + a { + color: var(--color-link); + text-decoration: none; + } + a:hover { + text-decoration: underline; + } + a.external[target="_blank"] { + background-image: var(--external-icon); + background-position: top 3px right; + background-repeat: no-repeat; + padding-right: 13px; + } + a.tsd-anchor-link { + color: var(--color-text); + } + :target { + scroll-margin-block: calc(var(--dim-header-height) + 0.5rem); + } + + code, + pre { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + padding: 0.2em; + margin: 0; + font-size: 0.875rem; + border-radius: 0.8em; + } + + pre { + position: relative; + white-space: pre-wrap; + word-wrap: break-word; + padding: 10px; + border: 1px solid var(--color-accent); + margin-bottom: 8px; + } + pre code { + padding: 0; + font-size: 100%; + } + pre > button { + position: absolute; + top: 10px; + right: 10px; + opacity: 0; + transition: opacity 0.1s; + box-sizing: border-box; + } + pre:hover > button, + pre > button.visible, + pre > button:focus-visible { + opacity: 1; + } + + blockquote { + margin: 1em 0; + padding-left: 1em; + border-left: 4px solid gray; + } + + img { + max-width: 100%; + } + + * { + scrollbar-width: thin; + scrollbar-color: var(--color-accent) var(--color-icon-background); + } + + *::-webkit-scrollbar { + width: 0.75rem; + } + + *::-webkit-scrollbar-track { + background: var(--color-icon-background); + } + + *::-webkit-scrollbar-thumb { + background-color: var(--color-accent); + border-radius: 999rem; + border: 0.25rem solid var(--color-icon-background); + } + + dialog { + border: none; + outline: none; + padding: 0; + background-color: var(--color-background); + } + dialog::backdrop { + display: none; + } + #tsd-overlay { + background-color: rgba(0, 0, 0, 0.5); + position: fixed; + z-index: 9999; + top: 0; + left: 0; + right: 0; + bottom: 0; + animation: fade-in var(--modal-animation-duration) forwards; + } + #tsd-overlay.closing { + animation-name: fade-out; + } + + .tsd-typography { + line-height: 1.333em; + } + .tsd-typography ul { + list-style: square; + padding: 0 0 0 20px; + margin: 0; + } + .tsd-typography .tsd-index-panel h3, + .tsd-index-panel .tsd-typography h3, + .tsd-typography h4, + .tsd-typography h5, + .tsd-typography h6 { + font-size: 1em; + } + .tsd-typography h5, + .tsd-typography h6 { + font-weight: normal; + } + .tsd-typography p, + .tsd-typography ul, + .tsd-typography ol { + margin: 1em 0; + } + .tsd-typography table { + border-collapse: collapse; + border: none; + } + .tsd-typography td, + .tsd-typography th { + padding: 6px 13px; + border: 1px solid var(--color-accent); + } + .tsd-typography thead, + .tsd-typography tr:nth-child(even) { + background-color: var(--color-background-secondary); + } + + .tsd-alert { + padding: 8px 16px; + margin-bottom: 16px; + border-left: 0.25em solid var(--alert-color); + } + .tsd-alert blockquote > :last-child, + .tsd-alert > :last-child { + margin-bottom: 0; + } + .tsd-alert-title { + color: var(--alert-color); + display: inline-flex; + align-items: center; + } + .tsd-alert-title span { + margin-left: 4px; + } + + .tsd-alert-note { + --alert-color: var(--color-alert-note); + } + .tsd-alert-tip { + --alert-color: var(--color-alert-tip); + } + .tsd-alert-important { + --alert-color: var(--color-alert-important); + } + .tsd-alert-warning { + --alert-color: var(--color-alert-warning); + } + .tsd-alert-caution { + --alert-color: var(--color-alert-caution); + } + + .tsd-breadcrumb { + margin: 0; + margin-top: 1rem; + padding: 0; + color: var(--color-text-aside); + } + .tsd-breadcrumb a { + color: var(--color-text-aside); + text-decoration: none; + } + .tsd-breadcrumb a:hover { + text-decoration: underline; + } + .tsd-breadcrumb li { + display: inline; + } + .tsd-breadcrumb li:after { + content: " / "; + } + + .tsd-comment-tags { + display: flex; + flex-direction: column; + } + dl.tsd-comment-tag-group { + display: flex; + align-items: center; + overflow: hidden; + margin: 0.5em 0; + } + dl.tsd-comment-tag-group dt { + display: flex; + margin-right: 0.5em; + font-size: 0.875em; + font-weight: normal; + } + dl.tsd-comment-tag-group dd { + margin: 0; + } + code.tsd-tag { + padding: 0.25em 0.4em; + border: 0.1em solid var(--color-accent); + margin-right: 0.25em; + font-size: 70%; + } + h1 code.tsd-tag:first-of-type { + margin-left: 0.25em; + } + + dl.tsd-comment-tag-group dd:before, + dl.tsd-comment-tag-group dd:after { + content: " "; + } + dl.tsd-comment-tag-group dd pre, + dl.tsd-comment-tag-group dd:after { + clear: both; + } + dl.tsd-comment-tag-group p { + margin: 0; + } + + .tsd-panel.tsd-comment .lead { + font-size: 1.1em; + line-height: 1.333em; + margin-bottom: 2em; + } + .tsd-panel.tsd-comment .lead:last-child { + margin-bottom: 0; + } + + .tsd-filter-visibility h4 { + font-size: 1rem; + padding-top: 0.75rem; + padding-bottom: 0.5rem; + margin: 0; + } + .tsd-filter-item:not(:last-child) { + margin-bottom: 0.5rem; + } + .tsd-filter-input { + display: flex; + width: -moz-fit-content; + width: fit-content; + align-items: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + } + .tsd-filter-input input[type="checkbox"] { + cursor: pointer; + position: absolute; + width: 1.5em; + height: 1.5em; + opacity: 0; + } + .tsd-filter-input input[type="checkbox"]:disabled { + pointer-events: none; + } + .tsd-filter-input svg { + cursor: pointer; + width: 1.5em; + height: 1.5em; + margin-right: 0.5em; + border-radius: 0.33em; + /* Leaving this at full opacity breaks event listeners on Firefox. + Don't remove unless you know what you're doing. */ + opacity: 0.99; + } + .tsd-filter-input input[type="checkbox"]:focus-visible + svg { + outline: 2px solid var(--color-focus-outline); + } + .tsd-checkbox-background { + fill: var(--color-accent); + } + input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { + stroke: var(--color-text); + } + .tsd-filter-input input:disabled ~ svg > .tsd-checkbox-background { + fill: var(--color-background); + stroke: var(--color-accent); + stroke-width: 0.25rem; + } + .tsd-filter-input input:disabled ~ svg > .tsd-checkbox-checkmark { + stroke: var(--color-accent); + } + + .settings-label { + font-weight: bold; + text-transform: uppercase; + display: inline-block; + } + + .tsd-filter-visibility .settings-label { + margin: 0.75rem 0 0.5rem 0; + } + + .tsd-theme-toggle .settings-label { + margin: 0.75rem 0.75rem 0 0; + } + + .tsd-hierarchy h4 label:hover span { + text-decoration: underline; + } + + .tsd-hierarchy { + list-style: square; + margin: 0; + } + .tsd-hierarchy-target { + font-weight: bold; + } + .tsd-hierarchy-toggle { + color: var(--color-link); + cursor: pointer; + } + + .tsd-full-hierarchy:not(:last-child) { + margin-bottom: 1em; + padding-bottom: 1em; + border-bottom: 1px solid var(--color-accent); + } + .tsd-full-hierarchy, + .tsd-full-hierarchy ul { + list-style: none; + margin: 0; + padding: 0; + } + .tsd-full-hierarchy ul { + padding-left: 1.5rem; + } + .tsd-full-hierarchy a { + padding: 0.25rem 0 !important; + font-size: 1rem; + display: inline-flex; + align-items: center; + color: var(--color-text); + } + .tsd-full-hierarchy svg[data-dropdown] { + cursor: pointer; + } + .tsd-full-hierarchy svg[data-dropdown="false"] { + transform: rotate(-90deg); + } + .tsd-full-hierarchy svg[data-dropdown="false"] ~ ul { + display: none; + } + + .tsd-panel-group.tsd-index-group { + margin-bottom: 0; + } + .tsd-index-panel .tsd-index-list { + list-style: none; + line-height: 1.333em; + margin: 0; + padding: 0.25rem 0 0 0; + overflow: hidden; + display: grid; + grid-template-columns: repeat(3, 1fr); + column-gap: 1rem; + grid-template-rows: auto; + } + @media (max-width: 1024px) { + .tsd-index-panel .tsd-index-list { + grid-template-columns: repeat(2, 1fr); + } + } + @media (max-width: 768px) { + .tsd-index-panel .tsd-index-list { + grid-template-columns: repeat(1, 1fr); + } + } + .tsd-index-panel .tsd-index-list li { + -webkit-page-break-inside: avoid; + -moz-page-break-inside: avoid; + -ms-page-break-inside: avoid; + -o-page-break-inside: avoid; + page-break-inside: avoid; + } + + .tsd-flag { + display: inline-block; + padding: 0.25em 0.4em; + border-radius: 4px; + color: var(--color-comment-tag-text); + background-color: var(--color-comment-tag); + text-indent: 0; + font-size: 75%; + line-height: 1; + font-weight: normal; + } + + .tsd-anchor { + position: relative; + top: -100px; + } + + .tsd-member { + position: relative; + } + .tsd-member .tsd-anchor + h3 { + display: flex; + align-items: center; + margin-top: 0; + margin-bottom: 0; + border-bottom: none; + } + + .tsd-navigation.settings { + margin: 0; + margin-bottom: 1rem; + } + .tsd-navigation > a, + .tsd-navigation .tsd-accordion-summary { + width: calc(100% - 0.25rem); + display: flex; + align-items: center; + } + .tsd-navigation a, + .tsd-navigation summary > span, + .tsd-page-navigation a { + display: flex; + width: calc(100% - 0.25rem); + align-items: center; + padding: 0.25rem; + color: var(--color-text); + text-decoration: none; + box-sizing: border-box; + } + .tsd-navigation a.current, + .tsd-page-navigation a.current { + background: var(--color-active-menu-item); + color: var(--color-contrast-text); + } + .tsd-navigation a:hover, + .tsd-page-navigation a:hover { + text-decoration: underline; + } + .tsd-navigation ul, + .tsd-page-navigation ul { + margin-top: 0; + margin-bottom: 0; + padding: 0; + list-style: none; + } + .tsd-navigation li, + .tsd-page-navigation li { + padding: 0; + max-width: 100%; + } + .tsd-navigation .tsd-nav-link { + display: none; + } + .tsd-nested-navigation { + margin-left: 3rem; + } + .tsd-nested-navigation > li > details { + margin-left: -1.5rem; + } + .tsd-small-nested-navigation { + margin-left: 1.5rem; + } + .tsd-small-nested-navigation > li > details { + margin-left: -1.5rem; + } + + .tsd-page-navigation-section > summary { + padding: 0.25rem; + } + .tsd-page-navigation-section > summary > svg { + margin-right: 0.25rem; + } + .tsd-page-navigation-section > div { + margin-left: 30px; + } + .tsd-page-navigation ul { + padding-left: 1.75rem; + } + + #tsd-sidebar-links a { + margin-top: 0; + margin-bottom: 0.5rem; + line-height: 1.25rem; + } + #tsd-sidebar-links a:last-of-type { + margin-bottom: 0; + } + + a.tsd-index-link { + padding: 0.25rem 0 !important; + font-size: 1rem; + line-height: 1.25rem; + display: inline-flex; + align-items: center; + color: var(--color-text); + } + .tsd-accordion-summary { + list-style-type: none; /* hide marker on non-safari */ + outline: none; /* broken on safari, so just hide it */ + display: flex; + align-items: center; + gap: 0.25rem; + box-sizing: border-box; + } + .tsd-accordion-summary::-webkit-details-marker { + display: none; /* hide marker on safari */ + } + .tsd-accordion-summary, + .tsd-accordion-summary a { + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + + cursor: pointer; + } + .tsd-accordion-summary a { + width: calc(100% - 1.5rem); + } + .tsd-accordion-summary > * { + margin-top: 0; + margin-bottom: 0; + padding-top: 0; + padding-bottom: 0; + } + /* + * We need to be careful to target the arrow indicating whether the accordion + * is open, but not any other SVGs included in the details element. + */ + .tsd-accordion:not([open]) > .tsd-accordion-summary > svg:first-child { + transform: rotate(-90deg); + } + .tsd-index-content > :not(:first-child) { + margin-top: 0.75rem; + } + .tsd-index-summary { + margin-top: 1.5rem; + margin-bottom: 0.75rem; + display: flex; + align-content: center; + } + + .tsd-no-select { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + .tsd-kind-icon { + margin-right: 0.5rem; + width: 1.25rem; + height: 1.25rem; + min-width: 1.25rem; + min-height: 1.25rem; + } + .tsd-signature > .tsd-kind-icon { + margin-right: 0.8rem; + } + + .tsd-panel { + margin-bottom: 2.5rem; + } + .tsd-panel.tsd-member { + margin-bottom: 4rem; + } + .tsd-panel:empty { + display: none; + } + .tsd-panel > h1, + .tsd-panel > h2, + .tsd-panel > h3 { + margin: 1.5rem -1.5rem 0.75rem -1.5rem; + padding: 0 1.5rem 0.75rem 1.5rem; + } + .tsd-panel > h1.tsd-before-signature, + .tsd-panel > h2.tsd-before-signature, + .tsd-panel > h3.tsd-before-signature { + margin-bottom: 0; + border-bottom: none; + } + + .tsd-panel-group { + margin: 2rem 0; + } + .tsd-panel-group.tsd-index-group { + margin: 2rem 0; + } + .tsd-panel-group.tsd-index-group details { + margin: 2rem 0; + } + .tsd-panel-group > .tsd-accordion-summary { + margin-bottom: 1rem; + } + + #tsd-search[open] { + animation: fade-in var(--modal-animation-duration) ease-out forwards; + } + #tsd-search[open].closing { + animation-name: fade-out; + } + + /* Avoid setting `display` on closed dialog */ + #tsd-search[open] { + display: flex; + flex-direction: column; + padding: 1rem; + width: 32rem; + max-width: 90vw; + max-height: calc(100vh - env(keyboard-inset-height, 0px) - 25vh); + /* Anchor dialog to top */ + margin-top: 10vh; + border-radius: 6px; + will-change: max-height; + } + #tsd-search-input { + box-sizing: border-box; + width: 100%; + padding: 0 0.625rem; /* 10px */ + outline: 0; + border: 2px solid var(--color-accent); + background-color: transparent; + color: var(--color-text); + border-radius: 4px; + height: 2.5rem; + flex: 0 0 auto; + font-size: 0.875rem; + transition: border-color 0.2s, background-color 0.2s; + } + #tsd-search-input:focus-visible { + background-color: var(--color-background-active); + border-color: transparent; + color: var(--color-contrast-text); + } + #tsd-search-input::placeholder { + color: inherit; + opacity: 0.8; + } + #tsd-search-results { + margin: 0; + padding: 0; + list-style: none; + flex: 1 1 auto; + display: flex; + flex-direction: column; + overflow-y: auto; + } + #tsd-search-results:not(:empty) { + margin-top: 0.5rem; + } + #tsd-search-results > li { + background-color: var(--color-background); + line-height: 1.5; + box-sizing: border-box; + border-radius: 4px; + } + #tsd-search-results > li:nth-child(even) { + background-color: var(--color-background-secondary); + } + #tsd-search-results > li:is(:hover, [aria-selected="true"]) { + background-color: var(--color-background-active); + color: var(--color-contrast-text); + } + /* It's important that this takes full size of parent `li`, to capture a click on `li` */ + #tsd-search-results > li > a { + display: flex; + align-items: center; + padding: 0.5rem 0.25rem; + box-sizing: border-box; + width: 100%; + } + #tsd-search-results > li > a > .text { + flex: 1 1 auto; + min-width: 0; + overflow-wrap: anywhere; + } + #tsd-search-results > li > a .parent { + color: var(--color-text-aside); + } + #tsd-search-results > li > a mark { + color: inherit; + background-color: inherit; + font-weight: bold; + } + #tsd-search-status { + flex: 1; + display: grid; + place-content: center; + text-align: center; + overflow-wrap: anywhere; + } + #tsd-search-status:not(:empty) { + min-height: 6rem; + } + + .tsd-signature { + margin: 0 0 1rem 0; + padding: 1rem 0.5rem; + border: 1px solid var(--color-accent); + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + font-size: 14px; + overflow-x: auto; + } + + .tsd-signature-keyword { + color: var(--color-ts-keyword); + font-weight: normal; + } + + .tsd-signature-symbol { + color: var(--color-text-aside); + font-weight: normal; + } + + .tsd-signature-type { + font-style: italic; + font-weight: normal; + } + + .tsd-signatures { + padding: 0; + margin: 0 0 1em 0; + list-style-type: none; + } + .tsd-signatures .tsd-signature { + margin: 0; + border-color: var(--color-accent); + border-width: 1px 0; + transition: background-color 0.1s; + } + .tsd-signatures .tsd-index-signature:not(:last-child) { + margin-bottom: 1em; + } + .tsd-signatures .tsd-index-signature .tsd-signature { + border-width: 1px; + } + .tsd-description .tsd-signatures .tsd-signature { + border-width: 1px; + } + + ul.tsd-parameter-list, + ul.tsd-type-parameter-list { + list-style: square; + margin: 0; + padding-left: 20px; + } + ul.tsd-parameter-list > li.tsd-parameter-signature, + ul.tsd-type-parameter-list > li.tsd-parameter-signature { + list-style: none; + margin-left: -20px; + } + ul.tsd-parameter-list h5, + ul.tsd-type-parameter-list h5 { + font-size: 16px; + margin: 1em 0 0.5em 0; + } + .tsd-sources { + margin-top: 1rem; + font-size: 0.875em; + } + .tsd-sources a { + color: var(--color-text-aside); + text-decoration: underline; + } + .tsd-sources ul { + list-style: none; + padding: 0; + } + + .tsd-page-toolbar { + position: sticky; + z-index: 1; + top: 0; + left: 0; + width: 100%; + color: var(--color-text); + background: var(--color-background-secondary); + border-bottom: var(--dim-toolbar-border-bottom-width) + var(--color-accent) solid; + transition: transform 0.3s ease-in-out; + } + .tsd-page-toolbar a { + color: var(--color-text); + } + .tsd-toolbar-contents { + display: flex; + align-items: center; + height: var(--dim-toolbar-contents-height); + margin: 0 auto; + } + .tsd-toolbar-contents > .title { + font-weight: bold; + margin-right: auto; + } + #tsd-toolbar-links { + display: flex; + align-items: center; + gap: 1.5rem; + margin-right: 1rem; + } + + .tsd-widget { + box-sizing: border-box; + display: inline-block; + opacity: 0.8; + height: 2.5rem; + width: 2.5rem; + transition: opacity 0.1s, background-color 0.1s; + text-align: center; + cursor: pointer; + border: none; + background-color: transparent; + } + .tsd-widget:hover { + opacity: 0.9; + } + .tsd-widget:active { + opacity: 1; + background-color: var(--color-accent); + } + #tsd-toolbar-menu-trigger { + display: none; + } + + .tsd-member-summary-name { + display: inline-flex; + align-items: center; + padding: 0.25rem; + text-decoration: none; + } + + .tsd-anchor-icon { + display: inline-flex; + align-items: center; + margin-left: 0.5rem; + color: var(--color-text); + vertical-align: middle; + } + + .tsd-anchor-icon svg { + width: 1em; + height: 1em; + visibility: hidden; + } + + .tsd-member-summary-name:hover > .tsd-anchor-icon svg, + .tsd-anchor-link:hover > .tsd-anchor-icon svg, + .tsd-anchor-icon:focus-visible svg { + visibility: visible; + } + + .deprecated { + text-decoration: line-through !important; + } + + .warning { + padding: 1rem; + color: var(--color-warning-text); + background: var(--color-background-warning); + } + + .tsd-kind-project { + color: var(--color-ts-project); + } + .tsd-kind-module { + color: var(--color-ts-module); + } + .tsd-kind-namespace { + color: var(--color-ts-namespace); + } + .tsd-kind-enum { + color: var(--color-ts-enum); + } + .tsd-kind-enum-member { + color: var(--color-ts-enum-member); + } + .tsd-kind-variable { + color: var(--color-ts-variable); + } + .tsd-kind-function { + color: var(--color-ts-function); + } + .tsd-kind-class { + color: var(--color-ts-class); + } + .tsd-kind-interface { + color: var(--color-ts-interface); + } + .tsd-kind-constructor { + color: var(--color-ts-constructor); + } + .tsd-kind-property { + color: var(--color-ts-property); + } + .tsd-kind-method { + color: var(--color-ts-method); + } + .tsd-kind-reference { + color: var(--color-ts-reference); + } + .tsd-kind-call-signature { + color: var(--color-ts-call-signature); + } + .tsd-kind-index-signature { + color: var(--color-ts-index-signature); + } + .tsd-kind-constructor-signature { + color: var(--color-ts-constructor-signature); + } + .tsd-kind-parameter { + color: var(--color-ts-parameter); + } + .tsd-kind-type-parameter { + color: var(--color-ts-type-parameter); + } + .tsd-kind-accessor { + color: var(--color-ts-accessor); + } + .tsd-kind-get-signature { + color: var(--color-ts-get-signature); + } + .tsd-kind-set-signature { + color: var(--color-ts-set-signature); + } + .tsd-kind-type-alias { + color: var(--color-ts-type-alias); + } + + /* if we have a kind icon, don't color the text by kind */ + .tsd-kind-icon ~ span { + color: var(--color-text); + } + + /* mobile */ + @media (max-width: 769px) { + #tsd-toolbar-menu-trigger { + display: inline-block; + /* temporary fix to vertically align, for compatibility */ + line-height: 2.5; + } + #tsd-toolbar-links { + display: none; + } + + .container-main { + display: flex; + } + .col-content { + float: none; + max-width: 100%; + width: 100%; + } + .col-sidebar { + position: fixed !important; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + z-index: 1024; + top: 0 !important; + bottom: 0 !important; + left: auto !important; + right: 0 !important; + padding: 1.5rem 1.5rem 0 0; + width: 75vw; + visibility: hidden; + background-color: var(--color-background); + transform: translate(100%, 0); + } + .col-sidebar > *:last-child { + padding-bottom: 20px; + } + .overlay { + content: ""; + display: block; + position: fixed; + z-index: 1023; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.75); + visibility: hidden; + } + + .to-has-menu .overlay { + animation: fade-in 0.4s; + } + + .to-has-menu .col-sidebar { + animation: pop-in-from-right 0.4s; + } + + .from-has-menu .overlay { + animation: fade-out 0.4s; + } + + .from-has-menu .col-sidebar { + animation: pop-out-to-right 0.4s; + } + + .has-menu body { + overflow: hidden; + } + .has-menu .overlay { + visibility: visible; + } + .has-menu .col-sidebar { + visibility: visible; + transform: translate(0, 0); + display: flex; + flex-direction: column; + gap: 1.5rem; + max-height: 100vh; + padding: 1rem 2rem; + } + .has-menu .tsd-navigation { + max-height: 100%; + } + .tsd-navigation .tsd-nav-link { + display: flex; + } + } + + /* one sidebar */ + @media (min-width: 770px) { + .container-main { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); + grid-template-areas: "sidebar content"; + --dim-container-main-margin-y: 2rem; + } + + .tsd-breadcrumb { + margin-top: 0; + } + + .col-sidebar { + grid-area: sidebar; + } + .col-content { + grid-area: content; + padding: 0 1rem; + } + } + @media (min-width: 770px) and (max-width: 1399px) { + .col-sidebar { + max-height: calc( + 100vh - var(--dim-header-height) - var(--dim-footer-height) - + 2 * var(--dim-container-main-margin-y) + ); + overflow: auto; + position: sticky; + top: calc( + var(--dim-header-height) + var(--dim-container-main-margin-y) + ); + } + .site-menu { + margin-top: 1rem; + } + } + + /* two sidebars */ + @media (min-width: 1200px) { + .container-main { + grid-template-columns: + minmax(0, 1fr) minmax(0, 2.5fr) minmax( + 0, + 20rem + ); + grid-template-areas: "sidebar content toc"; + } + + .col-sidebar { + display: contents; + } + + .page-menu { + grid-area: toc; + padding-left: 1rem; + } + .site-menu { + grid-area: sidebar; + } + + .site-menu { + margin-top: 0rem; + } + + .page-menu, + .site-menu { + max-height: calc( + 100vh - var(--dim-header-height) - var(--dim-footer-height) - + 2 * var(--dim-container-main-margin-y) + ); + overflow: auto; + position: sticky; + top: calc( + var(--dim-header-height) + var(--dim-container-main-margin-y) + ); + } + } +} diff --git a/docs/classes/Flag.Flag.html b/docs/classes/Flag.Flag.html new file mode 100644 index 0000000..fb798bb --- /dev/null +++ b/docs/classes/Flag.Flag.html @@ -0,0 +1,112 @@ +Flag | bitwise-flag - v1.1.0
bitwise-flag - v1.1.0
    Preparing search index...

    Class Flag<TFlags>

    Represents a bitwise combination of flags from a registry. This class encapsulates a bitmask value +derived from one or more flag keys, enabling efficient storage and manipulation of boolean states +(e.g., permissions, features, or configurations) using bitwise operations.

    +
    const registry = FlagsRegistry.from("READ", "WRITE");
    const readFlag = new Flag(registry, 1n); // Represents the "READ" flag
    console.log(readFlag.value); // 1n +
    + +

    Type Parameters

    • TFlags extends FlagKey

      The type of flag keys, extending FlagKey (string literals for type safety).

      +

    Implements

    Index

    Constructors

    Properties

    Accessors

    Methods

    Constructors

    • Type Parameters

      • TFlags extends string

      Parameters

      • context: IFlagsRegistry<TFlags>

        The registry defining the valid flags and their bit positions.

        +
      • value: bigint

        The raw BigInt bitmask representing the combined flags (e.g., 3n for bits 0 and 1 set).

        +

      Returns Flag<TFlags>

      If value is negative (e.g., Flag value cannot be negative: -1).

      +

      If value contains unknown bits (e.g., Flag value contains unknown flags).

      +

    Properties

    value: bigint

    The raw BigInt bitmask representing the combined flags (e.g., 3n for bits 0 and 1 set).

    +

    Accessors

    • get alias(): string

      A computed, human-readable alias for the flag combination.

      +
        +
      • For empty flags (value 0n), returns "EMPTY_FLAG".
      • +
      • For single flags, returns e.g., "[READ]".
      • +
      • For multiple flags, returns e.g., "[READ+WRITE]".
      • +
      +

      Returns string

      flag.alias; // "[READ+WRITE]" for a combined flag
      +
      + +

    Methods

    • Adds one or more flag keys to this flag combination, creating a new instance with the updated bitmask.

      +
        +
      • Idempotent: If a flag is already set, it remains unchanged.
      • +
      • Only adds flags that exist in the registry; unknown keys throw an error.
      • +
      • Returns the current instance if no changes are made (e.g., all flags already present).
      • +
      +

      Parameters

      • ...flagNames: TFlags[]

        One or more flag keys to add.

        +

      Returns IFlag<TFlags>

      A new Flag instance with the added flags, or the current instance if unchanged.

      +

      If any flagName is not registered in the registry (e.g., Flag with key UNKNOWN is not found.).

      +
      const base = registry.combine("READ");
      const extended = base.add("WRITE", "EXECUTE");
      extended.has("WRITE"); // true
      base.has("WRITE"); // false (immutable) +
      + +
    • Tests whether a specific flag key is set in this flag combination.

      +

      Performs a bitwise AND between the instance's value and the bitmask of the given flag key. +Returns false if the key is not found in the registry.

      +

      Parameters

      • flagName: TFlags

        The flag key to check (must be a valid key in the registry).

        +

      Returns boolean

      true if the flag is set, false otherwise.

      +
      const userFlag = registry.combine("READ", "EXECUTE");
      userFlag.has("READ"); // true
      userFlag.has("WRITE"); // false +
      + +
    • Checks if this flag instance represents no set flags (i.e., the bitmask value is 0n).

      +

      Returns boolean

      true if the flag is empty, false otherwise.

      +
      const empty = registry.empty();
      empty.isEmpty(); // true

      const full = registry.combine("READ", "WRITE");
      full.isEmpty(); // false +
      + +
    • Removes one or more flag keys from this flag combination, creating a new instance with the updated bitmask.

      +
        +
      • Idempotent: If a flag is not set, it remains unchanged.
      • +
      • Only removes flags that exist in the registry; unknown keys throw an error.
      • +
      • Returns the current instance if no changes are made (e.g., none of the flags were present).
      • +
      +

      Parameters

      • ...flagNames: TFlags[]

        One or more flag keys to remove.

        +

      Returns IFlag<TFlags>

      A new Flag instance with the removed flags, or the current instance if unchanged.

      +

      If any flagName is not registered in the registry (e.g., Flag with key UNKNOWN is not found.).

      +
      const full = registry.combine("READ", "WRITE");
      const reduced = full.remove("WRITE");
      reduced.has("WRITE"); // false
      full.has("WRITE"); // true (immutable) +
      + +
    • Returns a human-readable string representation of this flag instance.

      +

      The format is Flag(${alias}: ${value}), where alias is the computed alias (e.g., [READ+WRITE]) +and value is the raw BigInt bitmask.

      +

      Returns string

      A string like Flag([READ+WRITE]: 3).

      +
      const flag = registry.combine("READ");
      flag.toString(); // "Flag([READ]: 1)"

      const empty = registry.empty();
      empty.toString(); // "Flag(EMPTY_FLAG: 0)" +
      + +

    Generated using TypeDoc
    + + +

    diff --git a/docs/classes/FlagRegistry.FlagsRegistry.html b/docs/classes/FlagRegistry.FlagsRegistry.html new file mode 100644 index 0000000..5209b2d --- /dev/null +++ b/docs/classes/FlagRegistry.FlagsRegistry.html @@ -0,0 +1,101 @@ +FlagsRegistry | bitwise-flag - v1.1.0
    bitwise-flag - v1.1.0
      Preparing search index...

      Class FlagsRegistry<TFlags>

      A registry for managing bitwise flags. This class maps flag keys (strings) to unique bit positions +using BigInt for scalable storage.

      +

      Type Parameters

      • TFlags extends FlagKey

        The type of flag keys, extending string.

        +

      Implements

      Index

      Methods

      • Combines multiple flag keys into a single flag instance.

        +

        Parameters

        • ...flagKeys: TFlags[]

          The flag keys to combine.

          +

        Returns IFlag<TFlags>

        A flag instance representing the combined flags.

        +
        const registry = FlagsRegistry.from("READ", "WRITE", "EXECUTE");
        const combinedFlag = registry.combine("READ", "EXECUTE");
        combinedFlag.has("READ"); // true
        combinedFlag.has("WRITE"); // false
        combinedFlag.has("EXECUTE"); // true +
        + +
      • Returns a flag instance representing no set flags (i.e., a bitmask value of 0n).

        +

        Returns IFlag<TFlags>

        A flag instance with no flags set.

        +
        const registry = FlagsRegistry.from("READ", "WRITE");
        const emptyFlag = registry.empty();
        emptyFlag.isEmpty(); // true +
        + +
      • Retrieves the BigInt value associated with the given flag name.

        +

        Parameters

        • flagName: TFlags

          The name of the flag to retrieve.

          +

        Returns bigint | undefined

        The BigInt value of the flag, or undefined if not found.

        +
        const registry = FlagsRegistry.from("READ", "WRITE");
        registry.get("READ"); // 1n
        registry.get("WRITE"); // 2n
        registry.get("EXECUTE"); // undefined +
        + +
      • Parses a number value to create a flag instance.

        +

        Parameters

        • value: number

          The numeric value to parse.

          +

        Returns IFlag<TFlags>

        A flag instance representing the parsed value.

        +

        If the value is negative or contains unknown flags.

        +
        const registry = FlagsRegistry.from("READ", "WRITE");
        const flag = registry.parse(3); // Represents both READ and WRITE flags
        flag.has("READ"); // true
        flag.has("WRITE"); // true +
        + +
      • Parses a bigint value to create a flag instance.

        +

        Parameters

        • value: bigint

          The BigInt value to parse.

          +

        Returns IFlag<TFlags>

        A flag instance representing the parsed value.

        +

        If the value is negative or contains unknown flags.

        +
        const registry = FlagsRegistry.from("READ", "WRITE");
        const flag = registry.parse(3n); // Represents both READ and WRITE flags
        flag.has("READ"); // true
        flag.has("WRITE"); // true +
        + +
      • Parses a string value to create a flag instance.

        +

        Parameters

        • value: string

          The string value to parse.

          +
        • Optionalradix: number

          The radix to use when parsing the string (default is 10).

          +

        Returns IFlag<TFlags>

        A flag instance representing the parsed value.

        +

        If the value cannot be parsed, is negative, or contains unknown flags.

        +
        const registry = FlagsRegistry.from("READ", "WRITE");
        const flag = registry.parse("3"); // Represents both READ and WRITE flags
        flag.has("READ"); // true
        flag.has("WRITE"); // true

        const hexFlag = registry.parse("3", 16); // Parses "3" as hexadecimal
        hexFlag.has("READ"); // true
        hexFlag.has("WRITE"); // true

        const binaryFlag = registry.parse("11", 2); // Parses "11" as binary
        binaryFlag.has("READ"); // true
        binaryFlag.has("WRITE"); // true +
        + +
      • Returns an iterator over the flag values in the registry.

        +

        Returns MapIterator<bigint>

        An iterator over the flag values.

        +
      • Creates a new FlagsRegistry from the provided flag keys, assigning each a unique bit position.

        +

        Type Parameters

        • TFlags extends string

        Parameters

        • ...flagKeys: TFlags[]

          An array of flag keys to include in the registry.

          +

        Returns FlagsRegistry<TFlags>

        A new FlagsRegistry instance with the specified flags.

        +
        const registry = FlagsRegistry.from("READ", "WRITE", "EXECUTE");
        console.log(registry.get("READ")); // 1n
        console.log(registry.get("WRITE")); // 2n
        console.log(registry.get("EXECUTE")); // 4n +
        + +

      Generated using TypeDoc
      + + +

      diff --git a/docs/hierarchy.html b/docs/hierarchy.html new file mode 100644 index 0000000..4750464 --- /dev/null +++ b/docs/hierarchy.html @@ -0,0 +1,39 @@ +bitwise-flag - v1.1.0
      bitwise-flag - v1.1.0
        Preparing search index...

        bitwise-flag - v1.1.0

        Hierarchy Summary

        Generated using TypeDoc
        + + +

        diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..7f59704 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,53 @@ +bitwise-flag - v1.1.0
        bitwise-flag - v1.1.0
          Preparing search index...

          bitwise-flag - v1.1.0

          bitwise-flag

          +

          A lightweight TypeScript library for managing bitwise flags. This allows efficient storage, combination, and manipulation of multiple boolean flags in a single value, ideal for permissions, states, or configuration bitmasks. Each flag key is assigned a unique bit position, enabling operations like checking, adding, and removing flags without performance overhead.

          +

          The library is type-safe, supports immutable flag operations, and provides human-readable string aliases for debugging.

          +

          Getting Started

          npm install bitwise-flag # npm
          yarn add bitwise-flag # yarn
          pnpm add bitwise-flag # pnpm
          bun add bitwise-flag # bun +
          + +
          +
          import { FlagsRegistry } from "bitwise-flag";

          // create a flag registry
          const permissionRegistry = FlagsRegistry.from("READ", "WRITE", "EXECUTE");

          // create an empty flag
          const noPermissions = permissionRegistry.empty();
          console.log(noPermissions.isEmpty()); // true
          console.log(noPermissions.toString()); // Flag(EMPTY_FLAG: 0)

          // combine flags to create a new flag
          const readWrite = permissionsRegistry.combine("READ", "WRITE");
          console.log(readWrite.toString()); // Flag([READ+WRITE]: 3)

          // parse numeric values to create flags
          const fromNumber = permissionRegistry.parse(5); // READ + EXECUTE
          const fromHex = permissionRegistry.parse("3", 16); // READ + WRITE
          const fromBinary = permissionRegistry.parse("101", 2); // READ + EXECUTE

          // check for flags
          const userPermissions = permissionRegistry.combine("READ", "EXECUTE");

          console.log(userPermissions.has("READ")); // true
          console.log(userPermissions.has("WRITE")); // false
          console.log(userPermissions.has("EXECUTE")); // true +
          + +

          Flag's instances are immutable. Thats means all operations return new instances. For example:

          +
          const readWrite = permissionRegistry.combine("READ", "WRITE");

          // add execute flag
          const fullPermissions = readWrite.add("EXECUTE");
          console.log(readWrite.has("EXECUTE")); // false
          console.log(fullPermissions.has("EXECUTE")); // true

          // remove read flag
          const read = readWrite.remove("WRITE");
          console.log(readWrite.has("WRITE")); // true
          console.log(read.has("WRITE")); // false +
          + +

          Generated using TypeDoc
          + + +

          diff --git a/docs/interfaces/index.IFlag.html b/docs/interfaces/index.IFlag.html new file mode 100644 index 0000000..255286a --- /dev/null +++ b/docs/interfaces/index.IFlag.html @@ -0,0 +1,86 @@ +IFlag | bitwise-flag - v1.1.0
          bitwise-flag - v1.1.0
            Preparing search index...

            Interface IFlag<TFlags>

            Represents a bitwise combination of flags from a registry. This class encapsulates a bitmask value +derived from one or more flag keys, enabling efficient storage and manipulation of boolean states +(e.g., permissions, features, or configurations) using bitwise operations.

            +
            interface IFlag<TFlags extends FlagKey> {
                alias: string;
                value: bigint;
                add(...flagNames: TFlags[]): IFlag<TFlags>;
                has(flagName: TFlags): boolean;
                isEmpty(): boolean;
                remove(...flagNames: TFlags[]): IFlag<TFlags>;
                toString(): string;
            }

            Type Parameters

            Implemented by

            Index

            Properties

            Methods

            Properties

            alias: string

            A computed, human-readable alias for the flag combination.

            +
              +
            • For empty flags (value 0n), returns "EMPTY_FLAG".
            • +
            • For single flags, returns e.g., "[READ]".
            • +
            • For multiple flags, returns e.g., "[READ+WRITE]".
            • +
            +
            value: bigint

            The raw BigInt bitmask representing the combined flags in this instance. +This value is read-only and reflects the bitwise OR of all set flags.

            +

            Methods

            • Adds one or more flag keys to this flag combination, creating a new instance with the updated bitmask.

              +
                +
              • Idempotent: If a flag is already set, it remains unchanged.
              • +
              • Only adds flags that exist in the registry; unknown keys throw an error.
              • +
              • Returns the current instance if no changes are made (e.g., all flags already present).
              • +
              +

              Parameters

              • ...flagNames: TFlags[]

                One or more flag keys to add.

                +

              Returns IFlag<TFlags>

              A new Flag instance with the added flags, or the current instance if unchanged.

              +

              If any flagName is not registered in the registry (e.g., Flag with key UNKNOWN is not found.).

              +
            • Tests whether a specific flag key is set in this flag combination.

              +

              Performs a bitwise AND between the instance's value and the bitmask of the given flag key. +Returns false if the key is not found in the registry.

              +

              Parameters

              • flagName: TFlags

                The flag key to check (must be a valid key in the registry).

                +

              Returns boolean

              true if the flag is set, false otherwise.

              +
            • Checks if this flag instance represents no set flags (i.e., the bitmask value is 0n).

              +

              Returns boolean

              true if the flag is empty, false otherwise.

              +
            • Removes one or more flag keys from this flag combination, creating a new instance with the updated bitmask.

              +
                +
              • Idempotent: If a flag is not set, it remains unchanged.
              • +
              • Only removes flags that exist in the registry; unknown keys throw an error.
              • +
              • Returns the current instance if no changes are made (e.g., none of the flags were present).
              • +
              +

              Parameters

              • ...flagNames: TFlags[]

                One or more flag keys to remove.

                +

              Returns IFlag<TFlags>

              A new Flag instance with the removed flags, or the current instance if unchanged.

              +

              If any flagName is not registered in the registry (e.g., Flag with key UNKNOWN is not found.).

              +
            • Returns a human-readable string representation of this flag instance.

              +

              The format is Flag(${alias}: ${value}), where alias is the computed alias (e.g., [READ+WRITE]) +and value is the raw BigInt bitmask.

              +

              Returns string

              A string like Flag([READ+WRITE]: 3).

              +

            Generated using TypeDoc
            + + +

            diff --git a/docs/interfaces/index.IFlagsRegistry.html b/docs/interfaces/index.IFlagsRegistry.html new file mode 100644 index 0000000..3bc78b8 --- /dev/null +++ b/docs/interfaces/index.IFlagsRegistry.html @@ -0,0 +1,75 @@ +IFlagsRegistry | bitwise-flag - v1.1.0
            bitwise-flag - v1.1.0
              Preparing search index...

              Interface IFlagsRegistry<TFlags>

              A registry for managing bitwise flags. This class maps flag keys (strings) to unique bit positions +using BigInt for scalable storage.

              +
              interface IFlagsRegistry<TFlags extends FlagKey> {
                  combine(...flagKeys: TFlags[]): IFlag<TFlags>;
                  empty(): IFlag<TFlags>;
                  entries(): MapIterator<[TFlags, bigint]>;
                  get(flagName: TFlags): bigint | undefined;
                  keys(): MapIterator<TFlags>;
                  parse(value: number): IFlag<TFlags>;
                  parse(value: bigint): IFlag<TFlags>;
                  parse(value: string, radix?: number): IFlag<TFlags>;
                  values(): MapIterator<bigint>;
              }

              Type Parameters

              Implemented by

              Index

              Methods

              • Combines multiple flag keys into a single flag instance.

                +

                Parameters

                • ...flagKeys: TFlags[]

                  The flag keys to combine.

                  +

                Returns IFlag<TFlags>

                A flag instance representing the combined flags.

                +
              • Returns a flag instance representing no set flags (i.e., a bitmask value of 0n).

                +

                Returns IFlag<TFlags>

                A flag instance with no flags set.

                +
              • Returns an iterator over the [key, value] pairs in the registry.

                +

                Returns MapIterator<[TFlags, bigint]>

                An iterator over the [key, value] pairs.

                +
              • Retrieves the BigInt value associated with the given flag name.

                +

                Parameters

                • flagName: TFlags

                  The name of the flag to retrieve.

                  +

                Returns bigint | undefined

                The BigInt value of the flag, or undefined if not found.

                +
              • Returns an iterator over the flag keys in the registry.

                +

                Returns MapIterator<TFlags>

                An iterator over the flag keys.

                +
              • Parses a number value to create a flag instance.

                +

                Parameters

                • value: number

                  The numeric value to parse.

                  +

                Returns IFlag<TFlags>

                A flag instance representing the parsed value.

                +

                If the value is negative or contains unknown flags.

                +
              • Parses a bigint value to create a flag instance.

                +

                Parameters

                • value: bigint

                  The BigInt value to parse.

                  +

                Returns IFlag<TFlags>

                A flag instance representing the parsed value.

                +

                If the value is negative or contains unknown flags.

                +
              • Parses a string value to create a flag instance.

                +

                Parameters

                • value: string

                  The string value to parse.

                  +
                • Optionalradix: number

                  The radix to use when parsing the string (default is 10).

                  +

                Returns IFlag<TFlags>

                A flag instance representing the parsed value.

                +

                If the value cannot be parsed, is negative, or contains unknown flags.

                +
              • Returns an iterator over the flag values in the registry.

                +

                Returns MapIterator<bigint>

                An iterator over the flag values.

                +

              Generated using TypeDoc
              + + +

              diff --git a/docs/modules.html b/docs/modules.html new file mode 100644 index 0000000..bc0ce01 --- /dev/null +++ b/docs/modules.html @@ -0,0 +1,39 @@ +bitwise-flag - v1.1.0
              bitwise-flag - v1.1.0
                Preparing search index...

                  bitwise-flag - v1.1.0

                  Modules

                  Flag
                  FlagRegistry
                  index

                  Generated using TypeDoc
                  + + +

                  diff --git a/docs/modules/Flag.html b/docs/modules/Flag.html new file mode 100644 index 0000000..ee07255 --- /dev/null +++ b/docs/modules/Flag.html @@ -0,0 +1,39 @@ +Flag | bitwise-flag - v1.1.0
                  bitwise-flag - v1.1.0
                    Preparing search index...

                    Module Flag

                    Classes

                    Flag

                    Generated using TypeDoc
                    + + +

                    diff --git a/docs/modules/FlagRegistry.html b/docs/modules/FlagRegistry.html new file mode 100644 index 0000000..02ff2cb --- /dev/null +++ b/docs/modules/FlagRegistry.html @@ -0,0 +1,39 @@ +FlagRegistry | bitwise-flag - v1.1.0
                    bitwise-flag - v1.1.0
                      Preparing search index...

                      Module FlagRegistry

                      Classes

                      FlagsRegistry

                      Generated using TypeDoc
                      + + +

                      diff --git a/docs/modules/index.html b/docs/modules/index.html new file mode 100644 index 0000000..68eba35 --- /dev/null +++ b/docs/modules/index.html @@ -0,0 +1,39 @@ +index | bitwise-flag - v1.1.0
                      bitwise-flag - v1.1.0
                        Preparing search index...

                        Module index

                        Interfaces

                        IFlag
                        IFlagsRegistry

                        Type Aliases

                        FlagKey

                        References

                        FlagsRegistry → FlagsRegistry

                        Generated using TypeDoc
                        + + +

                        diff --git a/docs/types/index.FlagKey.html b/docs/types/index.FlagKey.html new file mode 100644 index 0000000..f4f653c --- /dev/null +++ b/docs/types/index.FlagKey.html @@ -0,0 +1,40 @@ +FlagKey | bitwise-flag - v1.1.0
                        bitwise-flag - v1.1.0
                          Preparing search index...

                          Type Alias FlagKey

                          FlagKey: string

                          A type representing the key of a flag.

                          +

                          Generated using TypeDoc
                          + + +

                          diff --git a/eslint.config.mjs b/eslint.config.mjs index 00c4ad2..3aaace1 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -25,4 +25,5 @@ export default defineConfig( }, globalIgnores(["dist/**/*"], "Ignore build directory"), globalIgnores(["**/*.test.*"], "Ignore test files"), + globalIgnores(["docs/**/*"], "Ignore documentation files"), ); diff --git a/lib/Flag.ts b/lib/Flag.ts index 12b87c8..67a493e 100644 --- a/lib/Flag.ts +++ b/lib/Flag.ts @@ -1,8 +1,36 @@ import type { FlagKey, IFlag, IFlagsRegistry } from "./types"; +/** + * Represents a bitwise combination of flags from a registry. This class encapsulates a bitmask value + * derived from one or more flag keys, enabling efficient storage and manipulation of boolean states + * (e.g., permissions, features, or configurations) using bitwise operations. + * + * @template TFlags - The type of flag keys, extending `FlagKey` (string literals for type safety). + * + * @example + * const registry = FlagsRegistry.from("READ", "WRITE"); + * const readFlag = new Flag(registry, 1n); // Represents the "READ" flag + * console.log(readFlag.value); // 1n + */ export class Flag implements IFlag { + /** + * Internal cache for the computed alias string. + * @private + * @type {string | null} + * @internal + */ private _alias: string | null = null; + /** + * Validates the provided bitmask value to ensure it is non-negative and only uses known bits + * from the registry. This method is called internally during construction. + * + * @param {bigint} value - The bitmask value to validate. + * @private + * @throws {Error} If `value` is negative. + * @throws {Error} If `value` contains unknown flags (bits not defined in the registry). + * @internal + */ private validate(value: bigint) { if (value < 0n) { throw new Error(`Flag value cannot be negative: ${value}`); @@ -17,6 +45,12 @@ export class Flag implements IFlag { } } + /** + * @param {IFlagsRegistry} context - The registry defining the valid flags and their bit positions. + * @param {bigint} value - The raw `BigInt` bitmask representing the combined flags (e.g., `3n` for bits 0 and 1 set). + * @throws {Error} If `value` is negative (e.g., `Flag value cannot be negative: -1`). + * @throws {Error} If `value` contains unknown bits (e.g., `Flag value contains unknown flags`). + */ constructor( private context: IFlagsRegistry, public readonly value: bigint, @@ -24,10 +58,34 @@ export class Flag implements IFlag { this.validate(value); } + /** + * Checks if this flag instance represents no set flags (i.e., the bitmask value is `0n`). + * + * @returns {boolean} `true` if the flag is empty, `false` otherwise. + * @example + * const empty = registry.empty(); + * empty.isEmpty(); // true + * + * const full = registry.combine("READ", "WRITE"); + * full.isEmpty(); // false + */ isEmpty(): boolean { return this.value === 0n; } + /** + * Tests whether a specific flag key is set in this flag combination. + * + * Performs a bitwise AND between the instance's value and the bitmask of the given flag key. + * Returns `false` if the key is not found in the registry. + * + * @param {TFlags} flagName - The flag key to check (must be a valid key in the registry). + * @returns {boolean} `true` if the flag is set, `false` otherwise. + * @example + * const userFlag = registry.combine("READ", "EXECUTE"); + * userFlag.has("READ"); // true + * userFlag.has("WRITE"); // false + */ has(flagName: TFlags): boolean { const value = this.context.get(flagName); @@ -36,6 +94,22 @@ export class Flag implements IFlag { return !!(this.value & value); } + /** + * Adds one or more flag keys to this flag combination, creating a new instance with the updated bitmask. + * + * - Idempotent: If a flag is already set, it remains unchanged. + * - Only adds flags that exist in the registry; unknown keys throw an error. + * - Returns the current instance if no changes are made (e.g., all flags already present). + * + * @param {...TFlags[]} flagNames - One or more flag keys to add. + * @returns {IFlag} A new `Flag` instance with the added flags, or the current instance if unchanged. + * @throws {Error} If any `flagName` is not registered in the registry (e.g., `Flag with key UNKNOWN is not found.`). + * @example + * const base = registry.combine("READ"); + * const extended = base.add("WRITE", "EXECUTE"); + * extended.has("WRITE"); // true + * base.has("WRITE"); // false (immutable) + */ add(...flagNames: TFlags[]): IFlag { const combinedValue = flagNames.reduce((acc, name) => { if (this.has(name)) return acc; @@ -54,6 +128,22 @@ export class Flag implements IFlag { return new Flag(this.context, combinedValue); } + /** + * Removes one or more flag keys from this flag combination, creating a new instance with the updated bitmask. + * + * - Idempotent: If a flag is not set, it remains unchanged. + * - Only removes flags that exist in the registry; unknown keys throw an error. + * - Returns the current instance if no changes are made (e.g., none of the flags were present). + * + * @param {...TFlags[]} flagNames - One or more flag keys to remove. + * @returns {IFlag} A new `Flag` instance with the removed flags, or the current instance if unchanged. + * @throws {Error} If any `flagName` is not registered in the registry (e.g., `Flag with key UNKNOWN is not found.`). + * @example + * const full = registry.combine("READ", "WRITE"); + * const reduced = full.remove("WRITE"); + * reduced.has("WRITE"); // false + * full.has("WRITE"); // true (immutable) + */ remove(...flagNames: TFlags[]): IFlag { const extractedValue = flagNames.reduce((acc, name) => { const value = this.context.get(name); @@ -72,10 +162,36 @@ export class Flag implements IFlag { return new Flag(this.context, extractedValue); } + /** + * Returns a human-readable string representation of this flag instance. + * + * The format is `Flag(${alias}: ${value})`, where `alias` is the computed alias (e.g., `[READ+WRITE]`) + * and `value` is the raw `BigInt` bitmask. + * + * @returns {string} A string like `Flag([READ+WRITE]: 3)`. + * @example + * const flag = registry.combine("READ"); + * flag.toString(); // "Flag([READ]: 1)" + * + * const empty = registry.empty(); + * empty.toString(); // "Flag(EMPTY_FLAG: 0)" + */ toString(): string { return `Flag(${this.alias}: ${this.value})`; } + /** + * A computed, human-readable alias for the flag combination. + * + * - For empty flags (value `0n`), returns `"EMPTY_FLAG"`. + * - For single flags, returns e.g., `"[READ]"`. + * - For multiple flags, returns e.g., `"[READ+WRITE]"`. + * + * @type {string} + * @readonly + * @example + * flag.alias; // "[READ+WRITE]" for a combined flag + */ get alias(): string { if (this._alias) return this._alias; diff --git a/lib/FlagRegistry.ts b/lib/FlagRegistry.ts index 433d367..43178a5 100644 --- a/lib/FlagRegistry.ts +++ b/lib/FlagRegistry.ts @@ -4,9 +4,27 @@ import type { FlagKey, IFlag, IFlagsRegistry } from "./types"; const unique = (arr: T[]): T[] => [...new Set(arr)]; +/** + * A registry for managing bitwise flags. This class maps flag keys (strings) to unique bit positions + * using BigInt for scalable storage. + * + * @template TFlags - The type of flag keys, extending string. + */ export class FlagsRegistry implements IFlagsRegistry { + /** + * Creates a new `FlagsRegistry` from the provided flag keys, assigning each a unique bit position. + * + * @param flagKeys - An array of flag keys to include in the registry. + * @returns {FlagsRegistry} A new `FlagsRegistry` instance with the specified flags. + * + * @example + * const registry = FlagsRegistry.from("READ", "WRITE", "EXECUTE"); + * console.log(registry.get("READ")); // 1n + * console.log(registry.get("WRITE")); // 2n + * console.log(registry.get("EXECUTE")); // 4n + */ static from( ...flagKeys: TFlags[] ): FlagsRegistry { @@ -19,29 +37,127 @@ export class FlagsRegistry return new this(flagsMap); } + /** + * + * @param flags - A map of flag keys to their corresponding BigInt values. + */ private constructor(private flags: Map) {} + /** + * Returns an iterator over the flag keys in the registry. + * + * @returns {MapIterator} An iterator over the flag keys. + */ keys(): MapIterator { return this.flags.keys(); } + + /** + * Returns an iterator over the flag values in the registry. + * + * @returns {MapIterator} An iterator over the flag values. + */ values(): MapIterator { return this.flags.values(); } + + /** + * Returns an iterator over the [key, value] pairs in the registry. + * + * @returns {MapIterator<[TFlags, bigint]>} An iterator over the [key, value] pairs. + */ entries(): MapIterator<[TFlags, bigint]> { return this.flags.entries(); } + /** + * Retrieves the BigInt value associated with the given flag name. + * + * @param flagName - The name of the flag to retrieve. + * @returns {bigint | undefined} The BigInt value of the flag, or `undefined` if not found. + * + * @example + * const registry = FlagsRegistry.from("READ", "WRITE"); + * registry.get("READ"); // 1n + * registry.get("WRITE"); // 2n + * registry.get("EXECUTE"); // undefined + */ get(flagName: TFlags): bigint | undefined { return this.flags.get(flagName); } + /** + * Returns a flag instance representing no set flags (i.e., a bitmask value of `0n`). + * + * @returns {IFlag} A flag instance with no flags set. + * @example + * const registry = FlagsRegistry.from("READ", "WRITE"); + * const emptyFlag = registry.empty(); + * emptyFlag.isEmpty(); // true + */ empty(): IFlag { return new Flag(this, 0n); } + /** + * Parses a number value to create a flag instance. + * + * @param {number} value - The numeric value to parse. + * @returns {IFlag} A flag instance representing the parsed value. + * @throws {Error} If the value is negative or contains unknown flags. + * + * @example + * const registry = FlagsRegistry.from("READ", "WRITE"); + * const flag = registry.parse(3); // Represents both READ and WRITE flags + * flag.has("READ"); // true + * flag.has("WRITE"); // true + */ parse(value: number): IFlag; + /** + * Parses a bigint value to create a flag instance. + * + * @param {bigint} value - The BigInt value to parse. + * @returns {IFlag} A flag instance representing the parsed value. + * @throws {Error} If the value is negative or contains unknown flags. + * + * @example + * const registry = FlagsRegistry.from("READ", "WRITE"); + * const flag = registry.parse(3n); // Represents both READ and WRITE flags + * flag.has("READ"); // true + * flag.has("WRITE"); // true + */ parse(value: bigint): IFlag; + /** + * Parses a string value to create a flag instance. + * + * @param {string} value - The string value to parse. + * @param {number} [radix=10] - The radix to use when parsing the string (default is 10). + * @returns {IFlag} A flag instance representing the parsed value. + * @throws {Error} If the value cannot be parsed, is negative, or contains unknown flags. + * + * @example + * const registry = FlagsRegistry.from("READ", "WRITE"); + * const flag = registry.parse("3"); // Represents both READ and WRITE flags + * flag.has("READ"); // true + * flag.has("WRITE"); // true + * + * const hexFlag = registry.parse("3", 16); // Parses "3" as hexadecimal + * hexFlag.has("READ"); // true + * hexFlag.has("WRITE"); // true + * + * const binaryFlag = registry.parse("11", 2); // Parses "11" as binary + * binaryFlag.has("READ"); // true + * binaryFlag.has("WRITE"); // true + */ parse(value: string, radix?: number): IFlag; + /** + * Parses a value (string, number, or bigint) to create a flag instance. + * + * @param {string | number | bigint} value - The value to parse. + * @param {number} [radix] - The radix to use when parsing a string value. + * @returns {IFlag} A flag instance representing the parsed value. + * @throws {Error} If the value cannot be parsed, is negative, or contains unknown flags. + */ parse(value: string | number | bigint, radix?: number): IFlag { if (typeof value === "bigint") return new Flag(this, value); @@ -56,6 +172,19 @@ export class FlagsRegistry return new Flag(this, BigInt(parsedValue)); } + /** + * Combines multiple flag keys into a single flag instance. + * + * @param {TFlags[]} flagKeys - The flag keys to combine. + * @returns {IFlag} A flag instance representing the combined flags. + * + * @example + * const registry = FlagsRegistry.from("READ", "WRITE", "EXECUTE"); + * const combinedFlag = registry.combine("READ", "EXECUTE"); + * combinedFlag.has("READ"); // true + * combinedFlag.has("WRITE"); // false + * combinedFlag.has("EXECUTE"); // true + */ combine(...flagKeys: TFlags[]): IFlag { const value = flagKeys.reduce((acc, key) => { const flagValue = this.get(key); diff --git a/lib/types.ts b/lib/types.ts index 1c39b4f..39d3297 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -1,29 +1,156 @@ +/** + * A type representing the key of a flag. + */ export type FlagKey = string; +/** + * Represents a bitwise combination of flags from a registry. This class encapsulates a bitmask value + * derived from one or more flag keys, enabling efficient storage and manipulation of boolean states + * (e.g., permissions, features, or configurations) using bitwise operations. + */ export interface IFlag { + /** + * The raw `BigInt` bitmask representing the combined flags in this instance. + * This value is read-only and reflects the bitwise OR of all set flags. + */ readonly value: bigint; + + /** + * A computed, human-readable alias for the flag combination. + * + * - For empty flags (value `0n`), returns `"EMPTY_FLAG"`. + * - For single flags, returns e.g., `"[READ]"`. + * - For multiple flags, returns e.g., `"[READ+WRITE]"`. + */ readonly alias: string; + /** + * Checks if this flag instance represents no set flags (i.e., the bitmask value is `0n`). + * + * @returns {boolean} `true` if the flag is empty, `false` otherwise. + */ isEmpty(): boolean; + + /** + * Tests whether a specific flag key is set in this flag combination. + * + * Performs a bitwise AND between the instance's value and the bitmask of the given flag key. + * Returns `false` if the key is not found in the registry. + * + * @param {TFlags} flagName - The flag key to check (must be a valid key in the registry). + * @returns {boolean} `true` if the flag is set, `false` otherwise. + */ has(flagName: TFlags): boolean; + /** + * Adds one or more flag keys to this flag combination, creating a new instance with the updated bitmask. + * + * - Idempotent: If a flag is already set, it remains unchanged. + * - Only adds flags that exist in the registry; unknown keys throw an error. + * - Returns the current instance if no changes are made (e.g., all flags already present). + * + * @param {...TFlags[]} flagNames - One or more flag keys to add. + * @returns {IFlag} A new `Flag` instance with the added flags, or the current instance if unchanged. + * @throws {Error} If any `flagName` is not registered in the registry (e.g., `Flag with key UNKNOWN is not found.`). + */ add(...flagNames: TFlags[]): IFlag; + + /** + * Removes one or more flag keys from this flag combination, creating a new instance with the updated bitmask. + * + * - Idempotent: If a flag is not set, it remains unchanged. + * - Only removes flags that exist in the registry; unknown keys throw an error. + * - Returns the current instance if no changes are made (e.g., none of the flags were present). + * + * @param {...TFlags[]} flagNames - One or more flag keys to remove. + * @returns {IFlag} A new `Flag` instance with the removed flags, or the current instance if unchanged. + * @throws {Error} If any `flagName` is not registered in the registry (e.g., `Flag with key UNKNOWN is not found.`). + */ remove(...flagNames: TFlags[]): IFlag; + /** + * Returns a human-readable string representation of this flag instance. + * + * The format is `Flag(${alias}: ${value})`, where `alias` is the computed alias (e.g., `[READ+WRITE]`) + * and `value` is the raw `BigInt` bitmask. + * + * @returns {string} A string like `Flag([READ+WRITE]: 3)`. + */ toString(): string; } +/** + * A registry for managing bitwise flags. This class maps flag keys (strings) to unique bit positions + * using BigInt for scalable storage. + */ export interface IFlagsRegistry { + /** + * Retrieves the BigInt value associated with the given flag name. + * + * @param flagName - The name of the flag to retrieve. + * @returns {bigint | undefined} The BigInt value of the flag, or `undefined` if not found. + */ get(flagName: TFlags): bigint | undefined; + + /** + * Combines multiple flag keys into a single flag instance. + * + * @param {TFlags[]} flagKeys - The flag keys to combine. + * @returns {IFlag} A flag instance representing the combined flags. + */ combine(...flagKeys: TFlags[]): IFlag; + /** + * Returns an iterator over the flag keys in the registry. + * + * @returns {MapIterator} An iterator over the flag keys. + */ keys(): MapIterator; + + /** + * Returns an iterator over the flag values in the registry. + * + * @returns {MapIterator} An iterator over the flag values. + */ values(): MapIterator; + + /** + * Returns an iterator over the [key, value] pairs in the registry. + * + * @returns {MapIterator<[TFlags, bigint]>} An iterator over the [key, value] pairs. + */ entries(): MapIterator<[TFlags, bigint]>; + /** + * Returns a flag instance representing no set flags (i.e., a bitmask value of `0n`). + * + * @returns {IFlag} A flag instance with no flags set. + */ empty(): IFlag; + /** + * Parses a number value to create a flag instance. + * + * @param {number} value - The numeric value to parse. + * @returns {IFlag} A flag instance representing the parsed value. + * @throws {Error} If the value is negative or contains unknown flags. + */ parse(value: number): IFlag; + /** + * Parses a bigint value to create a flag instance. + * + * @param {bigint} value - The BigInt value to parse. + * @returns {IFlag} A flag instance representing the parsed value. + * @throws {Error} If the value is negative or contains unknown flags. + */ parse(value: bigint): IFlag; + /** + * Parses a string value to create a flag instance. + * + * @param {string} value - The string value to parse. + * @param {number} [radix=10] - The radix to use when parsing the string (default is 10). + * @returns {IFlag} A flag instance representing the parsed value. + * @throws {Error} If the value cannot be parsed, is negative, or contains unknown flags. + */ parse(value: string, radix?: number): IFlag; } diff --git a/package.json b/package.json index cd13b03..72bc7e0 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,9 @@ "build": "bunup", "tests": "bun test", "lint": "eslint", - "lint:fix": "eslint --fix" + "lint:fix": "eslint --fix", + "docs": "typedoc", + "docs:serve": "typedoc --watch" }, "devDependencies": { "@eslint/js": "^9.39.0", @@ -43,6 +45,9 @@ "@types/bun": "^1.3.1", "bunup": "^0.15.13", "eslint": "^9.39.0", + "typedoc": "^0.28.14", + "typedoc-plugin-extras": "^4.0.1", + "typedoc-theme-hierarchy": "^6.0.0", "typescript-eslint": "^8.46.2" }, "peerDependencies": { diff --git a/typedoc.json b/typedoc.json new file mode 100644 index 0000000..7596d68 --- /dev/null +++ b/typedoc.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://typedoc.org/schema.json", + "name": "bitwise-flag", + "entryPoints": [ + "lib/index.ts", + "lib/Flag.ts", + "lib/FlagRegistry.ts", + ], + "theme": "hierarchy", + "plugin": [ + "typedoc-theme-hierarchy", + "typedoc-plugin-extras" + ], + "out": "docs", + "gitRevision": "main", + "footerLastModified": true, + "includeVersion": true, + "excludePrivate": true, + "excludeExternals": true, + "sourceLinkTemplate": "https://github.com/ThatsEmbarrassing/bitwise-flag/blob/{gitRevision}/{path}#L{line}" +} \ No newline at end of file