@uns-kit/api 2.0.4 → 2.0.6

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/dist/app.d.ts CHANGED
@@ -3,6 +3,11 @@
3
3
  */
4
4
  import { type Router } from "express";
5
5
  import * as http from "http";
6
+ type MountConfig = {
7
+ apiBasePrefix?: string;
8
+ swaggerBasePrefix?: string;
9
+ disableDefaultApiMount?: boolean;
10
+ };
6
11
  export default class App {
7
12
  private expressApplication;
8
13
  server: http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
@@ -10,6 +15,8 @@ export default class App {
10
15
  router: Router;
11
16
  private processName;
12
17
  private instanceName;
18
+ private apiBasePrefix;
19
+ private swaggerBasePrefix;
13
20
  swaggerSpec: {
14
21
  openapi: string;
15
22
  info: {
@@ -17,9 +24,12 @@ export default class App {
17
24
  version: string;
18
25
  };
19
26
  paths: Record<string, any>;
27
+ servers?: Array<{
28
+ url: string;
29
+ }>;
20
30
  };
21
31
  private swaggerDocs;
22
- constructor(port: number, processName: string, instanceName: string, appContext?: any);
32
+ constructor(port: number, processName: string, instanceName: string, appContext?: any, mountConfig?: MountConfig);
23
33
  static getExternalIPv4(): string | null;
24
34
  getSwaggerSpec(): {
25
35
  openapi: string;
@@ -28,7 +38,11 @@ export default class App {
28
38
  version: string;
29
39
  };
30
40
  paths: Record<string, any>;
41
+ servers?: Array<{
42
+ url: string;
43
+ }>;
31
44
  };
32
45
  registerSwaggerDoc(path: string, doc: Record<string, unknown>): void;
33
46
  start(): Promise<void>;
34
47
  }
48
+ export {};
package/dist/app.js CHANGED
@@ -8,6 +8,23 @@ import cookieParser from "cookie-parser";
8
8
  import { basePath } from "@uns-kit/core/base-path.js";
9
9
  import logger from "@uns-kit/core/logger.js";
10
10
  import os from 'os';
11
+ const normalizeBasePrefix = (value) => {
12
+ if (!value)
13
+ return "";
14
+ const trimmed = value.trim();
15
+ if (!trimmed)
16
+ return "";
17
+ const withLeading = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
18
+ return withLeading.replace(/\/+$/, "");
19
+ };
20
+ const buildSwaggerPath = (base, processName, instanceName) => {
21
+ const processSegment = `/${processName}`;
22
+ let baseWithProcess = base || "/";
23
+ if (!baseWithProcess.endsWith(processSegment)) {
24
+ baseWithProcess = `${baseWithProcess}${processSegment}`;
25
+ }
26
+ return `${baseWithProcess}/${instanceName}/swagger.json`.replace(/\/{2,}/g, "/");
27
+ };
11
28
  export default class App {
12
29
  expressApplication;
13
30
  server;
@@ -15,15 +32,22 @@ export default class App {
15
32
  router;
16
33
  processName;
17
34
  instanceName;
35
+ apiBasePrefix;
36
+ swaggerBasePrefix;
18
37
  swaggerSpec;
19
38
  swaggerDocs = new Map();
20
- constructor(port, processName, instanceName, appContext) {
39
+ constructor(port, processName, instanceName, appContext, mountConfig) {
21
40
  this.router = express.Router();
22
41
  this.port = port;
23
42
  this.expressApplication = express();
24
43
  this.server = http.createServer(this.expressApplication);
25
44
  this.processName = processName;
26
45
  this.instanceName = instanceName;
46
+ this.apiBasePrefix =
47
+ normalizeBasePrefix(mountConfig?.apiBasePrefix ?? process.env.UNS_API_BASE_PATH) || "/api";
48
+ this.swaggerBasePrefix =
49
+ normalizeBasePrefix(mountConfig?.swaggerBasePrefix ?? process.env.UNS_SWAGGER_BASE_PATH) ||
50
+ this.apiBasePrefix;
27
51
  // Add context
28
52
  this.expressApplication.use((req, _res, next) => {
29
53
  req.appContext = appContext;
@@ -44,7 +68,9 @@ export default class App {
44
68
  logger.info("Time: ", Date.now());
45
69
  next();
46
70
  });
47
- this.expressApplication.use("/api", this.router);
71
+ if (!mountConfig?.disableDefaultApiMount) {
72
+ this.expressApplication.use(this.apiBasePrefix, this.router);
73
+ }
48
74
  // Swagger specs
49
75
  this.swaggerSpec = {
50
76
  openapi: "3.0.0",
@@ -53,6 +79,7 @@ export default class App {
53
79
  version: "1.0.0",
54
80
  },
55
81
  paths: {},
82
+ servers: this.swaggerBasePrefix ? [{ url: this.swaggerBasePrefix }] : undefined,
56
83
  };
57
84
  }
58
85
  static getExternalIPv4() {
@@ -111,9 +138,10 @@ export default class App {
111
138
  ip = App.getExternalIPv4();
112
139
  port = "";
113
140
  }
114
- logger.info(`API listening on http://${ip}:${port}/api`);
115
- logger.info(`Swagger openAPI on http://${ip}:${port}/${this.processName}/${this.instanceName}/swagger.json`);
116
- this.expressApplication.get(`/${this.processName}/${this.instanceName}/swagger.json`, (req, res) => res.json(this.getSwaggerSpec()));
141
+ logger.info(`API listening on http://${ip}:${port}${this.apiBasePrefix}`);
142
+ const swaggerPath = buildSwaggerPath(this.swaggerBasePrefix, this.processName, this.instanceName);
143
+ logger.info(`Swagger openAPI on http://${ip}:${port}${swaggerPath}`);
144
+ this.expressApplication.get(swaggerPath, (req, res) => res.json(this.getSwaggerSpec()));
117
145
  });
118
146
  }
119
147
  }
@@ -11,6 +11,8 @@ export default class UnsApiProxy extends UnsProxy {
11
11
  protected processStatusTopic: string;
12
12
  private app;
13
13
  private options;
14
+ private apiBasePrefix;
15
+ private swaggerBasePrefix;
14
16
  private jwksCache?;
15
17
  private catchAllRouteRegistered;
16
18
  private startedAt;
@@ -13,6 +13,23 @@ import { DataSizeMeasurements, PhysicalMeasurements } from "@uns-kit/core/uns/un
13
13
  import App from "./app.js";
14
14
  const packageJsonPath = path.join(basePath, "package.json");
15
15
  const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
16
+ const normalizeBasePrefix = (value) => {
17
+ if (!value)
18
+ return "";
19
+ const trimmed = value.trim();
20
+ if (!trimmed)
21
+ return "";
22
+ const withLeading = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
23
+ return withLeading.replace(/\/+$/, "");
24
+ };
25
+ const buildSwaggerPath = (base, processName, instanceName) => {
26
+ const processSegment = `/${processName}`;
27
+ let baseWithProcess = base || "/";
28
+ if (!baseWithProcess.endsWith(processSegment)) {
29
+ baseWithProcess = `${baseWithProcess}${processSegment}`;
30
+ }
31
+ return `${baseWithProcess}/${instanceName}/swagger.json`.replace(/\/{2,}/g, "/");
32
+ };
16
33
  export default class UnsApiProxy extends UnsProxy {
17
34
  instanceName;
18
35
  topicBuilder;
@@ -20,6 +37,8 @@ export default class UnsApiProxy extends UnsProxy {
20
37
  processStatusTopic;
21
38
  app;
22
39
  options;
40
+ apiBasePrefix;
41
+ swaggerBasePrefix;
23
42
  jwksCache;
24
43
  catchAllRouteRegistered = false;
25
44
  startedAt;
@@ -28,7 +47,15 @@ export default class UnsApiProxy extends UnsProxy {
28
47
  constructor(processName, instanceName, options) {
29
48
  super();
30
49
  this.options = options;
31
- this.app = new App(0, processName, instanceName);
50
+ this.apiBasePrefix =
51
+ normalizeBasePrefix(options.apiBasePath ?? process.env.UNS_API_BASE_PATH) || "/api";
52
+ this.swaggerBasePrefix =
53
+ normalizeBasePrefix(options.swaggerBasePath ?? process.env.UNS_SWAGGER_BASE_PATH) || this.apiBasePrefix;
54
+ this.app = new App(0, processName, instanceName, undefined, {
55
+ apiBasePrefix: this.apiBasePrefix,
56
+ swaggerBasePrefix: this.swaggerBasePrefix,
57
+ disableDefaultApiMount: options.disableDefaultApiMount ?? false,
58
+ });
32
59
  this.app.start();
33
60
  this.startedAt = Date.now();
34
61
  this.instanceName = instanceName;
@@ -54,7 +81,7 @@ export default class UnsApiProxy extends UnsProxy {
54
81
  */
55
82
  async unregister(topic, asset, objectType, objectId, attribute, method) {
56
83
  const fullPath = `/${topic}${attribute}`;
57
- const apiPath = `/api${fullPath}`;
84
+ const apiPath = `${this.apiBasePrefix}${fullPath}`.replace(/\/{2,}/g, "/");
58
85
  const methodKey = method.toLowerCase(); // Express stores method keys in lowercase
59
86
  // Remove route from router
60
87
  if (this.app.router?.stack) {
@@ -88,6 +115,9 @@ export default class UnsApiProxy extends UnsProxy {
88
115
  await new Promise((resolve) => setTimeout(resolve, 100));
89
116
  }
90
117
  const time = UnsPacket.formatToISO8601(new Date());
118
+ const fullPath = `/${topic}${attribute}`;
119
+ const apiPath = `${this.apiBasePrefix}${fullPath}`.replace(/\/{2,}/g, "/");
120
+ const swaggerPath = buildSwaggerPath(this.swaggerBasePrefix, this.processName, this.instanceName);
91
121
  try {
92
122
  // Get ip and port from environment variables or defaults
93
123
  const addressInfo = this.app.server.address();
@@ -106,17 +136,16 @@ export default class UnsApiProxy extends UnsProxy {
106
136
  topic: topic,
107
137
  attribute: attribute,
108
138
  apiHost: `http://${ip}:${port}`,
109
- apiEndpoint: `/api/${topic}${attribute}`,
139
+ apiEndpoint: apiPath,
110
140
  apiMethod: "GET",
111
141
  apiQueryParams: options.queryParams,
112
142
  apiDescription: options?.apiDescription,
113
143
  attributeType: UnsAttributeType.Api,
114
- apiSwaggerEndpoint: `/${this.processName}/${this.instanceName}/swagger.json`,
144
+ apiSwaggerEndpoint: swaggerPath,
115
145
  asset,
116
146
  objectType,
117
147
  objectId
118
148
  });
119
- const fullPath = `/${topic}${attribute}`;
120
149
  const handler = (req, res) => {
121
150
  // Query param validation
122
151
  if (options?.queryParams) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uns-kit/api",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "Express-powered API gateway plugin for UnsProxyProcess with JWT/JWKS support.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -35,7 +35,7 @@
35
35
  "cookie-parser": "^1.4.7",
36
36
  "express": "^5.1.0",
37
37
  "multer": "^2.0.2",
38
- "@uns-kit/core": "2.0.4"
38
+ "@uns-kit/core": "2.0.6"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/jsonwebtoken": "^9.0.10",