taon 21.0.53 → 21.0.55

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 (115) hide show
  1. package/bin/taon +5 -5
  2. package/bin/taon-debug +5 -5
  3. package/bin/taon-debug-brk +4 -4
  4. package/browser/package.json +1 -1
  5. package/browser-prod/package.json +1 -1
  6. package/icon-menu-taon.svg +15 -15
  7. package/lib/build-info._auto-generated_.d.ts +1 -1
  8. package/lib/build-info._auto-generated_.js +1 -1
  9. package/lib/package.json +1 -1
  10. package/lib/ui/index.js +2 -2
  11. package/lib/ui/taon-admin-mode-configuration/index.js +2 -2
  12. package/lib-prod/base-classes/base-abstract-entity.js +17 -31
  13. package/lib-prod/base-classes/base-angular-service.js +83 -55
  14. package/lib-prod/base-classes/base-class.js +33 -35
  15. package/lib-prod/base-classes/base-context.js +17 -19
  16. package/lib-prod/base-classes/base-controller.js +146 -154
  17. package/lib-prod/base-classes/base-crud-controller.js +250 -221
  18. package/lib-prod/base-classes/base-custom-repository.js +7 -18
  19. package/lib-prod/base-classes/base-electron-service.js +49 -0
  20. package/lib-prod/base-classes/base-entity.js +20 -30
  21. package/lib-prod/base-classes/base-file-upload.middleware.js +72 -75
  22. package/lib-prod/base-classes/base-injector.js +176 -194
  23. package/lib-prod/base-classes/base-middleware.js +8 -5
  24. package/lib-prod/base-classes/base-migration.js +19 -22
  25. package/lib-prod/base-classes/base-provider.js +7 -5
  26. package/lib-prod/base-classes/base-repository.js +601 -573
  27. package/lib-prod/base-classes/base-subscriber-for-entity.js +143 -152
  28. package/lib-prod/base-classes/base.js +18 -0
  29. package/lib-prod/build-info._auto-generated_.js +26 -14
  30. package/lib-prod/config/controller-config.js +24 -24
  31. package/lib-prod/config/controller-options.js +2 -5
  32. package/lib-prod/config/method-config.js +6 -8
  33. package/lib-prod/config/param-config.js +2 -8
  34. package/lib-prod/constants.js +29 -25
  35. package/lib-prod/context-db-migrations.js +328 -324
  36. package/lib-prod/create-context.js +211 -146
  37. package/lib-prod/decorators/classes/controller-decorator.js +16 -20
  38. package/lib-prod/decorators/classes/entity-decorator.js +26 -47
  39. package/lib-prod/decorators/classes/middleware-decorator.js +14 -24
  40. package/lib-prod/decorators/classes/migration-decorator.js +13 -22
  41. package/lib-prod/decorators/classes/provider-decorator.js +13 -23
  42. package/lib-prod/decorators/classes/repository-decorator.js +13 -22
  43. package/lib-prod/decorators/classes/subscriber-decorator.js +13 -23
  44. package/lib-prod/decorators/decorator-abstract-opt.js +1 -4
  45. package/lib-prod/decorators/http/http-decorators.js +20 -5
  46. package/lib-prod/decorators/http/http-methods-decorators.js +91 -133
  47. package/lib-prod/decorators/http/http-params-decorators.js +36 -62
  48. package/lib-prod/dependency-injection/di-container.js +28 -29
  49. package/lib-prod/endpoint-context-storage.js +27 -32
  50. package/lib-prod/endpoint-context.js +2294 -1930
  51. package/lib-prod/entity-process.js +209 -198
  52. package/lib-prod/env/env.angular-node-app.js +66 -130
  53. package/lib-prod/env/env.docs-webapp.js +66 -130
  54. package/lib-prod/env/env.electron-app.js +66 -130
  55. package/lib-prod/env/env.mobile-app.js +66 -130
  56. package/lib-prod/env/env.npm-lib-and-cli-tool.js +66 -130
  57. package/lib-prod/env/env.vscode-plugin.js +66 -130
  58. package/lib-prod/env/index.js +6 -6
  59. package/lib-prod/express-types.js +1 -0
  60. package/lib-prod/formly/formly.models.js +1 -0
  61. package/lib-prod/formly/fromly.js +196 -175
  62. package/lib-prod/formly/type-from-entity.js +45 -52
  63. package/lib-prod/get-response-value.js +21 -18
  64. package/lib-prod/global-state/taon-global-state/index.js +6 -5
  65. package/lib-prod/global-state/taon-global-state/taon-global-state.abstract.context.js +18 -19
  66. package/lib-prod/global-state/taon-global-state/taon-global-state.constants.js +6 -9
  67. package/lib-prod/global-state/taon-global-state/taon-global-state.controller.js +40 -46
  68. package/lib-prod/global-state/taon-global-state/taon-global-state.entity.js +33 -46
  69. package/lib-prod/global-state/taon-global-state/taon-global-state.middleware.js +10 -20
  70. package/lib-prod/global-state/taon-global-state/taon-global-state.models.js +43 -33
  71. package/lib-prod/global-state/taon-global-state/taon-global-state.provider.js +10 -20
  72. package/lib-prod/global-state/taon-global-state/taon-global-state.repository.js +43 -44
  73. package/lib-prod/global-state/taon-global-state/taon-global-state.subscriber.js +20 -27
  74. package/lib-prod/global-state/taon-global-state/taon-global-state.utils.js +10 -10
  75. package/lib-prod/global-state/taon-transaction-registry/index.js +11 -10
  76. package/lib-prod/global-state/taon-transaction-registry/taon-transaction-registry.abstract.context.js +20 -21
  77. package/lib-prod/global-state/taon-transaction-registry/taon-transaction-registry.constants.js +4 -7
  78. package/lib-prod/global-state/taon-transaction-registry/taon-transaction-registry.controller.js +34 -39
  79. package/lib-prod/global-state/taon-transaction-registry/taon-transaction-registry.entity.js +34 -54
  80. package/lib-prod/global-state/taon-transaction-registry/taon-transaction-registry.middleware.js +10 -20
  81. package/lib-prod/global-state/taon-transaction-registry/taon-transaction-registry.models.js +7 -10
  82. package/lib-prod/global-state/taon-transaction-registry/taon-transaction-registry.provider.js +10 -20
  83. package/lib-prod/global-state/taon-transaction-registry/taon-transaction-registry.repository.js +29 -34
  84. package/lib-prod/global-state/taon-transaction-registry/taon-transaction-registry.subscriber.js +20 -27
  85. package/lib-prod/global-state/taon-transaction-registry/taon-transaction-registry.utils.js +4 -5
  86. package/lib-prod/helpers/class-helpers.js +210 -177
  87. package/lib-prod/helpers/clone-obj.js +16 -20
  88. package/lib-prod/helpers/taon-helpers.js +132 -114
  89. package/lib-prod/index._auto-generated_.js +5 -0
  90. package/lib-prod/index.js +248 -227
  91. package/lib-prod/inject.js +88 -33
  92. package/lib-prod/migrations/index.js +2 -1
  93. package/lib-prod/migrations/migrations_index._auto-generated_.js +3 -0
  94. package/lib-prod/models.js +72 -103
  95. package/lib-prod/orm/columns.js +58 -118
  96. package/lib-prod/orm/index.js +56 -1
  97. package/lib-prod/package.json +1 -1
  98. package/lib-prod/realtime/realtime-client.js +188 -186
  99. package/lib-prod/realtime/realtime-core.js +77 -78
  100. package/lib-prod/realtime/realtime-server.js +225 -240
  101. package/lib-prod/realtime/realtime-strategy/index.js +4 -4
  102. package/lib-prod/realtime/realtime-strategy/realtime-strategy-ipc.js +273 -219
  103. package/lib-prod/realtime/realtime-strategy/realtime-strategy-mock.js +267 -240
  104. package/lib-prod/realtime/realtime-strategy/realtime-strategy-socket-io.js +26 -20
  105. package/lib-prod/realtime/realtime-strategy/realtime-strategy.js +10 -13
  106. package/lib-prod/realtime/realtime-subs-manager.js +82 -90
  107. package/lib-prod/realtime/realtime.models.js +2 -0
  108. package/lib-prod/symbols.js +104 -105
  109. package/lib-prod/ui/index.js +1 -5
  110. package/lib-prod/ui/taon-admin-mode-configuration/index.js +1 -5
  111. package/lib-prod/validators.js +43 -37
  112. package/lib-prod.split-namespaces.json +32 -86
  113. package/package.json +1 -1
  114. package/websql/package.json +1 -1
  115. package/websql-prod/package.json +1 -1
@@ -1,786 +1,895 @@
1
- import { URL } from "url";
2
- import axios from "axios";
3
- import { ipcMain } from "electron";
4
- import { JSON10 } from "json10/lib-prod";
5
- import { walk } from "lodash-walk-object/lib-prod";
6
- import { Resource, RestHeaders, Mapping__NS__decode, Mapping__NS__encode } from "ng2-rest/lib-prod";
7
- import { from } from "rxjs";
8
- import { EventSubscriber } from "taon-typeorm/lib-prod";
9
- import { Entity as TypeormEntity } from "taon-typeorm/lib-prod";
10
- import {
11
- DataSource
12
- } from "taon-typeorm/lib-prod";
13
- import { path, requireDefault } from "tnp-core/lib-prod";
14
- import { config } from "tnp-core/lib-prod";
15
- import { CoreModels__NS__TaonHttpErrorCustomProp } from "tnp-core/lib-prod";
16
- import { fse, http, https } from "tnp-core/lib-prod";
17
- import { Utils__NS__uniqArray, UtilsOs__NS__getRealHomeDir, UtilsOs__NS__isBrowser, UtilsOs__NS__isElectron, UtilsOs__NS__isNode, UtilsOs__NS__isRunningInCliMode, UtilsOs__NS__isRunningInDocker, UtilsOs__NS__isWebSQL } from "tnp-core/lib-prod";
18
- import { crossPlatformPath } from "tnp-core/lib-prod";
19
- import { ___NS__cloneDeep, ___NS__first, ___NS__isBoolean, ___NS__isFunction, ___NS__isNil, ___NS__isObject, ___NS__isString, ___NS__isUndefined, ___NS__last, ___NS__set, ___NS__slice, ___NS__snakeCase, ___NS__startCase, Helpers__NS__error, Helpers__NS__exists, Helpers__NS__info, Helpers__NS__log, Helpers__NS__mkdirp, Helpers__NS__throwError, Helpers__NS__writeFile } from "tnp-core/lib-prod";
20
- import { apiPrefix } from "./constants";
21
- import { ContextDbMigrations } from "./context-db-migrations";
22
- import { DITaonContainer } from "./dependency-injection/di-container";
23
- import { EntityProcess } from "./entity-process";
24
- import { getResponseValue } from "./get-response-value";
25
- import { ClassHelpers__NS__asyncHandler, ClassHelpers__NS__getControllerConfigs, ClassHelpers__NS__getMethodsNames, ClassHelpers__NS__getName, ClassHelpers__NS__getOrginalClass } from "./helpers/class-helpers";
26
- import { TaonHelpers__NS__fillUpTo, TaonHelpers__NS__firstStringOrElemFromArray, TaonHelpers__NS__getExpressPath, TaonHelpers__NS__ipcKeyNameRequest, TaonHelpers__NS__ipcKeyNameResponse, TaonHelpers__NS__isGoodPath, TaonHelpers__NS__parseJSONwithStringJSONs, TaonHelpers__NS__tryTransformParam, TaonHelpers__NS__websqlMocks } from "./helpers/taon-helpers";
27
- import { Models__NS__ClassType, Models__NS__ClassTypeKey, Models__NS__DatabaseConfig, Models__NS__DatabasesFolder } from "./models";
28
- import { RealtimeCore } from "./realtime/realtime-core";
29
- import { Symbols__NS__classMethodsNames, Symbols__NS__classNameStaticProperty, Symbols__NS__ctxInClassOrClassObj, Symbols__NS__fullClassNameStaticProperty, Symbols__NS__metadata, Symbols__NS__old, Symbols__NS__orignalClass } from "./symbols";
1
+ import { URL } from 'url'; // @backend
2
+ import axios from 'axios';
3
+ import { ipcMain } from 'electron'; // @backend
4
+ import { JSON10 } from 'json10/lib-prod';
5
+ import { walk } from 'lodash-walk-object/lib-prod';
6
+ import { Resource, RestHeaders, Mapping__NS__decode, Mapping__NS__encode } from 'ng2-rest/lib-prod';
7
+ import { from } from 'rxjs';
8
+ import { EventSubscriber } from 'taon-typeorm/lib-prod'; // @websql
9
+ import { Entity as TypeormEntity } from 'taon-typeorm/lib-prod'; // @websql
10
+ import { DataSource, } from 'taon-typeorm/lib-prod';
11
+ import { path, requireDefault } from 'tnp-core/lib-prod';
12
+ import { config } from 'tnp-core/lib-prod';
13
+ import { CoreModels__NS__TaonHttpErrorCustomProp } from 'tnp-core/lib-prod';
14
+ import { fse, http, https } from 'tnp-core/lib-prod'; // @backend
15
+ import { Utils__NS__uniqArray, UtilsOs__NS__getRealHomeDir, UtilsOs__NS__isBrowser, UtilsOs__NS__isElectron, UtilsOs__NS__isNode, UtilsOs__NS__isRunningInCliMode, UtilsOs__NS__isRunningInDocker, UtilsOs__NS__isWebSQL } from 'tnp-core/lib-prod';
16
+ import { crossPlatformPath } from 'tnp-core/lib-prod';
17
+ import { ___NS__cloneDeep, ___NS__first, ___NS__isBoolean, ___NS__isFunction, ___NS__isNil, ___NS__isObject, ___NS__isString, ___NS__isUndefined, ___NS__last, ___NS__set, ___NS__slice, ___NS__snakeCase, ___NS__startCase, Helpers__NS__error, Helpers__NS__exists, Helpers__NS__info, Helpers__NS__log, Helpers__NS__mkdirp, Helpers__NS__throwError, Helpers__NS__writeFile } from 'tnp-core/lib-prod';
18
+ import { apiPrefix } from './constants';
19
+ import { ContextDbMigrations } from './context-db-migrations';
20
+ import { DITaonContainer } from './dependency-injection/di-container';
21
+ import { EntityProcess } from './entity-process';
22
+ import { getResponseValue } from './get-response-value';
23
+ import { ClassHelpers__NS__asyncHandler, ClassHelpers__NS__getControllerConfigs, ClassHelpers__NS__getMethodsNames, ClassHelpers__NS__getName, ClassHelpers__NS__getOrginalClass } from './helpers/class-helpers';
24
+ import { TaonHelpers__NS__fillUpTo, TaonHelpers__NS__firstStringOrElemFromArray, TaonHelpers__NS__getExpressPath, TaonHelpers__NS__ipcKeyNameRequest, TaonHelpers__NS__ipcKeyNameResponse, TaonHelpers__NS__isGoodPath, TaonHelpers__NS__parseJSONwithStringJSONs, TaonHelpers__NS__tryTransformParam, TaonHelpers__NS__websqlMocks } from './helpers/taon-helpers';
25
+ import { Models__NS__ClassType, Models__NS__ClassTypeKey, Models__NS__DatabaseConfig, Models__NS__DatabasesFolder } from './models';
26
+ import { RealtimeCore } from './realtime/realtime-core';
27
+ import { Symbols__NS__classMethodsNames, Symbols__NS__classNameStaticProperty, Symbols__NS__ctxInClassOrClassObj, Symbols__NS__fullClassNameStaticProperty, Symbols__NS__metadata, Symbols__NS__old, Symbols__NS__orignalClass } from './symbols';
28
+ /* */
29
+ //#endregion
30
30
  let bodyParser;
31
31
  let cookieParser;
32
32
  let cors;
33
33
  let express;
34
34
  let methodOverride;
35
35
  let expressSession;
