@moriajs/core 0.2.0 → 0.3.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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @moriajs/core@0.2.0 build C:\Codes\node\2026\github\moriajs\packages\core
2
+ > @moriajs/core@0.3.1 build C:\Codes\node\2026\github\moriajs\packages\core
3
3
  > tsc
4
4
 
package/dist/app.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAOnF,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,mDAAmD;IACnD,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9B,wCAAwC;IACxC,cAAc,CAAC,EAAE,oBAAoB,CAAC;CACzC;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACrB,sCAAsC;IACtC,MAAM,EAAE,eAAe,CAAC;IACxB,qDAAqD;IACrD,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,gCAAgC;IAChC,GAAG,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,uBAAuB;IACvB,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACxE,sBAAsB;IACtB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,QAAQ,CAAC,CA4EhF"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAOnF,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,mDAAmD;IACnD,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9B,wCAAwC;IACxC,cAAc,CAAC,EAAE,oBAAoB,CAAC;CACzC;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACrB,sCAAsC;IACtC,MAAM,EAAE,eAAe,CAAC;IACxB,qDAAqD;IACrD,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,gCAAgC;IAChC,GAAG,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,uBAAuB;IACvB,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACxE,sBAAsB;IACtB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAoFhF"}
package/dist/app.js CHANGED
@@ -45,6 +45,13 @@ export async function createApp(options = {}) {
45
45
  // Relax CSP in development for Vite HMR
46
46
  contentSecurityPolicy: mode === 'production',
47
47
  });
48
+ // ─── Global Middleware ─────────────────────────────────────
49
+ if (config.middleware && config.middleware.length > 0) {
50
+ for (const mw of config.middleware) {
51
+ server.addHook('onRequest', mw);
52
+ }
53
+ server.log.info(`Registered ${config.middleware.length} global middleware(s)`);
54
+ }
48
55
  // Health check route
49
56
  server.get('/health', async () => ({ status: 'ok', timestamp: new Date().toISOString() }));
50
57
  // ─── Vite Integration ────────────────────────────────────
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -53,6 +53,8 @@ export interface MoriaConfig {
53
53
  /** Routes directory relative to rootDir (default: 'src/routes') */
54
54
  dir?: string;
55
55
  };
56
+ /** Global middleware (runs on every request) */
57
+ middleware?: Array<import('./middleware.js').MoriaMiddleware>;
56
58
  }
