Skip to content

Commit 0556994

Browse files
committed
Test program execution to merge with master
2 parents a383a42 + aeca37a commit 0556994

File tree

171 files changed

+9800
-858
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

171 files changed

+9800
-858
lines changed

.github/dependabot.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ updates:
2424
- dependency-name: ts-node
2525
- dependency-name: ts-patch
2626
- dependency-name: typescript
27+
- dependency-name: typescript-transform-paths
2728
groups:
2829
NestJS:
2930
patterns:
@@ -38,4 +39,5 @@ updates:
3839
patterns:
3940
- "ts-node"
4041
- "ts-patch"
41-
- "typescript"
42+
- "typescript"
43+
- "typescript-transform-paths"

packages/cli/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nestia",
3-
"version": "6.2.0",
3+
"version": "6.3.0",
44
"description": "Nestia CLI tool",
55
"main": "bin/index.js",
66
"bin": {
@@ -42,7 +42,7 @@
4242
"@types/inquirer": "^9.0.3",
4343
"@types/node": "^18.11.16",
4444
"rimraf": "^3.0.2",
45-
"typescript": "^5.6.2"
45+
"typescript": "~5.6.3"
4646
},
4747
"files": [
4848
"bin",

packages/core/src/decorators/PlainBody.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type express from "express";
77
import type { FastifyRequest } from "fastify";
88

99
import { get_text_body } from "./internal/get_text_body";
10+
import { is_request_body_undefined } from "./internal/is_request_body_undefined";
1011
import { validate_request_body } from "./internal/validate_request_body";
1112

1213
/**
@@ -51,7 +52,12 @@ export function PlainBody(
5152
const request: express.Request | FastifyRequest = context
5253
.switchToHttp()
5354
.getRequest();
54-
if (!isTextPlain(request.headers["content-type"]))
55+
if (
56+
is_request_body_undefined(request) &&
57+
(checker ?? (() => null))(undefined as any) === null
58+
)
59+
return undefined;
60+
else if (!isTextPlain(request.headers["content-type"]))
5561
throw new BadRequestException(`Request body type is not "text/plain".`);
5662
const value: string = await get_text_body(request);
5763
if (checker) {

packages/core/src/decorators/TypedBody.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type express from "express";
77
import type { FastifyRequest } from "fastify";
88

99
import { IRequestBodyValidator } from "../options/IRequestBodyValidator";
10+
import { is_request_body_undefined } from "./internal/is_request_body_undefined";
1011
import { validate_request_body } from "./internal/validate_request_body";
1112

1213
/**
@@ -34,7 +35,9 @@ export function TypedBody<T>(
3435
const request: express.Request | FastifyRequest = context
3536
.switchToHttp()
3637
.getRequest();
37-
if (isApplicationJson(request.headers["content-type"]) === false)
38+
if (is_request_body_undefined(request) && checker(undefined as T) === null)
39+
return undefined;
40+
else if (isApplicationJson(request.headers["content-type"]) === false)
3841
throw new BadRequestException(
3942
`Request body type is not "application/json".`,
4043
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type express from "express";
2+
import type { FastifyRequest } from "fastify";
3+
4+
/**
5+
* @internal
6+
*/
7+
export const is_request_body_undefined = (
8+
request: express.Request | FastifyRequest,
9+
): boolean =>
10+
request.headers["content-type"] === undefined &&
11+
(request.body === undefined ||
12+
(typeof request.body === "object" &&
13+
request.body !== null &&
14+
Object.keys(request.body).length === 0));

packages/core/src/programmers/PlainBodyProgrammer.ts

-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ const validate = (metadata: Metadata): string[] => {
6363
.reduce((a, b) => a + b, 0);
6464
if (expected === 0 || expected !== metadata.size())
6565
insert(`only string type is allowed`);
66-
if (metadata.isRequired() === false) insert(`do not allow undefindable type`);
6766
if (metadata.nullable === true) insert(`do not allow nullable type`);
6867
else if (metadata.any === true) insert(`do not allow any type`);
6968

packages/core/tsconfig.test.json

+5-83
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,7 @@
11
{
2+
"extends": "./tsconfig.json",
23
"compilerOptions": {
3-
/* Visit https://aka.ms/tsconfig.json to read more about this file */
4-
5-
/* Basic Options */
6-
// "incremental": true, /* Enable incremental compilation */
7-
"target": "es2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
8-
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
9-
"lib": [
10-
"DOM",
11-
"ES2015"
12-
], /* Specify library files to be included in the compilation. */
13-
// "allowJs": true, /* Allow javascript files to be compiled. */
14-
// "checkJs": true, /* Report errors in .js files. */
15-
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
16-
"declaration": true, /* Generates corresponding '.d.ts' file. */
17-
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
18-
"sourceMap": true, /* Generates corresponding '.map' file. */
19-
// "outFile": "./", /* Concatenate and emit output to single file. */
20-
"outDir": "../../test/node_modules/@nestia/core/lib", /* Redirect output structure to the directory. */
21-
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
22-
// "composite": true, /* Enable project compilation */
23-
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
24-
// "removeComments": true, /* Do not emit comments to output. */
25-
// "noEmit": true, /* Do not emit outputs. */
26-
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
27-
"downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
28-
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
29-
30-
/* Strict Type-Checking Options */
31-
"strict": true, /* Enable all strict type-checking options. */
32-
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
33-
// "strictNullChecks": true, /* Enable strict null checks. */
34-
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
35-
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
36-
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
37-
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
38-
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
39-
40-
/* Additional Checks */
41-
"noUnusedLocals": true, /* Report errors on unused locals. */
42-
"noUnusedParameters": true, /* Report errors on unused parameters. */
43-
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
44-
"noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
45-
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
46-
47-
/* Module Resolution Options */
48-
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
49-
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
50-
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
51-
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
52-
// "typeRoots": [], /* List of folders to include type definitions from. */
53-
"types": [
54-
"node",
55-
"reflect-metadata"
56-
], /* Type declaration files to be included in compilation. */
57-
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
58-
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
59-
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
60-
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
61-
62-
/* Source Map Options */
63-
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
64-
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
65-
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
66-
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
67-
68-
/* Experimental Options */
69-
"experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
70-
"emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
71-
"stripInternal": true,
72-
73-
/* Advanced Options */
74-
"skipLibCheck": true, /* Skip type checking of declaration files. */
75-
"forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
76-
"plugins": [
77-
{
78-
"transform": "typia/lib/transform",
79-
"functional": true,
80-
}
81-
],
82-
"newLine": "LF",
83-
},
84-
"include": ["src"]
85-
}
4+
"target": "ES2015",
5+
"outDir": "../../test/node_modules/@nestia/core/lib"
6+
}
7+
}

