@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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +7 -0
- package/dist/app.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware.d.ts +61 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +117 -0
- package/dist/middleware.js.map +1 -0
- package/dist/router.d.ts +1 -0
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +14 -2
- package/dist/router.js.map +1 -1
- package/package.json +2 -2
- package/src/app.ts +8 -0
- package/src/config.ts +3 -0
- package/src/index.ts +4 -1
- package/src/middleware.ts +159 -0
- package/src/router.ts +18 -2
package/.turbo/turbo-build.log
CHANGED
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,
|
|
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.
|
package/dist/config.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
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,
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
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,
|
|
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
|
|
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 {};
|
package/dist/router.d.ts.map
CHANGED
|
@@ -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;
|
|
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}`);
|
package/dist/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;
|
|
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.
|
|
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.
|
|
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,
|
|
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>
|
|
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}`);
|