nestia 3.0.17 → 3.1.1-dev.20221015
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 +10 -0
- package/lib/executable/internal/NestiaStarter.d.ts +3 -0
- package/lib/executable/internal/NestiaStarter.js +61 -0
- package/lib/executable/internal/NestiaStarter.js.map +1 -0
- package/lib/executable/nestia.js +5 -2
- package/lib/executable/nestia.js.map +1 -1
- package/package.json +1 -1
- package/template/.github/workflows/build.yml +18 -0
- package/template/.vscode/launch.json +19 -0
- package/template/.vscode/settings.json +10 -0
- package/template/LICENSE +21 -0
- package/template/README.md +131 -0
- package/template/nestia.config.ts +12 -0
- package/template/package.json +62 -0
- package/template/packages/api/LICENSE +21 -0
- package/template/packages/api/README.md +66 -0
- package/template/packages/api/package.json +21 -0
- package/template/src/Backend.ts +65 -0
- package/template/src/Configuration.ts +11 -0
- package/template/src/api/HttpError.ts +1 -0
- package/template/src/api/IConnection.ts +1 -0
- package/template/src/api/Primitive.ts +1 -0
- package/template/src/api/__internal/AesPkcs5.ts +1 -0
- package/template/src/api/__internal/Fetcher.ts +1 -0
- package/template/src/api/functional/bbs/articles/index.ts +166 -0
- package/template/src/api/functional/bbs/index.ts +7 -0
- package/template/src/api/functional/index.ts +7 -0
- package/template/src/api/index.ts +4 -0
- package/template/src/api/module.ts +5 -0
- package/template/src/api/structures/bbs/IBbsArticle.ts +142 -0
- package/template/src/api/structures/common/IAttachmentFile.ts +5 -0
- package/template/src/api/structures/common/IPage.ts +75 -0
- package/template/src/controllers/BbsArticlesController.ts +46 -0
- package/template/src/providers/bbs/BbsArticleProvider.ts +217 -0
- package/template/src/test/features/api/bbs/test_api_bbs_article_at.ts +52 -0
- package/template/src/test/features/api/bbs/test_api_bbs_article_index_search.ts +82 -0
- package/template/src/test/features/api/bbs/test_api_bbs_article_index_sort.ts +49 -0
- package/template/src/test/features/api/bbs/test_api_bbs_article_store.ts +44 -0
- package/template/src/test/features/api/bbs/test_api_bbs_article_update.ts +66 -0
- package/template/src/test/index.ts +45 -0
- package/template/src/test/internal/DynamicImportIterator.ts +119 -0
- package/template/src/test/internal/GaffComparator.ts +48 -0
- package/template/src/test/internal/IPointer.ts +3 -0
- package/template/src/test/internal/RandomGenerator.ts +72 -0
- package/template/src/test/internal/StopWatch.ts +16 -0
- package/template/src/test/internal/exception_must_be_thrown.ts +11 -0
- package/template/src/test/internal/validate_index.ts +29 -0
- package/template/src/test/internal/validate_index_sort.ts +39 -0
- package/template/src/utils/ArrayUtil.ts +86 -0
- package/template/src/utils/MapUtil.ts +14 -0
- package/template/tsconfig.api.json +15 -0
- package/template/tsconfig.json +118 -0
- package/tsconfig.json +82 -0
package/README.md
CHANGED
|
@@ -75,6 +75,16 @@ export async function trace_sale_question_and_comment
|
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
## Setup
|
|
78
|
+
### Starter Kit
|
|
79
|
+
```bash
|
|
80
|
+
npx nestia start <directory>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Just run the upper command with target directory. Then, boilerplate project would be copied to the target directory.
|
|
84
|
+
|
|
85
|
+
After the composition being completed, read the README content of the boilderplate project and start developing your backend server.
|
|
86
|
+
|
|
87
|
+
### Manual Installation
|
|
78
88
|
Just like any other package, you've got to install it before you can use it.
|
|
79
89
|
|
|
80
90
|
For reference, `ttypescript` is not mis-writing. Don't forget to install it.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.NestiaStarter = void 0;
|
|
16
|
+
const child_process_1 = __importDefault(require("child_process"));
|
|
17
|
+
const fs_1 = __importDefault(require("fs"));
|
|
18
|
+
var NestiaStarter;
|
|
19
|
+
(function (NestiaStarter) {
|
|
20
|
+
function start(dest) {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
// VALIDATION
|
|
23
|
+
if (dest === undefined)
|
|
24
|
+
throw new Error(message("is not specified."));
|
|
25
|
+
else if (fs_1.default.existsSync(dest) === true)
|
|
26
|
+
throw new Error(message("already exists"));
|
|
27
|
+
// COPY PROJECTS
|
|
28
|
+
console.log("Copying files...");
|
|
29
|
+
yield copy(__dirname + "/../../../template", dest);
|
|
30
|
+
process.chdir(dest);
|
|
31
|
+
// INSTALL DEPENDENCIES
|
|
32
|
+
console.log("Installing dependencies...");
|
|
33
|
+
child_process_1.default.execSync("npm install", { stdio: "inherit" });
|
|
34
|
+
// BUILD TYPESCRIPT
|
|
35
|
+
console.log("Building project...");
|
|
36
|
+
child_process_1.default.execSync("npm run build", { stdio: "inherit" });
|
|
37
|
+
// DO TEST
|
|
38
|
+
console.log("Running test program...");
|
|
39
|
+
child_process_1.default.execSync("npm run test", { stdio: "inherit" });
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
NestiaStarter.start = start;
|
|
43
|
+
function copy(src, dest) {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
const stats = yield fs_1.default.promises.lstat(src);
|
|
46
|
+
if (stats.isDirectory()) {
|
|
47
|
+
if (src === __dirname + "/../../../template/.git")
|
|
48
|
+
return;
|
|
49
|
+
yield fs_1.default.promises.mkdir(dest);
|
|
50
|
+
for (const file of yield fs_1.default.promises.readdir(src))
|
|
51
|
+
yield copy(src + "/" + file, dest + "/" + file);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const content = yield fs_1.default.promises.readFile(src, "utf8");
|
|
55
|
+
yield fs_1.default.promises.writeFile(dest, content, "utf8");
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
})(NestiaStarter = exports.NestiaStarter || (exports.NestiaStarter = {}));
|
|
60
|
+
const message = (content) => `Error on nestia.start(): target directory ${content}.`;
|
|
61
|
+
//# sourceMappingURL=NestiaStarter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NestiaStarter.js","sourceRoot":"","sources":["../../../src/executable/internal/NestiaStarter.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,kEAA+B;AAC/B,4CAAoB;AAEpB,IAAiB,aAAa,CAsC7B;AAtCD,WAAiB,aAAa;IAC1B,SAAsB,KAAK,CAAC,IAAwB;;YAChD,aAAa;YACb,IAAI,IAAI,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC;iBACjE,IAAI,YAAE,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI;gBACjC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;YAE/C,gBAAgB;YAChB,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;YAChC,MAAM,IAAI,CAAC,SAAS,GAAG,oBAAoB,EAAE,IAAI,CAAC,CAAC;YACnD,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAEpB,uBAAuB;YACvB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;YAC1C,uBAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YAEjD,mBAAmB;YACnB,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;YACnC,uBAAE,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YAEnD,UAAU;YACV,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YACvC,uBAAE,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACtD,CAAC;KAAA;IAtBqB,mBAAK,QAsB1B,CAAA;IAED,SAAe,IAAI,CAAC,GAAW,EAAE,IAAY;;YACzC,MAAM,KAAK,GAAa,MAAM,YAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACrD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE;gBACrB,IAAI,GAAG,KAAK,SAAS,GAAG,yBAAyB;oBAAE,OAAO;gBAE1D,MAAM,YAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC9B,KAAK,MAAM,IAAI,IAAI,MAAM,YAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC;oBAC7C,MAAM,IAAI,CAAC,GAAG,GAAG,GAAG,GAAG,IAAI,EAAE,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;aACvD;iBAAM;gBACH,MAAM,OAAO,GAAW,MAAM,YAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;gBAChE,MAAM,YAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;aACtD;QACL,CAAC;KAAA;AACL,CAAC,EAtCgB,aAAa,GAAb,qBAAa,KAAb,qBAAa,QAsC7B;AAED,MAAM,OAAO,GAAG,CAAC,OAAe,EAAE,EAAE,CAChC,6CAA6C,OAAO,GAAG,CAAC"}
|
package/lib/executable/nestia.js
CHANGED
|
@@ -39,6 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
const child_process_1 = __importDefault(require("child_process"));
|
|
40
40
|
const fs_1 = __importDefault(require("fs"));
|
|
41
41
|
const process_1 = __importDefault(require("process"));
|
|
42
|
+
const NestiaStarter_1 = require("./internal/NestiaStarter");
|
|
42
43
|
function dependencies() {
|
|
43
44
|
// INSTALL DEPENDENCIES
|
|
44
45
|
for (const lib of ["nestia-fetcher", "typescript-json"]) {
|
|
@@ -64,7 +65,9 @@ function main() {
|
|
|
64
65
|
return __awaiter(this, void 0, void 0, function* () {
|
|
65
66
|
const type = process_1.default.argv[2];
|
|
66
67
|
const argv = process_1.default.argv.slice(3);
|
|
67
|
-
if (type === "
|
|
68
|
+
if (type === "start")
|
|
69
|
+
yield NestiaStarter_1.NestiaStarter.start(argv[0]);
|
|
70
|
+
else if (type === "install")
|
|
68
71
|
dependencies();
|
|
69
72
|
else if (type === "init")
|
|
70
73
|
yield initialize();
|
|
@@ -73,7 +76,7 @@ function main() {
|
|
|
73
76
|
else if (type === "swagger")
|
|
74
77
|
yield execute((c) => c.swagger(argv));
|
|
75
78
|
else
|
|
76
|
-
throw new Error(`nestia supports only
|
|
79
|
+
throw new Error(`nestia supports only five commands; (start, install, init, sdk and swagger), however you've typed the "${process_1.default.argv[2]}"`);
|
|
77
80
|
});
|
|
78
81
|
}
|
|
79
82
|
main().catch((exp) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nestia.js","sourceRoot":"","sources":["../../src/executable/nestia.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,kEAA+B;AAC/B,4CAAoB;AACpB,sDAA8B;
|
|
1
|
+
{"version":3,"file":"nestia.js","sourceRoot":"","sources":["../../src/executable/nestia.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,kEAA+B;AAC/B,4CAAoB;AACpB,sDAA8B;AAG9B,4DAAyD;AAEzD,SAAS,YAAY;IACjB,uBAAuB;IACvB,KAAK,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,EAAE;QACrD,MAAM,OAAO,GAAW,eAAe,GAAG,EAAE,CAAC;QAC7C,uBAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;KAC9C;AACL,CAAC;AAED,SAAe,UAAU;;QACrB,IAAI,YAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,KAAK,IAAI;YAC1C,MAAM,IAAI,KAAK,CACX,oFAAoF,CACvF,CAAC;QAEN,MAAM,OAAO,GAAW,MAAM,YAAE,CAAC,QAAQ,CAAC,QAAQ,CAC9C,GAAG,SAAS,uCAAuC,EACnD,MAAM,CACT,CAAC;QACF,MAAM,YAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,kBAAkB,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACrE,CAAC;CAAA;AAED,SAAe,OAAO,CAClB,OAA2D;;QAE3D,MAAM,MAAM,GAAG,wDAAa,0BAA0B,GAAC,CAAC;QACxD,MAAM,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACxC,CAAC;CAAA;AAED,SAAe,IAAI;;QACf,MAAM,IAAI,GAAuB,iBAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,IAAI,GAAa,iBAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAE7C,IAAI,IAAI,KAAK,OAAO;YAAE,MAAM,6BAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;aACpD,IAAI,IAAI,KAAK,SAAS;YAAE,YAAY,EAAE,CAAC;aACvC,IAAI,IAAI,KAAK,MAAM;YAAE,MAAM,UAAU,EAAE,CAAC;aACxC,IAAI,IAAI,KAAK,KAAK;YAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;aACtD,IAAI,IAAI,KAAK,SAAS;YAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;;YAE/D,MAAM,IAAI,KAAK,CACX,0GAA0G,iBAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAC/H,CAAC;IACV,CAAC;CAAA;AACD,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACjB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACzB,iBAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACrB,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: build
|
|
2
|
+
on: [push, pull_request]
|
|
3
|
+
|
|
4
|
+
jobs:
|
|
5
|
+
Ubuntu:
|
|
6
|
+
runs-on: ubuntu-latest
|
|
7
|
+
steps:
|
|
8
|
+
- uses: actions/checkout@v3
|
|
9
|
+
- uses: actions/setup-node@v3
|
|
10
|
+
|
|
11
|
+
- name: Install Backend-Server
|
|
12
|
+
run: npm install
|
|
13
|
+
|
|
14
|
+
- name: Compile Backend-Server
|
|
15
|
+
run: npm run build
|
|
16
|
+
|
|
17
|
+
- name: Test Backend-Server
|
|
18
|
+
run: npm run test
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Use IntelliSense to learn about possible Node.js debug attributes.
|
|
3
|
+
// Hover to view descriptions of existing attributes.
|
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
{
|
|
8
|
+
"type": "node",
|
|
9
|
+
"request": "launch",
|
|
10
|
+
"name": "JavaScript Test using SourceMap",
|
|
11
|
+
"program": "${workspaceRoot}/bin/test/index.js",
|
|
12
|
+
"cwd": "${workspaceRoot}",
|
|
13
|
+
|
|
14
|
+
// TypeScript
|
|
15
|
+
"sourceMaps": true,
|
|
16
|
+
"outFiles": ["${workspaceRot}/**.js"]
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
package/template/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Jeongho Nam
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Nestia Template
|
|
2
|
+
## Outline
|
|
3
|
+
[](https://github.com/samchon/nestia-template/actions?query=workflow%3Abuild)
|
|
4
|
+
|
|
5
|
+
A template repository for backend projects using [nestia](https://github.com/samchon/nestia).
|
|
6
|
+
|
|
7
|
+
You can create a new project from this boilerplate by running below command:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx nestia start <directory>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
For reference, this is a minimal boilerplate project concentrating only on [nestia](https://github.com/samchon/nestia) SDK generation. If you wanna much detailed boilerplate project even configured DB and Non-distruptive update system, visit [samchon/backend](https://github.com/samchon/backend) and create a new repository from that.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## Directories and Files
|
|
19
|
+
This template project has categorized directories like below.
|
|
20
|
+
|
|
21
|
+
As you can see from the below, all of the TypeScript source files are placed into the [src](src/) directory. When you build the TypeScript source files, compiled files would be placed into the `bin` directory following the [tsconfig.json](tsconfig.json) configuration. Otherwise you build client [SDK](#32-sdk) library for npm publishing and their compiled files would be placed into the [packages](packages) directory.
|
|
22
|
+
|
|
23
|
+
- [packages/api/](packages/api): SDK module built by `npm run build:api`
|
|
24
|
+
- [src/](src): TypeScript source directory
|
|
25
|
+
- [src/api/](src/api/): Client SDK that would be published to the `@ORGANIZATION/PROJECT-api`
|
|
26
|
+
- [**src/api/functional/**](src/api/functional/): API functions generated by the [`nestia`](https://github.com/samchon/nestia)
|
|
27
|
+
- [**src/api/structures/**](src/api/structures/): DTO structures
|
|
28
|
+
- [src/controllers/](src/controllers/): Controller classes of the Main Program
|
|
29
|
+
- [**src/test/**](src/test/): Test Automation Program
|
|
30
|
+
- [nestia.config.ts](nestia.config.ts): Configuration file of [`nestia`](https://github.com/samchon/nestia)
|
|
31
|
+
- [package.json](package.json): NPM configuration
|
|
32
|
+
- [tsconfig.json](tsconfig.json): TypeScript configuration for the main program
|
|
33
|
+
- [tsconfig.api.json](tsconfig.api.json): TypeScript configuration for the SDK generation
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## NPM Run Commands
|
|
39
|
+
List of the run commands defined in the [package.json](package.json) are like below:
|
|
40
|
+
|
|
41
|
+
- `build`: Compile the source code
|
|
42
|
+
- `build:api`: Build client SDK libray for the client developers
|
|
43
|
+
- `build:sdk`: Build SDK into main program only
|
|
44
|
+
- `build:swagger`: Build Swagger Documents
|
|
45
|
+
- `dev`: Incremental build for development
|
|
46
|
+
- `eslint` & `eslint:fix` & `prettier`: Prettier and ESLint execution
|
|
47
|
+
- `test`: Run test automation program
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
## Specialization
|
|
53
|
+
Transform this template project to be yours.
|
|
54
|
+
|
|
55
|
+
When you've created a new backend project through this template project, you can specialize it to be suitable for you by changing some words. Replace below words through IDE specific function like `Edit > Replace in Files` (*Ctrl + Shift + H*), who've been supported by the VSCode.
|
|
56
|
+
|
|
57
|
+
| Before | After
|
|
58
|
+
|-----------------|----------------------------------------
|
|
59
|
+
| ORGANIZATION | Your account or corporation name
|
|
60
|
+
| PROJECT | Your own project name
|
|
61
|
+
| AUTHOR | Author name
|
|
62
|
+
| https://github.com/samchon/nestia-template | Your repository URL
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
## Test Driven Development
|
|
68
|
+
With [nestia](https://github.com/samchon/nestia) helps to accomplish TDD (Test Driven Development).
|
|
69
|
+
|
|
70
|
+
Just define DTOs and API controllers' methods (only declarations) first. After the definitions, and build SDK (Software Development Kit) through [nestia](https://github.com/samchon/nestia) (`npm run build:sdk`). After buildling those SDK, develop test automation program using the SDK, following use-case scenarios in the framework of client side.
|
|
71
|
+
|
|
72
|
+
During the test automation program development, you can find that which API is mis-designed or which requirement analysis is not exact. Development of the main program must be the last step after such validation process during TDD.
|
|
73
|
+
|
|
74
|
+
> Visit the [samchon/backend](https://github.com/samchon/backend), then you may find much detailed story about this TDD.
|
|
75
|
+
>
|
|
76
|
+
> 1. Definitions
|
|
77
|
+
> 2. SDK
|
|
78
|
+
> 3. Test Automation Program
|
|
79
|
+
> 4. Main Program
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import TSON from "typescript-json";
|
|
83
|
+
|
|
84
|
+
import api from "@ORGANIZATION/PROJECT-api/lib/index";
|
|
85
|
+
import { IBbsArticle } from "@ORGANIZATION/PROJECT-api/lib/structures/bbs/IBbsArticle";
|
|
86
|
+
|
|
87
|
+
import { ArrayUtil } from "../../../../utils/ArrayUtil";
|
|
88
|
+
import { GaffComparator } from "../../../internal/GaffComparator";
|
|
89
|
+
import { RandomGenerator } from "../../../internal/RandomGenerator";
|
|
90
|
+
import { validate_index_sort } from "../../../internal/validate_index_sort";
|
|
91
|
+
|
|
92
|
+
export async function test_api_bbs_article_index_sort(
|
|
93
|
+
connection: api.IConnection,
|
|
94
|
+
): Promise<void> {
|
|
95
|
+
// GENERATE 100 ARTICLES
|
|
96
|
+
const section: string = "general";
|
|
97
|
+
const articles: IBbsArticle[] = await ArrayUtil.asyncRepeat(100, () =>
|
|
98
|
+
api.functional.bbs.articles.store(connection, section, {
|
|
99
|
+
writer: RandomGenerator.name(),
|
|
100
|
+
title: RandomGenerator.paragraph(),
|
|
101
|
+
body: RandomGenerator.content(),
|
|
102
|
+
format: "txt",
|
|
103
|
+
files: [],
|
|
104
|
+
password: RandomGenerator.alphabets(8),
|
|
105
|
+
}),
|
|
106
|
+
);
|
|
107
|
+
TSON.assertEquals(articles);
|
|
108
|
+
|
|
109
|
+
// PREPARE VALIDATOR
|
|
110
|
+
const validator = validate_index_sort("BbsArticleProvider.idex()")(
|
|
111
|
+
(input: IBbsArticle.IRequest) =>
|
|
112
|
+
api.functional.bbs.articles.index(connection, section, input),
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
// DO VALIDATE
|
|
116
|
+
const components = [
|
|
117
|
+
validator("created_at")(GaffComparator.dates((x) => x.created_at)),
|
|
118
|
+
validator("updated_at")(GaffComparator.dates((x) => x.updated_at)),
|
|
119
|
+
validator("title")(GaffComparator.strings((x) => x.title)),
|
|
120
|
+
validator("writer")(GaffComparator.strings((x) => x.writer)),
|
|
121
|
+
validator(
|
|
122
|
+
"writer",
|
|
123
|
+
"title",
|
|
124
|
+
)(GaffComparator.strings((x) => [x.writer, x.title])),
|
|
125
|
+
];
|
|
126
|
+
for (const comp of components) {
|
|
127
|
+
await comp("+");
|
|
128
|
+
await comp("-");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// nestia configuration file
|
|
2
|
+
import type nestia from "nestia";
|
|
3
|
+
|
|
4
|
+
const NESTIA_CONFIG: nestia.IConfiguration = {
|
|
5
|
+
input: "src/controllers",
|
|
6
|
+
output: "src/api",
|
|
7
|
+
swagger: {
|
|
8
|
+
output: "dist/swagger.json",
|
|
9
|
+
},
|
|
10
|
+
primitive: false,
|
|
11
|
+
};
|
|
12
|
+
export default NESTIA_CONFIG;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ORGANIZATION/PROJECT",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Starter kit of Nestia",
|
|
5
|
+
"main": "bin/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "rimraf bin && ttsc",
|
|
8
|
+
"build:api": "rimraf packages/api/lib && npm run build:sdk && ttsc -p tsconfig.api.json",
|
|
9
|
+
"build:sdk": "npx nestia sdk",
|
|
10
|
+
"build:swagger": "npx nestia swagger",
|
|
11
|
+
"eslint": "eslint src",
|
|
12
|
+
"eslint:fix": "eslint src --fix",
|
|
13
|
+
"dev": "rimraf bin && ttsc --watch",
|
|
14
|
+
"prettier": "prettier src --write",
|
|
15
|
+
"test": "node bin/test"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/samchon/nestia-template"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"nestia",
|
|
23
|
+
"template",
|
|
24
|
+
"boilerplate"
|
|
25
|
+
],
|
|
26
|
+
"author": "AUTHOR",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/samchon/nestia-template/issues"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/samchon/nestia-template#readme",
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@trivago/prettier-plugin-sort-imports": "^3.3.1",
|
|
34
|
+
"@types/cli": "^0.11.21",
|
|
35
|
+
"@types/express": "^4.17.14",
|
|
36
|
+
"@types/node": "^18.11.0",
|
|
37
|
+
"@types/uuid": "^8.3.4",
|
|
38
|
+
"@typescript-eslint/eslint-plugin": "^5.40.0",
|
|
39
|
+
"@typescript-eslint/parser": "^5.40.0",
|
|
40
|
+
"chalk": "^4.1.0",
|
|
41
|
+
"cli": "^1.0.1",
|
|
42
|
+
"nestia": "^3.1.0",
|
|
43
|
+
"prettier": "^2.7.1",
|
|
44
|
+
"rimraf": "^3.0.2",
|
|
45
|
+
"source-map-support": "^0.5.21",
|
|
46
|
+
"ts-node": "^10.9.1",
|
|
47
|
+
"ttypescript": "^1.5.13",
|
|
48
|
+
"typescript": "^4.8.4",
|
|
49
|
+
"typescript-transform-paths": "^3.3.1"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@nestjs/common": "^9.1.4",
|
|
53
|
+
"@nestjs/core": "^9.1.4",
|
|
54
|
+
"@nestjs/platform-express": "^9.1.4",
|
|
55
|
+
"nestia-helper": "^3.1.6",
|
|
56
|
+
"raw-body": "^2.5.1",
|
|
57
|
+
"rxjs": "^7.5.7",
|
|
58
|
+
"tstl": "^2.5.12",
|
|
59
|
+
"typescript-json": "^3.3.10",
|
|
60
|
+
"uuid": "^9.0.0"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 ORGANIZATION
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# SDK for Client Developers
|
|
2
|
+
## Outline
|
|
3
|
+
[`@ORGANIZATION/PROJECT`](https://github.com/samchon/nestia-template) provides SDK (Software Development Kit) for convenience.
|
|
4
|
+
|
|
5
|
+
For the client developers who are connecting to this backend server, [`@ORGANIZATION/PROJECT`](https://github.com/samchon/nestia-template) provides not API documents like the Swagger, but provides the API interaction library, one of the typical SDK (Software Development Kit) for the convenience.
|
|
6
|
+
|
|
7
|
+
With the SDK, client developers never need to re-define the duplicated API interfaces. Just utilize the provided interfaces and asynchronous functions defined in the SDK. It would be much convenient than any other Rest API solutions.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install --save @ORGANIZATION/PROJECT-api
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
Import the `@ORGANIZATION/PROJECT-api` and enjoy the auto-completion.
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import api from "@ORGINIZATION/PROJECT-api";
|
|
21
|
+
|
|
22
|
+
import { IBbsArticle } from "@ORGANIZATION/PROJECT-api/lib/structures/bbs/IBbsArticle";
|
|
23
|
+
|
|
24
|
+
async function main(): Promise<void>
|
|
25
|
+
{
|
|
26
|
+
//----
|
|
27
|
+
// PREPARATIONS
|
|
28
|
+
//----
|
|
29
|
+
// CONNECTION INFO
|
|
30
|
+
const connection: api.IConnection = {
|
|
31
|
+
host: "http://127.0.0.1:37001",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const article: IBbsArticle = await api.functional.bbs.articles.store(
|
|
35
|
+
connection,
|
|
36
|
+
"general",
|
|
37
|
+
{
|
|
38
|
+
writer: "Robot",
|
|
39
|
+
title: "Hello, world!",
|
|
40
|
+
body: "Hello, I'm test automation robot",
|
|
41
|
+
format: "txt",
|
|
42
|
+
files: [
|
|
43
|
+
{
|
|
44
|
+
name: "logo",
|
|
45
|
+
extension: "png",
|
|
46
|
+
url: "https://somewhere.com/logo.png",
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
password: "1234",
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
TSON.assertEquals(stored);
|
|
53
|
+
|
|
54
|
+
const page: IPage<IBbsArticle> = await api.functional.bbs.articles.index(
|
|
55
|
+
connection,
|
|
56
|
+
"general",
|
|
57
|
+
{
|
|
58
|
+
limit: 100,
|
|
59
|
+
search: {
|
|
60
|
+
writer: "Robot"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
await TSON.assertEquals(page);
|
|
65
|
+
}
|
|
66
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ORGANIZATION/PROJECT-api",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "API for PROJECT",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"typings": "lib/index.d.ts",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/samchon/nestia-template"
|
|
10
|
+
},
|
|
11
|
+
"author": "AUTHOR",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/samchon/nestia-template/issues"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/samchon/nestia-template#readme",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"nestia-fetcher": "^2.0.3",
|
|
19
|
+
"typescript-json": "^3.3.10"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { INestApplication } from "@nestjs/common";
|
|
2
|
+
import { NestFactory } from "@nestjs/core";
|
|
3
|
+
import express from "express";
|
|
4
|
+
import helper from "nestia-helper";
|
|
5
|
+
|
|
6
|
+
import { Configuration } from "./Configuration";
|
|
7
|
+
|
|
8
|
+
export class Backend {
|
|
9
|
+
private application_?: INestApplication;
|
|
10
|
+
private is_closing_: boolean = false;
|
|
11
|
+
|
|
12
|
+
public async open(): Promise<void> {
|
|
13
|
+
//----
|
|
14
|
+
// OPEN THE BACKEND SERVER
|
|
15
|
+
//----
|
|
16
|
+
// MOUNT CONTROLLERS
|
|
17
|
+
this.application_ = await NestFactory.create(
|
|
18
|
+
await helper.EncryptedModule.dynamic(
|
|
19
|
+
__dirname + "/controllers",
|
|
20
|
+
await Configuration.ENCRYPTION_PASSWORD(),
|
|
21
|
+
),
|
|
22
|
+
{ logger: false },
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
// CONFIGURATIONS
|
|
26
|
+
this.is_closing_ = false;
|
|
27
|
+
this.application_.enableCors();
|
|
28
|
+
this.application_.use(this.middleware.bind(this));
|
|
29
|
+
|
|
30
|
+
// DO OPEN
|
|
31
|
+
await this.application_.listen(await Configuration.API_PORT());
|
|
32
|
+
|
|
33
|
+
//----
|
|
34
|
+
// POST-PROCESSES
|
|
35
|
+
//----
|
|
36
|
+
// INFORM TO THE PM2
|
|
37
|
+
if (process.send) process.send("ready");
|
|
38
|
+
|
|
39
|
+
// WHEN KILL COMMAND COMES
|
|
40
|
+
process.on("SIGINT", async () => {
|
|
41
|
+
this.is_closing_ = true;
|
|
42
|
+
await this.close();
|
|
43
|
+
process.exit(0);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public async close(): Promise<void> {
|
|
48
|
+
if (this.application_ === undefined) return;
|
|
49
|
+
|
|
50
|
+
// DO CLOSE
|
|
51
|
+
await this.application_.close();
|
|
52
|
+
delete this.application_;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private middleware(
|
|
56
|
+
_request: express.Request,
|
|
57
|
+
response: express.Response,
|
|
58
|
+
next: FunctionLike,
|
|
59
|
+
): void {
|
|
60
|
+
if (this.is_closing_ === true) response.set("Connection", "close");
|
|
61
|
+
next();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
type FunctionLike = (...args: any[]) => any;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IEncryptionPassword } from "nestia-fetcher";
|
|
2
|
+
|
|
3
|
+
export namespace Configuration {
|
|
4
|
+
export const API_PORT = async () => 37001;
|
|
5
|
+
export const ENCRYPTION_PASSWORD = async (): Promise<
|
|
6
|
+
Readonly<IEncryptionPassword>
|
|
7
|
+
> => ({
|
|
8
|
+
key: "pJXhbHlYfzkC1CBK8R67faaBgJWB9Myu",
|
|
9
|
+
iv: "IXJBt4MflFxvxKkn",
|
|
10
|
+
});
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { HttpError } from "nestia-fetcher";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { IConnection } from "nestia-fetcher";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Primitive } from "nestia-fetcher";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AesPkcs5 } from "nestia-fetcher";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Fetcher } from "nestia-fetcher";
|