@newcms/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hook-engine.d.ts +134 -0
- package/dist/hook-engine.d.ts.map +1 -0
- package/dist/hook-engine.js +370 -0
- package/dist/hook-engine.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +124 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +34 -0
- package/dist/types.js.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import type { HookCallback, HookStackEntry, AddHookOptions, HasHookResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* HookEngine — the backbone of the CMS extensibility system.
|
|
4
|
+
*
|
|
5
|
+
* Implements a WordPress-compatible hook system with actions and filters.
|
|
6
|
+
* Actions are hooks that perform side effects. Filters are hooks that
|
|
7
|
+
* transform a value through a pipeline of callbacks.
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - Priority-based execution (lower number = earlier execution)
|
|
11
|
+
* - Recursive hook execution support
|
|
12
|
+
* - Universal "all" hook that fires for every hook
|
|
13
|
+
* - Execution stack tracking
|
|
14
|
+
* - Fire counters per hook
|
|
15
|
+
* - Precise removal by callback + priority
|
|
16
|
+
*/
|
|
17
|
+
export declare class HookEngine {
|
|
18
|
+
/**
|
|
19
|
+
* Map of hook name → array of handlers, kept sorted by priority.
|
|
20
|
+
*/
|
|
21
|
+
private hooks;
|
|
22
|
+
/**
|
|
23
|
+
* Stack of hooks currently being executed (supports recursion).
|
|
24
|
+
*/
|
|
25
|
+
private currentStack;
|
|
26
|
+
/**
|
|
27
|
+
* Counter of how many times each hook has been fired.
|
|
28
|
+
*/
|
|
29
|
+
private fireCount;
|
|
30
|
+
/**
|
|
31
|
+
* Register a callback for a hook.
|
|
32
|
+
*
|
|
33
|
+
* @param hookName - The hook identifier
|
|
34
|
+
* @param callback - The function to execute
|
|
35
|
+
* @param options - Priority and accepted args configuration
|
|
36
|
+
* @returns The generated handler ID
|
|
37
|
+
*/
|
|
38
|
+
addHook(hookName: string, callback: HookCallback, options?: AddHookOptions): string;
|
|
39
|
+
/**
|
|
40
|
+
* Remove a specific callback from a hook.
|
|
41
|
+
*
|
|
42
|
+
* Both the callback reference AND priority must match for removal.
|
|
43
|
+
*
|
|
44
|
+
* @param hookName - The hook identifier
|
|
45
|
+
* @param callback - The callback to remove
|
|
46
|
+
* @param priority - The priority it was registered with (default: 10)
|
|
47
|
+
* @returns true if a handler was removed
|
|
48
|
+
*/
|
|
49
|
+
removeHook(hookName: string, callback: HookCallback, priority?: number): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Remove all callbacks from a hook, optionally only for a specific priority.
|
|
52
|
+
*
|
|
53
|
+
* @param hookName - The hook identifier
|
|
54
|
+
* @param priority - If provided, only remove handlers at this priority
|
|
55
|
+
* @returns true if any handlers were removed
|
|
56
|
+
*/
|
|
57
|
+
removeAllHooks(hookName: string, priority?: number): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Check if a hook has registered handlers.
|
|
60
|
+
*
|
|
61
|
+
* @param hookName - The hook identifier
|
|
62
|
+
* @param callback - If provided, check for this specific callback
|
|
63
|
+
* @returns false if no handlers, or the priority of the matching handler
|
|
64
|
+
*/
|
|
65
|
+
hasHook(hookName: string, callback?: HookCallback): HasHookResult;
|
|
66
|
+
/**
|
|
67
|
+
* Execute an action hook. All registered callbacks are called in priority order.
|
|
68
|
+
* The "all" universal hook fires before the specific hook.
|
|
69
|
+
*
|
|
70
|
+
* @param hookName - The hook identifier
|
|
71
|
+
* @param args - Arguments to pass to callbacks
|
|
72
|
+
*/
|
|
73
|
+
doAction(hookName: string, ...args: unknown[]): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Execute an action hook synchronously.
|
|
76
|
+
*/
|
|
77
|
+
doActionSync(hookName: string, ...args: unknown[]): void;
|
|
78
|
+
/**
|
|
79
|
+
* Execute a filter hook. The first argument is the value being filtered.
|
|
80
|
+
* Each callback receives the (possibly modified) value and returns a new value.
|
|
81
|
+
* The "all" universal hook fires before the specific hook.
|
|
82
|
+
*
|
|
83
|
+
* @param hookName - The hook identifier
|
|
84
|
+
* @param value - The initial value to filter
|
|
85
|
+
* @param args - Additional arguments passed to each callback
|
|
86
|
+
* @returns The filtered value after all callbacks have processed it
|
|
87
|
+
*/
|
|
88
|
+
applyFilters(hookName: string, value: unknown, ...args: unknown[]): Promise<unknown>;
|
|
89
|
+
/**
|
|
90
|
+
* Execute a filter hook synchronously.
|
|
91
|
+
*/
|
|
92
|
+
applyFiltersSync(hookName: string, value: unknown, ...args: unknown[]): unknown;
|
|
93
|
+
/**
|
|
94
|
+
* Get how many times a hook has been fired.
|
|
95
|
+
*/
|
|
96
|
+
getFireCount(hookName: string): number;
|
|
97
|
+
/**
|
|
98
|
+
* Check if a specific hook is currently being executed.
|
|
99
|
+
*/
|
|
100
|
+
isDoingHook(hookName?: string): boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Get the name of the hook currently being executed (top of stack).
|
|
103
|
+
* Returns undefined if no hook is executing.
|
|
104
|
+
*/
|
|
105
|
+
currentHook(): string | undefined;
|
|
106
|
+
/**
|
|
107
|
+
* Get a snapshot of the current execution stack.
|
|
108
|
+
*/
|
|
109
|
+
getExecutionStack(): readonly HookStackEntry[];
|
|
110
|
+
/**
|
|
111
|
+
* Check if a hook has ever been fired (fire count > 0).
|
|
112
|
+
*/
|
|
113
|
+
didHook(hookName: string): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Get the number of handlers registered for a hook.
|
|
116
|
+
*/
|
|
117
|
+
getHandlerCount(hookName: string): number;
|
|
118
|
+
/**
|
|
119
|
+
* Reset the engine — useful for testing.
|
|
120
|
+
*/
|
|
121
|
+
reset(): void;
|
|
122
|
+
addAction(hookName: string, callback: HookCallback, options?: AddHookOptions): string;
|
|
123
|
+
addFilter(hookName: string, callback: HookCallback, options?: AddHookOptions): string;
|
|
124
|
+
removeAction(hookName: string, callback: HookCallback, priority?: number): boolean;
|
|
125
|
+
removeFilter(hookName: string, callback: HookCallback, priority?: number): boolean;
|
|
126
|
+
hasAction(hookName: string, callback?: HookCallback): HasHookResult;
|
|
127
|
+
hasFilter(hookName: string, callback?: HookCallback): HasHookResult;
|
|
128
|
+
didAction(hookName: string): boolean;
|
|
129
|
+
didFilter(hookName: string): boolean;
|
|
130
|
+
private incrementFireCount;
|
|
131
|
+
private fireUniversalHook;
|
|
132
|
+
private fireUniversalHookSync;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=hook-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-engine.d.ts","sourceRoot":"","sources":["../src/hook-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,YAAY,EAEZ,cAAc,EACd,cAAc,EACd,aAAa,EACb,MAAM,YAAY,CAAC;AAkBpB;;;;;;;;;;;;;;GAcG;AACH,qBAAa,UAAU;IACtB;;OAEG;IACH,OAAO,CAAC,KAAK,CAAyC;IAEtD;;OAEG;IACH,OAAO,CAAC,YAAY,CAAwB;IAE5C;;OAEG;IACH,OAAO,CAAC,SAAS,CAAkC;IAEnD;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,GAAE,cAAmB,GAAG,MAAM;IAqBvF;;;;;;;;;OASG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,GAAE,MAAW,GAAG,OAAO;IAoBpF;;;;;;OAMG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO;IAoB5D;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,YAAY,GAAG,aAAa;IAajE;;;;;;OAMG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BnE;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAyBxD;;;;;;;;;OASG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IA8B1F;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO;IA6B/E;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAItC;;OAEG;IACH,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO;IAOvC;;;OAGG;IACH,WAAW,IAAI,MAAM,GAAG,SAAS;IAKjC;;OAEG;IACH,iBAAiB,IAAI,SAAS,cAAc,EAAE;IAI9C;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIlC;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAIzC;;OAEG;IACH,KAAK,IAAI,IAAI;IASb,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM;IAIrF,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM;IAIrF,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO;IAIlF,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO;IAIlF,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,YAAY,GAAG,aAAa;IAInE,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,YAAY,GAAG,aAAa;IAInE,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIpC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAMpC,OAAO,CAAC,kBAAkB;YAIZ,iBAAiB;IAkB/B,OAAO,CAAC,qBAAqB;CAiB7B"}
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a unique identifier for a hook callback.
|
|
3
|
+
*
|
|
4
|
+
* For named functions, uses the function name + priority.
|
|
5
|
+
* For anonymous/arrow functions, uses a counter-based ID.
|
|
6
|
+
*/
|
|
7
|
+
let anonymousCounter = 0;
|
|
8
|
+
function generateCallbackId(callback, priority) {
|
|
9
|
+
if (callback.name && callback.name !== '') {
|
|
10
|
+
return `${callback.name}::${priority}`;
|
|
11
|
+
}
|
|
12
|
+
anonymousCounter++;
|
|
13
|
+
return `__anonymous_${anonymousCounter}::${priority}`;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* HookEngine — the backbone of the CMS extensibility system.
|
|
17
|
+
*
|
|
18
|
+
* Implements a WordPress-compatible hook system with actions and filters.
|
|
19
|
+
* Actions are hooks that perform side effects. Filters are hooks that
|
|
20
|
+
* transform a value through a pipeline of callbacks.
|
|
21
|
+
*
|
|
22
|
+
* Features:
|
|
23
|
+
* - Priority-based execution (lower number = earlier execution)
|
|
24
|
+
* - Recursive hook execution support
|
|
25
|
+
* - Universal "all" hook that fires for every hook
|
|
26
|
+
* - Execution stack tracking
|
|
27
|
+
* - Fire counters per hook
|
|
28
|
+
* - Precise removal by callback + priority
|
|
29
|
+
*/
|
|
30
|
+
export class HookEngine {
|
|
31
|
+
/**
|
|
32
|
+
* Map of hook name → array of handlers, kept sorted by priority.
|
|
33
|
+
*/
|
|
34
|
+
hooks = new Map();
|
|
35
|
+
/**
|
|
36
|
+
* Stack of hooks currently being executed (supports recursion).
|
|
37
|
+
*/
|
|
38
|
+
currentStack = [];
|
|
39
|
+
/**
|
|
40
|
+
* Counter of how many times each hook has been fired.
|
|
41
|
+
*/
|
|
42
|
+
fireCount = new Map();
|
|
43
|
+
/**
|
|
44
|
+
* Register a callback for a hook.
|
|
45
|
+
*
|
|
46
|
+
* @param hookName - The hook identifier
|
|
47
|
+
* @param callback - The function to execute
|
|
48
|
+
* @param options - Priority and accepted args configuration
|
|
49
|
+
* @returns The generated handler ID
|
|
50
|
+
*/
|
|
51
|
+
addHook(hookName, callback, options = {}) {
|
|
52
|
+
const priority = options.priority ?? 10;
|
|
53
|
+
const acceptedArgs = options.acceptedArgs ?? 1;
|
|
54
|
+
const id = generateCallbackId(callback, priority);
|
|
55
|
+
const handler = {
|
|
56
|
+
callback,
|
|
57
|
+
priority,
|
|
58
|
+
acceptedArgs,
|
|
59
|
+
id,
|
|
60
|
+
};
|
|
61
|
+
const existing = this.hooks.get(hookName) ?? [];
|
|
62
|
+
existing.push(handler);
|
|
63
|
+
// Stable sort by priority (preserves insertion order for same priority)
|
|
64
|
+
existing.sort((a, b) => a.priority - b.priority);
|
|
65
|
+
this.hooks.set(hookName, existing);
|
|
66
|
+
return id;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Remove a specific callback from a hook.
|
|
70
|
+
*
|
|
71
|
+
* Both the callback reference AND priority must match for removal.
|
|
72
|
+
*
|
|
73
|
+
* @param hookName - The hook identifier
|
|
74
|
+
* @param callback - The callback to remove
|
|
75
|
+
* @param priority - The priority it was registered with (default: 10)
|
|
76
|
+
* @returns true if a handler was removed
|
|
77
|
+
*/
|
|
78
|
+
removeHook(hookName, callback, priority = 10) {
|
|
79
|
+
const handlers = this.hooks.get(hookName);
|
|
80
|
+
if (!handlers)
|
|
81
|
+
return false;
|
|
82
|
+
const initialLength = handlers.length;
|
|
83
|
+
const filtered = handlers.filter((h) => !(h.callback === callback && h.priority === priority));
|
|
84
|
+
if (filtered.length === initialLength)
|
|
85
|
+
return false;
|
|
86
|
+
if (filtered.length === 0) {
|
|
87
|
+
this.hooks.delete(hookName);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
this.hooks.set(hookName, filtered);
|
|
91
|
+
}
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Remove all callbacks from a hook, optionally only for a specific priority.
|
|
96
|
+
*
|
|
97
|
+
* @param hookName - The hook identifier
|
|
98
|
+
* @param priority - If provided, only remove handlers at this priority
|
|
99
|
+
* @returns true if any handlers were removed
|
|
100
|
+
*/
|
|
101
|
+
removeAllHooks(hookName, priority) {
|
|
102
|
+
if (priority === undefined) {
|
|
103
|
+
return this.hooks.delete(hookName);
|
|
104
|
+
}
|
|
105
|
+
const handlers = this.hooks.get(hookName);
|
|
106
|
+
if (!handlers)
|
|
107
|
+
return false;
|
|
108
|
+
const filtered = handlers.filter((h) => h.priority !== priority);
|
|
109
|
+
if (filtered.length === handlers.length)
|
|
110
|
+
return false;
|
|
111
|
+
if (filtered.length === 0) {
|
|
112
|
+
this.hooks.delete(hookName);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
this.hooks.set(hookName, filtered);
|
|
116
|
+
}
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Check if a hook has registered handlers.
|
|
121
|
+
*
|
|
122
|
+
* @param hookName - The hook identifier
|
|
123
|
+
* @param callback - If provided, check for this specific callback
|
|
124
|
+
* @returns false if no handlers, or the priority of the matching handler
|
|
125
|
+
*/
|
|
126
|
+
hasHook(hookName, callback) {
|
|
127
|
+
const handlers = this.hooks.get(hookName);
|
|
128
|
+
if (!handlers || handlers.length === 0)
|
|
129
|
+
return false;
|
|
130
|
+
if (callback === undefined) {
|
|
131
|
+
// Return the lowest priority (first handler)
|
|
132
|
+
return handlers[0].priority;
|
|
133
|
+
}
|
|
134
|
+
const found = handlers.find((h) => h.callback === callback);
|
|
135
|
+
return found ? found.priority : false;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Execute an action hook. All registered callbacks are called in priority order.
|
|
139
|
+
* The "all" universal hook fires before the specific hook.
|
|
140
|
+
*
|
|
141
|
+
* @param hookName - The hook identifier
|
|
142
|
+
* @param args - Arguments to pass to callbacks
|
|
143
|
+
*/
|
|
144
|
+
async doAction(hookName, ...args) {
|
|
145
|
+
// Fire the universal "all" hook first (if we're not already in "all")
|
|
146
|
+
if (hookName !== 'all') {
|
|
147
|
+
await this.fireUniversalHook(hookName, args);
|
|
148
|
+
}
|
|
149
|
+
const handlers = this.hooks.get(hookName);
|
|
150
|
+
this.incrementFireCount(hookName);
|
|
151
|
+
if (!handlers || handlers.length === 0)
|
|
152
|
+
return;
|
|
153
|
+
// Push onto execution stack
|
|
154
|
+
const stackEntry = { name: hookName, currentIndex: 0 };
|
|
155
|
+
this.currentStack.push(stackEntry);
|
|
156
|
+
try {
|
|
157
|
+
for (let i = 0; i < handlers.length; i++) {
|
|
158
|
+
stackEntry.currentIndex = i;
|
|
159
|
+
const handler = handlers[i];
|
|
160
|
+
const slicedArgs = args.slice(0, handler.acceptedArgs);
|
|
161
|
+
await handler.callback(...slicedArgs);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
this.currentStack.pop();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Execute an action hook synchronously.
|
|
170
|
+
*/
|
|
171
|
+
doActionSync(hookName, ...args) {
|
|
172
|
+
if (hookName !== 'all') {
|
|
173
|
+
this.fireUniversalHookSync(hookName, args);
|
|
174
|
+
}
|
|
175
|
+
const handlers = this.hooks.get(hookName);
|
|
176
|
+
this.incrementFireCount(hookName);
|
|
177
|
+
if (!handlers || handlers.length === 0)
|
|
178
|
+
return;
|
|
179
|
+
const stackEntry = { name: hookName, currentIndex: 0 };
|
|
180
|
+
this.currentStack.push(stackEntry);
|
|
181
|
+
try {
|
|
182
|
+
for (let i = 0; i < handlers.length; i++) {
|
|
183
|
+
stackEntry.currentIndex = i;
|
|
184
|
+
const handler = handlers[i];
|
|
185
|
+
const slicedArgs = args.slice(0, handler.acceptedArgs);
|
|
186
|
+
handler.callback(...slicedArgs);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
this.currentStack.pop();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Execute a filter hook. The first argument is the value being filtered.
|
|
195
|
+
* Each callback receives the (possibly modified) value and returns a new value.
|
|
196
|
+
* The "all" universal hook fires before the specific hook.
|
|
197
|
+
*
|
|
198
|
+
* @param hookName - The hook identifier
|
|
199
|
+
* @param value - The initial value to filter
|
|
200
|
+
* @param args - Additional arguments passed to each callback
|
|
201
|
+
* @returns The filtered value after all callbacks have processed it
|
|
202
|
+
*/
|
|
203
|
+
async applyFilters(hookName, value, ...args) {
|
|
204
|
+
// Fire the universal "all" hook first
|
|
205
|
+
if (hookName !== 'all') {
|
|
206
|
+
await this.fireUniversalHook(hookName, [value, ...args]);
|
|
207
|
+
}
|
|
208
|
+
const handlers = this.hooks.get(hookName);
|
|
209
|
+
this.incrementFireCount(hookName);
|
|
210
|
+
if (!handlers || handlers.length === 0)
|
|
211
|
+
return value;
|
|
212
|
+
const stackEntry = { name: hookName, currentIndex: 0 };
|
|
213
|
+
this.currentStack.push(stackEntry);
|
|
214
|
+
let filteredValue = value;
|
|
215
|
+
try {
|
|
216
|
+
for (let i = 0; i < handlers.length; i++) {
|
|
217
|
+
stackEntry.currentIndex = i;
|
|
218
|
+
const handler = handlers[i];
|
|
219
|
+
const callArgs = [filteredValue, ...args].slice(0, handler.acceptedArgs);
|
|
220
|
+
filteredValue = await handler.callback(filteredValue, ...callArgs.slice(1));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
finally {
|
|
224
|
+
this.currentStack.pop();
|
|
225
|
+
}
|
|
226
|
+
return filteredValue;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Execute a filter hook synchronously.
|
|
230
|
+
*/
|
|
231
|
+
applyFiltersSync(hookName, value, ...args) {
|
|
232
|
+
if (hookName !== 'all') {
|
|
233
|
+
this.fireUniversalHookSync(hookName, [value, ...args]);
|
|
234
|
+
}
|
|
235
|
+
const handlers = this.hooks.get(hookName);
|
|
236
|
+
this.incrementFireCount(hookName);
|
|
237
|
+
if (!handlers || handlers.length === 0)
|
|
238
|
+
return value;
|
|
239
|
+
const stackEntry = { name: hookName, currentIndex: 0 };
|
|
240
|
+
this.currentStack.push(stackEntry);
|
|
241
|
+
let filteredValue = value;
|
|
242
|
+
try {
|
|
243
|
+
for (let i = 0; i < handlers.length; i++) {
|
|
244
|
+
stackEntry.currentIndex = i;
|
|
245
|
+
const handler = handlers[i];
|
|
246
|
+
const callArgs = [filteredValue, ...args].slice(0, handler.acceptedArgs);
|
|
247
|
+
filteredValue = handler.callback(filteredValue, ...callArgs.slice(1));
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
finally {
|
|
251
|
+
this.currentStack.pop();
|
|
252
|
+
}
|
|
253
|
+
return filteredValue;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Get how many times a hook has been fired.
|
|
257
|
+
*/
|
|
258
|
+
getFireCount(hookName) {
|
|
259
|
+
return this.fireCount.get(hookName) ?? 0;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Check if a specific hook is currently being executed.
|
|
263
|
+
*/
|
|
264
|
+
isDoingHook(hookName) {
|
|
265
|
+
if (hookName === undefined) {
|
|
266
|
+
return this.currentStack.length > 0;
|
|
267
|
+
}
|
|
268
|
+
return this.currentStack.some((entry) => entry.name === hookName);
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Get the name of the hook currently being executed (top of stack).
|
|
272
|
+
* Returns undefined if no hook is executing.
|
|
273
|
+
*/
|
|
274
|
+
currentHook() {
|
|
275
|
+
if (this.currentStack.length === 0)
|
|
276
|
+
return undefined;
|
|
277
|
+
return this.currentStack[this.currentStack.length - 1].name;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Get a snapshot of the current execution stack.
|
|
281
|
+
*/
|
|
282
|
+
getExecutionStack() {
|
|
283
|
+
return [...this.currentStack];
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Check if a hook has ever been fired (fire count > 0).
|
|
287
|
+
*/
|
|
288
|
+
didHook(hookName) {
|
|
289
|
+
return this.getFireCount(hookName) > 0;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Get the number of handlers registered for a hook.
|
|
293
|
+
*/
|
|
294
|
+
getHandlerCount(hookName) {
|
|
295
|
+
return this.hooks.get(hookName)?.length ?? 0;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Reset the engine — useful for testing.
|
|
299
|
+
*/
|
|
300
|
+
reset() {
|
|
301
|
+
this.hooks.clear();
|
|
302
|
+
this.currentStack = [];
|
|
303
|
+
this.fireCount.clear();
|
|
304
|
+
anonymousCounter = 0;
|
|
305
|
+
}
|
|
306
|
+
// --- Convenience aliases matching WordPress API names ---
|
|
307
|
+
addAction(hookName, callback, options) {
|
|
308
|
+
return this.addHook(hookName, callback, options);
|
|
309
|
+
}
|
|
310
|
+
addFilter(hookName, callback, options) {
|
|
311
|
+
return this.addHook(hookName, callback, options);
|
|
312
|
+
}
|
|
313
|
+
removeAction(hookName, callback, priority) {
|
|
314
|
+
return this.removeHook(hookName, callback, priority);
|
|
315
|
+
}
|
|
316
|
+
removeFilter(hookName, callback, priority) {
|
|
317
|
+
return this.removeHook(hookName, callback, priority);
|
|
318
|
+
}
|
|
319
|
+
hasAction(hookName, callback) {
|
|
320
|
+
return this.hasHook(hookName, callback);
|
|
321
|
+
}
|
|
322
|
+
hasFilter(hookName, callback) {
|
|
323
|
+
return this.hasHook(hookName, callback);
|
|
324
|
+
}
|
|
325
|
+
didAction(hookName) {
|
|
326
|
+
return this.didHook(hookName);
|
|
327
|
+
}
|
|
328
|
+
didFilter(hookName) {
|
|
329
|
+
return this.didHook(hookName);
|
|
330
|
+
}
|
|
331
|
+
// --- Private helpers ---
|
|
332
|
+
incrementFireCount(hookName) {
|
|
333
|
+
this.fireCount.set(hookName, (this.fireCount.get(hookName) ?? 0) + 1);
|
|
334
|
+
}
|
|
335
|
+
async fireUniversalHook(hookName, args) {
|
|
336
|
+
const allHandlers = this.hooks.get('all');
|
|
337
|
+
if (!allHandlers || allHandlers.length === 0)
|
|
338
|
+
return;
|
|
339
|
+
const stackEntry = { name: 'all', currentIndex: 0 };
|
|
340
|
+
this.currentStack.push(stackEntry);
|
|
341
|
+
try {
|
|
342
|
+
for (let i = 0; i < allHandlers.length; i++) {
|
|
343
|
+
stackEntry.currentIndex = i;
|
|
344
|
+
const handler = allHandlers[i];
|
|
345
|
+
await handler.callback(hookName, ...args);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
finally {
|
|
349
|
+
this.currentStack.pop();
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
fireUniversalHookSync(hookName, args) {
|
|
353
|
+
const allHandlers = this.hooks.get('all');
|
|
354
|
+
if (!allHandlers || allHandlers.length === 0)
|
|
355
|
+
return;
|
|
356
|
+
const stackEntry = { name: 'all', currentIndex: 0 };
|
|
357
|
+
this.currentStack.push(stackEntry);
|
|
358
|
+
try {
|
|
359
|
+
for (let i = 0; i < allHandlers.length; i++) {
|
|
360
|
+
stackEntry.currentIndex = i;
|
|
361
|
+
const handler = allHandlers[i];
|
|
362
|
+
handler.callback(hookName, ...args);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
finally {
|
|
366
|
+
this.currentStack.pop();
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
//# sourceMappingURL=hook-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-engine.js","sourceRoot":"","sources":["../src/hook-engine.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { HookEngine } from './hook-engine.js';
|
|
2
|
+
export type { HookCallback, HookHandler, HookStackEntry, AddHookOptions, HasHookResult, PostTypeDefinition, TaxonomyDefinition, CapabilityContext, } from './types.js';
|
|
3
|
+
export { POST_STATUS, USER_ROLES, HOOK_PRIORITY } from './types.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EACX,YAAY,EACZ,WAAW,EACX,cAAc,EACd,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAW9C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic hook callback. Used for both actions and filters.
|
|
3
|
+
* Actions ignore the return value; filters chain it.
|
|
4
|
+
*/
|
|
5
|
+
export type HookCallback = (...args: any[]) => any;
|
|
6
|
+
/**
|
|
7
|
+
* A registered hook handler with its metadata.
|
|
8
|
+
*/
|
|
9
|
+
export interface HookHandler {
|
|
10
|
+
/** The callback function */
|
|
11
|
+
callback: HookCallback;
|
|
12
|
+
/** Execution priority (lower = earlier). Default: 10 */
|
|
13
|
+
priority: number;
|
|
14
|
+
/** Number of arguments the callback accepts */
|
|
15
|
+
acceptedArgs: number;
|
|
16
|
+
/** Unique identifier for this handler */
|
|
17
|
+
id: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Represents a hook currently being executed in the stack.
|
|
21
|
+
*/
|
|
22
|
+
export interface HookStackEntry {
|
|
23
|
+
/** The hook name being executed */
|
|
24
|
+
name: string;
|
|
25
|
+
/** Current iteration index within the priority groups */
|
|
26
|
+
currentIndex: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Options for adding a hook.
|
|
30
|
+
*/
|
|
31
|
+
export interface AddHookOptions {
|
|
32
|
+
/** Execution priority. Default: 10 */
|
|
33
|
+
priority?: number;
|
|
34
|
+
/** Number of arguments the callback accepts. Default: 1 */
|
|
35
|
+
acceptedArgs?: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Result of checking if a hook has handlers.
|
|
39
|
+
* Returns false if no handlers, or the priority of the first matching handler.
|
|
40
|
+
*/
|
|
41
|
+
export type HasHookResult = false | number;
|
|
42
|
+
/**
|
|
43
|
+
* Registered post type definition.
|
|
44
|
+
*/
|
|
45
|
+
export interface PostTypeDefinition {
|
|
46
|
+
name: string;
|
|
47
|
+
label: string;
|
|
48
|
+
labels?: Record<string, string>;
|
|
49
|
+
public?: boolean;
|
|
50
|
+
hierarchical?: boolean;
|
|
51
|
+
showInRest?: boolean;
|
|
52
|
+
restBase?: string;
|
|
53
|
+
supports?: string[];
|
|
54
|
+
taxonomies?: string[];
|
|
55
|
+
hasArchive?: boolean;
|
|
56
|
+
rewrite?: {
|
|
57
|
+
slug: string;
|
|
58
|
+
withFront?: boolean;
|
|
59
|
+
} | false;
|
|
60
|
+
menuPosition?: number;
|
|
61
|
+
menuIcon?: string;
|
|
62
|
+
capability_type?: string;
|
|
63
|
+
capabilities?: Record<string, string>;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Registered taxonomy definition.
|
|
67
|
+
*/
|
|
68
|
+
export interface TaxonomyDefinition {
|
|
69
|
+
name: string;
|
|
70
|
+
objectTypes: string[];
|
|
71
|
+
label: string;
|
|
72
|
+
labels?: Record<string, string>;
|
|
73
|
+
public?: boolean;
|
|
74
|
+
hierarchical?: boolean;
|
|
75
|
+
showInRest?: boolean;
|
|
76
|
+
restBase?: string;
|
|
77
|
+
rewrite?: {
|
|
78
|
+
slug: string;
|
|
79
|
+
withFront?: boolean;
|
|
80
|
+
hierarchical?: boolean;
|
|
81
|
+
} | false;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* User capability check context.
|
|
85
|
+
*/
|
|
86
|
+
export interface CapabilityContext {
|
|
87
|
+
userId: number;
|
|
88
|
+
capability: string;
|
|
89
|
+
objectId?: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Standard post statuses.
|
|
93
|
+
*/
|
|
94
|
+
export declare const POST_STATUS: {
|
|
95
|
+
readonly PUBLISH: "publish";
|
|
96
|
+
readonly DRAFT: "draft";
|
|
97
|
+
readonly PENDING: "pending";
|
|
98
|
+
readonly PRIVATE: "private";
|
|
99
|
+
readonly TRASH: "trash";
|
|
100
|
+
readonly AUTO_DRAFT: "auto-draft";
|
|
101
|
+
readonly INHERIT: "inherit";
|
|
102
|
+
readonly FUTURE: "future";
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Default user roles.
|
|
106
|
+
*/
|
|
107
|
+
export declare const USER_ROLES: {
|
|
108
|
+
readonly ADMINISTRATOR: "administrator";
|
|
109
|
+
readonly EDITOR: "editor";
|
|
110
|
+
readonly AUTHOR: "author";
|
|
111
|
+
readonly CONTRIBUTOR: "contributor";
|
|
112
|
+
readonly SUBSCRIBER: "subscriber";
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Default hook priorities.
|
|
116
|
+
*/
|
|
117
|
+
export declare const HOOK_PRIORITY: {
|
|
118
|
+
readonly EARLIEST: 1;
|
|
119
|
+
readonly EARLY: 5;
|
|
120
|
+
readonly DEFAULT: 10;
|
|
121
|
+
readonly LATE: 15;
|
|
122
|
+
readonly LATEST: 20;
|
|
123
|
+
};
|
|
124
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,4BAA4B;IAC5B,QAAQ,EAAE,YAAY,CAAC;IACvB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;CACX;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,KAAK,CAAC;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,KAAK,CAAC;CAChF;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;CASd,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;CAMb,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;CAMhB,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard post statuses.
|
|
3
|
+
*/
|
|
4
|
+
export const POST_STATUS = {
|
|
5
|
+
PUBLISH: 'publish',
|
|
6
|
+
DRAFT: 'draft',
|
|
7
|
+
PENDING: 'pending',
|
|
8
|
+
PRIVATE: 'private',
|
|
9
|
+
TRASH: 'trash',
|
|
10
|
+
AUTO_DRAFT: 'auto-draft',
|
|
11
|
+
INHERIT: 'inherit',
|
|
12
|
+
FUTURE: 'future',
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Default user roles.
|
|
16
|
+
*/
|
|
17
|
+
export const USER_ROLES = {
|
|
18
|
+
ADMINISTRATOR: 'administrator',
|
|
19
|
+
EDITOR: 'editor',
|
|
20
|
+
AUTHOR: 'author',
|
|
21
|
+
CONTRIBUTOR: 'contributor',
|
|
22
|
+
SUBSCRIBER: 'subscriber',
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Default hook priorities.
|
|
26
|
+
*/
|
|
27
|
+
export const HOOK_PRIORITY = {
|
|
28
|
+
EARLIEST: 1,
|
|
29
|
+
EARLY: 5,
|
|
30
|
+
DEFAULT: 10,
|
|
31
|
+
LATE: 15,
|
|
32
|
+
LATEST: 20,
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA4FA;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IAC1B,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,UAAU,EAAE,YAAY;IACxB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;CACP,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACzB,aAAa,EAAE,eAAe;IAC9B,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,WAAW,EAAE,aAAa;IAC1B,UAAU,EAAE,YAAY;CACf,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC5B,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,CAAC;IACR,OAAO,EAAE,EAAE;IACX,IAAI,EAAE,EAAE;IACR,MAAM,EAAE,EAAE;CACD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@newcms/core",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Core hook engine, types, and constants for NewCMS",
|
|
6
|
+
"license": "GPL-2.0-or-later",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/durvs/newcms.git",
|
|
10
|
+
"directory": "packages/core"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"cms",
|
|
14
|
+
"hooks",
|
|
15
|
+
"filters",
|
|
16
|
+
"actions",
|
|
17
|
+
"newcms"
|
|
18
|
+
],
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"typescript": "^5.9.3",
|
|
30
|
+
"vitest": "^3.2.4",
|
|
31
|
+
"@newcms/config": "0.0.1"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc",
|
|
35
|
+
"dev": "tsc --watch",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"test:watch": "vitest",
|
|
39
|
+
"test:coverage": "vitest run --coverage",
|
|
40
|
+
"lint": "echo 'lint ok'",
|
|
41
|
+
"clean": "rm -rf dist .turbo"
|
|
42
|
+
}
|
|
43
|
+
}
|