@dldc/stack
Advanced tools
Comparing version 3.1.4 to 4.0.0
@@ -6,26 +6,24 @@ declare const INTERNAL: unique symbol; | ||
interface IKeyConsumer<T, HasDefault extends boolean = boolean> { | ||
readonly [INTERNAL]: true; | ||
readonly name: string; | ||
readonly [INTERNAL]: { | ||
hasDefault: HasDefault; | ||
defaultValue: T | undefined; | ||
help?: string; | ||
}; | ||
readonly hasDefault: HasDefault; | ||
readonly defaultValue: T | undefined; | ||
} | ||
interface IKeyProvider<T, HasDefault extends boolean = boolean> { | ||
readonly [INTERNAL]: true; | ||
readonly name: string; | ||
readonly [INTERNAL]: { | ||
consumer: IKeyConsumer<T, HasDefault>; | ||
value: T; | ||
}; | ||
readonly consumer: IKeyConsumer<T, HasDefault>; | ||
readonly value: T; | ||
} | ||
type TMaybeParam<T> = [T] extends [undefined] ? [value?: undefined] : [value: T]; | ||
type TKeyProviderFn<T, HasDefault extends boolean> = (...args: TMaybeParam<T>) => IKeyProvider<T, HasDefault>; | ||
interface IKey<T, HasDefault extends boolean = boolean> { | ||
type TArgsBase = readonly any[]; | ||
type TKeyProviderFn<T, HasDefault extends boolean, Args extends TArgsBase> = (...args: Args) => IKeyProvider<T, HasDefault>; | ||
interface IKey<T, HasDefault extends boolean = boolean, Args extends TArgsBase = [T]> { | ||
Consumer: IKeyConsumer<T, HasDefault>; | ||
Provider: TKeyProviderFn<T, HasDefault>; | ||
Provider: TKeyProviderFn<T, HasDefault, Args>; | ||
} | ||
declare const Key: { | ||
create: <T>(name: string, help?: string) => IKey<T, false>; | ||
createWithDefault: <T_1>(name: string, defaultValue: T_1, help?: string) => IKey<T_1, true>; | ||
createEmpty: (name: string, help?: string) => IKey<undefined, false>; | ||
create: <T>(name: string) => IKey<T, false, [value: T]>; | ||
createWithDefault: <T_1>(name: string, defaultValue: T_1) => IKey<T_1, true, [value: T_1]>; | ||
createEmpty: (name: string) => IKey<undefined, false, [ | ||
]>; | ||
}; | ||
@@ -35,31 +33,30 @@ | ||
keyConsumer: IKeyConsumer<any>; | ||
readonly help?: string; | ||
constructor(keyConsumer: IKeyConsumer<any>); | ||
} | ||
type TStaackCoreTuple = [parent: StaackCore, provider: IKeyProvider<any>]; | ||
type TStaackCoreValue = StaackCore | null; | ||
declare class StaackCore { | ||
type TStackCoreTuple = [parent: StackCore, provider: IKeyProvider<any>]; | ||
type TStackCoreValue = StackCore | null; | ||
declare class StackCore { | ||
static readonly MissingContextError: typeof MissingContextError; | ||
private readonly [PARENT]; | ||
private readonly [PROVIDER]; | ||
protected constructor(provider: IKeyProvider<any>, parent?: TStaackCoreValue); | ||
protected constructor(provider: IKeyProvider<any>, parent?: TStackCoreValue); | ||
/** | ||
* READ Functions | ||
*/ | ||
static findFirstMatch(staack: TStaackCoreValue, consumer: IKeyConsumer<any, any>): { | ||
static findFirstMatch(stack: TStackCoreValue, consumer: IKeyConsumer<any, any>): { | ||
found: boolean; | ||
value: any; | ||
}; | ||
static has(staack: TStaackCoreValue, consumer: IKeyConsumer<any, any>): boolean; | ||
static get<T, HasDefault extends boolean>(staack: TStaackCoreValue, consumer: IKeyConsumer<T, HasDefault>): HasDefault extends true ? T : T | null; | ||
static getAll<T>(staack: TStaackCoreValue, consumer: IKeyConsumer<T>): IterableIterator<T>; | ||
static getOrFail<T>(staack: TStaackCoreValue, consumer: IKeyConsumer<T>): T; | ||
static extract(staack: TStaackCoreValue): IterableIterator<TStaackCoreTuple>; | ||
static has(stack: TStackCoreValue, consumer: IKeyConsumer<any, any>): boolean; | ||
static get<T, HasDefault extends boolean>(stack: TStackCoreValue, consumer: IKeyConsumer<T, HasDefault>): HasDefault extends true ? T : T | null; | ||
static getAll<T>(stack: TStackCoreValue, consumer: IKeyConsumer<T>): IterableIterator<T>; | ||
static getOrFail<T>(stack: TStackCoreValue, consumer: IKeyConsumer<T>): T; | ||
static extract(stack: TStackCoreValue): IterableIterator<TStackCoreTuple>; | ||
/** | ||
* WRITE Functions | ||
*/ | ||
static with(staack: TStaackCoreValue, ...keys: readonly IKeyProvider<any>[]): TStaackCoreValue; | ||
static with(stack: TStackCoreValue, ...keys: readonly IKeyProvider<any>[]): TStackCoreValue; | ||
/** | ||
* Merge two StaackCore instances into one. | ||
* Merge two StackCore instances into one. | ||
* [...left, ...right] | ||
@@ -69,8 +66,8 @@ * If left is empty, return right. | ||
*/ | ||
static merge(left: TStaackCoreValue, right: TStaackCoreValue): TStaackCoreValue; | ||
static merge(left: TStackCoreValue, right: TStackCoreValue): TStackCoreValue; | ||
/** | ||
* Remove duplicated providers from the StaackCore. | ||
* Remove duplicated providers from the StackCore. | ||
*/ | ||
static dedupe(staack: TStaackCoreValue): TStaackCoreValue; | ||
static debug(staack: TStaackCoreValue): Array<{ | ||
static dedupe(stack: TStackCoreValue): TStackCoreValue; | ||
static debug(stack: TStackCoreValue): Array<{ | ||
value: any; | ||
@@ -81,5 +78,5 @@ ctxId: string; | ||
declare class Staack { | ||
declare class Stack { | ||
private readonly [INTERNAL]; | ||
constructor(core?: TStaackCoreValue); | ||
constructor(core?: TStackCoreValue); | ||
has(consumer: IKeyConsumer<any, any>): boolean; | ||
@@ -93,8 +90,8 @@ get<T, HasDefault extends boolean>(consumer: IKeyConsumer<T, HasDefault>): HasDefault extends true ? T : T | null; | ||
}>; | ||
protected instantiate(staackCore: TStaackCoreValue): this; | ||
protected instantiate(stackCore: TStackCoreValue): this; | ||
with(...keys: Array<IKeyProvider<any>>): this; | ||
merge(other: Staack): this; | ||
merge(other: Stack): this; | ||
dedupe(): this; | ||
} | ||
export { IKey, IKeyConsumer, IKeyProvider, Key, MissingContextError, Staack, StaackCore, TKeyProviderFn, TMaybeParam, TStaackCoreTuple, TStaackCoreValue }; | ||
export { IKey, IKeyConsumer, IKeyProvider, Key, MissingContextError, Stack, StackCore, TArgsBase, TKeyProviderFn, TStackCoreTuple, TStackCoreValue }; |
159
dist/mod.js
@@ -25,4 +25,4 @@ "use strict"; | ||
MissingContextError: () => MissingContextError, | ||
Staack: () => Staack, | ||
StaackCore: () => StaackCore | ||
Stack: () => Stack, | ||
StackCore: () => StackCore | ||
}); | ||
@@ -44,17 +44,16 @@ module.exports = __toCommonJS(mod_exports); | ||
}; | ||
function create(name, help) { | ||
return createInternal(name, { hasDefault: false, defaultValue: void 0, help }); | ||
function create(name) { | ||
return createInternal(name, false, void 0); | ||
} | ||
function createWithDefault(name, defaultValue, help) { | ||
return createInternal(name, { hasDefault: true, defaultValue, help }); | ||
function createWithDefault(name, defaultValue) { | ||
return createInternal(name, true, defaultValue); | ||
} | ||
function createEmpty(name, help) { | ||
return createInternal(name, { hasDefault: false, defaultValue: void 0, help }); | ||
function createEmpty(name) { | ||
return createInternal(name, false, void 0); | ||
} | ||
function createInternal(name, data) { | ||
const Consumer = { name, [INTERNAL]: data }; | ||
const Provider = (...args) => ({ | ||
name, | ||
[INTERNAL]: { value: args[0], consumer: Consumer } | ||
}); | ||
function createInternal(name, hasDefault, defaultValue) { | ||
const Consumer = { [INTERNAL]: true, name, hasDefault, defaultValue }; | ||
const Provider = (value) => { | ||
return { [INTERNAL]: true, name, consumer: Consumer, value }; | ||
}; | ||
return { | ||
@@ -73,9 +72,7 @@ Consumer, | ||
Object.setPrototypeOf(this, new.target.prototype); | ||
this.help = keyConsumer[INTERNAL].help; | ||
} | ||
help; | ||
}; | ||
// src/StaackCore.ts | ||
var StaackCore = class _StaackCore { | ||
// src/StackCore.ts | ||
var StackCore = class _StackCore { | ||
static MissingContextError = MissingContextError; | ||
@@ -92,23 +89,23 @@ [PARENT]; | ||
*/ | ||
static findFirstMatch(staack, consumer) { | ||
if (staack === null) { | ||
static findFirstMatch(stack, consumer) { | ||
if (stack === null) { | ||
return { found: false, value: null }; | ||
} | ||
const provider = staack[PROVIDER]; | ||
if (provider[INTERNAL].consumer === consumer) { | ||
const provider = stack[PROVIDER]; | ||
if (provider.consumer === consumer) { | ||
return { | ||
found: true, | ||
value: provider[INTERNAL].value | ||
value: provider.value | ||
}; | ||
} | ||
return _StaackCore.findFirstMatch(staack[PARENT], consumer); | ||
return _StackCore.findFirstMatch(stack[PARENT], consumer); | ||
} | ||
static has(staack, consumer) { | ||
return _StaackCore.findFirstMatch(staack, consumer).found; | ||
static has(stack, consumer) { | ||
return _StackCore.findFirstMatch(stack, consumer).found; | ||
} | ||
static get(staack, consumer) { | ||
const res = _StaackCore.findFirstMatch(staack, consumer); | ||
static get(stack, consumer) { | ||
const res = _StackCore.findFirstMatch(stack, consumer); | ||
if (res.found === false) { | ||
if (consumer[INTERNAL].hasDefault) { | ||
return consumer[INTERNAL].defaultValue; | ||
if (consumer.hasDefault) { | ||
return consumer.defaultValue; | ||
} | ||
@@ -119,4 +116,4 @@ return null; | ||
} | ||
static getAll(staack, consumer) { | ||
let current = staack; | ||
static getAll(stack, consumer) { | ||
let current = stack; | ||
return { | ||
@@ -127,4 +124,4 @@ next() { | ||
current = current[PARENT]; | ||
if (provider[INTERNAL].consumer === consumer) { | ||
return { value: provider[INTERNAL].value, done: false }; | ||
if (provider.consumer === consumer) { | ||
return { value: provider.value, done: false }; | ||
} | ||
@@ -139,7 +136,7 @@ } | ||
} | ||
static getOrFail(staack, consumer) { | ||
const res = _StaackCore.findFirstMatch(staack, consumer); | ||
static getOrFail(stack, consumer) { | ||
const res = _StackCore.findFirstMatch(stack, consumer); | ||
if (res.found === false) { | ||
if (consumer[INTERNAL].hasDefault) { | ||
return consumer[INTERNAL].defaultValue; | ||
if (consumer.hasDefault) { | ||
return consumer.defaultValue; | ||
} | ||
@@ -150,4 +147,4 @@ throw new MissingContextError(consumer); | ||
} | ||
static extract(staack) { | ||
let current = staack; | ||
static extract(stack) { | ||
let current = stack; | ||
return { | ||
@@ -171,12 +168,12 @@ next() { | ||
*/ | ||
static with(staack, ...keys) { | ||
static with(stack, ...keys) { | ||
if (keys.length === 0) { | ||
return staack; | ||
return stack; | ||
} | ||
return [...keys].reduce((parent, provider) => { | ||
return new _StaackCore(provider, parent); | ||
}, staack); | ||
return new _StackCore(provider, parent); | ||
}, stack); | ||
} | ||
/** | ||
* Merge two StaackCore instances into one. | ||
* Merge two StackCore instances into one. | ||
* [...left, ...right] | ||
@@ -190,10 +187,10 @@ * If left is empty, return right. | ||
} | ||
const rightExtracted = Array.from(_StaackCore.extract(right), ([, provider]) => provider).reverse(); | ||
return _StaackCore.with(left, ...rightExtracted); | ||
const rightExtracted = Array.from(_StackCore.extract(right), ([, provider]) => provider).reverse(); | ||
return _StackCore.with(left, ...rightExtracted); | ||
} | ||
/** | ||
* Remove duplicated providers from the StaackCore. | ||
* Remove duplicated providers from the StackCore. | ||
*/ | ||
static dedupe(staack) { | ||
if (staack === null) { | ||
static dedupe(stack) { | ||
if (stack === null) { | ||
return null; | ||
@@ -203,6 +200,6 @@ } | ||
const queue = []; | ||
let base = staack; | ||
let base = stack; | ||
let baseQueue = []; | ||
for (const [item, provider] of _StaackCore.extract(staack)) { | ||
if (seenKeys.has(provider[INTERNAL].consumer)) { | ||
for (const [item, provider] of _StackCore.extract(stack)) { | ||
if (seenKeys.has(provider.consumer)) { | ||
base = item[PARENT]; | ||
@@ -213,23 +210,23 @@ queue.push(...baseQueue); | ||
} | ||
seenKeys.add(provider[INTERNAL].consumer); | ||
seenKeys.add(provider.consumer); | ||
baseQueue.push(provider); | ||
} | ||
if (base === staack) { | ||
return staack; | ||
if (base === stack) { | ||
return stack; | ||
} | ||
queue.push(...baseQueue); | ||
return _StaackCore.with(base, ...queue.reverse()); | ||
return _StackCore.with(base, ...queue.reverse()); | ||
} | ||
static debug(staack) { | ||
static debug(stack) { | ||
const world = globalThis; | ||
const idMap = world[DEBUG] || (world[DEBUG] = /* @__PURE__ */ new WeakMap()); | ||
const result = []; | ||
traverse(staack); | ||
traverse(stack); | ||
return result; | ||
function traverse(staack2) { | ||
if (staack2 === null) { | ||
function traverse(stack2) { | ||
if (stack2 === null) { | ||
return; | ||
} | ||
const provider = staack2[PROVIDER]; | ||
const consumer = provider[INTERNAL].consumer; | ||
const provider = stack2[PROVIDER]; | ||
const consumer = provider.consumer; | ||
let ctxId = idMap.get(consumer); | ||
@@ -243,5 +240,5 @@ if (ctxId === void 0) { | ||
ctxName: consumer.name, | ||
value: provider[INTERNAL].value | ||
value: provider.value | ||
}); | ||
traverse(staack2[PARENT]); | ||
traverse(stack2[PARENT]); | ||
} | ||
@@ -251,4 +248,4 @@ } | ||
// src/Staack.ts | ||
var Staack = class _Staack { | ||
// src/Stack.ts | ||
var Stack = class _Stack { | ||
[INTERNAL]; | ||
@@ -259,24 +256,24 @@ constructor(core = null) { | ||
has(consumer) { | ||
return StaackCore.has(this[INTERNAL], consumer); | ||
return StackCore.has(this[INTERNAL], consumer); | ||
} | ||
get(consumer) { | ||
return StaackCore.get(this[INTERNAL], consumer); | ||
return StackCore.get(this[INTERNAL], consumer); | ||
} | ||
getAll(consumer) { | ||
return StaackCore.getAll(this[INTERNAL], consumer); | ||
return StackCore.getAll(this[INTERNAL], consumer); | ||
} | ||
getOrFail(consumer) { | ||
return StaackCore.getOrFail(this[INTERNAL], consumer); | ||
return StackCore.getOrFail(this[INTERNAL], consumer); | ||
} | ||
debug() { | ||
return StaackCore.debug(this[INTERNAL]); | ||
return StackCore.debug(this[INTERNAL]); | ||
} | ||
instantiate(staackCore) { | ||
if (this.constructor !== _Staack) { | ||
throw new Error("Cannot instantiate a Staack subclass, you need to override instantiate()"); | ||
instantiate(stackCore) { | ||
if (this.constructor !== _Stack) { | ||
throw new Error("Cannot instantiate a Stack subclass, you need to override instantiate()"); | ||
} | ||
return new _Staack(staackCore); | ||
return new _Stack(stackCore); | ||
} | ||
with(...keys) { | ||
const nextCore = StaackCore.with(this[INTERNAL], ...keys); | ||
const nextCore = StackCore.with(this[INTERNAL], ...keys); | ||
if (nextCore === this[INTERNAL]) { | ||
@@ -291,3 +288,3 @@ return this; | ||
} | ||
const nextCore = StaackCore.merge(this[INTERNAL], other[INTERNAL]); | ||
const nextCore = StackCore.merge(this[INTERNAL], other[INTERNAL]); | ||
if (nextCore === this[INTERNAL]) { | ||
@@ -299,3 +296,3 @@ return this; | ||
dedupe() { | ||
const nextCore = StaackCore.dedupe(this[INTERNAL]); | ||
const nextCore = StackCore.dedupe(this[INTERNAL]); | ||
if (nextCore === this[INTERNAL]) { | ||
@@ -311,4 +308,4 @@ return this; | ||
MissingContextError, | ||
Staack, | ||
StaackCore | ||
Stack, | ||
StackCore | ||
}); |
{ | ||
"name": "@dldc/stack", | ||
"version": "3.1.4", | ||
"version": "4.0.0", | ||
"description": "A library to create type-safe opaque stacks", | ||
@@ -35,2 +35,3 @@ "keywords": [ | ||
"build": "rimraf dist && tsup --format cjs,esm src/mod.ts --dts src/mod.ts", | ||
"build:watch": "tsup --watch --format cjs,esm src/mod.ts --dts src/mod.ts", | ||
"changelog": "auto-changelog --stdout --hide-credit true --commit-limit false -u --template https://raw.githubusercontent.com/release-it/release-it/main/templates/changelog-compact.hbs", | ||
@@ -48,15 +49,15 @@ "lint": "prettier . --check && eslint . && tsc --noEmit", | ||
"devDependencies": { | ||
"@types/node": "^20.4.2", | ||
"@typescript-eslint/eslint-plugin": "^6.0.0", | ||
"@typescript-eslint/parser": "^6.0.0", | ||
"@vitest/coverage-v8": "^0.33.0", | ||
"@types/node": "^20.5.7", | ||
"@typescript-eslint/eslint-plugin": "^6.5.0", | ||
"@typescript-eslint/parser": "^6.5.0", | ||
"@vitest/coverage-v8": "^0.34.3", | ||
"auto-changelog": "^2.4.0", | ||
"eslint": "^8.45.0", | ||
"eslint-config-prettier": "^8.8.0", | ||
"prettier": "^3.0.0", | ||
"release-it": "^16.1.0", | ||
"eslint": "^8.48.0", | ||
"eslint-config-prettier": "^9.0.0", | ||
"prettier": "^3.0.3", | ||
"release-it": "^16.1.5", | ||
"rimraf": "^5.0.1", | ||
"tsup": "^7.1.0", | ||
"typescript": "^5.1.6", | ||
"vitest": "^0.33.0" | ||
"tsup": "^7.2.0", | ||
"typescript": "^5.2.2", | ||
"vitest": "^0.34.3" | ||
}, | ||
@@ -63,0 +64,0 @@ "packageManager": "pnpm@8.6.1", |
@@ -1,2 +0,2 @@ | ||
# 🏯 Staack | ||
# 🏯 Stack | ||
@@ -12,5 +12,5 @@ > A library to create type-safe opaque stacks | ||
// 2. Create a stack | ||
const stack = new Staack(); | ||
const stack = new Stack(); | ||
// 3. Add a value to the stack using the key (Staack is immutable, it returns a new instance) | ||
// 3. Add a value to the stack using the key (Stack is immutable, it returns a new instance) | ||
const stack2 = stack.with(NumKey.Provider(42)); | ||
@@ -25,22 +25,22 @@ | ||
```bash | ||
npm install staack | ||
npm install stack | ||
# or | ||
yarn add staack | ||
yarn add stack | ||
``` | ||
## Extending `Staack` | ||
## Extending `Stack` | ||
You can create your own `Staack`: | ||
You can create your own `Stack`, this is useful to define custom properties and methods. | ||
```ts | ||
class CustomStaack extends Staack { | ||
class CustomStack extends Stack { | ||
// You need to override the `instantiate` method to return a new instance of your CustomStack | ||
protected instantiate(staackCore: StaackCoreValue): this { | ||
return new CustomStaack(staackCore) as any; | ||
protected instantiate(stackCore: StackCoreValue): this { | ||
return new CustomStack(stackCore) as any; | ||
} | ||
} | ||
const custom = new CustomStaack(); | ||
expect(custom instanceof CustomStaack).toBe(true); | ||
expect(custom instanceof Staack).toBe(true); | ||
const custom = new CustomStack(); | ||
expect(custom instanceof CustomStack).toBe(true); | ||
expect(custom instanceof Stack).toBe(true); | ||
``` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
26190
633