@expressots/adapter-express 4.0.0-preview.1 → 4.0.0-preview.3

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.
Files changed (36) hide show
  1. package/LICENSE.md +21 -21
  2. package/README.md +61 -61
  3. package/lib/CHANGELOG.md +10 -5
  4. package/lib/README.md +61 -61
  5. package/lib/cjs/adapter-express/application-express.js +401 -45
  6. package/lib/cjs/adapter-express/express-utils/decorators.js +44 -15
  7. package/lib/cjs/adapter-express/express-utils/inversify-express-server.js +20 -4
  8. package/lib/cjs/adapter-express/express-utils/path-pattern-compat.js +129 -0
  9. package/lib/cjs/adapter-express/express-utils/route-constraints.js +12 -3
  10. package/lib/cjs/adapter-express/micro-api/application-express-micro.js +5 -9
  11. package/lib/cjs/adapter-express/micro-api/micro.js +96 -41
  12. package/lib/cjs/adapter-express/studio/index.js +2 -1
  13. package/lib/cjs/adapter-express/studio/studio-integration.js +64 -11
  14. package/lib/cjs/types/adapter-express/application-express.d.ts +51 -9
  15. package/lib/cjs/types/adapter-express/express-utils/path-pattern-compat.d.ts +66 -0
  16. package/lib/cjs/types/adapter-express/express-utils/route-constraints.d.ts +12 -3
  17. package/lib/cjs/types/adapter-express/micro-api/micro.d.ts +19 -2
  18. package/lib/cjs/types/adapter-express/studio/index.d.ts +1 -1
  19. package/lib/cjs/types/adapter-express/studio/studio-integration.d.ts +78 -0
  20. package/lib/esm/adapter-express/application-express.js +402 -46
  21. package/lib/esm/adapter-express/express-utils/decorators.js +44 -15
  22. package/lib/esm/adapter-express/express-utils/inversify-express-server.js +20 -4
  23. package/lib/esm/adapter-express/express-utils/path-pattern-compat.js +125 -0
  24. package/lib/esm/adapter-express/express-utils/route-constraints.js +12 -3
  25. package/lib/esm/adapter-express/micro-api/application-express-micro.js +6 -10
  26. package/lib/esm/adapter-express/micro-api/micro.js +97 -42
  27. package/lib/esm/adapter-express/studio/index.js +1 -1
  28. package/lib/esm/adapter-express/studio/studio-integration.js +63 -11
  29. package/lib/esm/types/adapter-express/application-express.d.ts +51 -9
  30. package/lib/esm/types/adapter-express/express-utils/path-pattern-compat.d.ts +66 -0
  31. package/lib/esm/types/adapter-express/express-utils/route-constraints.d.ts +12 -3
  32. package/lib/esm/types/adapter-express/micro-api/micro.d.ts +19 -2
  33. package/lib/esm/types/adapter-express/studio/index.d.ts +1 -1
  34. package/lib/esm/types/adapter-express/studio/studio-integration.d.ts +78 -0
  35. package/lib/package.json +24 -10
  36. package/package.json +25 -11
@@ -5,24 +5,52 @@
5
5
  * when it's installed in the project. It enables request recording, tracing,
6
6
  * and real-time monitoring without requiring manual setup.
7
7
  */
8
+ import { Logger } from "@expressots/core";
9
+ // Lazy logger accessor so `new Logger()` only fires the first time we
10
+ // actually emit a Studio message. Routing through Logger means the
11
+ // framework's log-level configuration (e.g. `LOG_LEVEL=WARN`) silences
12
+ // the "listening" line as expected, instead of `console.log` always
13
+ // printing it. Lazy construction also keeps consumers that mock
14
+ // `@expressots/core` (test environments) from blowing up at module
15
+ // load when their Logger mock omits `.withContext`.
16
+ let _studioLogger = null;
17
+ function logger() {
18
+ if (!_studioLogger) {
19
+ _studioLogger = new Logger().withContext("studio");
20
+ }
21
+ return _studioLogger;
22
+ }
8
23
  let studioAgent = null;
9
24
  let studioEnabled = false;
