@nu-art/thunderstorm-backend 0.400.5

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 (111) hide show
  1. package/_entity/app-config/ModuleBE_AppConfigAPI.d.ts +9 -0
  2. package/_entity/app-config/ModuleBE_AppConfigAPI.js +20 -0
  3. package/_entity/app-config/ModuleBE_AppConfigDB.d.ts +27 -0
  4. package/_entity/app-config/ModuleBE_AppConfigDB.js +91 -0
  5. package/_entity/app-config/index.d.ts +2 -0
  6. package/_entity/app-config/index.js +2 -0
  7. package/_entity/app-config/module-pack.d.ts +2 -0
  8. package/_entity/app-config/module-pack.js +3 -0
  9. package/_entity/backup-doc/ModuleBE_BackupDocDB.d.ts +52 -0
  10. package/_entity/backup-doc/ModuleBE_BackupDocDB.js +350 -0
  11. package/_entity/backup-doc/ModuleBE_BackupScheduler.d.ts +7 -0
  12. package/_entity/backup-doc/ModuleBE_BackupScheduler.js +14 -0
  13. package/_entity/backup-doc/index.d.ts +3 -0
  14. package/_entity/backup-doc/index.js +3 -0
  15. package/_entity/backup-doc/module-pack.d.ts +2 -0
  16. package/_entity/backup-doc/module-pack.js +3 -0
  17. package/_entity/editable-test/ModuleBE_EditableTestDB.d.ts +8 -0
  18. package/_entity/editable-test/ModuleBE_EditableTestDB.js +8 -0
  19. package/_entity/editable-test/index.d.ts +1 -0
  20. package/_entity/editable-test/index.js +1 -0
  21. package/_entity/editable-test/module-pack.d.ts +1 -0
  22. package/_entity/editable-test/module-pack.js +3 -0
  23. package/_entity.d.ts +3 -0
  24. package/_entity.js +3 -0
  25. package/core/BaseStorm.d.ts +17 -0
  26. package/core/BaseStorm.js +77 -0
  27. package/core/Storm.d.ts +15 -0
  28. package/core/Storm.js +93 -0
  29. package/core/db-def.d.ts +10 -0
  30. package/core/db-def.js +11 -0
  31. package/core/default-storm.d.ts +3 -0
  32. package/core/default-storm.js +30 -0
  33. package/core/storm-modulepack.d.ts +3 -0
  34. package/core/storm-modulepack.js +20 -0
  35. package/core/typed-api.d.ts +7 -0
  36. package/core/typed-api.js +46 -0
  37. package/exceptions.d.ts +1 -0
  38. package/exceptions.js +21 -0
  39. package/index.d.ts +27 -0
  40. package/index.js +48 -0
  41. package/modules/CleanupScheduler.d.ts +14 -0
  42. package/modules/CleanupScheduler.js +50 -0
  43. package/modules/ModuleBE_APIs.d.ts +11 -0
  44. package/modules/ModuleBE_APIs.js +19 -0
  45. package/modules/ModuleBE_CSVParser.d.ts +9 -0
  46. package/modules/ModuleBE_CSVParser.js +50 -0
  47. package/modules/ModuleBE_ForceUpgrade.d.ts +21 -0
  48. package/modules/ModuleBE_ForceUpgrade.js +70 -0
  49. package/modules/ModuleBE_ServerInfo.d.ts +20 -0
  50. package/modules/ModuleBE_ServerInfo.js +76 -0
  51. package/modules/_imports.d.ts +6 -0
  52. package/modules/_imports.js +26 -0
  53. package/modules/_tdb/service-accounts.d.ts +19 -0
  54. package/modules/_tdb/service-accounts.js +2 -0
  55. package/modules/action-processor/Action_SetupProject.d.ts +9 -0
  56. package/modules/action-processor/Action_SetupProject.js +23 -0
  57. package/modules/action-processor/ModuleBE_ActionProcessor.d.ts +11 -0
  58. package/modules/action-processor/ModuleBE_ActionProcessor.js +67 -0
  59. package/modules/action-processor/types.d.ts +10 -0
  60. package/modules/action-processor/types.js +1 -0
  61. package/modules/archiving/ModuleBE_Archiving.d.ts +119 -0
  62. package/modules/archiving/ModuleBE_Archiving.js +236 -0
  63. package/modules/collection-actions/ModuleBE_CollectionActions.d.ts +12 -0
  64. package/modules/collection-actions/ModuleBE_CollectionActions.js +69 -0
  65. package/modules/collection-actions/dispatcher.d.ts +7 -0
  66. package/modules/collection-actions/dispatcher.js +2 -0
  67. package/modules/db-api-gen/ModuleBE_BaseApi.d.ts +16 -0
  68. package/modules/db-api-gen/ModuleBE_BaseApi.js +74 -0
  69. package/modules/db-api-gen/ModuleBE_BaseDB.d.ts +78 -0
  70. package/modules/db-api-gen/ModuleBE_BaseDB.js +298 -0
  71. package/modules/http/AxiosHttpModule.d.ts +25 -0
  72. package/modules/http/AxiosHttpModule.js +132 -0
  73. package/modules/http/types.d.ts +6 -0
  74. package/modules/http/types.js +1 -0
  75. package/modules/proxy/ModuleBE_RemoteProxy.d.ts +35 -0
  76. package/modules/proxy/ModuleBE_RemoteProxy.js +86 -0
  77. package/modules/proxy/RemoteProxyCaller.d.ts +19 -0
  78. package/modules/proxy/RemoteProxyCaller.js +82 -0
  79. package/modules/proxy/assert-secret-middleware.d.ts +2 -0
  80. package/modules/proxy/assert-secret-middleware.js +24 -0
  81. package/modules/server/HeaderKey.d.ts +8 -0
  82. package/modules/server/HeaderKey.js +41 -0
  83. package/modules/server/HttpServer.d.ts +41 -0
  84. package/modules/server/HttpServer.js +223 -0
  85. package/modules/server/consts.d.ts +13 -0
  86. package/modules/server/consts.js +9 -0
  87. package/modules/server/route-resolvers/RouteResolver_Dummy.d.ts +7 -0
  88. package/modules/server/route-resolvers/RouteResolver_Dummy.js +34 -0
  89. package/modules/server/route-resolvers/RouteResolver_ModulePath.d.ts +22 -0
  90. package/modules/server/route-resolvers/RouteResolver_ModulePath.js +84 -0
  91. package/modules/server/route-resolvers/index.d.ts +7 -0
  92. package/modules/server/route-resolvers/index.js +21 -0
  93. package/modules/server/server-api.d.ts +85 -0
  94. package/modules/server/server-api.js +362 -0
  95. package/modules/server/server-errors.d.ts +4 -0
  96. package/modules/server/server-errors.js +79 -0
  97. package/modules/sync-env/ModuleBE_SyncEnv.d.ts +36 -0
  98. package/modules/sync-env/ModuleBE_SyncEnv.js +212 -0
  99. package/modules/sync-manager/ModuleBE_SyncManager.d.ts +63 -0
  100. package/modules/sync-manager/ModuleBE_SyncManager.js +254 -0
  101. package/package.json +104 -0
  102. package/shared.d.ts +1 -0
  103. package/shared.js +21 -0
  104. package/test/StormTest.d.ts +23 -0
  105. package/test/StormTest.js +49 -0
  106. package/utils/file.d.ts +2 -0
  107. package/utils/file.js +29 -0
  108. package/utils/promisify-request.d.ts +3 -0
  109. package/utils/promisify-request.js +33 -0
  110. package/utils/types.d.ts +11 -0
  111. package/utils/types.js +21 -0
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Created by tacb0ss on 11/07/2018.
3
+ */
4
+ import { ApiException, Logger, TypedMap, ValidatorTypeResolver } from '@nu-art/ts-common';
5
+ import { Stream } from 'stream';
6
+ import { ExpressRequest, ExpressResponse, ExpressRouter, ServerApi_Middleware } from '../../utils/types.js';
7
+ import { MemKey } from '@nu-art/ts-common/mem-storage/MemStorage';
8
+ import { ApiDef, BodyApi, HttpMethod_Body, HttpMethod_Query, QueryApi, TypedApi } from '@nu-art/thunderstorm-shared';
9
+ export declare const MemKey_ServerApi: MemKey<ServerApi<any>>;
10
+ export declare abstract class ServerApi<API extends TypedApi<any, any, any, any>> extends Logger {
11
+ static isDebug: boolean;
12
+ printResponse: boolean;
13
+ printRequest: boolean;
14
+ headersToLog: string[];
15
+ private url;
16
+ private middlewares?;
17
+ private bodyValidator?;
18
+ private queryValidator?;
19
+ readonly apiDef: ApiDef<API>;
20
+ private postCallActions;
21
+ protected constructor(apiDef: ApiDef<API>, tag?: string);
22
+ setMiddlewares(...middlewares: ServerApi_Middleware[]): this;
23
+ addPostCallAction(sideEffect: () => Promise<any>): this;
24
+ addMiddlewares(...middlewares: ServerApi_Middleware[]): this;
25
+ addMiddleware(middleware: ServerApi_Middleware): this;
26
+ addHeaderToLog(...headersToLog: string[]): void;
27
+ setBodyValidator(bodyValidator: ValidatorTypeResolver<API['B']>): void;
28
+ setQueryValidator(queryValidator: ValidatorTypeResolver<API['P']>): void;
29
+ getUrl(): string;
30
+ dontPrintResponse(): void;
31
+ dontPrintRequest(): void;
32
+ setMaxResponsePrintSize(printResponseMaxSizeBytes: number): void;
33
+ route(router: ExpressRouter, prefixUrl: string): void;
34
+ private callWrapper;
35
+ private performPostCallActions;
36
+ call: (req: ExpressRequest, res: ExpressResponse) => Promise<void>;
37
+ protected abstract process(): Promise<API['R']>;
38
+ }
39
+ export declare abstract class ServerApi_Get<API extends QueryApi<any, any, any, any, HttpMethod_Query>> extends ServerApi<API> {
40
+ protected constructor(apiDef: ApiDef<API>);
41
+ }
42
+ export declare abstract class ServerApi_Post<API extends BodyApi<any, any, any, any, HttpMethod_Body>> extends ServerApi<API> {
43
+ protected constructor(apiDef: ApiDef<API>);
44
+ }
45
+ export declare class ServerApi_Redirect<API extends TypedApi<any, any, any, any>> extends ServerApi<any> {
46
+ private readonly responseCode;
47
+ private readonly redirectUrl;
48
+ constructor(apiDef: ApiDef<API>, responseCode: number, redirectUrl: string);
49
+ protected process(): Promise<void>;
50
+ }
51
+ export declare class _ServerQueryApi<API extends QueryApi<any, any, any, any, HttpMethod_Query>> extends ServerApi_Get<API> {
52
+ private readonly action;
53
+ constructor(apiDef: ApiDef<API>, action: (params: API['P']) => Promise<API['R']>);
54
+ protected process(): Promise<API['R']>;
55
+ }
56
+ export declare class _ServerBodyApi<API extends BodyApi<any, any, any, any, HttpMethod_Body>> extends ServerApi_Post<API> {
57
+ private readonly action;
58
+ constructor(apiDef: ApiDef<API>, action: (params: API['B']) => Promise<API['R']>);
59
+ protected process(): Promise<API['R']>;
60
+ }
61
+ export declare class ApiResponse {
62
+ private api;
63
+ private readonly res;
64
+ private consumed;
65
+ private headers?;
66
+ constructor(api: ServerApi<any>, res: ExpressResponse);
67
+ setHeader(key: string, value: string): void;
68
+ addHeader(key: string, value: string): void;
69
+ isConsumed(): boolean;
70
+ private consume;
71
+ stream(responseCode: number, stream: Stream, _headers?: {}): void;
72
+ private printHeaders;
73
+ private printResponse;
74
+ code(responseCode: number, _headers?: any): void;
75
+ text(responseCode: number, response?: string, _headers?: any): void;
76
+ html(responseCode: number, response?: string, _headers?: any): void;
77
+ json(responseCode: number, response?: object | string, _headers?: any): void;
78
+ private _json;
79
+ end(responseCode: number, response?: object | string, _headers?: any): void;
80
+ redirect(responseCode: number, url: string, _headers?: TypedMap<string>): void;
81
+ exception(exception: ApiException, _headers?: any): void;
82
+ serverError(error: Error & {
83
+ cause?: Error;
84
+ }, _headers?: any): void;
85
+ }
@@ -0,0 +1,362 @@
1
+ /*
2
+ * Thunderstorm is a full web app framework!
3
+ *
4
+ * Typescript & Express backend infrastructure that natively runs on firebase function
5
+ * Typescript & React frontend infrastructure
6
+ *
7
+ * Copyright (C) 2020 Adam van der Kruk aka TacB0sS
8
+ *
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ */
21
+ /**
22
+ * Created by tacb0ss on 11/07/2018.
23
+ */
24
+ import { _keys, ApiException, BadImplementationException, composeUrl, currentTimeMillis, dispatch_onApplicationException, isErrorOfType, Logger, LogLevel, MimeType_json, MUSTNeverHappenException, Promise_all_sequentially, tsValidate, ValidationException } from '@nu-art/ts-common';
25
+ import { parse } from 'url';
26
+ import { HttpServer } from './HttpServer.js';
27
+ import { MemKey_HttpRequest, MemKey_HttpRequestBody, MemKey_HttpRequestHeaders, MemKey_HttpRequestMethod, MemKey_HttpRequestPath, MemKey_HttpRequestQuery, MemKey_HttpRequestUrl, MemKey_HttpResponse } from './consts.js';
28
+ import { MemKey, MemStorage } from '@nu-art/ts-common/mem-storage/MemStorage';
29
+ export const MemKey_ServerApi = new MemKey('server-api', true);
30
+ export class ServerApi extends Logger {
31
+ static isDebug;
32
+ printResponse = true;
33
+ printRequest = true;
34
+ headersToLog = [];
35
+ url;
36
+ middlewares;
37
+ bodyValidator;
38
+ queryValidator;
39
+ apiDef;
40
+ postCallActions = [];
41
+ // readonly method: HttpMethod;
42
+ // readonly relativePath: string;
43
+ constructor(apiDef, tag) {
44
+ super(tag || apiDef.path);
45
+ this.setMinLevel(ServerApi.isDebug ? LogLevel.Debug : LogLevel.Info);
46
+ this.apiDef = apiDef;
47
+ }
48
+ setMiddlewares(...middlewares) {
49
+ this.middlewares = middlewares;
50
+ return this;
51
+ }
52
+ addPostCallAction(sideEffect) {
53
+ this.postCallActions.push(sideEffect);
54
+ return this;
55
+ }
56
+ addMiddlewares(...middlewares) {
57
+ (this.middlewares || (this.middlewares = [])).push(...middlewares);
58
+ return this;
59
+ }
60
+ addMiddleware(middleware) {
61
+ (this.middlewares || (this.middlewares = [])).push(middleware);
62
+ return this;
63
+ }
64
+ addHeaderToLog(...headersToLog) {
65
+ this.headersToLog.push(...headersToLog);
66
+ }
67
+ setBodyValidator(bodyValidator) {
68
+ this.bodyValidator = bodyValidator;
69
+ }
70
+ setQueryValidator(queryValidator) {
71
+ this.queryValidator = queryValidator;
72
+ }
73
+ getUrl() {
74
+ return this.url;
75
+ }
76
+ dontPrintResponse() {
77
+ // @ts-ignore
78
+ this.printResponse = false;
79
+ }
80
+ dontPrintRequest() {
81
+ // @ts-ignore
82
+ this.printRequest = false;
83
+ }
84
+ setMaxResponsePrintSize(printResponseMaxSizeBytes) {
85
+ // @ts-ignore
86
+ this.printResponse = printResponseMaxSizeBytes > -1;
87
+ }
88
+ route(router, prefixUrl) {
89
+ let path = this.apiDef.path;
90
+ if (!path.startsWith('/'))
91
+ path = `/${path}`;
92
+ const fullPath = `${prefixUrl ? prefixUrl : ''}${path}`;
93
+ this.setTag(fullPath);
94
+ router[this.apiDef.method](fullPath, this.callWrapper);
95
+ this.url = `${HttpServer.getBaseUrl()}${fullPath}`;
96
+ }
97
+ callWrapper = async (req, res) => {
98
+ await this.call(req, res);
99
+ await this.performPostCallActions();
100
+ };
101
+ performPostCallActions = async () => {
102
+ try {
103
+ await Promise_all_sequentially(this.postCallActions);
104
+ }
105
+ catch (e) {
106
+ this.logError('Error while performing post call actions', e);
107
+ }
108
+ finally {
109
+ this.postCallActions = [];
110
+ }
111
+ };
112
+ call = async (req, res) => {
113
+ return new MemStorage().init(async () => {
114
+ const startedAt = currentTimeMillis();
115
+ const response = new ApiResponse(this, res);
116
+ this.logInfo(`Intercepted Url: ${req.path}`);
117
+ if (this.headersToLog.length > 0) {
118
+ const headers = {};
119
+ for (const headerName of this.headersToLog) {
120
+ headers[headerName] = req.header(headerName);
121
+ }
122
+ this.logDebug(`-- Headers: `, headers);
123
+ }
124
+ const reqQuery = parse(req.url, true).query;
125
+ if (reqQuery && typeof reqQuery === 'object' && Object.keys(reqQuery).length)
126
+ this.logVerbose(`-- Url Params: `, reqQuery);
127
+ else
128
+ this.logVerbose(`-- No Params`);
129
+ const body = req.body;
130
+ if (body && ((typeof body === 'object')))
131
+ if (!this.printRequest)
132
+ this.logVerbose(`-- Body (Object): - Not Printing --`);
133
+ else
134
+ this.logVerbose(`-- Body (Object): `, body);
135
+ else if (body && body.length)
136
+ if (!this.printRequest)
137
+ this.logVerbose(`-- Body (String): - Not Printing --`);
138
+ else
139
+ this.logVerbose(`-- Body (String): `, body);
140
+ else
141
+ this.logVerbose(`-- No Body`);
142
+ MemKey_ServerApi.set(this);
143
+ MemKey_HttpRequest.set(req);
144
+ MemKey_HttpResponse.set(response);
145
+ MemKey_HttpRequestHeaders.set(req.headers);
146
+ MemKey_HttpRequestQuery.set(reqQuery);
147
+ MemKey_HttpRequestUrl.set(req.url);
148
+ MemKey_HttpRequestMethod.set(this.apiDef.method);
149
+ MemKey_HttpRequestPath.set(req.path);
150
+ MemKey_HttpRequestBody.set(body);
151
+ try {
152
+ this.bodyValidator && tsValidate(body, this.bodyValidator);
153
+ this.queryValidator && tsValidate(reqQuery, this.queryValidator);
154
+ if (this.middlewares)
155
+ await Promise_all_sequentially(this.middlewares);
156
+ const toReturn = await this.process();
157
+ if (response.isConsumed())
158
+ return;
159
+ if (!toReturn)
160
+ return await response.end(200);
161
+ // TODO need to handle stream and buffers
162
+ // if (Buffer.isBuffer(toReturn))
163
+ // return response.stream(200, toReturn as Buffer);
164
+ const responseType = typeof toReturn;
165
+ if (responseType === 'object')
166
+ return await response.json(200, toReturn);
167
+ if (responseType === 'string' && toReturn.toLowerCase().startsWith('<html'))
168
+ return await response.html(200, toReturn);
169
+ return await response.text(200, toReturn);
170
+ }
171
+ catch (err) {
172
+ let e = err;
173
+ if (typeof e === 'string')
174
+ e = new BadImplementationException(`String was thrown: ${e}`);
175
+ if (!(e instanceof Error) && typeof e === 'object')
176
+ e = new BadImplementationException(`Object instance was thrown: ${JSON.stringify(e)}`);
177
+ try {
178
+ this.logErrorBold(e);
179
+ }
180
+ catch (e2) {
181
+ this.logErrorBold('Error while handling error on request...', e2);
182
+ this.logErrorBold(`Original error thrown: ${JSON.stringify(e)}`);
183
+ this.logErrorBold(`-- Someone was stupid... you MUST only throw an Error and not objects or strings!! --`);
184
+ }
185
+ if (isErrorOfType(e, ValidationException))
186
+ e = new ApiException(400, 'Validator exception', e);
187
+ if (!isErrorOfType(e, ApiException))
188
+ e = new ApiException(500, 'Unexpected server error', e);
189
+ const apiException = isErrorOfType(e, ApiException);
190
+ if (!apiException)
191
+ throw new MUSTNeverHappenException('MUST NEVER REACH HERE!!!');
192
+ this.logErrorBold(e.responseBody);
193
+ try {
194
+ await dispatch_onApplicationException.dispatchModuleAsync(e, HttpServer);
195
+ }
196
+ catch (e) {
197
+ this.logError('Error while handing server error', e);
198
+ }
199
+ if (apiException.responseCode === 500)
200
+ return response.serverError(apiException);
201
+ return response.exception(apiException);
202
+ }
203
+ finally {
204
+ this.logInfo(`Url Complete in: ${req.path} - ${currentTimeMillis() - startedAt}ms`);
205
+ }
206
+ });
207
+ };
208
+ }
209
+ export class ServerApi_Get extends ServerApi {
210
+ constructor(apiDef) {
211
+ super(apiDef);
212
+ }
213
+ }
214
+ export class ServerApi_Post extends ServerApi {
215
+ constructor(apiDef) {
216
+ super(apiDef);
217
+ }
218
+ }
219
+ export class ServerApi_Redirect extends ServerApi {
220
+ responseCode;
221
+ redirectUrl;
222
+ constructor(apiDef, responseCode, redirectUrl) {
223
+ super(apiDef);
224
+ this.responseCode = responseCode;
225
+ this.redirectUrl = redirectUrl;
226
+ }
227
+ async process() {
228
+ const url = `${composeUrl(`${HttpServer.getBaseUrl()}${this.redirectUrl}`, MemKey_HttpRequestQuery.get())}`;
229
+ MemKey_HttpResponse.get().redirect(this.responseCode, url);
230
+ }
231
+ }
232
+ export class _ServerQueryApi extends ServerApi_Get {
233
+ action;
234
+ constructor(apiDef, action) {
235
+ super(apiDef);
236
+ this.action = action;
237
+ }
238
+ async process() {
239
+ return this.action(MemKey_HttpRequestQuery.get());
240
+ }
241
+ }
242
+ export class _ServerBodyApi extends ServerApi_Post {
243
+ action;
244
+ constructor(apiDef, action) {
245
+ super(apiDef);
246
+ this.action = action;
247
+ }
248
+ async process() {
249
+ return this.action(MemKey_HttpRequestBody.get());
250
+ }
251
+ }
252
+ function mergeHeaders(headers, _headers) {
253
+ if (!headers && !_headers)
254
+ return;
255
+ return { ...headers ?? {}, ..._headers ?? {} };
256
+ }
257
+ export class ApiResponse {
258
+ api;
259
+ res;
260
+ consumed = false;
261
+ headers;
262
+ constructor(api, res) {
263
+ this.api = api;
264
+ this.res = res;
265
+ }
266
+ setHeader(key, value) {
267
+ (this.headers || (this.headers = {}))[key] = value;
268
+ }
269
+ addHeader(key, value) {
270
+ (this.headers || (this.headers = {}))[key] = `${this.headers[key] ? `${this.headers[key]};` : ''}${value}`;
271
+ }
272
+ isConsumed() {
273
+ return this.consumed;
274
+ }
275
+ consume() {
276
+ if (this.consumed) {
277
+ this.api.logError('This API was already satisfied!!', new Error());
278
+ return;
279
+ }
280
+ this.consumed = true;
281
+ }
282
+ stream(responseCode, stream, _headers) {
283
+ const headers = mergeHeaders(this.headers, _headers);
284
+ this.consume();
285
+ this.printHeaders(headers);
286
+ this.res.set(headers);
287
+ this.res.writeHead(responseCode);
288
+ stream.pipe(this.res, { end: false });
289
+ stream.on('end', () => {
290
+ this.res.end();
291
+ });
292
+ }
293
+ printHeaders(_headers) {
294
+ const headers = mergeHeaders(this.headers, _headers);
295
+ if (!headers || _keys(headers).length === 0)
296
+ return this.api.logVerbose(` -- No response headers`);
297
+ if (!this.api.printResponse)
298
+ return this.api.logVerbose(` -- Response (Headers): -- Not Printing --`);
299
+ this.api.logVerbose(` -- Response (Headers): `, headers);
300
+ }
301
+ printResponse(response) {
302
+ if (!response)
303
+ return this.api.logVerbose(` -- No response body`);
304
+ if (!this.api.printResponse)
305
+ return this.api.logVerbose(` -- Response: -- Not Printing --`);
306
+ this.api.logVerbose(` -- Response:`, response);
307
+ }
308
+ code(responseCode, _headers) {
309
+ const headers = mergeHeaders(this.headers, _headers);
310
+ this.printHeaders(headers);
311
+ this.end(responseCode, '', headers);
312
+ }
313
+ text(responseCode, response, _headers) {
314
+ const headers = mergeHeaders(this.headers, _headers) || {};
315
+ headers['content-type'] = 'text/plain';
316
+ this.end(responseCode, response, headers);
317
+ }
318
+ html(responseCode, response, _headers) {
319
+ const headers = mergeHeaders(this.headers, _headers) || {};
320
+ headers['content-type'] = 'text/html';
321
+ this.end(responseCode, response, headers);
322
+ }
323
+ json(responseCode, response, _headers) {
324
+ this._json(responseCode, response, _headers);
325
+ }
326
+ _json(responseCode, response, _headers) {
327
+ const headers = mergeHeaders(this.headers, _headers) || {};
328
+ headers['content-type'] = MimeType_json;
329
+ this.end(responseCode, response, headers);
330
+ }
331
+ end(responseCode, response, _headers) {
332
+ this.consume();
333
+ const headers = mergeHeaders(this.headers, _headers);
334
+ this.printHeaders(headers);
335
+ this.printResponse(response);
336
+ this.res.set(headers);
337
+ this.res.writeHead(responseCode);
338
+ this.res.end(typeof response !== 'string' ? JSON.stringify(response, null, 2) : response);
339
+ }
340
+ redirect(responseCode, url, _headers) {
341
+ const headers = mergeHeaders(this.headers, _headers) || {};
342
+ this.consume();
343
+ _keys(headers).reduce((res, headerKey) => {
344
+ res.setHeader(headerKey, headers[headerKey]);
345
+ return res;
346
+ }, this.res);
347
+ this.res.redirect(responseCode, url);
348
+ }
349
+ exception(exception, _headers) {
350
+ const headers = mergeHeaders(this.headers, _headers);
351
+ const responseBody = exception.responseBody;
352
+ if (!ServerApi.isDebug)
353
+ delete responseBody.debugMessage;
354
+ this._json(exception.responseCode, responseBody, headers);
355
+ }
356
+ serverError(error, _headers) {
357
+ const headers = mergeHeaders(this.headers, _headers);
358
+ const stack = error.cause ? error.cause.stack : error.stack;
359
+ const message = (error.cause ? error.cause.message : error.message) || '';
360
+ this.text(500, ServerApi.isDebug && stack ? stack : message, headers);
361
+ }
362
+ }
@@ -0,0 +1,4 @@
1
+ import { StringMap } from '@nu-art/ts-common';
2
+ import { HttpErrorHandler } from '../../utils/types.js';
3
+ export type AppPropsResolver = () => Promise<StringMap>;
4
+ export declare function DefaultApiErrorMessageComposer(headersToAttach?: string[], propsResolver?: AppPropsResolver): HttpErrorHandler;
@@ -0,0 +1,79 @@
1
+ /*
2
+ * Thunderstorm is a full web app framework!
3
+ *
4
+ * Typescript & Express backend infrastructure that natively runs on firebase function
5
+ * Typescript & React frontend infrastructure
6
+ *
7
+ * Copyright (C) 2020 Adam van der Kruk aka TacB0sS
8
+ *
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ */
21
+ import { MemKey_HttpRequestBody, MemKey_HttpRequestHeaders, MemKey_HttpRequestQuery, MemKey_HttpRequestUrl } from './consts.js';
22
+ import { __stringify, _keys, ApiException, isErrorOfType, StaticLogger } from '@nu-art/ts-common';
23
+ const _propsResolver = async () => {
24
+ return {};
25
+ };
26
+ export function DefaultApiErrorMessageComposer(headersToAttach = [], propsResolver = _propsResolver) {
27
+ return async (error) => {
28
+ const headers = MemKey_HttpRequestHeaders.get();
29
+ const query = MemKey_HttpRequestQuery.get();
30
+ const url = MemKey_HttpRequestUrl.get();
31
+ const body = MemKey_HttpRequestBody.get();
32
+ const props = await propsResolver();
33
+ StaticLogger.logInfo('props: ', props);
34
+ let slackMessage = '';
35
+ slackMessage += `${error ? error.responseCode : '000'} - ${url} \n\n`;
36
+ const propsAsString = _keys(props).reduce((toRet, key) => {
37
+ return `${toRet} ${key}: ${props[key]}\n`;
38
+ }, '');
39
+ if (props && Object.keys(props).length > 0)
40
+ slackMessage += `App Data:\n${propsAsString}\n`;
41
+ if (error) {
42
+ const cause = error.cause || error;
43
+ if (cause && cause.stack) {
44
+ slackMessage += `${cause.stack
45
+ .replace(/\/srv\/dist\//g, '@')
46
+ .replace(/\/srv\/node_modules/g, '')
47
+ .replace(/\\n/g, `\n`)
48
+ .replace(/\\"/g, `"`)
49
+ .replace(/\\t/g, '')
50
+ .replace(/\/@nu-art/g, '')}\n`;
51
+ slackMessage += '--------------------------------------------------------------------------------------\n';
52
+ }
53
+ }
54
+ const _headers = headers && _keys(headers).reduce((toRet, key) => {
55
+ if (headersToAttach.includes(key))
56
+ toRet[key] = headers[key];
57
+ return toRet;
58
+ }, {});
59
+ if (_headers && Object.keys(_headers).length > 0)
60
+ slackMessage += `Headers: ${__stringify(_headers)}\n`;
61
+ else
62
+ slackMessage += 'Headers: -- No Included Headers --\n';
63
+ if (query) {
64
+ if (query && Object.keys(query).length > 0)
65
+ slackMessage += `Query: ${__stringify(query, true)}\n`;
66
+ else
67
+ slackMessage += 'Query: -- No Query --\n';
68
+ }
69
+ if (body) {
70
+ if (body && Object.keys(body).length > 0)
71
+ slackMessage += `Body: ${__stringify(body)}\n`;
72
+ else
73
+ slackMessage += 'Body: -- No Body --\n';
74
+ }
75
+ if (isErrorOfType(error.cause || error, ApiException)?.responseBody)
76
+ slackMessage += `Error: ${__stringify(isErrorOfType(error.cause || error, ApiException).responseBody.error, true)}`;
77
+ return slackMessage;
78
+ };
79
+ }
@@ -0,0 +1,36 @@
1
+ import { Module, TypedMap } from '@nu-art/ts-common';
2
+ import { Request_FetchFirebaseBackup, Request_FetchFromEnv, Request_GetMetadata, Response_FetchBackupMetadata } from '@nu-art/thunderstorm-shared';
3
+ type Config = {
4
+ urlMap: TypedMap<string>;
5
+ sessionMap: TypedMap<TypedMap<string>>;
6
+ maxBatch: number;
7
+ shouldBackupBeforeSync?: boolean;
8
+ allowCleanSync?: boolean;
9
+ allowSyncEnv?: boolean;
10
+ allowedEnvsToSyncFrom?: string[];
11
+ };
12
+ export interface OnSyncEnvCompleted {
13
+ __onSyncEnvCompleted: (env: string, baseUrl: string, requiredHeaders: TypedMap<string>) => void;
14
+ }
15
+ declare class ModuleBE_SyncEnv_Class extends Module<Config> {
16
+ constructor();
17
+ init(): void;
18
+ fetchBackupMetadata: (queryParams: Request_GetMetadata) => Promise<Response_FetchBackupMetadata>;
19
+ pushToEnv(body: {
20
+ env: 'dev' | 'prod';
21
+ moduleName: string;
22
+ items: any[];
23
+ }): Promise<void>;
24
+ createBackup: () => Promise<{
25
+ pathToBackup: string;
26
+ backupId: string;
27
+ } | undefined>;
28
+ getLatestBackupId: () => Promise<{
29
+ latestBackupId: string;
30
+ }>;
31
+ syncFromEnvBackup: (body: Request_FetchFromEnv) => Promise<void>;
32
+ private getBackupInfo;
33
+ syncFirebaseFromBackup: (queryParams: Request_FetchFirebaseBackup) => Promise<void>;
34
+ }
35
+ export declare const ModuleBE_SyncEnv: ModuleBE_SyncEnv_Class;
36
+ export {};