@intuitionrobotics/thunderstorm 2.1.1 → 2.2.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.
- package/dist/app-backend/core/Storm.d.ts +6 -2
- package/dist/app-backend/core/Storm.d.ts.map +1 -1
- package/dist/app-backend/core/Storm.js +8 -6
- package/dist/app-backend/core/Storm.js.map +1 -1
- package/dist/app-backend/modules/server/ApiFunction.d.ts +2 -6
- package/dist/app-backend/modules/server/ApiFunction.d.ts.map +1 -1
- package/dist/app-backend/modules/server/ApiFunction.js +11 -10
- package/dist/app-backend/modules/server/ApiFunction.js.map +1 -1
- package/dist/app-backend/modules/server/HttpServer.d.ts +0 -5
- package/dist/app-backend/modules/server/HttpServer.d.ts.map +1 -1
- package/dist/app-backend/modules/server/HttpServer.js +3 -3
- package/dist/app-backend/modules/server/HttpServer.js.map +1 -1
- package/dist/app-backend/modules/server/api-error.d.ts +21 -0
- package/dist/app-backend/modules/server/api-error.d.ts.map +1 -0
- package/dist/app-backend/modules/server/api-error.js +77 -0
- package/dist/app-backend/modules/server/api-error.js.map +1 -0
- package/dist/app-backend/modules/server/app-middleware.d.ts +13 -0
- package/dist/app-backend/modules/server/app-middleware.d.ts.map +1 -0
- package/dist/app-backend/modules/server/app-middleware.js +53 -0
- package/dist/app-backend/modules/server/app-middleware.js.map +1 -0
- package/dist/app-backend/modules/server/express-augmentation.d.ts +28 -0
- package/dist/app-backend/modules/server/express-augmentation.d.ts.map +1 -0
- package/dist/app-backend/modules/server/express-augmentation.js +2 -0
- package/dist/app-backend/modules/server/express-augmentation.js.map +1 -0
- package/dist/app-backend/modules/server/handler.d.ts +29 -0
- package/dist/app-backend/modules/server/handler.d.ts.map +1 -0
- package/dist/app-backend/modules/server/handler.js +49 -0
- package/dist/app-backend/modules/server/handler.js.map +1 -0
- package/dist/app-backend/modules/server/requireAuth.d.ts +24 -0
- package/dist/app-backend/modules/server/requireAuth.d.ts.map +1 -0
- package/dist/app-backend/modules/server/requireAuth.js +23 -0
- package/dist/app-backend/modules/server/requireAuth.js.map +1 -0
- package/dist/app-backend/modules/server/server-api.d.ts.map +1 -1
- package/dist/app-backend/modules/server/server-api.js +8 -55
- package/dist/app-backend/modules/server/server-api.js.map +1 -1
- package/dist/app-backend/modules/server/validators.d.ts +17 -0
- package/dist/app-backend/modules/server/validators.d.ts.map +1 -0
- package/dist/app-backend/modules/server/validators.js +37 -0
- package/dist/app-backend/modules/server/validators.js.map +1 -0
- package/dist/backend.d.ts +6 -0
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js +12 -0
- package/dist/backend.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -5,7 +5,6 @@ import { BaseStorm } from "./BaseStorm.js";
|
|
|
5
5
|
import { type Express, type Router } from "express";
|
|
6
6
|
export declare class Storm extends BaseStorm {
|
|
7
7
|
private routes?;
|
|
8
|
-
private initialPath;
|
|
9
8
|
private functions;
|
|
10
9
|
private express?;
|
|
11
10
|
private logClient;
|
|
@@ -25,7 +24,12 @@ export declare class Storm extends BaseStorm {
|
|
|
25
24
|
init(): this;
|
|
26
25
|
private assertNoLegacyModuleInit;
|
|
27
26
|
setRoutes(routes: Router): this;
|
|
28
|
-
|
|
27
|
+
/**
|
|
28
|
+
* @deprecated No-op. The URL prefix comes from the function name on Cloud
|
|
29
|
+
* Functions (the `api` function serves `…/api/**`), so the router always
|
|
30
|
+
* mounts at root — there is no standalone-server mode that needed a prefix.
|
|
31
|
+
*/
|
|
32
|
+
setInitialRoutePath(_initialPath: string): this;
|
|
29
33
|
build(onStarted?: () => Promise<void>): Record<string, DeployableFunction>;
|
|
30
34
|
}
|
|
31
35
|
//# sourceMappingURL=Storm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Storm.d.ts","sourceRoot":"","sources":["../../../src/main/app-backend/core/Storm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,SAAS,EAAiD,MAAM,8BAA8B,CAAC;AAC7I,OAAO,EACH,KAAK,kBAAkB,EAEvB,KAAK,uBAAuB,EAC/B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AAGtE,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAC,KAAK,OAAO,EAAE,KAAK,MAAM,EAAC,MAAM,SAAS,CAAC;AAIlD,qBAAa,KACT,SAAQ,SAAS;IAGjB,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"Storm.d.ts","sourceRoot":"","sources":["../../../src/main/app-backend/core/Storm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,SAAS,EAAiD,MAAM,8BAA8B,CAAC;AAC7I,OAAO,EACH,KAAK,kBAAkB,EAEvB,KAAK,uBAAuB,EAC/B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AAGtE,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAC,KAAK,OAAO,EAAE,KAAK,MAAM,EAAC,MAAM,SAAS,CAAC;AAIlD,qBAAa,KACT,SAAQ,SAAS;IAGjB,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,OAAO,CAAC,CAAU;IAC1B,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,SAAS,CAAC,CAAsB;IACxC,OAAO,CAAC,OAAO,CAAC,CAAsB;IACtC,OAAO,CAAC,kBAAkB,CAA+B;IAEzD,oBAAoB,EAAE,gBAAgB,CAAoC;;IAOnE,uBAAuB,CAAC,oBAAoB,EAAE,gBAAgB;IAK9D,MAAM,CAAC,GAAG,EAAE,OAAO;IAQnB,qBAAqB,CAAC,OAAO,EAAE,uBAAuB;IAKtD,YAAY,CAAC,SAAS,EAAE,SAAS;IAKjC,YAAY;IAIZ,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC;IAK5C,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC;IAK/C,MAAM,CAAC,WAAW,IAAI,KAAK;IAI3B,IAAI;IAiBJ,OAAO,CAAC,wBAAwB;IA2BhC,SAAS,CAAC,MAAM,EAAE,MAAM;IAKxB;;;;OAIG;IACH,mBAAmB,CAAC,YAAY,EAAE,MAAM;IAIxC,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC;CA+BxC"}
|
|
@@ -11,7 +11,6 @@ export class Storm extends BaseStorm {
|
|
|
11
11
|
// v2.0: consumers build an Express Router by hand and hand it here.
|
|
12
12
|
// The framework `app.use`s it during build(); there is no other path.
|
|
13
13
|
routes;
|
|
14
|
-
initialPath;
|
|
15
14
|
functions = [];
|
|
16
15
|
express;
|
|
17
16
|
logClient = LogClient_Function;
|
|
@@ -97,22 +96,25 @@ export class Storm extends BaseStorm {
|
|
|
97
96
|
this.routes = routes;
|
|
98
97
|
return this;
|
|
99
98
|
}
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
/**
|
|
100
|
+
* @deprecated No-op. The URL prefix comes from the function name on Cloud
|
|
101
|
+
* Functions (the `api` function serves `…/api/**`), so the router always
|
|
102
|
+
* mounts at root — there is no standalone-server mode that needed a prefix.
|
|
103
|
+
*/
|
|
104
|
+
setInitialRoutePath(_initialPath) {
|
|
102
105
|
return this;
|
|
103
106
|
}
|
|
104
107
|
build(onStarted) {
|
|
105
108
|
// The Express API is a regular module now (ApiFunction) — Storm no longer
|
|
106
109
|
// hand-builds it. When none is registered, an implicit default named "api"
|
|
107
110
|
// is created from the legacy builder methods (setApp/setRoutes/
|
|
108
|
-
//
|
|
109
|
-
//
|
|
111
|
+
// setApiFunctionOptions); registering ANY ApiFunction instance disables
|
|
112
|
+
// that default.
|
|
110
113
|
const registeredApis = this.modules.filter(module => module instanceof ApiFunction);
|
|
111
114
|
if (registeredApis.length === 0)
|
|
112
115
|
this.addModules(new ApiFunction("api", {
|
|
113
116
|
app: this.express,
|
|
114
117
|
router: this.routes,
|
|
115
|
-
initialRoutePath: this.initialPath,
|
|
116
118
|
options: this.apiFunctionOptions
|
|
117
119
|
}));
|
|
118
120
|
else if (this.routes)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Storm.js","sourceRoot":"","sources":["../../../src/main/app-backend/core/Storm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,0BAA0B,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,EAAC,MAAM,8BAA8B,CAAC;AAC7I,OAAO,EAEH,gBAAgB,EAEnB,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAuB,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAC,WAAW,EAAC,MAAM,kCAAkC,CAAC;AAC7D,OAAO,EAAC,SAAS,EAAC,MAAM,iCAAiC,CAAC;AAC1D,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAA2B,MAAM,SAAS,CAAC;AAClD,OAAO,EAAC,8BAA8B,EAAC,MAAM,oCAAoC,CAAC;AAClF,OAAO,EAAC,cAAc,EAAC,MAAM,qCAAqC,CAAC;AAEnE,MAAM,OAAO,KACT,SAAQ,SAAS;IACjB,oEAAoE;IACpE,sEAAsE;IAC9D,MAAM,CAAU;IAChB,
|
|
1
|
+
{"version":3,"file":"Storm.js","sourceRoot":"","sources":["../../../src/main/app-backend/core/Storm.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,8 +16,6 @@ export type ApiFunctionArgs = {
|
|
|
16
16
|
app?: Express;
|
|
17
17
|
/** The route table this API serves (an Express Router built by the app). */
|
|
18
18
|
router?: Router;
|
|
19
|
-
/** Mounted as the router's URL prefix when running outside GCP (emulator/local). */
|
|
20
|
-
initialRoutePath?: string;
|
|
21
19
|
/** Runtime options: memory, timeoutSeconds, generation ("v1"/"v2"), region, ... */
|
|
22
20
|
options?: FirebaseFunctionOptions;
|
|
23
21
|
};
|
|
@@ -39,17 +37,15 @@ export type ApiFunctionArgs = {
|
|
|
39
37
|
* the instance's own slice (config[name]) layers on top.
|
|
40
38
|
*
|
|
41
39
|
* When no ApiFunction is registered, Storm builds an implicit default named
|
|
42
|
-
* "api" from its legacy builder methods (setApp/setRoutes/
|
|
43
|
-
*
|
|
40
|
+
* "api" from its legacy builder methods (setApp/setRoutes/setApiFunctionOptions)
|
|
41
|
+
* — registering ANY instance disables that default.
|
|
44
42
|
*/
|
|
45
43
|
export declare class ApiFunction extends FirebaseFunction {
|
|
46
44
|
private readonly providedApp?;
|
|
47
45
|
private router?;
|
|
48
|
-
private initialRoutePath?;
|
|
49
46
|
private _app?;
|
|
50
47
|
constructor(name: string, args?: ApiFunctionArgs);
|
|
51
48
|
setRoutes(router: Router): this;
|
|
52
|
-
setInitialRoutePath(initialRoutePath: string): this;
|
|
53
49
|
private get app();
|
|
54
50
|
getFunction: () => DeployableFunction;
|
|
55
51
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiFunction.d.ts","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/ApiFunction.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,OAAO,EAAE,KAAK,MAAM,EAAC,MAAM,SAAS,CAAC;AAClD,OAAO,EACH,KAAK,kBAAkB,EAEvB,gBAAgB,EAChB,KAAK,uBAAuB,EAC/B,MAAM,+CAA+C,CAAC;
|
|
1
|
+
{"version":3,"file":"ApiFunction.d.ts","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/ApiFunction.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,OAAO,EAAE,KAAK,MAAM,EAAC,MAAM,SAAS,CAAC;AAClD,OAAO,EACH,KAAK,kBAAkB,EAEvB,gBAAgB,EAChB,KAAK,uBAAuB,EAC/B,MAAM,+CAA+C,CAAC;AAIvD,MAAM,MAAM,eAAe,GAAG;IAC1B;;;;;;;;;;;OAWG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,OAAO,CAAC,EAAE,uBAAuB,CAAC;CACrC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,WACT,SAAQ,gBAAgB;IAExB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAU;IACvC,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,IAAI,CAAC,CAAU;gBAEX,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,eAAoB;IAMpD,SAAS,CAAC,MAAM,EAAE,MAAM;IAQxB,OAAO,KAAK,GAAG,GAoBd;IAED,WAAW,QAAO,kBAAkB,CAUlC;CACL"}
|
|
@@ -2,6 +2,7 @@ import express from "express";
|
|
|
2
2
|
import {} from "express";
|
|
3
3
|
import { Firebase_ExpressFunction, FirebaseFunction } from "@intuitionrobotics/firebase/backend-functions";
|
|
4
4
|
import { HttpServer_Class } from "./HttpServer.js";
|
|
5
|
+
import { terminalErrorHandler } from "./app-middleware.js";
|
|
5
6
|
/**
|
|
6
7
|
* An Express-backed HTTPS Cloud Function as a *regular module* — registered via
|
|
7
8
|
* `Storm.addModules(...)` like any other function, named after the module
|
|
@@ -20,28 +21,22 @@ import { HttpServer_Class } from "./HttpServer.js";
|
|
|
20
21
|
* the instance's own slice (config[name]) layers on top.
|
|
21
22
|
*
|
|
22
23
|
* When no ApiFunction is registered, Storm builds an implicit default named
|
|
23
|
-
* "api" from its legacy builder methods (setApp/setRoutes/
|
|
24
|
-
*
|
|
24
|
+
* "api" from its legacy builder methods (setApp/setRoutes/setApiFunctionOptions)
|
|
25
|
+
* — registering ANY instance disables that default.
|
|
25
26
|
*/
|
|
26
27
|
export class ApiFunction extends FirebaseFunction {
|
|
27
28
|
providedApp;
|
|
28
29
|
router;
|
|
29
|
-
initialRoutePath;
|
|
30
30
|
_app;
|
|
31
31
|
constructor(name, args = {}) {
|
|
32
32
|
super(name, undefined, undefined, args.options ?? {});
|
|
33
33
|
this.providedApp = args.app;
|
|
34
34
|
this.router = args.router;
|
|
35
|
-
this.initialRoutePath = args.initialRoutePath;
|
|
36
35
|
}
|
|
37
36
|
setRoutes(router) {
|
|
38
37
|
this.router = router;
|
|
39
38
|
return this;
|
|
40
39
|
}
|
|
41
|
-
setInitialRoutePath(initialRoutePath) {
|
|
42
|
-
this.initialRoutePath = initialRoutePath;
|
|
43
|
-
return this;
|
|
44
|
-
}
|
|
45
40
|
// Built lazily at getFunction() time: framework middleware (compression/CORS/
|
|
46
41
|
// json — via HttpServer, whose config getter layers the shared "HttpServer"
|
|
47
42
|
// slice under this instance's own slice) + the instance's router.
|
|
@@ -51,9 +46,15 @@ export class ApiFunction extends FirebaseFunction {
|
|
|
51
46
|
const app = this.providedApp ?? express();
|
|
52
47
|
const httpServer = new HttpServer_Class(app, this.config);
|
|
53
48
|
httpServer.setup();
|
|
54
|
-
|
|
49
|
+
// The function name supplies the URL prefix on Cloud Functions (the `api`
|
|
50
|
+
// function serves `…/api/**`), so the router always mounts at root.
|
|
55
51
|
if (this.router)
|
|
56
|
-
httpServer.mountRouter(this.router
|
|
52
|
+
httpServer.mountRouter(this.router);
|
|
53
|
+
// Terminal error handler for raw handler()-wrapped endpoints — MUST be
|
|
54
|
+
// registered LAST, after the router (Express is order-sensitive). Legacy
|
|
55
|
+
// ServerApi endpoints catch internally and never reach it, so it is
|
|
56
|
+
// purely additive: only handler()'s `.catch(next)` routes here.
|
|
57
|
+
app.use(terminalErrorHandler());
|
|
57
58
|
return this._app = app;
|
|
58
59
|
}
|
|
59
60
|
getFunction = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiFunction.js","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/ApiFunction.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAA2B,MAAM,SAAS,CAAC;AAClD,OAAO,EAEH,wBAAwB,EACxB,gBAAgB,EAEnB,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"ApiFunction.js","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/ApiFunction.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAA2B,MAAM,SAAS,CAAC;AAClD,OAAO,EAEH,wBAAwB,EACxB,gBAAgB,EAEnB,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAC,oBAAoB,EAAC,MAAM,qBAAqB,CAAC;AAsBzD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,WACT,SAAQ,gBAAgB;IAEP,WAAW,CAAW;IAC/B,MAAM,CAAU;IAChB,IAAI,CAAW;IAEvB,YAAY,IAAY,EAAE,OAAwB,EAAE;QAChD,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,CAAC;IAED,SAAS,CAAC,MAAc;QACpB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,8EAA8E;IAC9E,4EAA4E;IAC5E,kEAAkE;IAClE,IAAY,GAAG;QACX,IAAI,IAAI,CAAC,IAAI;YACT,OAAO,IAAI,CAAC,IAAI,CAAC;QAErB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,IAAI,OAAO,EAAE,CAAC;QAC1C,MAAM,UAAU,GAAG,IAAI,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1D,UAAU,CAAC,KAAK,EAAE,CAAC;QAEnB,0EAA0E;QAC1E,oEAAoE;QACpE,IAAI,IAAI,CAAC,MAAM;YACX,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAExC,uEAAuE;QACvE,yEAAyE;QACzE,oEAAoE;QACpE,gEAAgE;QAChE,GAAG,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC,CAAC;QAEhC,OAAO,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;IAC3B,CAAC;IAED,WAAW,GAAG,GAAuB,EAAE;QACnC,0EAA0E;QAC1E,8DAA8D;QAC9D,MAAM,eAAe,GAAG,IAAI,wBAAwB,CAChD,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,EAC9C,EAAC,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAC,CAAC,CAAC;QAEpD,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/D,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;QACnE,OAAO,eAAe,CAAC,WAAW,EAAE,CAAC;IACzC,CAAC,CAAC;CACL"}
|
|
@@ -4,7 +4,6 @@ import type { ApiResponse, HttpRequestData } from "./server-api.js";
|
|
|
4
4
|
import { ApiException } from "../../exceptions.js";
|
|
5
5
|
import type { Express, ExpressRequest } from "../../utils/types.js";
|
|
6
6
|
type ConfigType = {
|
|
7
|
-
port: number;
|
|
8
7
|
baseUrl: string;
|
|
9
8
|
cors: {
|
|
10
9
|
origins?: string[];
|
|
@@ -12,10 +11,6 @@ type ConfigType = {
|
|
|
12
11
|
headers?: string[];
|
|
13
12
|
exposedHeaders?: string[];
|
|
14
13
|
};
|
|
15
|
-
ssl: {
|
|
16
|
-
key: string;
|
|
17
|
-
cert: string;
|
|
18
|
-
};
|
|
19
14
|
bodyParserLimit: number | string;
|
|
20
15
|
};
|
|
21
16
|
export type HttpErrorHandler = (requestData: HttpRequestData, error: ApiException) => Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpServer.d.ts","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/HttpServer.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2B,MAAM,EAAC,MAAM,8BAA8B,CAAC;AAC9E,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,8BAA8B,CAAC;AAE3D,OAAO,KAAK,EAAC,WAAW,EAAE,eAAe,EAAC,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAC,YAAY,EAAC,MAAM,qBAAqB,CAAC;AAGjD,OAAO,KAAK,EAAC,OAAO,EAAE,cAAc,EAAC,MAAM,sBAAsB,CAAC;AAelE,KAAK,UAAU,GAAG;IACd,
|
|
1
|
+
{"version":3,"file":"HttpServer.d.ts","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/HttpServer.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2B,MAAM,EAAC,MAAM,8BAA8B,CAAC;AAC9E,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,8BAA8B,CAAC;AAE3D,OAAO,KAAK,EAAC,WAAW,EAAE,eAAe,EAAC,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAC,YAAY,EAAC,MAAM,qBAAqB,CAAC;AAGjD,OAAO,KAAK,EAAC,OAAO,EAAE,cAAc,EAAC,MAAM,sBAAsB,CAAC;AAelE,KAAK,UAAU,GAAG;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE;QACF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;KAC5B,CAAA;IACD,eAAe,EAAE,MAAM,GAAG,MAAM,CAAA;CACnC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,eAAe,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEtG,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAA;AACxJ,qBAAa,gBACT,SAAQ,MAAM,CAAC,UAAU,CAAC;IAE1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;gBAEtB,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU;IAMxD,UAAU;IAIV;;;;OAIG;IACH,MAAM,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAO5C;;;;;OAKG;IACH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAUhD,KAAK;IAyEE,WAAW,CAAC,MAAM,EAAE,OAAO,SAAS,EAAE,MAAM,EAAE,SAAS,GAAE,MAAW;CAM9E;AAED,qBAAa,SAAS;IAClB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,GAAG,EAAE,MAAM,EAAE,YAAY,GAAE,MAAY;IAKnD,GAAG,CAAC,OAAO,EAAE,cAAc;CAO9B"}
|
|
@@ -110,9 +110,9 @@ export class HttpServer_Class extends Module {
|
|
|
110
110
|
// method just `app.use`s it. No RouteResolver, no fs walk, no codegen
|
|
111
111
|
// walker — Express owns the route table.
|
|
112
112
|
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
113
|
+
// The router mounts at the application root: on Cloud Functions the URL
|
|
114
|
+
// prefix comes from the function name (the `api` function serves `…/api/**`).
|
|
115
|
+
// `urlPrefix` is kept as an optional escape hatch but is normally unused.
|
|
116
116
|
mountRouter(router, urlPrefix = "") {
|
|
117
117
|
if (urlPrefix)
|
|
118
118
|
this.express.use(urlPrefix, router);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpServer.js","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/HttpServer.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,aAAa,CAAC;AACtC,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAC,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAC,MAAM,8BAA8B,CAAC;AAE9E,OAAO,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAE1C,OAAO,EAAC,YAAY,EAAC,MAAM,qBAAqB,CAAC;AACjD,OAAO,OAAO,MAAM,SAAS,CAAC;AAG9B,OAAO,EAAC,6BAA6B,EAAE,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAE5E,MAAM,cAAc,GAAa;IAC7B,cAAc;IACd,kBAAkB;IAClB,cAAc;IACd,eAAe;CAClB,CAAA;AAED,MAAM,cAAc,GAAa;IAC7B,6BAA6B;IAC7B,aAAa;CAChB,CAAC;
|
|
1
|
+
{"version":3,"file":"HttpServer.js","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/HttpServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Logger } from "@intuitionrobotics/ts-common";
|
|
2
|
+
import { ApiException } from "../../exceptions.js";
|
|
3
|
+
import { type HttpRequestData } from "./server-api.js";
|
|
4
|
+
/**
|
|
5
|
+
* The shared error-composition pipeline, extracted verbatim from
|
|
6
|
+
* `ServerApi.call()`'s catch block. BOTH the legacy `ServerApi` (its own
|
|
7
|
+
* internal catch) and the new app-level `terminalErrorHandler` route errors
|
|
8
|
+
* through this ONE function, so the two endpoint styles can never drift.
|
|
9
|
+
*
|
|
10
|
+
* It normalizes any thrown value to an `ApiException`, logs it, maps the
|
|
11
|
+
* response code to a `ServerErrorSeverity`, and — unless the exception opts
|
|
12
|
+
* out via `setDispatchError(false)` — composes an error message through the
|
|
13
|
+
* `Storm` instance and dispatches `dispatch_onServerError`.
|
|
14
|
+
*
|
|
15
|
+
* Returns the resolved `ApiException`; the CALLER decides how to write it
|
|
16
|
+
* (`response.serverError` for 500, `response.exception` otherwise). The
|
|
17
|
+
* `logger` lets callers attribute the logs to themselves (`ServerApi` passes
|
|
18
|
+
* `this`; the app-level handler passes its own module logger).
|
|
19
|
+
*/
|
|
20
|
+
export declare function composeApiError(err: any, requestData: HttpRequestData, logger: Logger): Promise<ApiException>;
|
|
21
|
+
//# sourceMappingURL=api-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-error.d.ts","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/api-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,KAAK,MAAM,EAId,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAC,YAAY,EAAC,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAC,KAAK,eAAe,EAAC,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAoEnH"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { BadImplementationException, dispatch_onServerError, isErrorOfType, MUSTNeverHappenException, ServerErrorSeverity, ValidationException } from "@intuitionrobotics/ts-common";
|
|
2
|
+
import { ApiException } from "../../exceptions.js";
|
|
3
|
+
import { Storm } from "../../core/Storm.js";
|
|
4
|
+
import {} from "./server-api.js";
|
|
5
|
+
/**
|
|
6
|
+
* The shared error-composition pipeline, extracted verbatim from
|
|
7
|
+
* `ServerApi.call()`'s catch block. BOTH the legacy `ServerApi` (its own
|
|
8
|
+
* internal catch) and the new app-level `terminalErrorHandler` route errors
|
|
9
|
+
* through this ONE function, so the two endpoint styles can never drift.
|
|
10
|
+
*
|
|
11
|
+
* It normalizes any thrown value to an `ApiException`, logs it, maps the
|
|
12
|
+
* response code to a `ServerErrorSeverity`, and — unless the exception opts
|
|
13
|
+
* out via `setDispatchError(false)` — composes an error message through the
|
|
14
|
+
* `Storm` instance and dispatches `dispatch_onServerError`.
|
|
15
|
+
*
|
|
16
|
+
* Returns the resolved `ApiException`; the CALLER decides how to write it
|
|
17
|
+
* (`response.serverError` for 500, `response.exception` otherwise). The
|
|
18
|
+
* `logger` lets callers attribute the logs to themselves (`ServerApi` passes
|
|
19
|
+
* `this`; the app-level handler passes its own module logger).
|
|
20
|
+
*/
|
|
21
|
+
export async function composeApiError(err, requestData, logger) {
|
|
22
|
+
let dispatchError = true;
|
|
23
|
+
let e = err;
|
|
24
|
+
let severity = ServerErrorSeverity.Warning;
|
|
25
|
+
if (typeof e === "string")
|
|
26
|
+
e = new BadImplementationException(`String was thrown: ${e}`);
|
|
27
|
+
if (!(e instanceof Error) && typeof e === "object")
|
|
28
|
+
e = new BadImplementationException(`Object instance was thrown: ${JSON.stringify(e)}`);
|
|
29
|
+
try {
|
|
30
|
+
logger.logErrorBold(e);
|
|
31
|
+
}
|
|
32
|
+
catch (e2) {
|
|
33
|
+
logger.logErrorBold("Error while handling error on request...", e2);
|
|
34
|
+
logger.logErrorBold(`Original error thrown: ${JSON.stringify(e)}`);
|
|
35
|
+
logger.logErrorBold(`-- Someone was stupid... you MUST only throw an Error and not objects or strings!! --`);
|
|
36
|
+
}
|
|
37
|
+
if (isErrorOfType(e, ValidationException))
|
|
38
|
+
e = new ApiException(400, "Validator exception", e);
|
|
39
|
+
if (!isErrorOfType(e, ApiException))
|
|
40
|
+
e = new ApiException(500, "Unexpected server error", e);
|
|
41
|
+
const apiException = isErrorOfType(e, ApiException);
|
|
42
|
+
if (!apiException)
|
|
43
|
+
throw new MUSTNeverHappenException("MUST NEVER REACH HERE!!!");
|
|
44
|
+
dispatchError = apiException.getDispatchError();
|
|
45
|
+
if (apiException.responseCode >= 500)
|
|
46
|
+
severity = ServerErrorSeverity.Error;
|
|
47
|
+
else if (apiException.responseCode >= 400)
|
|
48
|
+
severity = ServerErrorSeverity.Warning;
|
|
49
|
+
switch (apiException.responseCode) {
|
|
50
|
+
case 401:
|
|
51
|
+
severity = ServerErrorSeverity.Debug;
|
|
52
|
+
break;
|
|
53
|
+
case 404:
|
|
54
|
+
severity = ServerErrorSeverity.Info;
|
|
55
|
+
break;
|
|
56
|
+
case 403:
|
|
57
|
+
severity = ServerErrorSeverity.Warning;
|
|
58
|
+
break;
|
|
59
|
+
case 500:
|
|
60
|
+
severity = ServerErrorSeverity.Critical;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
if (dispatchError) {
|
|
64
|
+
try {
|
|
65
|
+
const storm = Storm.getInstance();
|
|
66
|
+
if (storm) {
|
|
67
|
+
const message = await storm.errorMessageComposer(requestData, apiException);
|
|
68
|
+
await dispatch_onServerError.dispatchModuleAsync(severity, message);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
logger.logError("Error while handing server error", e);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return apiException;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=api-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-error.js","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/api-error.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ErrorRequestHandler } from "express";
|
|
2
|
+
/**
|
|
3
|
+
* The single app-level error handler for raw (`handler()`-wrapped) endpoints.
|
|
4
|
+
* Register it LAST, after the router (see `ApiFunction`). It routes the error
|
|
5
|
+
* through the shared `composeApiError` pipeline, then writes the response with
|
|
6
|
+
* the same shape + `ServerApi.isDebug` gating as `ApiResponse.serverError` /
|
|
7
|
+
* `ApiResponse.exception` (server-api.ts:428-440).
|
|
8
|
+
*
|
|
9
|
+
* Legacy `ServerApi` endpoints never reach here (they catch internally), so
|
|
10
|
+
* this is purely additive.
|
|
11
|
+
*/
|
|
12
|
+
export declare function terminalErrorHandler(): ErrorRequestHandler;
|
|
13
|
+
//# sourceMappingURL=app-middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-middleware.d.ts","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/app-middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,mBAAmB,EAAe,MAAM,SAAS,CAAC;AAwB/D;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,IAAI,mBAAmB,CAsB1D"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Logger } from "@intuitionrobotics/ts-common";
|
|
2
|
+
import {} from "express";
|
|
3
|
+
import { parse } from "url";
|
|
4
|
+
import { composeApiError } from "./api-error.js";
|
|
5
|
+
import { ServerApi } from "./server-api.js";
|
|
6
|
+
import { HttpMethod } from "../../../shared/types.js";
|
|
7
|
+
const logger = new Logger("terminalErrorHandler");
|
|
8
|
+
/**
|
|
9
|
+
* Build the `HttpRequestData` shape (the same one `ServerApi.call()` assembles,
|
|
10
|
+
* server-api.ts:154-161) from a raw Express request, for the Storm error
|
|
11
|
+
* composer.
|
|
12
|
+
*/
|
|
13
|
+
function requestDataFrom(req) {
|
|
14
|
+
return {
|
|
15
|
+
method: (req.method ? req.method.toLowerCase() : HttpMethod.ALL),
|
|
16
|
+
originalUrl: req.path,
|
|
17
|
+
headers: req.headers,
|
|
18
|
+
url: req.url,
|
|
19
|
+
query: parse(req.url, true).query,
|
|
20
|
+
body: req.body
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The single app-level error handler for raw (`handler()`-wrapped) endpoints.
|
|
25
|
+
* Register it LAST, after the router (see `ApiFunction`). It routes the error
|
|
26
|
+
* through the shared `composeApiError` pipeline, then writes the response with
|
|
27
|
+
* the same shape + `ServerApi.isDebug` gating as `ApiResponse.serverError` /
|
|
28
|
+
* `ApiResponse.exception` (server-api.ts:428-440).
|
|
29
|
+
*
|
|
30
|
+
* Legacy `ServerApi` endpoints never reach here (they catch internally), so
|
|
31
|
+
* this is purely additive.
|
|
32
|
+
*/
|
|
33
|
+
export function terminalErrorHandler() {
|
|
34
|
+
return async (err, req, res, next) => {
|
|
35
|
+
// Headers already sent (stream/SSE) → can't rewrite the response; let
|
|
36
|
+
// Express's default finalize the (already-broken) connection.
|
|
37
|
+
if (res.headersSent)
|
|
38
|
+
return next(err);
|
|
39
|
+
const apiException = await composeApiError(err, requestDataFrom(req), logger);
|
|
40
|
+
const responseBody = apiException.responseBody;
|
|
41
|
+
if (!ServerApi.isDebug)
|
|
42
|
+
delete responseBody.debugMessage;
|
|
43
|
+
if (apiException.responseCode === 500) {
|
|
44
|
+
const cause = apiException.cause;
|
|
45
|
+
const stack = cause ? cause.stack : apiException.stack;
|
|
46
|
+
const message = (cause ? cause.message : apiException.message) || "";
|
|
47
|
+
res.status(500).set("Content-Type", "text/plain").send(ServerApi.isDebug && stack ? stack : message);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
res.status(apiException.responseCode).set("Content-Type", "application/json").send(JSON.stringify(responseBody, null, 2));
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=app-middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-middleware.js","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/app-middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,8BAA8B,CAAC;AACpD,OAAO,EAAwC,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAC,KAAK,EAAC,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAC,SAAS,EAAuB,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAC;AAEpD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAElD;;;;GAIG;AACH,SAAS,eAAe,CAAC,GAAY;IACjC,OAAO;QACH,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAe;QAC9E,WAAW,EAAE,GAAG,CAAC,IAAI;QACrB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,KAAK;QACjC,IAAI,EAAE,GAAG,CAAC,IAAI;KACjB,CAAC;AACN,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB;IAChC,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACjC,sEAAsE;QACtE,8DAA8D;QAC9D,IAAI,GAAG,CAAC,WAAW;YACf,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QAErB,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;QAC9E,MAAM,YAAY,GAAG,YAAY,CAAC,YAAY,CAAC;QAC/C,IAAI,CAAC,SAAS,CAAC,OAAO;YAClB,OAAO,YAAY,CAAC,YAAY,CAAC;QAErC,IAAI,YAAY,CAAC,YAAY,KAAK,GAAG,EAAE,CAAC;YACpC,MAAM,KAAK,GAAI,YAA0C,CAAC,KAAK,CAAC;YAChE,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC;YACvD,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACrE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACrG,OAAO;QACX,CAAC;QAED,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9H,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adds `req.account` to Express's `Request`, populated by `makeRequireAuth`.
|
|
3
|
+
*
|
|
4
|
+
* `AuthAccount` is intentionally EMPTY here so CONSUMERS widen it via
|
|
5
|
+
* declaration merging to their real account shape, e.g. in ir-q-support:
|
|
6
|
+
*
|
|
7
|
+
* declare global { namespace Express { interface AuthAccount {
|
|
8
|
+
* _id: string;
|
|
9
|
+
* email: string;
|
|
10
|
+
* } } }
|
|
11
|
+
*
|
|
12
|
+
* (A single `account` property can't be re-typed by two declarations, but an
|
|
13
|
+
* open interface merges cleanly across the framework and each consumer.)
|
|
14
|
+
*
|
|
15
|
+
* Side-effect-imported from `backend.ts` so the global merge loads transitively
|
|
16
|
+
* for consumers — without that, `req.account` silently degrades to `any`.
|
|
17
|
+
*/
|
|
18
|
+
declare global {
|
|
19
|
+
namespace Express {
|
|
20
|
+
interface AuthAccount {
|
|
21
|
+
}
|
|
22
|
+
interface Request {
|
|
23
|
+
account?: AuthAccount;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=express-augmentation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express-augmentation.d.ts","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/express-augmentation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,CAAC,MAAM,CAAC;IAIX,UAAU,OAAO,CAAC;QACd,UAAU,WAAW;SACpB;QAED,UAAU,OAAO;YACb,OAAO,CAAC,EAAE,WAAW,CAAC;SACzB;KACJ;CACJ;AAED,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express-augmentation.js","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/express-augmentation.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type NextFunction, type Request, type RequestHandler, type Response } from "express";
|
|
2
|
+
import { type ApiTypeBinder } from "../../../shared/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* An Express request typed off the same `ApiTypeBinder` the endpoint declares,
|
|
5
|
+
* so `req.body` / `req.query` and the handler's return value are all typed.
|
|
6
|
+
*/
|
|
7
|
+
export type TypedRequest<Binder extends ApiTypeBinder<any, any, any, any>> = Request<Record<string, string>, Binder["response"], Binder["body"], Binder["queryParams"]>;
|
|
8
|
+
/**
|
|
9
|
+
* A plain endpoint handler: receives the typed request (plus the raw `res`/`next`
|
|
10
|
+
* for the rare stream/redirect case) and usually just `return`s a value.
|
|
11
|
+
*/
|
|
12
|
+
export type TypedHandler<Binder extends ApiTypeBinder<any, any, any, any>> = (req: TypedRequest<Binder>, res: Response, next: NextFunction) => Promise<Binder["response"] | void> | Binder["response"] | void;
|
|
13
|
+
export type HandlerOptions = {
|
|
14
|
+
printResponse?: boolean;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Wrap a plain typed handler fn as an Express `RequestHandler`.
|
|
18
|
+
*
|
|
19
|
+
* Why a wrapper is needed at all on Express 4: a thrown/rejected async handler
|
|
20
|
+
* is NOT forwarded to `app.use((err,…)=>)` — so we `.catch(next)` to route it
|
|
21
|
+
* to the app-level `terminalErrorHandler`. We also auto-serialize the return
|
|
22
|
+
* value (object→json, "<html…>"→html, else text), matching the legacy
|
|
23
|
+
* `ServerApi.call()` behavior so handlers can simply `return`.
|
|
24
|
+
*
|
|
25
|
+
* A handler may instead write to `res` directly (stream/SSE/redirect): once
|
|
26
|
+
* `res.headersSent`, autoSend is a no-op. Rule: return a value XOR write `res`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function handler<Binder extends ApiTypeBinder<any, any, any, any>>(fn: TypedHandler<Binder>, opts?: HandlerOptions): RequestHandler;
|
|
29
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,YAAY,EAAE,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAC5F,OAAO,EAAC,KAAK,aAAa,EAAC,MAAM,0BAA0B,CAAC;AAI5D;;;GAGG;AACH,MAAM,MAAM,YAAY,CAAC,MAAM,SAAS,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IACrE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;AAE/F;;;GAGG;AACH,MAAM,MAAM,YAAY,CAAC,MAAM,SAAS,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IACrE,CAAC,GAAG,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;AAErI,MAAM,MAAM,cAAc,GAAG;IAIzB,aAAa,CAAC,EAAE,OAAO,CAAA;CAC1B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,MAAM,SAAS,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACpE,EAAE,EAAE,YAAY,CAAC,MAAM,CAAC,EACxB,IAAI,GAAE,cAAmB,GAC1B,cAAc,CAOhB"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Logger } from "@intuitionrobotics/ts-common";
|
|
2
|
+
import {} from "express";
|
|
3
|
+
import {} from "../../../shared/types.js";
|
|
4
|
+
const logger = new Logger("api-handler");
|
|
5
|
+
/**
|
|
6
|
+
* Wrap a plain typed handler fn as an Express `RequestHandler`.
|
|
7
|
+
*
|
|
8
|
+
* Why a wrapper is needed at all on Express 4: a thrown/rejected async handler
|
|
9
|
+
* is NOT forwarded to `app.use((err,…)=>)` — so we `.catch(next)` to route it
|
|
10
|
+
* to the app-level `terminalErrorHandler`. We also auto-serialize the return
|
|
11
|
+
* value (object→json, "<html…>"→html, else text), matching the legacy
|
|
12
|
+
* `ServerApi.call()` behavior so handlers can simply `return`.
|
|
13
|
+
*
|
|
14
|
+
* A handler may instead write to `res` directly (stream/SSE/redirect): once
|
|
15
|
+
* `res.headersSent`, autoSend is a no-op. Rule: return a value XOR write `res`.
|
|
16
|
+
*/
|
|
17
|
+
export function handler(fn, opts = {}) {
|
|
18
|
+
return (req, res, next) => {
|
|
19
|
+
Promise.resolve()
|
|
20
|
+
.then(() => fn(req, res, next))
|
|
21
|
+
.then(value => autoSend(res, value, opts))
|
|
22
|
+
.catch(next);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Mirrors the response auto-detect of the legacy `ServerApi.call()`
|
|
27
|
+
* (server-api.ts:170-187) — including the 2-space JSON formatting and the
|
|
28
|
+
* case-insensitive "<html" sniff — so migrated endpoints stay byte-identical.
|
|
29
|
+
*/
|
|
30
|
+
function autoSend(res, value, opts) {
|
|
31
|
+
if (res.headersSent)
|
|
32
|
+
return; // handler wrote the response itself (stream/SSE/redirect/manual res.*)
|
|
33
|
+
if (value === undefined || value === null) {
|
|
34
|
+
res.status(200).end();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (opts.printResponse !== false)
|
|
38
|
+
logger.logVerbose(" -- Response:", value);
|
|
39
|
+
if (typeof value === "object") {
|
|
40
|
+
res.status(200).set("Content-Type", "application/json").send(JSON.stringify(value, null, 2));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (typeof value === "string" && value.toLowerCase().startsWith("<html")) {
|
|
44
|
+
res.status(200).set("Content-Type", "text/html").send(value);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
res.status(200).set("Content-Type", "text/plain").send(String(value));
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,8BAA8B,CAAC;AACpD,OAAO,EAAqE,MAAM,SAAS,CAAC;AAC5F,OAAO,EAAoB,MAAM,0BAA0B,CAAC;AAE5D,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,aAAa,CAAC,CAAC;AAuBzC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,OAAO,CACnB,EAAwB,EACxB,OAAuB,EAAE;IAEzB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACtB,OAAO,CAAC,OAAO,EAAE;aACZ,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,GAAsC,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;aACjE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;aACzC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,SAAS,QAAQ,CAAC,GAAa,EAAE,KAAc,EAAE,IAAoB;IACjE,IAAI,GAAG,CAAC,WAAW;QACf,OAAO,CAAG,uEAAuE;IAErF,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACxC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QACtB,OAAO;IACX,CAAC;IAED,IAAI,IAAI,CAAC,aAAa,KAAK,KAAK;QAC5B,MAAM,CAAC,UAAU,CAAC,eAAe,EAAE,KAAe,CAAC,CAAC;IAExD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7F,OAAO;IACX,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7D,OAAO;IACX,CAAC;IAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAC1E,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type Request, type RequestHandler, type Response } from "express";
|
|
2
|
+
/**
|
|
3
|
+
* The auth logic itself (session/JWT validation + scope checks) lives in the
|
|
4
|
+
* CONSUMER (e.g. `AccountModule.validateSession` / `KasperoProxy.validateRequest`),
|
|
5
|
+
* so the framework ships only this factory. A validator resolves the request to
|
|
6
|
+
* an account (or rejects → the rejection flows to the terminal error handler).
|
|
7
|
+
*
|
|
8
|
+
* The legacy validators take an `ApiResponse`-shaped 3rd arg to refresh the JWT
|
|
9
|
+
* response header; the consumer adapts the raw `res` to that shape when
|
|
10
|
+
* instantiating (a tiny header sink) — see the migration recipe.
|
|
11
|
+
*/
|
|
12
|
+
export type AuthValidator = (req: Request, scopes: string[], res: Response) => Promise<Express.AuthAccount>;
|
|
13
|
+
/**
|
|
14
|
+
* Build a `requireAuth(...scopes)` middleware from a consumer auth validator.
|
|
15
|
+
*
|
|
16
|
+
* export const requireAuth = makeRequireAuth((req, scopes, res) =>
|
|
17
|
+
* AccountModule.validateSession(req, scopes, headerSink(res)));
|
|
18
|
+
*
|
|
19
|
+
* The returned middleware populates `req.account` and works both per-route
|
|
20
|
+
* (`router.post("/x", requireAuth("admin"), handler(fn))`) and at router-group
|
|
21
|
+
* level (`router.use(requireAuth())`).
|
|
22
|
+
*/
|
|
23
|
+
export declare function makeRequireAuth(validator: AuthValidator): (...scopes: string[]) => RequestHandler;
|
|
24
|
+
//# sourceMappingURL=requireAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requireAuth.d.ts","sourceRoot":"","sources":["../../../../src/main/app-backend/modules/server/requireAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAE5F;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;AAE5G;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,aAAa,IAC5C,GAAG,QAAQ,MAAM,EAAE,KAAG,cAAc,CAU/C"}
|