57
59
  /**
58
60
  * Helper to define a type-safe MoriaJS configuration.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,WAAW;IACxB,uBAAuB;IACvB,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IAEpC,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,2BAA2B;IAC3B,MAAM,CAAC,EAAE;QACL,wCAAwC;QACxC,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,2CAA2C;QAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,kCAAkC;QAClC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;QAC9E,yBAAyB;QACzB,IAAI,CAAC,EAAE;YACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;YACrC,WAAW,CAAC,EAAE,OAAO,CAAC;SACzB,CAAC;KACL,CAAC;IAEF,6BAA6B;IAC7B,QAAQ,CAAC,EAAE;QACP,kDAAkD;QAClD,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,qBAAqB;QACrB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,+CAA+C;QAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IAEF,mCAAmC;IACnC,IAAI,CAAC,EAAE;QACH,qBAAqB;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,2CAA2C;QAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gCAAgC;QAChC,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,yCAAyC;QACzC,aAAa,CAAC,EAAE,OAAO,CAAC;KAC3B,CAAC;IAEF,iCAAiC;IACjC,IAAI,CAAC,EAAE;QACH,+BAA+B;QAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,2DAA2D;QAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IAEF,uCAAuC;IACvC,MAAM,CAAC,EAAE;QACL,mEAAmE;QACnE,GAAG,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACL;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAE7D"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,WAAW;IACxB,uBAAuB;IACvB,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IAEpC,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,2BAA2B;IAC3B,MAAM,CAAC,EAAE;QACL,wCAAwC;QACxC,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,2CAA2C;QAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,kCAAkC;QAClC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;QAC9E,yBAAyB;QACzB,IAAI,CAAC,EAAE;YACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;YACrC,WAAW,CAAC,EAAE,OAAO,CAAC;SACzB,CAAC;KACL,CAAC;IAEF,6BAA6B;IAC7B,QAAQ,CAAC,EAAE;QACP,kDAAkD;QAClD,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,qBAAqB;QACrB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,+CAA+C;QAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IAEF,mCAAmC;IACnC,IAAI,CAAC,EAAE;QACH,qBAAqB;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,2CAA2C;QAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gCAAgC;QAChC,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,yCAAyC;QACzC,aAAa,CAAC,EAAE,OAAO,CAAC;KAC3B,CAAC;IAEF,iCAAiC;IACjC,IAAI,CAAC,EAAE;QACH,+BAA+B;QAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,2DAA2D;QAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IAEF,uCAAuC;IACvC,MAAM,CAAC,EAAE;QACL,mEAAmE;QACnE,GAAG,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IAEF,gDAAgD;IAChD,UAAU,CAAC,EAAE,KAAK,CAAC,OAAO,iBAAiB,EAAE,eAAe,CAAC,CAAC;CACjE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAE7D"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AA+DA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY,CAAC,MAAmB;IAC5C,OAAO,MAAM,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAkEA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY,CAAC,MAAmB;IAC5C,OAAO,MAAM,CAAC;AAClB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -2,15 +2,18 @@
2
2
  * @moriajs/core
3
3
  *
4
4
  * Framework core: Fastify server factory with sensible defaults,
5
- * plugin registration, Vite integration, and file-based routing.
5
+ * plugin registration, Vite integration, file-based routing,
6
+ * and middleware system.
6
7
  */
7
8
  export { createApp } from './app.js';
8
9
  export { defineConfig } from './config.js';
9
10
  export { defineMoriaPlugin } from './plugins.js';
11
+ export { defineMiddleware } from './middleware.js';
10
12
  export { createViteDevMiddleware, serveProductionAssets, getHtmlScripts } from './vite.js';
11
13
  export { scanRoutes, registerRoutes, filePathToUrlPath } from './router.js';
12
14
  export type { MoriaApp, MoriaAppOptions } from './app.js';
13
15
  export type { MoriaConfig } from './config.js';
14
16
  export type { MoriaPlugin, MoriaPluginContext } from './plugins.js';
17
+ export type { MoriaMiddleware, MiddlewareEntry } from './middleware.js';
15
18
  export type { RouteEntry, RouteHandler } from './router.js';
16
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE5E,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACpE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE5E,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACpE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACxE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -2,11 +2,13 @@
2
2
  * @moriajs/core
3
3
  *
4
4
  * Framework core: Fastify server factory with sensible defaults,
5
- * plugin registration, Vite integration, and file-based routing.
5
+ * plugin registration, Vite integration, file-based routing,
6
+ * and middleware system.
6
7
  */
7
8
  export { createApp } from './app.js';
8
9
  export { defineConfig } from './config.js';
9
10
  export { defineMoriaPlugin } from './plugins.js';
11
+ export { defineMiddleware } from './middleware.js';
10
12
  export { createViteDevMiddleware, serveProductionAssets, getHtmlScripts } from './vite.js';
11
13
  export { scanRoutes, registerRoutes, filePathToUrlPath } from './router.js';
