@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.
|
|
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.
|
|
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.
|
|
88
|
-
"@typescript-eslint/parser": "^8.
|
|
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.
|
|
92
|
+
"jsonc-eslint-parser": "^2.4.2",
|
|
93
93
|
"mysql2": "^3.16.0",
|
|
94
94
|
"pg": "^8.16.3",
|
|
95
|
-
"prettier": "^3.
|
|
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.
|
|
133
|
+
"packageManager": "pnpm@10.28.2"
|
|
134
134
|
}
|