@modular-rest/server 1.11.13 → 1.12.0

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 (181) hide show
  1. package/.nvmrc +1 -0
  2. package/.prettierrc.json +9 -0
  3. package/.releaserc.json +24 -0
  4. package/README.md +79 -94
  5. package/dist/application.d.ts +29 -0
  6. package/dist/application.js +217 -0
  7. package/dist/class/cms_trigger.d.ts +61 -0
  8. package/dist/class/cms_trigger.js +47 -0
  9. package/dist/class/collection_definition.d.ts +112 -0
  10. package/dist/class/collection_definition.js +87 -0
  11. package/dist/class/combinator.d.ts +43 -0
  12. package/dist/class/combinator.js +174 -0
  13. package/dist/class/database_trigger.d.ts +84 -0
  14. package/dist/class/database_trigger.js +64 -0
  15. package/dist/class/db_schemas.d.ts +25 -0
  16. package/dist/class/db_schemas.js +28 -0
  17. package/dist/class/directory.d.ts +20 -0
  18. package/dist/class/directory.js +87 -0
  19. package/dist/class/paginator.d.ts +31 -0
  20. package/dist/class/paginator.js +43 -0
  21. package/dist/class/reply.d.ts +29 -0
  22. package/dist/class/reply.js +44 -0
  23. package/dist/class/security.d.ts +186 -0
  24. package/dist/class/security.js +178 -0
  25. package/dist/class/trigger_operator.d.ts +92 -0
  26. package/dist/class/trigger_operator.js +99 -0
  27. package/dist/class/user.d.ts +81 -0
  28. package/dist/class/user.js +151 -0
  29. package/dist/class/validator.d.ts +19 -0
  30. package/dist/class/validator.js +101 -0
  31. package/dist/config.d.ts +112 -0
  32. package/dist/config.js +26 -0
  33. package/dist/defult-permissions.d.ts +2 -0
  34. package/dist/defult-permissions.js +31 -0
  35. package/dist/events.d.ts +23 -0
  36. package/dist/events.js +47 -0
  37. package/dist/helper/data_insertion.d.ts +38 -0
  38. package/dist/helper/data_insertion.js +110 -0
  39. package/dist/helper/presetup_services.d.ts +60 -0
  40. package/dist/helper/presetup_services.js +108 -0
  41. package/dist/index.d.ts +118 -0
  42. package/dist/index.js +79 -0
  43. package/dist/middlewares.d.ts +53 -0
  44. package/dist/middlewares.js +106 -0
  45. package/dist/play-test.d.ts +1 -0
  46. package/dist/play-test.js +9 -0
  47. package/dist/services/data_provider/router.d.ts +4 -0
  48. package/dist/services/data_provider/router.js +187 -0
  49. package/dist/services/data_provider/service.d.ts +131 -0
  50. package/dist/services/data_provider/service.js +252 -0
  51. package/dist/services/data_provider/typeCasters.d.ts +9 -0
  52. package/dist/services/data_provider/typeCasters.js +18 -0
  53. package/dist/services/file/db.d.ts +1 -0
  54. package/dist/services/file/db.js +31 -0
  55. package/dist/services/file/router.d.ts +4 -0
  56. package/dist/services/file/router.js +115 -0
  57. package/dist/services/file/service.d.ts +204 -0
  58. package/dist/services/file/service.js +341 -0
  59. package/dist/services/functions/router.d.ts +4 -0
  60. package/dist/services/functions/router.js +67 -0
  61. package/dist/services/functions/service.d.ts +132 -0
  62. package/dist/services/functions/service.js +159 -0
  63. package/dist/services/jwt/router.d.ts +4 -0
  64. package/dist/services/jwt/router.js +99 -0
  65. package/dist/services/jwt/service.d.ts +97 -0
  66. package/dist/services/jwt/service.js +135 -0
  67. package/dist/services/user_manager/db.d.ts +1 -0
  68. package/dist/services/user_manager/db.js +75 -0
  69. package/dist/services/user_manager/permissionManager.d.ts +19 -0
  70. package/dist/services/user_manager/permissionManager.js +42 -0
  71. package/dist/services/user_manager/router.d.ts +4 -0
  72. package/dist/services/user_manager/router.js +195 -0
  73. package/dist/services/user_manager/service.d.ts +317 -0
  74. package/dist/services/user_manager/service.js +628 -0
  75. package/docs/.keep +0 -0
  76. package/docs/system-access-type.md +26 -0
  77. package/package.json +58 -45
  78. package/src/application.ts +206 -0
  79. package/src/class/cms_trigger.ts +68 -0
  80. package/src/class/collection_definition.ts +134 -0
  81. package/src/class/combinator.ts +176 -0
  82. package/src/class/database_trigger.ts +99 -0
  83. package/src/class/db_schemas.ts +44 -0
  84. package/src/class/{directory.js → directory.ts} +40 -18
  85. package/src/class/paginator.ts +51 -0
  86. package/src/class/reply.ts +59 -0
  87. package/src/class/security.ts +250 -0
  88. package/src/class/trigger_operator.ts +142 -0
  89. package/src/class/user.ts +199 -0
  90. package/src/class/validator.ts +123 -0
  91. package/src/config.ts +121 -0
  92. package/src/defult-permissions.ts +31 -0
  93. package/src/events.ts +59 -0
  94. package/src/helper/data_insertion.ts +94 -0
  95. package/src/helper/presetup_services.ts +96 -0
  96. package/src/index.ts +146 -0
  97. package/src/middlewares.ts +75 -0
  98. package/src/play-test.ts +8 -0
  99. package/src/services/data_provider/router.ts +191 -0
  100. package/src/services/data_provider/service.ts +305 -0
  101. package/src/services/data_provider/typeCasters.ts +15 -0
  102. package/src/services/file/db.ts +29 -0
  103. package/src/services/file/router.ts +88 -0
  104. package/src/services/file/service.ts +387 -0
  105. package/src/services/functions/router.ts +34 -0
  106. package/src/services/functions/service.ts +203 -0
  107. package/src/services/jwt/router.ts +73 -0
  108. package/src/services/jwt/service.ts +139 -0
  109. package/src/services/user_manager/db.ts +87 -0
  110. package/src/services/user_manager/permissionManager.ts +49 -0
  111. package/src/services/user_manager/router.ts +193 -0
  112. package/src/services/user_manager/service.ts +698 -0
  113. package/tsconfig.json +16 -9
  114. package/typedoc.mjs +41 -0
  115. package/LICENSE +0 -21
  116. package/package-lock.json +0 -1373
  117. package/src/application.js +0 -239
  118. package/src/class/cms_trigger.js +0 -20
  119. package/src/class/collection_definition.js +0 -33
  120. package/src/class/combinator.js +0 -133
  121. package/src/class/database_trigger.js +0 -20
  122. package/src/class/db_schemas.js +0 -18
  123. package/src/class/paginator.js +0 -31
  124. package/src/class/reply.js +0 -37
  125. package/src/class/security.js +0 -141
  126. package/src/class/trigger_operator.js +0 -39
  127. package/src/class/user.js +0 -112
  128. package/src/class/validator.js +0 -91
  129. package/src/config.js +0 -67
  130. package/src/events.js +0 -15
  131. package/src/helper/data_insertion.js +0 -64
  132. package/src/helper/presetup_services.js +0 -31
  133. package/src/index.js +0 -66
  134. package/src/middlewares.js +0 -44
  135. package/src/services/data_provider/router.js +0 -552
  136. package/src/services/data_provider/service.js +0 -262
  137. package/src/services/data_provider/typeCasters.js +0 -10
  138. package/src/services/file/db.js +0 -29
  139. package/src/services/file/router.js +0 -92
  140. package/src/services/file/service.js +0 -231
  141. package/src/services/functions/router.js +0 -37
  142. package/src/services/functions/service.js +0 -74
  143. package/src/services/jwt/router.js +0 -82
  144. package/src/services/jwt/service.js +0 -37
  145. package/src/services/user_manager/db.js +0 -83
  146. package/src/services/user_manager/permissionManager.js +0 -43
  147. package/src/services/user_manager/router.js +0 -176
  148. package/src/services/user_manager/service.js +0 -377
  149. package/types/application.d.ts +0 -97
  150. package/types/class/cms_trigger.d.ts +0 -24
  151. package/types/class/collection_definition.d.ts +0 -36
  152. package/types/class/combinator.d.ts +0 -30
  153. package/types/class/database_trigger.d.ts +0 -28
  154. package/types/class/db_schemas.d.ts +0 -2
  155. package/types/class/directory.d.ts +0 -2
  156. package/types/class/paginator.d.ts +0 -8
  157. package/types/class/reply.d.ts +0 -8
  158. package/types/class/security.d.ts +0 -109
  159. package/types/class/trigger_operator.d.ts +0 -19
  160. package/types/class/user.d.ts +0 -24
  161. package/types/class/validator.d.ts +0 -9
  162. package/types/config.d.ts +0 -101
  163. package/types/events.d.ts +0 -7
  164. package/types/helper/data_insertion.d.ts +0 -4
  165. package/types/helper/presetup_services.d.ts +0 -5
  166. package/types/index.d.ts +0 -72
  167. package/types/middlewares.d.ts +0 -10
  168. package/types/services/data_provider/router.d.ts +0 -3
  169. package/types/services/data_provider/service.d.ts +0 -40
  170. package/types/services/data_provider/typeCasters.d.ts +0 -3
  171. package/types/services/file/db.d.ts +0 -3
  172. package/types/services/file/router.d.ts +0 -3
  173. package/types/services/file/service.d.ts +0 -81
  174. package/types/services/functions/router.d.ts +0 -3
  175. package/types/services/functions/service.d.ts +0 -23
  176. package/types/services/jwt/router.d.ts +0 -3
  177. package/types/services/jwt/service.d.ts +0 -10
  178. package/types/services/user_manager/db.d.ts +0 -3
  179. package/types/services/user_manager/permissionManager.d.ts +0 -3
  180. package/types/services/user_manager/router.d.ts +0 -3
  181. package/types/services/user_manager/service.d.ts +0 -131
