@modular-rest/server 1.11.5 → 1.11.7

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.
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modular-rest/server",
3
- "version": "1.11.5",
3
+ "version": "1.11.7",
4
4
  "description": "a nodejs module based on KOAJS for developing Rest-APIs in a modular solution.",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -10,7 +10,7 @@
10
10
  "types": "./types/index.d.ts",
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "git+https://github.com/navidshad/modular-rest.git"
13
+ "url": "git+https://github.com/modular-rest/modular-rest.git"
14
14
  },
15
15
  "keywords": [
16
16
  "app",
@@ -21,9 +21,9 @@
21
21
  "author": "Navid Shad <navidshad72@gmail.com> (http://navid-shad.ir)",
22
22
  "license": "MIT",
23
23
  "bugs": {
24
- "url": "https://github.com/navidshad/modular-rest/issues"
24
+ "url": "https://github.com/modular-rest/modular-rest/issues"
25
25
  },
26
- "homepage": "https://github.com/navidshad/modular-rest#readme",
26
+ "homepage": "https://github.com/modular-rest/modular-rest#readme",
27
27
  "dependencies": {
28
28
  "@koa/cors": "^3.1.0",
29
29
  "colog": "^1.0.4",
@@ -32,8 +32,9 @@
32
32
  "keypair": "^1.0.4",
33
33
  "koa": "^2.5.3",
34
34
  "koa-body": "^4.2.0",
35
+ "koa-mount": "^4.0.0",
35
36
  "koa-router": "^7.4.0",
36
- "koa-static-server": "^1.5.2",
37
+ "koa-static": "^5.0.0",
37
38
  "mongoose": "^5.10.9",
38
39
  "nested-property": "^4.0.0"
39
40
  },
@@ -43,4 +44,4 @@
43
44
  "@types/koa__cors": "^5.0.0",
44
45
  "typescript": "^5.3.3"
45
46
  }
46
- }
47
+ }
@@ -1,7 +1,8 @@
1
1
  const koa = require("koa");
2
2
  const cors = require("@koa/cors");
3
3
  const koaBody = require("koa-body");
4
- const koaStatic = require("koa-static-server");
4
+ const koaStatic = require("koa-static");
5
+ const mount = require("koa-mount");
5
6
  const path = require("path");
6
7
  const Combination = require("./class/combinator");
7
8
  const DataProvider = require("./services/data_provider/service");
@@ -13,8 +14,8 @@ const defaultServiceRoot = __dirname + "/services";
13
14
  * @typedef {import('koa')} Koa
14
15
  * @typedef {import('http').Server} server
15
16
  * @typedef {import('@koa/cors').Options} Cors
16
- * @typedef {import('./class/security').PermissionGroup} PermissionGroup
17
- * @typedef {import('./class/database_trigger.js')} DatabaseTrigger
17
+ * @typedef {import('./class/security.js').PermissionGroup} PermissionGroup
18
+ * @typedef {import('./class/cms_trigger.js')} CmsTrigger
18
19
  */
19
20
 
20
21
  const { config, setConfig } = require("./config");
@@ -25,18 +26,19 @@ const { config, setConfig } = require("./config");
25
26
  * cors?: Cors; // CORS options.
26
27
  * modulesPath?: string; // Root directory of your router.js/db.js files.
27
28
  * uploadDirectory?: string; // Root directory of your uploaded files.
