@mokup/server 1.1.8 → 1.2.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.
@@ -549,12 +549,16 @@ async function loadConfig(file, logger) {
549
549
  if (!mod) {
550
550
  return null;
551
551
  }
552
- const value = mod?.default ?? mod;
552
+ const raw = mod?.default ?? mod;
553
+ const value = isPromise(raw) ? await raw : raw;
553
554
  if (!value || typeof value !== "object") {
554
555
  return null;
555
556
  }
556
557
  return value;
557
558
  }
559
+ function isPromise(value) {
560
+ return !!value && typeof value.then === "function";
561
+ }
558
562
  function normalizeMiddlewares(value, source, logger, position) {
559
563
  if (!value) {
560
564
  return [];
@@ -1,4 +1,4 @@
1
- import { d as RouteTable } from './shared/server.CyVIKPsp.cjs';
1
+ import { d as RouteTable } from './shared/server.DLPB_I9q.cjs';
2
2
  import { MockEntryOptions, PlaygroundOptionsInput } from '@mokup/shared';
3
3
  import '@mokup/runtime';
4
4
  import '@mokup/shared/hono';
@@ -1,4 +1,4 @@
1
- import { d as RouteTable } from './shared/server.CyVIKPsp.mjs';
1
+ import { d as RouteTable } from './shared/server.DLPB_I9q.mjs';
2
2
  import { MockEntryOptions, PlaygroundOptionsInput } from '@mokup/shared';
3
3
  import '@mokup/runtime';
4
4
  import '@mokup/shared/hono';
@@ -1,4 +1,4 @@
1
- import { d as RouteTable } from './shared/server.CyVIKPsp.js';
1
+ import { d as RouteTable } from './shared/server.DLPB_I9q.js';
2
2
  import { MockEntryOptions, PlaygroundOptionsInput } from '@mokup/shared';
3
3
  import '@mokup/runtime';
4
4
  import '@mokup/shared/hono';
@@ -542,12 +542,16 @@ async function loadConfig(file, logger) {
542
542
  if (!mod) {
543
543
  return null;
544
544
  }
545
- const value = mod?.default ?? mod;
545
+ const raw = mod?.default ?? mod;
546
+ const value = isPromise(raw) ? await raw : raw;
546
547
  if (!value || typeof value !== "object") {
547
548
  return null;
548
549
  }
549
550
  return value;
550
551
  }
552
+ function isPromise(value) {
553
+ return !!value && typeof value.then === "function";
554
+ }
551
555
  function normalizeMiddlewares(value, source, logger, position) {
552
556
  if (!value) {
553
557
  return [];
package/dist/index.cjs CHANGED
@@ -6,12 +6,90 @@ require('@mokup/runtime');
6
6
  require('./shared/server.aaygIV2Q.cjs');
7
7
 
8
8
  const middlewareSymbol = Symbol.for("mokup.config.middlewares");
9
- function createRegistry(list) {
10
- return {
11
- use: (...handlers) => {
12
- list.push(...handlers);
9
+ const contextStack = [];
10
+ function getActiveContext() {
11
+ const context = contextStack[contextStack.length - 1];
12
+ if (!context) {
13
+ throw new Error("onBeforeAll/onAfterAll must be called inside defineConfig()");
14
+ }
15
+ return context;
16
+ }
17
+ function runWithContext(context, fn) {
18
+ contextStack.push(context);
19
+ try {
20
+ const result = fn();
21
+ if (isPromise(result)) {
22
+ return result.finally(() => {
23
+ contextStack.pop();
24
+ });
25
+ }
26
+ contextStack.pop();
27
+ return result;
28
+ } catch (error) {
29
+ contextStack.pop();
30
+ throw error;
31
+ }
32
+ }
33
+ function isPromise(value) {
34
+ return !!value && typeof value.then === "function";
35
+ }
36
+ function normalizeHookError(policy) {
37
+ if (policy === "throw" || policy === "silent") {
38
+ return policy;
39
+ }
40
+ return "warn";
41
+ }
42
+ function reportHookError(error, policy) {
43
+ if (policy === "silent") {
44
+ return;
45
+ }
46
+ if (policy === "warn") {
47
+ console.warn("[@mokup/server] defineConfig hook failed:", error);
48
+ }
49
+ }
50
+ function runHookSequence(stage, hooks, policy, setStage) {
51
+ if (hooks.length === 0) {
52
+ return;
53
+ }
54
+ setStage(stage);
55
+ let chain = null;
56
+ const runHook = (hook) => {
57
+ try {
58
+ const result = hook();
59
+ if (isPromise(result)) {
60
+ return result.catch((error) => {
61
+ if (policy === "throw") {
62
+ throw error;
63
+ }
64
+ reportHookError(error, policy);
65
+ });
66
+ }
67
+ return void 0;
68
+ } catch (error) {
69
+ if (policy === "throw") {
70
+ throw error;
71
+ }
72
+ reportHookError(error, policy);
73
+ return void 0;
13
74
  }
14
75
  };
76
+ for (const hook of hooks) {
77
+ if (chain) {
78
+ chain = chain.then(() => runHook(hook));
79
+ continue;
80
+ }
81
+ const result = runHook(hook);
82
+ if (isPromise(result)) {
83
+ chain = result;
84
+ }
85
+ }
86
+ if (!chain) {
87
+ setStage("normal");
88
+ return;
89
+ }
90
+ return chain.finally(() => {
91
+ setStage("normal");
92
+ });
15
93
  }
16
94
  function attachMetadata(config, meta) {
17
95
  Object.defineProperty(config, middlewareSymbol, {
@@ -20,24 +98,75 @@ function attachMetadata(config, meta) {
20
98
  });
21
99
  return config;
22
100
  }
101
+ function normalizeConfig(value) {
102
+ return value && typeof value === "object" ? value : {};
103
+ }
104
+ function onBeforeAll(handler) {
105
+ if (typeof handler !== "function") {
106
+ throw new TypeError("onBeforeAll expects a function");
107
+ }
108
+ const context = getActiveContext();
109
+ context.hooks.pre.push(handler);
110
+ }
111
+ function onAfterAll(handler) {
112
+ if (typeof handler !== "function") {
113
+ throw new TypeError("onAfterAll expects a function");
114
+ }
115
+ const context = getActiveContext();
116
+ context.hooks.post.push(handler);
117
+ }
23
118
  function defineConfig(input) {
24
119
  if (typeof input === "function") {
25
120
  const pre = [];
26
121
  const normal = [];
27
122
  const post = [];
123
+ let stage = "normal";
124
+ const app = {
125
+ use: (...handlers) => {
126
+ if (stage === "pre") {
127
+ pre.push(...handlers);
128
+ return;
129
+ }
130
+ if (stage === "post") {
131
+ post.push(...handlers);
132
+ return;
133
+ }
134
+ normal.push(...handlers);
135
+ }
136
+ };
28
137
  const context = {
29
- pre: createRegistry(pre),
30
- normal: createRegistry(normal),
31
- post: createRegistry(post)
138
+ app,
139
+ hooks: { pre: [], post: [] },
140
+ setStage: (next) => {
141
+ stage = next;
142
+ }
143
+ };
144
+ const result = runWithContext(context, () => input({ app }));
145
+ const finalize = (value) => {
146
+ const config2 = normalizeConfig(value);
147
+ const policy = normalizeHookError(config2.hookError);
148
+ const preResult = runHookSequence("pre", context.hooks.pre, policy, context.setStage);
149
+ const runPost = () => runHookSequence("post", context.hooks.post, policy, context.setStage);
150
+ if (isPromise(preResult)) {
151
+ return preResult.then(runPost).then(() => attachMetadata(config2, { pre, normal, post }));
152
+ }
153
+ const postResult = runPost();
154
+ if (isPromise(postResult)) {
155
+ return postResult.then(() => attachMetadata(config2, { pre, normal, post }));
156
+ }
157
+ return attachMetadata(config2, { pre, normal, post });
32
158
  };
33
- const result = input(context);
34
- const config2 = result && typeof result === "object" ? result : {};
35
- return attachMetadata(config2, { pre, normal, post });
159
+ if (isPromise(result)) {
160
+ return result.then(finalize);
161
+ }
162
+ return finalize(result);
36
163
  }
37
- const config = input && typeof input === "object" ? input : {};
164
+ const config = normalizeConfig(input);
38
165
  return attachMetadata(config, { pre: [], normal: [], post: [] });
39
166
  }
40
167
 
41
168
  exports.createFetchHandler = fetch.createFetchHandler;
42
169
  exports.createMokupWorker = worker.createMokupWorker;
43
170
  exports.defineConfig = defineConfig;
171
+ exports.onAfterAll = onAfterAll;
172
+ exports.onBeforeAll = onBeforeAll;
package/dist/index.d.cts CHANGED
@@ -1,43 +1,52 @@
1
- import { R as RouteDirectoryConfig, M as MiddlewareRegistry } from './shared/server.CyVIKPsp.cjs';
2
- export { a as MiddlewarePosition, b as ResolvedMiddleware, c as RouteRule } from './shared/server.CyVIKPsp.cjs';
1
+ import { R as RouteDirectoryConfig } from './shared/server.DLPB_I9q.cjs';
2
+ export { H as HookErrorPolicy, M as MiddlewarePosition, a as MiddlewareRegistry, b as ResolvedMiddleware, c as RouteRule } from './shared/server.DLPB_I9q.cjs';
3
+ import { MiddlewareHandler } from '@mokup/shared/hono';
4
+ export { MiddlewareHandler } from '@mokup/shared/hono';
3
5
  export { createFetchHandler } from './fetch.cjs';
4
6
  export { F as FetchHandler, S as ServerOptions, W as WorkerBundle, a as WorkerInput } from './shared/server.LMr0or7K.cjs';
5
7
  export { createMokupWorker } from './worker.cjs';
6
8
  export { Manifest, ManifestRoute, ModuleMap, RuntimeOptions } from '@mokup/runtime';
7
- export { MiddlewareHandler } from '@mokup/shared/hono';
8
9
 
10
+ type HookHandler = () => void | Promise<void>;
11
+ interface ConfigApp {
12
+ use: (...handlers: MiddlewareHandler[]) => void;
13
+ }
9
14
  type DefineConfigFactory = (context: {
10
- pre: MiddlewareRegistry;
11
- normal: MiddlewareRegistry;
12
- post: MiddlewareRegistry;
13
- }) => RouteDirectoryConfig | void;
15
+ app: ConfigApp;
16
+ }) => RouteDirectoryConfig | void | Promise<RouteDirectoryConfig | void>;
17
+ declare function onBeforeAll(handler: HookHandler): void;
18
+ declare function onAfterAll(handler: HookHandler): void;
14
19
  /**
15
- * Define a directory config with Hono-style middleware registration.
20
+ * Define a directory config with hook-based middleware registration.
16
21
  *
17
22
  * @param input - Config object or factory callback.
18
23
  * @returns Route directory config with middleware metadata.
19
24
  *
20
25
  * @example
21
- * import { defineConfig } from '@mokup/server'
26
+ * import { defineConfig, onBeforeAll, onAfterAll } from '@mokup/server'
22
27
  *
23
- * export default defineConfig(({ pre, normal, post }) => {
24
- * pre.use(async (c, next) => {
25
- * c.header('x-before', '1')
26
- * await next()
28
+ * export default defineConfig(({ app }) => {
29
+ * onBeforeAll(() => {
30
+ * app.use(async (c, next) => {
31
+ * c.header('x-before', '1')
32
+ * await next()
33
+ * })
27
34
  * })
28
35
  *
29
- * normal.use(async (_c, next) => {
36
+ * app.use(async (_c, next) => {
30
37
  * await next()
31
38
  * })
32
39
  *
33
- * post.use(async (c, next) => {
34
- * await next()
35
- * c.header('x-after', '1')
40
+ * onAfterAll(() => {
41
+ * app.use(async (c, next) => {
42
+ * await next()
43
+ * c.header('x-after', '1')
44
+ * })
36
45
  * })
37
46
  *
38
47
  * return { delay: 120 }
39
48
  * })
40
49
  */
41
- declare function defineConfig(input: RouteDirectoryConfig | DefineConfigFactory): RouteDirectoryConfig;
50
+ declare function defineConfig(input: RouteDirectoryConfig | DefineConfigFactory): RouteDirectoryConfig | Promise<RouteDirectoryConfig>;
42
51
 
43
- export { MiddlewareRegistry, RouteDirectoryConfig, defineConfig };
52
+ export { RouteDirectoryConfig, defineConfig, onAfterAll, onBeforeAll };
package/dist/index.d.mts CHANGED
@@ -1,43 +1,52 @@
1
- import { R as RouteDirectoryConfig, M as MiddlewareRegistry } from './shared/server.CyVIKPsp.mjs';
2
- export { a as MiddlewarePosition, b as ResolvedMiddleware, c as RouteRule } from './shared/server.CyVIKPsp.mjs';
1
+ import { R as RouteDirectoryConfig } from './shared/server.DLPB_I9q.mjs';
2
+ export { H as HookErrorPolicy, M as MiddlewarePosition, a as MiddlewareRegistry, b as ResolvedMiddleware, c as RouteRule } from './shared/server.DLPB_I9q.mjs';
3
+ import { MiddlewareHandler } from '@mokup/shared/hono';
4
+ export { MiddlewareHandler } from '@mokup/shared/hono';
3
5
  export { createFetchHandler } from './fetch.mjs';
4
6
  export { F as FetchHandler, S as ServerOptions, W as WorkerBundle, a as WorkerInput } from './shared/server.LMr0or7K.mjs';
5
7
  export { createMokupWorker } from './worker.mjs';
6
8
  export { Manifest, ManifestRoute, ModuleMap, RuntimeOptions } from '@mokup/runtime';
7
- export { MiddlewareHandler } from '@mokup/shared/hono';
8
9
 
10
+ type HookHandler = () => void | Promise<void>;
11
+ interface ConfigApp {
12
+ use: (...handlers: MiddlewareHandler[]) => void;
13
+ }
9
14
  type DefineConfigFactory = (context: {
10
- pre: MiddlewareRegistry;
11
- normal: MiddlewareRegistry;
12
- post: MiddlewareRegistry;
13
- }) => RouteDirectoryConfig | void;
15
+ app: ConfigApp;
16
+ }) => RouteDirectoryConfig | void | Promise<RouteDirectoryConfig | void>;
17
+ declare function onBeforeAll(handler: HookHandler): void;
18
+ declare function onAfterAll(handler: HookHandler): void;
14
19
  /**
15
- * Define a directory config with Hono-style middleware registration.
20
+ * Define a directory config with hook-based middleware registration.
16
21
  *
17
22
  * @param input - Config object or factory callback.
18
23
  * @returns Route directory config with middleware metadata.
19
24
  *
20
25
  * @example
21
- * import { defineConfig } from '@mokup/server'
26
+ * import { defineConfig, onBeforeAll, onAfterAll } from '@mokup/server'
22
27
  *
23
- * export default defineConfig(({ pre, normal, post }) => {
24
- * pre.use(async (c, next) => {
25
- * c.header('x-before', '1')
26
- * await next()
28
+ * export default defineConfig(({ app }) => {
29
+ * onBeforeAll(() => {
30
+ * app.use(async (c, next) => {
31
+ * c.header('x-before', '1')
32
+ * await next()
33
+ * })
27
34
  * })
28
35
  *
29
- * normal.use(async (_c, next) => {
36
+ * app.use(async (_c, next) => {
30
37
  * await next()
31
38
  * })
32
39
  *
33
- * post.use(async (c, next) => {
34
- * await next()
35
- * c.header('x-after', '1')
40
+ * onAfterAll(() => {
41
+ * app.use(async (c, next) => {
42
+ * await next()
43
+ * c.header('x-after', '1')
44
+ * })
36
45
  * })
37
46
  *
38
47
  * return { delay: 120 }
39
48
  * })
40
49
  */
41
- declare function defineConfig(input: RouteDirectoryConfig | DefineConfigFactory): RouteDirectoryConfig;
50
+ declare function defineConfig(input: RouteDirectoryConfig | DefineConfigFactory): RouteDirectoryConfig | Promise<RouteDirectoryConfig>;
42
51
 
43
- export { MiddlewareRegistry, RouteDirectoryConfig, defineConfig };
52
+ export { RouteDirectoryConfig, defineConfig, onAfterAll, onBeforeAll };
package/dist/index.d.ts CHANGED
@@ -1,43 +1,52 @@
1
- import { R as RouteDirectoryConfig, M as MiddlewareRegistry } from './shared/server.CyVIKPsp.js';
2
- export { a as MiddlewarePosition, b as ResolvedMiddleware, c as RouteRule } from './shared/server.CyVIKPsp.js';
1
+ import { R as RouteDirectoryConfig } from './shared/server.DLPB_I9q.js';
2
+ export { H as HookErrorPolicy, M as MiddlewarePosition, a as MiddlewareRegistry, b as ResolvedMiddleware, c as RouteRule } from './shared/server.DLPB_I9q.js';
3
+ import { MiddlewareHandler } from '@mokup/shared/hono';
4
+ export { MiddlewareHandler } from '@mokup/shared/hono';
3
5
  export { createFetchHandler } from './fetch.js';
4
6
  export { F as FetchHandler, S as ServerOptions, W as WorkerBundle, a as WorkerInput } from './shared/server.LMr0or7K.js';
5
7
  export { createMokupWorker } from './worker.js';
6
8
  export { Manifest, ManifestRoute, ModuleMap, RuntimeOptions } from '@mokup/runtime';
7
- export { MiddlewareHandler } from '@mokup/shared/hono';
8
9
 
10
+ type HookHandler = () => void | Promise<void>;
11
+ interface ConfigApp {
12
+ use: (...handlers: MiddlewareHandler[]) => void;
13
+ }
9
14
  type DefineConfigFactory = (context: {
10
- pre: MiddlewareRegistry;
11
- normal: MiddlewareRegistry;
12
- post: MiddlewareRegistry;
13
- }) => RouteDirectoryConfig | void;
15
+ app: ConfigApp;
16
+ }) => RouteDirectoryConfig | void | Promise<RouteDirectoryConfig | void>;
17
+ declare function onBeforeAll(handler: HookHandler): void;
18
+ declare function onAfterAll(handler: HookHandler): void;
14
19
  /**
15
- * Define a directory config with Hono-style middleware registration.
20
+ * Define a directory config with hook-based middleware registration.
16
21
  *
17
22
  * @param input - Config object or factory callback.
18
23
  * @returns Route directory config with middleware metadata.
19
24
  *
20
25
  * @example
21
- * import { defineConfig } from '@mokup/server'
26
+ * import { defineConfig, onBeforeAll, onAfterAll } from '@mokup/server'
22
27
  *
23
- * export default defineConfig(({ pre, normal, post }) => {
24
- * pre.use(async (c, next) => {
25
- * c.header('x-before', '1')
26
- * await next()
28
+ * export default defineConfig(({ app }) => {
29
+ * onBeforeAll(() => {
30
+ * app.use(async (c, next) => {
31
+ * c.header('x-before', '1')
32
+ * await next()
33
+ * })
27
34
  * })
28
35
  *
29
- * normal.use(async (_c, next) => {
36
+ * app.use(async (_c, next) => {
30
37
  * await next()
31
38
  * })
32
39
  *
33
- * post.use(async (c, next) => {
34
- * await next()
35
- * c.header('x-after', '1')
40
+ * onAfterAll(() => {
41
+ * app.use(async (c, next) => {
42
+ * await next()
43
+ * c.header('x-after', '1')
44
+ * })
36
45
  * })
37
46
  *
38
47
  * return { delay: 120 }
39
48
  * })
40
49
  */
41
- declare function defineConfig(input: RouteDirectoryConfig | DefineConfigFactory): RouteDirectoryConfig;
50
+ declare function defineConfig(input: RouteDirectoryConfig | DefineConfigFactory): RouteDirectoryConfig | Promise<RouteDirectoryConfig>;
42
51
 
43
- export { MiddlewareRegistry, RouteDirectoryConfig, defineConfig };
52
+ export { RouteDirectoryConfig, defineConfig, onAfterAll, onBeforeAll };
package/dist/index.mjs CHANGED
@@ -4,12 +4,90 @@ import '@mokup/runtime';
4
4
  import './shared/server.LbftO9Jh.mjs';
5
5
 
6
6
  const middlewareSymbol = Symbol.for("mokup.config.middlewares");
7
- function createRegistry(list) {
8
- return {
9
- use: (...handlers) => {
10
- list.push(...handlers);
7
+ const contextStack = [];
8
+ function getActiveContext() {
9
+ const context = contextStack[contextStack.length - 1];
10
+ if (!context) {
11
+ throw new Error("onBeforeAll/onAfterAll must be called inside defineConfig()");
12
+ }
13
+ return context;
14
+ }
15
+ function runWithContext(context, fn) {
16
+ contextStack.push(context);
17
+ try {
18
+ const result = fn();
19
+ if (isPromise(result)) {
20
+ return result.finally(() => {
21
+ contextStack.pop();
22
+ });
23
+ }
24
+ contextStack.pop();
25
+ return result;
26
+ } catch (error) {
27
+ contextStack.pop();
28
+ throw error;
29
+ }
30
+ }
31
+ function isPromise(value) {
32
+ return !!value && typeof value.then === "function";
33
+ }
34
+ function normalizeHookError(policy) {
35
+ if (policy === "throw" || policy === "silent") {
36
+ return policy;
37
+ }
38
+ return "warn";
39
+ }
40
+ function reportHookError(error, policy) {
41
+ if (policy === "silent") {
42
+ return;
43
+ }
44
+ if (policy === "warn") {
45
+ console.warn("[@mokup/server] defineConfig hook failed:", error);
46
+ }
47
+ }
48
+ function runHookSequence(stage, hooks, policy, setStage) {
49
+ if (hooks.length === 0) {
50
+ return;
51
+ }
52
+ setStage(stage);
53
+ let chain = null;
54
+ const runHook = (hook) => {
55
+ try {
56
+ const result = hook();
57
+ if (isPromise(result)) {
58
+ return result.catch((error) => {
59
+ if (policy === "throw") {
60
+ throw error;
61
+ }
62
+ reportHookError(error, policy);
63
+ });
64
+ }
65
+ return void 0;
66
+ } catch (error) {
67
+ if (policy === "throw") {
68
+ throw error;
69
+ }
70
+ reportHookError(error, policy);
71
+ return void 0;
11
72
  }
12
73
  };
74
+ for (const hook of hooks) {
75
+ if (chain) {
76
+ chain = chain.then(() => runHook(hook));
77
+ continue;
78
+ }
79
+ const result = runHook(hook);
80
+ if (isPromise(result)) {
81
+ chain = result;
82
+ }
83
+ }
84
+ if (!chain) {
85
+ setStage("normal");
86
+ return;
87
+ }
88
+ return chain.finally(() => {
89
+ setStage("normal");
90
+ });
13
91
  }
14
92
  function attachMetadata(config, meta) {
15
93
  Object.defineProperty(config, middlewareSymbol, {
@@ -18,22 +96,71 @@ function attachMetadata(config, meta) {
18
96
  });
19
97
  return config;
20
98
  }
99
+ function normalizeConfig(value) {
100
+ return value && typeof value === "object" ? value : {};
101
+ }
102
+ function onBeforeAll(handler) {
103
+ if (typeof handler !== "function") {
104
+ throw new TypeError("onBeforeAll expects a function");
105
+ }
106
+ const context = getActiveContext();
107
+ context.hooks.pre.push(handler);
108
+ }
109
+ function onAfterAll(handler) {
110
+ if (typeof handler !== "function") {
111
+ throw new TypeError("onAfterAll expects a function");
112
+ }
113
+ const context = getActiveContext();
114
+ context.hooks.post.push(handler);
115
+ }
21
116
  function defineConfig(input) {
22
117
  if (typeof input === "function") {
23
118
  const pre = [];
24
119
  const normal = [];
25
120
  const post = [];
121
+ let stage = "normal";
122
+ const app = {
123
+ use: (...handlers) => {
124
+ if (stage === "pre") {
125
+ pre.push(...handlers);
126
+ return;
127
+ }
128
+ if (stage === "post") {
129
+ post.push(...handlers);
130
+ return;
131
+ }
132
+ normal.push(...handlers);
133
+ }
134
+ };
26
135
  const context = {
27
- pre: createRegistry(pre),
28
- normal: createRegistry(normal),
29
- post: createRegistry(post)
136
+ app,
137
+ hooks: { pre: [], post: [] },
138
+ setStage: (next) => {
139
+ stage = next;
140
+ }
141
+ };
142
+ const result = runWithContext(context, () => input({ app }));
143
+ const finalize = (value) => {
144
+ const config2 = normalizeConfig(value);
145
+ const policy = normalizeHookError(config2.hookError);
146
+ const preResult = runHookSequence("pre", context.hooks.pre, policy, context.setStage);
147
+ const runPost = () => runHookSequence("post", context.hooks.post, policy, context.setStage);
148
+ if (isPromise(preResult)) {
149
+ return preResult.then(runPost).then(() => attachMetadata(config2, { pre, normal, post }));
150
+ }
151
+ const postResult = runPost();
152
+ if (isPromise(postResult)) {
153
+ return postResult.then(() => attachMetadata(config2, { pre, normal, post }));
154
+ }
155
+ return attachMetadata(config2, { pre, normal, post });
30
156
  };
31
- const result = input(context);
32
- const config2 = result && typeof result === "object" ? result : {};
33
- return attachMetadata(config2, { pre, normal, post });
157
+ if (isPromise(result)) {
158
+ return result.then(finalize);
159
+ }
160
+ return finalize(result);
34
161
  }
35
- const config = input && typeof input === "object" ? input : {};
162
+ const config = normalizeConfig(input);
36
163
  return attachMetadata(config, { pre: [], normal: [], post: [] });
37
164
  }
38
165
 
39
- export { defineConfig };
166
+ export { defineConfig, onAfterAll, onBeforeAll };
package/dist/node.d.cts CHANGED
@@ -9,6 +9,6 @@ export { serve } from '@hono/node-server';
9
9
  import './shared/server.D0gAciOr.cjs';
10
10
  import './shared/server.LMr0or7K.cjs';
11
11
  import '@mokup/runtime';
12
- import './shared/server.CyVIKPsp.cjs';
12
+ import './shared/server.DLPB_I9q.cjs';
13
13
  import '@mokup/shared/hono';
14
14
  import '@mokup/shared';
package/dist/node.d.mts CHANGED
@@ -9,6 +9,6 @@ export { serve } from '@hono/node-server';
9
9
  import './shared/server.D0gAciOr.mjs';
10
10
  import './shared/server.LMr0or7K.mjs';
11
11
  import '@mokup/runtime';
12
- import './shared/server.CyVIKPsp.mjs';
12
+ import './shared/server.DLPB_I9q.mjs';
13
13
  import '@mokup/shared/hono';
14
14
  import '@mokup/shared';
package/dist/node.d.ts CHANGED
@@ -9,6 +9,6 @@ export { serve } from '@hono/node-server';
9
9
  import './shared/server.D0gAciOr.js';
10
10
  import './shared/server.LMr0or7K.js';
11
11
  import '@mokup/runtime';
12
- import './shared/server.CyVIKPsp.js';
12
+ import './shared/server.DLPB_I9q.js';
13
13
  import '@mokup/shared/hono';
14
14
  import '@mokup/shared';
@@ -141,6 +141,12 @@ interface RouteDirectoryConfig {
141
141
  * @default undefined
142
142
  */
143
143
  middleware?: MiddlewareHandler | MiddlewareHandler[];
144
+ /**
145
+ * Error handling policy for defineConfig hooks.
146
+ *
147
+ * @default "warn"
148
+ */
149
+ hookError?: HookErrorPolicy;
144
150
  }
145
151
  /**
146
152
  * Middleware execution position.
@@ -151,6 +157,10 @@ interface RouteDirectoryConfig {
151
157
  * const position: MiddlewarePosition = 'pre'
152
158
  */
153
159
  type MiddlewarePosition = 'pre' | 'normal' | 'post';
160
+ /**
161
+ * Error handling policy for config hooks.
162
+ */
163
+ type HookErrorPolicy = 'throw' | 'warn' | 'silent';
154
164
  /**
155
165
  * Middleware registry used by defineConfig.
156
166
  *
@@ -211,4 +221,4 @@ interface ResolvedRoute {
211
221
  }
212
222
  type RouteTable = ResolvedRoute[];
213
223
 
214
- export type { MiddlewareRegistry as M, RouteDirectoryConfig as R, MiddlewarePosition as a, ResolvedMiddleware as b, RouteRule as c, RouteTable as d };
224
+ export type { HookErrorPolicy as H, MiddlewarePosition as M, RouteDirectoryConfig as R, MiddlewareRegistry as a, ResolvedMiddleware as b, RouteRule as c, RouteTable as d };
@@ -141,6 +141,12 @@ interface RouteDirectoryConfig {
141
141
  * @default undefined
142
142
  */
143
143
  middleware?: MiddlewareHandler | MiddlewareHandler[];
144
+ /**
145
+ * Error handling policy for defineConfig hooks.
146
+ *
147
+ * @default "warn"
148
+ */
149
+ hookError?: HookErrorPolicy;
144
150
  }
145
151
  /**
146
152
  * Middleware execution position.
@@ -151,6 +157,10 @@ interface RouteDirectoryConfig {
151
157
  * const position: MiddlewarePosition = 'pre'
152
158
  */
153
159
  type MiddlewarePosition = 'pre' | 'normal' | 'post';
160
+ /**
161
+ * Error handling policy for config hooks.
162
+ */
163
+ type HookErrorPolicy = 'throw' | 'warn' | 'silent';
154
164
  /**
155
165
  * Middleware registry used by defineConfig.
156
166
  *
@@ -211,4 +221,4 @@ interface ResolvedRoute {
211
221
  }
212
222
  type RouteTable = ResolvedRoute[];
213
223
 
214
- export type { MiddlewareRegistry as M, RouteDirectoryConfig as R, MiddlewarePosition as a, ResolvedMiddleware as b, RouteRule as c, RouteTable as d };
224
+ export type { HookErrorPolicy as H, MiddlewarePosition as M, RouteDirectoryConfig as R, MiddlewareRegistry as a, ResolvedMiddleware as b, RouteRule as c, RouteTable as d };
@@ -141,6 +141,12 @@ interface RouteDirectoryConfig {
141
141
  * @default undefined
142
142
  */
143
143
  middleware?: MiddlewareHandler | MiddlewareHandler[];
144
+ /**
145
+ * Error handling policy for defineConfig hooks.
146
+ *
147
+ * @default "warn"
148
+ */
149
+ hookError?: HookErrorPolicy;
144
150
  }
145
151
  /**
146
152
  * Middleware execution position.
@@ -151,6 +157,10 @@ interface RouteDirectoryConfig {
151
157
  * const position: MiddlewarePosition = 'pre'
152
158
  */
153
159
  type MiddlewarePosition = 'pre' | 'normal' | 'post';
160
+ /**
161
+ * Error handling policy for config hooks.
162
+ */
163
+ type HookErrorPolicy = 'throw' | 'warn' | 'silent';
154
164
  /**
155
165
  * Middleware registry used by defineConfig.
156
166
  *
@@ -211,4 +221,4 @@ interface ResolvedRoute {
211
221
  }
212
222
  type RouteTable = ResolvedRoute[];
213
223
 
214
- export type { MiddlewareRegistry as M, RouteDirectoryConfig as R, MiddlewarePosition as a, ResolvedMiddleware as b, RouteRule as c, RouteTable as d };
224
+ export type { HookErrorPolicy as H, MiddlewarePosition as M, RouteDirectoryConfig as R, MiddlewareRegistry as a, ResolvedMiddleware as b, RouteRule as c, RouteTable as d };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mokup/server",
3
3
  "type": "module",
4
- "version": "1.1.8",
4
+ "version": "1.2.0",
5
5
  "description": "Server adapters for @mokup/runtime.",
6
6
  "license": "MIT",
7
7
  "homepage": "https://mokup.icebreaker.top",
@@ -80,9 +80,9 @@
80
80
  "@hono/node-server": "^1.19.9",
81
81
  "@hono/node-ws": "^1.1.1",
82
82
  "tsx": "^4.21.0",
83
+ "@mokup/shared": "1.1.1",
83
84
  "@mokup/playground": "0.0.15",
84
- "@mokup/runtime": "1.0.6",
85
- "@mokup/shared": "1.1.1"
85
+ "@mokup/runtime": "1.0.6"
86
86
  },
87
87
  "devDependencies": {
88
88
  "@types/node": "^25.0.10",