@nattyjs/common 0.0.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/index.cjs +598 -0
- package/dist/index.d.ts +203 -0
- package/dist/index.mjs +544 -0
- package/package.json +23 -0
package/README.md
ADDED
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const dotenv = require('dotenv');
|
|
5
|
+
const dotenvExpand = require('dotenv-expand');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
function _interopNamespaceCompat(e) {
|
|
9
|
+
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
10
|
+
const n = Object.create(null);
|
|
11
|
+
if (e) {
|
|
12
|
+
for (const k in e) {
|
|
13
|
+
n[k] = e[k];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
n.default = e;
|
|
17
|
+
return n;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const fs__namespace = /*#__PURE__*/_interopNamespaceCompat(fs);
|
|
21
|
+
const dotenv__namespace = /*#__PURE__*/_interopNamespaceCompat(dotenv);
|
|
22
|
+
const dotenvExpand__namespace = /*#__PURE__*/_interopNamespaceCompat(dotenvExpand);
|
|
23
|
+
const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
|
|
24
|
+
|
|
25
|
+
const commonContainer = new class {
|
|
26
|
+
constructor() {
|
|
27
|
+
this.metadataConfig = { services: /* @__PURE__ */ new Map() };
|
|
28
|
+
}
|
|
29
|
+
setupConfig(config) {
|
|
30
|
+
const modelBinding = {
|
|
31
|
+
errorMessage: {
|
|
32
|
+
typed: {
|
|
33
|
+
number: "Invalid numeric value of '{0}'.",
|
|
34
|
+
boolean: "Invalid boolean value of '{0}'."
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
this.nattyConfig = { ...{ api: { rootPath: "api" }, modelBinding, globalConfig: {} }, ...config };
|
|
39
|
+
}
|
|
40
|
+
setupBuildOptions(options) {
|
|
41
|
+
this.buildOptions = options;
|
|
42
|
+
}
|
|
43
|
+
setEnvTsDefinition(tsDefinition) {
|
|
44
|
+
this.envTsDefinition = tsDefinition;
|
|
45
|
+
}
|
|
46
|
+
setMetadata(key, value, propName) {
|
|
47
|
+
this.metadataConfig[propName].set(key, value);
|
|
48
|
+
}
|
|
49
|
+
getMetadataValue(key, propName) {
|
|
50
|
+
return this.metadataConfig[propName].get(key);
|
|
51
|
+
}
|
|
52
|
+
get globalConfig() {
|
|
53
|
+
return this.nattyConfig.global || {};
|
|
54
|
+
}
|
|
55
|
+
}();
|
|
56
|
+
|
|
57
|
+
const CONTROLLER = "controller";
|
|
58
|
+
const ENVIRONMENTS = "environments";
|
|
59
|
+
const BLANK = "";
|
|
60
|
+
const GET = "get";
|
|
61
|
+
const POST = "post";
|
|
62
|
+
const PUT = "put";
|
|
63
|
+
const DELETE = "delete";
|
|
64
|
+
const ALLOW_METHODS = [GET, POST, PUT, DELETE];
|
|
65
|
+
const IGNORE_METHODS = "IGNORE:METHODS";
|
|
66
|
+
const ROUTE_METHODS = "ROUTE:METHODS";
|
|
67
|
+
const ROUTE_INSTANCES = "ROUTE:INSTANCES";
|
|
68
|
+
const ROUTE_PATHS = "ROUTE:PATHS";
|
|
69
|
+
const HTTP_METHOD_ROUTES = "HTTPMETHOD:ROUTES";
|
|
70
|
+
const isConstructor = (value) => value === "constructor";
|
|
71
|
+
const isFunction = (value) => typeof value === "function";
|
|
72
|
+
const DEFAULT_ACTIONS = [GET, POST, PUT, DELETE];
|
|
73
|
+
const MetaConfigProps = {
|
|
74
|
+
services: "services"
|
|
75
|
+
};
|
|
76
|
+
const DEFAULT_CHILD_PATH = "/";
|
|
77
|
+
const TS_EXTENSION = ".ts";
|
|
78
|
+
const BACK_SLASH_REGEX = /\\/g;
|
|
79
|
+
const RIGHT_SLASH = "/";
|
|
80
|
+
|
|
81
|
+
const typeContainer = new class {
|
|
82
|
+
constructor() {
|
|
83
|
+
this.controllerInfo = /* @__PURE__ */ new Map();
|
|
84
|
+
this.files = /* @__PURE__ */ new Map();
|
|
85
|
+
this.routes = {};
|
|
86
|
+
}
|
|
87
|
+
setControllerJsonSchema(classInfo) {
|
|
88
|
+
const className = this.files.get(classInfo.filePath);
|
|
89
|
+
const isChanged = !className ? false : className != classInfo.name;
|
|
90
|
+
if (isChanged)
|
|
91
|
+
this.controllerInfo.delete(className);
|
|
92
|
+
this.controllerInfo.set(classInfo.name, classInfo);
|
|
93
|
+
this.files.set(classInfo.filePath, classInfo.name);
|
|
94
|
+
}
|
|
95
|
+
getControllersJsonSchema() {
|
|
96
|
+
const items = new Array();
|
|
97
|
+
this.controllerInfo.forEach((t) => items.push(t));
|
|
98
|
+
return items;
|
|
99
|
+
}
|
|
100
|
+
getControllerRouteName(classInfo) {
|
|
101
|
+
const controllerName = classInfo.name;
|
|
102
|
+
if (classInfo.route?.route) {
|
|
103
|
+
return classInfo.route.route;
|
|
104
|
+
}
|
|
105
|
+
return controllerName.substr(0, controllerName.length - 10).toLowerCase();
|
|
106
|
+
}
|
|
107
|
+
getRoutes() {
|
|
108
|
+
const routes = {};
|
|
109
|
+
for (const key of this.controllerInfo.keys()) {
|
|
110
|
+
const classInfo = this.controllerInfo.get(key);
|
|
111
|
+
let templateInfo = {
|
|
112
|
+
path: `.${classInfo.filePath.replace(TS_EXTENSION, BLANK).replace(BACK_SLASH_REGEX, RIGHT_SLASH)}`,
|
|
113
|
+
route: this.getControllerRouteName(classInfo),
|
|
114
|
+
parameters: classInfo.constructorParameters
|
|
115
|
+
};
|
|
116
|
+
for (const method of classInfo.methods) {
|
|
117
|
+
const routeInfo = method.route = this.getRouteInfo(method);
|
|
118
|
+
let httpMethod = routeInfo?.httpMethod;
|
|
119
|
+
if (DEFAULT_ACTIONS.indexOf(method.name) > -1)
|
|
120
|
+
httpMethod = method.name;
|
|
121
|
+
if (!templateInfo[httpMethod])
|
|
122
|
+
templateInfo[httpMethod] = {};
|
|
123
|
+
let route = this.getRoutePath(method, httpMethod);
|
|
124
|
+
let parameters = [];
|
|
125
|
+
for (const parameterInfo of method.parameters) {
|
|
126
|
+
parameters.push({ name: parameterInfo.name, type: parameterInfo.type });
|
|
127
|
+
}
|
|
128
|
+
templateInfo[httpMethod][route] = { name: method.name, parameters, returnType: method.returnType };
|
|
129
|
+
}
|
|
130
|
+
routes[templateInfo.route] = templateInfo;
|
|
131
|
+
}
|
|
132
|
+
return routes;
|
|
133
|
+
}
|
|
134
|
+
getRouteInfo(methodInfo) {
|
|
135
|
+
let route = methodInfo.route;
|
|
136
|
+
const parameters = methodInfo.parameters || [];
|
|
137
|
+
if (!route && methodInfo.name == "getBy") {
|
|
138
|
+
route = {
|
|
139
|
+
httpMethod: "get",
|
|
140
|
+
route: parameters.filter((t) => t.name == "id").map((t) => `:${t.name}`).join("/")
|
|
141
|
+
};
|
|
142
|
+
} else if (!route && methodInfo.name == "put") {
|
|
143
|
+
const parameter = parameters.filter((t) => t.name == "id")[0];
|
|
144
|
+
if (parameter) {
|
|
145
|
+
route = {
|
|
146
|
+
httpMethod: "put",
|
|
147
|
+
route: ":id"
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return route;
|
|
152
|
+
}
|
|
153
|
+
getRoutePath(method, httpMethod) {
|
|
154
|
+
const route = method.route;
|
|
155
|
+
let routePath = method.route?.route || DEFAULT_CHILD_PATH;
|
|
156
|
+
if (!route && httpMethod == DELETE && method.parameters) {
|
|
157
|
+
const parameter = method.parameters.filter((parameterInfo) => parameterInfo.name == "id")[0];
|
|
158
|
+
if (parameter)
|
|
159
|
+
routePath = ":id";
|
|
160
|
+
}
|
|
161
|
+
return routePath;
|
|
162
|
+
}
|
|
163
|
+
removeControllerInfo(path) {
|
|
164
|
+
const name = this.files.get(path);
|
|
165
|
+
if (name) {
|
|
166
|
+
this.files.delete(path);
|
|
167
|
+
this.controllerInfo.delete(name);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
getControllerJsonSchema(name) {
|
|
171
|
+
return this.controllerInfo.get(name);
|
|
172
|
+
}
|
|
173
|
+
}();
|
|
174
|
+
|
|
175
|
+
function createTestServer() {
|
|
176
|
+
const test = require("./build");
|
|
177
|
+
console.log(test);
|
|
178
|
+
return test;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function tsDefinition(value) {
|
|
182
|
+
const definition = /^(true|false)+$/i.test(value) ? "boolean" : /^[0-9]+$/.test(value) ? "number" : "string";
|
|
183
|
+
const transformValue = definition === "boolean" ? Boolean(value) : definition === "number" ? Number(value) : value;
|
|
184
|
+
return { definition, transformValue };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function getEnvTsDefinition(parsed) {
|
|
188
|
+
let serverTypedDefinition = {};
|
|
189
|
+
if (parsed) {
|
|
190
|
+
const keys = Object.keys(parsed);
|
|
191
|
+
if (keys.length > 0) {
|
|
192
|
+
keys.forEach((key) => {
|
|
193
|
+
let keyName = key;
|
|
194
|
+
const { definition, transformValue } = tsDefinition(parsed[key]);
|
|
195
|
+
serverTypedDefinition[keyName] = definition;
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return serverTypedDefinition;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function createPath(pathToCreate) {
|
|
203
|
+
var isNotExits = false;
|
|
204
|
+
pathToCreate.split(path__namespace.sep).reduce((prevPath, folder) => {
|
|
205
|
+
const currentPath = path__namespace.join(prevPath, folder, path__namespace.sep);
|
|
206
|
+
isNotExits = !fs__namespace.existsSync(currentPath);
|
|
207
|
+
if (isNotExits) {
|
|
208
|
+
fs__namespace.mkdirSync(currentPath);
|
|
209
|
+
}
|
|
210
|
+
return currentPath;
|
|
211
|
+
}, "");
|
|
212
|
+
return isNotExits;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function getPath(pathCollection, isIncludeRoot = true, isCreateFolder = false) {
|
|
216
|
+
const rootPath = isIncludeRoot ? [commonContainer.buildOptions.rootDir] : [];
|
|
217
|
+
const currentPath = path__namespace.join(...rootPath, ...pathCollection);
|
|
218
|
+
if (isCreateFolder)
|
|
219
|
+
createPath(currentPath);
|
|
220
|
+
return currentPath;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async function readEnv() {
|
|
224
|
+
let filePath = getPath([ENVIRONMENTS, commonContainer.buildOptions.mode && commonContainer.buildOptions.mode !== "dev" ? `.env.${commonContainer.buildOptions.mode}` : `.env`]);
|
|
225
|
+
let parsedEnvTsDefinition = {};
|
|
226
|
+
if (fs.existsSync(filePath)) {
|
|
227
|
+
const { parsed, error } = dotenv__namespace.config({
|
|
228
|
+
debug: !!process.env.DEBUG || void 0,
|
|
229
|
+
path: filePath
|
|
230
|
+
});
|
|
231
|
+
parsedEnvTsDefinition = getEnvTsDefinition(parsed);
|
|
232
|
+
commonContainer.setEnvTsDefinition(parsedEnvTsDefinition);
|
|
233
|
+
dotenvExpand__namespace.expand({ parsed });
|
|
234
|
+
}
|
|
235
|
+
return parsedEnvTsDefinition;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
class AuthenticationFilter {
|
|
239
|
+
onFailedResponse() {
|
|
240
|
+
return {
|
|
241
|
+
type: "https://tools.ietf.org/html/rfc7235#section-3.1",
|
|
242
|
+
title: "Unauthorized"
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
class AuthorizationFilter {
|
|
248
|
+
onFailedAuthorization() {
|
|
249
|
+
return {
|
|
250
|
+
type: "https://tools.ietf.org/html/rfc7231#section-6.5.3",
|
|
251
|
+
title: "Forbidden"
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
class ActionFilter {
|
|
257
|
+
onActionExecuting(context) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
onActionExecuted(context) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
class Middleware {
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
class ExceptionFilter {
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function readEnvKey(key) {
|
|
272
|
+
const definition = commonContainer.envTsDefinition[key];
|
|
273
|
+
const value = process.env[key];
|
|
274
|
+
let transformValue = value;
|
|
275
|
+
if (definition) {
|
|
276
|
+
transformValue = definition === "boolean" ? value === "true" : definition === "number" ? Number(value) : value;
|
|
277
|
+
}
|
|
278
|
+
return transformValue;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
class UserIdentity {
|
|
282
|
+
constructor(isAuthenticate, id, claim) {
|
|
283
|
+
this.isAuthenticate = isAuthenticate;
|
|
284
|
+
this.id = id;
|
|
285
|
+
this.claim = claim;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function isObject(value) {
|
|
290
|
+
return !!value && typeof value === "object" && !(value instanceof Date);
|
|
291
|
+
}
|
|
292
|
+
function isEqual(first, second) {
|
|
293
|
+
return Object.entries(first).every(
|
|
294
|
+
([key, value]) => isObject(value) ? isEqual(second[key], value) : second[key] === value
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function getInstance(model, objectArguments) {
|
|
299
|
+
return Reflect.construct(model, objectArguments);
|
|
300
|
+
}
|
|
301
|
+
function getObject(model, objectArguments, jObject, props) {
|
|
302
|
+
let instance = getInstance(model, objectArguments);
|
|
303
|
+
Object.keys(jObject).forEach((t) => {
|
|
304
|
+
const currentPropName = t.toLowerCase();
|
|
305
|
+
if (props) {
|
|
306
|
+
const propName = props[currentPropName];
|
|
307
|
+
if (propName)
|
|
308
|
+
instance[propName] = jObject[t];
|
|
309
|
+
} else
|
|
310
|
+
instance[t] = jObject[t];
|
|
311
|
+
});
|
|
312
|
+
return instance;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
class List {
|
|
316
|
+
constructor(values, model, props) {
|
|
317
|
+
this.model = model;
|
|
318
|
+
this.props = props;
|
|
319
|
+
this._entities = new Array();
|
|
320
|
+
this.build(values);
|
|
321
|
+
}
|
|
322
|
+
add(entity) {
|
|
323
|
+
this._entities.push(this.createObject(entity));
|
|
324
|
+
}
|
|
325
|
+
addRange(entities) {
|
|
326
|
+
for (let entity of entities)
|
|
327
|
+
this.add(entity);
|
|
328
|
+
}
|
|
329
|
+
all(predicate) {
|
|
330
|
+
return this._entities.every(predicate);
|
|
331
|
+
}
|
|
332
|
+
any(predicate) {
|
|
333
|
+
return this._entities.some(predicate);
|
|
334
|
+
}
|
|
335
|
+
average(transform) {
|
|
336
|
+
return this.sum(transform) / this.count(transform);
|
|
337
|
+
}
|
|
338
|
+
contains(element) {
|
|
339
|
+
return this._entities.some((x) => x === element);
|
|
340
|
+
}
|
|
341
|
+
concat(items) {
|
|
342
|
+
if (items) {
|
|
343
|
+
this.addRange(items);
|
|
344
|
+
return new List(this._entities, this.model);
|
|
345
|
+
}
|
|
346
|
+
return void 0;
|
|
347
|
+
}
|
|
348
|
+
count(predicate) {
|
|
349
|
+
return predicate ? this.where(predicate).count() : this._entities.length;
|
|
350
|
+
}
|
|
351
|
+
where(predicate) {
|
|
352
|
+
return new List(this._entities.filter(predicate), this.model);
|
|
353
|
+
}
|
|
354
|
+
distinct() {
|
|
355
|
+
return this.where(
|
|
356
|
+
(value, index, iter) => isObject(value) ? iter.findIndex((t) => isEqual(t, value)) == index : iter.indexOf(value) === index
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
distinctBy(keySelector) {
|
|
360
|
+
const entityGroup = this.groupBy(keySelector);
|
|
361
|
+
return Object.keys(entityGroup).reduce((resource, key) => {
|
|
362
|
+
resource.add(entityGroup[key][0]);
|
|
363
|
+
return resource;
|
|
364
|
+
}, new List());
|
|
365
|
+
}
|
|
366
|
+
elementAt(index) {
|
|
367
|
+
if (this._entities.length > index && index >= 0)
|
|
368
|
+
return this._entities[index];
|
|
369
|
+
}
|
|
370
|
+
except(collection) {
|
|
371
|
+
return this.where((x) => !collection.contains(x));
|
|
372
|
+
}
|
|
373
|
+
first(predicate) {
|
|
374
|
+
if (this.count()) {
|
|
375
|
+
return predicate ? this.where(predicate).first() : this._entities[0];
|
|
376
|
+
} else {
|
|
377
|
+
throw new Error("No result found.");
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
firstOrDefault(predicate) {
|
|
381
|
+
return this.count() ? this.first(predicate) : void 0;
|
|
382
|
+
}
|
|
383
|
+
forEach(action) {
|
|
384
|
+
return this._entities.forEach(action);
|
|
385
|
+
}
|
|
386
|
+
aggregate(accumulator, initialValue) {
|
|
387
|
+
return this._entities.reduce(accumulator, initialValue);
|
|
388
|
+
}
|
|
389
|
+
groupBy(grouper, mapper) {
|
|
390
|
+
if (!mapper)
|
|
391
|
+
mapper = (value) => value;
|
|
392
|
+
return this.aggregate((ac, v) => (ac[grouper(v)] ? ac[grouper(v)].push(mapper(v)) : ac[grouper(v)] = [mapper(v)], ac), {});
|
|
393
|
+
}
|
|
394
|
+
insert(index, element) {
|
|
395
|
+
if (index < 0 || index > this._entities.length) {
|
|
396
|
+
throw new Error("Index is out of range.");
|
|
397
|
+
}
|
|
398
|
+
this._entities.splice(index, 0, this.createObject(element));
|
|
399
|
+
}
|
|
400
|
+
join(seperator) {
|
|
401
|
+
return this._entities ? this._entities.join(seperator) : null;
|
|
402
|
+
}
|
|
403
|
+
last(predicate) {
|
|
404
|
+
if (this.count()) {
|
|
405
|
+
return predicate ? this.where(predicate).last() : this._entities[this.count() - 1];
|
|
406
|
+
} else {
|
|
407
|
+
throw Error("No result found.");
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
lastOrDefault(predicate) {
|
|
411
|
+
return this.count() ? this.last(predicate) : void 0;
|
|
412
|
+
}
|
|
413
|
+
get length() {
|
|
414
|
+
return this._entities ? this._entities.length : 0;
|
|
415
|
+
}
|
|
416
|
+
max(predicate) {
|
|
417
|
+
if (!predicate)
|
|
418
|
+
return this.aggregate((x, y) => x > y ? x : y);
|
|
419
|
+
else
|
|
420
|
+
return Math.max(...this._entities.map(predicate));
|
|
421
|
+
}
|
|
422
|
+
maxBy(keySelector) {
|
|
423
|
+
const entityGroup = this.groupBy(keySelector);
|
|
424
|
+
let keys = Object.keys(entityGroup);
|
|
425
|
+
let maxKey = Math.max(...keys);
|
|
426
|
+
return entityGroup[maxKey][0];
|
|
427
|
+
}
|
|
428
|
+
min(predicate) {
|
|
429
|
+
if (!predicate)
|
|
430
|
+
return this.aggregate((x, y) => x < y ? x : y);
|
|
431
|
+
else
|
|
432
|
+
return Math.min(...this._entities.map(predicate));
|
|
433
|
+
}
|
|
434
|
+
minBy(keySelector) {
|
|
435
|
+
const entityGroup = this.groupBy(keySelector);
|
|
436
|
+
let keys = Object.keys(entityGroup);
|
|
437
|
+
let minKey = Math.min(...keys);
|
|
438
|
+
return entityGroup[minKey][0];
|
|
439
|
+
}
|
|
440
|
+
orderBy(predicate) {
|
|
441
|
+
return new List(this._entities.sort(this.customSort(predicate, false)));
|
|
442
|
+
}
|
|
443
|
+
orderByDescending(predicate) {
|
|
444
|
+
return new List(this._entities.sort(this.customSort(predicate, true)));
|
|
445
|
+
}
|
|
446
|
+
pop() {
|
|
447
|
+
return this._entities.pop();
|
|
448
|
+
}
|
|
449
|
+
indexOf(element) {
|
|
450
|
+
return this._entities.indexOf(element);
|
|
451
|
+
}
|
|
452
|
+
remove(element) {
|
|
453
|
+
return this._entities.indexOf(element) !== -1 ? (this.removeAt(this._entities.indexOf(element)), true) : false;
|
|
454
|
+
}
|
|
455
|
+
removeAll(predicate) {
|
|
456
|
+
return this.where(this._negate(predicate));
|
|
457
|
+
}
|
|
458
|
+
removeAt(index) {
|
|
459
|
+
this._entities.splice(index, 1);
|
|
460
|
+
}
|
|
461
|
+
reverse() {
|
|
462
|
+
return this._entities ? new List(this._entities.reverse(), this.model) : new List();
|
|
463
|
+
}
|
|
464
|
+
select(mapper) {
|
|
465
|
+
return this._entities.map(mapper);
|
|
466
|
+
}
|
|
467
|
+
single(predicate) {
|
|
468
|
+
if (this.count(predicate) !== 1) {
|
|
469
|
+
throw new Error("Item does not contain one element.");
|
|
470
|
+
} else {
|
|
471
|
+
return this.first(predicate);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
singleOrDefault(predicate) {
|
|
475
|
+
return this.count() ? this.first(predicate) : void 0;
|
|
476
|
+
}
|
|
477
|
+
shift() {
|
|
478
|
+
return this._entities ? this._entities.shift() : void 0;
|
|
479
|
+
}
|
|
480
|
+
skip(amount) {
|
|
481
|
+
return new List(this._entities.slice(Math.max(0, amount)), this.model);
|
|
482
|
+
}
|
|
483
|
+
sum(transform) {
|
|
484
|
+
let result = this.select(transform);
|
|
485
|
+
if (transform) {
|
|
486
|
+
let sum = 0;
|
|
487
|
+
if (result)
|
|
488
|
+
result.forEach((t) => sum += t);
|
|
489
|
+
return sum;
|
|
490
|
+
} else
|
|
491
|
+
return this.aggregate((ac, v) => ac += +v, 0);
|
|
492
|
+
}
|
|
493
|
+
take(amount) {
|
|
494
|
+
return new List(this._entities.slice(0, Math.max(0, amount)), this.model);
|
|
495
|
+
}
|
|
496
|
+
search(value, filterColumns) {
|
|
497
|
+
var filter = [];
|
|
498
|
+
this._entities.forEach((t) => {
|
|
499
|
+
if (this.wildcardSearch(t, value, filterColumns))
|
|
500
|
+
filter.push(t);
|
|
501
|
+
});
|
|
502
|
+
return new List(filter, this.model);
|
|
503
|
+
}
|
|
504
|
+
wildcardSearch(row, prefix, filterColumns) {
|
|
505
|
+
let isMatched = false;
|
|
506
|
+
for (var i = 0, j = filterColumns.length; i < j; i++) {
|
|
507
|
+
var t = filterColumns[i];
|
|
508
|
+
var columnValue = String(row[t]);
|
|
509
|
+
if (this.isExist(columnValue, prefix)) {
|
|
510
|
+
isMatched = true;
|
|
511
|
+
break;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return isMatched;
|
|
515
|
+
}
|
|
516
|
+
isExist(columnValue, prefix) {
|
|
517
|
+
if (columnValue == null) {
|
|
518
|
+
return false;
|
|
519
|
+
}
|
|
520
|
+
return String(columnValue).toLowerCase().includes(String(prefix).toLowerCase());
|
|
521
|
+
}
|
|
522
|
+
get toLocaleString() {
|
|
523
|
+
return this._entities ? this._entities.toLocaleString() : null;
|
|
524
|
+
}
|
|
525
|
+
get toString() {
|
|
526
|
+
return this._entities ? this._entities.toString() : null;
|
|
527
|
+
}
|
|
528
|
+
get values() {
|
|
529
|
+
return this._entities;
|
|
530
|
+
}
|
|
531
|
+
_negate(predicate) {
|
|
532
|
+
return function() {
|
|
533
|
+
const _arg = arguments;
|
|
534
|
+
return !predicate.apply(this, _arg);
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
customSort(predicate, orderByDescending) {
|
|
538
|
+
return (a, b) => {
|
|
539
|
+
const first = predicate(a);
|
|
540
|
+
const second = predicate(b);
|
|
541
|
+
if (first > second) {
|
|
542
|
+
return !orderByDescending ? 1 : -1;
|
|
543
|
+
} else if (first < second) {
|
|
544
|
+
return !orderByDescending ? -1 : 1;
|
|
545
|
+
} else {
|
|
546
|
+
return 0;
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
build(values) {
|
|
551
|
+
if (values && values.length > 0) {
|
|
552
|
+
this.addRange(values);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
createObject(object) {
|
|
556
|
+
if (this.model && object.constructor !== this.model)
|
|
557
|
+
return getObject(this.model, [], object, this.props);
|
|
558
|
+
return object;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
exports.ALLOW_METHODS = ALLOW_METHODS;
|
|
563
|
+
exports.ActionFilter = ActionFilter;
|
|
564
|
+
exports.AuthenticationFilter = AuthenticationFilter;
|
|
565
|
+
exports.AuthorizationFilter = AuthorizationFilter;
|
|
566
|
+
exports.BACK_SLASH_REGEX = BACK_SLASH_REGEX;
|
|
567
|
+
exports.BLANK = BLANK;
|
|
568
|
+
exports.CONTROLLER = CONTROLLER;
|
|
569
|
+
exports.DEFAULT_ACTIONS = DEFAULT_ACTIONS;
|
|
570
|
+
exports.DEFAULT_CHILD_PATH = DEFAULT_CHILD_PATH;
|
|
571
|
+
exports.DELETE = DELETE;
|
|
572
|
+
exports.ENVIRONMENTS = ENVIRONMENTS;
|
|
573
|
+
exports.ExceptionFilter = ExceptionFilter;
|
|
574
|
+
exports.GET = GET;
|
|
575
|
+
exports.HTTP_METHOD_ROUTES = HTTP_METHOD_ROUTES;
|
|
576
|
+
exports.IGNORE_METHODS = IGNORE_METHODS;
|
|
577
|
+
exports.List = List;
|
|
578
|
+
exports.MetaConfigProps = MetaConfigProps;
|
|
579
|
+
exports.Middleware = Middleware;
|
|
580
|
+
exports.POST = POST;
|
|
581
|
+
exports.PUT = PUT;
|
|
582
|
+
exports.RIGHT_SLASH = RIGHT_SLASH;
|
|
583
|
+
exports.ROUTE_INSTANCES = ROUTE_INSTANCES;
|
|
584
|
+
exports.ROUTE_METHODS = ROUTE_METHODS;
|
|
585
|
+
exports.ROUTE_PATHS = ROUTE_PATHS;
|
|
586
|
+
exports.TS_EXTENSION = TS_EXTENSION;
|
|
587
|
+
exports.UserIdentity = UserIdentity;
|
|
588
|
+
exports.commonContainer = commonContainer;
|
|
589
|
+
exports.createPath = createPath;
|
|
590
|
+
exports.createTestServer = createTestServer;
|
|
591
|
+
exports.getPath = getPath;
|
|
592
|
+
exports.isConstructor = isConstructor;
|
|
593
|
+
exports.isEqual = isEqual;
|
|
594
|
+
exports.isFunction = isFunction;
|
|
595
|
+
exports.isObject = isObject;
|
|
596
|
+
exports.readEnv = readEnv;
|
|
597
|
+
exports.readEnvKey = readEnvKey;
|
|
598
|
+
exports.typeContainer = typeContainer;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { RequestRouteInfo, IHttpResult, IModelBindingContext, ProblemDetail, IExceptionContext, HttpResponseInit, NattyTestModule, ModelBinding, BuildOptions, ClassTypeInfo } from '@nattyjs/types';
|
|
2
|
+
|
|
3
|
+
interface ClassType<T> extends Function {
|
|
4
|
+
new (...args: any[]): T;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
declare class UserIdentity<T> {
|
|
8
|
+
isAuthenticate: boolean;
|
|
9
|
+
id?: any;
|
|
10
|
+
claim?: T;
|
|
11
|
+
constructor(isAuthenticate: boolean, id?: any, claim?: T);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface IExecutionContext {
|
|
15
|
+
resolveService<T>(instance: ClassType<T>): T;
|
|
16
|
+
routeInfo: RequestRouteInfo;
|
|
17
|
+
get request(): any;
|
|
18
|
+
get user(): UserIdentity<any>;
|
|
19
|
+
result: IHttpResult;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface IActionExecutedContext extends IExecutionContext {
|
|
23
|
+
content: any;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface IActionExecutingContext extends IExecutionContext {
|
|
27
|
+
models: IModelBindingContext[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
declare abstract class ActionFilter {
|
|
31
|
+
onActionExecuting(context: IActionExecutingContext): Promise<void>;
|
|
32
|
+
onActionExecuted(context: IActionExecutedContext): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
declare abstract class AuthenticationFilter {
|
|
36
|
+
abstract onAuthentication(context: any): Promise<UserIdentity<any>>;
|
|
37
|
+
onFailedResponse(): ProblemDetail;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
declare abstract class AuthorizationFilter {
|
|
41
|
+
abstract onAuthorization(httpContext: any, permissionRequirement: any): Promise<boolean>;
|
|
42
|
+
onFailedAuthorization(): ProblemDetail;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
declare abstract class ExceptionFilter {
|
|
46
|
+
abstract onException(context: IExceptionContext): HttpResponseInit;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface GlobalConfig {
|
|
50
|
+
authentication?: ClassType<AuthenticationFilter>;
|
|
51
|
+
authorization?: ClassType<AuthorizationFilter>;
|
|
52
|
+
actionFilters?: ClassType<ActionFilter>[];
|
|
53
|
+
onException?: ClassType<ExceptionFilter>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface NattyConfig {
|
|
57
|
+
app: any;
|
|
58
|
+
testModule?: NattyTestModule;
|
|
59
|
+
api?: {
|
|
60
|
+
rootPath: string;
|
|
61
|
+
};
|
|
62
|
+
modelBinding?: ModelBinding;
|
|
63
|
+
global?: GlobalConfig;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
declare const commonContainer: {
|
|
67
|
+
setupConfig(config?: NattyConfig): void;
|
|
68
|
+
setupBuildOptions(options: BuildOptions): any;
|
|
69
|
+
get nattyConfig(): NattyConfig;
|
|
70
|
+
get buildOptions(): BuildOptions;
|
|
71
|
+
get envTsDefinition(): {
|
|
72
|
+
[key: string]: string;
|
|
73
|
+
};
|
|
74
|
+
setEnvTsDefinition(tsDefinition: {
|
|
75
|
+
[key: string]: string;
|
|
76
|
+
}): void;
|
|
77
|
+
setMetadata(key: string, value: any, propName: string): void;
|
|
78
|
+
getMetadataValue(key: string, propName: string): any;
|
|
79
|
+
get globalConfig(): GlobalConfig;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
declare const typeContainer: {
|
|
83
|
+
setControllerJsonSchema(classInfo: ClassTypeInfo): void;
|
|
84
|
+
getControllersJsonSchema(): ClassTypeInfo[];
|
|
85
|
+
getRoutes(): any;
|
|
86
|
+
getControllerJsonSchema(name: string): ClassTypeInfo;
|
|
87
|
+
removeControllerInfo(path: string): void;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
declare function createTestServer(): any;
|
|
91
|
+
|
|
92
|
+
declare const CONTROLLER: string;
|
|
93
|
+
declare const ENVIRONMENTS: string;
|
|
94
|
+
declare const BLANK: string;
|
|
95
|
+
declare const GET: string;
|
|
96
|
+
declare const POST: string;
|
|
97
|
+
declare const PUT: string;
|
|
98
|
+
declare const DELETE: string;
|
|
99
|
+
declare const ALLOW_METHODS: string[];
|
|
100
|
+
declare const IGNORE_METHODS: string;
|
|
101
|
+
declare const ROUTE_METHODS: string;
|
|
102
|
+
declare const ROUTE_INSTANCES: string;
|
|
103
|
+
declare const ROUTE_PATHS: string;
|
|
104
|
+
declare const HTTP_METHOD_ROUTES: string;
|
|
105
|
+
declare const isConstructor: (value: any) => boolean;
|
|
106
|
+
declare const isFunction: (value: any) => boolean;
|
|
107
|
+
declare const DEFAULT_ACTIONS: string[];
|
|
108
|
+
declare const MetaConfigProps: {
|
|
109
|
+
services: string;
|
|
110
|
+
};
|
|
111
|
+
declare const DEFAULT_CHILD_PATH: string;
|
|
112
|
+
declare const TS_EXTENSION: string;
|
|
113
|
+
declare const BACK_SLASH_REGEX: RegExp;
|
|
114
|
+
declare const RIGHT_SLASH: string;
|
|
115
|
+
|
|
116
|
+
declare function readEnv(): Promise<{
|
|
117
|
+
[key: string]: any;
|
|
118
|
+
}>;
|
|
119
|
+
|
|
120
|
+
declare abstract class Middleware {
|
|
121
|
+
abstract use(httpContext: any): Boolean | Promise<Boolean>;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
declare function getPath(pathCollection: string[], isIncludeRoot?: boolean, isCreateFolder?: boolean): string;
|
|
125
|
+
|
|
126
|
+
declare function readEnvKey(key: string): any;
|
|
127
|
+
|
|
128
|
+
declare function createPath(pathToCreate: any): boolean;
|
|
129
|
+
|
|
130
|
+
interface Claim {
|
|
131
|
+
key: string;
|
|
132
|
+
value: any;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
declare class List<T> {
|
|
136
|
+
private model?;
|
|
137
|
+
props?: {
|
|
138
|
+
[key: string]: string;
|
|
139
|
+
};
|
|
140
|
+
private _entities;
|
|
141
|
+
constructor(values?: T[] | any[], model?: ClassType<T>, props?: {
|
|
142
|
+
[key: string]: string;
|
|
143
|
+
});
|
|
144
|
+
add(entity: T): void;
|
|
145
|
+
addRange(entities: T[]): void;
|
|
146
|
+
all(predicate: (value?: T, index?: number, list?: T[]) => boolean): boolean;
|
|
147
|
+
any(predicate: (value?: T, index?: number, list?: T[]) => boolean): boolean;
|
|
148
|
+
average(transform?: (value?: T, index?: number, list?: T[]) => any): number;
|
|
149
|
+
contains(element: T): boolean;
|
|
150
|
+
concat(items: T[] | any[]): List<T>;
|
|
151
|
+
count(predicate?: (value?: T, index?: number, list?: T[]) => boolean): number;
|
|
152
|
+
where(predicate: (value?: T, index?: number, list?: T[]) => boolean): List<T>;
|
|
153
|
+
distinct(): List<T>;
|
|
154
|
+
distinctBy(keySelector: (key: T) => string | number): List<T>;
|
|
155
|
+
elementAt(index: number): T;
|
|
156
|
+
except(collection: List<T>): List<T>;
|
|
157
|
+
first(predicate?: (value?: T, index?: number, list?: T[]) => boolean): T;
|
|
158
|
+
firstOrDefault(predicate?: (value?: T, index?: number, list?: T[]) => boolean): T;
|
|
159
|
+
forEach(action: (value?: T, index?: number, list?: T[]) => any): void;
|
|
160
|
+
aggregate<U>(accumulator: (accum: U, value?: T, index?: number, list?: T[]) => any, initialValue?: U): any;
|
|
161
|
+
groupBy(grouper: (key: T) => any, mapper?: (element: T) => any): any;
|
|
162
|
+
insert(index: number, element: T): void | Error;
|
|
163
|
+
join(seperator?: string): string;
|
|
164
|
+
last(predicate?: (value?: T, index?: number, list?: T[]) => boolean): T;
|
|
165
|
+
lastOrDefault(predicate?: (value?: T, index?: number, list?: T[]) => boolean): T | Error;
|
|
166
|
+
get length(): number;
|
|
167
|
+
max(): number;
|
|
168
|
+
max(predicate: (value: T, index: number, list: T[]) => number): number;
|
|
169
|
+
maxBy(keySelector: (key: T) => number): T;
|
|
170
|
+
min(): number;
|
|
171
|
+
min(predicate: (value: T, index: number, list: T[]) => number): number;
|
|
172
|
+
minBy(keySelector: (key: T) => number): T;
|
|
173
|
+
orderBy(predicate: (key: T) => any): List<T>;
|
|
174
|
+
orderByDescending(predicate: (key: T) => any): List<T>;
|
|
175
|
+
pop(): T | undefined;
|
|
176
|
+
indexOf(element: T): number;
|
|
177
|
+
remove(element: T): boolean;
|
|
178
|
+
removeAll(predicate: (value?: T, index?: number, list?: T[]) => boolean): List<T>;
|
|
179
|
+
removeAt(index: number): void;
|
|
180
|
+
reverse(): List<T>;
|
|
181
|
+
select(mapper: (value?: T, index?: number, list?: T[]) => any): any;
|
|
182
|
+
single(predicate?: (value?: T, index?: number, list?: T[]) => boolean): T | Error;
|
|
183
|
+
singleOrDefault(predicate?: (value?: T, index?: number, list?: T[]) => boolean): T | Error;
|
|
184
|
+
shift(): T | undefined;
|
|
185
|
+
skip(amount: number): List<T>;
|
|
186
|
+
sum(transform?: (value?: T, index?: number, list?: T[]) => number): number;
|
|
187
|
+
take(amount: number): List<T>;
|
|
188
|
+
search(value: any, filterColumns: string[]): List<T>;
|
|
189
|
+
private wildcardSearch;
|
|
190
|
+
private isExist;
|
|
191
|
+
get toLocaleString(): string;
|
|
192
|
+
get toString(): string;
|
|
193
|
+
get values(): T[];
|
|
194
|
+
private _negate;
|
|
195
|
+
private customSort;
|
|
196
|
+
private build;
|
|
197
|
+
private createObject;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
declare function isObject(value: any): boolean;
|
|
201
|
+
declare function isEqual(first: any, second: any): boolean;
|
|
202
|
+
|
|
203
|
+
export { ALLOW_METHODS, ActionFilter, AuthenticationFilter, AuthorizationFilter, BACK_SLASH_REGEX, BLANK, CONTROLLER, Claim, ClassType, DEFAULT_ACTIONS, DEFAULT_CHILD_PATH, DELETE, ENVIRONMENTS, ExceptionFilter, GET, GlobalConfig, HTTP_METHOD_ROUTES, IActionExecutedContext, IActionExecutingContext, IExecutionContext, IGNORE_METHODS, List, MetaConfigProps, Middleware, NattyConfig, POST, PUT, RIGHT_SLASH, ROUTE_INSTANCES, ROUTE_METHODS, ROUTE_PATHS, TS_EXTENSION, UserIdentity, commonContainer, createPath, createTestServer, getPath, isConstructor, isEqual, isFunction, isObject, readEnv, readEnvKey, typeContainer };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import * as dotenv from 'dotenv';
|
|
4
|
+
import * as dotenvExpand from 'dotenv-expand';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
|
|
7
|
+
const commonContainer = new class {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.metadataConfig = { services: /* @__PURE__ */ new Map() };
|
|
10
|
+
}
|
|
11
|
+
setupConfig(config) {
|
|
12
|
+
const modelBinding = {
|
|
13
|
+
errorMessage: {
|
|
14
|
+
typed: {
|
|
15
|
+
number: "Invalid numeric value of '{0}'.",
|
|
16
|
+
boolean: "Invalid boolean value of '{0}'."
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
this.nattyConfig = { ...{ api: { rootPath: "api" }, modelBinding, globalConfig: {} }, ...config };
|
|
21
|
+
}
|
|
22
|
+
setupBuildOptions(options) {
|
|
23
|
+
this.buildOptions = options;
|
|
24
|
+
}
|
|
25
|
+
setEnvTsDefinition(tsDefinition) {
|
|
26
|
+
this.envTsDefinition = tsDefinition;
|
|
27
|
+
}
|
|
28
|
+
setMetadata(key, value, propName) {
|
|
29
|
+
this.metadataConfig[propName].set(key, value);
|
|
30
|
+
}
|
|
31
|
+
getMetadataValue(key, propName) {
|
|
32
|
+
return this.metadataConfig[propName].get(key);
|
|
33
|
+
}
|
|
34
|
+
get globalConfig() {
|
|
35
|
+
return this.nattyConfig.global || {};
|
|
36
|
+
}
|
|
37
|
+
}();
|
|
38
|
+
|
|
39
|
+
const CONTROLLER = "controller";
|
|
40
|
+
const ENVIRONMENTS = "environments";
|
|
41
|
+
const BLANK = "";
|
|
42
|
+
const GET = "get";
|
|
43
|
+
const POST = "post";
|
|
44
|
+
const PUT = "put";
|
|
45
|
+
const DELETE = "delete";
|
|
46
|
+
const ALLOW_METHODS = [GET, POST, PUT, DELETE];
|
|
47
|
+
const IGNORE_METHODS = "IGNORE:METHODS";
|
|
48
|
+
const ROUTE_METHODS = "ROUTE:METHODS";
|
|
49
|
+
const ROUTE_INSTANCES = "ROUTE:INSTANCES";
|
|
50
|
+
const ROUTE_PATHS = "ROUTE:PATHS";
|
|
51
|
+
const HTTP_METHOD_ROUTES = "HTTPMETHOD:ROUTES";
|
|
52
|
+
const isConstructor = (value) => value === "constructor";
|
|
53
|
+
const isFunction = (value) => typeof value === "function";
|
|
54
|
+
const DEFAULT_ACTIONS = [GET, POST, PUT, DELETE];
|
|
55
|
+
const MetaConfigProps = {
|
|
56
|
+
services: "services"
|
|
57
|
+
};
|
|
58
|
+
const DEFAULT_CHILD_PATH = "/";
|
|
59
|
+
const TS_EXTENSION = ".ts";
|
|
60
|
+
const BACK_SLASH_REGEX = /\\/g;
|
|
61
|
+
const RIGHT_SLASH = "/";
|
|
62
|
+
|
|
63
|
+
const typeContainer = new class {
|
|
64
|
+
constructor() {
|
|
65
|
+
this.controllerInfo = /* @__PURE__ */ new Map();
|
|
66
|
+
this.files = /* @__PURE__ */ new Map();
|
|
67
|
+
this.routes = {};
|
|
68
|
+
}
|
|
69
|
+
setControllerJsonSchema(classInfo) {
|
|
70
|
+
const className = this.files.get(classInfo.filePath);
|
|
71
|
+
const isChanged = !className ? false : className != classInfo.name;
|
|
72
|
+
if (isChanged)
|
|
73
|
+
this.controllerInfo.delete(className);
|
|
74
|
+
this.controllerInfo.set(classInfo.name, classInfo);
|
|
75
|
+
this.files.set(classInfo.filePath, classInfo.name);
|
|
76
|
+
}
|
|
77
|
+
getControllersJsonSchema() {
|
|
78
|
+
const items = new Array();
|
|
79
|
+
this.controllerInfo.forEach((t) => items.push(t));
|
|
80
|
+
return items;
|
|
81
|
+
}
|
|
82
|
+
getControllerRouteName(classInfo) {
|
|
83
|
+
const controllerName = classInfo.name;
|
|
84
|
+
if (classInfo.route?.route) {
|
|
85
|
+
return classInfo.route.route;
|
|
86
|
+
}
|
|
87
|
+
return controllerName.substr(0, controllerName.length - 10).toLowerCase();
|
|
88
|
+
}
|
|
89
|
+
getRoutes() {
|
|
90
|
+
const routes = {};
|
|
91
|
+
for (const key of this.controllerInfo.keys()) {
|
|
92
|
+
const classInfo = this.controllerInfo.get(key);
|
|
93
|
+
let templateInfo = {
|
|
94
|
+
path: `.${classInfo.filePath.replace(TS_EXTENSION, BLANK).replace(BACK_SLASH_REGEX, RIGHT_SLASH)}`,
|
|
95
|
+
route: this.getControllerRouteName(classInfo),
|
|
96
|
+
parameters: classInfo.constructorParameters
|
|
97
|
+
};
|
|
98
|
+
for (const method of classInfo.methods) {
|
|
99
|
+
const routeInfo = method.route = this.getRouteInfo(method);
|
|
100
|
+
let httpMethod = routeInfo?.httpMethod;
|
|
101
|
+
if (DEFAULT_ACTIONS.indexOf(method.name) > -1)
|
|
102
|
+
httpMethod = method.name;
|
|
103
|
+
if (!templateInfo[httpMethod])
|
|
104
|
+
templateInfo[httpMethod] = {};
|
|
105
|
+
let route = this.getRoutePath(method, httpMethod);
|
|
106
|
+
let parameters = [];
|
|
107
|
+
for (const parameterInfo of method.parameters) {
|
|
108
|
+
parameters.push({ name: parameterInfo.name, type: parameterInfo.type });
|
|
109
|
+
}
|
|
110
|
+
templateInfo[httpMethod][route] = { name: method.name, parameters, returnType: method.returnType };
|
|
111
|
+
}
|
|
112
|
+
routes[templateInfo.route] = templateInfo;
|
|
113
|
+
}
|
|
114
|
+
return routes;
|
|
115
|
+
}
|
|
116
|
+
getRouteInfo(methodInfo) {
|
|
117
|
+
let route = methodInfo.route;
|
|
118
|
+
const parameters = methodInfo.parameters || [];
|
|
119
|
+
if (!route && methodInfo.name == "getBy") {
|
|
120
|
+
route = {
|
|
121
|
+
httpMethod: "get",
|
|
122
|
+
route: parameters.filter((t) => t.name == "id").map((t) => `:${t.name}`).join("/")
|
|
123
|
+
};
|
|
124
|
+
} else if (!route && methodInfo.name == "put") {
|
|
125
|
+
const parameter = parameters.filter((t) => t.name == "id")[0];
|
|
126
|
+
if (parameter) {
|
|
127
|
+
route = {
|
|
128
|
+
httpMethod: "put",
|
|
129
|
+
route: ":id"
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return route;
|
|
134
|
+
}
|
|
135
|
+
getRoutePath(method, httpMethod) {
|
|
136
|
+
const route = method.route;
|
|
137
|
+
let routePath = method.route?.route || DEFAULT_CHILD_PATH;
|
|
138
|
+
if (!route && httpMethod == DELETE && method.parameters) {
|
|
139
|
+
const parameter = method.parameters.filter((parameterInfo) => parameterInfo.name == "id")[0];
|
|
140
|
+
if (parameter)
|
|
141
|
+
routePath = ":id";
|
|
142
|
+
}
|
|
143
|
+
return routePath;
|
|
144
|
+
}
|
|
145
|
+
removeControllerInfo(path) {
|
|
146
|
+
const name = this.files.get(path);
|
|
147
|
+
if (name) {
|
|
148
|
+
this.files.delete(path);
|
|
149
|
+
this.controllerInfo.delete(name);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
getControllerJsonSchema(name) {
|
|
153
|
+
return this.controllerInfo.get(name);
|
|
154
|
+
}
|
|
155
|
+
}();
|
|
156
|
+
|
|
157
|
+
function createTestServer() {
|
|
158
|
+
const test = require("./build");
|
|
159
|
+
console.log(test);
|
|
160
|
+
return test;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function tsDefinition(value) {
|
|
164
|
+
const definition = /^(true|false)+$/i.test(value) ? "boolean" : /^[0-9]+$/.test(value) ? "number" : "string";
|
|
165
|
+
const transformValue = definition === "boolean" ? Boolean(value) : definition === "number" ? Number(value) : value;
|
|
166
|
+
return { definition, transformValue };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function getEnvTsDefinition(parsed) {
|
|
170
|
+
let serverTypedDefinition = {};
|
|
171
|
+
if (parsed) {
|
|
172
|
+
const keys = Object.keys(parsed);
|
|
173
|
+
if (keys.length > 0) {
|
|
174
|
+
keys.forEach((key) => {
|
|
175
|
+
let keyName = key;
|
|
176
|
+
const { definition, transformValue } = tsDefinition(parsed[key]);
|
|
177
|
+
serverTypedDefinition[keyName] = definition;
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return serverTypedDefinition;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function createPath(pathToCreate) {
|
|
185
|
+
var isNotExits = false;
|
|
186
|
+
pathToCreate.split(path.sep).reduce((prevPath, folder) => {
|
|
187
|
+
const currentPath = path.join(prevPath, folder, path.sep);
|
|
188
|
+
isNotExits = !fs.existsSync(currentPath);
|
|
189
|
+
if (isNotExits) {
|
|
190
|
+
fs.mkdirSync(currentPath);
|
|
191
|
+
}
|
|
192
|
+
return currentPath;
|
|
193
|
+
}, "");
|
|
194
|
+
return isNotExits;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function getPath(pathCollection, isIncludeRoot = true, isCreateFolder = false) {
|
|
198
|
+
const rootPath = isIncludeRoot ? [commonContainer.buildOptions.rootDir] : [];
|
|
199
|
+
const currentPath = path.join(...rootPath, ...pathCollection);
|
|
200
|
+
if (isCreateFolder)
|
|
201
|
+
createPath(currentPath);
|
|
202
|
+
return currentPath;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async function readEnv() {
|
|
206
|
+
let filePath = getPath([ENVIRONMENTS, commonContainer.buildOptions.mode && commonContainer.buildOptions.mode !== "dev" ? `.env.${commonContainer.buildOptions.mode}` : `.env`]);
|
|
207
|
+
let parsedEnvTsDefinition = {};
|
|
208
|
+
if (existsSync(filePath)) {
|
|
209
|
+
const { parsed, error } = dotenv.config({
|
|
210
|
+
debug: !!process.env.DEBUG || void 0,
|
|
211
|
+
path: filePath
|
|
212
|
+
});
|
|
213
|
+
parsedEnvTsDefinition = getEnvTsDefinition(parsed);
|
|
214
|
+
commonContainer.setEnvTsDefinition(parsedEnvTsDefinition);
|
|
215
|
+
dotenvExpand.expand({ parsed });
|
|
216
|
+
}
|
|
217
|
+
return parsedEnvTsDefinition;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
class AuthenticationFilter {
|
|
221
|
+
onFailedResponse() {
|
|
222
|
+
return {
|
|
223
|
+
type: "https://tools.ietf.org/html/rfc7235#section-3.1",
|
|
224
|
+
title: "Unauthorized"
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
class AuthorizationFilter {
|
|
230
|
+
onFailedAuthorization() {
|
|
231
|
+
return {
|
|
232
|
+
type: "https://tools.ietf.org/html/rfc7231#section-6.5.3",
|
|
233
|
+
title: "Forbidden"
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
class ActionFilter {
|
|
239
|
+
onActionExecuting(context) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
onActionExecuted(context) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
class Middleware {
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
class ExceptionFilter {
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function readEnvKey(key) {
|
|
254
|
+
const definition = commonContainer.envTsDefinition[key];
|
|
255
|
+
const value = process.env[key];
|
|
256
|
+
let transformValue = value;
|
|
257
|
+
if (definition) {
|
|
258
|
+
transformValue = definition === "boolean" ? value === "true" : definition === "number" ? Number(value) : value;
|
|
259
|
+
}
|
|
260
|
+
return transformValue;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
class UserIdentity {
|
|
264
|
+
constructor(isAuthenticate, id, claim) {
|
|
265
|
+
this.isAuthenticate = isAuthenticate;
|
|
266
|
+
this.id = id;
|
|
267
|
+
this.claim = claim;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function isObject(value) {
|
|
272
|
+
return !!value && typeof value === "object" && !(value instanceof Date);
|
|
273
|
+
}
|
|
274
|
+
function isEqual(first, second) {
|
|
275
|
+
return Object.entries(first).every(
|
|
276
|
+
([key, value]) => isObject(value) ? isEqual(second[key], value) : second[key] === value
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function getInstance(model, objectArguments) {
|
|
281
|
+
return Reflect.construct(model, objectArguments);
|
|
282
|
+
}
|
|
283
|
+
function getObject(model, objectArguments, jObject, props) {
|
|
284
|
+
let instance = getInstance(model, objectArguments);
|
|
285
|
+
Object.keys(jObject).forEach((t) => {
|
|
286
|
+
const currentPropName = t.toLowerCase();
|
|
287
|
+
if (props) {
|
|
288
|
+
const propName = props[currentPropName];
|
|
289
|
+
if (propName)
|
|
290
|
+
instance[propName] = jObject[t];
|
|
291
|
+
} else
|
|
292
|
+
instance[t] = jObject[t];
|
|
293
|
+
});
|
|
294
|
+
return instance;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
class List {
|
|
298
|
+
constructor(values, model, props) {
|
|
299
|
+
this.model = model;
|
|
300
|
+
this.props = props;
|
|
301
|
+
this._entities = new Array();
|
|
302
|
+
this.build(values);
|
|
303
|
+
}
|
|
304
|
+
add(entity) {
|
|
305
|
+
this._entities.push(this.createObject(entity));
|
|
306
|
+
}
|
|
307
|
+
addRange(entities) {
|
|
308
|
+
for (let entity of entities)
|
|
309
|
+
this.add(entity);
|
|
310
|
+
}
|
|
311
|
+
all(predicate) {
|
|
312
|
+
return this._entities.every(predicate);
|
|
313
|
+
}
|
|
314
|
+
any(predicate) {
|
|
315
|
+
return this._entities.some(predicate);
|
|
316
|
+
}
|
|
317
|
+
average(transform) {
|
|
318
|
+
return this.sum(transform) / this.count(transform);
|
|
319
|
+
}
|
|
320
|
+
contains(element) {
|
|
321
|
+
return this._entities.some((x) => x === element);
|
|
322
|
+
}
|
|
323
|
+
concat(items) {
|
|
324
|
+
if (items) {
|
|
325
|
+
this.addRange(items);
|
|
326
|
+
return new List(this._entities, this.model);
|
|
327
|
+
}
|
|
328
|
+
return void 0;
|
|
329
|
+
}
|
|
330
|
+
count(predicate) {
|
|
331
|
+
return predicate ? this.where(predicate).count() : this._entities.length;
|
|
332
|
+
}
|
|
333
|
+
where(predicate) {
|
|
334
|
+
return new List(this._entities.filter(predicate), this.model);
|
|
335
|
+
}
|
|
336
|
+
distinct() {
|
|
337
|
+
return this.where(
|
|
338
|
+
(value, index, iter) => isObject(value) ? iter.findIndex((t) => isEqual(t, value)) == index : iter.indexOf(value) === index
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
distinctBy(keySelector) {
|
|
342
|
+
const entityGroup = this.groupBy(keySelector);
|
|
343
|
+
return Object.keys(entityGroup).reduce((resource, key) => {
|
|
344
|
+
resource.add(entityGroup[key][0]);
|
|
345
|
+
return resource;
|
|
346
|
+
}, new List());
|
|
347
|
+
}
|
|
348
|
+
elementAt(index) {
|
|
349
|
+
if (this._entities.length > index && index >= 0)
|
|
350
|
+
return this._entities[index];
|
|
351
|
+
}
|
|
352
|
+
except(collection) {
|
|
353
|
+
return this.where((x) => !collection.contains(x));
|
|
354
|
+
}
|
|
355
|
+
first(predicate) {
|
|
356
|
+
if (this.count()) {
|
|
357
|
+
return predicate ? this.where(predicate).first() : this._entities[0];
|
|
358
|
+
} else {
|
|
359
|
+
throw new Error("No result found.");
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
firstOrDefault(predicate) {
|
|
363
|
+
return this.count() ? this.first(predicate) : void 0;
|
|
364
|
+
}
|
|
365
|
+
forEach(action) {
|
|
366
|
+
return this._entities.forEach(action);
|
|
367
|
+
}
|
|
368
|
+
aggregate(accumulator, initialValue) {
|
|
369
|
+
return this._entities.reduce(accumulator, initialValue);
|
|
370
|
+
}
|
|
371
|
+
groupBy(grouper, mapper) {
|
|
372
|
+
if (!mapper)
|
|
373
|
+
mapper = (value) => value;
|
|
374
|
+
return this.aggregate((ac, v) => (ac[grouper(v)] ? ac[grouper(v)].push(mapper(v)) : ac[grouper(v)] = [mapper(v)], ac), {});
|
|
375
|
+
}
|
|
376
|
+
insert(index, element) {
|
|
377
|
+
if (index < 0 || index > this._entities.length) {
|
|
378
|
+
throw new Error("Index is out of range.");
|
|
379
|
+
}
|
|
380
|
+
this._entities.splice(index, 0, this.createObject(element));
|
|
381
|
+
}
|
|
382
|
+
join(seperator) {
|
|
383
|
+
return this._entities ? this._entities.join(seperator) : null;
|
|
384
|
+
}
|
|
385
|
+
last(predicate) {
|
|
386
|
+
if (this.count()) {
|
|
387
|
+
return predicate ? this.where(predicate).last() : this._entities[this.count() - 1];
|
|
388
|
+
} else {
|
|
389
|
+
throw Error("No result found.");
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
lastOrDefault(predicate) {
|
|
393
|
+
return this.count() ? this.last(predicate) : void 0;
|
|
394
|
+
}
|
|
395
|
+
get length() {
|
|
396
|
+
return this._entities ? this._entities.length : 0;
|
|
397
|
+
}
|
|
398
|
+
max(predicate) {
|
|
399
|
+
if (!predicate)
|
|
400
|
+
return this.aggregate((x, y) => x > y ? x : y);
|
|
401
|
+
else
|
|
402
|
+
return Math.max(...this._entities.map(predicate));
|
|
403
|
+
}
|
|
404
|
+
maxBy(keySelector) {
|
|
405
|
+
const entityGroup = this.groupBy(keySelector);
|
|
406
|
+
let keys = Object.keys(entityGroup);
|
|
407
|
+
let maxKey = Math.max(...keys);
|
|
408
|
+
return entityGroup[maxKey][0];
|
|
409
|
+
}
|
|
410
|
+
min(predicate) {
|
|
411
|
+
if (!predicate)
|
|
412
|
+
return this.aggregate((x, y) => x < y ? x : y);
|
|
413
|
+
else
|
|
414
|
+
return Math.min(...this._entities.map(predicate));
|
|
415
|
+
}
|
|
416
|
+
minBy(keySelector) {
|
|
417
|
+
const entityGroup = this.groupBy(keySelector);
|
|
418
|
+
let keys = Object.keys(entityGroup);
|
|
419
|
+
let minKey = Math.min(...keys);
|
|
420
|
+
return entityGroup[minKey][0];
|
|
421
|
+
}
|
|
422
|
+
orderBy(predicate) {
|
|
423
|
+
return new List(this._entities.sort(this.customSort(predicate, false)));
|
|
424
|
+
}
|
|
425
|
+
orderByDescending(predicate) {
|
|
426
|
+
return new List(this._entities.sort(this.customSort(predicate, true)));
|
|
427
|
+
}
|
|
428
|
+
pop() {
|
|
429
|
+
return this._entities.pop();
|
|
430
|
+
}
|
|
431
|
+
indexOf(element) {
|
|
432
|
+
return this._entities.indexOf(element);
|
|
433
|
+
}
|
|
434
|
+
remove(element) {
|
|
435
|
+
return this._entities.indexOf(element) !== -1 ? (this.removeAt(this._entities.indexOf(element)), true) : false;
|
|
436
|
+
}
|
|
437
|
+
removeAll(predicate) {
|
|
438
|
+
return this.where(this._negate(predicate));
|
|
439
|
+
}
|
|
440
|
+
removeAt(index) {
|
|
441
|
+
this._entities.splice(index, 1);
|
|
442
|
+
}
|
|
443
|
+
reverse() {
|
|
444
|
+
return this._entities ? new List(this._entities.reverse(), this.model) : new List();
|
|
445
|
+
}
|
|
446
|
+
select(mapper) {
|
|
447
|
+
return this._entities.map(mapper);
|
|
448
|
+
}
|
|
449
|
+
single(predicate) {
|
|
450
|
+
if (this.count(predicate) !== 1) {
|
|
451
|
+
throw new Error("Item does not contain one element.");
|
|
452
|
+
} else {
|
|
453
|
+
return this.first(predicate);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
singleOrDefault(predicate) {
|
|
457
|
+
return this.count() ? this.first(predicate) : void 0;
|
|
458
|
+
}
|
|
459
|
+
shift() {
|
|
460
|
+
return this._entities ? this._entities.shift() : void 0;
|
|
461
|
+
}
|
|
462
|
+
skip(amount) {
|
|
463
|
+
return new List(this._entities.slice(Math.max(0, amount)), this.model);
|
|
464
|
+
}
|
|
465
|
+
sum(transform) {
|
|
466
|
+
let result = this.select(transform);
|
|
467
|
+
if (transform) {
|
|
468
|
+
let sum = 0;
|
|
469
|
+
if (result)
|
|
470
|
+
result.forEach((t) => sum += t);
|
|
471
|
+
return sum;
|
|
472
|
+
} else
|
|
473
|
+
return this.aggregate((ac, v) => ac += +v, 0);
|
|
474
|
+
}
|
|
475
|
+
take(amount) {
|
|
476
|
+
return new List(this._entities.slice(0, Math.max(0, amount)), this.model);
|
|
477
|
+
}
|
|
478
|
+
search(value, filterColumns) {
|
|
479
|
+
var filter = [];
|
|
480
|
+
this._entities.forEach((t) => {
|
|
481
|
+
if (this.wildcardSearch(t, value, filterColumns))
|
|
482
|
+
filter.push(t);
|
|
483
|
+
});
|
|
484
|
+
return new List(filter, this.model);
|
|
485
|
+
}
|
|
486
|
+
wildcardSearch(row, prefix, filterColumns) {
|
|
487
|
+
let isMatched = false;
|
|
488
|
+
for (var i = 0, j = filterColumns.length; i < j; i++) {
|
|
489
|
+
var t = filterColumns[i];
|
|
490
|
+
var columnValue = String(row[t]);
|
|
491
|
+
if (this.isExist(columnValue, prefix)) {
|
|
492
|
+
isMatched = true;
|
|
493
|
+
break;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return isMatched;
|
|
497
|
+
}
|
|
498
|
+
isExist(columnValue, prefix) {
|
|
499
|
+
if (columnValue == null) {
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
return String(columnValue).toLowerCase().includes(String(prefix).toLowerCase());
|
|
503
|
+
}
|
|
504
|
+
get toLocaleString() {
|
|
505
|
+
return this._entities ? this._entities.toLocaleString() : null;
|
|
506
|
+
}
|
|
507
|
+
get toString() {
|
|
508
|
+
return this._entities ? this._entities.toString() : null;
|
|
509
|
+
}
|
|
510
|
+
get values() {
|
|
511
|
+
return this._entities;
|
|
512
|
+
}
|
|
513
|
+
_negate(predicate) {
|
|
514
|
+
return function() {
|
|
515
|
+
const _arg = arguments;
|
|
516
|
+
return !predicate.apply(this, _arg);
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
customSort(predicate, orderByDescending) {
|
|
520
|
+
return (a, b) => {
|
|
521
|
+
const first = predicate(a);
|
|
522
|
+
const second = predicate(b);
|
|
523
|
+
if (first > second) {
|
|
524
|
+
return !orderByDescending ? 1 : -1;
|
|
525
|
+
} else if (first < second) {
|
|
526
|
+
return !orderByDescending ? -1 : 1;
|
|
527
|
+
} else {
|
|
528
|
+
return 0;
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
build(values) {
|
|
533
|
+
if (values && values.length > 0) {
|
|
534
|
+
this.addRange(values);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
createObject(object) {
|
|
538
|
+
if (this.model && object.constructor !== this.model)
|
|
539
|
+
return getObject(this.model, [], object, this.props);
|
|
540
|
+
return object;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
export { ALLOW_METHODS, ActionFilter, AuthenticationFilter, AuthorizationFilter, BACK_SLASH_REGEX, BLANK, CONTROLLER, DEFAULT_ACTIONS, DEFAULT_CHILD_PATH, DELETE, ENVIRONMENTS, ExceptionFilter, 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, isConstructor, isEqual, isFunction, isObject, readEnv, readEnvKey, typeContainer };
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nattyjs/common",
|
|
3
|
+
"version": "0.0.1-beta.0",
|
|
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
|
+
"keywords": [],
|
|
6
|
+
"author": "ajayojha <ojhaajay@outlook.com>",
|
|
7
|
+
"license": "ISC",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"main": "./dist/index.cjs",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "unbuild"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/node": "20.3.1",
|
|
19
|
+
"@nattyjs/types": "0.0.1-beta.0",
|
|
20
|
+
"unbuild": "1.2.1",
|
|
21
|
+
"dotenv-expand": "10.0.0"
|
|
22
|
+
}
|
|
23
|
+
}
|