package/package.json CHANGED
@@ -1,47 +1,60 @@
1
1
  {
2
- "name": "@modular-rest/server",
3
- "version": "1.11.13",
4
- "description": "a nodejs module based on KOAJS for developing Rest-APIs in a modular solution.",
5
- "main": "src/index.js",
6
- "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1",
8
- "generate:types": "tsc"
9
- },
10
- "types": "./types/index.d.ts",
11
- "repository": {
12
- "type": "git",
13
- "url": "git+https://github.com/modular-rest/modular-rest.git"
14
- },
15
- "keywords": [
16
- "app",
17
- "rest",
18
- "api",
19
- "koa"
20
- ],
21
- "author": "Navid Shad <navidshad72@gmail.com> (http://navid-shad.ir)",
22
- "license": "MIT",
23
- "bugs": {
24
- "url": "https://github.com/modular-rest/modular-rest/issues"
25
- },
26
- "homepage": "https://github.com/modular-rest/modular-rest#readme",
27
- "dependencies": {
28
- "@koa/cors": "^3.1.0",
29
- "colog": "^1.0.4",
30
- "file-system": "^2.2.2",
31
- "jsonwebtoken": "^8.5.1",
32
- "keypair": "^1.0.4",
33
- "koa": "^2.5.3",
34
- "koa-body": "^4.2.0",
35
- "koa-mount": "^4.0.0",
36
- "koa-router": "^7.4.0",
37
- "koa-static": "^5.0.0",
38
- "mongoose": "^5.10.9",
39
- "nested-property": "^4.0.0"
40
- },
41
- "devDependencies": {
42
- "@types/bson": "4.2.0",
43
- "@types/koa": "^2.14.0",
44
- "@types/koa__cors": "^5.0.0",
45
- "typescript": "^5.3.3"
46
- }
2
+ "name": "@modular-rest/server",
3
+ "version": "1.12.0",
4
+ "description": "TypeScript version of a nodejs module based on KOAJS for developing Rest-APIs in a modular solution.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "dev": "tsc --watch",
10
+ "test": "echo \"Error: no test specified\" && exit 1",
11
+ "play-test": "tsc -p tsconfig.json && node dist/play-test.js",
12
+ "docs": "typedoc --router kind src/index.ts"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/modular-rest/modular-rest.git"
17
+ },
18
+ "keywords": [
19
+ "app",
20
+ "rest",
21
+ "api",
22
+ "koa",
23
+ "typescript"
24
+ ],
25
+ "author": "Navid Shad <navidshad72@gmail.com> (http://navid-shad.ir)",
26
+ "license": "MIT",
27
+ "bugs": {
28
+ "url": "https://github.com/modular-rest/modular-rest/issues"
29
+ },
30
+ "homepage": "https://github.com/modular-rest/modular-rest#readme",
31
+ "dependencies": {
32
+ "@koa/cors": "^3.1.0",
33
+ "colog": "^1.0.4",
34
+ "file-system": "^2.2.2",
35
+ "jsonwebtoken": "^8.5.1",
36
+ "keypair": "^1.0.4",
37
+ "koa": "^2.5.3",
38
+ "koa-body": "6.0.1",
39
+ "koa-mount": "^4.0.0",
40
+ "koa-router": "^7.4.0",
41
+ "koa-static": "^5.0.0",
42
+ "mongoose": "^5.10.9",
43
+ "nested-property": "^4.0.0"
44
+ },
45
+ "devDependencies": {
46
+ "@types/bson": "4.2.0",
47
+ "@types/jsonwebtoken": "^9.0.5",
48
+ "@types/koa": "^2.14.0",
49
+ "@types/koa-mount": "^4.0.5",
50
+ "@types/koa-router": "^7.4.8",
51
+ "@types/koa-static": "^4.0.4",
52
+ "@types/koa__cors": "^5.0.0",
53
+ "@types/mongoose": "^5.10.5",
54
+ "@types/node": "^20.10.0",
55
+ "typedoc": "^0.28.1",
56
+ "typedoc-plugin-markdown": "^4.6.0",
57
+ "typedoc-plugin-missing-exports": "^4.0.0",
58
+ "typescript": "^5.3.3"
59
+ }
47
60
  }