28
- * staticPath?: {
29
- * rootDir?: string; // Root directory of your static files.
30
- * rootPath?: string; // Root path of your static files.
31
- * notFoundFile?: string; // Not found file.
32
- * log?: boolean; // Log requests to console.
33
- * last?: boolean; // Don't execute any downstream middleware.
34
- * maxage?: number; // Browser cache max-age in milliseconds.
35
- * hidden?: boolean; // Allow transfer of hidden files.
36
- * gzip?: boolean; // Try to serve the gzipped version of a file automatically when gzip is supported by a client and if the requested file exists.
37
- * brotli?: boolean; // Try to serve the brotli version of a file automatically when brotli is supported by a client and if the requested file exists.
38
- * index?: string; // Index file.
39
- * };
29
+ * koaBodyOptions?: object; // Options for koa-body.
30
+ * staticPath?: {
31
+ * rootDir: string; // Root directory of your static files.
32
+ * rootPath: string; // Root path of your static files, defaults to '/assets'.
33
+ * maxage?: number; // Browser cache max-age in milliseconds. Defaults to 0.
34
+ * hidden?: boolean; // Allow transfer of hidden files. Defaults to false.
35
+ * index?: string; // Default file name. Defaults to 'index.html'.
36
+ * defer?: boolean; // If true, serves after return next(), allowing any downstream middleware to respond first. Defaults to false.
37
+ * gzip?: boolean; // Try to serve the gzipped version of a file automatically when gzip is supported by a client and if the requested file with .gz extension exists. Defaults to true.
38
+ * br?: boolean; // Try to serve the brotli version of a file automatically when brotli is supported by a client and if the requested file with .br extension exists. Note that brotli is only accepted over https. Defaults to false.
39
+ * setHeaders?: Function; // Function to set custom headers on response.
40
+ * extensions?: boolean|Array; // Try to match extensions from passed array to search for file when no extension is suffixed in URL. First found is served. Defaults to false.
41
+ * };
40
42
  * onBeforeInit?: (koaApp:Koa) => void; // A callback called before initializing the Koa server.
41
43
  * onAfterInit?: (koaApp:Koa) => void; // A callback called after server initialization.
42
44
  * port?: number; // Server port.
@@ -57,7 +59,8 @@ const { config, setConfig } = require("./config");
57
59
  * verificationCodeGeneratorMethod: () => string; // A method to return a verification code when registering a new user.
58
60
  * collectionDefinitions?: CollectionDefinition[]; // An array of additional collection definitions.
59
61
  * permissionGroups?: PermissionGroup[]; // An array of additional permission groups.
60
- * authTriggers?: DatabaseTrigger[]; // An array of additional database triggers for the auth collection.
62
+ * authTriggers?: CmsTrigger[]; // An array of additional database triggers for the auth collection.
63
+ * fileTriggers?: CmsTrigger[]; // An array of additional database triggers for the auth collection.
61
64
  * }} options
62
65
  * @returns {Promise<{app: Koa, server: Server}>}
63
66
  */