12
14
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * MoriaJS Middleware System
3
+ *
4
+ * Provides file-based middleware via `_middleware.ts` files and
5
+ * a `defineMiddleware` helper for type-safe middleware definition.
6
+ *
7
+ * Middleware files are scoped to sibling and child routes:
8
+ * src/routes/_middleware.ts → applies to ALL routes
9
+ * src/routes/api/_middleware.ts → applies to /api/* routes
10
+ * src/routes/pages/_middleware.ts → applies to page routes
11
+ *
12
+ * Middleware functions run as Fastify preHandler hooks in order:
13
+ * root → parent → child (outermost first)
14
+ */
15
+ import type { FastifyRequest, FastifyReply } from 'fastify';
16
+ /**
17
+ * A MoriaJS middleware function.
18
+ *
19
+ * - Return nothing to continue to the next middleware / handler
20
+ * - Call `reply.send()` or return a value to short-circuit
21
+ */
22
+ export type MoriaMiddleware = (request: FastifyRequest, reply: FastifyReply) => void | Promise<void>;
23
+ /**
24
+ * A resolved middleware entry from a `_middleware.ts` file.
25
+ */
26
+ export interface MiddlewareEntry {
27
+ /** Directory path relative to routes dir (e.g., '', 'api', 'api/admin') */
28
+ scope: string;
29
+ /** URL prefix this middleware applies to */
30
+ urlPrefix: string;
31
+ /** Ordered array of middleware functions */
32
+ handlers: MoriaMiddleware[];
33
+ }
34
+ /**
35
+ * Define a type-safe middleware function.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * import { defineMiddleware } from '@moriajs/core';
40
+ *
41
+ * export default defineMiddleware(async (request, reply) => {
42
+ * request.log.info('request received');
43
+ * });
44
+ * ```
45
+ */
46
+ export declare function defineMiddleware(fn: MoriaMiddleware): MoriaMiddleware;
47
+ /**
48
+ * Scan a routes directory for `_middleware.ts` files and return
49
+ * resolved middleware entries, sorted from root → deepest.
50
+ */
51
+ export declare function scanMiddleware(routesDir: string): Promise<MiddlewareEntry[]>;
52
+ /**
53
+ * Get the ordered middleware chain for a given route URL path.
54
+ *
55
+ * Returns middleware from outermost (root) to innermost (closest parent).
56
+ *
57
+ * @param routeFilePath - File path relative to routes dir (e.g., 'api/hello.ts')
58
+ * @param entries - Scanned middleware entries
59
+ */
60
+ export declare function getMiddlewareChain(routeFilePath: string, entries: MiddlewareEntry[]): MoriaMiddleware[];
61
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK5D;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,CAC1B,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,YAAY,KAClB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,eAAe,GAAG,eAAe,CAErE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAgElF;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAC9B,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,eAAe,EAAE,GAC3B,eAAe,EAAE,CAkBnB"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * MoriaJS Middleware System
3
+ *
4
+ * Provides file-based middleware via `_middleware.ts` files and
5
+ * a `defineMiddleware` helper for type-safe middleware definition.
6
+ *
7
+ * Middleware files are scoped to sibling and child routes:
8
+ * src/routes/_middleware.ts → applies to ALL routes
9
+ * src/routes/api/_middleware.ts → applies to /api/* routes
10
+ * src/routes/pages/_middleware.ts → applies to page routes
11
+ *
12
+ * Middleware functions run as Fastify preHandler hooks in order:
13
+ * root → parent → child (outermost first)
14
+ */
15
+ import { glob } from 'glob';
16
+ import path from 'node:path';
17
+ import { pathToFileURL } from 'node:url';
18
+ /**
19
+ * Define a type-safe middleware function.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * import { defineMiddleware } from '@moriajs/core';
24
+ *
25
+ * export default defineMiddleware(async (request, reply) => {
26
+ * request.log.info('request received');
27
+ * });
28
+ * ```
29
+ */
30
+ export function defineMiddleware(fn) {
31
+ return fn;
32
+ }
33
+ /**
34
+ * Scan a routes directory for `_middleware.ts` files and return
35
+ * resolved middleware entries, sorted from root → deepest.
36
+ */
37
+ export async function scanMiddleware(routesDir) {
38
+ const pattern = '**/_middleware.{ts,js,mts,mjs}';
39
+ const files = await glob(pattern, {
40
+ cwd: routesDir,
41
+ posix: true,
42
+ });
43
+ const entries = [];
44
+ for (const file of files) {
45
+ const dir = path.posix.dirname(file); // e.g., '.', 'api', 'pages/admin'
46
+ const scope = dir === '.' ? '' : dir;
47
+ // Build URL prefix from scope
48
+ let urlPrefix = '/';
49
+ if (scope) {
50
+ // pages/ prefix is stripped in route URLs
51
+ let adjustedScope = scope;
52
+ if (adjustedScope.startsWith('pages')) {
53
+ adjustedScope = adjustedScope.slice(5); // remove 'pages'
54
+ }
55
+ if (adjustedScope && !adjustedScope.startsWith('/')) {
56
+ adjustedScope = '/' + adjustedScope;
57
+ }
58
+ urlPrefix = adjustedScope || '/';
59
+ }
60
+ const absolutePath = path.resolve(routesDir, file);
61
+ const fileUrl = pathToFileURL(absolutePath).href;
62
+ let mod;
63
+ try {
64
+ mod = await import(fileUrl);
65
+ }
66
+ catch (err) {
67
+ console.warn(`[moria] Failed to load middleware: ${file}`, err);
68
+ continue;
69
+ }
70
+ // Resolve handlers from default export
71
+ const exported = mod.default;
72
+ let handlers = [];
73
+ if (Array.isArray(exported)) {
74
+ handlers = exported.filter((fn) => typeof fn === 'function');
75
+ }
76
+ else if (typeof exported === 'function') {
77
+ handlers = [exported];
78
+ }
79
+ if (handlers.length === 0) {
80
+ console.warn(`[moria] Middleware file has no handlers: ${file}`);
81
+ continue;
82
+ }
83
+ entries.push({ scope, urlPrefix, handlers });
84
+ }
85
+ // Sort by scope depth (root first, deeper scopes later)
86
+ entries.sort((a, b) => {
87
+ const depthA = a.scope === '' ? 0 : a.scope.split('/').length;
88
+ const depthB = b.scope === '' ? 0 : b.scope.split('/').length;
89
+ return depthA - depthB;
90
+ });
91
+ return entries;
92
+ }
93
+ /**
94
+ * Get the ordered middleware chain for a given route URL path.
95
+ *
96
+ * Returns middleware from outermost (root) to innermost (closest parent).
97
+ *
98
+ * @param routeFilePath - File path relative to routes dir (e.g., 'api/hello.ts')
99
+ * @param entries - Scanned middleware entries
100
+ */
101
+ export function getMiddlewareChain(routeFilePath, entries) {
102
+ const routeDir = path.posix.dirname(routeFilePath);
103
+ const chain = [];
104
+ for (const entry of entries) {
105
+ // Root middleware (scope '') applies to everything
106
+ if (entry.scope === '') {
107
+ chain.push(...entry.handlers);
108
+ continue;
109
+ }
110
+ // Check if the route file is within this middleware's scope
111
+ if (routeDir === entry.scope || routeDir.startsWith(entry.scope + '/')) {
112
+ chain.push(...entry.handlers);
113
+ }
114
+ }
115
+ return chain;
116
+ }
117
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
package/dist/router.d.ts CHANGED
@@ -74,6 +74,7 @@ export declare function scanRoutes(routesDir: string): Promise<RouteEntry[]>;
74
74
  *
