@singhak/nodeui-fastify 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -52
- package/dist/index.cjs +9 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +11 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
# @singhak/nodeui-fastify
|
|
2
|
-
|
|
3
|
-
Fastify plugin adapter for the NodeUI developer console. Serves the bundled React
|
|
4
|
-
console and its API under `{path}` (default `/nodeui`), records app requests in
|
|
5
|
-
the request-log panel and lists your Fastify routes in the routes panel.
|
|
6
|
-
|
|
7
|
-
Supports Fastify 4 and 5.
|
|
8
|
-
|
|
9
|
-
## Install
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
npm install @singhak/nodeui-fastify
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Usage
|
|
16
|
-
|
|
17
|
-
```ts
|
|
18
|
-
import Fastify from 'fastify';
|
|
19
|
-
import { nodeui } from '@singhak/nodeui-fastify';
|
|
20
|
-
|
|
21
|
-
const app = Fastify();
|
|
22
|
-
const ui = nodeui();
|
|
23
|
-
|
|
24
|
-
// Register before your routes so they appear in the routes panel.
|
|
25
|
-
await app.register(ui);
|
|
26
|
-
|
|
27
|
-
app.get('/hello', async () => ({ hello: 'world' }));
|
|
28
|
-
|
|
29
|
-
await app.listen({ port: 3000, host: '127.0.0.1' });
|
|
30
|
-
ui.server.mark('listening');
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Open `http://127.0.0.1:3000/nodeui` for the console and
|
|
34
|
-
`http://127.0.0.1:3000/nodeui/api/config` for the API.
|
|
35
|
-
|
|
36
|
-
The plugin is not encapsulated (equivalent to `fastify-plugin`), shuts the
|
|
37
|
-
server down on `app.close()`, and does nothing when NodeUI is disabled (for
|
|
38
|
-
example when `NODE_ENV=production`).
|
|
39
|
-
|
|
40
|
-
## Options
|
|
41
|
-
|
|
42
|
-
`nodeui(options?)` accepts any `@singhak/nodeui-core` `NodeUIOptions` (path, host
|
|
43
|
-
allow-lists, auth token, plugins, health checks, etc.). See the
|
|
44
|
-
`@singhak/nodeui-core` README for the full configuration table and safety model.
|
|
45
|
-
|
|
46
|
-
## Development
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
npm run typecheck
|
|
50
|
-
npm test
|
|
51
|
-
npm run build
|
|
52
|
-
```
|
|
1
|
+
# @singhak/nodeui-fastify
|
|
2
|
+
|
|
3
|
+
Fastify plugin adapter for the NodeUI developer console. Serves the bundled React
|
|
4
|
+
console and its API under `{path}` (default `/nodeui`), records app requests in
|
|
5
|
+
the request-log panel and lists your Fastify routes in the routes panel.
|
|
6
|
+
|
|
7
|
+
Supports Fastify 4 and 5.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @singhak/nodeui-fastify
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import Fastify from 'fastify';
|
|
19
|
+
import { nodeui } from '@singhak/nodeui-fastify';
|
|
20
|
+
|
|
21
|
+
const app = Fastify();
|
|
22
|
+
const ui = nodeui();
|
|
23
|
+
|
|
24
|
+
// Register before your routes so they appear in the routes panel.
|
|
25
|
+
await app.register(ui);
|
|
26
|
+
|
|
27
|
+
app.get('/hello', async () => ({ hello: 'world' }));
|
|
28
|
+
|
|
29
|
+
await app.listen({ port: 3000, host: '127.0.0.1' });
|
|
30
|
+
ui.server.mark('listening');
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Open `http://127.0.0.1:3000/nodeui` for the console and
|
|
34
|
+
`http://127.0.0.1:3000/nodeui/api/config` for the API.
|
|
35
|
+
|
|
36
|
+
The plugin is not encapsulated (equivalent to `fastify-plugin`), shuts the
|
|
37
|
+
server down on `app.close()`, and does nothing when NodeUI is disabled (for
|
|
38
|
+
example when `NODE_ENV=production`).
|
|
39
|
+
|
|
40
|
+
## Options
|
|
41
|
+
|
|
42
|
+
`nodeui(options?)` accepts any `@singhak/nodeui-core` `NodeUIOptions` (path, host
|
|
43
|
+
allow-lists, auth token, plugins, health checks, etc.). See the
|
|
44
|
+
`@singhak/nodeui-core` README for the full configuration table and safety model.
|
|
45
|
+
|
|
46
|
+
## Development
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm run typecheck
|
|
50
|
+
npm test
|
|
51
|
+
npm run build
|
|
52
|
+
```
|
package/dist/index.cjs
CHANGED
|
@@ -64,7 +64,16 @@ function nodeui(options) {
|
|
|
64
64
|
await server.handle(req.raw, reply.raw);
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
67
|
+
const pattern = req.routeOptions?.url ?? req.routerPath;
|
|
68
|
+
if (pattern) req.raw.nodeuiRoute = pattern;
|
|
67
69
|
recorder(req.raw, reply.raw, () => void 0);
|
|
70
|
+
(0, import_nodeui_core.enterRequestContext)(req.raw);
|
|
71
|
+
});
|
|
72
|
+
app.addHook("onError", (req, _reply, error, hookDone) => {
|
|
73
|
+
server.recordError(error, {
|
|
74
|
+
route: req.routeOptions?.url
|
|
75
|
+
});
|
|
76
|
+
hookDone();
|
|
68
77
|
});
|
|
69
78
|
app.addHook("onClose", (_instance, next) => {
|
|
70
79
|
server.shutdown();
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { FastifyInstance, FastifyPluginCallback, RouteOptions } from 'fastify';\r\nimport {\r\n createNodeUI,\r\n type NodeUIOptions,\r\n type NodeUIServer,\r\n type RouteEntry,\r\n} from '@singhak/nodeui-core';\r\n\r\nexport interface NodeUIFastifyPlugin extends FastifyPluginCallback {\r\n /** Handle to the underlying server (mark, shutdown, config). */\r\n server: NodeUIServer;\r\n /** Pushes an external log entry into the log viewer (logger adapter). */\r\n addLogSource: NodeUIServer['addLogSource'];\r\n}\r\n\r\nfunction pathnameOf(url: string | undefined): string {\r\n try {\r\n return new URL(url ?? '/', 'http://localhost').pathname;\r\n } catch {\r\n return url ?? '/';\r\n }\r\n}\r\n\r\n/**\r\n * Creates the NodeUI Fastify plugin. Register it before your routes so the\r\n * routes panel and request log see them.\r\n *\r\n * @example\r\n * const ui = nodeui();\r\n * await app.register(ui);\r\n * await app.listen({ port: 3000, host: '127.0.0.1' });\r\n * ui.server.mark('listening');\r\n */\r\nexport function nodeui(options?: NodeUIOptions): NodeUIFastifyPlugin {\r\n const server = createNodeUI(options);\r\n const prefix = server.config.path;\r\n const isUnderPrefix = (p: string): boolean => p === prefix || p.startsWith(`${prefix}/`);\r\n const recorder = server.middleware();\r\n const routes = new Map<string, RouteEntry>();\r\n\r\n const plugin = ((app: FastifyInstance, _opts: unknown, done: (err?: Error) => void) => {\r\n if (!server.active) {\r\n done();\r\n return;\r\n }\r\n\r\n server.setRoutes(() =>\r\n [...routes.values()].sort(\r\n (a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method),\r\n ),\r\n );\r\n\r\n app.addHook('onRoute', (route: RouteOptions) => {\r\n const methods = Array.isArray(route.method) ? route.method : [route.method];\r\n const handler = (route.handler as { name?: string } | undefined)?.name || 'anonymous';\r\n for (const m of methods) {\r\n const method = String(m).toUpperCase();\r\n if (isUnderPrefix(route.url)) continue;\r\n routes.set(`${method} ${route.url}`, { method, path: route.url, handler });\r\n }\r\n });\r\n\r\n app.addHook('onRequest', async (req, reply) => {\r\n if (isUnderPrefix(pathnameOf(req.raw.url))) {\r\n reply.hijack();\r\n await server.handle(req.raw, reply.raw);\r\n return;\r\n }\r\n // Core's middleware records the request (finish listener) then calls next.\r\n recorder(req.raw, reply.raw, () => undefined);\r\n });\r\n\r\n app.addHook('onClose', (_instance, next) => {\r\n server.shutdown();\r\n next();\r\n });\r\n done();\r\n }) as NodeUIFastifyPlugin;\r\n\r\n // Same effect as fastify-plugin: expose hooks to the parent scope.\r\n const marks = plugin as unknown as Record<symbol, unknown>;\r\n marks[Symbol.for('skip-override')] = true;\r\n marks[Symbol.for('fastify.display-name')] = 'nodeui-fastify';\r\n plugin.server = server;\r\n plugin.addLogSource = server.addLogSource;\r\n return plugin;\r\n}\r\n\r\nexport * from '@singhak/nodeui-core';\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { FastifyInstance, FastifyPluginCallback, RouteOptions } from 'fastify';\r\nimport {\r\n createNodeUI,\r\n enterRequestContext,\r\n type NodeUIOptions,\r\n type NodeUIServer,\r\n type RouteEntry,\r\n} from '@singhak/nodeui-core';\r\n\r\nexport interface NodeUIFastifyPlugin extends FastifyPluginCallback {\r\n /** Handle to the underlying server (mark, shutdown, config). */\r\n server: NodeUIServer;\r\n /** Pushes an external log entry into the log viewer (logger adapter). */\r\n addLogSource: NodeUIServer['addLogSource'];\r\n}\r\n\r\nfunction pathnameOf(url: string | undefined): string {\r\n try {\r\n return new URL(url ?? '/', 'http://localhost').pathname;\r\n } catch {\r\n return url ?? '/';\r\n }\r\n}\r\n\r\n/**\r\n * Creates the NodeUI Fastify plugin. Register it before your routes so the\r\n * routes panel and request log see them.\r\n *\r\n * @example\r\n * const ui = nodeui();\r\n * await app.register(ui);\r\n * await app.listen({ port: 3000, host: '127.0.0.1' });\r\n * ui.server.mark('listening');\r\n */\r\nexport function nodeui(options?: NodeUIOptions): NodeUIFastifyPlugin {\r\n const server = createNodeUI(options);\r\n const prefix = server.config.path;\r\n const isUnderPrefix = (p: string): boolean => p === prefix || p.startsWith(`${prefix}/`);\r\n const recorder = server.middleware();\r\n const routes = new Map<string, RouteEntry>();\r\n\r\n const plugin = ((app: FastifyInstance, _opts: unknown, done: (err?: Error) => void) => {\r\n if (!server.active) {\r\n done();\r\n return;\r\n }\r\n\r\n server.setRoutes(() =>\r\n [...routes.values()].sort(\r\n (a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method),\r\n ),\r\n );\r\n\r\n app.addHook('onRoute', (route: RouteOptions) => {\r\n const methods = Array.isArray(route.method) ? route.method : [route.method];\r\n const handler = (route.handler as { name?: string } | undefined)?.name || 'anonymous';\r\n for (const m of methods) {\r\n const method = String(m).toUpperCase();\r\n if (isUnderPrefix(route.url)) continue;\r\n routes.set(`${method} ${route.url}`, { method, path: route.url, handler });\r\n }\r\n });\r\n\r\n app.addHook('onRequest', async (req, reply) => {\r\n if (isUnderPrefix(pathnameOf(req.raw.url))) {\r\n reply.hijack();\r\n await server.handle(req.raw, reply.raw);\r\n return;\r\n }\r\n // Expose the matched route pattern to core's request recorder.\r\n const pattern =\r\n (req as { routeOptions?: { url?: string } }).routeOptions?.url ??\r\n (req as { routerPath?: string }).routerPath;\r\n if (pattern) (req.raw as { nodeuiRoute?: string }).nodeuiRoute = pattern;\r\n // Core's middleware records the request (finish listener) then calls next.\r\n recorder(req.raw, reply.raw, () => undefined);\r\n // Attribute outgoing calls and logs from the route handler to this request.\r\n enterRequestContext(req.raw);\r\n });\r\n\r\n app.addHook('onError', (req, _reply, error, hookDone) => {\r\n server.recordError(error, {\r\n route: (req as { routeOptions?: { url?: string } }).routeOptions?.url,\r\n });\r\n hookDone();\r\n });\r\n\r\n app.addHook('onClose', (_instance, next) => {\r\n server.shutdown();\r\n next();\r\n });\r\n done();\r\n }) as NodeUIFastifyPlugin;\r\n\r\n // Same effect as fastify-plugin: expose hooks to the parent scope.\r\n const marks = plugin as unknown as Record<symbol, unknown>;\r\n marks[Symbol.for('skip-override')] = true;\r\n marks[Symbol.for('fastify.display-name')] = 'nodeui-fastify';\r\n plugin.server = server;\r\n plugin.addLogSource = server.addLogSource;\r\n return plugin;\r\n}\r\n\r\nexport * from '@singhak/nodeui-core';\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,yBAMO;AAgGP,0BAAc,iCAvGd;AAgBA,SAAS,WAAW,KAAiC;AACnD,MAAI;AACF,WAAO,IAAI,IAAI,OAAO,KAAK,kBAAkB,EAAE;AAAA,EACjD,QAAQ;AACN,WAAO,OAAO;AAAA,EAChB;AACF;AAYO,SAAS,OAAO,SAA8C;AACnE,QAAM,aAAS,iCAAa,OAAO;AACnC,QAAM,SAAS,OAAO,OAAO;AAC7B,QAAM,gBAAgB,CAAC,MAAuB,MAAM,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG;AACvF,QAAM,WAAW,OAAO,WAAW;AACnC,QAAM,SAAS,oBAAI,IAAwB;AAE3C,QAAM,UAAU,CAAC,KAAsB,OAAgB,SAAgC;AACrF,QAAI,CAAC,OAAO,QAAQ;AAClB,WAAK;AACL;AAAA,IACF;AAEA,WAAO;AAAA,MAAU,MACf,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE;AAAA,QACnB,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,KAAK,EAAE,OAAO,cAAc,EAAE,MAAM;AAAA,MAC3E;AAAA,IACF;AAEA,QAAI,QAAQ,WAAW,CAAC,UAAwB;AAC9C,YAAM,UAAU,MAAM,QAAQ,MAAM,MAAM,IAAI,MAAM,SAAS,CAAC,MAAM,MAAM;AAC1E,YAAM,UAAW,MAAM,SAA2C,QAAQ;AAC1E,iBAAW,KAAK,SAAS;AACvB,cAAM,SAAS,OAAO,CAAC,EAAE,YAAY;AACrC,YAAI,cAAc,MAAM,GAAG,EAAG;AAC9B,eAAO,IAAI,GAAG,MAAM,IAAI,MAAM,GAAG,IAAI,EAAE,QAAQ,MAAM,MAAM,KAAK,QAAQ,CAAC;AAAA,MAC3E;AAAA,IACF,CAAC;AAED,QAAI,QAAQ,aAAa,OAAO,KAAK,UAAU;AAC7C,UAAI,cAAc,WAAW,IAAI,IAAI,GAAG,CAAC,GAAG;AAC1C,cAAM,OAAO;AACb,cAAM,OAAO,OAAO,IAAI,KAAK,MAAM,GAAG;AACtC;AAAA,MACF;AAEA,YAAM,UACH,IAA4C,cAAc,OAC1D,IAAgC;AACnC,UAAI,QAAS,CAAC,IAAI,IAAiC,cAAc;AAEjE,eAAS,IAAI,KAAK,MAAM,KAAK,MAAM,MAAS;AAE5C,kDAAoB,IAAI,GAAG;AAAA,IAC7B,CAAC;AAED,QAAI,QAAQ,WAAW,CAAC,KAAK,QAAQ,OAAO,aAAa;AACvD,aAAO,YAAY,OAAO;AAAA,QACxB,OAAQ,IAA4C,cAAc;AAAA,MACpE,CAAC;AACD,eAAS;AAAA,IACX,CAAC;AAED,QAAI,QAAQ,WAAW,CAAC,WAAW,SAAS;AAC1C,aAAO,SAAS;AAChB,WAAK;AAAA,IACP,CAAC;AACD,SAAK;AAAA,EACP;AAGA,QAAM,QAAQ;AACd,QAAM,uBAAO,IAAI,eAAe,CAAC,IAAI;AACrC,QAAM,uBAAO,IAAI,sBAAsB,CAAC,IAAI;AAC5C,SAAO,SAAS;AAChB,SAAO,eAAe,OAAO;AAC7B,SAAO;AACT;","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import {
|
|
3
|
-
createNodeUI
|
|
3
|
+
createNodeUI,
|
|
4
|
+
enterRequestContext
|
|
4
5
|
} from "@singhak/nodeui-core";
|
|
5
6
|
export * from "@singhak/nodeui-core";
|
|
6
7
|
function pathnameOf(url) {
|
|
@@ -41,7 +42,16 @@ function nodeui(options) {
|
|
|
41
42
|
await server.handle(req.raw, reply.raw);
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
45
|
+
const pattern = req.routeOptions?.url ?? req.routerPath;
|
|
46
|
+
if (pattern) req.raw.nodeuiRoute = pattern;
|
|
44
47
|
recorder(req.raw, reply.raw, () => void 0);
|
|
48
|
+
enterRequestContext(req.raw);
|
|
49
|
+
});
|
|
50
|
+
app.addHook("onError", (req, _reply, error, hookDone) => {
|
|
51
|
+
server.recordError(error, {
|
|
52
|
+
route: req.routeOptions?.url
|
|
53
|
+
});
|
|
54
|
+
hookDone();
|
|
45
55
|
});
|
|
46
56
|
app.addHook("onClose", (_instance, next) => {
|
|
47
57
|
server.shutdown();
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { FastifyInstance, FastifyPluginCallback, RouteOptions } from 'fastify';\r\nimport {\r\n createNodeUI,\r\n type NodeUIOptions,\r\n type NodeUIServer,\r\n type RouteEntry,\r\n} from '@singhak/nodeui-core';\r\n\r\nexport interface NodeUIFastifyPlugin extends FastifyPluginCallback {\r\n /** Handle to the underlying server (mark, shutdown, config). */\r\n server: NodeUIServer;\r\n /** Pushes an external log entry into the log viewer (logger adapter). */\r\n addLogSource: NodeUIServer['addLogSource'];\r\n}\r\n\r\nfunction pathnameOf(url: string | undefined): string {\r\n try {\r\n return new URL(url ?? '/', 'http://localhost').pathname;\r\n } catch {\r\n return url ?? '/';\r\n }\r\n}\r\n\r\n/**\r\n * Creates the NodeUI Fastify plugin. Register it before your routes so the\r\n * routes panel and request log see them.\r\n *\r\n * @example\r\n * const ui = nodeui();\r\n * await app.register(ui);\r\n * await app.listen({ port: 3000, host: '127.0.0.1' });\r\n * ui.server.mark('listening');\r\n */\r\nexport function nodeui(options?: NodeUIOptions): NodeUIFastifyPlugin {\r\n const server = createNodeUI(options);\r\n const prefix = server.config.path;\r\n const isUnderPrefix = (p: string): boolean => p === prefix || p.startsWith(`${prefix}/`);\r\n const recorder = server.middleware();\r\n const routes = new Map<string, RouteEntry>();\r\n\r\n const plugin = ((app: FastifyInstance, _opts: unknown, done: (err?: Error) => void) => {\r\n if (!server.active) {\r\n done();\r\n return;\r\n }\r\n\r\n server.setRoutes(() =>\r\n [...routes.values()].sort(\r\n (a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method),\r\n ),\r\n );\r\n\r\n app.addHook('onRoute', (route: RouteOptions) => {\r\n const methods = Array.isArray(route.method) ? route.method : [route.method];\r\n const handler = (route.handler as { name?: string } | undefined)?.name || 'anonymous';\r\n for (const m of methods) {\r\n const method = String(m).toUpperCase();\r\n if (isUnderPrefix(route.url)) continue;\r\n routes.set(`${method} ${route.url}`, { method, path: route.url, handler });\r\n }\r\n });\r\n\r\n app.addHook('onRequest', async (req, reply) => {\r\n if (isUnderPrefix(pathnameOf(req.raw.url))) {\r\n reply.hijack();\r\n await server.handle(req.raw, reply.raw);\r\n return;\r\n }\r\n // Core's middleware records the request (finish listener) then calls next.\r\n recorder(req.raw, reply.raw, () => undefined);\r\n });\r\n\r\n app.addHook('onClose', (_instance, next) => {\r\n server.shutdown();\r\n next();\r\n });\r\n done();\r\n }) as NodeUIFastifyPlugin;\r\n\r\n // Same effect as fastify-plugin: expose hooks to the parent scope.\r\n const marks = plugin as unknown as Record<symbol, unknown>;\r\n marks[Symbol.for('skip-override')] = true;\r\n marks[Symbol.for('fastify.display-name')] = 'nodeui-fastify';\r\n plugin.server = server;\r\n plugin.addLogSource = server.addLogSource;\r\n return plugin;\r\n}\r\n\r\nexport * from '@singhak/nodeui-core';\r\n"],"mappings":";AACA;AAAA,EACE;AAAA,OAIK;
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { FastifyInstance, FastifyPluginCallback, RouteOptions } from 'fastify';\r\nimport {\r\n createNodeUI,\r\n enterRequestContext,\r\n type NodeUIOptions,\r\n type NodeUIServer,\r\n type RouteEntry,\r\n} from '@singhak/nodeui-core';\r\n\r\nexport interface NodeUIFastifyPlugin extends FastifyPluginCallback {\r\n /** Handle to the underlying server (mark, shutdown, config). */\r\n server: NodeUIServer;\r\n /** Pushes an external log entry into the log viewer (logger adapter). */\r\n addLogSource: NodeUIServer['addLogSource'];\r\n}\r\n\r\nfunction pathnameOf(url: string | undefined): string {\r\n try {\r\n return new URL(url ?? '/', 'http://localhost').pathname;\r\n } catch {\r\n return url ?? '/';\r\n }\r\n}\r\n\r\n/**\r\n * Creates the NodeUI Fastify plugin. Register it before your routes so the\r\n * routes panel and request log see them.\r\n *\r\n * @example\r\n * const ui = nodeui();\r\n * await app.register(ui);\r\n * await app.listen({ port: 3000, host: '127.0.0.1' });\r\n * ui.server.mark('listening');\r\n */\r\nexport function nodeui(options?: NodeUIOptions): NodeUIFastifyPlugin {\r\n const server = createNodeUI(options);\r\n const prefix = server.config.path;\r\n const isUnderPrefix = (p: string): boolean => p === prefix || p.startsWith(`${prefix}/`);\r\n const recorder = server.middleware();\r\n const routes = new Map<string, RouteEntry>();\r\n\r\n const plugin = ((app: FastifyInstance, _opts: unknown, done: (err?: Error) => void) => {\r\n if (!server.active) {\r\n done();\r\n return;\r\n }\r\n\r\n server.setRoutes(() =>\r\n [...routes.values()].sort(\r\n (a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method),\r\n ),\r\n );\r\n\r\n app.addHook('onRoute', (route: RouteOptions) => {\r\n const methods = Array.isArray(route.method) ? route.method : [route.method];\r\n const handler = (route.handler as { name?: string } | undefined)?.name || 'anonymous';\r\n for (const m of methods) {\r\n const method = String(m).toUpperCase();\r\n if (isUnderPrefix(route.url)) continue;\r\n routes.set(`${method} ${route.url}`, { method, path: route.url, handler });\r\n }\r\n });\r\n\r\n app.addHook('onRequest', async (req, reply) => {\r\n if (isUnderPrefix(pathnameOf(req.raw.url))) {\r\n reply.hijack();\r\n await server.handle(req.raw, reply.raw);\r\n return;\r\n }\r\n // Expose the matched route pattern to core's request recorder.\r\n const pattern =\r\n (req as { routeOptions?: { url?: string } }).routeOptions?.url ??\r\n (req as { routerPath?: string }).routerPath;\r\n if (pattern) (req.raw as { nodeuiRoute?: string }).nodeuiRoute = pattern;\r\n // Core's middleware records the request (finish listener) then calls next.\r\n recorder(req.raw, reply.raw, () => undefined);\r\n // Attribute outgoing calls and logs from the route handler to this request.\r\n enterRequestContext(req.raw);\r\n });\r\n\r\n app.addHook('onError', (req, _reply, error, hookDone) => {\r\n server.recordError(error, {\r\n route: (req as { routeOptions?: { url?: string } }).routeOptions?.url,\r\n });\r\n hookDone();\r\n });\r\n\r\n app.addHook('onClose', (_instance, next) => {\r\n server.shutdown();\r\n next();\r\n });\r\n done();\r\n }) as NodeUIFastifyPlugin;\r\n\r\n // Same effect as fastify-plugin: expose hooks to the parent scope.\r\n const marks = plugin as unknown as Record<symbol, unknown>;\r\n marks[Symbol.for('skip-override')] = true;\r\n marks[Symbol.for('fastify.display-name')] = 'nodeui-fastify';\r\n plugin.server = server;\r\n plugin.addLogSource = server.addLogSource;\r\n return plugin;\r\n}\r\n\r\nexport * from '@singhak/nodeui-core';\r\n"],"mappings":";AACA;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAgGP,cAAc;AAvFd,SAAS,WAAW,KAAiC;AACnD,MAAI;AACF,WAAO,IAAI,IAAI,OAAO,KAAK,kBAAkB,EAAE;AAAA,EACjD,QAAQ;AACN,WAAO,OAAO;AAAA,EAChB;AACF;AAYO,SAAS,OAAO,SAA8C;AACnE,QAAM,SAAS,aAAa,OAAO;AACnC,QAAM,SAAS,OAAO,OAAO;AAC7B,QAAM,gBAAgB,CAAC,MAAuB,MAAM,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG;AACvF,QAAM,WAAW,OAAO,WAAW;AACnC,QAAM,SAAS,oBAAI,IAAwB;AAE3C,QAAM,UAAU,CAAC,KAAsB,OAAgB,SAAgC;AACrF,QAAI,CAAC,OAAO,QAAQ;AAClB,WAAK;AACL;AAAA,IACF;AAEA,WAAO;AAAA,MAAU,MACf,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE;AAAA,QACnB,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,KAAK,EAAE,OAAO,cAAc,EAAE,MAAM;AAAA,MAC3E;AAAA,IACF;AAEA,QAAI,QAAQ,WAAW,CAAC,UAAwB;AAC9C,YAAM,UAAU,MAAM,QAAQ,MAAM,MAAM,IAAI,MAAM,SAAS,CAAC,MAAM,MAAM;AAC1E,YAAM,UAAW,MAAM,SAA2C,QAAQ;AAC1E,iBAAW,KAAK,SAAS;AACvB,cAAM,SAAS,OAAO,CAAC,EAAE,YAAY;AACrC,YAAI,cAAc,MAAM,GAAG,EAAG;AAC9B,eAAO,IAAI,GAAG,MAAM,IAAI,MAAM,GAAG,IAAI,EAAE,QAAQ,MAAM,MAAM,KAAK,QAAQ,CAAC;AAAA,MAC3E;AAAA,IACF,CAAC;AAED,QAAI,QAAQ,aAAa,OAAO,KAAK,UAAU;AAC7C,UAAI,cAAc,WAAW,IAAI,IAAI,GAAG,CAAC,GAAG;AAC1C,cAAM,OAAO;AACb,cAAM,OAAO,OAAO,IAAI,KAAK,MAAM,GAAG;AACtC;AAAA,MACF;AAEA,YAAM,UACH,IAA4C,cAAc,OAC1D,IAAgC;AACnC,UAAI,QAAS,CAAC,IAAI,IAAiC,cAAc;AAEjE,eAAS,IAAI,KAAK,MAAM,KAAK,MAAM,MAAS;AAE5C,0BAAoB,IAAI,GAAG;AAAA,IAC7B,CAAC;AAED,QAAI,QAAQ,WAAW,CAAC,KAAK,QAAQ,OAAO,aAAa;AACvD,aAAO,YAAY,OAAO;AAAA,QACxB,OAAQ,IAA4C,cAAc;AAAA,MACpE,CAAC;AACD,eAAS;AAAA,IACX,CAAC;AAED,QAAI,QAAQ,WAAW,CAAC,WAAW,SAAS;AAC1C,aAAO,SAAS;AAChB,WAAK;AAAA,IACP,CAAC;AACD,SAAK;AAAA,EACP;AAGA,QAAM,QAAQ;AACd,QAAM,uBAAO,IAAI,eAAe,CAAC,IAAI;AACrC,QAAM,uBAAO,IAAI,sBAAsB,CAAC,IAAI;AAC5C,SAAO,SAAS;AAChB,SAAO,eAAe,OAAO;AAC7B,SAAO;AACT;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@singhak/nodeui-fastify",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Fastify plugin adapter for the NodeUI developer console.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"test": "vitest run"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@singhak/nodeui-core": "^0.
|
|
50
|
+
"@singhak/nodeui-core": "^0.5.0"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"fastify": "^4.0.0 || ^5.0.0"
|