packages/editor/package.json

+13-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
{
22
"name": "@nestia/editor",
3-
"version": "0.6.2",
3+
"version": "0.8.0",
44
"typings": "lib/index.d.ts",
55
"main": "lib/index.js",
66
"module": "lib/index.mjs",
77
"scripts": {
8-
"build:lib": "tsc --project tsconfig.lib.json && rollup -c",
9-
"build:static": "tsc -b && vite build",
8+
"build": "npm run build:static && npm run build:lib",
9+
"build:static": "rimraf dist && tsc -b && vite build",
10+
"build:lib": "rimraf lib && tsc --project tsconfig.lib.json && rollup -c",
1011
"dev": "vite",
1112
"lint": "eslint .",
1213
"preview": "vite preview"
@@ -33,18 +34,23 @@
3334
"homepage": "https://nestia.io",
3435
"dependencies": {
3536
"@mui/material": "^5.15.6",
36-
"@nestia/migrate": "^0.19.0",
37+
"@nestia/migrate": "^0.20.0",
3738
"@stackblitz/sdk": "^1.11.0",
3839
"js-yaml": "^4.1.0",
3940
"prettier": "^3.3.3",
4041
"react-mui-fileuploader": "^0.5.2",
41-
"typia": "^6.11.3"
42+
"typia": "^6.12.0"
4243
},
4344
"devDependencies": {
4445
"@eslint/js": "^9.13.0",
46+
"@nestjs/common": "^10.4.6",
47+
"@nestjs/core": "^10.4.6",
48+
"@nestjs/platform-express": "^10.4.6",
49+
"@nestjs/platform-fastify": "^10.4.6",
4550
"@rollup/plugin-terser": "^0.4.4",
4651
"@rollup/plugin-typescript": "^12.1.1",
4752
"@types/js-yaml": "^4.0.9",
53+
"@types/node": "^22.8.6",
4854
"@types/react": "^18.3.11",
4955
"@types/react-dom": "^18.3.1",
5056
"@vitejs/plugin-react": "^4.3.3",
@@ -55,6 +61,7 @@
5561
"react": "^18.3.1",
5662
"react-dom": "^18.3.1",
5763
"rollup": "^4.24.2",
64+
"ts-node": "^10.9.2",
5865
"typescript": "^5.6.2",
5966
"typescript-eslint": "^8.10.0",
6067
"vite": "^5.4.9"
@@ -63,6 +70,7 @@
6370
"README.md",
6471
"LICENSE",
6572
"package.json",
73+
"dist",
6674
"lib",
6775
"src"
6876
]
+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import type { OpenApiV3, OpenApiV3_1, SwaggerV2 } from "@samchon/openapi";
2+
import * as fs from "fs";
3+
4+
export namespace NestiaEditorModule {
5+
export const setup = async (props: {
6+
path: string;
7+
application: INestApplication;
8+
swagger:
9+
| string
10+
| SwaggerV2.IDocument
11+
| OpenApiV3.IDocument
12+
| OpenApiV3_1.IDocument;
13+
package?: string;
14+
simulate?: boolean;
15+
e2e?: boolean;
16+
}): Promise<void> => {
17+
const prefix: string =
18+
"/" +
19+
[getGlobalPrefix(props.application), props.path]
20+
.join("/")
21+
.split("/")
22+
.filter((str) => str.length !== 0)
23+
.join("/");
24+
const adaptor: INestHttpAdaptor = props.application.getHttpAdapter();
25+
const staticFiles: IStaticFile[] = [
26+
{
27+
path: "/index.html",
28+
type: "text/html",
29+
content: await getIndex(props),
30+
},
31+
{
32+
path: "/swagger.json",
33+
type: "application/json",
34+
content: JSON.stringify(
35+
typeof props.swagger === "string"
36+
? await getSwagger(props.swagger)
37+
: props.swagger,
38+
null,
39+
2,
40+
),
41+
},
42+
await getJavaScript(),
43+
];
44+
for (const f of staticFiles) {
45+
adaptor.get(prefix + f.path, (_: any, res: any) => {
46+
res.type(f.type);
47+
return res.send(f.content);
48+
});
49+
}
50+
for (const p of ["", "/"])
51+
adaptor.get(prefix + p, (_: any, res: any) => {
52+
return res.redirect(prefix + "/index.html");
53+
});
54+
};
55+
56+
const getGlobalPrefix = (app: INestApplication): string =>
57+
typeof (app as any).config?.globalPrefix === "string"
58+
? (app as any).config.globalPrefix
59+
: "";
60+
}
61+
62+
interface INestApplication {
63+
use(...args: any[]): this;
64+
getUrl(): Promise<string>;
65+
getHttpAdapter(): INestHttpAdaptor;
66+
setGlobalPrefix(prefix: string, options?: any): this;
67+
}
68+
interface INestHttpAdaptor {
69+
getType(): string;
70+
close(): any;
71+
init?(): Promise<void>;
72+
get: Function;
73+
post: Function;
74+
put: Function;
75+
patch: Function;
76+
delete: Function;
77+
head: Function;
78+
all: Function;
79+
}
80+
interface IStaticFile {
81+
path: string;
82+
type: string;
83+
content: string;
84+
}
85+
86+
const getIndex = async (props: {
87+
package?: string;
88+
simulate?: boolean;
89+
e2e?: boolean;
90+
}): Promise<string> => {
91+
const content: string = await fs.promises.readFile(
92+
`${__dirname}/../dist/index.html`,
93+
"utf8",
94+
);
95+
return content
96+
.replace(
97+
`"@ORGANIZATION/PROJECT"`,
98+
JSON.stringify(props.package ?? "@ORGANIZATION/PROJECT"),
99+
)
100+
.replace("window.simulate = false", `window.simulate = ${!!props.simulate}`)
101+
.replace("window.e2e = false", `window.e2e = ${!!props.e2e}`);
102+
};
103+
104+
const getJavaScript = async (): Promise<IStaticFile> => {
105+
const directory: string[] = await fs.promises.readdir(
106+
`${__dirname}/../dist/assets`,
107+
);
108+
const path: string | undefined = directory[0];
109+
if (path === undefined)
110+
throw new Error("Unreachable code, no JS file exists.");
111+
return {
112+
path: `/assets/${path}`,
113+
type: "application/javascript",
114+
content: await fs.promises.readFile(
115+
`${__dirname}/../dist/assets/${path}`,
116+
"utf8",
117+
),
118+
};
119+
};
120+
121+
const getSwagger = async (
122+
url: string,
123+
): Promise<
124+
SwaggerV2.IDocument | OpenApiV3.IDocument | OpenApiV3_1.IDocument
125+
> => {
126+
const response: Response = await fetch(url);
127+
if (response.status !== 200)
128+
throw new Error(`Failed to fetch Swagger document from ${url}`);
129+
return response.json();
130+
};

0 commit comments

Comments
 (0)