75
75
  * Page routes with Mithril components are auto-wrapped with SSR rendering.
76
76
  * API routes are registered directly as Fastify handlers.
77
+ * Middleware from `_middleware.ts` files is attached as `preHandler` hooks.
77
78
  */
78
79
  export declare function registerRoutes(server: FastifyInstance, routesDir: string, options?: RegisterRoutesOptions): Promise<RouteEntry[]>;
79
80
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,6CAA6C;AAC7C,QAAA,MAAM,YAAY,uEAAwE,CAAC;AAC3F,KAAK,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhD,mDAAmD;AACnD,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAExG,kEAAkE;AAClE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpF,8BAA8B;AAC9B,MAAM,WAAW,UAAU;IACvB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;IACrB,6CAA6C;IAC7C,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;IAC9D,2CAA2C;IAC3C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4CAA4C;IAC5C,aAAa,CAAC,EAAE,aAAa,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC,uBAAuB;IACvB,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IACpC,0CAA0C;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CACjC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkC1D;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAgGzE;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAChC,MAAM,EAAE,eAAe,EACvB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,qBAA0B,GACpC,OAAO,CAAC,UAAU,EAAE,CAAC,CAsDvB"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,6CAA6C;AAC7C,QAAA,MAAM,YAAY,uEAAwE,CAAC;AAC3F,KAAK,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhD,mDAAmD;AACnD,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAExG,kEAAkE;AAClE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpF,8BAA8B;AAC9B,MAAM,WAAW,UAAU;IACvB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;IACrB,6CAA6C;IAC7C,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;IAC9D,2CAA2C;IAC3C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4CAA4C;IAC5C,aAAa,CAAC,EAAE,aAAa,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC,uBAAuB;IACvB,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IACpC,0CAA0C;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CACjC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkC1D;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAgGzE;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAChC,MAAM,EAAE,eAAe,EACvB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,qBAA0B,GACpC,OAAO,CAAC,UAAU,EAAE,CAAC,CAoEvB"}
package/dist/router.js CHANGED
@@ -19,6 +19,7 @@
19
19
  import { glob } from 'glob';