10
25
  /**
11
- * Check if @expressots/studio-agent is installed
26
+ * Check if `@expressots/studio-agent` is installed and importable from the
27
+ * current process. Uses a dynamic `import()` rather than `require.resolve`
28
+ * because the latter is unavailable in pure-ESM consumers — adapter-express
29
+ * is published as a dual CJS/ESM build and this helper is exercised by both
30
+ * targets.
31
+ *
32
+ * The result is cached on first hit (success) so we avoid paying for the
33
+ * import twice. On failure we always retry, since the user may install the
34
+ * package mid-session in `expressots dev` workflows.
12
35
  */
36
+ let _studioAgentModule = null;
13
37
  async function isStudioAgentInstalled() {
14
38
  const debug = process.env.EXPRESSOTS_STUDIO_DEBUG === "true";
39
+ if (_studioAgentModule !== null)
40
+ return true;
15
41
  try {
16
- // Try to resolve the module first (works for both CJS and ESM)
17
- const resolved = require.resolve("@expressots/studio-agent");
42
+ // Dynamic import works for both CJS (returns module.exports) and ESM
43
+ // (returns the ESM namespace). If the package isn't installed, Node
44
+ // throws ERR_MODULE_NOT_FOUND / MODULE_NOT_FOUND, which we treat as
45
+ // "agent not present" — adapter-express continues without Studio.
46
+ _studioAgentModule = await import("@expressots/studio-agent");
18
47
  if (debug)
19
- console.log("[Studio] Resolved studio-agent at:", resolved);
48
+ console.log("[Studio] Loaded studio-agent successfully");
20
49
  return true;
21
50
  }
22
51
  catch (error) {
23
52
  if (debug)
24
- console.log("[Studio] Cannot resolve studio-agent:", error instanceof Error ? error.message : error);
25
- // Module not installed
53
+ console.log("[Studio] Cannot load studio-agent:", error instanceof Error ? error.message : error);
26
54
  return false;
27
55
  }
28
56
  }
