@lensjs/express 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var adapter_exports = {};
30
+ __export(adapter_exports, {
31
+ default: () => ExpressAdapter
32
+ });
33
+ module.exports = __toCommonJS(adapter_exports);
34
+ var import_core = require("@lensjs/core");
35
+ var path = __toESM(require("path"), 1);
36
+ var import_express2 = __toESM(require("express"), 1);
37
+ class ExpressAdapter extends import_core.LensAdapter {
38
+ app;
39
+ config;
40
+ constructor({ app }) {
41
+ super();
42
+ this.app = app;
43
+ }
44
+ setConfig(config) {
45
+ this.config = config;
46
+ return this;
47
+ }
48
+ setup() {
49
+ for (const watcher of this.getWatchers()) {
50
+ switch (watcher.name) {
51
+ case import_core.WatcherTypeEnum.REQUEST:
52
+ this.watchRequests(watcher);
53
+ break;
54
+ case import_core.WatcherTypeEnum.QUERY:
55
+ void this.watchQueries(watcher);
56
+ break;
57
+ }
58
+ }
59
+ }
60
+ registerRoutes(routes) {
61
+ routes.forEach((route) => {
62
+ this.app[route.method.toLowerCase()](
63
+ this.normalizePath(route.path),
64
+ async (req, res) => {
65
+ const result = await route.handler({
66
+ params: req.params,
67
+ qs: req.query
68
+ });
69
+ return res.json(result);
70
+ }
71
+ );
72
+ });
73
+ }
74
+ serveUI(uiPath, spaRoute, _dataToInject) {
75
+ this.app.use(this.normalizePath(spaRoute), import_express2.default.static(uiPath));
76
+ this.app.get(
77
+ this.normalizePath(`${spaRoute}/favicon.svg`),
78
+ (_, res) => res.sendFile(path.join(uiPath, "favicon.svg"))
79
+ );
80
+ this.app.get(new RegExp(`^/${spaRoute}(?!/api)(/.*)?$`), (req, res) => {
81
+ if (import_core.lensUtils.isStaticFile(req.path.split("/"))) {
82
+ return res.download(
83
+ path.join(uiPath, import_core.lensUtils.stripBeforeAssetsPath(req.path))
84
+ );
85
+ }
86
+ return res.sendFile(path.join(uiPath, "index.html"));
87
+ });
88
+ }
89
+ async watchQueries(watcher) {
90
+ if (!this.config.queryWatcher.enabled) return;
91
+ const handler = this.config.queryWatcher.handler;
92
+ await handler({
93
+ onQuery: async (query) => {
94
+ const queryPayload = {
95
+ query: query.query,
96
+ duration: query.duration || "0 ms",
97
+ createdAt: query.createdAt || import_core.lensUtils.sqlDateTime(),
98
+ type: query.type
99
+ };
100
+ await watcher?.log({
101
+ data: queryPayload
102
+ });
103
+ }
104
+ });
105
+ }
106
+ watchRequests(requestWatcher) {
107
+ if (!this.config.requestWatcherEnabled) return;
108
+ this.app.use((req, res, next) => {
109
+ if (this.shouldIgnorePath(req.path)) return next();
110
+ const start = process.hrtime();
111
+ this.patchResponseMethods(res);
112
+ res.on("finish", async () => {
113
+ await this.finalizeRequestLog(req, res, requestWatcher, start);
114
+ });
115
+ next();
116
+ });
117
+ }
118
+ patchResponseMethods(res) {
119
+ const originalJson = res.json.bind(res);
120
+ const originalSend = res.send.bind(res);
121
+ res._body = void 0;
122
+ res.json = function(body) {
123
+ res._body = body;
124
+ return originalJson(body);
125
+ };
126
+ res.send = function(body) {
127
+ res._body = body;
128
+ return originalSend(body);
129
+ };
130
+ }
131
+ async finalizeRequestLog(req, res, requestWatcher, start) {
132
+ try {
133
+ const duration = import_core.lensUtils.prettyHrTime(process.hrtime(start));
134
+ const logPayload = {
135
+ request: {
136
+ id: import_core.lensUtils.generateRandomUuid(),
137
+ method: req.method,
138
+ duration,
139
+ path: req.originalUrl,
140
+ headers: req.headers,
141
+ body: req.body ?? {},
142
+ status: res.statusCode,
143
+ ip: req.socket?.remoteAddress ?? "",
144
+ createdAt: import_core.lensUtils.nowISO()
145
+ },
146
+ response: {
147
+ json: res._body ?? null,
148
+ headers: res.getHeaders?.()
149
+ },
150
+ user: await this.config.isAuthenticated?.(req) ? await this.config.getUser?.(req) : null
151
+ };
152
+ await requestWatcher.log(logPayload);
153
+ } catch (err) {
154
+ console.error("Error finalizing request log:", err);
155
+ }
156
+ }
157
+ normalizePath(pathStr) {
158
+ return pathStr.startsWith("/") ? pathStr : `/${pathStr}`;
159
+ }
160
+ }
@@ -0,0 +1,23 @@
1
+ import { LensAdapter, RouteDefinition } from '@lensjs/core';
2
+ import { RequiredExpressAdapterConfig } from './types/index.cjs';
3
+ import { Express } from 'express';
4
+ import '@lensjs/watchers';
5
+
6
+ declare class ExpressAdapter extends LensAdapter {
7
+ protected app: Express;
8
+ protected config: RequiredExpressAdapterConfig;
9
+ constructor({ app }: {
10
+ app: Express;
11
+ });
12
+ setConfig(config: RequiredExpressAdapterConfig): this;
13
+ setup(): void;
14
+ registerRoutes(routes: RouteDefinition[]): void;
15
+ serveUI(uiPath: string, spaRoute: string, _dataToInject: Record<string, any>): void;
16
+ private watchQueries;
17
+ private watchRequests;
18
+ private patchResponseMethods;
19
+ private finalizeRequestLog;
20
+ private normalizePath;
21
+ }
22
+
23
+ export { ExpressAdapter as default };
@@ -0,0 +1,23 @@
1
+ import { LensAdapter, RouteDefinition } from '@lensjs/core';
2
+ import { RequiredExpressAdapterConfig } from './types/index.js';
3
+ import { Express } from 'express';
4
+ import '@lensjs/watchers';
5
+
6
+ declare class ExpressAdapter extends LensAdapter {
7
+ protected app: Express;
8
+ protected config: RequiredExpressAdapterConfig;
9
+ constructor({ app }: {
10
+ app: Express;
11
+ });
12
+ setConfig(config: RequiredExpressAdapterConfig): this;
13
+ setup(): void;
14
+ registerRoutes(routes: RouteDefinition[]): void;
15
+ serveUI(uiPath: string, spaRoute: string, _dataToInject: Record<string, any>): void;
16
+ private watchQueries;
17
+ private watchRequests;
18
+ private patchResponseMethods;
19
+ private finalizeRequestLog;
20
+ private normalizePath;
21
+ }
22
+
23
+ export { ExpressAdapter as default };
@@ -0,0 +1,134 @@
1
+ import {
2
+ LensAdapter,
3
+ lensUtils,
4
+ WatcherTypeEnum
5
+ } from "@lensjs/core";
6
+ import * as path from "path";
7
+ import express from "express";
8
+ class ExpressAdapter extends LensAdapter {
9
+ app;
10
+ config;
11
+ constructor({ app }) {
12
+ super();
13
+ this.app = app;
14
+ }
15
+ setConfig(config) {
16
+ this.config = config;
17
+ return this;
18
+ }
19
+ setup() {
20
+ for (const watcher of this.getWatchers()) {
21
+ switch (watcher.name) {
22
+ case WatcherTypeEnum.REQUEST:
23
+ this.watchRequests(watcher);
24
+ break;
25
+ case WatcherTypeEnum.QUERY:
26
+ void this.watchQueries(watcher);
27
+ break;
28
+ }
29
+ }
30
+ }
31
+ registerRoutes(routes) {
32
+ routes.forEach((route) => {
33
+ this.app[route.method.toLowerCase()](
34
+ this.normalizePath(route.path),
35
+ async (req, res) => {
36
+ const result = await route.handler({
37
+ params: req.params,
38
+ qs: req.query
39
+ });
40
+ return res.json(result);
41
+ }
42
+ );
43
+ });
44
+ }
45
+ serveUI(uiPath, spaRoute, _dataToInject) {
46
+ this.app.use(this.normalizePath(spaRoute), express.static(uiPath));
47
+ this.app.get(
48
+ this.normalizePath(`${spaRoute}/favicon.svg`),
49
+ (_, res) => res.sendFile(path.join(uiPath, "favicon.svg"))
50
+ );
51
+ this.app.get(new RegExp(`^/${spaRoute}(?!/api)(/.*)?$`), (req, res) => {
52
+ if (lensUtils.isStaticFile(req.path.split("/"))) {
53
+ return res.download(
54
+ path.join(uiPath, lensUtils.stripBeforeAssetsPath(req.path))
55
+ );
56
+ }
57
+ return res.sendFile(path.join(uiPath, "index.html"));
58
+ });
59
+ }
60
+ async watchQueries(watcher) {
61
+ if (!this.config.queryWatcher.enabled) return;
62
+ const handler = this.config.queryWatcher.handler;
63
+ await handler({
64
+ onQuery: async (query) => {
65
+ const queryPayload = {
66
+ query: query.query,
67
+ duration: query.duration || "0 ms",
68
+ createdAt: query.createdAt || lensUtils.sqlDateTime(),
69
+ type: query.type
70
+ };
71
+ await watcher?.log({
72
+ data: queryPayload
73
+ });
74
+ }
75
+ });
76
+ }
77
+ watchRequests(requestWatcher) {
78
+ if (!this.config.requestWatcherEnabled) return;
79
+ this.app.use((req, res, next) => {
80
+ if (this.shouldIgnorePath(req.path)) return next();
81
+ const start = process.hrtime();
82
+ this.patchResponseMethods(res);
83
+ res.on("finish", async () => {
84
+ await this.finalizeRequestLog(req, res, requestWatcher, start);
85
+ });
86
+ next();
87
+ });
88
+ }
89
+ patchResponseMethods(res) {
90
+ const originalJson = res.json.bind(res);
91
+ const originalSend = res.send.bind(res);
92
+ res._body = void 0;
93
+ res.json = function(body) {
94
+ res._body = body;
95
+ return originalJson(body);
96
+ };
97
+ res.send = function(body) {
98
+ res._body = body;
99
+ return originalSend(body);
100
+ };
101
+ }
102
+ async finalizeRequestLog(req, res, requestWatcher, start) {
103
+ try {
104
+ const duration = lensUtils.prettyHrTime(process.hrtime(start));
105
+ const logPayload = {
106
+ request: {
107
+ id: lensUtils.generateRandomUuid(),
108
+ method: req.method,
109
+ duration,
110
+ path: req.originalUrl,
111
+ headers: req.headers,
112
+ body: req.body ?? {},
113
+ status: res.statusCode,
114
+ ip: req.socket?.remoteAddress ?? "",
115
+ createdAt: lensUtils.nowISO()
116
+ },
117
+ response: {
118
+ json: res._body ?? null,
119
+ headers: res.getHeaders?.()
120
+ },
121
+ user: await this.config.isAuthenticated?.(req) ? await this.config.getUser?.(req) : null
122
+ };
123
+ await requestWatcher.log(logPayload);
124
+ } catch (err) {
125
+ console.error("Error finalizing request log:", err);
126
+ }
127
+ }
128
+ normalizePath(pathStr) {
129
+ return pathStr.startsWith("/") ? pathStr : `/${pathStr}`;
130
+ }
131
+ }
132
+ export {
133
+ ExpressAdapter as default
134
+ };
package/dist/index.cjs ADDED
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var index_exports = {};
30
+ __export(index_exports, {
31
+ lens: () => lens
32
+ });
33
+ module.exports = __toCommonJS(index_exports);
34
+ var import_core = require("@lensjs/core");
35
+ var import_adapter = __toESM(require("./adapter"), 1);
36
+ const defaultConfig = {
37
+ appName: "Lens",
38
+ enabled: true,
39
+ path: "/lens",
40
+ ignoredPaths: [],
41
+ onlyPaths: []
42
+ };
43
+ const lens = async (config) => {
44
+ const adapter = new import_adapter.default({ app: config.app });
45
+ const watchers = [new import_core.RequestWatcher()];
46
+ const mergedConfig = {
47
+ ...config,
48
+ ...defaultConfig
49
+ };
50
+ if (config.queryWatcher?.enabled) {
51
+ watchers.push(new import_core.QueryWatcher());
52
+ }
53
+ const { ignoredPaths, normalizedPath } = import_core.lensUtils.prepareIgnoredPaths(
54
+ mergedConfig.path,
55
+ mergedConfig.ignoredPaths
56
+ );
57
+ adapter.setConfig(mergedConfig).setIgnoredPaths(ignoredPaths).setOnlyPaths(mergedConfig.onlyPaths);
58
+ await import_core.Lens.setAdapter(adapter).setWatchers(watchers).start({
59
+ appName: mergedConfig.appName,
60
+ enabled: mergedConfig.enabled,
61
+ basePath: normalizedPath
62
+ });
63
+ };
64
+ // Annotate the CommonJS export names for ESM import in node:
65
+ 0 && (module.exports = {
66
+ lens
67
+ });
@@ -0,0 +1,8 @@
1
+ import { ExpressAdapterConfig } from './types/index.cjs';
2
+ import 'express';
3
+ import '@lensjs/watchers';
4
+ import '@lensjs/core';
5
+
6
+ declare const lens: (config: ExpressAdapterConfig) => Promise<void>;
7
+
8
+ export { lens };
@@ -0,0 +1,8 @@
1
+ import { ExpressAdapterConfig } from './types/index.js';
2
+ import 'express';
3
+ import '@lensjs/watchers';
4
+ import '@lensjs/core';
5
+
6
+ declare const lens: (config: ExpressAdapterConfig) => Promise<void>;
7
+
8
+ export { lens };
package/dist/index.js ADDED
@@ -0,0 +1,38 @@
1
+ import {
2
+ Lens,
3
+ lensUtils,
4
+ QueryWatcher,
5
+ RequestWatcher
6
+ } from "@lensjs/core";
7
+ import ExpressAdapter from "./adapter";
8
+ const defaultConfig = {
9
+ appName: "Lens",
10
+ enabled: true,
11
+ path: "/lens",
12
+ ignoredPaths: [],
13
+ onlyPaths: []
14
+ };
15
+ const lens = async (config) => {
16
+ const adapter = new ExpressAdapter({ app: config.app });
17
+ const watchers = [new RequestWatcher()];
18
+ const mergedConfig = {
19
+ ...config,
20
+ ...defaultConfig
21
+ };
22
+ if (config.queryWatcher?.enabled) {
23
+ watchers.push(new QueryWatcher());
24
+ }
25
+ const { ignoredPaths, normalizedPath } = lensUtils.prepareIgnoredPaths(
26
+ mergedConfig.path,
27
+ mergedConfig.ignoredPaths
28
+ );
29
+ adapter.setConfig(mergedConfig).setIgnoredPaths(ignoredPaths).setOnlyPaths(mergedConfig.onlyPaths);
30
+ await Lens.setAdapter(adapter).setWatchers(watchers).start({
31
+ appName: mergedConfig.appName,
32
+ enabled: mergedConfig.enabled,
33
+ basePath: normalizedPath
34
+ });
35
+ };
36
+ export {
37
+ lens
38
+ };
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+ var types_exports = {};
16
+ module.exports = __toCommonJS(types_exports);
@@ -0,0 +1,26 @@
1
+ import { Express, Request } from 'express';
2
+ import { QueryWatcherHandler } from '@lensjs/watchers';
3
+ import { UserEntry } from '@lensjs/core';
4
+
5
+ type ExpressAdapterConfig = {
6
+ app: Express;
7
+ appName?: string;
8
+ enabled?: boolean;
9
+ path?: string;
10
+ ignoredPaths?: RegExp[];
11
+ onlyPaths?: RegExp[];
12
+ requestWatcherEnabled?: boolean;
13
+ queryWatcher?: {
14
+ enabled: boolean;
15
+ handler: QueryWatcherHandler;
16
+ };
17
+ isAuthenticated?: (request: Request) => Promise<boolean>;
18
+ getUser?: (request: Request) => Promise<UserEntry>;
19
+ };
20
+ type RequiredExpressAdapterConfig = Required<ExpressAdapterConfig> & {
21
+ queryWatcher?: ExpressAdapterConfig["queryWatcher"];
22
+ isAuthenticated?: ExpressAdapterConfig["isAuthenticated"];
23
+ getUser?: ExpressAdapterConfig["getUser"];
24
+ };
25
+
26
+ export type { ExpressAdapterConfig, RequiredExpressAdapterConfig };
@@ -0,0 +1,26 @@
1
+ import { Express, Request } from 'express';
2
+ import { QueryWatcherHandler } from '@lensjs/watchers';
3
+ import { UserEntry } from '@lensjs/core';
4
+
5
+ type ExpressAdapterConfig = {
6
+ app: Express;
7
+ appName?: string;
8
+ enabled?: boolean;
9
+ path?: string;
10
+ ignoredPaths?: RegExp[];
11
+ onlyPaths?: RegExp[];
12
+ requestWatcherEnabled?: boolean;
13
+ queryWatcher?: {
14
+ enabled: boolean;
15
+ handler: QueryWatcherHandler;
16
+ };
17
+ isAuthenticated?: (request: Request) => Promise<boolean>;
18
+ getUser?: (request: Request) => Promise<UserEntry>;
19
+ };
20
+ type RequiredExpressAdapterConfig = Required<ExpressAdapterConfig> & {
21
+ queryWatcher?: ExpressAdapterConfig["queryWatcher"];
22
+ isAuthenticated?: ExpressAdapterConfig["isAuthenticated"];
23
+ getUser?: ExpressAdapterConfig["getUser"];
24
+ };
25
+
26
+ export type { ExpressAdapterConfig, RequiredExpressAdapterConfig };
File without changes
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@lensjs/express",
3
+ "version": "1.0.1",
4
+ "description": "Express adapter for Lens",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "type": "module",
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "require": "./dist/index.cjs",
14
+ "import": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup --clean"
22
+ },
23
+ "dependencies": {
24
+ "express": "^5.1.0",
25
+ "utf-8-validate": "^6.0.5"
26
+ },
27
+ "trustedDependencies": [
28
+ "utf-8-validate"
29
+ ],
30
+ "devDependencies": {
31
+ "@types/express": "^5.0.3"
32
+ },
33
+ "gitHead": "a229fde5700970ec290ff31f1e3b7d84cc56d325"
34
+ }