20
20
  import path from 'node:path';
21
21
  import { pathToFileURL } from 'node:url';
22
+ import { scanMiddleware, getMiddlewareChain } from './middleware.js';
22
23
  /** Supported HTTP methods in route files. */
23
24
  const HTTP_METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];
24
25
  /**
@@ -157,12 +158,21 @@ export async function scanRoutes(routesDir) {
157
158
  *
158
159
  * Page routes with Mithril components are auto-wrapped with SSR rendering.
159
160
  * API routes are registered directly as Fastify handlers.
161
+ * Middleware from `_middleware.ts` files is attached as `preHandler` hooks.
160
162
  */
161
163
  export async function registerRoutes(server, routesDir, options = {}) {
162
164
  const routes = await scanRoutes(routesDir);
163
165
  const mode = options.mode ?? 'development';
164
166
  const config = options.config ?? {};
167
+ // ─── Scan file-based middleware ──────────────────────────
168
+ const middlewareEntries = await scanMiddleware(routesDir);
169
+ if (middlewareEntries.length > 0) {
170
+ server.log.info(`Found ${middlewareEntries.length} middleware file(s): ${middlewareEntries.map((m) => m.scope || '/').join(', ')}`);
171
+ }
165
172
  for (const route of routes) {
173
+ // Resolve middleware chain for this route
174
+ const chain = getMiddlewareChain(route.filePath, middlewareEntries);
175
+ const preHandler = chain.length > 0 ? chain : undefined;
166
176
  // ─── Page route with Mithril component → SSR handler ─────
167
177
  if (route.component) {
168
178
  const component = route.component;
@@ -171,11 +181,12 @@ export async function registerRoutes(server, routesDir, options = {}) {
171
181
  server.route({
172
182
  method: 'GET',
173
183
  url: route.urlPath,
184
+ preHandler,
174
185
  handler: async (request, reply) => {
175
186
  // Load server data if available
176
- let initialData;
187
+ let initialData = {};
177
188
  if (getServerData) {
178
- initialData = (await getServerData(request));
189
+ initialData = (await getServerData(request)) || {};
179
190
  }
180
191
  // Dynamic import of renderer (avoids circular deps)
181
192
  const { renderToString } = await import('@moriajs/renderer');
@@ -197,6 +208,7 @@ export async function registerRoutes(server, routesDir, options = {}) {
197
208
  server.route({
198
209
  method: method.toUpperCase(),
199
210
  url: route.urlPath,
211
+ preHandler,
200
212
  handler: handler,
201
213
  });
202
214
  server.log.info(`Route: ${method.toUpperCase()} ${route.urlPath} → ${route.filePath}`);
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moriajs/core",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "description": "MoriaJS framework core — Fastify server, Vite integration, and routing",
6
6
  "main": "./dist/index.js",
@@ -29,7 +29,7 @@
29
29
  "@types/node": "^22.0.0"
30
30
  },
31
31
  "peerDependencies": {
32
- "@moriajs/renderer": "0.2.0"
32
+ "@moriajs/renderer": "0.3.1"
33
33
  },
34
34
  "license": "MIT",
35
35
  "author": "Guntur-D <guntur.d.npm@gmail.com>",
package/src/app.ts CHANGED
@@ -81,6 +81,14 @@ export async function createApp(options: MoriaAppOptions = {}): Promise<MoriaApp
81
81
  contentSecurityPolicy: mode === 'production',
82
82
  });
83
83
 
84
+ // ─── Global Middleware ─────────────────────────────────────
85
+ if (config.middleware && config.middleware.length > 0) {
86
+ for (const mw of config.middleware) {
87
+ server.addHook('onRequest', mw);
88
+ }
89
+ server.log.info(`Registered ${config.middleware.length} global middleware(s)`);
90
+ }
91
+
84
92
  // Health check route
85
93
  server.get('/health', async () => ({ status: 'ok', timestamp: new Date().toISOString() }));
86
94
 
package/src/config.ts CHANGED
@@ -59,6 +59,9 @@ export interface MoriaConfig {
59
59
  /** Routes directory relative to rootDir (default: 'src/routes') */
60
60
  dir?: string;
61
61
  };
62
+
63
+ /** Global middleware (runs on every request) */
64
+ middleware?: Array<import('./middleware.js').MoriaMiddleware>;
62
65
  }
63
66
 
64
67
  /**
package/src/index.ts CHANGED
@@ -2,16 +2,19 @@
2
2
  * @moriajs/core
3
3
  *
4
4
  * Framework core: Fastify server factory with sensible defaults,
5
- * plugin registration, Vite integration, and file-based routing.
5
+ * plugin registration, Vite integration, file-based routing,
6
+ * and middleware system.
6
7
  */
7
8
 
8
9
  export { createApp } from './app.js';
9
10
  export { defineConfig } from './config.js';
10
11
  export { defineMoriaPlugin } from './plugins.js';
12
+ export { defineMiddleware } from './middleware.js';
11
13
  export { createViteDevMiddleware, serveProductionAssets, getHtmlScripts } from './vite.js';
12
14
  export { scanRoutes, registerRoutes, filePathToUrlPath } from './router.js';
13
15
 
14
16
  export type { MoriaApp, MoriaAppOptions } from './app.js';
15
17
  export type { MoriaConfig } from './config.js';
16
18
  export type { MoriaPlugin, MoriaPluginContext } from './plugins.js';
19
+ export type { MoriaMiddleware, MiddlewareEntry } from './middleware.js';
17
20
  export type { RouteEntry, RouteHandler } from './router.js';
@@ -0,0 +1,159 @@
1
+ /**
2
+ * MoriaJS Middleware System
3
+ *
4
+ * Provides file-based middleware via `_middleware.ts` files and
5
+ * a `defineMiddleware` helper for type-safe middleware definition.
6
+ *
7
+ * Middleware files are scoped to sibling and child routes:
8
+ * src/routes/_middleware.ts → applies to ALL routes
9
+ * src/routes/api/_middleware.ts → applies to /api/* routes
10
+ * src/routes/pages/_middleware.ts → applies to page routes
11
+ *
12
+ * Middleware functions run as Fastify preHandler hooks in order:
13
+ * root → parent → child (outermost first)
14
+ */
15
+
16
+ import type { FastifyRequest, FastifyReply } from 'fastify';
17
+ import { glob } from 'glob';
18
+ import path from 'node:path';
19
+ import { pathToFileURL } from 'node:url';
20
+
21
+ /**
22
+ * A MoriaJS middleware function.
23
+ *
24
+ * - Return nothing to continue to the next middleware / handler
25
+ * - Call `reply.send()` or return a value to short-circuit
26
+ */
27
+ export type MoriaMiddleware = (
28
+ request: FastifyRequest,
29
+ reply: FastifyReply
30
+ ) => void | Promise<void>;
31
+
32
+ /**
33
+ * A resolved middleware entry from a `_middleware.ts` file.
34
+ */
35
+ export interface MiddlewareEntry {
36
+ /** Directory path relative to routes dir (e.g., '', 'api', 'api/admin') */
37
+ scope: string;
38
+ /** URL prefix this middleware applies to */
39
+ urlPrefix: string;
40
+ /** Ordered array of middleware functions */
41
+ handlers: MoriaMiddleware[];
42
+ }
43
+
44
+ /**
45
+ * Define a type-safe middleware function.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * import { defineMiddleware } from '@moriajs/core';
50
+ *
51
+ * export default defineMiddleware(async (request, reply) => {
52
+ * request.log.info('request received');
53
+ * });
54
+ * ```
55
+ */
56
+ export function defineMiddleware(fn: MoriaMiddleware): MoriaMiddleware {
57
+ return fn;
58
+ }
59
+
60
+ /**
61
+ * Scan a routes directory for `_middleware.ts` files and return
62
+ * resolved middleware entries, sorted from root → deepest.
63
+ */
64
+ export async function scanMiddleware(routesDir: string): Promise<MiddlewareEntry[]> {
65
+ const pattern = '**/_middleware.{ts,js,mts,mjs}';
66
+ const files = await glob(pattern, {
67
+ cwd: routesDir,
68
+ posix: true,
69
+ });
70
+
71
+ const entries: MiddlewareEntry[] = [];
72
+
73
+ for (const file of files) {
74
+ const dir = path.posix.dirname(file); // e.g., '.', 'api', 'pages/admin'
75
+ const scope = dir === '.' ? '' : dir;
76
+
77
+ // Build URL prefix from scope
78
+ let urlPrefix = '/';
79
+ if (scope) {
80
+ // pages/ prefix is stripped in route URLs
81
+ let adjustedScope = scope;
82
+ if (adjustedScope.startsWith('pages')) {
83
+ adjustedScope = adjustedScope.slice(5); // remove 'pages'
84
+ }
85
+ if (adjustedScope && !adjustedScope.startsWith('/')) {
86
+ adjustedScope = '/' + adjustedScope;
87
+ }
88
+ urlPrefix = adjustedScope || '/';
89
+ }
90
+
91
+ const absolutePath = path.resolve(routesDir, file);
92
+ const fileUrl = pathToFileURL(absolutePath).href;
93
+
94
+ let mod: Record<string, unknown>;
95
+ try {
96
+ mod = await import(fileUrl);
97
+ } catch (err) {
98
+ console.warn(`[moria] Failed to load middleware: ${file}`, err);
99
+ continue;
100
+ }
101
+
102
+ // Resolve handlers from default export
103
+ const exported = mod.default;
104
+ let handlers: MoriaMiddleware[] = [];
105
+
106
+ if (Array.isArray(exported)) {
107
+ handlers = exported.filter((fn) => typeof fn === 'function') as MoriaMiddleware[];
108
+ } else if (typeof exported === 'function') {
109
+ handlers = [exported as MoriaMiddleware];
110
+ }
111
+
112
+ if (handlers.length === 0) {
113
+ console.warn(`[moria] Middleware file has no handlers: ${file}`);
114
+ continue;
115
+ }
116
+
117
+ entries.push({ scope, urlPrefix, handlers });
118
+ }
119
+
120
+ // Sort by scope depth (root first, deeper scopes later)
121
+ entries.sort((a, b) => {
122
+ const depthA = a.scope === '' ? 0 : a.scope.split('/').length;
123
+ const depthB = b.scope === '' ? 0 : b.scope.split('/').length;
124
+ return depthA - depthB;
125
+ });
126
+
127
+ return entries;
128
+ }
129
+
130
+ /**
131
+ * Get the ordered middleware chain for a given route URL path.
132
+ *
133
+ * Returns middleware from outermost (root) to innermost (closest parent).
134
+ *
135
+ * @param routeFilePath - File path relative to routes dir (e.g., 'api/hello.ts')
136
+ * @param entries - Scanned middleware entries
137
+ */
138
+ export function getMiddlewareChain(
139
+ routeFilePath: string,
140
+ entries: MiddlewareEntry[]
141
+ ): MoriaMiddleware[] {
142
+ const routeDir = path.posix.dirname(routeFilePath);
143
+ const chain: MoriaMiddleware[] = [];
144
+
145
+ for (const entry of entries) {
146
+ // Root middleware (scope '') applies to everything
147
+ if (entry.scope === '') {
148
+ chain.push(...entry.handlers);
149
+ continue;
150
+ }
151
+
152
+ // Check if the route file is within this middleware's scope
153
+ if (routeDir === entry.scope || routeDir.startsWith(entry.scope + '/')) {
154
+ chain.push(...entry.handlers);
155
+ }
156
+ }
157
+
158
+ return chain;
159
+ }
package/src/router.ts CHANGED
@@ -22,6 +22,7 @@ import { glob } from 'glob';
22
22
  import path from 'node:path';
23
23
  import { pathToFileURL } from 'node:url';
24
24
  import type { MoriaConfig } from './config.js';
25
+ import { scanMiddleware, getMiddlewareChain, type MoriaMiddleware } from './middleware.js';
25
26
 
26
27
  /** Supported HTTP methods in route files. */
27
28
  const HTTP_METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'] as const;
@@ -216,6 +217,7 @@ export async function scanRoutes(routesDir: string): Promise<RouteEntry[]> {
216
217
  *
217
218
  * Page routes with Mithril components are auto-wrapped with SSR rendering.
218
219
  * API routes are registered directly as Fastify handlers.
220
+ * Middleware from `_middleware.ts` files is attached as `preHandler` hooks.
219
221
  */
220
222
  export async function registerRoutes(
221
223
  server: FastifyInstance,
@@ -226,7 +228,19 @@ export async function registerRoutes(
226
228
  const mode = options.mode ?? 'development';
227
229
  const config = options.config ?? {};
228
230
 
231
+ // ─── Scan file-based middleware ──────────────────────────
232
+ const middlewareEntries = await scanMiddleware(routesDir);
233
+ if (middlewareEntries.length > 0) {
234
+ server.log.info(
235
+ `Found ${middlewareEntries.length} middleware file(s): ${middlewareEntries.map((m) => m.scope || '/').join(', ')}`
236
+ );
237
+ }
238
+
229
239
  for (const route of routes) {
240
+ // Resolve middleware chain for this route
241
+ const chain: MoriaMiddleware[] = getMiddlewareChain(route.filePath, middlewareEntries);
242
+ const preHandler = chain.length > 0 ? chain : undefined;
243
+
230
244
  // ─── Page route with Mithril component → SSR handler ─────
231
245
  if (route.component) {
232
246
  const component = route.component;
@@ -236,11 +250,12 @@ export async function registerRoutes(
236
250
  server.route({
237
251
  method: 'GET',
238
252
  url: route.urlPath,
253
+ preHandler,
239
254
  handler: async (request: FastifyRequest, reply: FastifyReply) => {
240
255
  // Load server data if available
241
- let initialData: Record<string, unknown> | undefined;
256
+ let initialData: Record<string, unknown> = {};
242
257
  if (getServerData) {
243
- initialData = (await getServerData(request)) as Record<string, unknown>;
258
+ initialData = (await getServerData(request)) as Record<string, unknown> || {};
244
259
  }
245
260
 
246
261
  // Dynamic import of renderer (avoids circular deps)
@@ -267,6 +282,7 @@ export async function registerRoutes(
267
282
  server.route({
268
283
  method: method.toUpperCase() as Uppercase<string>,
269
284
  url: route.urlPath,
285
+ preHandler,
270
286
  handler: handler as RouteHandler,
271
287
  });
272
288
  server.log.info(`Route: ${method.toUpperCase()} ${route.urlPath} → ${route.filePath}`);