@technomoron/api-server-base 2.0.0-beta.16 → 2.0.0-beta.17

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.txt CHANGED
@@ -102,6 +102,7 @@ apiBasePath (string, default '/api') Prefix applied to every module namespace.
102
102
  origins (string array, default empty array) CORS allowlist; empty allows all origins.
103
103
  uploadPath (string, default empty string) Enables multer.any() when provided.
104
104
  uploadMax (number, default 30 * 1024 * 1024) Maximum upload size in bytes.
105
+ staticDirs (record, default empty object) Map of mount path => disk path for serving static files as-is (ex: { '/assets': './public' }).
105
106
  accessSecret (string, default empty string) Required for JWT signing and verification.
106
107
  refreshSecret (string, default empty string) Used for refresh tokens if you implement them.
107
108
  cookieDomain (string, default '.somewhere-over-the-rainbow.com') Domain applied to auth cookies.
@@ -343,6 +343,7 @@ function fillConfig(config) {
343
343
  apiHost: config.apiHost ?? 'localhost',
344
344
  uploadPath: config.uploadPath ?? '',
345
345
  uploadMax: config.uploadMax ?? 30 * 1024 * 1024,
346
+ staticDirs: config.staticDirs,
346
347
  origins: config.origins ?? [],
347
348
  debug: config.debug ?? false,
348
349
  apiBasePath: config.apiBasePath ?? '/api',
@@ -399,6 +400,7 @@ class ApiServer {
399
400
  this.app.use(upload.any());
400
401
  }
401
402
  this.middlewares();
403
+ this.installStaticDirs();
402
404
  this.installPingHandler();
403
405
  this.installSwaggerHandler();
404
406
  // addSwaggerUi(this.app);
@@ -656,6 +658,21 @@ class ApiServer {
656
658
  };
657
659
  this.app.use((0, cors_1.default)(corsOptions));
658
660
  }