@@ -78,9 +106,9 @@ export async function initializeStudio(app, config = {}, appContainer) {
78
106
  const studioAgentModuleAny = studioAgentModule;
79
107
  const StudioAgent = studioAgentModuleAny.StudioAgent || studioAgentModuleAny.default?.StudioAgent;
80
108
  if (!StudioAgent) {
81
- console.warn("⚠️ Studio Agent module found but StudioAgent class not exported");
109
+ logger().warn("Studio Agent module found but StudioAgent class not exported");
82
110
  if (debug)
83
- console.log("[Studio] Module contents:", studioAgentModule);
111
+ logger().debug(`Module contents: ${Object.keys(studioAgentModule).join(", ")}`);
84
112
  return false;
85
113
  }
86
114
  if (debug)
@@ -103,7 +131,7 @@ export async function initializeStudio(app, config = {}, appContainer) {
103
131
  // Start the agent (this also scans routes)
104
132
  await studioAgent.start();
105
133
  studioEnabled = true;
106
- console.log(`[ExpressoTS] Studio Agent listening on ws://localhost:${agentOptions.port}`);
134
+ logger().info(`Studio Agent listening on ws://localhost:${agentOptions.port}`);
107
135
  return true;
108
136
  }
109
137
  catch (error) {
@@ -131,12 +159,12 @@ export async function initializeStudio(app, config = {}, appContainer) {
131
159
  // Friendlier message for the most common failure mode: hot-reload
132
160
  // race left the port in TIME_WAIT.
133
161
  if (errorCode === "EADDRINUSE") {
134
- console.warn(`⚠️ Studio Agent could not bind its WebSocket port ` +
162
+ logger().warn(`Studio Agent could not bind its WebSocket port ` +
135
163
  `(${errorMessage}). The host app will continue without Studio. ` +
136
164
  `If this happened during hot-reload, the next restart should recover.`);
137
165
  return false;
138
166
  }
139
- console.warn("⚠️ Failed to initialize Studio Agent:", errorMessage);
167
+ logger().warn(`Failed to initialize Studio Agent: ${errorMessage}`);
140
168
  return false;
141
169
  }
142
170
  }
@@ -160,6 +188,30 @@ export function reportStudioRuntimeInfo(patch) {
160
188
  // Best-effort — never break the host on a status-page update.
161
189
  }
162
190
  }
191
+ /**
192
+ * Re-trigger the Studio Agent's route discovery. Used by the host
193
+ * after `app.listen()` so that the agent's runtime route scanner sees
194
+ * the fully-populated Express `_router` stack (controllers are bound
195
+ * by `InversifyExpressServer.build()` AFTER `initializeStudio()` runs,
196
+ * so the agent's first scan only catches static-source routes).
197
+ *
198
+ * No-ops when:
199
+ * - Studio isn't enabled, or
200
+ * - the installed agent is too old to expose `scanRoutes()`.
201
+ */
202
+ export async function rescanStudioRoutes() {
203
+ if (!studioAgent)
204
+ return;
205
+ if (typeof studioAgent.scanRoutes !== "function")
206
+ return;
207
+ try {
208
+ await studioAgent.scanRoutes();
209
+ }
210
+ catch (error) {
211
+ // Best-effort — never break the host on a Studio rescan.
212
+ logger().warn(`Studio route rescan failed: ${error instanceof Error ? error.message : String(error)}`);
213
+ }
214
+ }
163
215
  /**
164
216
  * Stop the Studio Agent
165
217
  */
@@ -1,5 +1,5 @@
1
1
  import { Server as HTTPServer } from "http";
2
- import { AppContainer, IConsoleMessage, IMiddleware, ProviderManager, BannerConfig } from "@expressots/core";
2
+ import { AppContainer, IConsoleMessage, IMiddleware, Logger, ProviderManager, BannerConfig } from "@expressots/core";
3
3
  import { IWebServerPublic, RenderEngine, Server } from "@expressots/shared";
4
4
  import { interfaces } from "@expressots/core";
5
5
  /**
@@ -14,7 +14,7 @@ import { interfaces } from "@expressots/core";
14
14
  * @method isDevelopment - Verifies if the current environment is development.
15
15
  */
16
16
  export declare class AppExpress implements Server.IWebServer {
17
- private logger;
17
+ protected logger: Logger;
18
18
  private console;
19
19
  private app;
20
20
  private serverInstance;
@@ -51,9 +51,7 @@ export declare class AppExpress implements Server.IWebServer {
51
51
  private static originalStderrWrite;
52
52
  private static logBuffer;
53
53
  private static isBuffering;
54
- private static bufferingInitialized;
55
54
  private static originalGlobalConsole;
56
- private static initBuffering;
57
55
  /**
58
56
  * Disable log buffering. Called by micro() to restore normal console output
59
57
  * since micro API doesn't use the banner system.
@@ -61,11 +59,17 @@ export declare class AppExpress implements Server.IWebServer {
61
59
  */
62
60
  static disableBuffering(): void;
63
61
  /**
64
- * Start buffering all console output.
65
- * This captures both console.log and direct process.stdout.write calls.
66
- * @private
62
+ * Start buffering all console output for the banner-first display flow.
63
+ * Captures both `console.*` and direct `process.stdout.write` / `process.stderr.write`
64
+ * calls so they can be flushed in the correct order after the banner displays.
65
+ *
66
+ * Idempotent: calling this multiple times is safe.
67
+ *
68
+ * @public API — called by `bootstrap()` so logs emitted during container
69
+ * setup are captured before the `AppExpress` instance exists. Also called
70
+ * automatically inside the constructor as a safety net.
67
71
  */
68
- private static startLogBuffering;
72
+ static startLogBuffering(): void;
69
73
  /**
70
74
  * Stop buffering but keep the buffered logs for later flushing.
71
75
  * This restores normal console/stdout output.
@@ -390,9 +394,47 @@ export declare class AppExpress implements Server.IWebServer {
390
394
  * harvested (keeps the WS payload small).
391
395
  */
392
396
  private collectStudioRuntimeItems;
397
+ /**
398
+ * Harvest controller- and route-scoped middleware bindings from
399
+ * Reflect metadata. Each entry describes a single edge the Studio
400
+ * architecture map should draw, e.g. "AuthMiddleware → UserController
401
+ * (route POST /users/:id)".
402
+ *
403
+ * The middleware values stored on `ControllerMetadata.middleware` are
404
+ * a polymorphic union (class, function, registered name, conditional
405
+ * config, …). We normalise each to a display name; entries we can't
406
+ * name (anonymous arrow functions, plain object configs without a
407
+ * `name` field) are omitted. The agent's static scan picks up the
408
+ * remaining named cases via decorator parsing — between the two
409
+ * sources Studio sees a complete graph for the common patterns.
410
+ */
411
+ private collectMiddlewareBindings;
412
+ /**
413
+ * Combine a controller's base path with a route path, normalising
414
+ * leading/trailing slashes. Mirrors the simpler logic Studio uses to
415
+ * build `RouteInfo.path` so the bindings line up with route entries.
416
+ */
417
+ private joinRoutePath;
418
+ /**
419
+ * Collect the ordered middleware pipeline from the Middleware service
420
+ * for forwarding to Studio. Uses feature-detection so older core
421
+ * versions that lack `getPipelineInfo()` won't break.
422
+ */
423
+ private collectMiddlewarePipelineItems;
424
+ /**
425
+ * Build the middleware preset info snapshot for Studio. Reads the
426
+ * last applied preset from the Middleware service and transforms it
427
+ * into the shape Studio expects.
428
+ */
429
+ private collectMiddlewarePresetInfo;
393
430
  /**
394
431
  * Display middleware startup logs after the banner.
395
- * This makes startup logging transparent to the user - no need for manual code in postServerInitialization().
432
+ *
433
+ * Warnings (e.g. missing optional packages like `helmet`) are always surfaced
434
+ * so the developer can act on them. Informational entries (e.g. "Security
435
+ * configured", "Applied preset: api") are demoted to `debug` since the
436
+ * dashboard already shows the active middleware count; set `LOG_LEVEL=DEBUG`
437
+ * to see the full breakdown.
396
438
  * @private
397
439
  */
398
440
  private displayMiddlewareStartupLogs;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Express 5 / path-to-regexp v8 compatibility for the `:name(regex)`
3
+ * inline-constraint syntax.
4
+ *
5
+ * `path-to-regexp` v8 (the parser Express 5 ships with) removed the
6
+ * inline regex form entirely — `/users/:id(\\d+)` now throws
7
+ *
8
+ * Unexpected ( at index 10: /users/:id(\\d+)
9
+ *
10
+ * That breaks two things we ship as public API:
11
+ *
12
+ * 1. The {@link Patterns} / {@link pattern} helpers in
13
+ * `route-constraints.ts`, which were introduced specifically to
14
+ * encourage that pattern.
15
+ * 2. Hand-written controller routes upgraded from v3, where users
16
+ * relied on Express 4 inline regex.
17
+ *
18
+ * Rather than break those at the surface of preview-3, we keep the
19
+ * authoring-time syntax and translate it at decorator time:
20
+ *
21
+ * - {@link splitPathConstraints} parses the path into a
22
+ * plain-`:name`-only form plus a list of `(name, regex)` pairs.
23
+ * - {@link createPathConstraintMiddleware} returns a middleware that
24
+ * runs at request time and 404s when any captured `req.params[name]`
25
+ * fails to match its constraint.
26
+ *
27
+ * The middleware emits an HTTP 404 (not 400) so the behaviour matches
28
+ * Express 4's "no route matched" semantics — under v6 of path-to-regexp,
29
+ * a non-matching `:id(\\d+)` simply meant the route wasn't selected and
30
+ * the request fell through to the framework's NotFound handler.
31
+ */
32
+ import type { RequestHandler } from "express";
33
+ export interface PathConstraint {
34
+ /** The `:name` placeholder, without the leading colon. */
35
+ paramName: string;
36
+ /** Compiled regex. Anchored with `^...$` to match the whole segment. */
37
+ regex: RegExp;
38
+ /** The original raw regex text, for diagnostics. */
39
+ rawPattern: string;
40
+ }
41
+ export interface SplitPath {
42
+ /** Path string ready to hand to Express 5 / path-to-regexp v8. */
43
+ path: string;
44
+ /** Param-level regex constraints, in path declaration order. */
45
+ constraints: Array<PathConstraint>;
46
+ }
47
+ /**
48
+ * Split `:name(regex)` segments out of an Express-style route path.
49
+ *
50
+ * The walker honours balanced parens inside the regex (e.g.
51
+ * `(\\d{4})` or `((a|b)+)`), which is more forgiving than a naive
52
+ * single-pass regex match would be. Returns the original path and an
53
+ * empty constraints list when no inline patterns are found, so this is
54
+ * a no-op for the common case.
55
+ */
56
+ export declare function splitPathConstraints(path: string): SplitPath;
57
+ /**
58
+ * Build a middleware that enforces the given param-level regex
59
+ * constraints on `req.params`. Returns `null` when the list is empty
60
+ * (so callers can avoid wiring an unnecessary middleware).
61
+ *
62
+ * When a constraint fails, the middleware delegates to `next()` without
63
+ * a value; the framework's NotFound handler then converts that into a
64
+ * 404 — same observable behaviour as Express 4's "no route matched".
65
+ */
66
+ export declare function createPathConstraintMiddleware(constraints: Array<PathConstraint>): RequestHandler | null;
@@ -1,6 +1,15 @@
1
1
  /**
2
2
  * Route parameter patterns for common use cases.
3
- * These are Express regex patterns that can be used in route paths.
3
+ *
4
+ * Express 5 / path-to-regexp v8 dropped the inline-regex form
5
+ * (`:id(\\d+)`), so the framework no longer hands these patterns to
6
+ * the underlying matcher verbatim. Instead, the HTTP-method decorators
7
+ * (`@Get`, `@Post`, …) parse the constraint out of the path at decorator
8
+ * time, register the route under a plain `:id` placeholder, and inject
9
+ * a small validator middleware that 404s when the captured value
10
+ * doesn't match. The user-facing semantics are unchanged: a path that
11
+ * uses `Patterns.NUMERIC_ID` still rejects `/users/abc` and only
12
+ * dispatches the handler for matches like `/users/123`.
4
13
  *
5
14
  * @example
6
15
  * ```typescript
@@ -8,12 +17,12 @@
8
17
  *
9
18
  * @Get(`/users/${pattern("id", Patterns.NUMERIC_ID)}`)
10
19
  * getUserById(@param("id") id: number) {
11
- * // Only matches numeric IDs like /users/123
20
+ * // Only dispatches for numeric IDs like /users/123
12
21
  * }
13
22
  *
14
23
  * @Get(`/documents/${pattern("uuid", Patterns.UUID)}`)
15
24
  * getDocument(@param("uuid") uuid: string) {
16
- * // Only matches valid UUIDs
25
+ * // Only dispatches for valid UUIDs
17
26
  * }
18
27
  * ```
19
28
  *
@@ -12,6 +12,19 @@ export interface MicroConfig {
12
12
  globalPrefix?: string;
13
13
  /** Show startup banner (default: true) */
14
14
  showBanner?: boolean;
15
+ /** Application environment. Auto-detected from NODE_ENV if not provided. */
16
+ environment?: string;
17
+ /** Studio Agent configuration. Auto-enabled in development when the package is installed. */
18
+ studio?: {
19
+ /** Explicitly enable/disable Studio (default: auto-detect in development) */
20
+ enabled?: boolean;
21
+ /** WebSocket port for the Studio Agent (default: 3334) */
22
+ port?: number;
23
+ /** Path to the SQLite database (default: ".studio/studio.db") */
24
+ dbPath?: string;
25
+ /** Service name shown in Studio (default: "expressots-micro") */
26
+ serviceName?: string;
27
+ };
15
28
  }
16
29
  /**
17
30
  * Route handler that can return a value or use res directly
@@ -43,10 +56,14 @@ export interface MicroApp {
43
56
  setErrorHandler(handler: express.ErrorRequestHandler): this;
44
57
  /** Start listening for requests */
45
58
  listen(port: number | string, appInfo?: IConsoleMessage): Promise<void>;
46
- /** Get the underlying HTTP server (available after listen) */
47
- getHttpServer(): Server;
59
+ /** Get the underlying HTTP server (null before listen resolves) */
60
+ getHttpServer(): Server | null;
48
61
  /** Get the Express app instance (for advanced use) */
49
62
  getApp(): express.Application;
63
+ /** Configure Studio integration (call before listen) */
64
+ setStudio(config: NonNullable<MicroConfig["studio"]>): this;
65
+ /** Check if Studio Agent is currently enabled */
66
+ isStudioEnabled(): boolean;
50
67
  }
51
68
  /**
52
69
  * Create a new micro API instance
@@ -1 +1 @@
1
- export { initializeStudio, stopStudio, isStudioEnabled, getStudioAgent, reportStudioRuntimeInfo, } from "./studio-integration.js";
1
+ export { initializeStudio, stopStudio, isStudioEnabled, getStudioAgent, reportStudioRuntimeInfo, rescanStudioRoutes, } from "./studio-integration.js";
@@ -23,6 +23,7 @@ interface StudioAgentInstance {
23
23
  providerCount?: number;
24
24
  middlewareCount?: number;
25
25
  runtimeItems?: StudioRuntimeItems;
26
+ middlewarePreset?: StudioMiddlewarePresetInfo;
26
27
  }): void;
27
28
  }
28
29
  /**
@@ -45,6 +46,70 @@ export interface StudioRuntimeItems {
45
46
  priority?: number;
46
47
  source?: string;
47
48
  }>;
49
+ middleware?: Array<{
50
+ name: string;
51
+ category: string;
52
+ type: "built-in" | "custom";
53
+ order: number;
54
+ path?: string;
55
+ }>;
56
+ /**
57
+ * Controller- and route-scoped middleware bindings, harvested from
58
+ * `ControllerMetadata.middleware` Reflect entries after
59
+ * `app.listen()`. Used by the agent to draw scope-aware
60
+ * "middleware → controller / route" edges on the architecture map.
61
+ *
62
+ * Mirrors `MiddlewareBinding` in `@expressots/studio-agent`.
63
+ */
64
+ middlewareBindings?: Array<{
65
+ middlewareName: string;
66
+ scope: "controller" | "route";
67
+ controllerName: string;
68
+ controllerMethod?: string;
69
+ httpMethod?: string;
70
+ routePath?: string;
71
+ }>;
72
+ }
73
+ /**
74
+ * Middleware preset info forwarded to the Studio Agent. Mirrors
75
+ * `MiddlewarePresetInfo` in `@expressots/studio-agent` so the adapter
76
+ * doesn't need to import from the studio package.
77
+ */
78
+ export interface StudioMiddlewarePresetInfo {
79
+ name: string;
80
+ hasOverrides: boolean;
81
+ parse?: {
82
+ json?: {
83
+ limit?: string;
84
+ };
85
+ urlencoded?: {
86
+ limit?: string;
87
+ extended?: boolean;
88
+ };
89
+ cookies?: boolean;
90
+ };
91
+ security?: {
92
+ tier?: string;
93
+ helmet?: boolean;
94
+ cors?: {
95
+ origin?: boolean | string;
96
+ credentials?: boolean;
97
+ methods?: Array<string>;
98
+ allowedHeaders?: Array<string>;
99
+ };
100
+ rateLimit?: {
101
+ windowMs?: number;
102
+ max?: number;
103
+ } | false;
104
+ };
105
+ compress?: {
106
+ enabled: boolean;
107
+ level?: number;
108
+ };
109
+ logger?: {
110
+ enabled: boolean;
111
+ implementation?: string;
112
+ };
48
113
  }
49
114
  interface StudioIntegrationConfig {
50
115
  enabled?: boolean;
@@ -76,7 +141,20 @@ export declare function reportStudioRuntimeInfo(patch: {
76
141
  providerCount?: number;
77
142
  middlewareCount?: number;
78
143
  runtimeItems?: StudioRuntimeItems;
144
+ middlewarePreset?: StudioMiddlewarePresetInfo;
79
145
  }): void;
146
+ /**
147
+ * Re-trigger the Studio Agent's route discovery. Used by the host
148
+ * after `app.listen()` so that the agent's runtime route scanner sees
149
+ * the fully-populated Express `_router` stack (controllers are bound
150
+ * by `InversifyExpressServer.build()` AFTER `initializeStudio()` runs,
151
+ * so the agent's first scan only catches static-source routes).
152
+ *
153
+ * No-ops when:
154
+ * - Studio isn't enabled, or
155
+ * - the installed agent is too old to expose `scanRoutes()`.
156
+ */
157
+ export declare function rescanStudioRoutes(): Promise<void>;
80
158
  /**
81
159
  * Stop the Studio Agent
82
160
  */
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expressots/adapter-express",
3
- "version": "4.0.0-preview.1",
3
+ "version": "4.0.0-preview.3",
4
4
  "description": "Expressots - modern, fast, lightweight nodejs web framework (@adapter-express)",
5
5
  "author": "",
6
6
  "main": "./lib/cjs/index.js",
@@ -36,6 +36,9 @@
36
36
  "publishConfig": {
37
37
  "access": "public"
38
38
  },
39
+ "engines": {
40
+ "node": ">=20.18.0"
41
+ },
39
42
  "keywords": [
40
43
  "expressots",
41
44
  "nodejs",
@@ -54,16 +57,21 @@
54
57
  "build:cjs": "tsc -p tsconfig.cjs.json",
55
58
  "build:esm": "node scripts/build-esm.js",
56
59
  "release": "release-it",
60
+ "release:prepare": "node scripts/release/prepare-publish.mjs",
61
+ "release:restore": "node scripts/release/restore-package-json.mjs",
62
+ "release:publish": "npm run build && npm run release:prepare && npm publish --tag next --access public && npm run release:restore",
57
63
  "prepublish": "npm run build && npm pack",
58
64
  "test": "jest",
59
65
  "test:watch": "jest --watch",
60
66
  "coverage": "jest --coverage",
61
67
  "format": "prettier --write \"src/**/*.ts\" --cache",
62
- "lint": "eslint \"src/**/*.ts\"",
63
- "lint:fix": "eslint \"src/**/*.ts\" --fix"
68
+ "lint": "eslint \"src/**/*.ts\" --cache --cache-location node_modules/.cache/eslint/",
69
+ "lint:fix": "eslint \"src/**/*.ts\" --fix --cache --cache-location node_modules/.cache/eslint/"
64
70
  },
65
71
  "dependencies": {
66
- "express": "4.22.2",
72
+ "@expressots/core": "file:../expressots/expressots-core-4.0.0-preview.3.tgz",
73
+ "@expressots/shared": "file:../shared/expressots-shared-4.0.0-preview.3.tgz",
74
+ "express": "^5.1.0",
67
75
  "reflect-metadata": "0.2.2"
68
76
  },
69
77
  "peerDependencies": {
@@ -75,14 +83,12 @@
75
83
  }
76
84
  },
77
85
  "devDependencies": {
78
- "@codecov/vite-plugin": "0.0.1-beta.6",
86
+ "@codecov/vite-plugin": "^2.0.1",
79
87
  "@commitlint/cli": "19.2.1",
80
88
  "@commitlint/config-conventional": "19.2.2",
81
- "@expressots/core": "file:../expressots/expressots-core-4.0.0-preview.1.tgz",
82
- "@expressots/shared": "file:../shared/expressots-shared-4.0.0-preview.1.tgz",
83
89
  "@expressots/studio-agent": "file:../expressots-studio/packages/studio-agent",
84
- "@release-it/conventional-changelog": "8.0.1",
85
- "@types/express": "4.17.21",
90
+ "@release-it/conventional-changelog": "^11.0.0",
91
+ "@types/express": "^5.0.0",
86
92
  "@types/jest": "29.5.14",
87
93
  "@types/node": "20.14.10",
88
94
  "@typescript-eslint/eslint-plugin": "7.16.1",
@@ -91,11 +97,19 @@
91
97
  "eslint-config-prettier": "9.1.0",
92
98
  "husky": "9.1.1",
93
99
  "jest": "29.7.0",
100
+ "lint-staged": "^15.2.10",
94
101
  "prettier": "3.3.3",
95
- "release-it": "17.6.0",
102
+ "release-it": "^20.0.1",
96
103
  "ts-jest": "29.2.5",
104
+ "ts-node": "^10.9.2",
97
105
  "typescript": "5.5.3"
98
106
  },
107
+ "lint-staged": {
108
+ "src/**/*.ts": [
109
+ "eslint --cache --cache-location node_modules/.cache/eslint/ --fix",
110
+ "prettier --write --cache"
111
+ ]
112
+ },
99
113
  "release-it": {
100
114
  "git": {
101
115
  "commitMessage": "chore(release): ${version}"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expressots/adapter-express",
3
- "version": "4.0.0-preview.1",
3
+ "version": "4.0.0-preview.3",
4
4
  "description": "Expressots - modern, fast, lightweight nodejs web framework (@adapter-express)",
5
5
  "author": "",
6
6
  "main": "./lib/cjs/index.js",
@@ -36,6 +36,9 @@
36
36
  "publishConfig": {
37
37
  "access": "public"
38
38
  },
39
+ "engines": {
40
+ "node": ">=20.18.0"
41
+ },
39
42
  "keywords": [
40
43
  "expressots",
41
44
  "nodejs",
@@ -54,16 +57,21 @@
54
57
  "build:cjs": "tsc -p tsconfig.cjs.json",
55
58
  "build:esm": "node scripts/build-esm.js",
56
59
  "release": "release-it",
60
+ "release:prepare": "node scripts/release/prepare-publish.mjs",
61
+ "release:restore": "node scripts/release/restore-package-json.mjs",
62
+ "release:publish": "npm run build && npm run release:prepare && npm publish --tag next --access public && npm run release:restore",
57
63
  "prepublish": "npm run build && npm pack",
58
64
  "test": "jest",
59
65
  "test:watch": "jest --watch",
60
66
  "coverage": "jest --coverage",
61
67
  "format": "prettier --write \"src/**/*.ts\" --cache",
62
- "lint": "eslint \"src/**/*.ts\"",
63
- "lint:fix": "eslint \"src/**/*.ts\" --fix"
68
+ "lint": "eslint \"src/**/*.ts\" --cache --cache-location node_modules/.cache/eslint/",
69
+ "lint:fix": "eslint \"src/**/*.ts\" --fix --cache --cache-location node_modules/.cache/eslint/"
64
70
  },
65
71
  "dependencies": {
66
- "express": "4.22.2",
72
+ "@expressots/core": "^4.0.0-preview.3",
73
+ "@expressots/shared": "^4.0.0-preview.3",
74
+ "express": "^5.1.0",
67
75
  "reflect-metadata": "0.2.2"
68
76
  },
69
77
  "peerDependencies": {
@@ -75,14 +83,12 @@
75
83
  }
76
84
  },
77
85
  "devDependencies": {
78
- "@codecov/vite-plugin": "0.0.1-beta.6",
86
+ "@codecov/vite-plugin": "^2.0.1",
79
87
  "@commitlint/cli": "19.2.1",
80
88
  "@commitlint/config-conventional": "19.2.2",
81
- "@expressots/core": "file:../expressots/expressots-core-4.0.0-preview.1.tgz",
82
- "@expressots/shared": "file:../shared/expressots-shared-4.0.0-preview.1.tgz",
83
- "@expressots/studio-agent": "file:../expressots-studio/packages/studio-agent",
84
- "@release-it/conventional-changelog": "8.0.1",
85
- "@types/express": "4.17.21",
89
+ "@expressots/studio-agent": "^4.0.0-preview.3",
90
+ "@release-it/conventional-changelog": "^11.0.0",
91
+ "@types/express": "^5.0.0",
86
92
  "@types/jest": "29.5.14",
87
93
  "@types/node": "20.14.10",
88
94
  "@typescript-eslint/eslint-plugin": "7.16.1",
@@ -91,11 +97,19 @@
91
97
  "eslint-config-prettier": "9.1.0",
92
98
  "husky": "9.1.1",
93
99
  "jest": "29.7.0",
100
+ "lint-staged": "^15.2.10",
94
101
  "prettier": "3.3.3",
95
- "release-it": "17.6.0",
102
+ "release-it": "^20.0.1",
96
103
  "ts-jest": "29.2.5",
104
+ "ts-node": "^10.9.2",
97
105
  "typescript": "5.5.3"
98
106
  },
107
+ "lint-staged": {
108
+ "src/**/*.ts": [
109
+ "eslint --cache --cache-location node_modules/.cache/eslint/ --fix",
110
+ "prettier --write --cache"
111
+ ]
112
+ },
99
113
  "release-it": {
100
114
  "git": {
101
115
  "commitMessage": "chore(release): ${version}"