@@ -0,0 +1,206 @@
1
+ import Koa from 'koa';
2
+ import cors from '@koa/cors';
3
+ import koaBody from 'koa-body';
4
+ import koaStatic from 'koa-static';
5
+ import mount from 'koa-mount';
6
+ import path from 'path';
7
+ import { Server } from 'http';
8
+ import Combination from './class/combinator';
9
+ import * as DataProvider from './services/data_provider/service';
10
+ import { MongoOption } from './services/data_provider/service';
11
+ import * as UserService from './services/user_manager/service';
12
+ import { config, setConfig, RestOptions, StaticPathOptions } from './config';
13
+ import { permissionGroups as defaultPermissionGroups } from './defult-permissions';
14
+
15
+ const defaultServiceRoot = __dirname + '/services';
16
+
17
+ /**
18
+ * Create a modular REST instance with Koa and MongoDB support.
19
+ *
20
+ * @param {RestOptions} options - Options for the REST instance
21
+ * @expandType RestOptions
22
+ *
23
+ * @returns {Promise<{ app: Koa; server?: Server }>} - A promise that resolves to the Koa app and server
24
+ *
25
+ * @example
26
+ * import { createRest } from '@modular-rest/server';
27
+ *
28
+ * const app = createRest({
29
+ * port: '80',
30
+ * mongo: {
31
+ * mongoBaseAddress: 'mongodb://localhost:27017',
32
+ * dbPrefix: 'mrest_'
33
+ * },
34
+ * onBeforeInit: (koaApp) => {
35
+ * // do something before init with the koa app
36
+ * }
37
+ * })
38
+ */
39
+ export async function createRest(options: RestOptions): Promise<{ app: Koa; server?: Server }> {
40
+ setConfig({
41
+ port: 3000,
42
+ dontListen: false,
43
+ mongo: {
44
+ mongoBaseAddress: 'mongodb://localhost:27017',
45
+ dbPrefix: 'mrest_',
46
+ },
47
+ adminUser: {
48
+ email: 'admin@email.com',
49
+ password: '@dmin',
50
+ },
51
+ ...options,
52
+ });
53
+
54
+ if (config.permissionGroups === undefined) {
55
+ config.permissionGroups = defaultPermissionGroups;
56
+ }
57
+
58
+ const app = new Koa();
59
+
60
+ /**
61
+ * Plug in Cors
62
+ */
63
+ app.use(cors(config.cors || {}));
64
+
65
+ /**
66
+ * Plug in BodyParser
67
+ */
68
+ const bodyParserOptions = {
69
+ multipart: true,
70
+ ...(config.koaBodyOptions || {}),
71
+ };
72
+ app.use(koaBody(bodyParserOptions));
73
+
74
+ /**
75
+ * Plug In KoaStatic
76
+ */
77
+ if (config.staticPath) {
78
+ const defaultStaticPath = config.staticPath.actualPath || '';
79
+ const defaultStaticRootPath = config.staticPath.path || '/assets';
80
+
81
+ const staticOptions: Partial<StaticPathOptions> = { ...config.staticPath };
82
+
83
+ delete staticOptions.actualPath;
84
+ delete staticOptions.path;
85
+
86
+ app.use(mount(defaultStaticRootPath, koaStatic(defaultStaticPath, staticOptions)));
87
+ }
88
+
89
+ /**
90
+ * Run before hook
91
+ */
92
+ if (config.onBeforeInit) config.onBeforeInit(app);
93
+
94
+ /**
95
+ * Setup default services
96
+ *
97
+ * - Collect and plug in router.js/db.js of default services
98
+ * - Setting up default services
99
+ */
100
+
101
+ // 1. Plug in default routes
102
+ await Combination.combineRoutesByFilePath(path.join(defaultServiceRoot), app);
103
+
104
+ // Collect default databaseDefinitions
105
+ const defaultDatabaseDefinitionList = await Combination.combineModulesByFilePath({
106
+ rootDirectory: defaultServiceRoot,
107
+ filename: {
108
+ name: 'db',
109
+ extension: '.js',
110
+ },
111
+ combineWithRoot: true,
112
+ });
113
+
114
+ // 2. Plug in default databaseDefinitions
115
+ await DataProvider.addCollectionDefinitionByList({
116
+ list: defaultDatabaseDefinitionList,
117
+ mongoOption: config.mongo as MongoOption,
118
+ });
119
+
120
+ /**
121
+ * User Services
122
+ *
123
+ * 3. Plug in routes and database
124
+ */
125
+ if (config.modulesPath) {
126
+ // Plug in user routes
127
+ await Combination.combineRoutesByFilePath(config.modulesPath, app);
128
+
129
+ // Collect user CollectionDefinitions (db.js files)
130
+ let userDatabaseDetail: any[] = [];
131
+ userDatabaseDetail = await Combination.combineModulesByFilePath({
132
+ rootDirectory: config.modulesPath,
133
+ filename: {
134
+ name: 'db',
135
+ extension: '.js',
136
+ },
137
+ combineWithRoot: true,
138
+ });
139
+
140
+ // Combine additional CollectionDefinitions
141
+ if (config.collectionDefinitions) {
142
+ userDatabaseDetail = userDatabaseDetail.concat(config.collectionDefinitions);
143
+ }
144
+
145
+ // Plug in user CollectionDefinitions
146
+ await DataProvider.addCollectionDefinitionByList({
147
+ list: userDatabaseDetail || [],
148
+ mongoOption: config.mongo as MongoOption,
149
+ });
150
+
151
+ // Plug in Verification method
152
+ if (typeof config.verificationCodeGeneratorMethod === 'function') {
153
+ UserService.main.setCustomVerificationCodeGeneratorMethod(
154
+ config.verificationCodeGeneratorMethod
155
+ );
156
+ }
157
+
158
+ // 4. plug in modular functions
159
+ await Combination.combineFunctionsByFilePath({
160
+ rootDirectory: config.modulesPath,
161
+ filename: {
162
+ name: 'functions',
163
+ extension: '.js',
164
+ },
165
+ });
166
+
167
+ // 5. Plug in additional defined functions
168
+ if (config.functions) {
169
+ Combination.addFunctionsByArray(config.functions);
170
+ }
171
+ }
172
+
173
+ // 4. Setting up default services
174
+ try {
175
+ await require('./helper/presetup_services').setup(options);
176
+ } catch (e) {
177
+ return Promise.reject(e);
178
+ }
179
+
180
+ /**
181
+ * Run the server
182
+ *
183
+ * return KOA app object
184
+ */
185
+ return new Promise((done, reject) => {
186
+ try {
187
+ let server: Server | undefined;
188
+
189
+ if (!config.dontListen) {
190
+ server = app.listen(config.port);
191
+
192
+ console.log('\x1b[35m', `KOAS has been launched on: localhost:${config.port}`);
193
+ }
194
+
195
+ // on after init
196
+ if (config.onAfterInit) config.onAfterInit(app);
197
+
198
+ done({
199
+ app,
200
+ server,
201
+ });
202
+ } catch (err) {
203
+ reject(err);
204
+ }
205
+ });
206
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Type for CMS operations that can trigger a callback
3
+ * @typedef {('update-one' | 'insert-one' | 'remove-one')} CmsOperation
4
+ * @description Supported CMS operations:
5
+ * - 'update-one': Triggered when updating a single document in the CMS
6
+ * - 'insert-one': Triggered when inserting a new document in the CMS
7
+ * - 'remove-one': Triggered when removing a document from the CMS
8
+ */
9
+ export type CmsOperation = 'update-one' | 'insert-one' | 'remove-one';
10
+
11
+ /**
12
+ * Context interface for CMS trigger callbacks
13
+ * @interface CmsTriggerContext
14
+ * @property {Record<string, any>} query - The query parameters used in the CMS operation
15
+ * @property {any} queryResult - The result of the CMS operation
16
+ */
17
+ export interface CmsTriggerContext {
18
+ query: Record<string, any>;
19
+ queryResult: any;
20
+ }
21
+
22
+ /**
23
+ * Defines a callback to be executed on specific CMS operations
24
+ * @class CmsTrigger
25
+ * @property {CmsOperation} operation - The CMS operation that triggers the callback
26
+ * @property {Function} callback - The callback function to be executed
27
+ * @example
28
+ * ```typescript
29
+ * const trigger = new CmsTrigger('insert-one', (context) => {
30
+ * console.log('New CMS document inserted:', context.queryResult);
31
+ * // Perform additional actions after CMS document insertion
32
+ * });
33
+ *
34
+ * // Use the trigger in RestOptions
35
+ * const { app } = await createRest({
36
+ * authTriggers: [trigger],
37
+ * // ... other options
38
+ * });
39
+ * ```
40
+ */
41
+ export class CmsTrigger {
42
+ operation: CmsOperation;
43
+ callback: (context: CmsTriggerContext) => void;
44
+
45
+ /**
46
+ * Creates a new CmsTrigger instance
47
+ * @param {CmsOperation} operation - The CMS operation to trigger on
48
+ * @param {Function} [callback=() => {}] - The callback function to execute
49
+ * @example
50
+ * ```typescript
51
+ * // Log all CMS updates
52
+ * const updateTrigger = new CmsTrigger('update-one', (context) => {
53
+ * console.log('CMS document updated:', context.queryResult);
54
+ * });
55
+ *
56
+ * // Track CMS document removals
57
+ * const removeTrigger = new CmsTrigger('remove-one', (context) => {
58
+ * console.log('CMS document removed:', context.queryResult);
59
+ * });
60
+ * ```
61
+ */
62
+ constructor(operation: CmsOperation, callback: (context: CmsTriggerContext) => void = () => {}) {
63
+ this.operation = operation;
64
+ this.callback = callback;
65
+ }
66
+ }
67
+
68
+ export default CmsTrigger;
@@ -0,0 +1,134 @@
1
+ import { Schema } from 'mongoose';
2
+ import { Permission } from './security';
3
+ import { DatabaseTrigger } from './database_trigger';
4
+
5
+ /**
6
+ * Configuration options for creating a collection definition.
7
+ * This interface defines the structure for configuring MongoDB collections with their associated
8
+ * schemas, permissions, and triggers.
9
+ *
10
+ * @inline
11
+ *
12
+ */
13
+ interface CollectionDefinitionOptions {
14
+ /** The name of the database where the collection resides */
15
+ database: string;
16
+ /** The name of the collection to be configured */
17
+ collection: string;
18
+ /** List of permissions controlling access to the collection */
19
+ permissions: Permission[];
20
+ /** Optional database triggers for custom operations */
21
+ triggers?: DatabaseTrigger[];
22
+
23
+ /**
24
+ * Mongoose schema definition for the collection
25
+ * @type {Schema}
26
+ * @see https://mongoosejs.com/docs/5.x/docs/guide.html
27
+ */
28
+ schema: Schema;
29
+ }
30
+
31
+ /**
32
+ * To have define any collection in your database you haveto use below method in your `db.[js|ts]` file and export an array of CollectionDefinition instances.
33
+ *
34
+ * @param {CollectionDefinitionOptions} options - The options for the collection
35
+ * @expandType CollectionDefinitionOptions
36
+ *
37
+ * @returns A new instance of CollectionDefinition
38
+ *
39
+ * @public
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * import { defineCollection } from '@modular-rest/server';
44
+ *
45
+ * export default [
46
+ * defineCollection({
47
+ * database: 'users',
48
+ * collection: 'info',
49
+ * // schema: Schema,
50
+ * // permissions: Permission[]
51
+ * // trigger: DatabaseTrigger[]
52
+ * })
53
+ * ]
54
+ * ```
55
+ */
56
+ export function defineCollection(options: CollectionDefinitionOptions) {
57
+ return new CollectionDefinition(options);
58
+ }
59
+
60
+ /**
61
+ * A class that represents a MongoDB collection configuration. Provides full support for schema validation, access control through permissions,
62
+ * and custom triggers for various database operations.
63
+ *
64
+ * @hideconstructor
65
+ *
66
+ * @deprecated Use `defineCollection` instead.
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * const userSchema = new Schema({
71
+ * name: String,
72
+ * email: String,
73
+ * age: Number
74
+ * });
75
+ *
76
+ * const collection = new CollectionDefinition({
77
+ * database: 'myapp',
78
+ * collection: 'users',
79
+ * schema: userSchema,
80
+ * permissions: [
81
+ * new Permission({
82
+ * type: 'user_access',
83
+ * read: true,
84
+ * write: true
85
+ * })
86
+ * ],
87
+ * triggers: [
88
+ * new DatabaseTrigger('insert-one', (data) => {
89
+ * console.log('New user created:', data);
90
+ * })
91
+ * ]
92
+ * });
93
+ * ```
94
+ *
95
+ * @private
96
+ */
97
+ export class CollectionDefinition {
98
+ /** @readonly The name of the database */
99
+ database: string;
100
+
101
+ /** @readonly The name of the collection */
102
+ collection: string;
103
+
104
+ /** @readonly Mongoose schema definition */
105
+ schema: Schema;
106
+
107
+ /** @readonly List of permissions for the collection */
108
+ permissions: Permission[];
109
+
110
+ /** @readonly Optional database triggers */
111
+ triggers?: DatabaseTrigger[];
112
+
113
+ /**
114
+ * Creates a new CollectionDefinition instance
115
+ *
116
+ * @param options - Configuration options for the collection
117
+ * @returns A new instance of CollectionDefinition
118
+ *
119
+ * @beta
120
+ */
121
+ constructor({
122
+ database,
123
+ collection,
124
+ schema,
125
+ permissions,
126
+ triggers,
127
+ }: CollectionDefinitionOptions) {
128
+ this.database = database;
129
+ this.collection = collection;
130
+ this.schema = schema;
131
+ this.permissions = permissions;
132
+ this.triggers = triggers;
133
+ }
134
+ }
@@ -0,0 +1,176 @@
1
+ import Router from 'koa-router';
2
+ import Koa from 'koa';
3
+ import * as directory from './directory';
4
+ import { addFunction } from '../services/functions/service';
5
+
6
+ interface FilenameOption {
7
+ name: string;
8
+ extension: string;
9
+ }
10
+
11
+ interface ModuleOptions {
12
+ rootDirectory: string;
13
+ filename: FilenameOption;
14
+ combineWithRoot?: boolean;
15
+ convertToArray?: boolean;
16
+ }
17
+
18
+ interface FunctionOptions {
19
+ rootDirectory: string;
20
+ filename: FilenameOption;
21
+ }
22
+
23
+ class Combinator {
24
+ async combineRoutesByFilePath(rootDirectory: string, app: Koa): Promise<void> {
25
+ // find route paths
26
+ const option = {
27
+ name: 'router',
28
+ filter: ['.js'],
29
+ };
30
+
31
+ let routerPaths: string[] = [];
32
+ try {
33
+ routerPaths = await directory.find(rootDirectory, option);
34
+ } catch (e) {
35
+ console.log(e);
36
+ }
37
+
38
+ // create and combine routes into the app
39
+ for (let i = 0; i < routerPaths.length; i++) {
40
+ const service = require(routerPaths[i]);
41
+ const name = service.name;
42
+
43
+ const serviceRouter = new Router();
44
+ serviceRouter.use(`/${name}`, service.main.routes());
45
+
46
+ app.use(serviceRouter.routes());
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Combine modules from files in a directory
52
+ * @param options - Configuration options
53
+ */
54
+ async combineModulesByFilePath({
55
+ rootDirectory,
56
+ filename,
57
+ combineWithRoot,
58
+ convertToArray,
59
+ }: ModuleOptions): Promise<any> {
60
+ // find route paths
61
+ let rootObject_temp: any;
62
+
63
+ const option = {
64
+ name: filename.name,
65
+ filter: [filename.extension],
66
+ };
67
+
68
+ let modulesPath: string[] = [];
69
+ try {
70
+ modulesPath = await directory.find(rootDirectory, option);
71
+ } catch (e) {
72
+ console.log(e);
73
+ }
74
+
75
+ // create and combine routes into the app
76
+ for (let i = 0; i < modulesPath.length; i++) {
77
+ const moduleObject = require(modulesPath[i]);
78
+
79
+ // act by otherOption
80
+ if (combineWithRoot) {
81
+ if (moduleObject.name) delete moduleObject.name;
82
+
83
+ if (Array.isArray(moduleObject)) {
84
+ if (!rootObject_temp) rootObject_temp = [];
85
+
86
+ rootObject_temp = [...rootObject_temp, ...moduleObject];
87
+ } else {
88
+ rootObject_temp = this.extendObj(rootObject_temp, moduleObject);
89
+ }
90
+ }
91
+ // default act
92
+ else {
93
+ const name = moduleObject.name;
94
+ rootObject_temp[name] = moduleObject;
95
+ }
96
+ }
97
+
98
+ // options
99
+ // convertToArray
100
+ if (convertToArray) {
101
+ rootObject_temp = Object.values(rootObject_temp);
102
+ }
103
+
104
+ // set result to main rootObject
105
+ return rootObject_temp;
106
+ }
107
+
108
+ /**
109
+ * Combine functions from files in a directory
110
+ * @param options - Function options
111
+ */
112
+ async combineFunctionsByFilePath({ rootDirectory, filename }: FunctionOptions): Promise<void> {
113
+ // find route paths
114
+ const option = {
115
+ name: filename.name,
116
+ filter: [filename.extension],
117
+ };
118
+
119
+ let functionsPaths: string[] = [];
120
+ try {
121
+ functionsPaths = await directory.find(rootDirectory, option);
122
+ } catch (e) {
123
+ console.log(e);
124
+ }
125
+
126
+ // create and combine routes into the app
127
+ for (let i = 0; i < functionsPaths.length; i++) {
128
+ const modularFunctions = require(functionsPaths[i]);
129
+
130
+ if (!modularFunctions.functions) {
131
+ throw new Error(`Module file ${functionsPaths[i]} does not have functions property.`);
132
+ }
133
+
134
+ // if array
135
+ if (Array.isArray(modularFunctions.functions)) {
136
+ for (const moduleFunction of modularFunctions.functions) {
137
+ addFunction(moduleFunction);
138
+ }
139
+ } else {
140
+ addFunction(modularFunctions.functions);
141
+ }
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Add functions from an array
147
+ * @param functionList - List of functions to add
148
+ */
149
+ addFunctionsByArray(functionList: any[]): void {
150
+ for (const functionItem of functionList) {
151
+ addFunction(functionItem);
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Extend an object with properties from another
157
+ * @param obj - Target object
158
+ * @param src - Source object
159
+ * @returns Extended object
160
+ */
161
+ extendObj(obj: any, src: any): any {
162
+ obj = obj || {};
163
+ for (const key in src) {
164
+ if (Object.prototype.hasOwnProperty.call(src, key)) obj[key] = src[key];
165
+ }
166
+ return obj;
167
+ }
168
+
169
+ static get instance(): Combinator {
170
+ return instance;
171
+ }
172
+ }
173
+
174
+ const instance = new Combinator();
175
+
176
+ export = instance;