661
+ installStaticDirs() {
662
+ const staticDirs = this.config.staticDirs;
663
+ if (!staticDirs || !isPlainObject(staticDirs)) {
664
+ return;
665
+ }
666
+ for (const [mountRaw, dirRaw] of Object.entries(staticDirs)) {
667
+ const mount = typeof mountRaw === 'string' ? mountRaw.trim() : '';
668
+ const dir = typeof dirRaw === 'string' ? dirRaw.trim() : '';
669
+ if (!mount || !dir) {
670
+ continue;
671
+ }
672
+ const resolvedMount = mount.startsWith('/') ? mount : `/${mount}`;
673
+ this.app.use(resolvedMount, express_1.default.static(dir));
674
+ }
675
+ }
659
676
  installPingHandler() {
660
677
  const path = `${this.apiBasePath}/v1/ping`;
661
678
  this.app.get(path, (_req, res) => {
@@ -92,6 +92,7 @@ export interface ApiServerConf {
92
92
  apiHost: string;
93
93
  uploadPath: string;
94
94
  uploadMax: number;
95
+ staticDirs?: Record<string, string>;
95
96
  origins: string[];
96
97
  debug: boolean;
97
98
  apiBasePath: string;
@@ -193,6 +194,7 @@ export declare class ApiServer {
193
194
  guessExceptionText(error: unknown, defMsg?: string): string;
194
195
  protected authorize(apiReq: ApiRequest, requiredClass: ApiAuthClass): Promise<void>;
195
196
  private middlewares;
197
+ private installStaticDirs;
196
198
  private installPingHandler;
197
199
  private loadSwaggerSpec;
198
200
  private installSwaggerHandler;
@@ -92,6 +92,7 @@ export interface ApiServerConf {
92
92
  apiHost: string;
93
93
  uploadPath: string;
94
94
  uploadMax: number;
95
+ staticDirs?: Record<string, string>;
95
96
  origins: string[];
96
97
  debug: boolean;
97
98
  apiBasePath: string;
@@ -193,6 +194,7 @@ export declare class ApiServer {
193
194
  guessExceptionText(error: unknown, defMsg?: string): string;
194
195
  protected authorize(apiReq: ApiRequest, requiredClass: ApiAuthClass): Promise<void>;
195
196
  private middlewares;
197
+ private installStaticDirs;
196
198
  private installPingHandler;
197
199
  private loadSwaggerSpec;
198
200
  private installSwaggerHandler;
@@ -335,6 +335,7 @@ function fillConfig(config) {
335
335
  apiHost: config.apiHost ?? 'localhost',
336
336
  uploadPath: config.uploadPath ?? '',
337
337
  uploadMax: config.uploadMax ?? 30 * 1024 * 1024,
338
+ staticDirs: config.staticDirs,
338
339
  origins: config.origins ?? [],
339
340
  debug: config.debug ?? false,
340
341
  apiBasePath: config.apiBasePath ?? '/api',
@@ -391,6 +392,7 @@ export class ApiServer {
391
392
  this.app.use(upload.any());
392
393
  }
393
394
  this.middlewares();
395
+ this.installStaticDirs();
394
396
  this.installPingHandler();
395
397
  this.installSwaggerHandler();
396
398
  // addSwaggerUi(this.app);
@@ -648,6 +650,21 @@ export class ApiServer {
648
650
  };
649
651
  this.app.use(cors(corsOptions));
650
652
  }
653
+ installStaticDirs() {
654
+ const staticDirs = this.config.staticDirs;
655
+ if (!staticDirs || !isPlainObject(staticDirs)) {
656
+ return;
657
+ }
658
+ for (const [mountRaw, dirRaw] of Object.entries(staticDirs)) {
659
+ const mount = typeof mountRaw === 'string' ? mountRaw.trim() : '';
660
+ const dir = typeof dirRaw === 'string' ? dirRaw.trim() : '';
661
+ if (!mount || !dir) {
662
+ continue;
663
+ }
664
+ const resolvedMount = mount.startsWith('/') ? mount : `/${mount}`;
665
+ this.app.use(resolvedMount, express.static(dir));
666
+ }
667
+ }
651
668
  installPingHandler() {
652
669
  const path = `${this.apiBasePath}/v1/ping`;
653
670
  this.app.get(path, (_req, res) => {
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "API Server Base",
5
- "version": "2.0.0-beta.16",
5
+ "version": "2.0.0-beta.17",
6
6
  "description": "OpenAPI reference for ApiServer base endpoints and optional modules. Auth, passkey, and oauth modules are optional and require the corresponding module to be enabled in the ApiServer config. Base endpoints are always available."
7
7
  },
8
8
  "servers": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@technomoron/api-server-base",
3
- "version": "2.0.0-beta.16",
3
+ "version": "2.0.0-beta.17",
4
4
  "description": "Api Server Skeleton / Base Class",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.cjs",
@@ -84,15 +84,15 @@
84
84
  "@types/bcryptjs": "^2.4.6",
85
85
  "@types/express-serve-static-core": "^5.1.0",
86
86
  "@types/supertest": "^6.0.3",
87
- "@typescript-eslint/eslint-plugin": "^8.50.1",
88
- "@typescript-eslint/parser": "^8.50.1",
87
+ "@typescript-eslint/eslint-plugin": "^8.54.0",
88
+ "@typescript-eslint/parser": "^8.54.0",
89
89
  "eslint": "^9.39.2",
90
90
  "eslint-config-prettier": "^10.1.8",
91
91
  "eslint-plugin-import": "^2.32.0",
92
- "jsonc-eslint-parser": "^2.4.1",
92
+ "jsonc-eslint-parser": "^2.4.2",
93
93
  "mysql2": "^3.16.0",
94
94
  "pg": "^8.16.3",
95
- "prettier": "^3.7.4",
95
+ "prettier": "^3.8.1",
96
96
  "sequelize": "^6.37.7",
97
97
  "sqlite3": "^5.1.7",
98
98
  "supertest": "^7.1.4",
@@ -130,5 +130,5 @@
130
130
  "docs/swagger/openapi.json",
131
131
  "package.json"
132
132
  ],
133
- "packageManager": "pnpm@10.27.0+sha512.72d699da16b1179c14ba9e64dc71c9a40988cbdc65c264cb0e489db7de917f20dcf4d64d8723625f2969ba52d4b7e2a1170682d9ac2a5dcaeaab732b7e16f04a"
133
+ "packageManager": "pnpm@10.28.2"
134
134
  }