@nattyjs/common 0.0.1-beta.7 → 0.0.1-beta.71
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/dist/index.cjs +184 -12
- package/dist/index.d.ts +120 -4
- package/dist/index.mjs +182 -13
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -4,6 +4,8 @@ const fs = require('fs');
|
|
|
4
4
|
const dotenv = require('dotenv');
|
|
5
5
|
const dotenvExpand = require('dotenv-expand');
|
|
6
6
|
const path = require('path');
|
|
7
|
+
const child_process = require('child_process');
|
|
8
|
+
const getPortPlease = require('get-port-please');
|
|
7
9
|
|
|
8
10
|
function _interopNamespaceCompat(e) {
|
|
9
11
|
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
@@ -28,8 +30,11 @@ const commonContainer = new class {
|
|
|
28
30
|
this.types = {};
|
|
29
31
|
}
|
|
30
32
|
registerType(type) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
if (type) {
|
|
34
|
+
if (typeof type === "string")
|
|
35
|
+
type = JSON.parse(type);
|
|
36
|
+
this.types[type.name] = type;
|
|
37
|
+
}
|
|
33
38
|
}
|
|
34
39
|
setupCliConfig(config) {
|
|
35
40
|
this.nattyCliConfig = config;
|
|
@@ -43,10 +48,19 @@ const commonContainer = new class {
|
|
|
43
48
|
}
|
|
44
49
|
}
|
|
45
50
|
};
|
|
46
|
-
|
|
51
|
+
const secureConfig = {};
|
|
52
|
+
this.nattyConfig = { ...{ api: { rootPath: "api" }, ...{ static: { enabled: true } }, autoGeneratePort: true, modelBinding, globalConfig: {}, secure: secureConfig }, ...config };
|
|
47
53
|
}
|
|
48
54
|
setupBuildOptions(options) {
|
|
49
|
-
this.buildOptions =
|
|
55
|
+
this.buildOptions = {
|
|
56
|
+
commandName: options.commandName || "dev",
|
|
57
|
+
mode: options.mode || "dev",
|
|
58
|
+
port: options.port ?? 0,
|
|
59
|
+
rootDir: options.rootDir || process.cwd(),
|
|
60
|
+
outDir: options.outDir || "dist",
|
|
61
|
+
startupFilePath: options.startupFilePath || "dist/index.js",
|
|
62
|
+
clearScreen: options.clearScreen ?? false
|
|
63
|
+
};
|
|
50
64
|
}
|
|
51
65
|
setEnvTsDefinition(tsDefinition) {
|
|
52
66
|
this.envTsDefinition = tsDefinition;
|
|
@@ -60,6 +74,9 @@ const commonContainer = new class {
|
|
|
60
74
|
getMetadataValue(key, propName) {
|
|
61
75
|
return this.metadataConfig[propName].get(key);
|
|
62
76
|
}
|
|
77
|
+
deleteMetadataValue(key, propName) {
|
|
78
|
+
this.metadataConfig[propName].delete(key);
|
|
79
|
+
}
|
|
63
80
|
get globalConfig() {
|
|
64
81
|
return this.nattyConfig.global || {};
|
|
65
82
|
}
|
|
@@ -94,6 +111,7 @@ const typeContainer = new class {
|
|
|
94
111
|
this.controllerInfo = /* @__PURE__ */ new Map();
|
|
95
112
|
this.files = /* @__PURE__ */ new Map();
|
|
96
113
|
this.routes = {};
|
|
114
|
+
this.modelSchemas = new Array();
|
|
97
115
|
}
|
|
98
116
|
setControllerJsonSchema(classInfo) {
|
|
99
117
|
const className = this.files.get(classInfo.filePath);
|
|
@@ -115,10 +133,18 @@ const typeContainer = new class {
|
|
|
115
133
|
}
|
|
116
134
|
return controllerName.substr(0, controllerName.length - 10).toLowerCase();
|
|
117
135
|
}
|
|
136
|
+
setClassMetaInfo(typeMeta) {
|
|
137
|
+
this.modelSchemas.push(typeMeta);
|
|
138
|
+
}
|
|
139
|
+
getClassMetaInfo() {
|
|
140
|
+
return this.modelSchemas;
|
|
141
|
+
}
|
|
118
142
|
getRoutes() {
|
|
119
143
|
const routes = {};
|
|
120
144
|
for (const key of this.controllerInfo.keys()) {
|
|
121
145
|
const classInfo = this.controllerInfo.get(key);
|
|
146
|
+
if (!classInfo?.filePath)
|
|
147
|
+
continue;
|
|
122
148
|
let templateInfo = {
|
|
123
149
|
path: `.${classInfo.filePath.replace(TS_EXTENSION, BLANK).replace(BACK_SLASH_REGEX, RIGHT_SLASH)}`,
|
|
124
150
|
route: this.getControllerRouteName(classInfo),
|
|
@@ -139,6 +165,7 @@ const typeContainer = new class {
|
|
|
139
165
|
templateInfo[httpMethod][route] = { name: method.name, parameters, returnType: method.returnType };
|
|
140
166
|
}
|
|
141
167
|
routes[templateInfo.route] = templateInfo;
|
|
168
|
+
routes[templateInfo.route].jsDoc = classInfo.jsDoc;
|
|
142
169
|
}
|
|
143
170
|
return routes;
|
|
144
171
|
}
|
|
@@ -233,20 +260,29 @@ function getPath(pathCollection, isIncludeRoot = true, isCreateFolder = false) {
|
|
|
233
260
|
return currentPath;
|
|
234
261
|
}
|
|
235
262
|
|
|
263
|
+
function resolvePath(path$1) {
|
|
264
|
+
return path.resolve(commonContainer.buildOptions.rootDir, path$1);
|
|
265
|
+
}
|
|
266
|
+
|
|
236
267
|
async function readEnv() {
|
|
237
|
-
|
|
268
|
+
const envConfig = commonContainer.nattyCliConfig?.env;
|
|
269
|
+
let filePath = envConfig?.dictionary ? void 0 : getPath([ENVIRONMENTS, commonContainer.buildOptions.mode && commonContainer.buildOptions.mode !== "dev" ? `.env.${commonContainer.buildOptions.mode}` : `.env`]);
|
|
270
|
+
if (envConfig && envConfig.path)
|
|
271
|
+
filePath = resolvePath(envConfig.path);
|
|
238
272
|
let parsedEnvTsDefinition = {};
|
|
239
|
-
|
|
273
|
+
let parsedEnv = envConfig?.dictionary;
|
|
274
|
+
if (!parsedEnv && filePath && fs.existsSync(filePath)) {
|
|
240
275
|
const { parsed, error } = dotenv__namespace.config({
|
|
241
276
|
debug: !!process.env.DEBUG || void 0,
|
|
242
277
|
path: filePath
|
|
243
278
|
});
|
|
244
|
-
|
|
245
|
-
parsedEnvTsDefinition = info.parsedEnvTsDefinition;
|
|
246
|
-
commonContainer.setEnvTsDefinition(parsedEnvTsDefinition);
|
|
247
|
-
commonContainer.setEnvValueInfo(info.envVariableValueInfo);
|
|
248
|
-
dotenvExpand__namespace.expand({ parsed });
|
|
279
|
+
parsedEnv = parsed;
|
|
249
280
|
}
|
|
281
|
+
const info = getEnvTsDefinition(parsedEnv);
|
|
282
|
+
parsedEnvTsDefinition = info.parsedEnvTsDefinition;
|
|
283
|
+
commonContainer.setEnvTsDefinition(parsedEnvTsDefinition);
|
|
284
|
+
commonContainer.setEnvValueInfo(info.envVariableValueInfo);
|
|
285
|
+
dotenvExpand__namespace.expand({ parsed: parsedEnv });
|
|
250
286
|
return parsedEnvTsDefinition;
|
|
251
287
|
}
|
|
252
288
|
|
|
@@ -389,7 +425,7 @@ class List {
|
|
|
389
425
|
if (this.count()) {
|
|
390
426
|
return predicate ? this.where(predicate).first() : this._entities[0];
|
|
391
427
|
} else {
|
|
392
|
-
|
|
428
|
+
return void 0;
|
|
393
429
|
}
|
|
394
430
|
}
|
|
395
431
|
firstOrDefault(predicate) {
|
|
@@ -587,13 +623,147 @@ function registerType(type) {
|
|
|
587
623
|
commonContainer.registerType(type);
|
|
588
624
|
}
|
|
589
625
|
|
|
626
|
+
class AbstractRunner {
|
|
627
|
+
async stop() {
|
|
628
|
+
if (this.childProcess)
|
|
629
|
+
this.childProcess.kill();
|
|
630
|
+
}
|
|
631
|
+
async exec(command, args, cwd = process.cwd()) {
|
|
632
|
+
const options = {
|
|
633
|
+
cwd,
|
|
634
|
+
stdio: "pipe",
|
|
635
|
+
shell: true
|
|
636
|
+
};
|
|
637
|
+
return new Promise((resolve, reject) => {
|
|
638
|
+
const child = child_process.spawn(
|
|
639
|
+
`${command}`,
|
|
640
|
+
[...args],
|
|
641
|
+
options
|
|
642
|
+
);
|
|
643
|
+
this.childProcess = child;
|
|
644
|
+
child.stdout.on(
|
|
645
|
+
"data",
|
|
646
|
+
(data) => {
|
|
647
|
+
const writeData = data.toString().replace(/\r\n|\n/, "");
|
|
648
|
+
if (writeData.indexOf("[NATTYJS]") > -1 || writeData.indexOf("[NATTYJS:LOGGER]") > -1) {
|
|
649
|
+
console.log(writeData);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
);
|
|
653
|
+
child.stderr.on("data", (data) => {
|
|
654
|
+
const writeData = data.toString().replace(/\r\n|\n/, "");
|
|
655
|
+
console.log(writeData);
|
|
656
|
+
});
|
|
657
|
+
child.on("close", (code) => {
|
|
658
|
+
if (code === 0) {
|
|
659
|
+
resolve(null);
|
|
660
|
+
} else {
|
|
661
|
+
console.error(
|
|
662
|
+
`${command} ${args}`
|
|
663
|
+
);
|
|
664
|
+
reject();
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
async function getPort() {
|
|
672
|
+
const configuredPort = commonContainer.nattyConfig?.port;
|
|
673
|
+
if (configuredPort)
|
|
674
|
+
return configuredPort;
|
|
675
|
+
const preferredPorts = [3200, ...Array(50).fill(3001).map((fillValue, index) => fillValue + index)];
|
|
676
|
+
const port = await getPortPlease.getPort({ ports: preferredPorts });
|
|
677
|
+
commonContainer.nattyConfig.port = port;
|
|
678
|
+
return port;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
const reset = "\x1B[0m";
|
|
682
|
+
const NATTY_LOGGER = `[NATTYJS:LOGGER] `;
|
|
683
|
+
const log = {
|
|
684
|
+
green: (text) => console.log("\x1B[32m" + NATTY_LOGGER + text + reset),
|
|
685
|
+
red: (text) => console.log("\x1B[31m" + NATTY_LOGGER + text + reset),
|
|
686
|
+
blue: (text) => console.log("\x1B[34m" + NATTY_LOGGER + text + reset),
|
|
687
|
+
yellow: (text) => console.log("\x1B[33m" + NATTY_LOGGER + text + reset)
|
|
688
|
+
};
|
|
689
|
+
class AbstractConsoleLogger {
|
|
690
|
+
log(message) {
|
|
691
|
+
log.yellow(message);
|
|
692
|
+
}
|
|
693
|
+
info(message) {
|
|
694
|
+
log.blue(message);
|
|
695
|
+
}
|
|
696
|
+
warn(message) {
|
|
697
|
+
log.yellow(message);
|
|
698
|
+
}
|
|
699
|
+
error(message) {
|
|
700
|
+
log.red(message);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
class ConsoleLogger extends AbstractConsoleLogger {
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
function typed() {
|
|
708
|
+
return function(OriginalClass) {
|
|
709
|
+
const extendedClass = class extends OriginalClass {
|
|
710
|
+
constructor(...args) {
|
|
711
|
+
super(...args);
|
|
712
|
+
const typeInfo = commonContainer.types[OriginalClass.name];
|
|
713
|
+
defineProps(this, typeInfo?.props, OriginalClass.name);
|
|
714
|
+
}
|
|
715
|
+
};
|
|
716
|
+
delete extendedClass.name;
|
|
717
|
+
Object.defineProperty(extendedClass, "name", {
|
|
718
|
+
value: OriginalClass.name,
|
|
719
|
+
writable: false
|
|
720
|
+
});
|
|
721
|
+
return extendedClass;
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
const types = ["string", "number", "boolean"];
|
|
725
|
+
function defineProps(instance, props, modelName) {
|
|
726
|
+
if (props && Array.isArray(props)) {
|
|
727
|
+
for (const prop of props) {
|
|
728
|
+
if (prop.type && types.indexOf(prop.type) > -1) {
|
|
729
|
+
overrideProp(instance, prop, modelName);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
function overrideProp(instance, prop, modelName) {
|
|
735
|
+
let descriptor = Object.getOwnPropertyDescriptor(
|
|
736
|
+
Object.getPrototypeOf(instance),
|
|
737
|
+
prop.name
|
|
738
|
+
);
|
|
739
|
+
let value = instance[prop.name];
|
|
740
|
+
Object.defineProperty(instance, prop.name, {
|
|
741
|
+
enumerable: true,
|
|
742
|
+
configurable: true,
|
|
743
|
+
get: () => {
|
|
744
|
+
return descriptor ? descriptor.get.call(instance) : value;
|
|
745
|
+
},
|
|
746
|
+
set: (v) => {
|
|
747
|
+
if (prop.type == "boolean" && v !== null && v !== void 0)
|
|
748
|
+
v = v === 0 || v === false ? false : true;
|
|
749
|
+
const type = typeof v;
|
|
750
|
+
if (v === null || v === void 0 || prop.type == type)
|
|
751
|
+
value = v;
|
|
752
|
+
else
|
|
753
|
+
throw new Error(`Incorrect value type of ${modelName} class property '${prop.name}' `);
|
|
754
|
+
}
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
|
|
590
758
|
exports.ALLOW_METHODS = ALLOW_METHODS;
|
|
759
|
+
exports.AbstractRunner = AbstractRunner;
|
|
591
760
|
exports.ActionFilter = ActionFilter;
|
|
592
761
|
exports.AuthenticationFilter = AuthenticationFilter;
|
|
593
762
|
exports.AuthorizationFilter = AuthorizationFilter;
|
|
594
763
|
exports.BACK_SLASH_REGEX = BACK_SLASH_REGEX;
|
|
595
764
|
exports.BLANK = BLANK;
|
|
596
765
|
exports.CONTROLLER = CONTROLLER;
|
|
766
|
+
exports.ConsoleLogger = ConsoleLogger;
|
|
597
767
|
exports.DEFAULT_ACTIONS = DEFAULT_ACTIONS;
|
|
598
768
|
exports.DEFAULT_CHILD_PATH = DEFAULT_CHILD_PATH;
|
|
599
769
|
exports.DELETE = DELETE;
|
|
@@ -618,6 +788,7 @@ exports.commonContainer = commonContainer;
|
|
|
618
788
|
exports.createPath = createPath;
|
|
619
789
|
exports.createTestServer = createTestServer;
|
|
620
790
|
exports.getPath = getPath;
|
|
791
|
+
exports.getPort = getPort;
|
|
621
792
|
exports.isConstructor = isConstructor;
|
|
622
793
|
exports.isEqual = isEqual;
|
|
623
794
|
exports.isFunction = isFunction;
|
|
@@ -626,3 +797,4 @@ exports.readEnv = readEnv;
|
|
|
626
797
|
exports.readEnvKey = readEnvKey;
|
|
627
798
|
exports.registerType = registerType;
|
|
628
799
|
exports.typeContainer = typeContainer;
|
|
800
|
+
exports.typed = typed;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { RequestRouteInfo, IHttpResult, IModelBindingContext, ProblemDetail, IExceptionContext, HttpResponseInit, NattyTestModule, ModelBinding,
|
|
1
|
+
import { RequestRouteInfo, IHttpResult, Cookie, IModelBindingContext, ProblemDetail, IExceptionContext, HttpResponseInit, NattyTestModule, ModelBinding, GenerateOpenApiOptions, BuildOptions, TypesInfo, ClassTypeInfo, TypeMeta } from '@nattyjs/types';
|
|
2
|
+
import { ChildProcess } from 'child_process';
|
|
2
3
|
|
|
3
4
|
interface ClassType<T> extends Function {
|
|
4
5
|
new (...args: any[]): T;
|
|
@@ -21,6 +22,11 @@ interface IExecutionContext {
|
|
|
21
22
|
|
|
22
23
|
interface IActionExecutedContext extends IExecutionContext {
|
|
23
24
|
content: any;
|
|
25
|
+
get response(): {
|
|
26
|
+
cookies: Array<Cookie>;
|
|
27
|
+
headers: Headers;
|
|
28
|
+
status: number;
|
|
29
|
+
};
|
|
24
30
|
}
|
|
25
31
|
|
|
26
32
|
interface IActionExecutingContext extends IExecutionContext {
|
|
@@ -37,8 +43,12 @@ declare abstract class AuthenticationFilter {
|
|
|
37
43
|
onFailedResponse(): ProblemDetail;
|
|
38
44
|
}
|
|
39
45
|
|
|
46
|
+
interface IAuthorizationContext extends IActionExecutingContext {
|
|
47
|
+
config: any;
|
|
48
|
+
}
|
|
49
|
+
|
|
40
50
|
declare abstract class AuthorizationFilter {
|
|
41
|
-
abstract onAuthorization(httpContext:
|
|
51
|
+
abstract onAuthorization(httpContext: IAuthorizationContext, permissionRequirement: any): Promise<boolean>;
|
|
42
52
|
onFailedAuthorization(): ProblemDetail;
|
|
43
53
|
}
|
|
44
54
|
|
|
@@ -53,6 +63,37 @@ interface GlobalConfig {
|
|
|
53
63
|
onException?: ClassType<ExceptionFilter>;
|
|
54
64
|
}
|
|
55
65
|
|
|
66
|
+
interface CorsConfig {
|
|
67
|
+
origin: string[];
|
|
68
|
+
methods: string;
|
|
69
|
+
preflightContinue: boolean;
|
|
70
|
+
optionsSuccessStatus: number;
|
|
71
|
+
credentials: boolean;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface PayloadConfig {
|
|
75
|
+
limit?: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface SecureConfig {
|
|
79
|
+
sensitiveProps?: String[];
|
|
80
|
+
denyByDefault?: boolean;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface PreInitEventConfig {
|
|
84
|
+
cors?: CorsConfig;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface LifeCycleEvents {
|
|
88
|
+
preInit: () => PreInitEventConfig;
|
|
89
|
+
onStart: () => Promise<void>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface WebScheduleConfig {
|
|
93
|
+
interval: number;
|
|
94
|
+
scheduleFunction: () => Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
|
|
56
97
|
interface NattyConfig {
|
|
57
98
|
app: any;
|
|
58
99
|
testModule?: NattyTestModule;
|
|
@@ -62,12 +103,69 @@ interface NattyConfig {
|
|
|
62
103
|
modelBinding?: ModelBinding;
|
|
63
104
|
global?: GlobalConfig;
|
|
64
105
|
autoGeneratePort?: boolean;
|
|
106
|
+
port?: number;
|
|
107
|
+
cors?: CorsConfig;
|
|
108
|
+
payload?: PayloadConfig;
|
|
109
|
+
secure?: SecureConfig;
|
|
110
|
+
lifeCycle?: LifeCycleEvents;
|
|
111
|
+
webSchedules?: Array<WebScheduleConfig>;
|
|
112
|
+
static?: {
|
|
113
|
+
indexFile?: string;
|
|
114
|
+
spaFallback?: boolean;
|
|
115
|
+
enabled?: boolean;
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
declare abstract class AbstractRunner {
|
|
120
|
+
abstract run(): void;
|
|
121
|
+
childProcess: ChildProcess;
|
|
122
|
+
stop(): Promise<void>;
|
|
123
|
+
protected exec(command: string, args: any[], cwd?: string): Promise<null | string>;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
interface ClientConfig {
|
|
127
|
+
path: string;
|
|
128
|
+
packageName?: string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
interface DiTransformConfig {
|
|
132
|
+
decoratorName?: string;
|
|
133
|
+
markerName?: string;
|
|
134
|
+
stripPathPrefixes?: string[];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface EnvConfig {
|
|
138
|
+
path: string;
|
|
139
|
+
dictionary: {
|
|
140
|
+
[key: string]: any;
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
interface PackageJsonConfig {
|
|
145
|
+
addExports: string[];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
interface LibraryConfig {
|
|
149
|
+
packageJson: PackageJsonConfig;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
interface NattyCliConfig {
|
|
153
|
+
library?: Partial<LibraryConfig>;
|
|
154
|
+
env?: Partial<EnvConfig>;
|
|
155
|
+
di?: DiTransformConfig;
|
|
156
|
+
runner?: ClassType<AbstractRunner>;
|
|
157
|
+
port?: number;
|
|
158
|
+
openapi?: GenerateOpenApiOptions;
|
|
159
|
+
swagger?: {
|
|
160
|
+
ui: boolean;
|
|
161
|
+
};
|
|
162
|
+
client?: ClientConfig;
|
|
65
163
|
}
|
|
66
164
|
|
|
67
165
|
declare const commonContainer: {
|
|
68
166
|
setupConfig(config?: NattyConfig): void;
|
|
69
167
|
setupCliConfig(config: NattyCliConfig): void;
|
|
70
|
-
setupBuildOptions(options: BuildOptions):
|
|
168
|
+
setupBuildOptions(options: Partial<BuildOptions>): void;
|
|
71
169
|
get nattyConfig(): NattyConfig;
|
|
72
170
|
get nattyCliConfig(): NattyCliConfig;
|
|
73
171
|
get buildOptions(): BuildOptions;
|
|
@@ -85,13 +183,17 @@ declare const commonContainer: {
|
|
|
85
183
|
}): void;
|
|
86
184
|
setMetadata(key: string, value: any, propName: string): void;
|
|
87
185
|
getMetadataValue(key: string, propName: string): any;
|
|
186
|
+
deleteMetadataValue(key: string, propName: string): void;
|
|
88
187
|
get globalConfig(): GlobalConfig;
|
|
89
188
|
registerType(type: TypesInfo): void;
|
|
189
|
+
types: TypesInfo;
|
|
90
190
|
};
|
|
91
191
|
|
|
92
192
|
declare const typeContainer: {
|
|
93
193
|
setControllerJsonSchema(classInfo: ClassTypeInfo): void;
|
|
94
194
|
getControllersJsonSchema(): ClassTypeInfo[];
|
|
195
|
+
setClassMetaInfo(typeMeta: TypeMeta): void;
|
|
196
|
+
getClassMetaInfo(): TypeMeta[];
|
|
95
197
|
getRoutes(): any;
|
|
96
198
|
getControllerJsonSchema(name: string): ClassTypeInfo;
|
|
97
199
|
removeControllerInfo(path: string): void;
|
|
@@ -224,4 +326,18 @@ interface NattyAppConfig extends NattyConfig {
|
|
|
224
326
|
|
|
225
327
|
declare function registerType(type: TypesInfo): void;
|
|
226
328
|
|
|
227
|
-
|
|
329
|
+
declare function getPort(): Promise<number>;
|
|
330
|
+
|
|
331
|
+
declare abstract class AbstractConsoleLogger {
|
|
332
|
+
log(message: any): void;
|
|
333
|
+
info(message: any): void;
|
|
334
|
+
warn(message: any): void;
|
|
335
|
+
error(message: any): void;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
declare class ConsoleLogger extends AbstractConsoleLogger {
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
declare function typed(): <T extends new (...args: any[]) => {}>(OriginalClass: T) => T;
|
|
342
|
+
|
|
343
|
+
export { ALLOW_METHODS, AbstractRunner, ActionFilter, AuthenticationFilter, AuthorizationFilter, BACK_SLASH_REGEX, BLANK, CONTROLLER, Claim, ClassType, ClientConfig, ConsoleLogger, DEFAULT_ACTIONS, DEFAULT_CHILD_PATH, DELETE, DiTransformConfig, ENVIRONMENTS, ExceptionFilter, FrameworkType, GET, GlobalConfig, HTTP_METHOD_ROUTES, IActionExecutedContext, IActionExecutingContext, IAuthorizationContext, IExecutionContext, IGNORE_METHODS, List, MetaConfigProps, Middleware, NattyAppConfig, NattyCliConfig, NattyConfig, POST, PUT, RIGHT_SLASH, ROUTE_INSTANCES, ROUTE_METHODS, ROUTE_PATHS, TS_EXTENSION, UserIdentity, WebScheduleConfig, commonContainer, createPath, createTestServer, getPath, getPort, isConstructor, isEqual, isFunction, isObject, readEnv, readEnvKey, registerType, typeContainer, typed };
|
package/dist/index.mjs
CHANGED
|
@@ -3,6 +3,9 @@ import { existsSync } from 'fs';
|
|
|
3
3
|
import * as dotenv from 'dotenv';
|
|
4
4
|
import * as dotenvExpand from 'dotenv-expand';
|
|
5
5
|
import * as path from 'path';
|
|
6
|
+
import { resolve } from 'path';
|
|
7
|
+
import { spawn } from 'child_process';
|
|
8
|
+
import { getPort as getPort$1 } from 'get-port-please';
|
|
6
9
|
|
|
7
10
|
const commonContainer = new class {
|
|
8
11
|
constructor() {
|
|
@@ -10,8 +13,11 @@ const commonContainer = new class {
|
|
|
10
13
|
this.types = {};
|
|
11
14
|
}
|
|
12
15
|
registerType(type) {
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
if (type) {
|
|
17
|
+
if (typeof type === "string")
|
|
18
|
+
type = JSON.parse(type);
|
|
19
|
+
this.types[type.name] = type;
|
|
20
|
+
}
|
|
15
21
|
}
|
|
16
22
|
setupCliConfig(config) {
|
|
17
23
|
this.nattyCliConfig = config;
|
|
@@ -25,10 +31,19 @@ const commonContainer = new class {
|
|
|
25
31
|
}
|
|
26
32
|
}
|
|
27
33
|
};
|
|
28
|
-
|
|
34
|
+
const secureConfig = {};
|
|
35
|
+
this.nattyConfig = { ...{ api: { rootPath: "api" }, ...{ static: { enabled: true } }, autoGeneratePort: true, modelBinding, globalConfig: {}, secure: secureConfig }, ...config };
|
|
29
36
|
}
|
|
30
37
|
setupBuildOptions(options) {
|
|
31
|
-
this.buildOptions =
|
|
38
|
+
this.buildOptions = {
|
|
39
|
+
commandName: options.commandName || "dev",
|
|
40
|
+
mode: options.mode || "dev",
|
|
41
|
+
port: options.port ?? 0,
|
|
42
|
+
rootDir: options.rootDir || process.cwd(),
|
|
43
|
+
outDir: options.outDir || "dist",
|
|
44
|
+
startupFilePath: options.startupFilePath || "dist/index.js",
|
|
45
|
+
clearScreen: options.clearScreen ?? false
|
|
46
|
+
};
|
|
32
47
|
}
|
|
33
48
|
setEnvTsDefinition(tsDefinition) {
|
|
34
49
|
this.envTsDefinition = tsDefinition;
|
|
@@ -42,6 +57,9 @@ const commonContainer = new class {
|
|
|
42
57
|
getMetadataValue(key, propName) {
|
|
43
58
|
return this.metadataConfig[propName].get(key);
|
|
44
59
|
}
|
|
60
|
+
deleteMetadataValue(key, propName) {
|
|
61
|
+
this.metadataConfig[propName].delete(key);
|
|
62
|
+
}
|
|
45
63
|
get globalConfig() {
|
|
46
64
|
return this.nattyConfig.global || {};
|
|
47
65
|
}
|
|
@@ -76,6 +94,7 @@ const typeContainer = new class {
|
|
|
76
94
|
this.controllerInfo = /* @__PURE__ */ new Map();
|
|
77
95
|
this.files = /* @__PURE__ */ new Map();
|
|
78
96
|
this.routes = {};
|
|
97
|
+
this.modelSchemas = new Array();
|
|
79
98
|
}
|
|
80
99
|
setControllerJsonSchema(classInfo) {
|
|
81
100
|
const className = this.files.get(classInfo.filePath);
|
|
@@ -97,10 +116,18 @@ const typeContainer = new class {
|
|
|
97
116
|
}
|
|
98
117
|
return controllerName.substr(0, controllerName.length - 10).toLowerCase();
|
|
99
118
|
}
|
|
119
|
+
setClassMetaInfo(typeMeta) {
|
|
120
|
+
this.modelSchemas.push(typeMeta);
|
|
121
|
+
}
|
|
122
|
+
getClassMetaInfo() {
|
|
123
|
+
return this.modelSchemas;
|
|
124
|
+
}
|
|
100
125
|
getRoutes() {
|
|
101
126
|
const routes = {};
|
|
102
127
|
for (const key of this.controllerInfo.keys()) {
|
|
103
128
|
const classInfo = this.controllerInfo.get(key);
|
|
129
|
+
if (!classInfo?.filePath)
|
|
130
|
+
continue;
|
|
104
131
|
let templateInfo = {
|
|
105
132
|
path: `.${classInfo.filePath.replace(TS_EXTENSION, BLANK).replace(BACK_SLASH_REGEX, RIGHT_SLASH)}`,
|
|
106
133
|
route: this.getControllerRouteName(classInfo),
|
|
@@ -121,6 +148,7 @@ const typeContainer = new class {
|
|
|
121
148
|
templateInfo[httpMethod][route] = { name: method.name, parameters, returnType: method.returnType };
|
|
122
149
|
}
|
|
123
150
|
routes[templateInfo.route] = templateInfo;
|
|
151
|
+
routes[templateInfo.route].jsDoc = classInfo.jsDoc;
|
|
124
152
|
}
|
|
125
153
|
return routes;
|
|
126
154
|
}
|
|
@@ -215,20 +243,29 @@ function getPath(pathCollection, isIncludeRoot = true, isCreateFolder = false) {
|
|
|
215
243
|
return currentPath;
|
|
216
244
|
}
|
|
217
245
|
|
|
246
|
+
function resolvePath(path) {
|
|
247
|
+
return resolve(commonContainer.buildOptions.rootDir, path);
|
|
248
|
+
}
|
|
249
|
+
|
|
218
250
|
async function readEnv() {
|
|
219
|
-
|
|
251
|
+
const envConfig = commonContainer.nattyCliConfig?.env;
|
|
252
|
+
let filePath = envConfig?.dictionary ? void 0 : getPath([ENVIRONMENTS, commonContainer.buildOptions.mode && commonContainer.buildOptions.mode !== "dev" ? `.env.${commonContainer.buildOptions.mode}` : `.env`]);
|
|
253
|
+
if (envConfig && envConfig.path)
|
|
254
|
+
filePath = resolvePath(envConfig.path);
|
|
220
255
|
let parsedEnvTsDefinition = {};
|
|
221
|
-
|
|
256
|
+
let parsedEnv = envConfig?.dictionary;
|
|
257
|
+
if (!parsedEnv && filePath && existsSync(filePath)) {
|
|
222
258
|
const { parsed, error } = dotenv.config({
|
|
223
259
|
debug: !!process.env.DEBUG || void 0,
|
|
224
260
|
path: filePath
|
|
225
261
|
});
|
|
226
|
-
|
|
227
|
-
parsedEnvTsDefinition = info.parsedEnvTsDefinition;
|
|
228
|
-
commonContainer.setEnvTsDefinition(parsedEnvTsDefinition);
|
|
229
|
-
commonContainer.setEnvValueInfo(info.envVariableValueInfo);
|
|
230
|
-
dotenvExpand.expand({ parsed });
|
|
262
|
+
parsedEnv = parsed;
|
|
231
263
|
}
|
|
264
|
+
const info = getEnvTsDefinition(parsedEnv);
|
|
265
|
+
parsedEnvTsDefinition = info.parsedEnvTsDefinition;
|
|
266
|
+
commonContainer.setEnvTsDefinition(parsedEnvTsDefinition);
|
|
267
|
+
commonContainer.setEnvValueInfo(info.envVariableValueInfo);
|
|
268
|
+
dotenvExpand.expand({ parsed: parsedEnv });
|
|
232
269
|
return parsedEnvTsDefinition;
|
|
233
270
|
}
|
|
234
271
|
|
|
@@ -371,7 +408,7 @@ class List {
|
|
|
371
408
|
if (this.count()) {
|
|
372
409
|
return predicate ? this.where(predicate).first() : this._entities[0];
|
|
373
410
|
} else {
|
|
374
|
-
|
|
411
|
+
return void 0;
|
|
375
412
|
}
|
|
376
413
|
}
|
|
377
414
|
firstOrDefault(predicate) {
|
|
@@ -569,4 +606,136 @@ function registerType(type) {
|
|
|
569
606
|
commonContainer.registerType(type);
|
|
570
607
|
}
|
|
571
608
|
|
|
572
|
-
|
|
609
|
+
class AbstractRunner {
|
|
610
|
+
async stop() {
|
|
611
|
+
if (this.childProcess)
|
|
612
|
+
this.childProcess.kill();
|
|
613
|
+
}
|
|
614
|
+
async exec(command, args, cwd = process.cwd()) {
|
|
615
|
+
const options = {
|
|
616
|
+
cwd,
|
|
617
|
+
stdio: "pipe",
|
|
618
|
+
shell: true
|
|
619
|
+
};
|
|
620
|
+
return new Promise((resolve, reject) => {
|
|
621
|
+
const child = spawn(
|
|
622
|
+
`${command}`,
|
|
623
|
+
[...args],
|
|
624
|
+
options
|
|
625
|
+
);
|
|
626
|
+
this.childProcess = child;
|
|
627
|
+
child.stdout.on(
|
|
628
|
+
"data",
|
|
629
|
+
(data) => {
|
|
630
|
+
const writeData = data.toString().replace(/\r\n|\n/, "");
|
|
631
|
+
if (writeData.indexOf("[NATTYJS]") > -1 || writeData.indexOf("[NATTYJS:LOGGER]") > -1) {
|
|
632
|
+
console.log(writeData);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
);
|
|
636
|
+
child.stderr.on("data", (data) => {
|
|
637
|
+
const writeData = data.toString().replace(/\r\n|\n/, "");
|
|
638
|
+
console.log(writeData);
|
|
639
|
+
});
|
|
640
|
+
child.on("close", (code) => {
|
|
641
|
+
if (code === 0) {
|
|
642
|
+
resolve(null);
|
|
643
|
+
} else {
|
|
644
|
+
console.error(
|
|
645
|
+
`${command} ${args}`
|
|
646
|
+
);
|
|
647
|
+
reject();
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
async function getPort() {
|
|
655
|
+
const configuredPort = commonContainer.nattyConfig?.port;
|
|
656
|
+
if (configuredPort)
|
|
657
|
+
return configuredPort;
|
|
658
|
+
const preferredPorts = [3200, ...Array(50).fill(3001).map((fillValue, index) => fillValue + index)];
|
|
659
|
+
const port = await getPort$1({ ports: preferredPorts });
|
|
660
|
+
commonContainer.nattyConfig.port = port;
|
|
661
|
+
return port;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
const reset = "\x1B[0m";
|
|
665
|
+
const NATTY_LOGGER = `[NATTYJS:LOGGER] `;
|
|
666
|
+
const log = {
|
|
667
|
+
green: (text) => console.log("\x1B[32m" + NATTY_LOGGER + text + reset),
|
|
668
|
+
red: (text) => console.log("\x1B[31m" + NATTY_LOGGER + text + reset),
|
|
669
|
+
blue: (text) => console.log("\x1B[34m" + NATTY_LOGGER + text + reset),
|
|
670
|
+
yellow: (text) => console.log("\x1B[33m" + NATTY_LOGGER + text + reset)
|
|
671
|
+
};
|
|
672
|
+
class AbstractConsoleLogger {
|
|
673
|
+
log(message) {
|
|
674
|
+
log.yellow(message);
|
|
675
|
+
}
|
|
676
|
+
info(message) {
|
|
677
|
+
log.blue(message);
|
|
678
|
+
}
|
|
679
|
+
warn(message) {
|
|
680
|
+
log.yellow(message);
|
|
681
|
+
}
|
|
682
|
+
error(message) {
|
|
683
|
+
log.red(message);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
class ConsoleLogger extends AbstractConsoleLogger {
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
function typed() {
|
|
691
|
+
return function(OriginalClass) {
|
|
692
|
+
const extendedClass = class extends OriginalClass {
|
|
693
|
+
constructor(...args) {
|
|
694
|
+
super(...args);
|
|
695
|
+
const typeInfo = commonContainer.types[OriginalClass.name];
|
|
696
|
+
defineProps(this, typeInfo?.props, OriginalClass.name);
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
delete extendedClass.name;
|
|
700
|
+
Object.defineProperty(extendedClass, "name", {
|
|
701
|
+
value: OriginalClass.name,
|
|
702
|
+
writable: false
|
|
703
|
+
});
|
|
704
|
+
return extendedClass;
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
const types = ["string", "number", "boolean"];
|
|
708
|
+
function defineProps(instance, props, modelName) {
|
|
709
|
+
if (props && Array.isArray(props)) {
|
|
710
|
+
for (const prop of props) {
|
|
711
|
+
if (prop.type && types.indexOf(prop.type) > -1) {
|
|
712
|
+
overrideProp(instance, prop, modelName);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
function overrideProp(instance, prop, modelName) {
|
|
718
|
+
let descriptor = Object.getOwnPropertyDescriptor(
|
|
719
|
+
Object.getPrototypeOf(instance),
|
|
720
|
+
prop.name
|
|
721
|
+
);
|
|
722
|
+
let value = instance[prop.name];
|
|
723
|
+
Object.defineProperty(instance, prop.name, {
|
|
724
|
+
enumerable: true,
|
|
725
|
+
configurable: true,
|
|
726
|
+
get: () => {
|
|
727
|
+
return descriptor ? descriptor.get.call(instance) : value;
|
|
728
|
+
},
|
|
729
|
+
set: (v) => {
|
|
730
|
+
if (prop.type == "boolean" && v !== null && v !== void 0)
|
|
731
|
+
v = v === 0 || v === false ? false : true;
|
|
732
|
+
const type = typeof v;
|
|
733
|
+
if (v === null || v === void 0 || prop.type == type)
|
|
734
|
+
value = v;
|
|
735
|
+
else
|
|
736
|
+
throw new Error(`Incorrect value type of ${modelName} class property '${prop.name}' `);
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
export { ALLOW_METHODS, AbstractRunner, ActionFilter, AuthenticationFilter, AuthorizationFilter, BACK_SLASH_REGEX, BLANK, CONTROLLER, ConsoleLogger, DEFAULT_ACTIONS, DEFAULT_CHILD_PATH, DELETE, ENVIRONMENTS, ExceptionFilter, FrameworkType, GET, HTTP_METHOD_ROUTES, IGNORE_METHODS, List, MetaConfigProps, Middleware, POST, PUT, RIGHT_SLASH, ROUTE_INSTANCES, ROUTE_METHODS, ROUTE_PATHS, TS_EXTENSION, UserIdentity, commonContainer, createPath, createTestServer, getPath, getPort, isConstructor, isEqual, isFunction, isObject, readEnv, readEnvKey, registerType, typeContainer, typed };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nattyjs/common",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.71",
|
|
4
4
|
"description": "Now I’m the model of a modern major general / The venerated Virginian veteran whose men are all / Lining up, to put me up on a pedestal / Writin’ letters to relatives / Embellishin’ my elegance and eloquence / But the elephant is in the room / The truth is in ya face when ya hear the British cannons go / BOOM",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"author": "ajayojha <ojhaajay@outlook.com>",
|
|
@@ -16,11 +16,12 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"dotenv": "16.3.1",
|
|
19
|
-
"dotenv-expand": "10.0.0"
|
|
19
|
+
"dotenv-expand": "10.0.0",
|
|
20
|
+
"get-port-please": "3.1.1"
|
|
20
21
|
},
|
|
21
22
|
"devDependencies": {
|
|
22
23
|
"@types/node": "20.3.1",
|
|
23
|
-
"@nattyjs/types": "0.0.1-beta.
|
|
24
|
+
"@nattyjs/types": "0.0.1-beta.71",
|
|
24
25
|
"unbuild": "1.2.1"
|
|
25
26
|
}
|
|
26
27
|
}
|