@arkstack/foundry 0.19.5 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -12
- package/dist/index.d.ts +44 -12
- package/dist/index.js +51 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,24 +16,32 @@ pnpm add @arkstack/foundry
|
|
|
16
16
|
|
|
17
17
|
**`src/Hook.ts`**
|
|
18
18
|
|
|
19
|
-
A global, named hook registry for extending Arkstack internals without modifying core code. Hooks are keyed by name and support positional slots (`before`, `after`, or any custom string).
|
|
19
|
+
A global, named hook registry for extending Arkstack internals without modifying core code. Hooks are keyed by name and support positional slots (`before`, `after`, or any custom string). There is one registry per process: `@arkstack/common` re-exports this same `Hook`.
|
|
20
20
|
|
|
21
|
-
#### `Hook.
|
|
21
|
+
#### `Hook.on(name, positions)`
|
|
22
22
|
|
|
23
|
-
Registers a hook.
|
|
23
|
+
Registers callbacks for a hook's positions. Registering the same name again merges: only the positions supplied are added or replaced.
|
|
24
24
|
|
|
25
25
|
```ts
|
|
26
26
|
import { Hook } from '@arkstack/foundry'
|
|
27
27
|
|
|
28
|
-
Hook.
|
|
28
|
+
Hook.on('request:handle', {
|
|
29
29
|
before: (ctx) => console.log('before handler'),
|
|
30
30
|
after: (ctx) => console.log('after handler'),
|
|
31
31
|
})
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
#### `Hook.emit(name, pos, ...args)`
|
|
35
|
+
|
|
36
|
+
Calls a position with the given arguments and returns its result: a Promise for an async hook, so it can be awaited. When nothing is registered there it does nothing and returns `undefined`, so callers need no `has()` check.
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
await Hook.emit('request:handle', 'before', ctx)
|
|
40
|
+
```
|
|
41
|
+
|
|
34
42
|
#### `Hook.get(name, pos?)`
|
|
35
43
|
|
|
36
|
-
Retrieves the full hook object or
|
|
44
|
+
Retrieves the full hook object or one position's callback, without calling it.
|
|
37
45
|
|
|
38
46
|
```ts
|
|
39
47
|
const hook = Hook.get('request:handle') // IHook | undefined
|
|
@@ -49,25 +57,29 @@ Hook.has('request:handle') // true | false
|
|
|
49
57
|
Hook.has('request:handle', 'after') // true | false
|
|
50
58
|
```
|
|
51
59
|
|
|
52
|
-
#### `Hook.
|
|
60
|
+
#### `Hook.off(name?, pos?)`
|
|
53
61
|
|
|
54
|
-
Removes a hook or a single
|
|
62
|
+
Removes a hook or a single position. A hook left with no positions is deleted. Called with no arguments it clears every hook; a name that isn't registered is a no-op.
|
|
55
63
|
|
|
56
64
|
```ts
|
|
57
|
-
Hook.
|
|
58
|
-
Hook.
|
|
59
|
-
Hook.
|
|
65
|
+
Hook.off('request:handle', 'before') // removes only the 'before' callback
|
|
66
|
+
Hook.off('request:handle') // removes the entire hook
|
|
67
|
+
Hook.off() // clears all hooks
|
|
60
68
|
```
|
|
61
69
|
|
|
62
|
-
#### `Hook.
|
|
70
|
+
#### `Hook.all()`
|
|
63
71
|
|
|
64
72
|
Returns all registered hooks as a plain record.
|
|
65
73
|
|
|
66
74
|
```ts
|
|
67
|
-
const hooks = Hook.
|
|
75
|
+
const hooks = Hook.all()
|
|
68
76
|
// { 'request:handle': { before: fn, after: fn } }
|
|
69
77
|
```
|
|
70
78
|
|
|
71
79
|
#### `Hook.clear()`
|
|
72
80
|
|
|
73
81
|
Clears all registered hooks.
|
|
82
|
+
|
|
83
|
+
#### Deprecated aliases
|
|
84
|
+
|
|
85
|
+
`set()` → `on()`, `unset()` → `off()`, `getAll()` → `all()`. `get(name, pos, ...args)` with arguments still calls the hook, but use `emit()`; `get()` should only retrieve.
|
package/dist/index.d.ts
CHANGED
|
@@ -7,23 +7,44 @@ type HookFor<N extends string> = N extends keyof HookRegistry ? HookRegistry[N]
|
|
|
7
7
|
type HookPos<N extends string, P extends string> = N extends keyof HookRegistry ? P extends keyof HookRegistry[N] ? HookRegistry[N][P] : (...args: any[]) => void : (...args: any[]) => void;
|
|
8
8
|
type HookPositions<N extends string> = N extends keyof HookRegistry ? keyof HookRegistry[N] : Position;
|
|
9
9
|
type HookArgs<N extends string, P extends string> = N extends keyof HookRegistry ? P extends keyof HookRegistry[N] ? HookRegistry[N][P] extends ((...args: infer A) => any) ? A : any[] : any[] : any[];
|
|
10
|
+
type HookResult<N extends string, P extends string> = HookPos<N, P> extends ((...args: any[]) => infer R) ? R : unknown;
|
|
10
11
|
//#endregion
|
|
11
12
|
//#region src/Hook.d.ts
|
|
12
13
|
declare class Hook {
|
|
13
14
|
private static hooks;
|
|
14
15
|
/**
|
|
15
|
-
*
|
|
16
|
+
* Register callbacks for a hook's positions. Registering the same name again
|
|
17
|
+
* merges: only the positions supplied are added or replaced.
|
|
16
18
|
*
|
|
17
19
|
* @param name
|
|
18
|
-
* @param
|
|
20
|
+
* @param hook
|
|
19
21
|
*/
|
|
20
|
-
static
|
|
22
|
+
static on<N extends HookName>(name: N | (string & {}), hook: Partial<HookFor<N>>): void;
|
|
21
23
|
/**
|
|
22
|
-
*
|
|
24
|
+
* @deprecated Use {@link Hook.on}; `set` merges rather than replaces.
|
|
23
25
|
*
|
|
24
26
|
* @param name
|
|
27
|
+
* @param hook
|
|
28
|
+
*/
|
|
29
|
+
static set<N extends HookName>(name: N | (string & {}), hook: Partial<HookFor<N>>): void;
|
|
30
|
+
/**
|
|
31
|
+
* Check if a hook is defined by name, or a position of it.
|
|
32
|
+
*
|
|
33
|
+
* @param name
|
|
34
|
+
* @param pos
|
|
25
35
|
*/
|
|
26
36
|
static has<N extends HookName, P extends HookPositions<N>>(name: N | (string & {}), pos?: P): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Run a hook position with the given arguments and return its result (a
|
|
39
|
+
* Promise for an async hook, so it can be awaited). A no-op returning
|
|
40
|
+
* `undefined` when nothing is registered there, so call sites need no
|
|
41
|
+
* {@link Hook.has} check.
|
|
42
|
+
*
|
|
43
|
+
* @param name
|
|
44
|
+
* @param pos
|
|
45
|
+
* @param args
|
|
46
|
+
*/
|
|
47
|
+
static emit<N extends HookName, P extends HookPositions<N>>(name: N, pos: P, ...args: HookArgs<N, P & string>): HookResult<N, P & string> | undefined;
|
|
27
48
|
/**
|
|
28
49
|
* Retrieve a defined hook by name
|
|
29
50
|
*
|
|
@@ -31,35 +52,46 @@ declare class Hook {
|
|
|
31
52
|
*/
|
|
32
53
|
static get<N extends HookName>(name: N): HookFor<N> | undefined;
|
|
33
54
|
/**
|
|
34
|
-
* Retrieve a defined hook by name and position
|
|
55
|
+
* Retrieve a defined hook's position by name and position
|
|
35
56
|
*
|
|
36
57
|
* @param name
|
|
37
58
|
* @param pos
|
|
38
59
|
*/
|
|
39
|
-
static get<N extends HookName, P extends HookPositions<N>>(name: N, pos: P): HookPos<N, P> | undefined;
|
|
60
|
+
static get<N extends HookName, P extends HookPositions<N>>(name: N, pos: P): HookPos<N, P & string> | undefined;
|
|
40
61
|
/**
|
|
41
|
-
*
|
|
62
|
+
* @deprecated Use {@link Hook.emit} to call a hook; `get` with arguments calls it.
|
|
42
63
|
*
|
|
43
64
|
* @param name
|
|
44
65
|
* @param pos
|
|
66
|
+
* @param args
|
|
45
67
|
*/
|
|
46
|
-
static get<N extends HookName, P extends HookPositions<N>>(name: N, pos: P, ...args: HookArgs<N, P>): void;
|
|
68
|
+
static get<N extends HookName, P extends HookPositions<N>>(name: N, pos: P, ...args: HookArgs<N, P & string>): void;
|
|
47
69
|
/**
|
|
48
70
|
* Retrieve all defined hooks
|
|
71
|
+
*/
|
|
72
|
+
static all: () => Record<string, IHook> & HookRegistry;
|
|
73
|
+
/**
|
|
74
|
+
* @deprecated Use {@link Hook.all}.
|
|
75
|
+
*/
|
|
76
|
+
static getAll: () => Record<string, IHook> & HookRegistry;
|
|
77
|
+
/**
|
|
78
|
+
* Remove a hook, or one position of it. With no name, removes every hook.
|
|
49
79
|
*
|
|
50
80
|
* @param name
|
|
81
|
+
* @param pos
|
|
51
82
|
*/
|
|
52
|
-
static
|
|
83
|
+
static off<N extends HookName, P extends HookPositions<N>>(name?: N | (string & {}), pos?: P): undefined;
|
|
53
84
|
/**
|
|
54
|
-
*
|
|
85
|
+
* @deprecated Use {@link Hook.off}.
|
|
55
86
|
*
|
|
56
87
|
* @param name
|
|
88
|
+
* @param pos
|
|
57
89
|
*/
|
|
58
|
-
static unset<N extends HookName, P extends HookPositions<N>>(name?: N | (string & {}), pos?: P):
|
|
90
|
+
static unset<N extends HookName, P extends HookPositions<N>>(name?: N | (string & {}), pos?: P): void;
|
|
59
91
|
/**
|
|
60
92
|
* Clear all the defined hooks
|
|
61
93
|
*/
|
|
62
94
|
static clear: () => void;
|
|
63
95
|
}
|
|
64
96
|
//#endregion
|
|
65
|
-
export { Hook, HookArgs, HookFor, HookName, HookPos, HookPositions, HookRegistry, IHook };
|
|
97
|
+
export { Hook, HookArgs, HookFor, HookName, HookPos, HookPositions, HookRegistry, HookResult, IHook };
|
package/dist/index.js
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
var Hook = class {
|
|
3
3
|
static hooks = /* @__PURE__ */ new Map();
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Register callbacks for a hook's positions. Registering the same name again
|
|
6
|
+
* merges: only the positions supplied are added or replaced.
|
|
6
7
|
*
|
|
7
8
|
* @param name
|
|
8
|
-
* @param
|
|
9
|
+
* @param hook
|
|
9
10
|
*/
|
|
10
|
-
static
|
|
11
|
+
static on(name, hook) {
|
|
11
12
|
const oldhook = this.hooks.get(name) ?? {};
|
|
12
13
|
this.hooks.set(name, {
|
|
13
14
|
...oldhook,
|
|
@@ -15,48 +16,82 @@ var Hook = class {
|
|
|
15
16
|
});
|
|
16
17
|
}
|
|
17
18
|
/**
|
|
18
|
-
*
|
|
19
|
+
* @deprecated Use {@link Hook.on}; `set` merges rather than replaces.
|
|
20
|
+
*
|
|
21
|
+
* @param name
|
|
22
|
+
* @param hook
|
|
23
|
+
*/
|
|
24
|
+
static set(name, hook) {
|
|
25
|
+
this.on(name, hook);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Check if a hook is defined by name, or a position of it.
|
|
19
29
|
*
|
|
20
30
|
* @param name
|
|
31
|
+
* @param pos
|
|
21
32
|
*/
|
|
22
33
|
static has(name, pos) {
|
|
23
|
-
if (pos && this.hooks.has(name)) return Boolean(this.get(name
|
|
34
|
+
if (pos && this.hooks.has(name)) return Boolean(this.hooks.get(name)?.[pos]);
|
|
24
35
|
return this.hooks.has(name);
|
|
25
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Run a hook position with the given arguments and return its result (a
|
|
39
|
+
* Promise for an async hook, so it can be awaited). A no-op returning
|
|
40
|
+
* `undefined` when nothing is registered there, so call sites need no
|
|
41
|
+
* {@link Hook.has} check.
|
|
42
|
+
*
|
|
43
|
+
* @param name
|
|
44
|
+
* @param pos
|
|
45
|
+
* @param args
|
|
46
|
+
*/
|
|
47
|
+
static emit(name, pos, ...args) {
|
|
48
|
+
const fn = this.hooks.get(name)?.[pos];
|
|
49
|
+
return fn ? fn(...args) : void 0;
|
|
50
|
+
}
|
|
26
51
|
static get(name, pos, ...args) {
|
|
27
52
|
const hook = this.hooks.get(name);
|
|
28
53
|
if (!hook) return void 0;
|
|
29
54
|
if (pos === void 0) return hook;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (args.length > 0) return fn(...args);
|
|
33
|
-
return fn;
|
|
55
|
+
if (args.length > 0) return void this.emit(name, pos, ...args);
|
|
56
|
+
return hook[pos];
|
|
34
57
|
}
|
|
35
58
|
/**
|
|
36
59
|
* Retrieve all defined hooks
|
|
37
|
-
*
|
|
38
|
-
* @param name
|
|
39
60
|
*/
|
|
40
|
-
static
|
|
61
|
+
static all = () => {
|
|
41
62
|
const hooks = {};
|
|
42
63
|
for (const [name, value] of this.hooks) hooks[name] = value;
|
|
43
64
|
return hooks;
|
|
44
65
|
};
|
|
45
66
|
/**
|
|
46
|
-
*
|
|
67
|
+
* @deprecated Use {@link Hook.all}.
|
|
68
|
+
*/
|
|
69
|
+
static getAll = () => this.all();
|
|
70
|
+
/**
|
|
71
|
+
* Remove a hook, or one position of it. With no name, removes every hook.
|
|
47
72
|
*
|
|
48
73
|
* @param name
|
|
74
|
+
* @param pos
|
|
49
75
|
*/
|
|
50
|
-
static
|
|
76
|
+
static off(name, pos) {
|
|
51
77
|
if (name && this.hooks.has(name)) {
|
|
52
78
|
if (pos !== void 0) {
|
|
53
|
-
const hook = this.get(name);
|
|
79
|
+
const hook = this.hooks.get(name);
|
|
54
80
|
if (hook?.[pos]) delete hook[pos];
|
|
55
81
|
Object.keys(hook ?? {}).length < 1 && this.hooks.delete(name);
|
|
56
82
|
return;
|
|
57
83
|
}
|
|
58
84
|
this.hooks.delete(name);
|
|
59
|
-
} else this.clear();
|
|
85
|
+
} else if (!name) this.clear();
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* @deprecated Use {@link Hook.off}.
|
|
89
|
+
*
|
|
90
|
+
* @param name
|
|
91
|
+
* @param pos
|
|
92
|
+
*/
|
|
93
|
+
static unset(name, pos) {
|
|
94
|
+
this.off(name, pos);
|
|
60
95
|
}
|
|
61
96
|
/**
|
|
62
97
|
* Clear all the defined hooks
|
package/package.json
CHANGED