36
- bodyParser = requireDefault("body-parser");
37
- cookieParser = requireDefault("cookie-parser");
38
- cors = requireDefault("cors");
39
- express = requireDefault("express");
40
- methodOverride = requireDefault("method-override");
41
- expressSession = requireDefault("express-session");
42
- class EndpointContext {
43
- constructor(originalConfig, configFn, cloneOptions) {
44
- this.originalConfig = originalConfig;
45
- this.configFn = configFn;
46
- this.cloneOptions = cloneOptions;
47
- this.cloneOptions = this.cloneOptions || {};
48
- this.isRunningInsideDocker = UtilsOs__NS__isRunningInDocker();
49
- }
50
- //#region fields
51
- //#region fields / use mariadb mysql in docker
52
- /**
53
- * JUST FOR TESTING PURPOSES
54
- */
55
- USE_MARIADB_MYSQL_IN_DOCKER = false;
56
- //#endregion
57
- //#region fields / flags
58
- disabledRealtime = false;
59
- /**
60
- * check whether context is inited
61
- * (with init() function )
62
- */
63
- inited = false;
64
- //#endregion
65
- //#region fields / db migrations
66
- dbMigrations = new ContextDbMigrations(this);
67
- //#endregion
68
- //#region fields / local instance obj symbol
69
- localInstaceObjSymbol = Symbol("localInstaceObjSymbol");
70
- //#endregion
71
- //#region fields / all instances of classes from context
72
- /**
73
- * all instances of classes from context
74
- * key is class name
75
- */
76
- allClassesInstances = {};
77
- //#endregion
78
- //#region fields / class instances by name
79
- classInstancesByNameObj = {};
80
- //#endregion
81
- //#region fields / obj with classes instances arr
82
- objWithClassesInstancesArr = {};
83
- //#endregion
84
- //#region fields / active routes
85
- activeRoutes = [];
86
- //#endregion
87
- //#region fields / typeorm repositories
88
- //#region @websql
89
- repos = /* @__PURE__ */ new Map();
90
- //#endregion
91
- //#endregion
92
- //#region fields / source context
93
- get sourceContext() {
94
- return this.cloneOptions?.sourceContext;
95
- }
96
- //#endregion
97
- //#region fields / skip writing server routes
98
- skipWritingServerRoutes = false;
99
- //#endregion
100
- //#region fields / types from contexts
101
- injectableTypesfromContexts = [
102
- Models__NS__ClassType.CONTROLLER,
103
- Models__NS__ClassType.PROVIDER,
104
- Models__NS__ClassType.MIDDLEWARE,
105
- Models__NS__ClassType.REPOSITORY,
106
- Models__NS__ClassType.SUBSCRIBER,
107
- Models__NS__ClassType.MIGRATION
108
- ];
109
- //#endregion
110
- //#region fields / all types from contexts
111
- allTypesfromContexts = [
112
- ...this.injectableTypesfromContexts,
113
- Models__NS__ClassType.ENTITY
114
- ];
115
- //#endregion
116
- //#region fields / express app
117
- expressApp = {};
118
- //#endregion
119
- //#region fields / server tcp udp
120
- serverTcpUdp;
121
- //#endregion
122
- //#region fields / database config
123
- databaseConfig;
124
- //#endregion
125
- //#region fields / mode
126
- mode;
127
- //#endregion
128
- //#region fields / only migration start
129
- onlyMigrationRun = false;
130
- onlyMigrationRevertToTimestamp = void 0;
131
- get isRunOrRevertOnlyMigrationAppStart() {
132
- return !!(this.onlyMigrationRun || this.onlyMigrationRevertToTimestamp);
133
- }
134
- //#endregion
135
- //#region fields / session
136
- session;
137
- //#endregion
138
- //#region fields / connection
139
- connection;
140
- //#endregion
141
- //#region fields / entities triggers
142
- entitiesTriggers = {};
143
- //#endregion
144
- //#region fields / realtime
145
- realtime;
146
- get realtimeClient() {
147
- return this.realtime.client;
148
- }
149
- get realtimeServer() {
150
- return this.realtime.server;
151
- }
152
- //#endregion
153
- //#region fields / config
154
- /**
155
- * available after init()
156
- */
157
- config;
158
- //#endregion
159
- //#region fields / logs
160
- get logHttp() {
161
- if (___NS__isObject(this.config?.logs)) {
162
- return !!this.config.logs.http;
163
- }
164
- return this.config?.logs === true;
165
- }
166
- get logRealtime() {
167
- if (___NS__isObject(this.config?.logs)) {
168
- return !!this.config.logs.realtime;
169
- }
170
- return this.config?.logs === true;
171
- }
172
- get logFramework() {
173
- if (___NS__isObject(this.config?.logs)) {
174
- return !!this.config.logs.framework;
175
- }
176
- return this.config?.logs === true;
177
- }
178
- get logRoutes() {
179
- if (___NS__isObject(this.config?.logs)) {
180
- return !!this.config.logs.routes;
181
- }
182
- return this.config?.logs === true;
183
- }
184
- get logDb() {
185
- if (___NS__isObject(this.config?.logs)) {
186
- return !!this.config.logs.db;
187
- }
188
- return this.config?.logs === true;
189
- }
190
- get logMigrations() {
191
- if (___NS__isObject(this.config?.logs)) {
192
- return !!this.config.logs.migrations;
193
- }
194
- return this.config?.logs === true;
195
- }
196
- //#endregion
197
- //#endregion
198
- //#region constructor
199
- /**
200
- * Inside docker there is not need for https secure server
201
- */
202
- isRunningInsideDocker = false;
203
- //#endregion
204
- //#region methods & getters / init
205
- async init(options) {
206
- const {
207
- initFromRecrusiveContextResovle,
208
- onlyMigrationRun,
209
- onlyMigrationRevertToTimestamp
210
- } = options || {};
211
- this.inited = true;
212
- this.onlyMigrationRun = onlyMigrationRun;
213
- this.onlyMigrationRevertToTimestamp = onlyMigrationRevertToTimestamp;
214
- this.config = this.configFn({});
215
- if (___NS__isObject(this.config.database)) {
216
- this.config.database = Models__NS__DatabaseConfig.from(
217
- this.config.database
218
- ).databaseConfigTypeORM;
219
- }
220
- this.config.host = this.host === null ? void 0 : this.host;
221
- if (this.cloneOptions.overrideHost && !this.cloneOptions.useAsRemoteContext) {
222
- this.config.host = this.cloneOptions.overrideHost;
223
- }
224
- if (this.cloneOptions.overrideRemoteHost && this.cloneOptions.useAsRemoteContext) {
225
- this.config.host = this.cloneOptions.overrideRemoteHost;
226
- }
227
- if (this.config.host && !this.config.host.startsWith("http://") && !this.config.host.startsWith("https://")) {
228
- Helpers__NS__throwError(
229
- `[taon-config] Your${this.host ? " remote" : ""} 'host' must start with http:// or https://`
230
- );
231
- }
232
- if (___NS__isUndefined(this.config.useIpcWhenElectron)) {
233
- this.config.useIpcWhenElectron = true;
234
- }
235
- this.skipWritingServerRoutes = ___NS__isBoolean(
236
- this.config.skipWritingServerRoutes
237
- ) ? this.config.skipWritingServerRoutes : false;
238
- if (this.config.host) {
239
- this.mode = "backend-frontend(tcp+udp)";
240
- }
241
- if (this.isRemoteHost) {
242
- this.mode = "remote-backend(tcp+udp)";
243
- }
244
- if (this.config.useIpcWhenElectron && UtilsOs__NS__isElectron) {
245
- if (UtilsOs__NS__isWebSQL) {
246
- this.mode = "backend-frontend(websql-electron)";
247
- } else {
248
- this.mode = "backend-frontend(ipc-electron)";
249
- }
250
- }
251
- if (!this.mode && !this.config.abstract) {
252
- const errMsg = `You need to provide host property or useIpcWhenElectron or mark it as abstract`;
253
- Helpers__NS__error(
254
- `[taon][Context=${this.contextName}]: ${errMsg}`,
255
- false,
256
- true
257
- );
258
- process.exit(1);
259
- }
260
- if (this.config.database === true) {
261
- this.logFramework && console.log(`
36
+ //#region @backend
37
+ bodyParser = requireDefault('body-parser');
38
+ cookieParser = requireDefault('cookie-parser');
39
+ cors = requireDefault('cors');
40
+ express = requireDefault('express');
41
+ methodOverride = requireDefault('method-override');
42
+ expressSession = requireDefault('express-session');
43
+ //#endregion
44
+ export class EndpointContext {
45
+ //#endregion
46
+ //#endregion
47
+ //#region fields / source context
48
+ get sourceContext() {
49
+ return this.cloneOptions?.sourceContext;
50
+ }
51
+ get isRunOrRevertOnlyMigrationAppStart() {
52
+ return !!(this.onlyMigrationRun || this.onlyMigrationRevertToTimestamp);
53
+ }
54
+ get realtimeClient() {
55
+ return this.realtime.client;
56
+ }
57
+ get realtimeServer() {
58
+ return this.realtime.server;
59
+ }
60
+ //#endregion
61
+ //#region fields / logs
62
+ get logHttp() {
63
+ if (___NS__isObject(this.config?.logs)) {
64
+ return !!this.config.logs.http;
65
+ }
66
+ return this.config?.logs === true;
67
+ }
68
+ get logRealtime() {
69
+ if (___NS__isObject(this.config?.logs)) {
70
+ return !!this.config.logs.realtime;
71
+ }
72
+ return this.config?.logs === true;
73
+ }
74
+ get logFramework() {
75
+ if (___NS__isObject(this.config?.logs)) {
76
+ return !!this.config.logs.framework;
77
+ }
78
+ return this.config?.logs === true;
79
+ }
80
+ get logRoutes() {
81
+ if (___NS__isObject(this.config?.logs)) {
82
+ return !!this.config.logs.routes;
83
+ }
84
+ return this.config?.logs === true;
85
+ }
86
+ get logDb() {
87
+ if (___NS__isObject(this.config?.logs)) {
88
+ return !!this.config.logs.db;
89
+ }
90
+ return this.config?.logs === true;
91
+ }
92
+ get logMigrations() {
93
+ if (___NS__isObject(this.config?.logs)) {
94
+ return !!this.config.logs.migrations;
95
+ }
96
+ return this.config?.logs === true;
97
+ }
98
+ constructor(originalConfig, configFn,
99
+ /**
100
+ * (@default: false)
101
+ * If TRUE context is NOT going to create db/express server/http endpoints
102
+ * PURPOSE OF THIS PROPERTY
103
+ * -> ONLY remote access from backend or frontend to specific backend
104
+ */
105
+ cloneOptions) {
106
+ this.originalConfig = originalConfig;
107
+ this.configFn = configFn;
108
+ this.cloneOptions = cloneOptions;
109
+ //#region fields
110
+ //#region fields / use mariadb mysql in docker
111
+ /**
112
+ * JUST FOR TESTING PURPOSES
113
+ */
114
+ this.USE_MARIADB_MYSQL_IN_DOCKER = false;
115
+ //#endregion
116
+ //#region fields / flags
117
+ this.disabledRealtime = false;
118
+ /**
119
+ * check whether context is inited
120
+ * (with init() function )
121
+ */
122
+ this.inited = false;
123
+ //#endregion
124
+ //#region fields / db migrations
125
+ this.dbMigrations = new ContextDbMigrations(this);
126
+ //#endregion
127
+ //#region fields / local instance obj symbol
128
+ this.localInstaceObjSymbol = Symbol('localInstaceObjSymbol');
129
+ //#endregion
130
+ //#region fields / all instances of classes from context
131
+ /**
132
+ * all instances of classes from context
133
+ * key is class name
134
+ */
135
+ this.allClassesInstances = {};
136
+ //#endregion
137
+ //#region fields / class instances by name
138
+ this.classInstancesByNameObj = {};
139
+ //#endregion
140
+ //#region fields / obj with classes instances arr
141
+ this.objWithClassesInstancesArr = {};
142
+ //#endregion
143
+ //#region fields / active routes
144
+ this.activeRoutes = [];
145
+ //#endregion
146
+ //#region fields / typeorm repositories
147
+ //#region @websql
148
+ this.repos = new Map();
149
+ //#endregion
150
+ //#region fields / skip writing server routes
151
+ this.skipWritingServerRoutes = false;
152
+ //#endregion
153
+ //#region fields / types from contexts
154
+ this.injectableTypesfromContexts = [
155
+ Models__NS__ClassType.CONTROLLER,
156
+ Models__NS__ClassType.PROVIDER,
157
+ Models__NS__ClassType.MIDDLEWARE,
158
+ Models__NS__ClassType.REPOSITORY,
159
+ Models__NS__ClassType.SUBSCRIBER,
160
+ Models__NS__ClassType.MIGRATION,
161
+ ];
162
+ //#endregion
163
+ //#region fields / all types from contexts
164
+ this.allTypesfromContexts = [
165
+ ...this.injectableTypesfromContexts,
166
+ Models__NS__ClassType.ENTITY,
167
+ ];
168
+ //#endregion
169
+ //#region fields / express app
170
+ this.expressApp = {};
171
+ //#endregion
172
+ //#region fields / only migration start
173
+ this.onlyMigrationRun = false;
174
+ this.onlyMigrationRevertToTimestamp = undefined;
175
+ //#endregion
176
+ //#region fields / entities triggers
177
+ this.entitiesTriggers = {};
178
+ //#endregion
179
+ //#endregion
180
+ //#region constructor
181
+ /**
182
+ * Inside docker there is not need for https secure server
183
+ */
184
+ this.isRunningInsideDocker = false;
185
+ //#endregion
186
+ //#region methods & getters / clone class
187
+ this.cloneClassWithNewMetadata = ({ TaonBaseClass, className, config, ctx, classType, }) => {
188
+ // Return a new class that extends the base class
189
+ const cloneClass = () => {
190
+ var _a, _b, _c, _d, _e;
191
+ if (TaonBaseClass[Symbols__NS__fullClassNameStaticProperty] ===
192
+ `${ctx.contextName}.${className}`) {
193
+ return TaonBaseClass;
194
+ }
195
+ return class extends TaonBaseClass {
196
+ constructor() {
197
+ // static ['_'] = TaonBaseClass['_'];
198
+ super(...arguments);
199
+ this[_e] = ctx;
200
+ // You can override prototype properties or methods here if needed
201
+ // static properties override allowed
202
+ }
203
+ static { _a = Symbols__NS__orignalClass, _b = Symbols__NS__fullClassNameStaticProperty, _c = Symbols__NS__classNameStaticProperty, _d = Symbols__NS__ctxInClassOrClassObj, _e = Symbols__NS__ctxInClassOrClassObj; }
204
+ // @ts-ignore
205
+ static { this[_a] = TaonBaseClass; }
206
+ // @ts-ignore
207
+ static { this[_b] = `${ctx.contextName}.${className}`; }
208
+ // @ts-ignore
209
+ static { this[_c] = className; }
210
+ static { this[_d] = ctx; }
211
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
212
+ static __getFullPathForClass__(arr = []) {
213
+ const name = this[Symbols__NS__fullClassNameStaticProperty];
214
+ arr.push(name);
215
+ // @ts-ignore
216
+ if (this[Symbols__NS__orignalClass] && // @ts-ignore
217
+ this[Symbols__NS__orignalClass].__getFullPathForClass__) {
218
+ // @ts-ignore
219
+ this[Symbols__NS__orignalClass].__getFullPathForClass__(arr);
220
+ }
221
+ return arr.join('/');
222
+ }
223
+ static get fullPathForClass() {
224
+ return this.__getFullPathForClass__();
225
+ }
226
+ };
227
+ };
228
+ const cloneClassFunction = cloneClass();
229
+ //#region gather all instances for all contexts
230
+ // TODO this is not needed anymore - for typeorm I use normal entities
231
+ // this thinng belowe is nice for debugging purpose
232
+ // if (___NS__isUndefined(cloneClassFunction[Symbols__NS__orignalClassClonesObj])) {
233
+ // cloneClassFunction[Symbols__NS__orignalClassClonesObj] = {};
234
+ // }
235
+ // if (___NS__isUndefined(TaonBaseClass[Symbols__NS__orignalClassClonesObj])) {
236
+ // TaonBaseClass[Symbols__NS__orignalClassClonesObj] = {};
237
+ // }
238
+ // const all = {
239
+ // ...TaonBaseClass[Symbols__NS__orignalClassClonesObj],
240
+ // ...cloneClassFunction[Symbols__NS__orignalClassClonesObj],
241
+ // };
242
+ // all[ctx.contextName] = cloneClassFunction;
243
+ // cloneClassFunction[Symbols__NS__orignalClassClonesObj] = all;
244
+ // TaonBaseClass[Symbols__NS__orignalClassClonesObj] = all;
245
+ //#endregion
246
+ return cloneClassFunction;
247
+ };
248
+ //#endregion
249
+ //#region methods & getters / clone classes obj with new metadata
250
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
251
+ this.cloneClassesObjWithNewMetadata = ({ classesInput, config, ctx, classType, }) => {
252
+ const classes = {};
253
+ // console.log(Object.keys(classesInput))
254
+ for (const key of Object.keys(classesInput || {})) {
255
+ const TaonBaseClass = classesInput[key];
256
+ if (!TaonBaseClass) {
257
+ Helpers__NS__error(`Class ${key} is not defined in context ${ctx.contextName}
258
+
259
+ Please check if you have correct import in context file
260
+
261
+ `);
262
+ }
263
+ var className = Reflect.getMetadata(Symbols__NS__metadata.className, TaonBaseClass);
264
+ // console.log('Metadata className', className, TaonBaseClass);
265
+ // if (!className) {
266
+ // console.warn(`Please provide className for ${TaonBaseClass.name} class`);
267
+ // }
268
+ className = className || key;
269
+ TaonBaseClass[Symbols__NS__classNameStaticProperty] = className;
270
+ const clonedClass = this.cloneClassWithNewMetadata({
271
+ TaonBaseClass,
272
+ className,
273
+ config,
274
+ ctx,
275
+ classType,
276
+ });
277
+ classes[className] = clonedClass;
278
+ }
279
+ return classes;
280
+ };
281
+ this.cloneOptions = this.cloneOptions || {};
282
+ this.isRunningInsideDocker = UtilsOs__NS__isRunningInDocker();
283
+ }
284
+ //#endregion
285
+ //#region methods & getters / init
286
+ async init(options) {
287
+ const { initFromRecrusiveContextResovle, onlyMigrationRun, onlyMigrationRevertToTimestamp, } = options || {}; // TODO use it ?
288
+ this.inited = true;
289
+ // @ts-ignore
290
+ this.onlyMigrationRun = onlyMigrationRun;
291
+ // @ts-ignore
292
+ this.onlyMigrationRevertToTimestamp = onlyMigrationRevertToTimestamp;
293
+ this.config = this.configFn({});
294
+ if (___NS__isObject(this.config.database)) {
295
+ this.config.database = Models__NS__DatabaseConfig.from(this.config.database).databaseConfigTypeORM;
296
+ }
297
+ this.config.host = this.host === null ? void 0 : this.host;
298
+ if (this.cloneOptions.overrideHost &&
299
+ !this.cloneOptions.useAsRemoteContext) {
300
+ this.config.host = this.cloneOptions.overrideHost;
301
+ }
302
+ if (this.cloneOptions.overrideRemoteHost &&
303
+ this.cloneOptions.useAsRemoteContext) {
304
+ this.config.host = this.cloneOptions.overrideRemoteHost;
305
+ }
306
+ if (this.config.host &&
307
+ !this.config.host.startsWith('http://') &&
308
+ !this.config.host.startsWith('https://')) {
309
+ Helpers__NS__throwError(`[taon-config] Your${this.host ? ' remote' : ''} 'host' must start with http:// or https://`);
310
+ }
311
+ if (___NS__isUndefined(this.config.useIpcWhenElectron)) {
312
+ this.config.useIpcWhenElectron = true;
313
+ }
314
+ // console.log(`config for ${this.contextName}`, this.config);
315
+ //#region resolve if skipping writing server routes
316
+ //@ts-expect-error overriding readonly
317
+ this.skipWritingServerRoutes = ___NS__isBoolean(this.config.skipWritingServerRoutes)
318
+ ? this.config.skipWritingServerRoutes
319
+ : false;
320
+ //#endregion
321
+ //#region resolve mode
322
+ if (this.config.host) {
323
+ this.mode = 'backend-frontend(tcp+udp)';
324
+ /* */
325
+ /* */
326
+ }
327
+ if (this.isRemoteHost) {
328
+ this.mode = 'remote-backend(tcp+udp)';
329
+ }
330
+ // console.log(`
331
+ // useIpcWhenElectron: ${this.config.useIpcWhenElectron}
332
+ // UtilsOs__NS__isElectron: ${UtilsOs__NS__isElectron}
333
+ // `)
334
+ if (this.config.useIpcWhenElectron && UtilsOs__NS__isElectron) {
335
+ if (UtilsOs__NS__isWebSQL) {
336
+ this.mode = 'backend-frontend(websql-electron)';
337
+ }
338
+ else {
339
+ this.mode = 'backend-frontend(ipc-electron)';
340
+ }
341
+ }
342
+ // mode === undefined for TaonBaseContext => ok behavior
343
+ // console.log(`Mode for BE/FE communication: ${this.mode}`);
344
+ // if(!this.mode) {
345
+ // console.log(this.config)
346
+ // }
347
+ if (!this.mode && !this.config.abstract) {
348
+ const errMsg = `You need to provide host property or ` +
349
+ `useIpcWhenElectron or mark it as abstract`;
350
+ Helpers__NS__error(`[taon][Context=${this.contextName}]: ${errMsg}`, false, true);
351
+ //#region @backend
352
+ process.exit(1);
353
+ //#endregion
354
+ }
355
+ //#endregion
356
+ //#region resolve database config
357
+ if (this.config.database === true) {
358
+ this.logFramework &&
359
+ console.log(`
262
360
 
263
361
  ASSIGNING AUTO GENERATED DATABASE CONFIG
264
362
 
265
363
  `);
266
- this.databaseConfig = this.getAutoGeneratedConfig();
267
- } else if (___NS__isObject(this.config.database)) {
268
- this.logFramework && console.log(`
364
+ this.databaseConfig = this.getAutoGeneratedConfig();
365
+ }
366
+ else if (___NS__isObject(this.config.database)) {
367
+ this.logFramework &&
368
+ console.log(`
269
369
 
270
370
  OVERRIDE DATABASE CONFIG FROM CONFIGURATION
271
371
 
272
372
  `);
273
- this.databaseConfig = this.getAutoGeneratedConfig();
274
- walk.Object(
275
- this.config.database,
276
- (value, lodashPath) => {
277
- if (___NS__isNil(value) || ___NS__isFunction(value) || ___NS__isObject(value)) {
278
- } else {
279
- this.logFramework && console.info(
280
- `Overriding database config: ${lodashPath}=${value}`
281
- );
282
- ___NS__set(this.databaseConfig, lodashPath, value);
283
- }
284
- },
285
- {
286
- walkGetters: false
287
- }
288
- );
289
- }
290
- if (this.config.session) {
291
- this.session = ___NS__cloneDeep(this.config.session);
292
- const oneHour = 1e3 * 60 * 60 * 1;
293
- if (!this.session.cookieMaxAge) {
294
- this.session.cookieMaxAge = oneHour;
295
- }
296
- axios.defaults.withCredentials = true;
297
- }
298
- this.config.contexts = this.config.contexts || {};
299
- this.config.entities = this.config.entities || {};
300
- this.config.controllers = this.config.controllers || {};
301
- this.config.repositories = this.config.repositories || {};
302
- this.config.providers = this.config.providers || {};
303
- this.config.subscribers = this.config.subscribers || {};
304
- this.config.migrations = this.config.migrations || {};
305
- this.config.entities = {
306
- ...await this.getRecrusiveClassesfromContextsObj(
307
- Models__NS__ClassType.ENTITY
308
- ),
309
- ...this.config.entities
310
- };
311
- this.config.controllers = {
312
- ...await this.getRecrusiveClassesfromContextsObj(
313
- Models__NS__ClassType.CONTROLLER
314
- ),
315
- ...this.config.controllers
316
- };
317
- this.config.providers = {
318
- ...await this.getRecrusiveClassesfromContextsObj(
319
- Models__NS__ClassType.PROVIDER
320
- ),
321
- ...this.config.providers
322
- };
323
- this.config.middlewares = {
324
- ...await this.getRecrusiveClassesfromContextsObj(
325
- Models__NS__ClassType.MIDDLEWARE
326
- ),
327
- ...this.config.middlewares
328
- };
329
- this.config.subscribers = {
330
- ...await this.getRecrusiveClassesfromContextsObj(
331
- Models__NS__ClassType.SUBSCRIBER
332
- ),
333
- ...this.config.subscribers
334
- };
335
- this.config.repositories = {
336
- ...await this.getRecrusiveClassesfromContextsObj(
337
- Models__NS__ClassType.REPOSITORY
338
- ),
339
- ...this.config.repositories
340
- };
341
- this.config.migrations = {
342
- ...await this.getRecrusiveClassesfromContextsObj(
343
- Models__NS__ClassType.MIGRATION
344
- ),
345
- ...this.config.migrations
346
- };
347
- this.config.controllers = this.cloneClassesObjWithNewMetadata({
348
- classesInput: this.config.controllers,
349
- config: this.config,
350
- ctx: this,
351
- classType: Models__NS__ClassType.CONTROLLER
352
- });
353
- this.config.repositories = this.cloneClassesObjWithNewMetadata({
354
- classesInput: this.config.repositories,
355
- config: this.config,
356
- ctx: this,
357
- classType: Models__NS__ClassType.REPOSITORY
358
- });
359
- this.config.providers = this.cloneClassesObjWithNewMetadata({
360
- classesInput: this.config.providers,
361
- config: this.config,
362
- ctx: this,
363
- classType: Models__NS__ClassType.PROVIDER
364
- });
365
- this.config.middlewares = this.cloneClassesObjWithNewMetadata({
366
- classesInput: this.config.middlewares,
367
- config: this.config,
368
- ctx: this,
369
- classType: Models__NS__ClassType.MIDDLEWARE
370
- });
371
- this.config.subscribers = this.cloneClassesObjWithNewMetadata({
372
- classesInput: this.config.subscribers,
373
- config: this.config,
374
- ctx: this,
375
- classType: Models__NS__ClassType.SUBSCRIBER
376
- });
377
- this.config.migrations = this.cloneClassesObjWithNewMetadata({
378
- classesInput: this.config.migrations,
379
- config: this.config,
380
- ctx: this,
381
- classType: Models__NS__ClassType.MIGRATION
382
- });
383
- for (const classTypeName of this.injectableTypesfromContexts) {
384
- this.classInstancesByNameObj[classTypeName] = {};
385
- this.objWithClassesInstancesArr[classTypeName] = [];
386
- }
387
- for (const classTypeName of this.injectableTypesfromContexts) {
388
- await this.createInstances(
389
- this.config[Models__NS__ClassTypeKey[classTypeName]],
390
- classTypeName
391
- );
392
- }
393
- if (!this.isRunOrRevertOnlyMigrationAppStart) {
394
- if (this.mode === "backend-frontend(tcp+udp)" && !this.config.abstract) {
395
- this.expressApp = express();
396
- if (process.env.NODE_ENV === "production") {
397
- this.expressApp.set("trust proxy", 1);
398
- }
399
- await this.initBackendMiddlewares();
400
- await this.initCustomBackendMiddlewares();
401
- const shouldStartHttpsSecureServer = this.isHttpServer && !this.isRunningInsideDocker;
402
- this.logFramework && Helpers__NS__info(`
373
+ this.databaseConfig = this.getAutoGeneratedConfig();
374
+ walk.Object(this.config.database, (value, lodashPath) => {
375
+ if (___NS__isNil(value) || ___NS__isFunction(value) || ___NS__isObject(value)) {
376
+ // skipping
377
+ }
378
+ else {
379
+ this.logFramework &&
380
+ console.info(`Overriding database config: ${lodashPath}=${value}`);
381
+ ___NS__set(this.databaseConfig, lodashPath, value);
382
+ }
383
+ }, {
384
+ walkGetters: false,
385
+ });
386
+ }
387
+ //#endregion
388
+ //#region resolve session
389
+ if (this.config.session) {
390
+ this.session = ___NS__cloneDeep(this.config.session);
391
+ const oneHour = 1000 * 60 * 60 * 1; // 24;
392
+ if (!this.session.cookieMaxAge) {
393
+ this.session.cookieMaxAge = oneHour;
394
+ }
395
+ // serever and browser cookie authentication
396
+ axios.defaults.withCredentials = true;
397
+ }
398
+ //#endregion
399
+ //#region prepare & gather all classes recursively
400
+ this.config.contexts = this.config.contexts || {};
401
+ this.config.entities = this.config.entities || {};
402
+ this.config.controllers = this.config.controllers || {};
403
+ this.config.repositories = this.config.repositories || {};
404
+ this.config.providers = this.config.providers || {};
405
+ this.config.subscribers = this.config.subscribers || {};
406
+ this.config.migrations = this.config.migrations || {};
407
+ this.config.entities = {
408
+ ...(await this.getRecrusiveClassesfromContextsObj(Models__NS__ClassType.ENTITY)),
409
+ ...this.config.entities,
410
+ };
411
+ this.config.controllers = {
412
+ ...(await this.getRecrusiveClassesfromContextsObj(Models__NS__ClassType.CONTROLLER)),
413
+ ...this.config.controllers,
414
+ };
415
+ this.config.providers = {
416
+ ...(await this.getRecrusiveClassesfromContextsObj(Models__NS__ClassType.PROVIDER)),
417
+ ...this.config.providers,
418
+ };
419
+ this.config.middlewares = {
420
+ ...(await this.getRecrusiveClassesfromContextsObj(Models__NS__ClassType.MIDDLEWARE)),
421
+ ...this.config.middlewares,
422
+ };
423
+ this.config.subscribers = {
424
+ ...(await this.getRecrusiveClassesfromContextsObj(Models__NS__ClassType.SUBSCRIBER)),
425
+ ...this.config.subscribers,
426
+ };
427
+ this.config.repositories = {
428
+ ...(await this.getRecrusiveClassesfromContextsObj(Models__NS__ClassType.REPOSITORY)),
429
+ ...this.config.repositories,
430
+ };
431
+ this.config.migrations = {
432
+ ...(await this.getRecrusiveClassesfromContextsObj(Models__NS__ClassType.MIGRATION)),
433
+ ...this.config.migrations,
434
+ };
435
+ // console.log(this.config);
436
+ // debugger;
437
+ //#endregion
438
+ //#region prepare classes instances/functions clones
439
+ this.config.controllers = this.cloneClassesObjWithNewMetadata({
440
+ classesInput: this.config.controllers,
441
+ config: this.config,
442
+ ctx: this,
443
+ classType: Models__NS__ClassType.CONTROLLER,
444
+ });
445
+ this.config.repositories = this.cloneClassesObjWithNewMetadata({
446
+ classesInput: this.config.repositories,
447
+ config: this.config,
448
+ ctx: this,
449
+ classType: Models__NS__ClassType.REPOSITORY,
450
+ });
451
+ this.config.providers = this.cloneClassesObjWithNewMetadata({
452
+ classesInput: this.config.providers,
453
+ config: this.config,
454
+ ctx: this,
455
+ classType: Models__NS__ClassType.PROVIDER,
456
+ });
457
+ this.config.middlewares = this.cloneClassesObjWithNewMetadata({
458
+ classesInput: this.config.middlewares,
459
+ config: this.config,
460
+ ctx: this,
461
+ classType: Models__NS__ClassType.MIDDLEWARE,
462
+ });
463
+ this.config.subscribers = this.cloneClassesObjWithNewMetadata({
464
+ classesInput: this.config.subscribers,
465
+ config: this.config,
466
+ ctx: this,
467
+ classType: Models__NS__ClassType.SUBSCRIBER,
468
+ });
469
+ this.config.migrations = this.cloneClassesObjWithNewMetadata({
470
+ classesInput: this.config.migrations,
471
+ config: this.config,
472
+ ctx: this,
473
+ classType: Models__NS__ClassType.MIGRATION,
474
+ });
475
+ //#endregion
476
+ //#region prepare instances
477
+ for (const classTypeName of this.injectableTypesfromContexts) {
478
+ this.classInstancesByNameObj[classTypeName] = {};
479
+ this.objWithClassesInstancesArr[classTypeName] = [];
480
+ }
481
+ for (const classTypeName of this.injectableTypesfromContexts) {
482
+ await this.createInstances(this.config[Models__NS__ClassTypeKey[classTypeName]], classTypeName);
483
+ }
484
+ //#endregion
485
+ if (!this.isRunOrRevertOnlyMigrationAppStart) {
486
+ //#region prepares server
487
+ if (this.mode === 'backend-frontend(tcp+udp)' && !this.config.abstract) {
488
+ //#region @backend
489
+ this.expressApp = express();
490
+ if (process.env.NODE_ENV === 'production') {
491
+ this.expressApp.set('trust proxy', 1);
492
+ }
493
+ await this.initBackendMiddlewares();
494
+ await this.initCustomBackendMiddlewares();
495
+ const shouldStartHttpsSecureServer = this.isHttpServer && !this.isRunningInsideDocker;
496
+ this.logFramework &&
497
+ Helpers__NS__info(`
403
498
 
404
- Starting server ${shouldStartHttpsSecureServer ? "with" : "without"} HTTPS secure server
499
+ Starting server ${shouldStartHttpsSecureServer ? 'with' : 'without'} HTTPS secure server
405
500
 
406
501
  `);
407
- this.serverTcpUdp = shouldStartHttpsSecureServer ? new https.Server(
408
- {
409
- key: this.config.https?.key,
410
- cert: this.config.https?.cert
411
- },
412
- this.expressApp
413
- ) : new http.Server(this.expressApp);
414
- this.publicAssets.forEach((asset) => {
415
- this.expressApp.use(
416
- asset.serverPath,
417
- express.static(asset.locationOnDisk)
418
- );
419
- });
420
- await this.initCustomClientMiddlewares();
421
- }
422
- if (!this.config.abstract) {
423
- this.disabledRealtime = this.config.disabledRealtime;
424
- if (!this.host) {
425
- throw `
502
+ this.serverTcpUdp = shouldStartHttpsSecureServer
503
+ ? new https.Server({
504
+ key: this.config.https?.key,
505
+ cert: this.config.https?.cert,
506
+ }, this.expressApp)
507
+ : new http.Server(this.expressApp);
508
+ this.publicAssets.forEach(asset => {
509
+ this.expressApp.use(asset.serverPath, express.static(asset.locationOnDisk));
510
+ });
511
+ //#endregion
512
+ await this.initCustomClientMiddlewares();
513
+ }
514
+ //#endregion
515
+ //#region prepare realtime
516
+ if (!this.config.abstract) {
517
+ this.disabledRealtime = this.config.disabledRealtime;
518
+ if (!this.host) {
519
+ throw `
426
520
 
427
521
  host is required for context initialization..
428
522
  (Or maybe you forgot mark ${this.config.contextName} context as abstract?)
429
523
 
430
524
  `;
525
+ }
526
+ //#region @backend
527
+ // if (UtilsOs__NS__isRunningInCliMode() && !___NS__isNil(this.config.disabledRealtime)) {
528
+ // // TODO for now...
529
+ // Helpers__NS__logInfo(`Realtime disable on backend for cli mode`);
530
+ // this.disabledRealtime = true;
531
+ // } else {
532
+ // Helpers__NS__logInfo(`Realtime enabled on backend`);
533
+ // }
534
+ //#endregion
535
+ this.logRealtime &&
536
+ Helpers__NS__info(`[ctx=${this.contextName}] Init Realtime for ${this.mode}`);
537
+ this.realtime = new RealtimeCore(this);
538
+ }
539
+ //#endregion
431
540
  }
432
- this.logRealtime && Helpers__NS__info(
433
- `[ctx=${this.contextName}] Init Realtime for ${this.mode}`
434
- );
435
- this.realtime = new RealtimeCore(this);
436
- }
437
- }
438
- if (this.config.abstract) {
439
- this.logFramework && Helpers__NS__info(
440
- `[taon] Create abstract context: ${this.config.contextName}`
441
- );
442
- } else {
443
- if (this.isRemoteHost) {
444
- this.logFramework && Helpers__NS__info(
445
- `[taon] Create context for remote host: ${this.config.host}`
446
- );
447
- } else {
448
- this.logFramework && Helpers__NS__info(`[taon] Create context for host: ${this.config.host}`);
449
- }
450
- }
451
- Object.keys(this.config).forEach((key) => {
452
- this.originalConfig[key] = this.config[key];
453
- });
454
- }
455
- //#endregion
456
- //#region methods & getters / get auto generated config
457
- getAutoGeneratedConfig() {
458
- this.logFramework && console.log(`
541
+ //#region show context info
542
+ // console.log({ ref })
543
+ if (this.config.abstract) {
544
+ this.logFramework &&
545
+ Helpers__NS__info(`[taon] Create abstract context: ${this.config.contextName}`);
546
+ }
547
+ else {
548
+ if (this.isRemoteHost) {
549
+ this.logFramework &&
550
+ Helpers__NS__info(`[taon] Create context for remote host: ${this.config.host}`);
551
+ }
552
+ else {
553
+ this.logFramework &&
554
+ Helpers__NS__info(`[taon] Create context for host: ${this.config.host}`);
555
+ }
556
+ }
557
+ //#endregion
558
+ // update first exposed config
559
+ Object.keys(this.config).forEach(key => {
560
+ this.originalConfig[key] = this.config[key];
561
+ });
562
+ }
563
+ //#endregion
564
+ //#region methods & getters / get auto generated config
565
+ getAutoGeneratedConfig() {
566
+ this.logFramework &&
567
+ console.log(`
459
568
 
460
569
 
461
570
  IS RUNNING IN DOCKER: ${this.isRunningInsideDocker}
462
571
 
463
572
  `);
464
- let databaseConfig = Models__NS__DatabaseConfig.from({});
465
- const tcpUdpDatabaseSqliteRelativeFileLocation = `${Models__NS__DatabasesFolder}/db-${this.contextName}.sqlite`;
466
- if (this.isRunningInsideDocker) {
467
- if (this.USE_MARIADB_MYSQL_IN_DOCKER) {
468
- } else {
469
- this.logFramework && console.log(`
573
+ //#region @websqlFunc
574
+ let databaseConfig = Models__NS__DatabaseConfig.from({});
575
+ const tcpUdpDatabaseSqliteRelativeFileLocation = `${Models__NS__DatabasesFolder}/db-${this.contextName}.sqlite`;
576
+ if (this.isRunningInsideDocker) {
577
+ if (this.USE_MARIADB_MYSQL_IN_DOCKER) {
578
+ // Helpers__NS__info('Running in docker, using in mysql database');
579
+ // // TODO auto resolve database config in docker
580
+ // databaseConfig = Models__NS__DatabaseConfig.from({
581
+ // database: `db-${this.contextName}.sqlite`,
582
+ // type: 'mysql',
583
+ // recreateMode: 'PRESERVE_DATA+MIGRATIONS',
584
+ // logging: this.logDb,
585
+ // databasePort: 3306,
586
+ // databaseHost: 'localhost',
587
+ // databaseUsername: 'root',
588
+ // databasePassword: 'admin',
589
+ // });
590
+ }
591
+ else {
592
+ // TOOD @LAST for now.. just use sqljs in docker
593
+ this.logFramework &&
594
+ console.log(`
470
595
 
471
596
  USING GENERATED CONFIG FOR SQLJS IN DOCKER
472
597
 
473
598
  `);
474
- const locationOfTheDatabase = crossPlatformPath([
475
- process.cwd(),
476
- `db-${this.contextName}.sqlite`
477
- ]);
478
- databaseConfig = databaseConfig = Models__NS__DatabaseConfig.from({
479
- location: tcpUdpDatabaseSqliteRelativeFileLocation,
480
- type: "sqljs",
481
- useLocalForage: false,
482
- recreateMode: "PRESERVE_DATA+MIGRATIONS",
483
- logging: true
484
- });
485
- if (!fse.existsSync(locationOfTheDatabase)) {
486
- databaseConfig.recreateMode = "DROP_DB+MIGRATIONS";
487
- }
488
- this.logFramework && console.log(`
599
+ //#region @backend
600
+ const locationOfTheDatabase = crossPlatformPath([
601
+ process.cwd(),
602
+ `db-${this.contextName}.sqlite`,
603
+ ]);
604
+ //#endregion
605
+ databaseConfig = databaseConfig = Models__NS__DatabaseConfig.from({
606
+ location: tcpUdpDatabaseSqliteRelativeFileLocation,
607
+ type: 'sqljs',
608
+ useLocalForage: false,
609
+ recreateMode: 'PRESERVE_DATA+MIGRATIONS',
610
+ logging: true,
611
+ });
612
+ //#region @backend
613
+ if (!fse.existsSync(locationOfTheDatabase)) {
614
+ databaseConfig.recreateMode = 'DROP_DB+MIGRATIONS';
615
+ }
616
+ // TODO @LAST add same thing for mariadb/mysql
617
+ this.logFramework &&
618
+ console.log(`
489
619
  location of database: ${locationOfTheDatabase}
490
620
  db file exists: ${fse.existsSync(locationOfTheDatabase)}
491
621
  synchronize: ${databaseConfig.synchronize}
492
622
  dropSchema: ${databaseConfig.dropSchema}
493
623
  `);
494
- }
495
- } else {
496
- this.logFramework && Helpers__NS__info(
497
- `[taon][database] Automatically resolving database config for mode ${this.mode}`
498
- );
499
- switch (this.mode) {
500
- //#region resolve database config for backend-frontend(ipc-electron)
501
- case "backend-frontend(ipc-electron)":
502
- let dbLocationInOs;
503
- if (UtilsOs__NS__isElectron) {
504
- dbLocationInOs = crossPlatformPath([
505
- UtilsOs__NS__getRealHomeDir(),
506
- `.taon/databases-for-electron-apps/${this.appId || ___NS__snakeCase(process.cwd()).replace(/\_/, ".")}/${this.contextName}.sqlite`
507
- ]);
508
- if (!Helpers__NS__exists(path.dirname(dbLocationInOs))) {
509
- Helpers__NS__mkdirp(path.dirname(dbLocationInOs));
624
+ //#endregion
510
625
  }
511
- }
512
- databaseConfig = Models__NS__DatabaseConfig.from({
513
- location: UtilsOs__NS__isElectron ? dbLocationInOs : `db-${this.contextName}.sqlite`,
514
- type: "sqljs",
515
- recreateMode: "DROP_DB+MIGRATIONS",
516
- logging: this.logDb
517
- });
518
- break;
519
- //#endregion
520
- //#region resolve database config for mode backend-frontend(websql)
521
- case "backend-frontend(websql-electron)":
522
- case "backend-frontend(websql)":
523
- let keepWebsqlDbDataAfterReload = false;
524
- databaseConfig = databaseConfig = Models__NS__DatabaseConfig.from({
525
- location: `db-${this.contextName}.sqlite`,
526
- type: "sqljs",
527
- useLocalForage: true,
528
- // !!window['localforage'], // TODO this need to be checked in runtime
529
- recreateMode: keepWebsqlDbDataAfterReload ? "PRESERVE_DATA+MIGRATIONS" : "DROP_DB+MIGRATIONS",
530
- logging: this.logDb
531
- });
532
- break;
626
+ }
627
+ else {
628
+ //#region auto resolve db config
629
+ this.logFramework &&
630
+ Helpers__NS__info(`[taon][database] Automatically resolving database config for mode ${this.mode}`);
631
+ switch (this.mode) {
632
+ //#region resolve database config for backend-frontend(ipc-electron)
633
+ case 'backend-frontend(ipc-electron)':
634
+ let dbLocationInOs;
635
+ //#region @backend
636
+ if (UtilsOs__NS__isElectron) {
637
+ dbLocationInOs = crossPlatformPath([
638
+ UtilsOs__NS__getRealHomeDir(),
639
+ `.taon/databases-for-electron-apps/${this.appId || ___NS__snakeCase(process.cwd()).replace(/\_/, '.')}/${this.contextName}.sqlite`,
640
+ ]);
641
+ if (!Helpers__NS__exists(path.dirname(dbLocationInOs))) {
642
+ Helpers__NS__mkdirp(path.dirname(dbLocationInOs));
643
+ }
644
+ }
645
+ //#endregion
646
+ databaseConfig = Models__NS__DatabaseConfig.from({
647
+ location: UtilsOs__NS__isElectron
648
+ ? dbLocationInOs
649
+ : `db-${this.contextName}.sqlite`,
650
+ type: 'sqljs',
651
+ recreateMode: 'DROP_DB+MIGRATIONS',
652
+ logging: this.logDb,
653
+ });
654
+ break;
655
+ //#endregion
656
+ //#region resolve database config for mode backend-frontend(websql)
657
+ case 'backend-frontend(websql-electron)':
658
+ case 'backend-frontend(websql)':
659
+ let keepWebsqlDbDataAfterReload = false;
660
+ /* */
661
+ /* */
662
+ /* */
663
+ databaseConfig = databaseConfig = Models__NS__DatabaseConfig.from({
664
+ location: `db-${this.contextName}.sqlite`,
665
+ type: 'sqljs',
666
+ useLocalForage: true, // !!window['localforage'], // TODO this need to be checked in runtime
667
+ recreateMode: keepWebsqlDbDataAfterReload
668
+ ? 'PRESERVE_DATA+MIGRATIONS'
669
+ : 'DROP_DB+MIGRATIONS',
670
+ logging: this.logDb,
671
+ });
672
+ break;
673
+ //#endregion
674
+ //#region resolve database config for mode backend-frontend(tcp+udp)
675
+ case 'backend-frontend(tcp+udp)':
676
+ databaseConfig = Models__NS__DatabaseConfig.from({
677
+ database: `context-db-${this.contextName}`,
678
+ location: tcpUdpDatabaseSqliteRelativeFileLocation,
679
+ type: 'sqljs',
680
+ recreateMode: 'DROP_DB+MIGRATIONS',
681
+ logging: this.logDb,
682
+ });
683
+ break;
684
+ //#endregion
685
+ }
686
+ //#endregion
687
+ }
688
+ return databaseConfig.databaseConfigTypeORM;
533
689
  //#endregion
534
- //#region resolve database config for mode backend-frontend(tcp+udp)
535
- case "backend-frontend(tcp+udp)":
536
- databaseConfig = Models__NS__DatabaseConfig.from({
537
- database: `context-db-${this.contextName}`,
538
- location: tcpUdpDatabaseSqliteRelativeFileLocation,
539
- type: "sqljs",
540
- recreateMode: "DROP_DB+MIGRATIONS",
541
- logging: this.logDb
542
- });
543
- break;
544
- }
545
- }
546
- return databaseConfig.databaseConfigTypeORM;
547
- }
548
- //#endregion
549
- //#region methods & getters / start server
550
- async startServer() {
551
- if (this.isRemoteHost || this.isRunOrRevertOnlyMigrationAppStart) {
552
- return;
553
- }
554
- if (this.mode === "backend-frontend(tcp+udp)") {
555
- return await new Promise((resolve) => {
556
- if (this.isRunningInsideDocker) {
557
- this.serverTcpUdp.listen(Number(this.uriPort), "0.0.0.0", () => {
558
- this.logFramework && Helpers__NS__log(
559
- `[ctx=${this.contextName}] Express server (inside docker) started 0.0.0.0:${this.uriPort}`
560
- );
561
- this.logFramework && Helpers__NS__log(`[taon][express-server]listening on port: ${this.uriPort}, hostname: ${this.uriPathname},
690
+ }
691
+ //#endregion
692
+ //#region methods & getters / start server
693
+ async startServer() {
694
+ //#region @backendFunc
695
+ if (this.isRemoteHost || this.isRunOrRevertOnlyMigrationAppStart) {
696
+ return;
697
+ }
698
+ if (this.mode === 'backend-frontend(tcp+udp)') {
699
+ return await new Promise(resolve => {
700
+ if (this.isRunningInsideDocker) {
701
+ // this.displayRoutes(this.expressApp);
702
+ this.serverTcpUdp.listen(Number(this.uriPort), '0.0.0.0', () => {
703
+ this.logFramework &&
704
+ Helpers__NS__log(`[ctx=${this.contextName}] Express server (inside docker) started 0.0.0.0:${this.uriPort}`);
705
+ this.logFramework &&
706
+ Helpers__NS__log(`[taon][express-server]listening on port: ${this.uriPort}, hostname: ${this.uriPathname},
562
707
  address: ${this.uriProtocol}//localhost:${this.uriPort}${this.uriPathname}
563
708
  ExpressJS mode: ${this.expressApp.settings.env}
564
709
  `);
565
- resolve(void 0);
566
- });
567
- } else {
568
- this.serverTcpUdp.listen(Number(this.uriPort), () => {
569
- this.logFramework && Helpers__NS__log(
570
- `[ctx=${this.contextName}] Express server (inside nodejs app) started on localhost:${this.uriPort}`
571
- );
572
- this.logFramework && Helpers__NS__log(`[taon][express-server]listening on port: ${this.uriPort}, hostname: ${this.uriPathname},
710
+ resolve(void 0);
711
+ });
712
+ }
713
+ else {
714
+ // this.displayRoutes(this.expressApp);
715
+ this.serverTcpUdp.listen(Number(this.uriPort), () => {
716
+ this.logFramework &&
717
+ Helpers__NS__log(`[ctx=${this.contextName}] Express server (inside nodejs app) started on localhost:${this.uriPort}`);
718
+ this.logFramework &&
719
+ Helpers__NS__log(`[taon][express-server]listening on port: ${this.uriPort}, hostname: ${this.uriPathname},
573
720
  address: ${this.uriProtocol}//localhost:${this.uriPort}${this.uriPathname}
574
721
  expressJS mode: ${this.expressApp.settings.env}
575
722
  `);
576
- resolve(void 0);
577
- });
578
- }
579
- });
580
- } else {
581
- this.logFramework && Helpers__NS__info("Ipc communication enable instead tcp/upd");
582
- }
583
- }
584
- //#endregion
585
- //#region methods & getters / display express routes
586
- displayRoutes(app) {
587
- const routes = [];
588
- app._router?.stack.forEach(function(middleware) {
589
- if (middleware.route) {
590
- const methods = [];
591
- for (let method in middleware.route.methods) {
592
- if (middleware.route.methods[method]) {
593
- methods.push(method.toUpperCase());
594
- }
595
- }
596
- routes.push({ path: middleware.route.path, methods });
597
- } else if (middleware.name === "router") {
598
- middleware.handle.stack.forEach(function(handler) {
599
- const methods = [];
600
- for (let method in handler.route.methods) {
601
- if (handler.route.methods[method]) {
602
- methods.push(method.toUpperCase());
723
+ resolve(void 0);
724
+ });
725
+ }
726
+ });
727
+ }
728
+ else {
729
+ this.logFramework &&
730
+ Helpers__NS__info('Ipc communication enable instead tcp/upd');
731
+ }
732
+ //#endregion
733
+ }
734
+ //#endregion
735
+ //#region methods & getters / display express routes
736
+ displayRoutes(app) {
737
+ //#region @backend
738
+ const routes = [];
739
+ app._router?.stack.forEach(function (middleware) {
740
+ if (middleware.route) {
741
+ // routes registered directly on the app
742
+ const methods = [];
743
+ for (let method in middleware.route.methods) {
744
+ if (middleware.route.methods[method]) {
745
+ methods.push(method.toUpperCase());
746
+ }
747
+ }
748
+ routes.push({ path: middleware.route.path, methods: methods });
749
+ }
750
+ else if (middleware.name === 'router') {
751
+ // router middleware
752
+ middleware.handle.stack.forEach(function (handler) {
753
+ const methods = [];
754
+ for (let method in handler.route.methods) {
755
+ if (handler.route.methods[method]) {
756
+ methods.push(method.toUpperCase());
757
+ }
758
+ }
759
+ routes.push({ path: handler.route.path, methods: methods });
760
+ });
603
761
  }
604
- }
605
- routes.push({ path: handler.route.path, methods });
606
762
  });
607
- }
608
- });
609
- console.log(routes);
610
- }
611
- //#endregion
612
- //#region methods & getters / mode allows database creation
613
- get modeAllowsDatabaseCreation() {
614
- return this.mode === "backend-frontend(tcp+udp)" || this.mode === "backend-frontend(websql)" || this.mode === "backend-frontend(ipc-electron)";
615
- }
616
- //#endregion
617
- //#region methods & getters / clone class
618
- cloneClassWithNewMetadata = ({
619
- TaonBaseClass,
620
- className,
621
- config: config2,
622
- ctx,
623
- classType
624
- }) => {
625
- const cloneClass = () => {
626
- if (TaonBaseClass[Symbols__NS__fullClassNameStaticProperty] === `${ctx.contextName}.${className}`) {
627
- return TaonBaseClass;
628
- }
629
- return class extends TaonBaseClass {
630
- // static ['_'] = TaonBaseClass['_'];
631
- // @ts-ignore
632
- static [Symbols__NS__orignalClass] = TaonBaseClass;
633
- // @ts-ignore
634
- static [Symbols__NS__fullClassNameStaticProperty] = `${ctx.contextName}.${className}`;
635
- // @ts-ignore
636
- static [Symbols__NS__classNameStaticProperty] = className;
637
- static [Symbols__NS__ctxInClassOrClassObj] = ctx;
638
- // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
639
- static __getFullPathForClass__(arr = []) {
640
- const name = this[Symbols__NS__fullClassNameStaticProperty];
641
- arr.push(name);
642
- if (this[Symbols__NS__orignalClass] && // @ts-ignore
643
- this[Symbols__NS__orignalClass].__getFullPathForClass__) {
644
- this[Symbols__NS__orignalClass].__getFullPathForClass__(arr);
645
- }
646
- return arr.join("/");
647
- }
648
- static get fullPathForClass() {
649
- return this.__getFullPathForClass__();
650
- }
651
- [Symbols__NS__ctxInClassOrClassObj] = ctx;
652
- // You can override prototype properties or methods here if needed
653
- // static properties override allowed
654
- };
655
- };
656
- const cloneClassFunction = cloneClass();
657
- return cloneClassFunction;
658
- };
659
- //#endregion
660
- //#region methods & getters / clone classes obj with new metadata
661
- // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
662
- cloneClassesObjWithNewMetadata = ({
663
- classesInput,
664
- config: config2,
665
- ctx,
666
- classType
667
- }) => {
668
- const classes = {};
669
- for (const key of Object.keys(classesInput || {})) {
670
- const TaonBaseClass = classesInput[key];
671
- if (!TaonBaseClass) {
672
- Helpers__NS__error(`Class ${key} is not defined in context ${ctx.contextName}
673
-
674
- Please check if you have correct import in context file
675
-
676
- `);
677
- }
678
- var className = Reflect.getMetadata(
679
- Symbols__NS__metadata.className,
680
- TaonBaseClass
681
- );
682
- className = className || key;
683
- TaonBaseClass[Symbols__NS__classNameStaticProperty] = className;
684
- const clonedClass = this.cloneClassWithNewMetadata({
685
- TaonBaseClass,
686
- className,
687
- config: config2,
688
- ctx,
689
- classType
690
- });
691
- classes[className] = clonedClass;
692
- }
693
- return classes;
694
- };
695
- //#endregion
696
- //#region methods & getters / get recursive classes from contexts
697
- async getRecrusiveClassesfromContextsObj(classType) {
698
- const arr = await this.getRecrusiveClassesfromContexts(classType);
699
- return arr.reduce((acc, c) => {
700
- acc[ClassHelpers__NS__getName(c)] = c;
701
- return acc;
702
- }, {});
703
- }
704
- async getRecrusiveClassesfromContexts(classType, arr = []) {
705
- const contexts = Object.values(this.config.contexts || {});
706
- for (const ctx of contexts) {
707
- const ref = await ctx.__ref();
708
- const classesInput = ref.getClassFunBy(classType);
709
- const clonedClasses = Object.values(
710
- this.cloneClassesObjWithNewMetadata({
711
- classesInput,
712
- config: this.config,
713
- ctx: this,
714
- classType
715
- })
716
- );
717
- clonedClasses.forEach((c) => arr.push(c));
718
- await ref.getRecrusiveClassesfromContexts(classType, arr);
719
- }
720
- return arr;
721
- }
722
- //#endregion
723
- //#region methods & getters / get class instances by class type
724
- getClassInstanceObjBy(classType) {
725
- return this.classInstancesByNameObj[classType];
726
- }
727
- //#endregion
728
- //#region methods & getters / get class instances arr
729
- getClassesInstancesArrBy(classType) {
730
- return this.objWithClassesInstancesArr[classType];
731
- }
732
- //#endregion
733
- //#region methods & getters / inject
734
- inject(ctor, options) {
735
- const className = ClassHelpers__NS__getName(ctor);
736
- const locaInstanceConstructorArgs = options.locaInstanceConstructorArgs || [];
737
- if (this.isCLassType(Models__NS__ClassType.REPOSITORY, ctor)) {
738
- options.localInstance = true;
739
- }
740
- if (options?.localInstance) {
741
- const ctxClassFn = this.getClassFunByClassName(className);
742
- let entityName = "";
743
- const entityFn = ___NS__first(locaInstanceConstructorArgs);
744
- const entity = entityFn && entityFn();
745
- entityName = entity && ClassHelpers__NS__getName(entity) || "";
746
- if (!options.contextClassInstance[this.localInstaceObjSymbol]) {
747
- options.contextClassInstance[this.localInstaceObjSymbol] = {};
748
- }
749
- const instanceKey = className + (entityName ? `.${entityName}` : "");
750
- const existed = options.contextClassInstance[this.localInstaceObjSymbol][instanceKey];
751
- if (existed) {
752
- return existed;
753
- }
754
- if (!ctxClassFn) {
755
- throw new Error(`Not able to inject "${className}" inside context "${this.contextName}"
763
+ console.log(routes);
764
+ //#endregion
765
+ }
766
+ //#endregion
767
+ //#region methods & getters / mode allows database creation
768
+ get modeAllowsDatabaseCreation() {
769
+ return (this.mode === 'backend-frontend(tcp+udp)' ||
770
+ this.mode === 'backend-frontend(websql)' ||
771
+ this.mode === 'backend-frontend(ipc-electron)');
772
+ }
773
+ //#endregion
774
+ //#region methods & getters / get recursive classes from contexts
775
+ async getRecrusiveClassesfromContextsObj(classType) {
776
+ const arr = await this.getRecrusiveClassesfromContexts(classType);
777
+ return arr.reduce((acc, c) => {
778
+ acc[ClassHelpers__NS__getName(c)] = c;
779
+ return acc;
780
+ }, {});
781
+ }
782
+ async getRecrusiveClassesfromContexts(classType, arr = []) {
783
+ const contexts = Object.values(this.config.contexts || {});
784
+ // console.log({
785
+ // contexts,
786
+ // });
787
+ for (const ctx of contexts) {
788
+ // console.log(`STARTING ${ctx.contextName}`);
789
+ const ref = await ctx.__ref();
790
+ // console.log(`CTX FROM ${ctx.contextName}`, ref.contextName);
791
+ const classesInput = ref.getClassFunBy(classType);
792
+ // console.log(`${ref.contextName} - ${classType}`, { classesInput });
793
+ const clonedClasses = Object.values(this.cloneClassesObjWithNewMetadata({
794
+ classesInput,
795
+ config: this.config,
796
+ ctx: this,
797
+ classType,
798
+ }));
799
+ // console.log(`${classType} clonedClasses`, clonedClasses);
800
+ clonedClasses.forEach(c => arr.push(c));
801
+ await ref.getRecrusiveClassesfromContexts(classType, arr);
802
+ }
803
+ return arr;
804
+ }
805
+ //#endregion
806
+ //#region methods & getters / get class instances by class type
807
+ getClassInstanceObjBy(classType) {
808
+ return this.classInstancesByNameObj[classType];
809
+ }
810
+ //#endregion
811
+ //#region methods & getters / get class instances arr
812
+ getClassesInstancesArrBy(classType) {
813
+ return this.objWithClassesInstancesArr[classType];
814
+ }
815
+ //#endregion
816
+ //#region methods & getters / inject
817
+ inject(ctor, options) {
818
+ const className = ClassHelpers__NS__getName(ctor);
819
+ const locaInstanceConstructorArgs = options.locaInstanceConstructorArgs || [];
820
+ if (this.isCLassType(Models__NS__ClassType.REPOSITORY, ctor)) {
821
+ options.localInstance = true;
822
+ }
823
+ if (options?.localInstance) {
824
+ const ctxClassFn = this.getClassFunByClassName(className);
825
+ let entityName = '';
826
+ // entity thing is only for repositories local repositories
827
+ // if (className === 'TaonBaseRepository') {
828
+ const entityFn = ___NS__first(locaInstanceConstructorArgs);
829
+ const entity = entityFn && entityFn();
830
+ entityName = (entity && ClassHelpers__NS__getName(entity)) || '';
831
+ // console.log(`entityName `, entityName);
832
+ // }
833
+ if (!options.contextClassInstance[this.localInstaceObjSymbol]) {
834
+ options.contextClassInstance[this.localInstaceObjSymbol] = {};
835
+ }
836
+ const instanceKey = className + (entityName ? `.${entityName}` : '');
837
+ const existed = options.contextClassInstance[this.localInstaceObjSymbol][instanceKey];
838
+ if (existed) {
839
+ // console.log(
840
+ // `EXISTED ${ClassHelpers__NS__getName(options.parentInstanceThatWillGetInjectedStuff)} Inject ${className} instanceKey "${instanceKey}"`,
841
+ // );
842
+ return existed;
843
+ }
844
+ // console.log(
845
+ // `NEW ${ClassHelpers__NS__getName(options.parentInstanceThatWillGetInjectedStuff)} Inject ${className} instanceKey "${instanceKey}"`,
846
+ // );
847
+ if (!ctxClassFn) {
848
+ throw new Error(`Not able to inject "${className}" inside context "${this.contextName}"
756
849
 
757
850
  Make sure they share the same context or import context where "${className}" is defined.
758
851
 
759
852
  `);
760
- }
761
- const injectedInstance = new ctxClassFn(
762
- ...locaInstanceConstructorArgs
763
- );
764
- options.contextClassInstance[this.localInstaceObjSymbol][instanceKey] = injectedInstance;
765
- return injectedInstance;
766
- }
767
- const contextScopeInstance = this.allClassesInstances[className];
768
- return contextScopeInstance;
769
- }
770
- /**
771
- * alias for inject
772
- */
773
- getInstanceBy(ctor) {
774
- return this.inject(ctor, {
775
- localInstance: false,
776
- parentInstanceThatWillGetInjectedStuff: this
777
- });
778
- }
779
- //#endregion
780
- //#region methods & getters / check if context initialized
781
- checkIfContextInitialized() {
782
- if (___NS__isUndefined(this.config)) {
783
- throw new Error(`Please check if your context has been initialized.
853
+ }
854
+ const injectedInstance = new ctxClassFn(...locaInstanceConstructorArgs);
855
+ options.contextClassInstance[this.localInstaceObjSymbol][instanceKey] =
856
+ injectedInstance;
857
+ // console.log(`injectedInstance `, existed)
858
+ return injectedInstance;
859
+ }
860
+ const contextScopeInstance = this.allClassesInstances[className];
861
+ // if (className === 'TopicController') {
862
+ // debugger;
863
+ // }
864
+ return contextScopeInstance;
865
+ }
866
+ /**
867
+ * alias for inject
868
+ */
869
+ getInstanceBy(ctor) {
870
+ // if (!!this.__contextForControllerInstanceAccess) {
871
+ // const className = ClassHelpers__NS__getName(ctor);
872
+ // const allControllers = this.getClassFunByArr(Models__NS__ClassType.CONTROLLER);
873
+ // // TODO QUICK_FIX cache controllers
874
+ // for (const ctrl of allControllers) {
875
+ // if (ClassHelpers__NS__getName(ctrl) === className) {
876
+ // // console.log('injecting from contextForControllerInstanceAcesss', className);
877
+ // return this.__contextForControllerInstanceAccess.inject(ctor, {
878
+ // localInstance: false,
879
+ // });
880
+ // }
881
+ // }
882
+ // }
883
+ return this.inject(ctor, {
884
+ localInstance: false,
885
+ parentInstanceThatWillGetInjectedStuff: this,
886
+ });
887
+ }
888
+ //#endregion
889
+ //#region methods & getters / check if context initialized
890
+ checkIfContextInitialized() {
891
+ if (___NS__isUndefined(this.config)) {
892
+ throw new Error(`Please check if your context has been initialized.
784
893
 
785
894
  // ...
786
895
  await Context.initialize();
@@ -788,1178 +897,1448 @@ class EndpointContext {
788
897
 
789
898
 
790
899
  `);
900
+ }
901
+ }
902
+ //#endregion
903
+ //#region methods & getters / get class function by class type name
904
+ getClassFunBy(classType) {
905
+ this.checkIfContextInitialized();
906
+ switch (classType) {
907
+ case Models__NS__ClassType.CONTROLLER:
908
+ return this.config.controllers;
909
+ case Models__NS__ClassType.ENTITY:
910
+ return this.config.entities;
911
+ case Models__NS__ClassType.PROVIDER:
912
+ return this.config.providers;
913
+ case Models__NS__ClassType.MIDDLEWARE:
914
+ return this.config.middlewares;
915
+ case Models__NS__ClassType.REPOSITORY:
916
+ return this.config.repositories;
917
+ case Models__NS__ClassType.SUBSCRIBER:
918
+ return this.config.subscribers;
919
+ case Models__NS__ClassType.MIGRATION:
920
+ return this.config.migrations;
921
+ }
922
+ }
923
+ isCLassType(classType, classFn) {
924
+ return !!this.getClassFunBy(classType)[ClassHelpers__NS__getName(classFn)];
925
+ }
926
+ /**
927
+ * Only for injectable types
928
+ * Only for classType: CONTROLLER, REPOSITORY, PROVIDER, MIDDLEWARES
929
+ */
930
+ getClassFunByClassName(className) {
931
+ for (const classTypeName of this.allTypesfromContexts) {
932
+ const classesForInjectableType = this.config[Models__NS__ClassTypeKey[classTypeName]];
933
+ if (classesForInjectableType[className]) {
934
+ return classesForInjectableType[className];
935
+ }
936
+ }
937
+ }
938
+ getClassFunByClass(classFunction) {
939
+ const className = ClassHelpers__NS__getName(classFunction);
940
+ return this.getClassFunByClassName(className);
941
+ }
942
+ getClassFunByArr(classType) {
943
+ return Object.values(this.getClassFunBy(classType) || {});
944
+ }
945
+ //#endregion
946
+ //#region methods & getters / create class instances
947
+ async createInstances(classes, classType) {
948
+ // const recrusiveValuesFromContext =
949
+ // await this.getRecrusiveClassesfromContexts(classType);
950
+ // console.log(this.config.contexts);
951
+ // console.log('recrusiveValuesFromContext', recrusiveValuesFromContext);
952
+ for (const classFn of [
953
+ // ...recrusiveValuesFromContext,
954
+ ...Object.values(classes),
955
+ ]) {
956
+ const instance = DITaonContainer.resolve(classFn);
957
+ const classInstancesByNameObj = this.classInstancesByNameObj[classType];
958
+ const className = ClassHelpers__NS__getName(classFn);
959
+ // console.log({ classFn, classType, instance, place, className, 'classInstancesByNameObj': this.classInstancesByNameObj });
960
+ classInstancesByNameObj[className] = instance;
961
+ // update config
962
+ this.config[Models__NS__ClassTypeKey[classType]][className] = classFn;
963
+ this.objWithClassesInstancesArr[classType].push(instance);
964
+ this.allClassesInstances[className] = instance;
965
+ }
966
+ }
967
+ //#endregion
968
+ //#region methods & getters / init classes
969
+ async initClasses() {
970
+ if (this.isRemoteHost) {
971
+ return;
972
+ }
973
+ //#region @websql
974
+ for (const classFun of this.getClassFunByArr(Models__NS__ClassType.ENTITY)) {
975
+ const repo = (await this.connection.getRepository(ClassHelpers__NS__getOrginalClass(classFun)));
976
+ this.repos.set(ClassHelpers__NS__getName(classFun), repo);
977
+ }
978
+ //#endregion
979
+ for (const classTypeName of [
980
+ Models__NS__ClassType.MIDDLEWARE,
981
+ Models__NS__ClassType.PROVIDER,
982
+ Models__NS__ClassType.REPOSITORY,
983
+ Models__NS__ClassType.CONTROLLER,
984
+ Models__NS__ClassType.ENTITY,
985
+ Models__NS__ClassType.MIGRATION,
986
+ ]) {
987
+ //#region init class static _ property
988
+ for (const classFun of this.getClassFunByArr(classTypeName)) {
989
+ if (___NS__isFunction(classFun._)) {
990
+ await classFun._();
991
+ }
992
+ }
993
+ //#endregion
994
+ }
995
+ for (const classTypeName of [
996
+ Models__NS__ClassType.MIDDLEWARE,
997
+ Models__NS__ClassType.PROVIDER,
998
+ Models__NS__ClassType.REPOSITORY,
999
+ Models__NS__ClassType.CONTROLLER,
1000
+ Models__NS__ClassType.MIGRATION,
1001
+ ]) {
1002
+ //#region init providers, repositories _ property
1003
+ // Helpers__NS__taskStarted(
1004
+ // `[taon] REINITING _ INS FN ${classTypeName} ${this.contextName} STARTED`,
1005
+ // );
1006
+ for (const ctrl of this.getClassesInstancesArrBy(classTypeName)) {
1007
+ if (___NS__isFunction(ctrl._)) {
1008
+ await ctrl._();
1009
+ }
1010
+ }
1011
+ // Helpers__NS__taskStarted(
1012
+ // `[taon] REINITING _ INS FN ${classTypeName} ${this.contextName} DONE`,
1013
+ // );
1014
+ //#endregion
1015
+ }
1016
+ }
1017
+ //#endregion
1018
+ //#region methods & getters / is active on
1019
+ isActiveOn(classInstance) {
1020
+ let contextRef = classInstance[Symbols__NS__ctxInClassOrClassObj];
1021
+ return this === contextRef;
1022
+ }
1023
+ //#endregion
1024
+ //#region methods & getters / uri
1025
+ get frontendHostUri() {
1026
+ const url = this.config?.frontendHost?.startsWith('http')
1027
+ ? this.config.frontendHost
1028
+ : `${globalThis?.location?.protocol || 'http:'}//${this.config?.frontendHost}`;
1029
+ const uri = new URL(url.replace(/\/$/, ''));
1030
+ return uri;
1031
+ }
1032
+ get uri() {
1033
+ const url = this.host ? new URL(this.host) : void 0;
1034
+ return url;
1035
+ }
1036
+ //#endregion
1037
+ //#region methods & getters / host uri protocol
1038
+ get uriProtocol() {
1039
+ return this.uri?.protocol;
1040
+ }
1041
+ //#endregion
1042
+ //#region methods & getters / host uri origin
1043
+ /**
1044
+ * Examples
1045
+ * http://localhost:3000
1046
+ * https://localhost (from localhost:80) *
1047
+ */
1048
+ get uriOrigin() {
1049
+ return this.uri?.origin;
1050
+ }
1051
+ //#endregion
1052
+ //#region methods & getters / host uri pathname
1053
+ /**
1054
+ * Exampels
1055
+ * http://localhost:3000/path/to/somewhere
1056
+ * https://localhost/path/to/somewhere (from localhost:80)
1057
+ */
1058
+ // get uriOriginWithPathname(): string | undefined {
1059
+ // return this.uri?.origin
1060
+ // ? this.uri?.origin + this.uriPathnameOrNothingIfRoot.replace(/\/$/, '')
1061
+ // : undefined;
1062
+ // }
1063
+ get uriPathname() {
1064
+ return this.uri?.pathname;
1065
+ }
1066
+ //#endregion
1067
+ //#region methods & getters / uri pathname or nothing if root
1068
+ /**
1069
+ * Examples
1070
+ * http://localhost:3000/path/to/somewhere -> '/path/to/somewhere'
1071
+ * http://localhost:3000 -> '' #
1072
+ * https://localhost/path/to/ -> '/path/to/somewhere' # remove last slash
1073
+ */
1074
+ get uriPathnameOrNothingIfRoot() {
1075
+ const isNonRootProperPathName = this.uri?.pathname && this.uri.pathname !== '/';
1076
+ return isNonRootProperPathName ? this.uri.pathname.replace(/\/$/, '') : '';
1077
+ }
1078
+ //#endregion
1079
+ //#region methods & getters / port from uri
1080
+ get uriPort() {
1081
+ if (!this.uri?.origin?.includes('localhost')) {
1082
+ return this.config?.hostPortNumber?.toString();
1083
+ }
1084
+ return this.uri?.port;
1085
+ }
1086
+ // TODO do i need 2 getters for port?
1087
+ /**
1088
+ * Port from uri as number
1089
+ * @returns {Number | undefined}
1090
+ */
1091
+ get port() {
1092
+ return this.uri?.port ? Number(this.uriPort) : undefined;
1093
+ }
1094
+ //#endregion
1095
+ //#region methods & getters / is https server
1096
+ get isHttpServer() {
1097
+ return this.uriProtocol === 'https:';
1098
+ }
1099
+ //#endregion
1100
+ //#region methods & getters / is remote host
1101
+ /**
1102
+ * Check if context is for remote only
1103
+ */
1104
+ get isRemoteHost() {
1105
+ return !!this.cloneOptions?.useAsRemoteContext;
1106
+ }
1107
+ //#endregion
1108
+ //#region methods & getters / context name
1109
+ /**
1110
+ * ipc/udp needs this
1111
+ */
1112
+ get contextName() {
1113
+ // console.log(this.originalConfig);
1114
+ return this.config?.contextName || this.originalConfig?.contextName;
1115
+ }
1116
+ //#endregion
1117
+ //#region methods & getters / context name for communication
1118
+ /**
1119
+ * ipc/udp needs this
1120
+ */
1121
+ get contextNameForCommunication() {
1122
+ let contextName = this.contextName;
1123
+ if (this.isRemoteHost) {
1124
+ if (this.sourceContext?.contextName) {
1125
+ contextName = this.sourceContext?.contextName;
1126
+ }
1127
+ else {
1128
+ // console.log(
1129
+ // `CANT GET SOURCE CONTEXT NAME FOR REMOTE CONTEXT ${this.contextName}`,
1130
+ // );
1131
+ }
1132
+ }
1133
+ return contextName;
1134
+ }
1135
+ //#endregion
1136
+ //#region methods & getters / get context type
1137
+ /**
1138
+ * Check context type
1139
+ */
1140
+ get contextType() {
1141
+ if (this.config.abstract) {
1142
+ return 'abstract';
1143
+ }
1144
+ if (this.host) {
1145
+ return this.isRemoteHost ? 'remote' : 'normal';
1146
+ }
1147
+ return 'invalid';
1148
+ }
1149
+ //#endregion
1150
+ //#region methods & getters / current working directory
1151
+ get cwd() {
1152
+ return this.config.cwd || process.cwd();
1153
+ }
1154
+ //#endregion
1155
+ //#region methods & getters / active context
1156
+ get activeContext() {
1157
+ return this.config.activeContext || null;
1158
+ }
1159
+ //#endregion
1160
+ //#region methods & getters / app id
1161
+ get appId() {
1162
+ return this.config.appId;
1163
+ }
1164
+ //#endregion
1165
+ //#region methods & getters / public assets
1166
+ get publicAssets() {
1167
+ return this.config?.publicAssets || [];
1168
+ }
1169
+ //#endregion
1170
+ //#region methods & getters / is production mode
1171
+ get isProductionMode() {
1172
+ return this.config.productionMode;
1173
+ }
1174
+ //#endregion
1175
+ //#region methods & getters / host
1176
+ get host() {
1177
+ return this.config.host;
1178
+ }
1179
+ //#endregion
1180
+ //#region methods & getters / origin
1181
+ get origin() {
1182
+ return this.uri?.origin;
1183
+ }
1184
+ //#endregion
1185
+ //#region methods & getters / init subscribers
1186
+ async initSubscribers() {
1187
+ //#region @websqlFunc
1188
+ if (this.isRemoteHost) {
1189
+ return;
1190
+ }
1191
+ const subscriberClasses = this.getClassFunByArr(Models__NS__ClassType.SUBSCRIBER);
1192
+ for (const subscriberClassFn of subscriberClasses) {
1193
+ const options = Reflect.getMetadata(Symbols__NS__metadata.options.subscriber, subscriberClassFn);
1194
+ // console.log('subscriber options', options);
1195
+ // const nameForSubscriber = ClassHelpers__NS__getName(subscriber);
1196
+ EventSubscriber()(subscriberClassFn);
1197
+ }
1198
+ //#endregion
1199
+ }
1200
+ //#endregion
1201
+ //#region methods & getters / init entities
1202
+ async initEntities() {
1203
+ //#region @websql
1204
+ if (this.isRemoteHost) {
1205
+ return;
1206
+ }
1207
+ const entities = this.getClassFunByArr(Models__NS__ClassType.ENTITY);
1208
+ for (const entity of entities) {
1209
+ const options = Reflect.getMetadata(Symbols__NS__metadata.options.entity, entity);
1210
+ const createTable = ___NS__isUndefined(options.createTable)
1211
+ ? true
1212
+ : options.createTable;
1213
+ const nameForEntity = ClassHelpers__NS__getName(entity);
1214
+ if (createTable) {
1215
+ this.logDb &&
1216
+ console.info(`[taon][typeorm] create table for entity "${nameForEntity}" ? '${createTable}'`);
1217
+ // console.log('TypeormEntity', { TypeormEntity });
1218
+ TypeormEntity(nameForEntity)(entity);
1219
+ }
1220
+ else {
1221
+ this.logDb &&
1222
+ console.info(`[taon][typeorm] create table for entity "${nameForEntity}" ? '${createTable}'`);
1223
+ }
1224
+ }
1225
+ //#endregion
1226
+ }
1227
+ //#endregion
1228
+ //#region methods & getters / destroy
1229
+ async destroy() {
1230
+ //#region @websqlFunc
1231
+ if (this.connection) {
1232
+ await this.connection?.destroy();
1233
+ delete this.connection;
1234
+ }
1235
+ if (this.serverTcpUdp) {
1236
+ await new Promise(resolve => {
1237
+ this.serverTcpUdp?.close(() => {
1238
+ resolve(true);
1239
+ });
1240
+ });
1241
+ delete this.serverTcpUdp;
1242
+ }
1243
+ delete this.expressApp;
1244
+ //#endregion
791
1245
  }
792
- }
793
- //#endregion
794
- //#region methods & getters / get class function by class type name
795
- getClassFunBy(classType) {
796
- this.checkIfContextInitialized();
797
- switch (classType) {
798
- case Models__NS__ClassType.CONTROLLER:
799
- return this.config.controllers;
800
- case Models__NS__ClassType.ENTITY:
801
- return this.config.entities;
802
- case Models__NS__ClassType.PROVIDER:
803
- return this.config.providers;
804
- case Models__NS__ClassType.MIDDLEWARE:
805
- return this.config.middlewares;
806
- case Models__NS__ClassType.REPOSITORY:
807
- return this.config.repositories;
808
- case Models__NS__ClassType.SUBSCRIBER:
809
- return this.config.subscribers;
810
- case Models__NS__ClassType.MIGRATION:
811
- return this.config.migrations;
812
- }
813
- }
814
- isCLassType(classType, classFn) {
815
- return !!this.getClassFunBy(classType)[ClassHelpers__NS__getName(classFn)];
816
- }
817
- /**
818
- * Only for injectable types
819
- * Only for classType: CONTROLLER, REPOSITORY, PROVIDER, MIDDLEWARES
820
- */
821
- getClassFunByClassName(className) {
822
- for (const classTypeName of this.allTypesfromContexts) {
823
- const classesForInjectableType = this.config[Models__NS__ClassTypeKey[classTypeName]];
824
- if (classesForInjectableType[className]) {
825
- return classesForInjectableType[className];
826
- }
827
- }
828
- }
829
- getClassFunByClass(classFunction) {
830
- const className = ClassHelpers__NS__getName(classFunction);
831
- return this.getClassFunByClassName(className);
832
- }
833
- getClassFunByArr(classType) {
834
- return Object.values(this.getClassFunBy(classType) || {});
835
- }
836
- //#endregion
837
- //#region methods & getters / create class instances
838
- async createInstances(classes, classType) {
839
- for (const classFn of [
840
- // ...recrusiveValuesFromContext,
841
- ...Object.values(classes)
842
- ]) {
843
- const instance = DITaonContainer.resolve(classFn);
844
- const classInstancesByNameObj = this.classInstancesByNameObj[classType];
845
- const className = ClassHelpers__NS__getName(classFn);
846
- classInstancesByNameObj[className] = instance;
847
- this.config[Models__NS__ClassTypeKey[classType]][className] = classFn;
848
- this.objWithClassesInstancesArr[classType].push(instance);
849
- this.allClassesInstances[className] = instance;
850
- }
851
- }
852
- //#endregion
853
- //#region methods & getters / init classes
854
- async initClasses() {
855
- if (this.isRemoteHost) {
856
- return;
857
- }
858
- for (const classFun of this.getClassFunByArr(
859
- Models__NS__ClassType.ENTITY
860
- )) {
861
- const repo = await this.connection.getRepository(
862
- ClassHelpers__NS__getOrginalClass(classFun)
863
- );
864
- this.repos.set(ClassHelpers__NS__getName(classFun), repo);
865
- }
866
- for (const classTypeName of [
867
- Models__NS__ClassType.MIDDLEWARE,
868
- Models__NS__ClassType.PROVIDER,
869
- Models__NS__ClassType.REPOSITORY,
870
- Models__NS__ClassType.CONTROLLER,
871
- Models__NS__ClassType.ENTITY,
872
- Models__NS__ClassType.MIGRATION
873
- ]) {
874
- for (const classFun of this.getClassFunByArr(classTypeName)) {
875
- if (___NS__isFunction(classFun._)) {
876
- await classFun._();
877
- }
878
- }
879
- }
880
- for (const classTypeName of [
881
- Models__NS__ClassType.MIDDLEWARE,
882
- Models__NS__ClassType.PROVIDER,
883
- Models__NS__ClassType.REPOSITORY,
884
- Models__NS__ClassType.CONTROLLER,
885
- Models__NS__ClassType.MIGRATION
886
- ]) {
887
- for (const ctrl of this.getClassesInstancesArrBy(classTypeName)) {
888
- if (___NS__isFunction(ctrl._)) {
889
- await ctrl._();
890
- }
891
- }
892
- }
893
- }
894
- //#endregion
895
- //#region methods & getters / is active on
896
- isActiveOn(classInstance) {
897
- let contextRef = classInstance[Symbols__NS__ctxInClassOrClassObj];
898
- return this === contextRef;
899
- }
900
- //#endregion
901
- //#region methods & getters / uri
902
- get frontendHostUri() {
903
- const url = this.config?.frontendHost?.startsWith("http") ? this.config.frontendHost : `${globalThis?.location?.protocol || "http:"}//${this.config?.frontendHost}`;
904
- const uri = new URL(url.replace(/\/$/, ""));
905
- return uri;
906
- }
907
- get uri() {
908
- const url = this.host ? new URL(this.host) : void 0;
909
- return url;
910
- }
911
- //#endregion
912
- //#region methods & getters / host uri protocol
913
- get uriProtocol() {
914
- return this.uri?.protocol;
915
- }
916
- //#endregion
917
- //#region methods & getters / host uri origin
918
- /**
919
- * Examples
920
- * http://localhost:3000
921
- * https://localhost (from localhost:80) *
922
- */
923
- get uriOrigin() {
924
- return this.uri?.origin;
925
- }
926
- //#endregion
927
- //#region methods & getters / host uri pathname
928
- /**
929
- * Exampels
930
- * http://localhost:3000/path/to/somewhere
931
- * https://localhost/path/to/somewhere (from localhost:80)
932
- */
933
- // get uriOriginWithPathname(): string | undefined {
934
- // return this.uri?.origin
935
- // ? this.uri?.origin + this.uriPathnameOrNothingIfRoot.replace(/\/$/, '')
936
- // : undefined;
937
- // }
938
- get uriPathname() {
939
- return this.uri?.pathname;
940
- }
941
- //#endregion
942
- //#region methods & getters / uri pathname or nothing if root
943
- /**
944
- * Examples
945
- * http://localhost:3000/path/to/somewhere -> '/path/to/somewhere'
946
- * http://localhost:3000 -> '' #
947
- * https://localhost/path/to/ -> '/path/to/somewhere' # remove last slash
948
- */
949
- get uriPathnameOrNothingIfRoot() {
950
- const isNonRootProperPathName = this.uri?.pathname && this.uri.pathname !== "/";
951
- return isNonRootProperPathName ? this.uri.pathname.replace(/\/$/, "") : "";
952
- }
953
- //#endregion
954
- //#region methods & getters / port from uri
955
- get uriPort() {
956
- if (!this.uri?.origin?.includes("localhost")) {
957
- return this.config?.hostPortNumber?.toString();
958
- }
959
- return this.uri?.port;
960
- }
961
- // TODO do i need 2 getters for port?
962
- /**
963
- * Port from uri as number
964
- * @returns {Number | undefined}
965
- */
966
- get port() {
967
- return this.uri?.port ? Number(this.uriPort) : void 0;
968
- }
969
- //#endregion
970
- //#region methods & getters / is https server
971
- get isHttpServer() {
972
- return this.uriProtocol === "https:";
973
- }
974
- //#endregion
975
- //#region methods & getters / is remote host
976
- /**
977
- * Check if context is for remote only
978
- */
979
- get isRemoteHost() {
980
- return !!this.cloneOptions?.useAsRemoteContext;
981
- }
982
- //#endregion
983
- //#region methods & getters / context name
984
- /**
985
- * ipc/udp needs this
986
- */
987
- get contextName() {
988
- return this.config?.contextName || this.originalConfig?.contextName;
989
- }
990
- //#endregion
991
- //#region methods & getters / context name for communication
992
- /**
993
- * ipc/udp needs this
994
- */
995
- get contextNameForCommunication() {
996
- let contextName = this.contextName;
997
- if (this.isRemoteHost) {
998
- if (this.sourceContext?.contextName) {
999
- contextName = this.sourceContext?.contextName;
1000
- } else {
1001
- }
1002
- }
1003
- return contextName;
1004
- }
1005
- //#endregion
1006
- //#region methods & getters / get context type
1007
- /**
1008
- * Check context type
1009
- */
1010
- get contextType() {
1011
- if (this.config.abstract) {
1012
- return "abstract";
1013
- }
1014
- if (this.host) {
1015
- return this.isRemoteHost ? "remote" : "normal";
1016
- }
1017
- return "invalid";
1018
- }
1019
- //#endregion
1020
- //#region methods & getters / current working directory
1021
- get cwd() {
1022
- return this.config.cwd || process.cwd();
1023
- }
1024
- //#endregion
1025
- //#region methods & getters / active context
1026
- get activeContext() {
1027
- return this.config.activeContext || null;
1028
- }
1029
- //#endregion
1030
- //#region methods & getters / app id
1031
- get appId() {
1032
- return this.config.appId;
1033
- }
1034
- //#endregion
1035
- //#region methods & getters / public assets
1036
- get publicAssets() {
1037
- return this.config?.publicAssets || [];
1038
- }
1039
- //#endregion
1040
- //#region methods & getters / is production mode
1041
- get isProductionMode() {
1042
- return this.config.productionMode;
1043
- }
1044
- //#endregion
1045
- //#region methods & getters / host
1046
- get host() {
1047
- return this.config.host;
1048
- }
1049
- //#endregion
1050
- //#region methods & getters / origin
1051
- get origin() {
1052
- return this.uri?.origin;
1053
- }
1054
- //#endregion
1055
- //#region methods & getters / init subscribers
1056
- async initSubscribers() {
1057
- if (this.isRemoteHost) {
1058
- return;
1059
- }
1060
- const subscriberClasses = this.getClassFunByArr(
1061
- Models__NS__ClassType.SUBSCRIBER
1062
- );
1063
- for (const subscriberClassFn of subscriberClasses) {
1064
- const options = Reflect.getMetadata(
1065
- Symbols__NS__metadata.options.subscriber,
1066
- subscriberClassFn
1067
- );
1068
- EventSubscriber()(subscriberClassFn);
1069
- }
1070
- }
1071
- //#endregion
1072
- //#region methods & getters / init entities
1073
- async initEntities() {
1074
- if (this.isRemoteHost) {
1075
- return;
1076
- }
1077
- const entities = this.getClassFunByArr(Models__NS__ClassType.ENTITY);
1078
- for (const entity of entities) {
1079
- const options = Reflect.getMetadata(
1080
- Symbols__NS__metadata.options.entity,
1081
- entity
1082
- );
1083
- const createTable = ___NS__isUndefined(options.createTable) ? true : options.createTable;
1084
- const nameForEntity = ClassHelpers__NS__getName(entity);
1085
- if (createTable) {
1086
- this.logDb && console.info(
1087
- `[taon][typeorm] create table for entity "${nameForEntity}" ? '${createTable}'`
1088
- );
1089
- TypeormEntity(nameForEntity)(entity);
1090
- } else {
1091
- this.logDb && console.info(
1092
- `[taon][typeorm] create table for entity "${nameForEntity}" ? '${createTable}'`
1093
- );
1094
- }
1095
- }
1096
- }
1097
- //#endregion
1098
- //#region methods & getters / destroy
1099
- async destroy() {
1100
- if (this.connection) {
1101
- await this.connection?.destroy();
1102
- delete this.connection;
1103
- }
1104
- if (this.serverTcpUdp) {
1105
- await new Promise((resolve) => {
1106
- this.serverTcpUdp?.close(() => {
1107
- resolve(true);
1246
+ //#endregion
1247
+ //#region methods & getters / init connection
1248
+ async initDatabaseConnection() {
1249
+ //#region @websqlFunc
1250
+ if (this.isRemoteHost || !this.databaseConfig) {
1251
+ return;
1252
+ }
1253
+ const entities = this.getClassFunByArr(Models__NS__ClassType.ENTITY).map(entityFn => {
1254
+ return ClassHelpers__NS__getOrginalClass(entityFn);
1108
1255
  });
1109
- });
1110
- delete this.serverTcpUdp;
1111
- }
1112
- delete this.expressApp;
1113
- }
1114
- //#endregion
1115
- //#region methods & getters / init connection
1116
- async initDatabaseConnection() {
1117
- if (this.isRemoteHost || !this.databaseConfig) {
1118
- return;
1119
- }
1120
- const entities = this.getClassFunByArr(Models__NS__ClassType.ENTITY).map(
1121
- (entityFn) => {
1122
- return ClassHelpers__NS__getOrginalClass(entityFn);
1123
- }
1124
- );
1125
- const subscribers = this.getClassFunByArr(Models__NS__ClassType.SUBSCRIBER);
1126
- let autoSave = false;
1127
- if (!___NS__isNil(this.databaseConfig.autoSave)) {
1128
- autoSave = this.databaseConfig.autoSave;
1129
- } else {
1130
- if (this.USE_MARIADB_MYSQL_IN_DOCKER) {
1131
- autoSave = !this.isRunningInsideDocker;
1132
- } else {
1133
- autoSave = true;
1134
- }
1135
- }
1136
- const dataSourceDbConfig = ___NS__isObject(this.databaseConfig) ? {
1137
- type: this.databaseConfig.type,
1138
- port: this.databaseConfig.databasePort,
1139
- host: this.databaseConfig.databaseHost,
1140
- database: this.databaseConfig.database,
1141
- username: this.databaseConfig.databaseUsername,
1142
- password: this.databaseConfig.databasePassword,
1143
- useLocalForage: this.databaseConfig.useLocalForage,
1144
- // I am not using typeorm migration system
1145
- entities,
1146
- subscribers,
1147
- synchronize: this.isRunOrRevertOnlyMigrationAppStart ? false : this.databaseConfig.synchronize,
1148
- autoSave,
1149
- dropSchema: this.isRunOrRevertOnlyMigrationAppStart ? false : this.databaseConfig.dropSchema,
1150
- logging: !!this.databaseConfig.logging,
1151
- location: this.databaseConfig.location
1152
- } : {};
1153
- this.logFramework && console.log(
1154
- `[Context: "${this.contextName}"] dataSourceDbConfig`,
1155
- dataSourceDbConfig
1156
- );
1157
- if (this.modeAllowsDatabaseCreation && this.databaseConfig) {
1158
- this.logDb && this.logFramework && Helpers__NS__info("[taon][database] prepare typeorm connection...");
1159
- try {
1160
- const connection = new DataSource(dataSourceDbConfig);
1161
- this.connection = connection;
1162
- await this.connection.initialize();
1163
- } catch (error) {
1164
- console.error(
1165
- `[taon][typeorm] Error while initializing connection for ${this.contextName}, ERROR STARTED `
1166
- );
1167
- console.error(error?.stack || "< No stack trace > ");
1168
- console.error(error?.message || error);
1169
- console.error(
1170
- `[taon][typeorm] Error while initializing connection for ${this.contextName}, ERROR ENDS `
1171
- );
1172
- }
1173
- if (!this.connection?.isInitialized) {
1174
- console.log("WRONG CONFIG", dataSourceDbConfig);
1175
- throw new Error(`Something wrong with connection init in ${this.mode}`);
1176
- process.exit(1);
1177
- }
1178
- if (this.logDb || this.logFramework) {
1179
- console.info(
1180
- `
1256
+ const subscribers = this.getClassFunByArr(Models__NS__ClassType.SUBSCRIBER);
1257
+ let autoSave = false;
1258
+ if (!___NS__isNil(this.databaseConfig.autoSave)) {
1259
+ autoSave = this.databaseConfig.autoSave;
1260
+ }
1261
+ else {
1262
+ if (this.USE_MARIADB_MYSQL_IN_DOCKER) {
1263
+ autoSave = !this.isRunningInsideDocker; // in docker I am using mysql or posgress
1264
+ }
1265
+ else {
1266
+ autoSave = true; // on docker with sqljs I need to save db
1267
+ }
1268
+ }
1269
+ const dataSourceDbConfig = ___NS__isObject(this.databaseConfig)
1270
+ ? {
1271
+ type: this.databaseConfig.type,
1272
+ port: this.databaseConfig.databasePort,
1273
+ host: this.databaseConfig.databaseHost,
1274
+ database: this.databaseConfig.database,
1275
+ username: this.databaseConfig.databaseUsername,
1276
+ password: this.databaseConfig.databasePassword,
1277
+ useLocalForage: this.databaseConfig.useLocalForage,
1278
+ // I am not using typeorm migration system
1279
+ entities,
1280
+ subscribers,
1281
+ synchronize: this.isRunOrRevertOnlyMigrationAppStart
1282
+ ? false
1283
+ : this.databaseConfig.synchronize,
1284
+ autoSave,
1285
+ dropSchema: this.isRunOrRevertOnlyMigrationAppStart
1286
+ ? false
1287
+ : this.databaseConfig.dropSchema,
1288
+ logging: !!this.databaseConfig.logging,
1289
+ location: this.databaseConfig.location,
1290
+ }
1291
+ : {};
1292
+ // debugger;
1293
+ this.logFramework &&
1294
+ console.log(`[Context: "${this.contextName}"] dataSourceDbConfig`, dataSourceDbConfig);
1295
+ if (this.modeAllowsDatabaseCreation && this.databaseConfig) {
1296
+ this.logDb &&
1297
+ this.logFramework &&
1298
+ Helpers__NS__info('[taon][database] prepare typeorm connection...');
1299
+ try {
1300
+ const connection = new DataSource(dataSourceDbConfig);
1301
+ this.connection = connection;
1302
+ await this.connection.initialize();
1303
+ }
1304
+ catch (error) {
1305
+ console.error(`[taon][typeorm] Error while initializing connection for ${this.contextName}, ERROR STARTED `);
1306
+ console.error(error?.stack || '< No stack trace > ');
1307
+ console.error(error?.message || error);
1308
+ console.error(`[taon][typeorm] Error while initializing connection for ${this.contextName}, ERROR ENDS `);
1309
+ }
1310
+ if (!this.connection?.isInitialized) {
1311
+ console.log('WRONG CONFIG', dataSourceDbConfig);
1312
+ throw new Error(`Something wrong with connection init in ${this.mode}`);
1313
+ //#region @backend
1314
+ process.exit(1);
1315
+ //#endregion
1316
+ }
1317
+ if (this.logDb || this.logFramework) {
1318
+ console.info(`
1181
1319
 
1182
1320
  CONTECTION OK for ${this.contextName} - ${this.mode}
1183
1321
 
1184
1322
  [taon][typeorm] db prepration done.. db initialize=${this.connection?.isInitialized}
1185
1323
 
1186
1324
 
1187
- `,
1188
- // dataSourceDbConfig,
1189
- { "this.connection": !!this.connection }
1190
- );
1191
- console.log(
1192
- `Database file location: ${this.connection.options.database}`
1193
- );
1194
- }
1195
- } else {
1196
- Helpers__NS__info(`[taon][typeorm] Not initing db for mode ${this.mode}`);
1197
- }
1198
- }
1199
- //#endregion
1200
- //#region methods & getters / initialize metadata
1201
- //#region methods & getters / update class calculate path
1202
- updateCalculatedPathsForControllers(rawConfigs, classConfig, controllerClassFn) {
1203
- const parentsCalculatedPath = ___NS__slice(rawConfigs, 1).reverse().map((bc) => {
1204
- if (TaonHelpers__NS__isGoodPath(bc.path)) {
1205
- return bc.path;
1206
- }
1207
- return bc.className;
1208
- }).join("/");
1209
- const contextNameForCommunication = this.contextNameForCommunication;
1210
- if (TaonHelpers__NS__isGoodPath(classConfig.path)) {
1211
- classConfig.calculatedPath = classConfig.path;
1212
- } else {
1213
- classConfig.calculatedPath = `${this.uriPathnameOrNothingIfRoot}/${apiPrefix}/${contextNameForCommunication}/tcp${parentsCalculatedPath}/${ClassHelpers__NS__getName(controllerClassFn)}`.replace(/\/\//g, "/").split("/").reduce((acc, bc) => {
1214
- return ___NS__last(acc) === bc ? acc : [...acc, bc];
1215
- }, []).join("/");
1216
- }
1217
- }
1218
- //#endregion
1219
- //#region methods & getters / dedupe class configs
1220
- mergeControllerMethodsConfigs(rawConfigs, classConfig, controllerClassFn) {
1221
- const currentControllerMethodsConfig = classConfig.methods;
1222
- ___NS__slice(rawConfigs, 1).forEach((bc) => {
1223
- const parentControllerMethods = ___NS__cloneDeep(bc.methods);
1224
- for (const methodsName in parentControllerMethods) {
1225
- if (parentControllerMethods.hasOwnProperty(methodsName)) {
1226
- if (!currentControllerMethodsConfig[methodsName]) {
1227
- const methodConfig = parentControllerMethods[methodsName];
1228
- currentControllerMethodsConfig[methodsName] = methodConfig;
1229
- }
1230
- }
1231
- }
1232
- });
1233
- }
1234
- //#endregion
1235
- async initControllersHook(ctxStorage) {
1236
- if (this.isRunOrRevertOnlyMigrationAppStart) {
1237
- return;
1238
- }
1239
- const allControllers = this.getClassFunByArr(Models__NS__ClassType.CONTROLLER);
1240
- for (const controllerClassFn of allControllers) {
1241
- const instance = this.getInstanceBy(
1242
- controllerClassFn
1243
- );
1244
- if (___NS__isFunction(instance.afterAllCtxInited)) {
1245
- await instance.afterAllCtxInited({ ctxStorage });
1246
- }
1247
- }
1248
- }
1249
- async initControllers() {
1250
- if (this.isRunOrRevertOnlyMigrationAppStart) {
1251
- return;
1252
- }
1253
- const allControllers = this.getClassFunByArr(Models__NS__ClassType.CONTROLLER);
1254
- for (const controllerClassFn of allControllers) {
1255
- controllerClassFn[Symbols__NS__classMethodsNames] = ClassHelpers__NS__getMethodsNames(controllerClassFn);
1256
- const rawConfigs = ClassHelpers__NS__getControllerConfigs(controllerClassFn);
1257
- const classConfig = rawConfigs[0];
1258
- this.updateCalculatedPathsForControllers(
1259
- rawConfigs,
1260
- classConfig,
1261
- controllerClassFn
1262
- );
1263
- this.mergeControllerMethodsConfigs(
1264
- rawConfigs,
1265
- classConfig,
1266
- controllerClassFn
1267
- );
1268
- classConfig.calculatedMiddlewaresControllerObj = {};
1269
- [...rawConfigs].reverse().forEach((rc) => {
1270
- if (___NS__isFunction(rc.middlewares)) {
1271
- classConfig.calculatedMiddlewaresControllerObj = rc.middlewares({
1272
- parentMiddlewares: classConfig.calculatedMiddlewaresControllerObj,
1273
- className(middlewareClass) {
1274
- return ClassHelpers__NS__getName(controllerClassFn);
1325
+ `,
1326
+ // dataSourceDbConfig,
1327
+ { 'this.connection': !!this.connection });
1328
+ console.log(`Database file location: ${this.connection.options.database}`);
1329
+ }
1330
+ // const entityMetadata = getMetadataArgsStorage();
1331
+ // console.log(
1332
+ // `
1333
+ // entityMetadata after connection init for ${this.contextName} - ${this.mode}
1334
+ // `,
1335
+ // entityMetadata,
1336
+ // );
1337
+ // debugger;
1338
+ }
1339
+ else {
1340
+ Helpers__NS__info(`[taon][typeorm] Not initing db for mode ${this.mode}`);
1341
+ }
1342
+ //#endregion
1343
+ }
1344
+ //#endregion
1345
+ //#region methods & getters / initialize metadata
1346
+ //#region methods & getters / update class calculate path
1347
+ updateCalculatedPathsForControllers(rawConfigs, classConfig, controllerClassFn) {
1348
+ const parentsCalculatedPath = ___NS__slice(rawConfigs, 1)
1349
+ .reverse()
1350
+ .map(bc => {
1351
+ if (TaonHelpers__NS__isGoodPath(bc.path)) {
1352
+ return bc.path;
1275
1353
  }
1276
- });
1277
- }
1278
- });
1279
- if (!UtilsOs__NS__isRunningInCliMode()) {
1280
- this.logHttp && console.groupCollapsed(
1281
- `[taon][express-server] routes [${classConfig.className}]`
1282
- );
1283
- }
1284
- const methodNames = Object.keys(classConfig.methods);
1285
- for (const methodName of methodNames) {
1286
- const methodConfig = classConfig.methods[methodName];
1287
- let calculatedMiddlewaresMethodObj = {};
1288
- [...rawConfigs].reverse().forEach((rc) => {
1289
- if (rc.methods[methodName]) {
1290
- const parentMethodConfig = rc.methods[methodName];
1291
- if (___NS__isFunction(parentMethodConfig.middlewares)) {
1292
- calculatedMiddlewaresMethodObj = parentMethodConfig.middlewares({
1293
- parentMiddlewares: calculatedMiddlewaresMethodObj,
1294
- className(middlewareClass) {
1295
- return ClassHelpers__NS__getName(controllerClassFn);
1354
+ return bc.className;
1355
+ })
1356
+ .join('/');
1357
+ const contextNameForCommunication = this.contextNameForCommunication;
1358
+ if (TaonHelpers__NS__isGoodPath(classConfig.path)) {
1359
+ classConfig.calculatedPath = classConfig.path;
1360
+ }
1361
+ else {
1362
+ classConfig.calculatedPath = (`${this.uriPathnameOrNothingIfRoot}` +
1363
+ `/${apiPrefix}/${contextNameForCommunication}/tcp${parentsCalculatedPath}/` +
1364
+ `${ClassHelpers__NS__getName(controllerClassFn)}`)
1365
+ .replace(/\/\//g, '/')
1366
+ .split('/')
1367
+ .reduce((acc, bc) => {
1368
+ return ___NS__last(acc) === bc ? acc : [...acc, bc];
1369
+ }, [])
1370
+ .join('/');
1371
+ }
1372
+ // console.log('calculatedPath', classConfig.calculatedPath);
1373
+ }
1374
+ //#endregion
1375
+ //#region methods & getters / dedupe class configs
1376
+ mergeControllerMethodsConfigs(rawConfigs, classConfig, controllerClassFn) {
1377
+ const currentControllerMethodsConfig = classConfig.methods;
1378
+ ___NS__slice(rawConfigs, 1).forEach(bc => {
1379
+ const parentControllerMethods = ___NS__cloneDeep(bc.methods);
1380
+ for (const methodsName in parentControllerMethods) {
1381
+ if (parentControllerMethods.hasOwnProperty(methodsName)) {
1382
+ if (!currentControllerMethodsConfig[methodsName]) {
1383
+ //#region add non existed method
1384
+ const methodConfig = parentControllerMethods[methodsName];
1385
+ currentControllerMethodsConfig[methodsName] = methodConfig;
1386
+ //#endregion
1387
+ }
1296
1388
  }
1297
- });
1298
1389
  }
1299
- }
1300
1390
  });
1301
- methodConfig.calculatedMiddlewaresMethodObj = {
1302
- ...calculatedMiddlewaresMethodObj,
1303
- ...classConfig.calculatedMiddlewaresControllerObj
1304
- };
1305
- methodConfig.calculatedMiddlewares = Object.values(
1306
- methodConfig.calculatedMiddlewaresMethodObj || {}
1307
- );
1308
- const httpMethodType = methodConfig.type;
1309
- const globalPathPart = this.isRunningInsideDocker || !this.frontendHostUri?.origin?.includes("localhost") ? `${this.uriPathnameOrNothingIfRoot.replace(
1310
- /\/$/,
1311
- ""
1312
- )}/${apiPrefix}/${this.contextName}`.replace(/\/\//, "/") : "";
1313
- const expressPath = methodConfig.global ? `${globalPathPart}/${methodConfig.path?.replace(
1314
- /\/$/,
1315
- ""
1316
- )}`.replace(/\/\//, "/") : TaonHelpers__NS__getExpressPath(classConfig, methodConfig);
1317
- if (UtilsOs__NS__isNode || UtilsOs__NS__isWebSQL) {
1318
- const route = this.initServer(
1319
- httpMethodType,
1320
- methodConfig,
1321
- classConfig,
1322
- expressPath,
1323
- controllerClassFn
1324
- );
1325
- this.activeRoutes.push({
1326
- expressPath: route.expressPath,
1327
- method: route.method
1328
- });
1329
- }
1330
- const shouldInitClient = UtilsOs__NS__isBrowser || this.isRemoteHost || UtilsOs__NS__isWebSQL;
1331
- if (shouldInitClient) {
1332
- await this.initClient(
1333
- controllerClassFn,
1334
- httpMethodType,
1335
- methodConfig,
1336
- expressPath
1337
- );
1338
- }
1339
- }
1340
- if (!UtilsOs__NS__isRunningInCliMode()) {
1341
- this.logHttp && console.groupEnd();
1342
- }
1343
- }
1344
- }
1345
- //#endregion
1346
- //#region methods & getters / write active routes
1347
- writeActiveRoutes() {
1348
- if (this.isRemoteHost || this.isRunOrRevertOnlyMigrationAppStart) {
1349
- return;
1350
- }
1351
- const troutes = Utils__NS__uniqArray(
1352
- this.activeRoutes.map((f) => {
1353
- return `${f.method} ${f.expressPath}`;
1354
- })
1355
- ).map((f) => {
1356
- const [method, expressPath] = f.split(" ");
1357
- return `
1358
- ### ${___NS__startCase(___NS__last(expressPath.split("/")))}
1359
- ` + TaonHelpers__NS__fillUpTo(method.toUpperCase() + " ", 10) + this.uriOrigin + expressPath;
1360
- });
1361
- const routes = [
1362
- ...["", `# ROUTES FOR HOST ${this.uriOrigin} `],
1363
- ...troutes
1364
- ].join("\n");
1365
- const fileName = crossPlatformPath([
1366
- //#region @backend
1367
- process.cwd(),
1368
- //#endregion
1369
- `routes/routes-${this.config.contextName}.rest`
1370
- ]);
1371
- this.logFramework && console.log(`[taon] routes file: ${fileName} `);
1372
- this.logRoutes && console.log(routes);
1373
- if (!UtilsOs__NS__isElectron && !this.skipWritingServerRoutes) {
1374
- Helpers__NS__writeFile(fileName, routes);
1375
- }
1376
- }
1377
- //#endregion
1378
- //#region methods & getters / middlewares
1379
- get middlewares() {
1380
- return this.config.middlewares || [];
1381
- }
1382
- //#endregion
1383
- //#region methods & getters / init middlewares
1384
- async initCustomClientMiddlewares() {
1385
- const middlewares = this.getClassesInstancesArrBy(
1386
- Models__NS__ClassType.MIDDLEWARE
1387
- ).map((f) => f).filter((f) => ___NS__isFunction(f.interceptClient));
1388
- middlewares.forEach((middlewareInstanceName) => {
1389
- const contextName = this.contextName;
1390
- const interceptorName = `${contextName}-${ClassHelpers__NS__getName(
1391
- middlewareInstanceName
1392
- )}`;
1393
- Resource.request.interceptors.set(interceptorName, {
1394
- intercept: ({ req, next }) => {
1395
- const url = new URL(req.url);
1396
- if (url.pathname.startsWith(
1397
- `${this.uriPathnameOrNothingIfRoot}/${apiPrefix}/${contextName}/`
1398
- )) {
1399
- return middlewareInstanceName.interceptClient({
1400
- req,
1401
- next
1391
+ }
1392
+ //#endregion
1393
+ async initControllersHook(ctxStorage) {
1394
+ if (this.isRunOrRevertOnlyMigrationAppStart) {
1395
+ return;
1396
+ }
1397
+ const allControllers = this.getClassFunByArr(Models__NS__ClassType.CONTROLLER);
1398
+ for (const controllerClassFn of allControllers) {
1399
+ const instance = this.getInstanceBy(controllerClassFn);
1400
+ if (___NS__isFunction(instance.afterAllCtxInited)) {
1401
+ await instance.afterAllCtxInited({ ctxStorage });
1402
+ }
1403
+ }
1404
+ }
1405
+ async initControllers() {
1406
+ if (this.isRunOrRevertOnlyMigrationAppStart) {
1407
+ return;
1408
+ }
1409
+ const allControllers = this.getClassFunByArr(Models__NS__ClassType.CONTROLLER);
1410
+ // debugger
1411
+ // console.log('allControllers', allControllers);
1412
+ for (const controllerClassFn of allControllers) {
1413
+ // console.log(ClassHelpers__NS__getClassConfig(controllerClassFn));
1414
+ // const controllerName = ClassHelpers__NS__getName(controllerClassFn);
1415
+ // console.log(
1416
+ // `for ${controllerName}`,
1417
+ // ClassHelpers__NS__getClassConfig(controllerClassFn),
1418
+ // );
1419
+ controllerClassFn[Symbols__NS__classMethodsNames] =
1420
+ ClassHelpers__NS__getMethodsNames(controllerClassFn);
1421
+ const rawConfigs = ClassHelpers__NS__getControllerConfigs(controllerClassFn);
1422
+ // console.log(controllerName, { rawConfigs });
1423
+ // console.log(`Class config for ${ClassHelpers__NS__getName(controllerClassFn)}`, configs)
1424
+ const classConfig = rawConfigs[0];
1425
+ this.updateCalculatedPathsForControllers(rawConfigs, classConfig, controllerClassFn);
1426
+ this.mergeControllerMethodsConfigs(rawConfigs, classConfig, controllerClassFn);
1427
+ //#region combine middlewares from controllers
1428
+ classConfig.calculatedMiddlewaresControllerObj = {};
1429
+ [...rawConfigs].reverse().forEach(rc => {
1430
+ if (___NS__isFunction(rc.middlewares)) {
1431
+ classConfig.calculatedMiddlewaresControllerObj = rc.middlewares({
1432
+ parentMiddlewares: classConfig.calculatedMiddlewaresControllerObj,
1433
+ className(middlewareClass) {
1434
+ return ClassHelpers__NS__getName(controllerClassFn);
1435
+ },
1436
+ });
1437
+ }
1402
1438
  });
1403
- }
1404
- return next.handle(req);
1405
- }
1406
- });
1407
- });
1408
- }
1409
- async initCustomBackendMiddlewares() {
1410
- const app = this.expressApp;
1411
- const middlewares = this.getClassesInstancesArrBy(
1412
- Models__NS__ClassType.MIDDLEWARE
1413
- );
1414
- for (const middleware of middlewares) {
1415
- const middlewareInstance = middleware;
1416
- if (___NS__isFunction(middlewareInstance.interceptServer)) {
1417
- const middlewareFn = ClassHelpers__NS__asyncHandler(
1418
- async (req, res, next) => {
1419
- if (req.originalUrl.startsWith(
1420
- `${this.uriPathnameOrNothingIfRoot}/${apiPrefix}/${this.contextName}/`
1421
- )) {
1422
- await middlewareInstance.interceptServer({
1423
- req,
1424
- res,
1425
- next
1426
- });
1427
- } else {
1428
- next();
1439
+ //#endregion
1440
+ //#region group start
1441
+ //#region @backend
1442
+ if (!UtilsOs__NS__isRunningInCliMode()) {
1443
+ //#endregion
1444
+ this.logHttp &&
1445
+ console.groupCollapsed(`[taon][express-server] routes [${classConfig.className}]`);
1446
+ //#region @backend
1429
1447
  }
1430
- }
1431
- );
1432
- app.use(middlewareFn);
1433
- }
1434
- }
1435
- }
1436
- async initBackendMiddlewares() {
1437
- const app = this.expressApp;
1438
- this.expressApp.get("/helloworld", (req, res) => {
1439
- res.send(`Hello, world from context ${this.contextName}`);
1440
- });
1441
- app.use(bodyParser.urlencoded({ extended: true }));
1442
- app.use(bodyParser.json());
1443
- app.use(methodOverride());
1444
- app.use(cookieParser());
1445
- if (this.session) {
1446
- Helpers__NS__info(
1447
- "[taon][express-server] session enabled for this context " + this.contextName
1448
- );
1449
- const { cookieMaxAge } = this.session;
1450
- const frontendHost = this.config.frontendHost;
1451
- const sessionObj = {
1452
- frontendHost,
1453
- secret: "mysecretsessioncookithing",
1454
- saveUninitialized: true,
1455
- cookieMaxAge,
1456
- secure: frontendHost.startsWith("https://"),
1457
- resave: false
1458
- };
1459
- app.use(
1460
- cors({
1461
- credentials: true,
1462
- origin: frontendHost
1463
- })
1464
- );
1465
- app.use(expressSession(sessionObj));
1466
- console.log(`
1448
+ //#endregion
1449
+ //#endregion
1450
+ //#region init client or server methods
1451
+ const methodNames = Object.keys(classConfig.methods);
1452
+ for (const methodName of methodNames) {
1453
+ const methodConfig = classConfig.methods[methodName];
1454
+ //#region combine all class methods middlewares
1455
+ let calculatedMiddlewaresMethodObj = {};
1456
+ [...rawConfigs].reverse().forEach(rc => {
1457
+ if (rc.methods[methodName]) {
1458
+ const parentMethodConfig = rc.methods[methodName];
1459
+ if (___NS__isFunction(parentMethodConfig.middlewares)) {
1460
+ calculatedMiddlewaresMethodObj = parentMethodConfig.middlewares({
1461
+ parentMiddlewares: calculatedMiddlewaresMethodObj,
1462
+ className(middlewareClass) {
1463
+ return ClassHelpers__NS__getName(controllerClassFn);
1464
+ },
1465
+ });
1466
+ }
1467
+ }
1468
+ });
1469
+ // add class middlewares to method middlewares
1470
+ methodConfig.calculatedMiddlewaresMethodObj = {
1471
+ ...calculatedMiddlewaresMethodObj,
1472
+ ...classConfig.calculatedMiddlewaresControllerObj,
1473
+ };
1474
+ methodConfig.calculatedMiddlewares = Object.values(methodConfig.calculatedMiddlewaresMethodObj || {});
1475
+ //#endregion
1476
+ // methodConfig.calculatedMiddlewares = TODO
1477
+ //#region initialized method express path
1478
+ const httpMethodType = methodConfig.type;
1479
+ // this is quick fix - in docker global path should not be used
1480
+ const globalPathPart = this.isRunningInsideDocker ||
1481
+ !this.frontendHostUri?.origin?.includes('localhost') // fe with domain -> is in docker
1482
+ ? `${this.uriPathnameOrNothingIfRoot.replace(/\/$/, '')}/${apiPrefix}/${this.contextName}`.replace(/\/\//, '/')
1483
+ : '';
1484
+ const expressPath = methodConfig.global
1485
+ ? `${globalPathPart}/${methodConfig.path?.replace(/\/$/, '')}`.replace(/\/\//, '/')
1486
+ : TaonHelpers__NS__getExpressPath(classConfig, methodConfig);
1487
+ //#endregion
1488
+ //#region init server
1489
+ // console.log({ expressPath });
1490
+ if (UtilsOs__NS__isNode || UtilsOs__NS__isWebSQL) {
1491
+ //#region @websql
1492
+ const route = this.initServer(httpMethodType, methodConfig, classConfig, expressPath, controllerClassFn);
1493
+ this.activeRoutes.push({
1494
+ expressPath: route.expressPath,
1495
+ method: route.method,
1496
+ });
1497
+ //#endregion
1498
+ }
1499
+ //#endregion
1500
+ //#region init client
1501
+ const shouldInitClient = UtilsOs__NS__isBrowser || this.isRemoteHost || UtilsOs__NS__isWebSQL;
1502
+ // console.log('shouldInitClient', shouldInitClient);
1503
+ if (shouldInitClient) {
1504
+ // console.log(
1505
+ // 'initClient',
1506
+ // ClassHelpers__NS__getFullInternalName(controllerClassFn),
1507
+ // type,
1508
+ // methodConfig,
1509
+ // expressPath,
1510
+ // );
1511
+ await this.initClient(controllerClassFn, httpMethodType, methodConfig, expressPath);
1512
+ }
1513
+ //#endregion
1514
+ }
1515
+ //#endregion
1516
+ //#region group end
1517
+ //#region @backend
1518
+ if (!UtilsOs__NS__isRunningInCliMode()) {
1519
+ //#endregion
1520
+ this.logHttp && console.groupEnd();
1521
+ //#region @backend
1522
+ }
1523
+ //#endregion
1524
+ //#endregion
1525
+ }
1526
+ }
1527
+ //#endregion
1528
+ //#region methods & getters / write active routes
1529
+ writeActiveRoutes() {
1530
+ if (this.isRemoteHost || this.isRunOrRevertOnlyMigrationAppStart) {
1531
+ return;
1532
+ }
1533
+ // const contexts: EndpointContext[] = [this];
1534
+ //#region @websql
1535
+ const troutes = Utils__NS__uniqArray(this.activeRoutes.map(f => {
1536
+ return `${f.method} ${f.expressPath}`;
1537
+ })).map(f => {
1538
+ const [method, expressPath] = f.split(' ');
1539
+ return (`\n### ${___NS__startCase(___NS__last(expressPath.split('/')))}\n` +
1540
+ TaonHelpers__NS__fillUpTo(method.toUpperCase() + ' ', 10) +
1541
+ this.uriOrigin +
1542
+ expressPath);
1543
+ // return `${TaonHelpers.string(method.toUpperCase() + ':')
1544
+ // .fillUpTo(10)}${context.uriHref.replace(/\/$/, '')}${expressPath}`
1545
+ });
1546
+ const routes = [
1547
+ ...['', `# ROUTES FOR HOST ${this.uriOrigin} `],
1548
+ ...troutes,
1549
+ ].join('\n');
1550
+ const fileName = crossPlatformPath([
1551
+ //#region @backend
1552
+ process.cwd(),
1553
+ //#endregion
1554
+ `routes/routes-${this.config.contextName}.rest`,
1555
+ ]);
1556
+ this.logFramework && console.log(`[taon] routes file: ${fileName} `);
1557
+ this.logRoutes && console.log(routes);
1558
+ //#region @backend
1559
+ if (!UtilsOs__NS__isElectron && !this.skipWritingServerRoutes) {
1560
+ Helpers__NS__writeFile(fileName, routes);
1561
+ }
1562
+ //#endregion
1563
+ //#endregion
1564
+ }
1565
+ //#endregion
1566
+ //#region methods & getters / middlewares
1567
+ get middlewares() {
1568
+ //#region @backendFunc
1569
+ return this.config.middlewares || [];
1570
+ //#endregion
1571
+ }
1572
+ //#endregion
1573
+ //#region methods & getters / init middlewares
1574
+ async initCustomClientMiddlewares() {
1575
+ const middlewares = this.getClassesInstancesArrBy(Models__NS__ClassType.MIDDLEWARE)
1576
+ .map(f => f)
1577
+ .filter(f => ___NS__isFunction(f.interceptClient));
1578
+ middlewares.forEach(middlewareInstanceName => {
1579
+ const contextName = this.contextName;
1580
+ const interceptorName = `${contextName}-${ClassHelpers__NS__getName(middlewareInstanceName)}`;
1581
+ Resource.request.interceptors.set(interceptorName, {
1582
+ intercept: ({ req, next }) => {
1583
+ const url = new URL(req.url);
1584
+ if (url.pathname.startsWith(`${this.uriPathnameOrNothingIfRoot}/${apiPrefix}/${contextName}/`)) {
1585
+ // console.log('intercepting', url.pathname, req);
1586
+ return middlewareInstanceName.interceptClient({
1587
+ req,
1588
+ next,
1589
+ });
1590
+ }
1591
+ return next.handle(req);
1592
+ },
1593
+ });
1594
+ });
1595
+ }
1596
+ async initCustomBackendMiddlewares() {
1597
+ //#region @backend
1598
+ const app = this.expressApp;
1599
+ const middlewares = this.getClassesInstancesArrBy(Models__NS__ClassType.MIDDLEWARE);
1600
+ for (const middleware of middlewares) {
1601
+ const middlewareInstance = middleware;
1602
+ if (___NS__isFunction(middlewareInstance.interceptServer)) {
1603
+ const middlewareFn = ClassHelpers__NS__asyncHandler(async (req, res, next) => {
1604
+ if (req.originalUrl.startsWith(`${this.uriPathnameOrNothingIfRoot}/${apiPrefix}/${this.contextName}/`)) {
1605
+ await middlewareInstance.interceptServer({
1606
+ req,
1607
+ res,
1608
+ next,
1609
+ });
1610
+ }
1611
+ else {
1612
+ next();
1613
+ }
1614
+ });
1615
+ app.use(middlewareFn);
1616
+ }
1617
+ }
1618
+ //#endregion
1619
+ }
1620
+ async initBackendMiddlewares() {
1621
+ //#region @backend
1622
+ const app = this.expressApp;
1623
+ // if (this.middlewares) {
1624
+ // this.middlewares.forEach(m => {
1625
+ // const [fun, args] = m;
1626
+ // app.use(fun.apply(null, args));
1627
+ // });
1628
+ // }
1629
+ this.expressApp.get('/helloworld', (req, res) => {
1630
+ res.send(`Hello, world from context ${this.contextName}`);
1631
+ });
1632
+ // app.use(fileUpload());
1633
+ app.use(bodyParser.urlencoded({ extended: true }));
1634
+ app.use(bodyParser.json());
1635
+ app.use(methodOverride());
1636
+ app.use(cookieParser());
1637
+ if (this.session) {
1638
+ Helpers__NS__info('[taon][express-server] session enabled for this context ' +
1639
+ this.contextName);
1640
+ const { cookieMaxAge } = this.session;
1641
+ const frontendHost = this.config.frontendHost;
1642
+ const sessionObj = {
1643
+ frontendHost,
1644
+ secret: 'mysecretsessioncookithing',
1645
+ saveUninitialized: true,
1646
+ cookieMaxAge,
1647
+ secure: frontendHost.startsWith('https://'),
1648
+ resave: false,
1649
+ };
1650
+ app.use(cors({
1651
+ credentials: true,
1652
+ origin: frontendHost,
1653
+ }));
1654
+ app.use(expressSession(sessionObj));
1655
+ console.log(`
1467
1656
 
1468
1657
  CORS ENABLED FOR SESSION
1469
1658
 
1470
1659
  `);
1471
- } else {
1472
- this.logHttp && Helpers__NS__info(
1473
- `[taon][express-server] session not enabled for this context '${this.contextName}'`
1474
- );
1475
- app.use(
1476
- cors({
1477
- // origin: "http://localhost:5555",
1478
- // methods: ["GET", "POST"],
1479
- // allowedHeaders: ["my-custom-header"],
1480
- // credentials: true
1481
- })
1482
- );
1483
- this.logHttp && console.log(`
1660
+ }
1661
+ else {
1662
+ // if(this.config?.serverLogs) {
1663
+ this.logHttp &&
1664
+ Helpers__NS__info(`[taon][express-server] session not enabled for this context '${this.contextName}'`);
1665
+ // }
1666
+ app.use(cors({
1667
+ // origin: "http://localhost:5555",
1668
+ // methods: ["GET", "POST"],
1669
+ // allowedHeaders: ["my-custom-header"],
1670
+ // credentials: true
1671
+ }));
1672
+ this.logHttp &&
1673
+ console.log(`
1484
1674
 
1485
1675
  CORS ENABLED WITHOUT SESSION
1486
1676
 
1487
1677
  `);
1678
+ }
1679
+ (() => {
1680
+ app.use((req, res, next) => {
1681
+ //#region good for cors session obj
1682
+ // if (this.context.session) {
1683
+ // res.header('Access-Control-Allow-Origin', this.context.session.frontendHost);
1684
+ // res.header('Access-Control-Allow-Credentials', 'true');
1685
+ // res.header(
1686
+ // 'Access-Control-Allow-Headers',
1687
+ // 'Origin, X-Requested-With, Content-Type, Accept'
1688
+ // );
1689
+ // res.header("Access-Control-Allow-Methods", "PUT,POST,GET,HEAD,DELETE,OPTIONS,PATCH");
1690
+ // // maybe this
1691
+ // res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
1692
+ // }
1693
+ //#endregion
1694
+ res.set('Access-Control-Expose-Headers', [
1695
+ 'Content-Type',
1696
+ 'Authorization',
1697
+ 'X-Requested-With',
1698
+ Symbols__NS__old.X_TOTAL_COUNT,
1699
+ Symbols__NS__old.MAPPING_CONFIG_HEADER,
1700
+ Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY,
1701
+ Symbols__NS__old.CIRCURAL_OBJECTS_MAP_QUERY_PARAM,
1702
+ ].join(', '));
1703
+ next();
1704
+ });
1705
+ })();
1706
+ //#endregion
1488
1707
  }
1489
- (() => {
1490
- app.use((req, res, next) => {
1491
- res.set(
1492
- "Access-Control-Expose-Headers",
1493
- [
1494
- "Content-Type",
1495
- "Authorization",
1496
- "X-Requested-With",
1497
- Symbols__NS__old.X_TOTAL_COUNT,
1498
- Symbols__NS__old.MAPPING_CONFIG_HEADER,
1499
- Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY,
1500
- Symbols__NS__old.CIRCURAL_OBJECTS_MAP_QUERY_PARAM
1501
- ].join(", ")
1502
- );
1503
- next();
1504
- });
1505
- })();
1506
- }
1507
- //#endregion
1508
- //#region methods & getters / init methods node
1509
- initServer(httpMethodType, methodConfig, classConfig, expressPath, target) {
1510
- const middlewareHandlers = methodConfig.calculatedMiddlewares.map((middlewareClassFun) => {
1511
- const middlewareInstance = this.getInstanceBy(
1512
- middlewareClassFun
1513
- );
1514
- if (middlewareInstance && ___NS__isFunction(middlewareInstance.interceptServerMethod)) {
1515
- const middlewareFn = ClassHelpers__NS__asyncHandler(
1516
- async (req, res, next) => {
1517
- await middlewareInstance.interceptServerMethod(
1518
- {
1519
- req,
1520
- res,
1521
- next
1522
- },
1523
- {
1524
- methodName: methodConfig.methodName,
1525
- expressPath,
1526
- httpRequestType: methodConfig.type
1527
- }
1528
- );
1529
- }
1530
- );
1531
- return middlewareFn;
1532
- }
1533
- }).filter((f) => !!f);
1534
- const getResult = async (resolvedParams, req, res) => {
1535
- const response = methodConfig.descriptor.value.apply(
1536
- /**
1537
- * Context for method @GET,@PUT etc.
1538
- */
1539
- this.getInstanceBy(target),
1540
- /**
1541
- * Params for method @GET, @PUT etc.
1542
- */
1543
- resolvedParams
1544
- );
1545
- let result = await getResponseValue(response, { req, res });
1546
- return result;
1547
- };
1548
- if (UtilsOs__NS__isElectron) {
1549
- const ipcKeyName = TaonHelpers__NS__ipcKeyNameRequest(
1550
- target,
1551
- methodConfig,
1552
- expressPath
1553
- );
1554
- ipcMain.on(ipcKeyName, async (event, paramsFromBrowser) => {
1555
- const responseJsonData = await getResult(
1556
- paramsFromBrowser,
1557
- void 0,
1558
- void 0
1559
- );
1560
- const sendToIpsMainOn = TaonHelpers__NS__ipcKeyNameResponse(
1561
- target,
1562
- methodConfig,
1563
- expressPath
1564
- );
1565
- event.sender.send(sendToIpsMainOn, responseJsonData);
1566
- });
1567
- return {
1568
- expressPath,
1569
- method: methodConfig.type
1570
- };
1571
- }
1572
- if (!this.isRemoteHost) {
1573
- if (UtilsOs__NS__isWebSQL) {
1574
- if (!this.expressApp[httpMethodType.toLowerCase()]) {
1575
- this.expressApp[httpMethodType.toLowerCase()] = () => {
1576
- };
1577
- }
1578
- }
1579
- this.expressApp[httpMethodType.toLowerCase()](
1580
- expressPath,
1581
- ...middlewareHandlers,
1582
- async (req, res) => {
1583
- const args = [];
1584
- let tBody = req.body;
1585
- let tParams = req.params;
1586
- let tQuery = req.query;
1587
- if (req.headers[Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY]) {
1588
- try {
1589
- tBody = JSON.parse(
1590
- JSON.stringify(tBody),
1591
- JSON.parse(
1592
- TaonHelpers__NS__firstStringOrElemFromArray(
1593
- req.headers[Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY]
1594
- )
1595
- )
1596
- );
1597
- } catch (e) {
1708
+ //#endregion
1709
+ //#region methods & getters / init methods node
1710
+ initServer(
1711
+ //#region parameters
1712
+ httpMethodType, methodConfig, classConfig, expressPath, target) {
1713
+ //#region resolve variables
1714
+ // console.log(
1715
+ // `CLIENT: expressPath: "${expressPath}" interceptor for method: ${methodConfig.calculatedMiddlewares.length}`,
1716
+ // );
1717
+ const middlewareHandlers = methodConfig.calculatedMiddlewares
1718
+ .map(middlewareClassFun => {
1719
+ const middlewareInstance = this.getInstanceBy(middlewareClassFun);
1720
+ if (middlewareInstance &&
1721
+ ___NS__isFunction(middlewareInstance.interceptServerMethod)) {
1722
+ const middlewareFn = ClassHelpers__NS__asyncHandler(async (req, res, next) => {
1723
+ await middlewareInstance.interceptServerMethod({
1724
+ req,
1725
+ res,
1726
+ next,
1727
+ }, {
1728
+ methodName: methodConfig.methodName,
1729
+ expressPath,
1730
+ httpRequestType: methodConfig.type,
1731
+ });
1732
+ });
1733
+ return middlewareFn;
1598
1734
  }
1599
- }
1600
- if (req.headers[Symbols__NS__old.CIRCURAL_OBJECTS_MAP_QUERY_PARAM]) {
1601
- try {
1602
- tQuery = JSON.parse(
1603
- JSON.stringify(tQuery),
1604
- JSON.parse(
1605
- TaonHelpers__NS__firstStringOrElemFromArray(
1606
- req.headers[Symbols__NS__old.CIRCURAL_OBJECTS_MAP_QUERY_PARAM]
1607
- )
1608
- )
1609
- );
1610
- } catch (e) {
1611
- }
1612
- }
1613
- if (req.headers[Symbols__NS__old.MAPPING_CONFIG_HEADER_BODY_PARAMS]) {
1614
- try {
1615
- const entity = JSON.parse(
1616
- TaonHelpers__NS__firstStringOrElemFromArray(
1617
- req.headers[Symbols__NS__old.MAPPING_CONFIG_HEADER_BODY_PARAMS]
1618
- )
1619
- );
1620
- tBody = Mapping__NS__encode(tBody, entity);
1621
- } catch (e) {
1622
- }
1623
- } else {
1624
- Object.keys(tBody).forEach((paramName) => {
1625
- try {
1626
- const entityForParam = JSON.parse(
1627
- TaonHelpers__NS__firstStringOrElemFromArray(
1628
- req.headers[`${Symbols__NS__old.MAPPING_CONFIG_HEADER_BODY_PARAMS}${paramName} `]
1629
- )
1630
- );
1631
- tBody[paramName] = Mapping__NS__encode(
1632
- tBody[paramName],
1633
- entityForParam
1634
- );
1635
- } catch (e) {
1636
- }
1735
+ })
1736
+ .filter(f => !!f);
1737
+ // const url = this.uri;
1738
+ //#region get result
1739
+ const getResult = async (resolvedParams, req, res) => {
1740
+ const response = methodConfig.descriptor.value.apply(
1741
+ /**
1742
+ * Context for method @GET,@PUT etc.
1743
+ */
1744
+ this.getInstanceBy(target),
1745
+ /**
1746
+ * Params for method @GET, @PUT etc.
1747
+ */
1748
+ resolvedParams);
1749
+ let result = await getResponseValue(response, { req, res });
1750
+ return result;
1751
+ };
1752
+ //#endregion
1753
+ // console.log(`BACKEND: expressPath: "${expressPath}" `);
1754
+ //#endregion
1755
+ if (UtilsOs__NS__isElectron) {
1756
+ //#region @backend
1757
+ const ipcKeyName = TaonHelpers__NS__ipcKeyNameRequest(target, methodConfig, expressPath);
1758
+ ipcMain.on(ipcKeyName, async (event, paramsFromBrowser) => {
1759
+ const responseJsonData = await getResult(paramsFromBrowser, void 0, void 0);
1760
+ const sendToIpsMainOn = TaonHelpers__NS__ipcKeyNameResponse(target, methodConfig, expressPath);
1761
+ // console.log({ sendToIpsMainOn });
1762
+ event.sender.send(sendToIpsMainOn, responseJsonData);
1637
1763
  });
1638
- }
1639
- if (req.headers[Symbols__NS__old.MAPPING_CONFIG_HEADER_QUERY_PARAMS]) {
1640
- try {
1641
- const entity = JSON.parse(
1642
- TaonHelpers__NS__firstStringOrElemFromArray(
1643
- req.headers[Symbols__NS__old.MAPPING_CONFIG_HEADER_QUERY_PARAMS]
1644
- )
1645
- );
1646
- tQuery = TaonHelpers__NS__parseJSONwithStringJSONs(
1647
- Mapping__NS__encode(tQuery, entity)
1648
- );
1649
- } catch (e) {
1764
+ return {
1765
+ expressPath,
1766
+ method: methodConfig.type,
1767
+ };
1768
+ //#endregion
1769
+ }
1770
+ if (!this.isRemoteHost) {
1771
+ //#region apply dummy websql express routers
1772
+ //#region @websql
1773
+ if (UtilsOs__NS__isWebSQL) {
1774
+ if (!this.expressApp[httpMethodType.toLowerCase()]) {
1775
+ this.expressApp[httpMethodType.toLowerCase()] = () => { };
1776
+ // TODO add middlewares for WEBSQL and ELECTRON mode
1777
+ }
1650
1778
  }
1651
- } else {
1652
- Object.keys(tQuery).forEach((queryParamName) => {
1653
- try {
1654
- const entityForParam = JSON.parse(
1655
- TaonHelpers__NS__firstStringOrElemFromArray(
1656
- req.headers[`${Symbols__NS__old.MAPPING_CONFIG_HEADER_QUERY_PARAMS}${queryParamName} `]
1657
- )
1658
- );
1659
- let beforeTransofrm = tQuery[queryParamName];
1660
- if (___NS__isString(beforeTransofrm)) {
1661
- try {
1662
- const paresed = TaonHelpers__NS__tryTransformParam(beforeTransofrm);
1663
- beforeTransofrm = paresed;
1664
- } catch (e) {
1665
- }
1779
+ //#endregion
1780
+ //#endregion
1781
+ //#region @backend
1782
+ // this.logHttp &&
1783
+ // console.log(`[${httpMethodType.toUpperCase()}] ${expressPath} `);
1784
+ this.expressApp[httpMethodType.toLowerCase()](expressPath, ...middlewareHandlers, async (req, res) => {
1785
+ // console.log(`[${type.toUpperCase()}] ${expressPath} `);
1786
+ //#region process params
1787
+ const args = [];
1788
+ let tBody = req.body;
1789
+ let tParams = req.params;
1790
+ let tQuery = req.query;
1791
+ if (req.headers[Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY]) {
1792
+ try {
1793
+ tBody = JSON.parse(JSON.stringify(tBody), JSON.parse(TaonHelpers__NS__firstStringOrElemFromArray(req.headers[Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY])));
1794
+ }
1795
+ catch (e) { }
1796
+ }
1797
+ if (req.headers[Symbols__NS__old.CIRCURAL_OBJECTS_MAP_QUERY_PARAM]) {
1798
+ try {
1799
+ tQuery = JSON.parse(JSON.stringify(tQuery), JSON.parse(TaonHelpers__NS__firstStringOrElemFromArray(req.headers[Symbols__NS__old.CIRCURAL_OBJECTS_MAP_QUERY_PARAM])));
1800
+ }
1801
+ catch (e) { }
1802
+ }
1803
+ // make class instance from body
1804
+ // console.log('req.headers', req.headers)
1805
+ if (req.headers[Symbols__NS__old.MAPPING_CONFIG_HEADER_BODY_PARAMS]) {
1806
+ try {
1807
+ const entity = JSON.parse(TaonHelpers__NS__firstStringOrElemFromArray(req.headers[Symbols__NS__old.MAPPING_CONFIG_HEADER_BODY_PARAMS]));
1808
+ tBody = Mapping__NS__encode(tBody, entity);
1809
+ }
1810
+ catch (e) { }
1811
+ }
1812
+ else {
1813
+ Object.keys(tBody).forEach(paramName => {
1814
+ try {
1815
+ const entityForParam = JSON.parse(TaonHelpers__NS__firstStringOrElemFromArray(req.headers[`${Symbols__NS__old.MAPPING_CONFIG_HEADER_BODY_PARAMS}${paramName} `]));
1816
+ tBody[paramName] = Mapping__NS__encode(tBody[paramName], entityForParam);
1817
+ }
1818
+ catch (e) { }
1819
+ });
1820
+ }
1821
+ // make class instance from query params
1822
+ // console.log('req.headers', tQuery)
1823
+ if (req.headers[Symbols__NS__old.MAPPING_CONFIG_HEADER_QUERY_PARAMS]) {
1824
+ try {
1825
+ const entity = JSON.parse(TaonHelpers__NS__firstStringOrElemFromArray(req.headers[Symbols__NS__old.MAPPING_CONFIG_HEADER_QUERY_PARAMS]));
1826
+ tQuery = TaonHelpers__NS__parseJSONwithStringJSONs(Mapping__NS__encode(tQuery, entity));
1827
+ }
1828
+ catch (e) { }
1829
+ }
1830
+ else {
1831
+ Object.keys(tQuery).forEach(queryParamName => {
1832
+ try {
1833
+ const entityForParam = JSON.parse(TaonHelpers__NS__firstStringOrElemFromArray(req.headers[`${Symbols__NS__old.MAPPING_CONFIG_HEADER_QUERY_PARAMS}${queryParamName} `]));
1834
+ let beforeTransofrm = tQuery[queryParamName];
1835
+ if (___NS__isString(beforeTransofrm)) {
1836
+ try {
1837
+ const paresed = TaonHelpers__NS__tryTransformParam(beforeTransofrm);
1838
+ beforeTransofrm = paresed;
1839
+ }
1840
+ catch (e) { }
1841
+ }
1842
+ const afterEncoding = Mapping__NS__encode(beforeTransofrm, entityForParam);
1843
+ tQuery[queryParamName] =
1844
+ TaonHelpers__NS__parseJSONwithStringJSONs(afterEncoding);
1845
+ }
1846
+ catch (e) { }
1847
+ });
1848
+ }
1849
+ Object.keys(methodConfig.parameters).forEach(paramName => {
1850
+ let p = methodConfig.parameters[paramName];
1851
+ if (p.paramType === 'Path' && tParams) {
1852
+ args.push(tParams[p.paramName]);
1853
+ }
1854
+ if (p.paramType === 'Query' && tQuery) {
1855
+ if (p.paramName) {
1856
+ args.push(tQuery[p.paramName]);
1857
+ }
1858
+ else {
1859
+ args.push(tQuery);
1860
+ }
1861
+ }
1862
+ if (p.paramType === 'Header' && req.headers) {
1863
+ args.push(req.headers[p.paramName.toLowerCase()]);
1864
+ }
1865
+ if (p.paramType === 'Cookie' && req.cookies) {
1866
+ args.push(req.cookies[p.paramName]);
1867
+ }
1868
+ if (p.paramType === 'Body' && tBody) {
1869
+ if (p.paramName && typeof tBody === 'object') {
1870
+ args.push(tBody[p.paramName]);
1871
+ }
1872
+ else {
1873
+ args.push(tBody);
1874
+ }
1875
+ }
1876
+ });
1877
+ //#endregion
1878
+ const resolvedParams = args
1879
+ .reverse()
1880
+ .map(v => TaonHelpers__NS__tryTransformParam(v));
1881
+ try {
1882
+ let result = await getResult(resolvedParams, req, res);
1883
+ if (methodConfig.responseType)
1884
+ if (res.headersSent) {
1885
+ // SKIP FURTHER PROCESSING IF RESPONSE ALREADY SENT
1886
+ return;
1887
+ }
1888
+ if (methodConfig.overrideExpressSendAsHtml) {
1889
+ res.setHeader('Content-Type', 'text/html');
1890
+ res.send(result);
1891
+ return;
1892
+ }
1893
+ if (result instanceof Blob &&
1894
+ methodConfig.responseType ===
1895
+ 'blob') {
1896
+ // console.log('INSTANCE OF BLOB')
1897
+ //#region processs blob result type
1898
+ const blob = result;
1899
+ const file = Buffer.from(await blob.arrayBuffer());
1900
+ res.writeHead(200, {
1901
+ 'Content-Type': blob.type,
1902
+ 'Content-Length': file.length,
1903
+ });
1904
+ res.end(file);
1905
+ //#endregion
1906
+ }
1907
+ else if (___NS__isString(result) &&
1908
+ methodConfig.responseType ===
1909
+ 'blob') {
1910
+ // console.log('BASE64')
1911
+ //#region process string buffer TODO refacetor
1912
+ const img_base64 = result;
1913
+ const m = /^data:(.+?);base64,(.+)$/.exec(img_base64);
1914
+ if (!m) {
1915
+ throw new Error(`[taon - framework] Not a base64 image[${img_base64}]`);
1916
+ }
1917
+ const [_, content_type, file_base64] = m;
1918
+ const file = Buffer.from(file_base64, 'base64');
1919
+ res.writeHead(200, {
1920
+ 'Content-Type': content_type,
1921
+ 'Content-Length': file.length,
1922
+ });
1923
+ res.end(file);
1924
+ //#endregion
1925
+ }
1926
+ else {
1927
+ //#region process json request
1928
+ await EntityProcess.init(result, res);
1929
+ //#endregion
1930
+ }
1931
+ }
1932
+ catch (error) {
1933
+ if (res.headersSent) {
1934
+ // SKIP FURTHER PROCESSING IF RESPONSE ALREADY SENT
1935
+ return;
1936
+ }
1937
+ if (methodConfig.overrideExpressSendAsHtml) {
1938
+ res.setHeader('Content-Type', 'text/html');
1939
+ res.send(error);
1940
+ return;
1941
+ }
1942
+ this.sendError(res, error, req, expressPath);
1666
1943
  }
1667
- const afterEncoding = Mapping__NS__encode(
1668
- beforeTransofrm,
1669
- entityForParam
1670
- );
1671
- tQuery[queryParamName] = TaonHelpers__NS__parseJSONwithStringJSONs(afterEncoding);
1672
- } catch (e) {
1673
- }
1674
1944
  });
1675
- }
1676
- Object.keys(methodConfig.parameters).forEach((paramName) => {
1677
- let p = methodConfig.parameters[paramName];
1678
- if (p.paramType === "Path" && tParams) {
1679
- args.push(tParams[p.paramName]);
1680
- }
1681
- if (p.paramType === "Query" && tQuery) {
1682
- if (p.paramName) {
1683
- args.push(tQuery[p.paramName]);
1684
- } else {
1685
- args.push(tQuery);
1686
- }
1687
- }
1688
- if (p.paramType === "Header" && req.headers) {
1689
- args.push(req.headers[p.paramName.toLowerCase()]);
1690
- }
1691
- if (p.paramType === "Cookie" && req.cookies) {
1692
- args.push(req.cookies[p.paramName]);
1693
- }
1694
- if (p.paramType === "Body" && tBody) {
1695
- if (p.paramName && typeof tBody === "object") {
1696
- args.push(tBody[p.paramName]);
1697
- } else {
1698
- args.push(tBody);
1699
- }
1700
- }
1701
- });
1702
- const resolvedParams = args.reverse().map((v) => TaonHelpers__NS__tryTransformParam(v));
1703
- try {
1704
- let result = await getResult(resolvedParams, req, res);
1705
- if (methodConfig.responseType) {
1706
- if (res.headersSent) {
1707
- return;
1708
- }
1709
- }
1710
- if (methodConfig.overrideExpressSendAsHtml) {
1711
- res.setHeader("Content-Type", "text/html");
1712
- res.send(result);
1713
- return;
1714
- }
1715
- if (result instanceof Blob && methodConfig.responseType === "blob") {
1716
- const blob = result;
1717
- const file = Buffer.from(await blob.arrayBuffer());
1718
- res.writeHead(200, {
1719
- "Content-Type": blob.type,
1720
- "Content-Length": file.length
1721
- });
1722
- res.end(file);
1723
- } else if (___NS__isString(result) && methodConfig.responseType === "blob") {
1724
- const img_base64 = result;
1725
- const m = /^data:(.+?);base64,(.+)$/.exec(img_base64);
1726
- if (!m) {
1727
- throw new Error(
1728
- `[taon - framework] Not a base64 image[${img_base64}]`
1729
- );
1730
- }
1731
- const [_, content_type, file_base64] = m;
1732
- const file = Buffer.from(file_base64, "base64");
1733
- res.writeHead(200, {
1734
- "Content-Type": content_type,
1735
- "Content-Length": file.length
1736
- });
1737
- res.end(file);
1738
- } else {
1739
- await EntityProcess.init(result, res);
1740
- }
1741
- } catch (error) {
1742
- if (res.headersSent) {
1743
- return;
1744
- }
1745
- if (methodConfig.overrideExpressSendAsHtml) {
1746
- res.setHeader("Content-Type", "text/html");
1747
- res.send(error);
1748
- return;
1749
- }
1750
- this.sendError(res, error, req, expressPath);
1751
- }
1752
- }
1753
- );
1754
- }
1755
- return {
1756
- expressPath,
1757
- method: methodConfig.type
1758
- };
1759
- }
1760
- //#endregion
1761
- //#region methods & getters / send error
1762
- sendError(res, error, req, expressPath) {
1763
- let status = 500;
1764
- let message = "Internal Server Error";
1765
- let details = void 0;
1766
- let success = false;
1767
- let code = void 0;
1768
- if (typeof error === "function") {
1769
- const obj = error(res) || {};
1770
- status = obj.status || 400;
1771
- message = obj.message;
1772
- details = obj.details;
1773
- code = obj.code;
1774
- } else if (typeof error === "string") {
1775
- message = error;
1776
- status = 400;
1777
- } else if (error instanceof Error) {
1778
- message = error.message;
1779
- details = process.env.NODE_ENV !== "production" ? error.stack : void 0;
1780
- } else {
1781
- message = "Unexpected error";
1782
- details = error;
1783
- }
1784
- res.status(status).json({
1785
- success,
1786
- message,
1787
- details,
1788
- code,
1789
- [CoreModels__NS__TaonHttpErrorCustomProp]: true
1790
- });
1791
- }
1792
- //#endregion
1793
- //#region methods & getters / init client
1794
- /**
1795
- * client can be browser or nodejs (when remote host)
1796
- */
1797
- async initClient(target, httpRequestType, methodConfig, expressPath) {
1798
- const ctx = this;
1799
- const middlewares = methodConfig.calculatedMiddlewares;
1800
- const middlewaresInstances = middlewares.map((f) => this.getInstanceBy(f)).filter((f) => ___NS__isFunction(f.interceptClientMethod));
1801
- middlewaresInstances.forEach((instance) => {
1802
- const middlewareName = ClassHelpers__NS__getName(instance);
1803
- const interceptorKey = `${middlewareName}-${methodConfig.type?.toUpperCase()}-${expressPath}`;
1804
- Resource.request.methodsInterceptors.set(interceptorKey, {
1805
- intercept: ({ req, next }) => {
1806
- return instance.interceptClientMethod(
1807
- {
1808
- req,
1809
- next
1810
- },
1811
- {
1812
- methodName: methodConfig.methodName,
1813
- expressPath,
1814
- httpRequestType
1815
- }
1816
- );
1817
- }
1818
- });
1819
- });
1820
- const storage = globalThis;
1821
- const orgMethods = target.prototype[methodConfig.methodName];
1822
- if (UtilsOs__NS__isElectron) {
1823
- const ipcRenderer = window.require("electron").ipcRenderer;
1824
- target.prototype[methodConfig.methodName] = function(...args) {
1825
- const received = new Promise(async (resolve, reject) => {
1826
- const headers = {};
1827
- const { request, response } = TaonHelpers__NS__websqlMocks(headers);
1828
- });
1829
- received["observable"] = from(received);
1945
+ //#endregion
1946
+ }
1830
1947
  return {
1831
- received,
1832
- request(axiosConfig) {
1833
- return received;
1834
- }
1948
+ expressPath: expressPath,
1949
+ method: methodConfig.type,
1835
1950
  };
1836
- };
1837
- return;
1838
- }
1839
- target.prototype[methodConfig.methodName] = function(...args) {
1840
- if (!storage[Symbols__NS__old.ENDPOINT_META_CONFIG])
1841
- storage[Symbols__NS__old.ENDPOINT_META_CONFIG] = {};
1842
- if (!storage[Symbols__NS__old.ENDPOINT_META_CONFIG][ctx.uriOrigin])
1843
- storage[Symbols__NS__old.ENDPOINT_META_CONFIG][ctx.uriOrigin] = {};
1844
- const endpoints = storage[Symbols__NS__old.ENDPOINT_META_CONFIG];
1845
- let rest;
1846
- if (!endpoints[ctx.uriOrigin][expressPath]) {
1847
- let headers = {};
1848
- if (methodConfig.contentType && !methodConfig.responseType) {
1849
- rest = Resource.create(
1850
- ctx.uriOrigin,
1851
- expressPath,
1852
- Symbols__NS__old.MAPPING_CONFIG_HEADER,
1853
- Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY,
1854
- RestHeaders.from({
1855
- "Content-Type": methodConfig.contentType,
1856
- Accept: methodConfig.contentType
1857
- })
1858
- );
1859
- } else if (methodConfig.contentType && methodConfig.responseType) {
1860
- rest = Resource.create(
1861
- ctx.uriOrigin,
1862
- expressPath,
1863
- Symbols__NS__old.MAPPING_CONFIG_HEADER,
1864
- Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY,
1865
- RestHeaders.from({
1866
- "Content-Type": methodConfig.contentType,
1867
- Accept: methodConfig.contentType,
1868
- responsetypeaxios: methodConfig.responseType
1869
- })
1870
- );
1871
- } else if (!methodConfig.contentType && methodConfig.responseType) {
1872
- rest = Resource.create(
1873
- ctx.uriOrigin,
1874
- expressPath,
1875
- Symbols__NS__old.MAPPING_CONFIG_HEADER,
1876
- Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY,
1877
- RestHeaders.from({
1878
- responsetypeaxios: methodConfig.responseType
1879
- })
1880
- );
1881
- } else {
1882
- rest = Resource.create(
1883
- ctx.uriOrigin,
1884
- expressPath,
1885
- Symbols__NS__old.MAPPING_CONFIG_HEADER,
1886
- Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY
1887
- );
1888
- }
1889
- endpoints[ctx.uriOrigin][expressPath] = rest;
1890
- } else {
1891
- rest = endpoints[ctx.uriOrigin][expressPath];
1892
- }
1893
- const method = httpRequestType.toLowerCase();
1894
- const pathPrams = {};
1895
- let queryParams = {};
1896
- let bodyObject = {};
1897
- args.forEach((param, i) => {
1898
- let currentParam = void 0;
1899
- for (let pp in methodConfig.parameters) {
1900
- let v = methodConfig.parameters[pp];
1901
- if (v.index === i) {
1902
- currentParam = v;
1903
- break;
1904
- }
1905
- }
1906
- if (!currentParam) {
1907
- const errorMessage = `[${config.frameworkName}] Unable to resolve parameter at index ${i} for method ${methodConfig.methodName} at path ${expressPath}.`;
1908
- console.error(errorMessage);
1909
- process.exit(0);
1910
- throw new Error(errorMessage);
1911
- }
1912
- if (currentParam.paramType === "Path") {
1913
- pathPrams[currentParam.paramName] = param;
1914
- }
1915
- if (currentParam.paramType === "Query") {
1916
- if (currentParam.paramName) {
1917
- const mapping = Mapping__NS__decode(param, !ctx.isProductionMode);
1918
- if (mapping) {
1919
- rest.headers.set(
1920
- `${Symbols__NS__old.MAPPING_CONFIG_HEADER_QUERY_PARAMS}${currentParam.paramName} `,
1921
- JSON.stringify(mapping)
1922
- );
1923
- }
1924
- queryParams[currentParam.paramName] = param;
1925
- } else {
1926
- const mapping = Mapping__NS__decode(param, !ctx.isProductionMode);
1927
- if (mapping) {
1928
- rest.headers.set(
1929
- Symbols__NS__old.MAPPING_CONFIG_HEADER_QUERY_PARAMS,
1930
- JSON.stringify(mapping)
1931
- );
1932
- }
1933
- queryParams = ___NS__cloneDeep(param);
1934
- }
1935
- }
1936
- if (currentParam.paramType === "Header") {
1937
- if (currentParam.paramName) {
1938
- if (currentParam.paramName === Symbols__NS__old.MDC_KEY) {
1939
- rest.headers.set(
1940
- currentParam.paramName,
1941
- encodeURIComponent(JSON.stringify(param))
1942
- );
1943
- } else {
1944
- rest.headers.set(currentParam.paramName, param);
1951
+ }
1952
+ //#endregion
1953
+ //#region methods & getters / send error
1954
+ sendError(res, error, req, expressPath) {
1955
+ //#region @backendFunc
1956
+ let status = 500;
1957
+ let message = 'Internal Server Error';
1958
+ let details = undefined;
1959
+ let success = false;
1960
+ let code = undefined;
1961
+ if (typeof error === 'function') {
1962
+ const obj = error(res) || {};
1963
+ status = obj.status || 400;
1964
+ message = obj.message;
1965
+ details = obj.details;
1966
+ code = obj.code;
1967
+ }
1968
+ else if (typeof error === 'string') {
1969
+ message = error;
1970
+ status = 400;
1971
+ }
1972
+ else if (error instanceof Error) {
1973
+ message = error.message;
1974
+ details = process.env.NODE_ENV !== 'production' ? error.stack : undefined;
1975
+ }
1976
+ else {
1977
+ message = 'Unexpected error';
1978
+ details = error;
1979
+ }
1980
+ res.status(status).json({
1981
+ success,
1982
+ message,
1983
+ details,
1984
+ code,
1985
+ [CoreModels__NS__TaonHttpErrorCustomProp]: true,
1986
+ });
1987
+ //#endregion
1988
+ }
1989
+ //#endregion
1990
+ //#region methods & getters / init client
1991
+ /**
1992
+ * client can be browser or nodejs (when remote host)
1993
+ */
1994
+ async initClient(target, httpRequestType, methodConfig, // Models.Http.Rest.MethodConfig,
1995
+ expressPath) {
1996
+ const ctx = this;
1997
+ // console.log(
1998
+ // `CLIENT: expressPath: "${expressPath}" interceptor for method: ${methodConfig.calculatedMiddlewares?.length} `,
1999
+ // );
2000
+ //#region init middlewares
2001
+ const middlewares = methodConfig.calculatedMiddlewares;
2002
+ const middlewaresInstances = middlewares
2003
+ .map(f => this.getInstanceBy(f))
2004
+ .filter(f => ___NS__isFunction(f.interceptClientMethod));
2005
+ middlewaresInstances.forEach(instance => {
2006
+ const middlewareName = ClassHelpers__NS__getName(instance);
2007
+ // middlewareName - only needed for inheritace and uniqness of interceptors
2008
+ const interceptorKey = `${middlewareName}-${methodConfig.type?.toUpperCase()}-${expressPath}`;
2009
+ Resource.request.methodsInterceptors.set(interceptorKey, {
2010
+ intercept: ({ req, next }) => {
2011
+ return instance.interceptClientMethod({
2012
+ req,
2013
+ next,
2014
+ }, {
2015
+ methodName: methodConfig.methodName,
2016
+ expressPath,
2017
+ httpRequestType: httpRequestType,
2018
+ });
2019
+ },
2020
+ });
2021
+ });
2022
+ //#endregion
2023
+ // : { received: any; /* Rest<any, any> */ }
2024
+ // this.logHttp &&
2025
+ // console.log(`${httpRequestType?.toUpperCase()} ${expressPath} `);
2026
+ // console.log('INITING', methodConfig); // TODO inject in static
2027
+ //#region resolve storage
2028
+ // TODO not a good idea
2029
+ const storage = globalThis;
2030
+ //#endregion
2031
+ const orgMethods = target.prototype[methodConfig.methodName];
2032
+ //#region handle electron ipc request
2033
+ if (UtilsOs__NS__isElectron) {
2034
+ const ipcRenderer = window.require('electron').ipcRenderer;
2035
+ target.prototype[methodConfig.methodName] = function (...args) {
2036
+ const received = new Promise(async (resolve, reject) => {
2037
+ const headers = {};
2038
+ const { request, response } = TaonHelpers__NS__websqlMocks(headers);
2039
+ /* */
2040
+ /* */
2041
+ /* */
2042
+ /* */
2043
+ /* */
2044
+ /* */
2045
+ /* */
2046
+ /* */
2047
+ /* */
2048
+ /* */
2049
+ /* */
2050
+ /* */
2051
+ /* */
2052
+ /* */
2053
+ /* */
2054
+ /* */
2055
+ /* */
2056
+ /* */
2057
+ /* */
2058
+ /* */
2059
+ /* */
2060
+ /* */
2061
+ /* */
2062
+ /* */
2063
+ /* */
2064
+ /* */
2065
+ /* */
2066
+ /* */
2067
+ /* */
2068
+ /* */
2069
+ /* */
2070
+ /* */
2071
+ /* */
2072
+ /* */
2073
+ /* */
2074
+ /* */
2075
+ });
2076
+ received['observable'] = from(received);
2077
+ return {
2078
+ received,
2079
+ request(axiosConfig) {
2080
+ return received;
2081
+ },
2082
+ };
2083
+ };
2084
+ return;
2085
+ }
2086
+ //#endregion
2087
+ //#region handling web sql request
2088
+ /* */
2089
+ /* */
2090
+ /* */
2091
+ /* */
2092
+ /* */
2093
+ /* */
2094
+ /* */
2095
+ /* */
2096
+ /* */
2097
+ /* */
2098
+ /* */
2099
+ /* */
2100
+ /* */
2101
+ /* */
2102
+ /* */
2103
+ /* */
2104
+ /* */
2105
+ /* */
2106
+ /* */
2107
+ /* */
2108
+ /* */
2109
+ /* */
2110
+ /* */
2111
+ /* */
2112
+ /* */
2113
+ /* */
2114
+ /* */
2115
+ /* */
2116
+ /* */
2117
+ /* */
2118
+ /* */
2119
+ /* */
2120
+ /* */
2121
+ /* */
2122
+ /* */
2123
+ /* */
2124
+ /* */
2125
+ /* */
2126
+ /* */
2127
+ /* */
2128
+ /* */
2129
+ /* */
2130
+ /* */
2131
+ /* */
2132
+ /* */
2133
+ /* */
2134
+ /* */
2135
+ /* */
2136
+ /* */
2137
+ /* */
2138
+ /* */
2139
+ /* */
2140
+ /* */
2141
+ /* */
2142
+ /* */
2143
+ /* */
2144
+ /* */
2145
+ /* */
2146
+ /* */
2147
+ /* */
2148
+ /* */
2149
+ /* */
2150
+ /* */
2151
+ /* */
2152
+ /* */
2153
+ /* */
2154
+ /* */
2155
+ /* */
2156
+ /* */
2157
+ /* */
2158
+ /* */
2159
+ /* */
2160
+ /* */
2161
+ /* */
2162
+ /* */
2163
+ /* */
2164
+ /* */
2165
+ /* */
2166
+ /* */
2167
+ /* */
2168
+ /* */
2169
+ /* */
2170
+ /* */
2171
+ /* */
2172
+ /* */
2173
+ /* */
2174
+ /* */
2175
+ /* */
2176
+ /* */
2177
+ /* */
2178
+ /* */
2179
+ /* */
2180
+ /* */
2181
+ /* */
2182
+ /* */
2183
+ /* */
2184
+ /* */
2185
+ /* */
2186
+ /* */
2187
+ /* */
2188
+ /* */
2189
+ /* */
2190
+ /* */
2191
+ /* */
2192
+ /* */
2193
+ /* */
2194
+ /* */
2195
+ /* */
2196
+ /* */
2197
+ /* */
2198
+ /* */
2199
+ /* */
2200
+ /* */
2201
+ /* */
2202
+ /* */
2203
+ /* */
2204
+ /* */
2205
+ /* */
2206
+ /* */
2207
+ /* */
2208
+ /* */
2209
+ /* */
2210
+ /* */
2211
+ /* */
2212
+ /* */
2213
+ /* */
2214
+ /* */
2215
+ /* */
2216
+ /* */
2217
+ /* */
2218
+ /* */
2219
+ /* */
2220
+ /* */
2221
+ /* */
2222
+ /* */
2223
+ /* */
2224
+ /* */
2225
+ /* */
2226
+ /* */
2227
+ /* */
2228
+ /* */
2229
+ /* */
2230
+ /* */
2231
+ /* */
2232
+ /* */
2233
+ /* */
2234
+ /* */
2235
+ /* */
2236
+ /* */
2237
+ /* */
2238
+ //#endregion
2239
+ //#region handle normal request
2240
+ target.prototype[methodConfig.methodName] = function (...args) {
2241
+ // console.log('[init method browser] FRONTEND expressPath', expressPath)
2242
+ // const productionMode = FrameworkContext.isProductionMode;
2243
+ //#region resolve frontend parameters
2244
+ if (!storage[Symbols__NS__old.ENDPOINT_META_CONFIG])
2245
+ storage[Symbols__NS__old.ENDPOINT_META_CONFIG] = {};
2246
+ if (!storage[Symbols__NS__old.ENDPOINT_META_CONFIG][ctx.uriOrigin])
2247
+ storage[Symbols__NS__old.ENDPOINT_META_CONFIG][ctx.uriOrigin] = {};
2248
+ const endpoints = storage[Symbols__NS__old.ENDPOINT_META_CONFIG];
2249
+ let rest;
2250
+ if (!endpoints[ctx.uriOrigin][expressPath]) {
2251
+ let headers = {};
2252
+ if (methodConfig.contentType && !methodConfig.responseType) {
2253
+ rest = Resource.create(ctx.uriOrigin, expressPath, Symbols__NS__old.MAPPING_CONFIG_HEADER, Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY, RestHeaders.from({
2254
+ 'Content-Type': methodConfig.contentType,
2255
+ Accept: methodConfig.contentType,
2256
+ }));
2257
+ }
2258
+ else if (methodConfig.contentType && methodConfig.responseType) {
2259
+ rest = Resource.create(ctx.uriOrigin, expressPath, Symbols__NS__old.MAPPING_CONFIG_HEADER, Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY, RestHeaders.from({
2260
+ 'Content-Type': methodConfig.contentType,
2261
+ Accept: methodConfig.contentType,
2262
+ responsetypeaxios: methodConfig.responseType,
2263
+ }));
2264
+ }
2265
+ else if (!methodConfig.contentType && methodConfig.responseType) {
2266
+ rest = Resource.create(ctx.uriOrigin, expressPath, Symbols__NS__old.MAPPING_CONFIG_HEADER, Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY, RestHeaders.from({
2267
+ responsetypeaxios: methodConfig.responseType,
2268
+ }));
2269
+ }
2270
+ else {
2271
+ rest = Resource.create(ctx.uriOrigin, expressPath, Symbols__NS__old.MAPPING_CONFIG_HEADER, Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY);
2272
+ }
2273
+ endpoints[ctx.uriOrigin][expressPath] = rest;
1945
2274
  }
1946
- } else {
1947
- for (let header in param) {
1948
- rest.headers.set(header, param[header]);
2275
+ else {
2276
+ rest = endpoints[ctx.uriOrigin][expressPath];
1949
2277
  }
1950
- }
1951
- }
1952
- if (currentParam.paramType === "Cookie") {
1953
- Resource.Cookies.write(
1954
- currentParam.paramName,
1955
- param,
1956
- currentParam.expireInSeconds
1957
- );
1958
- }
1959
- if (currentParam.paramType === "Body") {
1960
- if (currentParam.paramName) {
1961
- if (ClassHelpers__NS__getName(bodyObject) === "FormData") {
1962
- throw new Error(`[taon - framework] Don use param names when posting / putting FormData.
2278
+ const method = httpRequestType.toLowerCase();
2279
+ const pathPrams = {};
2280
+ let queryParams = {};
2281
+ let bodyObject = {};
2282
+ args.forEach((param, i) => {
2283
+ let currentParam = void 0;
2284
+ for (let pp in methodConfig.parameters) {
2285
+ let v = methodConfig.parameters[pp];
2286
+ if (v.index === i) {
2287
+ currentParam = v;
2288
+ break;
2289
+ }
2290
+ }
2291
+ if (!currentParam) {
2292
+ const errorMessage = `[${config.frameworkName}] Unable to resolve parameter` +
2293
+ ` at index ${i} for method ${methodConfig.methodName} at path ${expressPath}.`;
2294
+ //#region @backend
2295
+ console.error(errorMessage);
2296
+ process.exit(0);
2297
+ //#endregion
2298
+ throw new Error(errorMessage);
2299
+ }
2300
+ if (currentParam.paramType === 'Path') {
2301
+ pathPrams[currentParam.paramName] = param;
2302
+ }
2303
+ if (currentParam.paramType === 'Query') {
2304
+ if (currentParam.paramName) {
2305
+ const mapping = Mapping__NS__decode(param, !ctx.isProductionMode);
2306
+ if (mapping) {
2307
+ rest.headers.set(`${Symbols__NS__old.MAPPING_CONFIG_HEADER_QUERY_PARAMS}${currentParam.paramName} `, JSON.stringify(mapping));
2308
+ }
2309
+ queryParams[currentParam.paramName] = param;
2310
+ }
2311
+ else {
2312
+ const mapping = Mapping__NS__decode(param, !ctx.isProductionMode);
2313
+ if (mapping) {
2314
+ rest.headers.set(Symbols__NS__old.MAPPING_CONFIG_HEADER_QUERY_PARAMS, JSON.stringify(mapping));
2315
+ }
2316
+ queryParams = ___NS__cloneDeep(param);
2317
+ }
2318
+ }
2319
+ if (currentParam.paramType === 'Header') {
2320
+ if (currentParam.paramName) {
2321
+ if (currentParam.paramName === Symbols__NS__old.MDC_KEY) {
2322
+ // parese MDC
2323
+ rest.headers.set(currentParam.paramName, encodeURIComponent(JSON.stringify(param)));
2324
+ }
2325
+ else {
2326
+ rest.headers.set(currentParam.paramName, param);
2327
+ }
2328
+ }
2329
+ else {
2330
+ for (let header in param) {
2331
+ rest.headers.set(header, param[header]);
2332
+ }
2333
+ }
2334
+ }
2335
+ if (currentParam.paramType === 'Cookie') {
2336
+ Resource.Cookies.write(currentParam.paramName, param, currentParam.expireInSeconds);
2337
+ }
2338
+ if (currentParam.paramType === 'Body') {
2339
+ if (currentParam.paramName) {
2340
+ if (ClassHelpers__NS__getName(bodyObject) === 'FormData') {
2341
+ throw new Error(`[taon - framework] Don use param names when posting / putting FormData.
1963
2342
  Use this:
1964
2343
  // ...
1965
2344
  (@Taon.Http.Param.Body() formData: FormData) ...
@@ -1970,64 +2349,49 @@ instead
1970
2349
  (@Taon.Http.Param.Body('${currentParam.paramName}') formData: FormData) ...
1971
2350
  // ...
1972
2351
  `);
2352
+ }
2353
+ const mapping = Mapping__NS__decode(param, !ctx.isProductionMode);
2354
+ if (mapping) {
2355
+ rest.headers.set(`${Symbols__NS__old.MAPPING_CONFIG_HEADER_BODY_PARAMS}${currentParam.paramName} `, JSON.stringify(mapping));
2356
+ }
2357
+ bodyObject[currentParam.paramName] = param;
2358
+ }
2359
+ else {
2360
+ const mapping = Mapping__NS__decode(param, !ctx.isProductionMode);
2361
+ if (mapping) {
2362
+ rest.headers.set(Symbols__NS__old.MAPPING_CONFIG_HEADER_BODY_PARAMS, JSON.stringify(mapping));
2363
+ }
2364
+ bodyObject = param;
2365
+ }
2366
+ }
2367
+ });
2368
+ if (typeof bodyObject === 'object' &&
2369
+ ClassHelpers__NS__getName(bodyObject) !== 'FormData') {
2370
+ let circuralFromItem = [];
2371
+ bodyObject = JSON10.parse(JSON10.stringify(bodyObject, void 0, void 0, circs => {
2372
+ circuralFromItem = circs;
2373
+ }));
2374
+ rest.headers.set(Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY, JSON10.stringify(circuralFromItem));
1973
2375
  }
1974
- const mapping = Mapping__NS__decode(param, !ctx.isProductionMode);
1975
- if (mapping) {
1976
- rest.headers.set(
1977
- `${Symbols__NS__old.MAPPING_CONFIG_HEADER_BODY_PARAMS}${currentParam.paramName} `,
1978
- JSON.stringify(mapping)
1979
- );
1980
- }
1981
- bodyObject[currentParam.paramName] = param;
1982
- } else {
1983
- const mapping = Mapping__NS__decode(param, !ctx.isProductionMode);
1984
- if (mapping) {
1985
- rest.headers.set(
1986
- Symbols__NS__old.MAPPING_CONFIG_HEADER_BODY_PARAMS,
1987
- JSON.stringify(mapping)
1988
- );
2376
+ if (typeof queryParams === 'object') {
2377
+ let circuralFromQueryParams = [];
2378
+ queryParams = JSON10.parse(JSON10.stringify(queryParams, void 0, void 0, circs => {
2379
+ circuralFromQueryParams = circs;
2380
+ }));
2381
+ rest.headers.set(Symbols__NS__old.CIRCURAL_OBJECTS_MAP_QUERY_PARAM, JSON10.stringify(circuralFromQueryParams));
1989
2382
  }
1990
- bodyObject = param;
1991
- }
1992
- }
1993
- });
1994
- if (typeof bodyObject === "object" && ClassHelpers__NS__getName(bodyObject) !== "FormData") {
1995
- let circuralFromItem = [];
1996
- bodyObject = JSON10.parse(
1997
- JSON10.stringify(bodyObject, void 0, void 0, (circs) => {
1998
- circuralFromItem = circs;
1999
- })
2000
- );
2001
- rest.headers.set(
2002
- Symbols__NS__old.CIRCURAL_OBJECTS_MAP_BODY,
2003
- JSON10.stringify(circuralFromItem)
2004
- );
2005
- }
2006
- if (typeof queryParams === "object") {
2007
- let circuralFromQueryParams = [];
2008
- queryParams = JSON10.parse(
2009
- JSON10.stringify(queryParams, void 0, void 0, (circs) => {
2010
- circuralFromQueryParams = circs;
2011
- })
2012
- );
2013
- rest.headers.set(
2014
- Symbols__NS__old.CIRCURAL_OBJECTS_MAP_QUERY_PARAM,
2015
- JSON10.stringify(circuralFromQueryParams)
2016
- );
2017
- }
2018
- const httpResultObj = {
2019
- get received() {
2020
- return rest.model(pathPrams)[method](bodyObject, [queryParams]);
2021
- },
2022
- request(axiosConfig) {
2023
- return rest.model(pathPrams)[method](bodyObject, [queryParams], axiosConfig);
2024
- }
2025
- };
2026
- return httpResultObj;
2027
- };
2028
- }
2029
- //#endregion
2383
+ //#endregion
2384
+ const httpResultObj = {
2385
+ get received() {
2386
+ return rest.model(pathPrams)[method](bodyObject, [queryParams]);
2387
+ },
2388
+ request(axiosConfig) {
2389
+ return rest
2390
+ .model(pathPrams)[method](bodyObject, [queryParams], axiosConfig);
2391
+ },
2392
+ };
2393
+ return httpResultObj;
2394
+ };
2395
+ //#endregion
2396
+ }
2030
2397
  }
2031
- export {
2032
- EndpointContext
2033
- };