@adaptivestone/framework 5.0.0-beta.10 → 5.0.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/LICENCE +1 -1
- package/cliCommand.ts +10 -0
- package/dist/Cli.d.ts +7 -0
- package/dist/Cli.js +19 -0
- package/dist/Cli.js.map +1 -0
- package/dist/cluster.d.ts +1 -0
- package/dist/cluster.js +18 -0
- package/dist/cluster.js.map +1 -0
- package/dist/commands/CreateUser.d.ts +32 -0
- package/dist/commands/CreateUser.js +81 -0
- package/dist/commands/CreateUser.js.map +1 -0
- package/dist/commands/Documentation.d.ts +5 -0
- package/dist/commands/Documentation.js +15 -0
- package/dist/commands/Documentation.js.map +1 -0
- package/dist/commands/DropIndex.d.ts +16 -0
- package/dist/commands/DropIndex.js +30 -0
- package/dist/commands/DropIndex.js.map +1 -0
- package/dist/commands/GenerateRandomBytes.d.ts +7 -0
- package/dist/commands/GenerateRandomBytes.js +18 -0
- package/dist/commands/GenerateRandomBytes.js.map +1 -0
- package/dist/commands/GetOpenApiJson.d.ts +17 -0
- package/dist/commands/GetOpenApiJson.js +272 -0
- package/dist/commands/GetOpenApiJson.js.map +1 -0
- package/dist/commands/SyncIndexes.d.ts +6 -0
- package/dist/commands/SyncIndexes.js +32 -0
- package/dist/commands/SyncIndexes.js.map +1 -0
- package/dist/commands/migration/Create.d.ts +18 -0
- package/dist/commands/migration/Create.js +57 -0
- package/dist/commands/migration/Create.js.map +1 -0
- package/dist/commands/migration/Migrate.d.ts +6 -0
- package/dist/commands/migration/Migrate.js +46 -0
- package/dist/commands/migration/Migrate.js.map +1 -0
- package/dist/config/auth.d.ts +6 -0
- package/dist/config/auth.js +7 -0
- package/dist/config/auth.js.map +1 -0
- package/dist/config/http.d.ts +8 -0
- package/dist/config/http.js +10 -0
- package/dist/config/http.js.map +1 -0
- package/dist/config/i18n.d.ts +10 -0
- package/dist/config/i18n.js +13 -0
- package/dist/config/i18n.js.map +1 -0
- package/dist/config/ipDetector.d.ts +5 -0
- package/dist/config/ipDetector.js +15 -0
- package/dist/config/ipDetector.js.map +1 -0
- package/dist/config/log.d.ts +22 -0
- package/dist/config/log.js +23 -0
- package/dist/config/log.js.map +1 -0
- package/dist/config/mongo.d.ts +4 -0
- package/dist/config/mongo.js +4 -0
- package/dist/config/mongo.js.map +1 -0
- package/dist/config/rateLimiter.d.ts +15 -0
- package/dist/config/rateLimiter.js +17 -0
- package/dist/config/rateLimiter.js.map +1 -0
- package/dist/config/redis.d.ts +5 -0
- package/dist/config/redis.js +5 -0
- package/dist/config/redis.js.map +1 -0
- package/dist/config/validate.d.ts +4 -0
- package/dist/config/validate.js +4 -0
- package/dist/config/validate.js.map +1 -0
- package/dist/controllers/Auth.d.ts +74 -0
- package/dist/controllers/Auth.js +181 -0
- package/dist/controllers/Auth.js.map +1 -0
- package/dist/controllers/Home.d.ts +15 -0
- package/dist/controllers/Home.js +24 -0
- package/dist/controllers/Home.js.map +1 -0
- package/dist/controllers/index.d.ts +16 -0
- package/dist/controllers/index.js +59 -0
- package/dist/controllers/index.js.map +1 -0
- package/dist/folderConfig.d.ts +34 -0
- package/dist/folderConfig.js +15 -0
- package/dist/folderConfig.js.map +1 -0
- package/dist/helpers/files.d.ts +16 -0
- package/dist/helpers/files.js +73 -0
- package/dist/helpers/files.js.map +1 -0
- package/dist/helpers/logger.d.ts +4 -0
- package/dist/helpers/logger.js +28 -0
- package/dist/helpers/logger.js.map +1 -0
- package/dist/helpers/redis/clearNamespace.d.ts +3 -0
- package/dist/helpers/redis/clearNamespace.js +15 -0
- package/dist/helpers/redis/clearNamespace.js.map +1 -0
- package/dist/helpers/yup.d.ts +13 -0
- package/{helpers → dist/helpers}/yup.js +8 -9
- package/dist/helpers/yup.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/models/Lock.d.ts +62 -0
- package/dist/models/Lock.js +94 -0
- package/dist/models/Lock.js.map +1 -0
- package/dist/models/Migration.d.ts +11 -0
- package/dist/models/Migration.js +14 -0
- package/dist/models/Migration.js.map +1 -0
- package/dist/models/Sequence.d.ts +16 -0
- package/dist/models/Sequence.js +16 -0
- package/dist/models/Sequence.js.map +1 -0
- package/dist/models/User.d.ts +101 -0
- package/dist/models/User.js +230 -0
- package/dist/models/User.js.map +1 -0
- package/dist/modules/AbstractCommand.d.ts +30 -0
- package/dist/modules/AbstractCommand.js +44 -0
- package/dist/modules/AbstractCommand.js.map +1 -0
- package/dist/modules/AbstractConnector.d.ts +5 -0
- package/dist/modules/AbstractConnector.js +8 -0
- package/dist/modules/AbstractConnector.js.map +1 -0
- package/dist/modules/AbstractController.d.ts +90 -0
- package/dist/modules/AbstractController.js +324 -0
- package/dist/modules/AbstractController.js.map +1 -0
- package/dist/modules/AbstractModel.d.ts +32 -0
- package/dist/modules/AbstractModel.js +73 -0
- package/dist/modules/AbstractModel.js.map +1 -0
- package/dist/modules/Base.d.ts +29 -0
- package/dist/modules/Base.js +54 -0
- package/dist/modules/Base.js.map +1 -0
- package/dist/modules/BaseCli.d.ts +25 -0
- package/dist/modules/BaseCli.js +138 -0
- package/dist/modules/BaseCli.js.map +1 -0
- package/dist/server.d.ts +110 -0
- package/dist/server.js +372 -0
- package/dist/server.js.map +1 -0
- package/dist/services/cache/Cache.d.ts +31 -0
- package/dist/services/cache/Cache.js +115 -0
- package/dist/services/cache/Cache.js.map +1 -0
- package/dist/services/documentation/DocumentationGenerator.d.ts +11 -0
- package/dist/services/documentation/DocumentationGenerator.js +134 -0
- package/dist/services/documentation/DocumentationGenerator.js.map +1 -0
- package/dist/services/http/HttpServer.d.ts +35 -0
- package/dist/services/http/HttpServer.js +71 -0
- package/dist/services/http/HttpServer.js.map +1 -0
- package/dist/services/http/middleware/AbstractMiddleware.d.ts +25 -0
- package/dist/services/http/middleware/AbstractMiddleware.js +43 -0
- package/dist/services/http/middleware/AbstractMiddleware.js.map +1 -0
- package/dist/services/http/middleware/Auth.d.ts +9 -0
- package/dist/services/http/middleware/Auth.js +18 -0
- package/dist/services/http/middleware/Auth.js.map +1 -0
- package/dist/services/http/middleware/Cors.d.ts +10 -0
- package/dist/services/http/middleware/Cors.js +36 -0
- package/dist/services/http/middleware/Cors.js.map +1 -0
- package/dist/services/http/middleware/GetUserByToken.d.ts +19 -0
- package/dist/services/http/middleware/GetUserByToken.js +40 -0
- package/dist/services/http/middleware/GetUserByToken.js.map +1 -0
- package/dist/services/http/middleware/I18n.d.ts +26 -0
- package/dist/services/http/middleware/I18n.js +97 -0
- package/dist/services/http/middleware/I18n.js.map +1 -0
- package/dist/services/http/middleware/IpDetector.d.ts +12 -0
- package/dist/services/http/middleware/IpDetector.js +51 -0
- package/dist/services/http/middleware/IpDetector.js.map +1 -0
- package/dist/services/http/middleware/Pagination.d.ts +27 -0
- package/dist/services/http/middleware/Pagination.js +47 -0
- package/dist/services/http/middleware/Pagination.js.map +1 -0
- package/dist/services/http/middleware/PrepareAppInfo.d.ts +8 -0
- package/dist/services/http/middleware/PrepareAppInfo.js +17 -0
- package/dist/services/http/middleware/PrepareAppInfo.js.map +1 -0
- package/dist/services/http/middleware/RateLimiter.d.ts +18 -0
- package/dist/services/http/middleware/RateLimiter.js +106 -0
- package/dist/services/http/middleware/RateLimiter.js.map +1 -0
- package/dist/services/http/middleware/RequestLogger.d.ts +8 -0
- package/dist/services/http/middleware/RequestLogger.js +18 -0
- package/dist/services/http/middleware/RequestLogger.js.map +1 -0
- package/dist/services/http/middleware/RequestParser.d.ts +8 -0
- package/dist/services/http/middleware/RequestParser.js +35 -0
- package/dist/services/http/middleware/RequestParser.js.map +1 -0
- package/dist/services/http/middleware/Role.d.ts +9 -0
- package/dist/services/http/middleware/Role.js +24 -0
- package/dist/services/http/middleware/Role.js.map +1 -0
- package/dist/services/validate/ValidateService.d.ts +31 -0
- package/dist/services/validate/ValidateService.js +96 -0
- package/dist/services/validate/ValidateService.js.map +1 -0
- package/dist/services/validate/drivers/AbstractValidator.d.ts +14 -0
- package/dist/services/validate/drivers/AbstractValidator.js +32 -0
- package/dist/services/validate/drivers/AbstractValidator.js.map +1 -0
- package/dist/services/validate/drivers/CustomValidator.d.ts +14 -0
- package/dist/services/validate/drivers/CustomValidator.js +48 -0
- package/dist/services/validate/drivers/CustomValidator.js.map +1 -0
- package/dist/services/validate/drivers/YupValidator.d.ts +13 -0
- package/dist/services/validate/drivers/YupValidator.js +86 -0
- package/dist/services/validate/drivers/YupValidator.js.map +1 -0
- package/dist/tests/globalSetupVitest.d.ts +2 -0
- package/dist/tests/globalSetupVitest.js +29 -0
- package/dist/tests/globalSetupVitest.js.map +1 -0
- package/dist/tests/setupVitest.d.ts +1 -0
- package/dist/tests/setupVitest.js +99 -0
- package/dist/tests/setupVitest.js.map +1 -0
- package/package.json +19 -10
- package/Cli.js +0 -21
- package/cluster.js +0 -25
- package/commands/.gitkeep +0 -0
- package/commands/CreateUser.js +0 -106
- package/commands/Documentation.js +0 -17
- package/commands/DropIndex.js +0 -38
- package/commands/GenerateRandomBytes.js +0 -21
- package/commands/GetOpenApiJson.js +0 -336
- package/commands/SyncIndexes.js +0 -40
- package/commands/migration/Create.js +0 -72
- package/commands/migration/Migrate.js +0 -56
- package/config/auth.js +0 -9
- package/config/http.js +0 -9
- package/config/i18n.js +0 -12
- package/config/ipDetector.js +0 -14
- package/config/log.js +0 -22
- package/config/mongo.js +0 -3
- package/config/rateLimiter.js +0 -16
- package/config/redis.js +0 -4
- package/config/validate.js +0 -3
- package/controllers/Auth.js +0 -201
- package/controllers/Home.js +0 -28
- package/controllers/index.js +0 -60
- package/eslint.config.js +0 -68
- package/folderConfig.js +0 -13
- package/helpers/files.js +0 -76
- package/helpers/logger.js +0 -16
- package/helpers/redis/clearNamespace.js +0 -14
- package/index.js +0 -8
- package/jsconfig.json +0 -9
- package/locales/en/translation.json +0 -27
- package/locales/ru/translation.json +0 -27
- package/migrations/.gitkeep +0 -0
- package/models/Lock.js +0 -107
- package/models/Migration.js +0 -15
- package/models/Sequence.js +0 -22
- package/models/User.js +0 -280
- package/modules/AbstractCommand.js +0 -52
- package/modules/AbstractConnector.js +0 -9
- package/modules/AbstractController.js +0 -406
- package/modules/AbstractModel.d.ts +0 -48
- package/modules/AbstractModel.js +0 -92
- package/modules/Base.d.ts +0 -37
- package/modules/Base.js +0 -64
- package/modules/BaseCli.js +0 -157
- package/server.d.ts +0 -100
- package/server.js +0 -439
- package/services/cache/Cache.d.ts +0 -35
- package/services/cache/Cache.js +0 -124
- package/services/documentation/DocumentationGenerator.js +0 -169
- package/services/http/HttpServer.js +0 -89
- package/services/http/middleware/AbstractMiddleware.js +0 -51
- package/services/http/middleware/Auth.js +0 -20
- package/services/http/middleware/Cors.js +0 -46
- package/services/http/middleware/GetUserByToken.js +0 -47
- package/services/http/middleware/I18n.js +0 -117
- package/services/http/middleware/IpDetector.js +0 -59
- package/services/http/middleware/Pagination.js +0 -57
- package/services/http/middleware/PrepareAppInfo.js +0 -18
- package/services/http/middleware/RateLimiter.js +0 -134
- package/services/http/middleware/RequestLogger.js +0 -22
- package/services/http/middleware/RequestParser.js +0 -40
- package/services/http/middleware/Role.js +0 -29
- package/services/messaging/email/resources/.gitkeep +0 -1
- package/services/messaging/email/templates/.gitkeep +0 -0
- package/services/messaging/email/templates/recovery/html.pug +0 -8
- package/services/messaging/email/templates/recovery/subject.pug +0 -2
- package/services/messaging/email/templates/recovery/text.pug +0 -3
- package/services/messaging/email/templates/verification/html.pug +0 -10
- package/services/messaging/email/templates/verification/subject.pug +0 -1
- package/services/messaging/email/templates/verification/text.pug +0 -1
- package/services/validate/ValidateService.js +0 -157
- package/services/validate/drivers/AbstractValidator.js +0 -37
- package/services/validate/drivers/CustomValidator.js +0 -51
- package/services/validate/drivers/YupValidator.js +0 -103
- package/tests/globalSetupVitest.js +0 -35
- package/tests/setup.js +0 -120
- package/tests/setupVitest.js +0 -111
- package/types/Expand.d.ts +0 -11
- package/types/ICommandArguments.d.ts +0 -41
- package/types/TFoldersConfig.d.ts +0 -20
- package/views/404.pug +0 -3
- package/views/home.pug +0 -3
- package/views/layouts/base.pug +0 -39
- package/vitest.config.js +0 -17
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import AbstractModel from '../modules/AbstractModel.ts';
|
|
2
|
+
import type { IAbstractModel, IAbstractModelMethods } from '../modules/AbstractModel.ts';
|
|
3
|
+
interface ILock {
|
|
4
|
+
_id: string;
|
|
5
|
+
expiredAt: Date;
|
|
6
|
+
}
|
|
7
|
+
interface IStatic extends IAbstractModel<ILock, IAbstractModelMethods<ILock>> {
|
|
8
|
+
acquireLock(name: string, ttlSeconds?: number): Promise<boolean>;
|
|
9
|
+
releaseLock(name: string): Promise<boolean>;
|
|
10
|
+
waitForUnlock(name: string): Promise<void>;
|
|
11
|
+
getLockData(name: string): Promise<{
|
|
12
|
+
ttl: number;
|
|
13
|
+
}>;
|
|
14
|
+
getLocksData(names: string[]): Promise<{
|
|
15
|
+
name: string;
|
|
16
|
+
ttl: number;
|
|
17
|
+
}[]>;
|
|
18
|
+
}
|
|
19
|
+
declare class Lock extends AbstractModel<ILock, IAbstractModelMethods<ILock>, IStatic> {
|
|
20
|
+
initHooks(): void;
|
|
21
|
+
get modelSchema(): {
|
|
22
|
+
_id: {
|
|
23
|
+
type: StringConstructor;
|
|
24
|
+
required: boolean;
|
|
25
|
+
};
|
|
26
|
+
expiredAt: {
|
|
27
|
+
type: DateConstructor;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* acquire lock based on lock name
|
|
32
|
+
* @param {string} name
|
|
33
|
+
* @param {number} [ttlSeconds=30]
|
|
34
|
+
*/
|
|
35
|
+
static acquireLock(this: Lock['mongooseModel'], name: string, ttlSeconds?: number): Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* release lock based on lock name
|
|
38
|
+
* @param {string} name
|
|
39
|
+
*/
|
|
40
|
+
static releaseLock(this: Lock['mongooseModel'], name: string): Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* wait lock based on lock name
|
|
43
|
+
* @param {string} name
|
|
44
|
+
*/
|
|
45
|
+
static waitForUnlock(this: Lock['mongooseModel'], name: string): Promise<unknown>;
|
|
46
|
+
/**
|
|
47
|
+
* get lock remaining time based on lock name
|
|
48
|
+
* @param {string} name
|
|
49
|
+
*/
|
|
50
|
+
static getLockData(this: Lock['mongooseModel'], name: string): Promise<{
|
|
51
|
+
ttl: number;
|
|
52
|
+
}>;
|
|
53
|
+
/**
|
|
54
|
+
* get lock remaining time based on lock name
|
|
55
|
+
* @param {string[]} names
|
|
56
|
+
*/
|
|
57
|
+
static getLocksData(this: Lock['mongooseModel'], names: string[]): Promise<{
|
|
58
|
+
name: string;
|
|
59
|
+
ttl: number;
|
|
60
|
+
}[]>;
|
|
61
|
+
}
|
|
62
|
+
export default Lock;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import AbstractModel from "../modules/AbstractModel.js";
|
|
2
|
+
class Lock extends AbstractModel {
|
|
3
|
+
initHooks() {
|
|
4
|
+
this.mongooseSchema.index({ expiredAt: 1 }, { expireAfterSeconds: 0 });
|
|
5
|
+
}
|
|
6
|
+
// eslint-disable-next-line class-methods-use-this
|
|
7
|
+
get modelSchema() {
|
|
8
|
+
return {
|
|
9
|
+
_id: { type: String, required: true },
|
|
10
|
+
expiredAt: {
|
|
11
|
+
type: Date,
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* acquire lock based on lock name
|
|
17
|
+
* @param {string} name
|
|
18
|
+
* @param {number} [ttlSeconds=30]
|
|
19
|
+
*/
|
|
20
|
+
static async acquireLock(name, ttlSeconds = 30) {
|
|
21
|
+
try {
|
|
22
|
+
await this.create({
|
|
23
|
+
_id: name,
|
|
24
|
+
expiredAt: new Date(Date.now() + ttlSeconds * 1000),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
if (error.code !== 11000) {
|
|
29
|
+
// not a duplicate leys
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* release lock based on lock name
|
|
38
|
+
* @param {string} name
|
|
39
|
+
*/
|
|
40
|
+
static async releaseLock(name) {
|
|
41
|
+
const res = await this.deleteOne({ _id: name });
|
|
42
|
+
if (res.acknowledged && res.deletedCount) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* wait lock based on lock name
|
|
49
|
+
* @param {string} name
|
|
50
|
+
*/
|
|
51
|
+
static async waitForUnlock(name) {
|
|
52
|
+
const res = await this.findOne({ _id: name });
|
|
53
|
+
if (!res) {
|
|
54
|
+
return Promise.resolve();
|
|
55
|
+
}
|
|
56
|
+
return new Promise((resolve) => {
|
|
57
|
+
const stream = this.watch([
|
|
58
|
+
{ $match: { operationType: 'delete', 'documentKey._id': name } },
|
|
59
|
+
]);
|
|
60
|
+
stream.on('change', () => {
|
|
61
|
+
stream.close();
|
|
62
|
+
resolve(true);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* get lock remaining time based on lock name
|
|
68
|
+
* @param {string} name
|
|
69
|
+
*/
|
|
70
|
+
static async getLockData(name) {
|
|
71
|
+
const res = await this.findOne({ _id: name });
|
|
72
|
+
if (!res) {
|
|
73
|
+
return { ttl: 0 };
|
|
74
|
+
}
|
|
75
|
+
return { ttl: res.expiredAt.getTime() - Date.now() };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* get lock remaining time based on lock name
|
|
79
|
+
* @param {string[]} names
|
|
80
|
+
*/
|
|
81
|
+
static async getLocksData(names) {
|
|
82
|
+
const res = await this.find({ _id: { $in: names } });
|
|
83
|
+
const lockMap = new Map(res.map((lock) => [lock._id, lock]));
|
|
84
|
+
return names.map((name) => {
|
|
85
|
+
const lock = lockMap.get(name);
|
|
86
|
+
return {
|
|
87
|
+
name,
|
|
88
|
+
ttl: lock ? lock.expiredAt.getTime() - Date.now() : 0,
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export default Lock;
|
|
94
|
+
//# sourceMappingURL=Lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Lock.js","sourceRoot":"","sources":["../../src/models/Lock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default Migration;
|
|
2
|
+
declare class Migration extends AbstractModel<any, import("../modules/AbstractModel.ts").IAbstractModelMethods<any>, import("../modules/AbstractModel.ts").IAbstractModel<any, import("../modules/AbstractModel.ts").IAbstractModelMethods<any>>> {
|
|
3
|
+
constructor(app: import("../server.ts").IApp, callback?: () => void);
|
|
4
|
+
get modelSchema(): {
|
|
5
|
+
migrationFile: {
|
|
6
|
+
type: StringConstructor;
|
|
7
|
+
unique: boolean;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
import AbstractModel from '../modules/AbstractModel.ts';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import AbstractModel from "../modules/AbstractModel.js";
|
|
2
|
+
class Migration extends AbstractModel {
|
|
3
|
+
// eslint-disable-next-line class-methods-use-this
|
|
4
|
+
get modelSchema() {
|
|
5
|
+
return {
|
|
6
|
+
migrationFile: {
|
|
7
|
+
type: String,
|
|
8
|
+
unique: true,
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export default Migration;
|
|
14
|
+
//# sourceMappingURL=Migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Migration.js","sourceRoot":"","sources":["../../src/models/Migration.js"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,6BAA6B,CAAC;AAExD,MAAM,SAAU,SAAQ,aAAa;IACnC,kDAAkD;IAClD,IAAI,WAAW;QACb,OAAO;YACL,aAAa,EAAE;gBACb,IAAI,EAAE,MAAM;gBACZ,MAAM,EAAE,IAAI;aACb;SACF,CAAC;IACJ,CAAC;CACF;AAED,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export default Sequence;
|
|
2
|
+
declare class Sequence extends AbstractModel<any, import("../modules/AbstractModel.ts").IAbstractModelMethods<any>, import("../modules/AbstractModel.ts").IAbstractModel<any, import("../modules/AbstractModel.ts").IAbstractModelMethods<any>>> {
|
|
3
|
+
static getSequence(forType: any): Promise<any>;
|
|
4
|
+
constructor(app: import("../server.ts").IApp, callback?: () => void);
|
|
5
|
+
get modelSchema(): {
|
|
6
|
+
_id: {
|
|
7
|
+
type: StringConstructor;
|
|
8
|
+
required: boolean;
|
|
9
|
+
};
|
|
10
|
+
seq: {
|
|
11
|
+
type: NumberConstructor;
|
|
12
|
+
default: number;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
import AbstractModel from '../modules/AbstractModel.ts';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import AbstractModel from "../modules/AbstractModel.js";
|
|
2
|
+
class Sequence extends AbstractModel {
|
|
3
|
+
// eslint-disable-next-line class-methods-use-this
|
|
4
|
+
get modelSchema() {
|
|
5
|
+
return {
|
|
6
|
+
_id: { type: String, required: true },
|
|
7
|
+
seq: { type: Number, default: 1 },
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
static async getSequence(forType) {
|
|
11
|
+
const sequence = await this.findByIdAndUpdate({ _id: forType }, { $inc: { seq: 1 } }, { new: true, upsert: true });
|
|
12
|
+
return sequence.seq;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export default Sequence;
|
|
16
|
+
//# sourceMappingURL=Sequence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Sequence.js","sourceRoot":"","sources":["../../src/models/Sequence.js"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,6BAA6B,CAAC;AAExD,MAAM,QAAS,SAAQ,aAAa;IAClC,kDAAkD;IAClD,IAAI,WAAW;QACb,OAAO;YACL,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;YACrC,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE;SAClC,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO;QAC9B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAC3C,EAAE,GAAG,EAAE,OAAO,EAAE,EAChB,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EACpB,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAC5B,CAAC;QACF,OAAO,QAAQ,CAAC,GAAG,CAAC;IACtB,CAAC;CACF;AAED,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export default User;
|
|
2
|
+
declare class User extends AbstractModel<any, import("../modules/AbstractModel.ts").IAbstractModelMethods<any>, import("../modules/AbstractModel.ts").IAbstractModel<any, import("../modules/AbstractModel.ts").IAbstractModelMethods<any>>> {
|
|
3
|
+
static getUserByEmailAndPassword(email: any, password: any): Promise<any>;
|
|
4
|
+
static hashPassword(password: any): Promise<any>;
|
|
5
|
+
static getUserByToken(token: any): Promise<any>;
|
|
6
|
+
static getUserByEmail(email: any): Promise<any>;
|
|
7
|
+
static generateUserPasswordRecoveryToken(userMongoose: any): Promise<{
|
|
8
|
+
token: any;
|
|
9
|
+
until: number;
|
|
10
|
+
}>;
|
|
11
|
+
static getUserByPasswordRecoveryToken(passwordRecoveryToken: any): Promise<any>;
|
|
12
|
+
static generateUserVerificationToken(userMongoose: any): Promise<{
|
|
13
|
+
token: any;
|
|
14
|
+
until: number;
|
|
15
|
+
}>;
|
|
16
|
+
static getUserByVerificationToken(verificationToken: any): Promise<any>;
|
|
17
|
+
constructor(app: any);
|
|
18
|
+
hashRounds: any;
|
|
19
|
+
saltSecret: any;
|
|
20
|
+
get modelSchema(): {
|
|
21
|
+
avatar: {
|
|
22
|
+
type: StringConstructor;
|
|
23
|
+
maxlength: number;
|
|
24
|
+
};
|
|
25
|
+
name: {
|
|
26
|
+
first: {
|
|
27
|
+
type: StringConstructor;
|
|
28
|
+
maxlength: number;
|
|
29
|
+
};
|
|
30
|
+
last: {
|
|
31
|
+
type: StringConstructor;
|
|
32
|
+
maxlength: number;
|
|
33
|
+
};
|
|
34
|
+
nick: {
|
|
35
|
+
minlength: number;
|
|
36
|
+
maxlength: number;
|
|
37
|
+
type: StringConstructor;
|
|
38
|
+
index: {
|
|
39
|
+
unique: boolean;
|
|
40
|
+
partialFilterExpression: {
|
|
41
|
+
'name.nick': {
|
|
42
|
+
$type: string;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
password: StringConstructor;
|
|
49
|
+
email: {
|
|
50
|
+
type: StringConstructor;
|
|
51
|
+
maxlength: number;
|
|
52
|
+
index: {
|
|
53
|
+
unique: boolean;
|
|
54
|
+
partialFilterExpression: {
|
|
55
|
+
email: {
|
|
56
|
+
$type: string;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
sessionTokens: {
|
|
62
|
+
token: StringConstructor;
|
|
63
|
+
valid: DateConstructor;
|
|
64
|
+
}[];
|
|
65
|
+
verificationTokens: {
|
|
66
|
+
until: DateConstructor;
|
|
67
|
+
token: StringConstructor;
|
|
68
|
+
}[];
|
|
69
|
+
passwordRecoveryTokens: {
|
|
70
|
+
until: DateConstructor;
|
|
71
|
+
token: StringConstructor;
|
|
72
|
+
}[];
|
|
73
|
+
permissions: never[];
|
|
74
|
+
roles: never[];
|
|
75
|
+
isVerified: {
|
|
76
|
+
type: BooleanConstructor;
|
|
77
|
+
default: boolean;
|
|
78
|
+
};
|
|
79
|
+
locale: {
|
|
80
|
+
type: StringConstructor;
|
|
81
|
+
default: string;
|
|
82
|
+
};
|
|
83
|
+
languages: StringConstructor[];
|
|
84
|
+
};
|
|
85
|
+
generateToken(): Promise<{
|
|
86
|
+
token: any;
|
|
87
|
+
valid: Date;
|
|
88
|
+
}>;
|
|
89
|
+
getPublic(): {
|
|
90
|
+
avatar: any;
|
|
91
|
+
name: any;
|
|
92
|
+
email: any;
|
|
93
|
+
id: any;
|
|
94
|
+
isVerified: any;
|
|
95
|
+
permissions: any;
|
|
96
|
+
locale: any;
|
|
97
|
+
};
|
|
98
|
+
sendPasswordRecoveryEmail(i18n: any): Promise<any>;
|
|
99
|
+
sendVerificationEmail(i18n: any): Promise<any>;
|
|
100
|
+
}
|
|
101
|
+
import AbstractModel from '../modules/AbstractModel.ts';
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { scrypt } from 'node:crypto';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import AbstractModel from "../modules/AbstractModel.js";
|
|
4
|
+
class User extends AbstractModel {
|
|
5
|
+
constructor(app) {
|
|
6
|
+
super(app);
|
|
7
|
+
const authConfig = this.app.getConfig('auth');
|
|
8
|
+
this.hashRounds = authConfig.hashRounds;
|
|
9
|
+
this.saltSecret = authConfig.saltSecret;
|
|
10
|
+
}
|
|
11
|
+
initHooks() {
|
|
12
|
+
this.mongooseSchema.pre('save', async function userPreSaveHook() {
|
|
13
|
+
if (this.isModified('password')) {
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
this.password = await this.constructor.hashPassword(this.password);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
// eslint-disable-next-line class-methods-use-this
|
|
20
|
+
get modelSchema() {
|
|
21
|
+
return {
|
|
22
|
+
avatar: {
|
|
23
|
+
type: String,
|
|
24
|
+
maxlength: 255,
|
|
25
|
+
},
|
|
26
|
+
name: {
|
|
27
|
+
first: {
|
|
28
|
+
type: String,
|
|
29
|
+
maxlength: 255,
|
|
30
|
+
},
|
|
31
|
+
last: {
|
|
32
|
+
type: String,
|
|
33
|
+
maxlength: 255,
|
|
34
|
+
},
|
|
35
|
+
nick: {
|
|
36
|
+
minlength: 3,
|
|
37
|
+
maxlength: 255,
|
|
38
|
+
type: String,
|
|
39
|
+
index: {
|
|
40
|
+
unique: true,
|
|
41
|
+
partialFilterExpression: { 'name.nick': { $type: 'string' } },
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
password: String,
|
|
46
|
+
email: {
|
|
47
|
+
type: String,
|
|
48
|
+
maxlength: 255,
|
|
49
|
+
index: {
|
|
50
|
+
unique: true,
|
|
51
|
+
partialFilterExpression: { email: { $type: 'string' } },
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
sessionTokens: [{ token: String, valid: Date }],
|
|
55
|
+
verificationTokens: [{ until: Date, token: String }],
|
|
56
|
+
passwordRecoveryTokens: [{ until: Date, token: String }],
|
|
57
|
+
permissions: [],
|
|
58
|
+
roles: [],
|
|
59
|
+
isVerified: { type: Boolean, default: false },
|
|
60
|
+
locale: { type: String, default: 'en' },
|
|
61
|
+
languages: [String],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
static async getUserByEmailAndPassword(email, password) {
|
|
65
|
+
const data = await this.findOne({ email: String(email) });
|
|
66
|
+
if (!data) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
const hashedPasswords = await this.hashPassword(password);
|
|
70
|
+
if (data.password !== hashedPasswords) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
return data;
|
|
74
|
+
}
|
|
75
|
+
async generateToken() {
|
|
76
|
+
const timestamp = new Date();
|
|
77
|
+
timestamp.setDate(timestamp.getDate() + 30);
|
|
78
|
+
const scryptAsync = promisify(scrypt);
|
|
79
|
+
const data = await scryptAsync(this.email + Date.now(), this.getSuper().saltSecret, this.getSuper().hashRounds);
|
|
80
|
+
const token = data.toString('base64url');
|
|
81
|
+
this.sessionTokens.push({ token, valid: timestamp });
|
|
82
|
+
await this.save();
|
|
83
|
+
return { token, valid: timestamp };
|
|
84
|
+
}
|
|
85
|
+
getPublic() {
|
|
86
|
+
return {
|
|
87
|
+
avatar: this.avatar,
|
|
88
|
+
name: this.name,
|
|
89
|
+
email: this.email,
|
|
90
|
+
id: this.id,
|
|
91
|
+
isVerified: this.isVerified,
|
|
92
|
+
permissions: this.permissions,
|
|
93
|
+
locale: this.locale,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
static async hashPassword(password) {
|
|
97
|
+
const scryptAsync = promisify(scrypt);
|
|
98
|
+
const data = await scryptAsync(String(password), this.getSuper().saltSecret, this.getSuper().hashRounds);
|
|
99
|
+
return data.toString('base64url');
|
|
100
|
+
}
|
|
101
|
+
static async getUserByToken(token) {
|
|
102
|
+
const data = await this.findOne({ 'sessionTokens.token': String(token) });
|
|
103
|
+
return data || false;
|
|
104
|
+
}
|
|
105
|
+
static async getUserByEmail(email) {
|
|
106
|
+
const data = await this.findOne({ email: String(email) });
|
|
107
|
+
if (!data) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
return data;
|
|
111
|
+
}
|
|
112
|
+
static async generateUserPasswordRecoveryToken(userMongoose) {
|
|
113
|
+
const date = new Date();
|
|
114
|
+
date.setDate(date.getDate() + 14);
|
|
115
|
+
const scryptAsync = promisify(scrypt);
|
|
116
|
+
const data = await scryptAsync(userMongoose.email + Date.now(), userMongoose.getSuper().saltSecret, userMongoose.getSuper().hashRounds);
|
|
117
|
+
const token = data.toString('base64url');
|
|
118
|
+
// if (err) {
|
|
119
|
+
// this.logger.error("Hash 2 error ", err);
|
|
120
|
+
// reject(err);
|
|
121
|
+
// return;
|
|
122
|
+
// }
|
|
123
|
+
userMongoose.passwordRecoveryTokens = [];
|
|
124
|
+
userMongoose.passwordRecoveryTokens.push({
|
|
125
|
+
until: date,
|
|
126
|
+
token,
|
|
127
|
+
});
|
|
128
|
+
await userMongoose.save();
|
|
129
|
+
return { token, until: date.getTime() };
|
|
130
|
+
}
|
|
131
|
+
static async getUserByPasswordRecoveryToken(passwordRecoveryToken) {
|
|
132
|
+
const data = await this.findOne({
|
|
133
|
+
passwordRecoveryTokens: {
|
|
134
|
+
$elemMatch: { token: String(passwordRecoveryToken) },
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
if (!data) {
|
|
138
|
+
return Promise.reject(new Error('User not exists'));
|
|
139
|
+
}
|
|
140
|
+
// TODO token expiration and remove that token
|
|
141
|
+
data.passwordRecoveryTokens.pop();
|
|
142
|
+
const result = await data.save();
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
async sendPasswordRecoveryEmail(i18n) {
|
|
146
|
+
const passwordRecoveryToken = await User.generateUserPasswordRecoveryToken(this);
|
|
147
|
+
let Mailer;
|
|
148
|
+
// speed optimisation
|
|
149
|
+
try {
|
|
150
|
+
// @ts-ignore
|
|
151
|
+
// eslint-disable-next-line import-x/no-unresolved
|
|
152
|
+
Mailer = (await import('@adaptivestone/framework-module-email')).default;
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
const error = 'Mailer not found. Please install @adaptivestone/framework-module-email in order to use it';
|
|
156
|
+
this.getSuper().logger.error(error);
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
const mail = new Mailer(this.getSuper().app, 'recovery', {
|
|
160
|
+
link: `${i18n.language}/auth/recovery?password_recovery_token=${passwordRecoveryToken.token}`,
|
|
161
|
+
editor: this.name.nick,
|
|
162
|
+
}, i18n);
|
|
163
|
+
return mail.send(this.email);
|
|
164
|
+
}
|
|
165
|
+
static async generateUserVerificationToken(userMongoose) {
|
|
166
|
+
const date = new Date();
|
|
167
|
+
date.setDate(date.getDate() + 14);
|
|
168
|
+
const scryptAsync = promisify(scrypt);
|
|
169
|
+
const data = await scryptAsync(userMongoose.email + Date.now(), userMongoose.getSuper().saltSecret, userMongoose.getSuper().hashRounds);
|
|
170
|
+
const token = data.toString('base64url');
|
|
171
|
+
// if (err) {
|
|
172
|
+
// this.logger.error("Hash 2 error ", err);
|
|
173
|
+
// reject(err);
|
|
174
|
+
// return;
|
|
175
|
+
// }
|
|
176
|
+
userMongoose.verificationTokens = [];
|
|
177
|
+
userMongoose.verificationTokens.push({
|
|
178
|
+
until: date,
|
|
179
|
+
token,
|
|
180
|
+
});
|
|
181
|
+
await userMongoose.save();
|
|
182
|
+
return { token, until: date.getTime() };
|
|
183
|
+
}
|
|
184
|
+
static async getUserByVerificationToken(verificationToken) {
|
|
185
|
+
const data = await this.findOne({
|
|
186
|
+
verificationTokens: {
|
|
187
|
+
$elemMatch: { token: String(verificationToken) },
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
if (!data) {
|
|
191
|
+
return Promise.reject(new Error('User not exists'));
|
|
192
|
+
}
|
|
193
|
+
// TODO token expiration and remove that token
|
|
194
|
+
data.verificationTokens.pop();
|
|
195
|
+
const result = await data.save();
|
|
196
|
+
return result;
|
|
197
|
+
}
|
|
198
|
+
// async removeVerificationToken(verificationToken) {
|
|
199
|
+
// this.mongooseModel.updateOne(
|
|
200
|
+
// {
|
|
201
|
+
// verificationTokens: {
|
|
202
|
+
// $elemMatch: { token: String(verificationToken) },
|
|
203
|
+
// },
|
|
204
|
+
// },
|
|
205
|
+
// { $pop: { verificationTokens: 1 } },
|
|
206
|
+
// );
|
|
207
|
+
// }
|
|
208
|
+
async sendVerificationEmail(i18n) {
|
|
209
|
+
const verificationToken = await User.generateUserVerificationToken(this);
|
|
210
|
+
// speed optimisation
|
|
211
|
+
let Mailer;
|
|
212
|
+
try {
|
|
213
|
+
// @ts-ignore
|
|
214
|
+
// eslint-disable-next-line import-x/no-unresolved
|
|
215
|
+
Mailer = (await import('@adaptivestone/framework-module-email')).default;
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
const error = 'Mailer not found. Please install @adaptivestone/framework-module-email in order to use it';
|
|
219
|
+
this.getSuper().logger.error(error);
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
const mail = new Mailer(this.getSuper().app, 'verification', {
|
|
223
|
+
link: `${i18n.language}/auth/login?verification_token=${verificationToken.token}`,
|
|
224
|
+
editor: this.name.nick,
|
|
225
|
+
}, i18n);
|
|
226
|
+
return mail.send(this.email);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
export default User;
|
|
230
|
+
//# sourceMappingURL=User.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"User.js","sourceRoot":"","sources":["../../src/models/User.js"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import Base from './Base.ts';
|
|
2
|
+
import type { IApp } from '../server.ts';
|
|
3
|
+
import type { ParseArgsOptionsConfigExtended } from './BaseCli.ts';
|
|
4
|
+
declare class AbstractCommand extends Base {
|
|
5
|
+
commands: Record<string, string>;
|
|
6
|
+
args: Record<string, any>;
|
|
7
|
+
constructor(app: IApp, commands: Record<string, string>, args: Record<string, any>);
|
|
8
|
+
static get description(): string;
|
|
9
|
+
/**
|
|
10
|
+
* If true, then this command will load models and init mongo connection
|
|
11
|
+
*/
|
|
12
|
+
static isShouldInitModels: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Get mongo connection name
|
|
15
|
+
* @param {String} commandName
|
|
16
|
+
* @param {object} args
|
|
17
|
+
*/
|
|
18
|
+
static getMongoConnectionName(commandName: string, args: Record<string, any>): string;
|
|
19
|
+
/**
|
|
20
|
+
* You able to add command arguments for parsing there.
|
|
21
|
+
* @see https://nodejs.org/api/util.html#utilparseargsconfig in config.options plus extended with description and required
|
|
22
|
+
*/
|
|
23
|
+
static get commandArguments(): Record<string, ParseArgsOptionsConfigExtended>;
|
|
24
|
+
/**
|
|
25
|
+
* Entry point to every command. This method should be overridden
|
|
26
|
+
*/
|
|
27
|
+
run(): Promise<boolean>;
|
|
28
|
+
static get loggerGroup(): string;
|
|
29
|
+
}
|
|
30
|
+
export default AbstractCommand;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import Base from "./Base.js";
|
|
2
|
+
class AbstractCommand extends Base {
|
|
3
|
+
commands;
|
|
4
|
+
args;
|
|
5
|
+
constructor(app, commands, args) {
|
|
6
|
+
super(app);
|
|
7
|
+
this.args = args;
|
|
8
|
+
this.commands = commands;
|
|
9
|
+
}
|
|
10
|
+
static get description() {
|
|
11
|
+
return 'Command description. PLEASE PROVIDE IT';
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* If true, then this command will load models and init mongo connection
|
|
15
|
+
*/
|
|
16
|
+
static isShouldInitModels = true;
|
|
17
|
+
/**
|
|
18
|
+
* Get mongo connection name
|
|
19
|
+
* @param {String} commandName
|
|
20
|
+
* @param {object} args
|
|
21
|
+
*/
|
|
22
|
+
static getMongoConnectionName(commandName, args) {
|
|
23
|
+
return `CLI: ${commandName} ${JSON.stringify(args)}`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* You able to add command arguments for parsing there.
|
|
27
|
+
* @see https://nodejs.org/api/util.html#utilparseargsconfig in config.options plus extended with description and required
|
|
28
|
+
*/
|
|
29
|
+
static get commandArguments() {
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Entry point to every command. This method should be overridden
|
|
34
|
+
*/
|
|
35
|
+
async run() {
|
|
36
|
+
this.logger?.error('You should implement run method');
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
static get loggerGroup() {
|
|
40
|
+
return 'command';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export default AbstractCommand;
|
|
44
|
+
//# sourceMappingURL=AbstractCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AbstractCommand.js","sourceRoot":"","sources":["../../src/modules/AbstractCommand.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,MAAM,eAAgB,SAAQ,IAAI;IAChC,QAAQ,CAAyB;IAEjC,IAAI,CAAsB;IAE1B,YACE,GAAS,EACT,QAAgC,EAChC,IAAyB;QAEzB,KAAK,CAAC,GAAG,CAAC,CAAC;QACX,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,MAAM,KAAK,WAAW;QACpB,OAAO,wCAAwC,CAAC;IAClD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAEjC;;;;OAIG;IACH,MAAM,CAAC,sBAAsB,CAC3B,WAAmB,EACnB,IAAyB;QAEzB,OAAO,QAAQ,WAAW,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;IACvD,CAAC;IAED;;;OAGG;IACH,MAAM,KAAK,gBAAgB;QAIzB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG;QACP,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACtD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,KAAK,WAAW;QACpB,OAAO,SAAS,CAAC;IACnB,CAAC;;AAGH,eAAe,eAAe,CAAC"}
|