@@ -90,6 +93,7 @@ async function createRest(options) {
90
93
  */
91
94
  const bodyParserOptions = {
92
95
  multipart: true,
96
+ ...(config.koaBodyOptions || {}),
93
97
  };
94
98
  app.use(koaBody(bodyParserOptions));
95
99
 
@@ -97,7 +101,18 @@ async function createRest(options) {
97
101
  * Plug In KoaStatic
98
102
  */
99
103
  if (config.staticPath) {
100
- app.use(koaStatic(config.staticPath));
104
+ const defaultStaticPath = config.staticPath.rootDir;
105
+ const defaultStaticRootPath = config.staticPath.rootPath || "/assets";
106
+
107
+ delete config.staticPath.rootDir;
108
+ delete config.staticPath.rootPath;
109
+
110
+ app.use(
111
+ mount(
112
+ defaultStaticRootPath,
113
+ koaStatic(defaultStaticPath, config.staticPath)
114
+ )
115
+ );
101
116
  }
102
117
 
103
118
  /**
@@ -0,0 +1,20 @@
1
+ /**
2
+ * `CmsTrigger` is a class that defines a callback to be called on a specific database transaction.
3
+ *
4
+ * @class
5
+ */
6
+ class CmsTrigger {
7
+ /**
8
+ * Creates a new instance of `CmsTrigger`.
9
+ *
10
+ * @param {'update-one' | 'insert-one' | 'remove-one' } operation - The operation to be triggered.
11
+ * @param {function({query: any, queryResult: any}): void} [callback=(context) => {}] - The callback to be called when the operation is executed. The callback function takes an object as parameter with two properties: 'query' and 'queryResult'.
12
+ * @constructor
13
+ */
14
+ constructor(operation, callback = (context) => {}) {
15
+ this.operation = operation;
16
+ this.callback = callback;
17
+ }
18
+ }
19
+
20
+ module.exports = CmsTrigger;
@@ -11,6 +11,7 @@ module.exports = {
11
11
  // Tag being used as the parent dir for files
12
12
  // uploadDir/$format/$tag/timestamp.format
13
13
  tag: String,
14
+ size: Number,
14
15
  },
15
16
  { timestamps: true }
16
17
  ),
@@ -6,8 +6,9 @@
6
6
  * @returns {Object} - An object containing pagination information.
7
7
  */
8
8
  function create(count, perPage, page) {
9
- let totalPgaes = Math.ceil(count / perPage);
10
- if (page > totalPgaes) page = 1;
9
+ const totalPages = Math.ceil(count / perPage);
10
+
11
+ if (page > totalPages) page = 1;
11
12
 
12
13
  let from = 0;
13
14
  if (perPage == 1) from = page - 1;
@@ -16,7 +17,7 @@ function create(count, perPage, page) {
16
17
  if (page <= 1) from = 0;
17
18
 
18
19
  let result = {
19
- 'pages': totalPgaes,
20
+ 'pages': totalPages,
20
21
  'page': page,
21
22
  'from': from,
22
23
  'to': perPage
@@ -9,7 +9,7 @@ function create(status, detail = {}) {
9
9
 
10
10
  let result = detail || {};
11
11
 
12
- // defin status
12
+ // define status
13
13
  switch (status) {
14
14
  case 's':
15
15
  result['status'] = 'success';
@@ -8,13 +8,13 @@
8
8
  function validate(obj, requiredFields) {
9
9
  /*
10
10
  this method could validate an Object by given field's name list and return bool.
11
- - requiredFields: is a string that contains keys being spareted by " ".
11
+ - requiredFields: is a string that contains keys being spared by " ".
12
12
  */
13
13
  let type = typeof requiredFields;
14
14
  let result;
15
15
 
16
16
  if (type == 'string')
17
- result = ckeckSimple(obj, requiredFields);
17
+ result = checkSimple(obj, requiredFields);
18
18
  else if (type == 'object')
19
19
  result = checkComplex(obj, requiredFields);
20
20
 
@@ -25,7 +25,7 @@ function validate(obj, requiredFields) {
25
25
 
26
26
  module.exports = validate;
27
27
 
28
- function ckeckSimple(obj, requiredFields = '') {
28
+ function checkSimple(obj, requiredFields = '') {
29
29
  let isValide = false;
30
30
  let requires = requiredFields.split(' ');
31
31
 
package/src/config.js CHANGED
@@ -1,27 +1,28 @@
1
1
  /**
2
2
  * @typedef {import('koa')} Koa
3
3
  * @typedef {import('@koa/cors').Options} Cors
4
- * @typedef {import('./class/collection_definition')} CollectionDefinition
5
- * @typedef {import('./class/security').PermissionGroup} PermissionGroup
6
- * @typedef {import('./class/database_trigger.js')} DatabaseTrigger
4
+ * @typedef {import('./class/collection_definition.js')} CollectionDefinition
5
+ * @typedef {import('./class/security.js').PermissionGroup} PermissionGroup
6
+ * @typedef {import('./class/cms_trigger.js')} CmsTrigger
7
7
  */
8
8
 
9
9
  /**
10
10
  * @typedef {{
11
11
  * cors?: Cors; // CORS options.
12
12
  * modulesPath?: string; // Root directory of your router.js/db.js files.
13
- * staticPath?: {
14
- * rootDir?: string; // Root directory of your static files.
15
- * rootPath?: string; // Root path of your static files.
16
- * notFoundFile?: string; // Not found file.
17
- * log?: boolean; // Log requests to console.
18
- * last?: boolean; // Don't execute any downstream middleware.
19
- * maxage?: number; // Browser cache max-age in milliseconds.
20
- * hidden?: boolean; // Allow transfer of hidden files.
21
- * gzip?: boolean; // Try to serve the gzipped version of a file automatically when gzip is supported by a client and if the requested file exists.
22
- * brotli?: boolean; // Try to serve the brotli version of a file automatically when brotli is supported by a client and if the requested file exists.
23
- * index?: string; // Index file.
24
- * };
13
+ * koaBodyOptions?: object; // Options for koa-body.
14
+ * staticPath?: {
15
+ * rootDir: string; // Root directory of your static files.
16
+ * rootPath: string; // Root path of your static files, defaults to '/assets'.
17
+ * maxage?: number; // Browser cache max-age in milliseconds. Defaults to 0.
18
+ * hidden?: boolean; // Allow transfer of hidden files. Defaults to false.
19
+ * index?: string; // Default file name. Defaults to 'index.html'.
20
+ * defer?: boolean; // If true, serves after return next(), allowing any downstream middleware to respond first. Defaults to false.
21
+ * gzip?: boolean; // Try to serve the gzipped version of a file automatically when gzip is supported by a client and if the requested file with .gz extension exists. Defaults to true.
22
+ * br?: boolean; // Try to serve the brotli version of a file automatically when brotli is supported by a client and if the requested file with .br extension exists. Note that brotli is only accepted over https. Defaults to false.
23
+ * setHeaders?: Function; // Function to set custom headers on response.
24
+ * extensions?: boolean|Array; // Try to match extensions from passed array to search for file when no extension is suffixed in URL. First found is served. Defaults to false.
25
+ * };
25
26
  * onBeforeInit?: (koaApp:Koa) => void; // A callback called before initializing the Koa server.
26
27
  * onAfterInit?: (koaApp:Koa) => void; // A callback called after server initialization.
27
28
  * port?: number; // Server port.
@@ -43,6 +44,7 @@
43
44
  * collectionDefinitions?: CollectionDefinition[]; // An array of additional collection definitions.
44
45
  * permissionGroups?: PermissionGroup[]; // An array of additional permission groups.
45
46
  * authTriggers?: DatabaseTrigger[]; // An array of additional database triggers for the auth collection.
47
+ * fileTriggers?: CmsTrigger[]; // An array of additional database triggers for the auth collection.
46
48
  * }} Config
47
49
  * @exports Config
48
50
  */
package/src/index.js CHANGED
@@ -9,36 +9,58 @@ const validator = require("./class/validator");
9
9
  const { getCollection } = require("./services/data_provider/service");
10
10
  const { defineFunction } = require("./services/functions/service");
11
11
  const TypeCasters = require("./services/data_provider/typeCasters");
12
+ const userManager = require("./services/user_manager/service");
13
+ const {
14
+ getFile,
15
+ getFileLink,
16
+ getFilePath,
17
+ removeFile,
18
+ storeFile,
19
+ } = require("./services/file/service");
12
20
 
13
21
  // Base class
14
22
  const CollectionDefinition = require("./class/collection_definition");
15
23
  const Schemas = require("./class/db_schemas");
16
24
  const DatabaseTrigger = require("./class/database_trigger");
25
+ const CmsTrigger = require("./class/cms_trigger");
17
26
  const SecurityClass = require("./class/security");
18
27
  const middleware = require("./middlewares");
19
- const userManager = require("./services/user_manager/service");
20
28
 
21
29
  module.exports = {
22
30
  createRest,
23
31
 
24
- // Route utilities
25
- reply,
26
- TypeCasters,
27
- paginator,
28
- validator,
29
-
30
- // Service utilities
31
- getCollection,
32
- defineFunction,
33
-
34
32
  // Database
35
33
  CollectionDefinition,
36
34
  Schemas,
37
35
  Schema,
38
36
  DatabaseTrigger,
37
+ CmsTrigger,
39
38
  ...SecurityClass,
40
39
 
41
- // Middlewares
40
+ // Function
41
+ defineFunction,
42
+
43
+ // Private utilities
44
+ TypeCasters,
45
+ validator,
46
+
47
+ // Route utilities
48
+ reply,
49
+ paginator,
50
+
51
+ // Database utilities
52
+ getCollection,
53
+
54
+ // File Utilities
55
+ getFile,
56
+ getFileLink,
57
+ getFilePath,
58
+ removeFile,
59
+ storeFile,
60
+
61
+ // Middleware utilities
42
62
  middleware,
63
+
64
+ // User utilities
43
65
  userManager: userManager.main,
44
66
  };
@@ -1,9 +1,10 @@
1
- let Mongoose = require('mongoose');
1
+ const Mongoose = require('mongoose');
2
+
2
3
  module.exports = {
3
4
  'ObjectId': Mongoose.Types.ObjectId,
4
5
  'Date': (dateValue) => {
5
- let strDate = dateValue.toString();
6
- let mongoDateFormateInString = new Date(strDate).toISOString().split('T')[0];
6
+ const strDate = dateValue.toString();
7
+ const mongoDateFormateInString = new Date(strDate).toISOString().split('T')[0];
7
8
  return new Date(mongoDateFormateInString);
8
9
  }
9
10
  }
@@ -1,27 +1,29 @@
1
- var mongoose = require('mongoose');
2
- var Schemas = require('../../class/db_schemas');
1
+ var mongoose = require("mongoose");
2
+ var Schemas = require("../../class/db_schemas");
3
3
 
4
- let CollectionDefinition = require('../../class/collection_definition');
5
- let { Permission, PermissionTypes } = require('../../class/security');
4
+ let CollectionDefinition = require("../../class/collection_definition");
5
+ let { Permission, PermissionTypes } = require("../../class/security");
6
+ const { config } = require("../../config");
6
7
 
7
8
  module.exports = [
8
- new CollectionDefinition({
9
- db: 'cms',
10
- collection: 'file',
11
- schema: Schemas.file,
12
- permissions: [
13
- new Permission({
14
- type: PermissionTypes.upload_file_access,
15
- read: true,
16
- write: true,
17
- onlyOwnData: false,
18
- }),
19
- new Permission({
20
- type: PermissionTypes.remove_file_access,
21
- read: true,
22
- write: true,
23
- onlyOwnData: false,
24
- }),
25
- ],
26
- }),
27
- ]
9
+ new CollectionDefinition({
10
+ db: "cms",
11
+ collection: "file",
12
+ schema: Schemas.file,
13
+ permissions: [
14
+ new Permission({
15
+ type: PermissionTypes.upload_file_access,
16
+ read: true,
17
+ write: true,
18
+ onlyOwnData: false,
19
+ }),
20
+ new Permission({
21
+ type: PermissionTypes.remove_file_access,
22
+ read: true,
23
+ write: true,
24
+ onlyOwnData: false,
25
+ }),
26
+ ],
27
+ triggers: config.fileTriggers || [],
28
+ }),
29
+ ];
@@ -1,9 +1,10 @@
1
- const fs = require('file-system');
2
- const pathModule = require('path');
3
- const DataProvider = require('./../data_provider/service')
1
+ const fs = require("file-system");
2
+ const pathModule = require("path");
3
+ const DataProvider = require("./../data_provider/service");
4
+ const triggerService = require("./../../class/trigger_operator");
5
+ const { config } = require("./../../config");
4
6
 
5
7
  class FileService {
6
-
7
8
  constructor() {
8
9
  this.directory = null;
9
10
  }
@@ -13,9 +14,10 @@ class FileService {
13
14
  }
14
15
 
15
16
  /**
16
- *
17
- * @param {string} fileType
18
- *
17
+ *
18
+ * @param {string} fileType
19
+ * @param {string} tag
20
+ *
19
21
  * @returns storedFile
20
22
  * @returns storedFile.fileName
21
23
  * @returns storedFile.directory
@@ -23,119 +25,207 @@ class FileService {
23
25
  * @returns storedFile.fileFormat
24
26
  */
25
27
  createStoredDetail(fileType, tag) {
28
+ const typeParts = fileType.split("/");
29
+ const fileFormat = typeParts[1] || typeParts[0] || "unknown";
30
+
31
+ const time = new Date().getTime();
32
+ const fileName = `${time}.${fileFormat}`;
26
33
 
27
- let time = new Date().getTime();
28
- let fileFormat = fileType.split('/')[1];
29
- let fileName = `${time}.${fileFormat}`;
30
- let fullPath = pathModule.join(this.directory, fileFormat, tag, fileName);
34
+ const fullPath = pathModule.join(
35
+ FileService.instance.directory,
36
+ fileFormat,
37
+ tag,
38
+ fileName
39
+ );
31
40
 
32
41
  return { fileName, fullPath, fileFormat };
33
42
  }
34
43
 
35
-
36
44
  /**
37
- *
38
- * @param args
39
- * @param {file} args.file file object
40
- * @param {string} args.ownerId file object
45
+ * Stores a file, removes the given temporary file, and submits file details into the database.
46
+ *
47
+ * @param {Object} options - The options for storing the file.
48
+ * @param {Object} options.file - The file to be stored.
49
+ * @param {string} options.file.path - The path of the file.
50
+ * @param {string} options.file.type - The type of the file.
51
+ * @param {string} options.file.name - The original name of the file.
52
+ * @param {number} options.file.size - The size of the file.
53
+ * @param {string} options.ownerId - The ID of the owner of the file.
54
+ * @param {string} options.tag - The tag associated with the file.
55
+ * @param {boolean} [options.removeFileAfterStore=true] - Whether to remove the file after storing it.
56
+ *
57
+ * @returns {Promise} A promise that resolves with the document of the stored file.
58
+ *
59
+ * @throws {string} If the upload directory has not been set.
41
60
  */
42
- storeFile({ file, ownerId, tag }) {
43
-
44
- if (!this.directory)
45
- throw 'upload directory has not been set.'
61
+ storeFile({ file, ownerId, tag, removeFileAfterStore = true }) {
62
+ if (!FileService.instance.directory)
63
+ throw "upload directory has not been set.";
46
64
 
47
65
  let storedFile;
48
66
 
49
- return new Promise(async (done, reject) =>
50
- /**
51
- * Store file and remove temp file
52
- */ {
53
-
54
- storedFile = this.createStoredDetail(file.type, tag);
67
+ return (
68
+ new Promise(async (done, reject) => /**
69
+ * Store file and remove temp file
70
+ */ {
71
+ storedFile = FileService.instance.createStoredDetail(file.type, tag);
55
72
 
56
- fs.copyFile(file.path, storedFile.fullPath, {
57
- done: (err) => {
58
- if (err) reject(err);
59
- else done();
73
+ fs.copyFile(file.path, storedFile.fullPath, {
74
+ done: (err) => {
75
+ if (err) reject(err);
76
+ else done();
60
77
 
61
- // remove temp file
62
- fs.fs.unlinkSync(file.path);
63
- }
64
- });
65
- })
66
- /**
67
- * Submit file detail into database
68
- */
69
- .then(() => {
70
-
71
- // Get collection model for access to relative collection
72
- let CollectionModel = DataProvider.getCollection('cms', 'file');
73
-
74
- // Create new document
75
- let doc = new CollectionModel({
76
- owner: ownerId,
77
- fileName: storedFile.fileName,
78
- originalName: file.name,
79
- format: storedFile.fileFormat,
80
- tag,
78
+ // remove temp file
79
+ if (removeFileAfterStore) fs.fs.unlinkSync(file.path);
80
+ },
81
81
  });
82
-
83
- return doc.save().then(() => doc);
84
-
85
- }).catch(err => {
86
-
87
- // remove stored file
88
- fs.fs.unlinkSync(storedFile.fullPath);
89
-
90
- throw err;
91
82
  })
83
+ /**
84
+ * Submit file detail into database
85
+ */
86
+ .then(() => {
87
+ // Get collection model for access to relative collection
88
+ const CollectionModel = DataProvider.getCollection("cms", "file");
89
+
90
+ const data = {
91
+ owner: ownerId,
92
+ fileName: storedFile.fileName,
93
+ originalName: file.name,
94
+ format: storedFile.fileFormat,
95
+ tag,
96
+ size: file.size,
97
+ };
98
+
99
+ // Create new document
100
+ const doc = new CollectionModel(data);
101
+
102
+ return doc.save().then((savedDoc) => {
103
+ triggerService.call("insert-one", "cms", "file", {
104
+ query: null,
105
+ queryResult: savedDoc,
106
+ });
107
+
108
+ return savedDoc;
109
+ });
110
+ })
111
+ .catch((err) => {
112
+ // remove stored file
113
+ fs.fs.unlinkSync(storedFile.fullPath);
114
+
115
+ throw err;
116
+ })
117
+ );
92
118
  }
93
119
 
120
+ /**
121
+ * Removes a file from the disk.
122
+ *
123
+ * @param {string} path - The path of the file to be removed.
124
+ * @returns {Promise} A promise that resolves if the file is successfully removed, and rejects if an error occurs.
125
+ */
94
126
  removeFromDisc(path) {
95
127
  return new Promise((done, reject) => {
96
128
  fs.fs.unlink(path, (err) => {
97
- if (err) reject()
98
- else done()
129
+ if (err) reject();
130
+ else done();
99
131
  });
100
- })
132
+ });
101
133
  }
102
134
 
135
+ /**
136
+ * Removes a file from the database and the disk.
137
+ *
138
+ * @param {string} fileId - The ID of the file to be removed.
139
+ * @returns {Promise} A promise that resolves if the file is successfully removed, and rejects if an error occurs.
140
+ * @throws Will throw an error if upload directory has not been set.
141
+ */
103
142
  removeFile(fileId) {
104
-
105
- if (!this.directory)
106
- throw 'upload directory has not been set.'
143
+ if (!FileService.instance.directory)
144
+ throw "upload directory has not been set.";
107
145
 
108
146
  return new Promise(async (done, reject) => {
109
- let CollectionModel = DataProvider.getCollection('cms', 'file');
147
+ let CollectionModel = DataProvider.getCollection("cms", "file");
110
148
  let fileDoc = await CollectionModel.findOne({ _id: fileId }).exec();
111
149
 
112
150
  if (!fileDoc) {
113
- reject('file not found');
151
+ reject("file not found");
114
152
  return;
115
153
  }
116
154
 
117
- await CollectionModel.deleteOne({ _id: fileId }).exec()
155
+ await CollectionModel.deleteOne({ _id: fileId })
156
+ .exec()
118
157
  .then(() => {
119
-
120
158
  // create file path
121
- let filePath = pathModule.join(this.directory, fileDoc.format, fileDoc.tag, fileDoc.fileName);
159
+ const filePath = pathModule.join(
160
+ FileService.instance.directory,
161
+ fileDoc.format,
162
+ fileDoc.tag,
163
+ fileDoc.fileName
164
+ );
122
165
 
123
166
  // Remove file from disc
124
- return this.removeFromDisc(filePath)
167
+ return FileService.instance
168
+ .removeFromDisc(filePath)
125
169
  .catch(async (err) => {
126
-
127
- // Recreate fileDoc if removing file operation has error
170
+ // Recreate fileDoc if removing file operation has error
128
171
  await new CollectionModel(fileDoc).save();
129
172
 
130
173
  throw err;
131
- })
132
-
174
+ });
175
+ })
176
+ .then(() => {
177
+ triggerService.call("remove-one", "cms", "file", {
178
+ query: { _id: fileId },
179
+ queryResult: null,
180
+ });
133
181
  })
134
182
  .then(done)
135
- .catch(reject)
136
- })
183
+ .catch(reject);
184
+ });
185
+ }
186
+
187
+ /**
188
+ * Retrieves a file from the database.
189
+ *
190
+ * @param {string} fileId - The ID of the file to be retrieved.
191
+ * @returns {Promise} A promise that resolves with the file document, or rejects if an error occurs.
192
+ */
193
+ getFile(fileId) {
194
+ const CollectionModel = DataProvider.getCollection("cms", "file");
195
+
196
+ return CollectionModel.findOne({ _id: fileId }).exec();
197
+ }
198
+
199
+ /**
200
+ * Retrieves the link of a file.
201
+ *
202
+ * @param {string} fileId - The ID of the file to get the link for.
203
+ * @returns {Promise} A promise that resolves with the file link, or rejects if an error occurs.
204
+ */
205
+ async getFileLink(fileId) {
206
+ const fileDoc = await FileService.instance.getFile(fileId);
207
+
208
+ const link =
209
+ config.staticPath.rootPath +
210
+ `/${fileDoc.format}/${fileDoc.tag}/` +
211
+ fileDoc.fileName;
212
+
213
+ return link;
214
+ }
215
+
216
+ async getFilePath(fileId) {
217
+ const { fileName, format, tag } = await FileService.instance.getFile(
218
+ fileId
219
+ );
220
+ const fullPath = pathModule.join(
221
+ FileService.instance.directory,
222
+ format,
223
+ tag,
224
+ fileName
225
+ );
226
+ return fullPath;
137
227
  }
138
228
  }
139
229
 
140
- FileService.instance = new FileService()
141
- module.exports = FileService.instance;
230
+ FileService.instance = new FileService();
231
+ module.exports = FileService.instance;
@@ -14,18 +14,21 @@ class UserManager {
14
14
  }
15
15
 
16
16
  /**
17
- * Set a custom method for generating verification codes.
18
- * @param {function} method - A method that returns a random verification code.
17
+ * Sets a custom method for generating verification codes.
18
+ *
19
+ * @param {Function} generatorMethod - A function that returns a random verification code.
20
+ * @returns {void}
19
21
  */
20
- setCustomVerificationCodeGeneratorMethod(method) {
21
- this.verificationCodeGeneratorMethod = method;
22
+ setCustomVerificationCodeGeneratorMethod(generatorMethod) {
23
+ this.verificationCodeGeneratorMethod = generatorMethod;
22
24
  }
23
25
 
24
26
  /**
25
- * Generate a verification code.
26
- * @param {string} id - The ID for which to generate the verification code.
27
- * @param {string} idType - The type of the ID.
28
- * @returns {string} The generated verification code.
27
+ * Get a user by their ID.
28
+ *
29
+ * @param {string} id - The ID of the user.
30
+ * @returns {Promise<User>} A promise that resolves to the user.
31
+ * @throws {Error} If the user is not found.
29
32
  */
30
33
  generateVerificationCode(id, idType) {
31
34
  if (this.verificationCodeGeneratorMethod)
@@ -37,6 +40,7 @@ class UserManager {
37
40
 
38
41
  /**
39
42
  * Get a user by their ID.
43
+ *
40
44
  * @param {string} id - The ID of the user.
41
45
  * @returns {Promise<User>} A promise that resolves to the user.
42
46
  * @throws {string} If the user is not found.
@@ -63,6 +67,7 @@ class UserManager {
63
67
 
64
68
  /**
65
69
  * Get a user by their identity.
70
+ *
66
71
  * @param {string} id - The identity of the user.
67
72
  * @param {string} idType - The type of the identity (phone or email).
68
73
  * @returns {Promise<User>} A promise that resolves to the user.
@@ -95,6 +100,7 @@ class UserManager {
95
100
 
96
101
  /**
97
102
  * Get a user by their token.
103
+ *
98
104
  * @param {string} token - The token of the user.
99
105
  * @returns {Promise<User>} A promise that resolves to the user.
100
106
  */
@@ -105,6 +111,7 @@ class UserManager {
105
111
 
106
112
  /**
107
113
  * Check if a verification code is valid.
114
+ *
108
115
  * @param {string} id - The ID of the user.
109
116
  * @param {string} code - The verification code.
110
117
  * @returns {boolean} Whether the verification code is valid.
@@ -123,6 +130,7 @@ class UserManager {
123
130
 
124
131
  /**
125
132
  * Login a user and return their token.
133
+ *
126
134
  * @param {string} id - The ID of the user.
127
135
  * @param {string} idType - The type of the ID (phone or email).
128
136
  * @param {string} password - The password of the user.
@@ -172,6 +180,7 @@ class UserManager {
172
180
 
173
181
  /**
174
182
  * Issue a token for a user.
183
+ *
175
184
  * @param {string} email - The email of the user.
176
185
  * @returns {Promise<string>} A promise that resolves to the token of the user.
177
186
  * @throws {string} If the user is not found.
@@ -199,6 +208,7 @@ class UserManager {
199
208
 
200
209
  /**
201
210
  * Login as an anonymous user.
211
+ *
202
212
  * @returns {Promise<string>} A promise that resolves to the token of the anonymous user.
203
213
  * @throws {string} If the anonymous user is not found.
204
214
  */
@@ -245,6 +255,7 @@ class UserManager {
245
255
 
246
256
  /**
247
257
  * Register a temporary ID.
258
+ *
248
259
  * @param {string} id - The ID to register.
249
260
  * @param {string} type - The type of the ID.
250
261
  * @param {string} code - The verification code.
@@ -255,6 +266,7 @@ class UserManager {
255
266
 
256
267
  /**
257
268
  * Submit a password for a temporary ID.
269
+ *
258
270
  * @param {string} id - The ID.
259
271
  * @param {string} password - The password.
260
272
  * @param {string} code - The verification code.
@@ -285,6 +297,7 @@ class UserManager {
285
297
 
286
298
  /**
287
299
  * Change the password for a temporary ID.
300
+ *
288
301
  * @param {string} id - The ID.
289
302
  * @param {string} password - The new password.
290
303
  * @param {string} code - The verification code.
@@ -310,6 +323,7 @@ class UserManager {
310
323
 
311
324
  /**
312
325
  * Register a user.
326
+ *
313
327
  * @param {Object} detail - The details of the user.
314
328
  * @returns {Promise<string>} A promise that resolves to the ID of the new user.
315
329
  * @throws {string} If the user could not be registered.
@@ -342,6 +356,7 @@ class UserManager {
342
356
 
343
357
  /**
344
358
  * Change the password of a user.
359
+ *
345
360
  * @param {Object} query - The query to find the user.
346
361
  * @param {string} newPass - The new password.
347
362
  * @returns {Promise<void>} A promise that resolves when the operation is complete.
package/test.js DELETED
@@ -1,10 +0,0 @@
1
- const { createRest } = require('.');
2
- const { PermissionTypes } = require('./src/class/security');
3
-
4
- { createRest } require('./src/application');
5
- {PermissionTypes} require('./src/class/security');
6
-
7
- createRest({
8
- uploadDirectory: 'uploads',
9
- port: '3001'
10
- });