@nestia/editor 12.0.0-rc.2 → 12.0.0-rc.4
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/LICENSE +21 -21
- package/dist/assets/index-Wyu3BnMf.js +4289 -0
- package/dist/index.html +19 -19
- package/lib/NestiaEditorApplication.mjs +66 -3
- package/lib/NestiaEditorApplication.mjs.map +1 -1
- package/lib/NestiaEditorIframe.js +11 -17
- package/lib/NestiaEditorIframe.js.map +1 -1
- package/lib/NestiaEditorIframe.mjs +159 -3
- package/lib/NestiaEditorIframe.mjs.map +1 -1
- package/lib/NestiaEditorModule.mjs +51 -3
- package/lib/NestiaEditorModule.mjs.map +1 -1
- package/lib/NestiaEditorUploader.js +4 -11
- package/lib/NestiaEditorUploader.js.map +1 -1
- package/lib/NestiaEditorUploader.mjs +129 -3
- package/lib/NestiaEditorUploader.mjs.map +1 -1
- package/lib/index.mjs +4 -2
- package/lib/internal/NestiaEditorArchiver.d.ts +20 -0
- package/lib/internal/NestiaEditorArchiver.js +38 -0
- package/lib/internal/NestiaEditorArchiver.js.map +1 -0
- package/lib/internal/NestiaEditorArchiver.mjs +24 -0
- package/lib/internal/NestiaEditorArchiver.mjs.map +1 -0
- package/lib/internal/NestiaEditorComposer.mjs +52 -3
- package/lib/internal/NestiaEditorComposer.mjs.map +1 -1
- package/lib/internal/NestiaEditorFileUploader.mjs +43 -3
- package/lib/internal/NestiaEditorFileUploader.mjs.map +1 -1
- package/lib/main.mjs +9 -3
- package/lib/main.mjs.map +1 -1
- package/package.json +9 -12
- package/src/NestiaEditorApplication.tsx +94 -94
- package/src/NestiaEditorIframe.tsx +258 -245
- package/src/NestiaEditorModule.ts +136 -136
- package/src/NestiaEditorUploader.tsx +146 -154
- package/src/index.ts +3 -3
- package/src/internal/NestiaEditorArchiver.ts +43 -0
- package/src/internal/NestiaEditorComposer.ts +89 -89
- package/src/internal/NestiaEditorFileUploader.tsx +65 -65
- package/src/main.tsx +10 -10
- package/src/typings/react-mui-fileuploader.d.ts +27 -27
- package/src/vite-env.d.ts +1 -1
- package/README.md +0 -93
- package/dist/assets/index-tCs1FGcC.js +0 -4318
- package/lib/NestiaEditorApplication2.mjs +0 -86
- package/lib/NestiaEditorApplication2.mjs.map +0 -1
- package/lib/NestiaEditorIframe2.mjs +0 -139
- package/lib/NestiaEditorIframe2.mjs.map +0 -1
- package/lib/NestiaEditorModule2.mjs +0 -124
- package/lib/NestiaEditorModule2.mjs.map +0 -1
- package/lib/NestiaEditorUploader2.mjs +0 -90
- package/lib/NestiaEditorUploader2.mjs.map +0 -1
- package/lib/_virtual/NestiaEditorApplication.mjs +0 -4
- package/lib/_virtual/NestiaEditorApplication.mjs.map +0 -1
- package/lib/_virtual/NestiaEditorComposer.mjs +0 -4
- package/lib/_virtual/NestiaEditorComposer.mjs.map +0 -1
- package/lib/_virtual/NestiaEditorFileUploader.mjs +0 -4
- package/lib/_virtual/NestiaEditorFileUploader.mjs.map +0 -1
- package/lib/_virtual/NestiaEditorIframe.mjs +0 -4
- package/lib/_virtual/NestiaEditorIframe.mjs.map +0 -1
- package/lib/_virtual/NestiaEditorModule.mjs +0 -4
- package/lib/_virtual/NestiaEditorModule.mjs.map +0 -1
- package/lib/_virtual/NestiaEditorUploader.mjs +0 -4
- package/lib/_virtual/NestiaEditorUploader.mjs.map +0 -1
- package/lib/_virtual/_commonjsHelpers.mjs +0 -35
- package/lib/_virtual/_commonjsHelpers.mjs.map +0 -1
- package/lib/_virtual/_js-yaml.mjs +0 -7
- package/lib/_virtual/_js-yaml.mjs.map +0 -1
- package/lib/_virtual/_node_fs.mjs +0 -7
- package/lib/_virtual/_node_fs.mjs.map +0 -1
- package/lib/_virtual/_react-mui-fileuploader.mjs +0 -7
- package/lib/_virtual/_react-mui-fileuploader.mjs.map +0 -1
- package/lib/_virtual/_react.mjs +0 -7
- package/lib/_virtual/_react.mjs.map +0 -1
- package/lib/_virtual/client.mjs +0 -7
- package/lib/_virtual/client.mjs.map +0 -1
- package/lib/_virtual/estree.mjs +0 -7
- package/lib/_virtual/estree.mjs.map +0 -1
- package/lib/_virtual/index.mjs +0 -4
- package/lib/_virtual/index.mjs.map +0 -1
- package/lib/_virtual/jsx-runtime.mjs +0 -7
- package/lib/_virtual/jsx-runtime.mjs.map +0 -1
- package/lib/_virtual/main.mjs +0 -4
- package/lib/_virtual/main.mjs.map +0 -1
- package/lib/_virtual/material.mjs +0 -7
- package/lib/_virtual/material.mjs.map +0 -1
- package/lib/_virtual/migrate.mjs +0 -7
- package/lib/_virtual/migrate.mjs.map +0 -1
- package/lib/_virtual/sdk.mjs +0 -7
- package/lib/_virtual/sdk.mjs.map +0 -1
- package/lib/_virtual/standalone.mjs +0 -7
- package/lib/_virtual/standalone.mjs.map +0 -1
- package/lib/_virtual/typescript.mjs +0 -7
- package/lib/_virtual/typescript.mjs.map +0 -1
- package/lib/index.mjs.map +0 -1
- package/lib/index2.mjs +0 -35
- package/lib/index2.mjs.map +0 -1
- package/lib/internal/NestiaEditorComposer2.mjs +0 -110
- package/lib/internal/NestiaEditorComposer2.mjs.map +0 -1
- package/lib/internal/NestiaEditorFileUploader2.mjs +0 -51
- package/lib/internal/NestiaEditorFileUploader2.mjs.map +0 -1
- package/lib/main2.mjs +0 -16
- package/lib/main2.mjs.map +0 -1
|
@@ -1,136 +1,136 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
OpenApiV3,
|
|
3
|
-
OpenApiV3_1,
|
|
4
|
-
OpenApiV3_2,
|
|
5
|
-
SwaggerV2,
|
|
6
|
-
} from "@typia/interface";
|
|
7
|
-
import * as fs from "fs";
|
|
8
|
-
|
|
9
|
-
export namespace NestiaEditorModule {
|
|
10
|
-
export const setup = async (props: {
|
|
11
|
-
path: string;
|
|
12
|
-
application: INestApplication;
|
|
13
|
-
swagger:
|
|
14
|
-
| string
|
|
15
|
-
| SwaggerV2.IDocument
|
|
16
|
-
| OpenApiV3.IDocument
|
|
17
|
-
| OpenApiV3_1.IDocument
|
|
18
|
-
| OpenApiV3_2.IDocument;
|
|
19
|
-
package?: string;
|
|
20
|
-
simulate?: boolean;
|
|
21
|
-
e2e?: boolean;
|
|
22
|
-
}): Promise<void> => {
|
|
23
|
-
const prefix: string =
|
|
24
|
-
"/" +
|
|
25
|
-
[getGlobalPrefix(props.application), props.path]
|
|
26
|
-
.join("/")
|
|
27
|
-
.split("/")
|
|
28
|
-
.filter((str) => str.length !== 0)
|
|
29
|
-
.join("/");
|
|
30
|
-
const adaptor: INestHttpAdaptor = props.application.getHttpAdapter();
|
|
31
|
-
const staticFiles: IStaticFile[] = [
|
|
32
|
-
{
|
|
33
|
-
path: "/index.html",
|
|
34
|
-
type: "text/html",
|
|
35
|
-
content: await getIndex(props),
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
path: "/swagger.json",
|
|
39
|
-
type: "application/json",
|
|
40
|
-
content: JSON.stringify(
|
|
41
|
-
typeof props.swagger === "string"
|
|
42
|
-
? await getSwagger(props.swagger)
|
|
43
|
-
: props.swagger,
|
|
44
|
-
null,
|
|
45
|
-
2,
|
|
46
|
-
),
|
|
47
|
-
},
|
|
48
|
-
await getJavaScript(),
|
|
49
|
-
];
|
|
50
|
-
for (const f of staticFiles) {
|
|
51
|
-
adaptor.get(prefix + f.path, (_: any, res: any) => {
|
|
52
|
-
res.type(f.type);
|
|
53
|
-
return res.send(f.content);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
for (const p of ["", "/"])
|
|
57
|
-
adaptor.get(prefix + p, (_: any, res: any) => {
|
|
58
|
-
return res.redirect(prefix + "/index.html");
|
|
59
|
-
});
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const getGlobalPrefix = (app: INestApplication): string =>
|
|
63
|
-
typeof (app as any).config?.globalPrefix === "string"
|
|
64
|
-
? (app as any).config.globalPrefix
|
|
65
|
-
: "";
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
interface INestApplication {
|
|
69
|
-
use(...args: any[]): this;
|
|
70
|
-
getUrl(): Promise<string>;
|
|
71
|
-
getHttpAdapter(): INestHttpAdaptor;
|
|
72
|
-
setGlobalPrefix(prefix: string, options?: any): this;
|
|
73
|
-
}
|
|
74
|
-
interface INestHttpAdaptor {
|
|
75
|
-
getType(): string;
|
|
76
|
-
close(): any;
|
|
77
|
-
init?(): Promise<void>;
|
|
78
|
-
get: Function;
|
|
79
|
-
post: Function;
|
|
80
|
-
put: Function;
|
|
81
|
-
patch: Function;
|
|
82
|
-
delete: Function;
|
|
83
|
-
head: Function;
|
|
84
|
-
all: Function;
|
|
85
|
-
}
|
|
86
|
-
interface IStaticFile {
|
|
87
|
-
path: string;
|
|
88
|
-
type: string;
|
|
89
|
-
content: string;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const getIndex = async (props: {
|
|
93
|
-
package?: string;
|
|
94
|
-
simulate?: boolean;
|
|
95
|
-
e2e?: boolean;
|
|
96
|
-
}): Promise<string> => {
|
|
97
|
-
const content: string = await fs.promises.readFile(
|
|
98
|
-
`${__dirname}/../dist/index.html`,
|
|
99
|
-
"utf8",
|
|
100
|
-
);
|
|
101
|
-
return content
|
|
102
|
-
.replace(
|
|
103
|
-
`"@ORGANIZATION/PROJECT"`,
|
|
104
|
-
JSON.stringify(props.package ?? "@ORGANIZATION/PROJECT"),
|
|
105
|
-
)
|
|
106
|
-
.replace("window.simulate = false", `window.simulate = ${!!props.simulate}`)
|
|
107
|
-
.replace("window.e2e = false", `window.e2e = ${!!props.e2e}`);
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const getJavaScript = async (): Promise<IStaticFile> => {
|
|
111
|
-
const directory: string[] = await fs.promises.readdir(
|
|
112
|
-
`${__dirname}/../dist/assets`,
|
|
113
|
-
);
|
|
114
|
-
const path: string | undefined = directory[0];
|
|
115
|
-
if (path === undefined)
|
|
116
|
-
throw new Error("Unreachable code, no JS file exists.");
|
|
117
|
-
return {
|
|
118
|
-
path: `/assets/${path}`,
|
|
119
|
-
type: "application/javascript",
|
|
120
|
-
content: await fs.promises.readFile(
|
|
121
|
-
`${__dirname}/../dist/assets/${path}`,
|
|
122
|
-
"utf8",
|
|
123
|
-
),
|
|
124
|
-
};
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
const getSwagger = async (
|
|
128
|
-
url: string,
|
|
129
|
-
): Promise<
|
|
130
|
-
SwaggerV2.IDocument | OpenApiV3.IDocument | OpenApiV3_1.IDocument
|
|
131
|
-
> => {
|
|
132
|
-
const response: Response = await fetch(url);
|
|
133
|
-
if (response.status !== 200)
|
|
134
|
-
throw new Error(`Failed to fetch Swagger document from ${url}`);
|
|
135
|
-
return response.json();
|
|
136
|
-
};
|
|
1
|
+
import type {
|
|
2
|
+
OpenApiV3,
|
|
3
|
+
OpenApiV3_1,
|
|
4
|
+
OpenApiV3_2,
|
|
5
|
+
SwaggerV2,
|
|
6
|
+
} from "@typia/interface";
|
|
7
|
+
import * as fs from "fs";
|
|
8
|
+
|
|
9
|
+
export namespace NestiaEditorModule {
|
|
10
|
+
export const setup = async (props: {
|
|
11
|
+
path: string;
|
|
12
|
+
application: INestApplication;
|
|
13
|
+
swagger:
|
|
14
|
+
| string
|
|
15
|
+
| SwaggerV2.IDocument
|
|
16
|
+
| OpenApiV3.IDocument
|
|
17
|
+
| OpenApiV3_1.IDocument
|
|
18
|
+
| OpenApiV3_2.IDocument;
|
|
19
|
+
package?: string;
|
|
20
|
+
simulate?: boolean;
|
|
21
|
+
e2e?: boolean;
|
|
22
|
+
}): Promise<void> => {
|
|
23
|
+
const prefix: string =
|
|
24
|
+
"/" +
|
|
25
|
+
[getGlobalPrefix(props.application), props.path]
|
|
26
|
+
.join("/")
|
|
27
|
+
.split("/")
|
|
28
|
+
.filter((str) => str.length !== 0)
|
|
29
|
+
.join("/");
|
|
30
|
+
const adaptor: INestHttpAdaptor = props.application.getHttpAdapter();
|
|
31
|
+
const staticFiles: IStaticFile[] = [
|
|
32
|
+
{
|
|
33
|
+
path: "/index.html",
|
|
34
|
+
type: "text/html",
|
|
35
|
+
content: await getIndex(props),
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
path: "/swagger.json",
|
|
39
|
+
type: "application/json",
|
|
40
|
+
content: JSON.stringify(
|
|
41
|
+
typeof props.swagger === "string"
|
|
42
|
+
? await getSwagger(props.swagger)
|
|
43
|
+
: props.swagger,
|
|
44
|
+
null,
|
|
45
|
+
2,
|
|
46
|
+
),
|
|
47
|
+
},
|
|
48
|
+
await getJavaScript(),
|
|
49
|
+
];
|
|
50
|
+
for (const f of staticFiles) {
|
|
51
|
+
adaptor.get(prefix + f.path, (_: any, res: any) => {
|
|
52
|
+
res.type(f.type);
|
|
53
|
+
return res.send(f.content);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
for (const p of ["", "/"])
|
|
57
|
+
adaptor.get(prefix + p, (_: any, res: any) => {
|
|
58
|
+
return res.redirect(prefix + "/index.html");
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const getGlobalPrefix = (app: INestApplication): string =>
|
|
63
|
+
typeof (app as any).config?.globalPrefix === "string"
|
|
64
|
+
? (app as any).config.globalPrefix
|
|
65
|
+
: "";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface INestApplication {
|
|
69
|
+
use(...args: any[]): this;
|
|
70
|
+
getUrl(): Promise<string>;
|
|
71
|
+
getHttpAdapter(): INestHttpAdaptor;
|
|
72
|
+
setGlobalPrefix(prefix: string, options?: any): this;
|
|
73
|
+
}
|
|
74
|
+
interface INestHttpAdaptor {
|
|
75
|
+
getType(): string;
|
|
76
|
+
close(): any;
|
|
77
|
+
init?(): Promise<void>;
|
|
78
|
+
get: Function;
|
|
79
|
+
post: Function;
|
|
80
|
+
put: Function;
|
|
81
|
+
patch: Function;
|
|
82
|
+
delete: Function;
|
|
83
|
+
head: Function;
|
|
84
|
+
all: Function;
|
|
85
|
+
}
|
|
86
|
+
interface IStaticFile {
|
|
87
|
+
path: string;
|
|
88
|
+
type: string;
|
|
89
|
+
content: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const getIndex = async (props: {
|
|
93
|
+
package?: string;
|
|
94
|
+
simulate?: boolean;
|
|
95
|
+
e2e?: boolean;
|
|
96
|
+
}): Promise<string> => {
|
|
97
|
+
const content: string = await fs.promises.readFile(
|
|
98
|
+
`${__dirname}/../dist/index.html`,
|
|
99
|
+
"utf8",
|
|
100
|
+
);
|
|
101
|
+
return content
|
|
102
|
+
.replace(
|
|
103
|
+
`"@ORGANIZATION/PROJECT"`,
|
|
104
|
+
JSON.stringify(props.package ?? "@ORGANIZATION/PROJECT"),
|
|
105
|
+
)
|
|
106
|
+
.replace("window.simulate = false", `window.simulate = ${!!props.simulate}`)
|
|
107
|
+
.replace("window.e2e = false", `window.e2e = ${!!props.e2e}`);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const getJavaScript = async (): Promise<IStaticFile> => {
|
|
111
|
+
const directory: string[] = await fs.promises.readdir(
|
|
112
|
+
`${__dirname}/../dist/assets`,
|
|
113
|
+
);
|
|
114
|
+
const path: string | undefined = directory[0];
|
|
115
|
+
if (path === undefined)
|
|
116
|
+
throw new Error("Unreachable code, no JS file exists.");
|
|
117
|
+
return {
|
|
118
|
+
path: `/assets/${path}`,
|
|
119
|
+
type: "application/javascript",
|
|
120
|
+
content: await fs.promises.readFile(
|
|
121
|
+
`${__dirname}/../dist/assets/${path}`,
|
|
122
|
+
"utf8",
|
|
123
|
+
),
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const getSwagger = async (
|
|
128
|
+
url: string,
|
|
129
|
+
): Promise<
|
|
130
|
+
SwaggerV2.IDocument | OpenApiV3.IDocument | OpenApiV3_1.IDocument
|
|
131
|
+
> => {
|
|
132
|
+
const response: Response = await fetch(url);
|
|
133
|
+
if (response.status !== 200)
|
|
134
|
+
throw new Error(`Failed to fetch Swagger document from ${url}`);
|
|
135
|
+
return response.json();
|
|
136
|
+
};
|
|
@@ -1,154 +1,146 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Button,
|
|
3
|
-
FormControl,
|
|
4
|
-
FormControlLabel,
|
|
5
|
-
FormLabel,
|
|
6
|
-
Radio,
|
|
7
|
-
RadioGroup,
|
|
8
|
-
Switch,
|
|
9
|
-
TextField,
|
|
10
|
-
} from "@mui/material";
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
import { NestiaEditorComposer } from "./internal/NestiaEditorComposer";
|
|
16
|
-
import { NestiaEditorFileUploader } from "./internal/NestiaEditorFileUploader";
|
|
17
|
-
|
|
18
|
-
export function NestiaEditorUploader(props: NestiaEditorUploader.IProps) {
|
|
19
|
-
// PARAMETERS
|
|
20
|
-
const [mode, setMode] = React.useState<"nest" | "sdk">("sdk");
|
|
21
|
-
const [keyword, setKeyword] = React.useState(true);
|
|
22
|
-
const [simulate, setSimulate] = React.useState(true);
|
|
23
|
-
const [e2e, setE2e] = React.useState(true);
|
|
24
|
-
const [name, setName] = React.useState("@ORGINIZATION/PROJECT");
|
|
25
|
-
|
|
26
|
-
// RESULT
|
|
27
|
-
const [document, setDocument] = React.useState<
|
|
28
|
-
SwaggerV2.IDocument | OpenApiV3.IDocument | OpenApiV3_1.IDocument | null
|
|
29
|
-
>(null);
|
|
30
|
-
const [progress, setProgress] = React.useState(false);
|
|
31
|
-
|
|
32
|
-
const handleError = (error: string) => {
|
|
33
|
-
if (props.onError) props.onError(error);
|
|
34
|
-
else alert(error);
|
|
35
|
-
};
|
|
36
|
-
const handleSwagger = (
|
|
37
|
-
document:
|
|
38
|
-
| SwaggerV2.IDocument
|
|
39
|
-
| OpenApiV3.IDocument
|
|
40
|
-
| OpenApiV3_1.IDocument
|
|
41
|
-
| null,
|
|
42
|
-
error: string | null,
|
|
43
|
-
) => {
|
|
44
|
-
setDocument(document);
|
|
45
|
-
if (error !== null) handleError(error);
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const generate = async () => {
|
|
49
|
-
if (document === null) return;
|
|
50
|
-
|
|
51
|
-
setProgress(true);
|
|
52
|
-
try {
|
|
53
|
-
const result = await NestiaEditorComposer[mode]({
|
|
54
|
-
document,
|
|
55
|
-
keyword,
|
|
56
|
-
e2e,
|
|
57
|
-
simulate,
|
|
58
|
-
package: name,
|
|
59
|
-
});
|
|
60
|
-
if (result.success === true) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
onChange={(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
</>
|
|
148
|
-
);
|
|
149
|
-
}
|
|
150
|
-
export namespace NestiaEditorUploader {
|
|
151
|
-
export interface IProps {
|
|
152
|
-
onError?: (error: string) => void;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
FormControl,
|
|
4
|
+
FormControlLabel,
|
|
5
|
+
FormLabel,
|
|
6
|
+
Radio,
|
|
7
|
+
RadioGroup,
|
|
8
|
+
Switch,
|
|
9
|
+
TextField,
|
|
10
|
+
} from "@mui/material";
|
|
11
|
+
import { OpenApiV3, OpenApiV3_1, SwaggerV2 } from "@typia/interface";
|
|
12
|
+
import React from "react";
|
|
13
|
+
|
|
14
|
+
import { NestiaEditorArchiver } from "./internal/NestiaEditorArchiver";
|
|
15
|
+
import { NestiaEditorComposer } from "./internal/NestiaEditorComposer";
|
|
16
|
+
import { NestiaEditorFileUploader } from "./internal/NestiaEditorFileUploader";
|
|
17
|
+
|
|
18
|
+
export function NestiaEditorUploader(props: NestiaEditorUploader.IProps) {
|
|
19
|
+
// PARAMETERS
|
|
20
|
+
const [mode, setMode] = React.useState<"nest" | "sdk">("sdk");
|
|
21
|
+
const [keyword, setKeyword] = React.useState(true);
|
|
22
|
+
const [simulate, setSimulate] = React.useState(true);
|
|
23
|
+
const [e2e, setE2e] = React.useState(true);
|
|
24
|
+
const [name, setName] = React.useState("@ORGINIZATION/PROJECT");
|
|
25
|
+
|
|
26
|
+
// RESULT
|
|
27
|
+
const [document, setDocument] = React.useState<
|
|
28
|
+
SwaggerV2.IDocument | OpenApiV3.IDocument | OpenApiV3_1.IDocument | null
|
|
29
|
+
>(null);
|
|
30
|
+
const [progress, setProgress] = React.useState(false);
|
|
31
|
+
|
|
32
|
+
const handleError = (error: string) => {
|
|
33
|
+
if (props.onError) props.onError(error);
|
|
34
|
+
else alert(error);
|
|
35
|
+
};
|
|
36
|
+
const handleSwagger = (
|
|
37
|
+
document:
|
|
38
|
+
| SwaggerV2.IDocument
|
|
39
|
+
| OpenApiV3.IDocument
|
|
40
|
+
| OpenApiV3_1.IDocument
|
|
41
|
+
| null,
|
|
42
|
+
error: string | null,
|
|
43
|
+
) => {
|
|
44
|
+
setDocument(document);
|
|
45
|
+
if (error !== null) handleError(error);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const generate = async () => {
|
|
49
|
+
if (document === null) return;
|
|
50
|
+
|
|
51
|
+
setProgress(true);
|
|
52
|
+
try {
|
|
53
|
+
const result = await NestiaEditorComposer[mode]({
|
|
54
|
+
document,
|
|
55
|
+
keyword,
|
|
56
|
+
e2e,
|
|
57
|
+
simulate,
|
|
58
|
+
package: name,
|
|
59
|
+
});
|
|
60
|
+
if (result.success === true) {
|
|
61
|
+
NestiaEditorArchiver.download({
|
|
62
|
+
name: NestiaEditorArchiver.name(name),
|
|
63
|
+
files: result.data.files,
|
|
64
|
+
});
|
|
65
|
+
} else {
|
|
66
|
+
handleError(JSON.stringify(result.errors, null, 2));
|
|
67
|
+
}
|
|
68
|
+
} catch (exp) {
|
|
69
|
+
handleError(exp instanceof Error ? exp.message : "unknown error");
|
|
70
|
+
}
|
|
71
|
+
setProgress(false);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<>
|
|
76
|
+
<NestiaEditorFileUploader onChange={handleSwagger} />
|
|
77
|
+
<br />
|
|
78
|
+
<FormControl fullWidth style={{ paddingLeft: 15 }}>
|
|
79
|
+
<TextField
|
|
80
|
+
onChange={(e) => setName(e.target.value)}
|
|
81
|
+
defaultValue={name}
|
|
82
|
+
label="Package Name"
|
|
83
|
+
variant="outlined"
|
|
84
|
+
/>
|
|
85
|
+
<FormLabel style={{ paddingTop: 20 }}> Mode </FormLabel>
|
|
86
|
+
<RadioGroup
|
|
87
|
+
defaultValue={mode}
|
|
88
|
+
onChange={(_e, value) => setMode(value as "nest" | "sdk")}
|
|
89
|
+
style={{ paddingLeft: 15 }}
|
|
90
|
+
>
|
|
91
|
+
<FormControlLabel
|
|
92
|
+
value="sdk"
|
|
93
|
+
control={<Radio />}
|
|
94
|
+
label="Software Development Kit"
|
|
95
|
+
/>
|
|
96
|
+
<FormControlLabel
|
|
97
|
+
value="nest"
|
|
98
|
+
control={<Radio />}
|
|
99
|
+
label="NestJS Project"
|
|
100
|
+
/>
|
|
101
|
+
</RadioGroup>
|
|
102
|
+
<FormLabel style={{ paddingTop: 20 }}> Options </FormLabel>
|
|
103
|
+
<FormControlLabel
|
|
104
|
+
label="Keyword Parameter"
|
|
105
|
+
style={{ paddingTop: 5, paddingLeft: 15 }}
|
|
106
|
+
control={
|
|
107
|
+
<Switch checked={keyword} onChange={() => setKeyword(!keyword)} />
|
|
108
|
+
}
|
|
109
|
+
/>
|
|
110
|
+
<FormControlLabel
|
|
111
|
+
label="Mockup Simulator"
|
|
112
|
+
style={{ paddingTop: 5, paddingLeft: 15 }}
|
|
113
|
+
control={
|
|
114
|
+
<Switch
|
|
115
|
+
checked={simulate}
|
|
116
|
+
onChange={() => setSimulate(!simulate)}
|
|
117
|
+
/>
|
|
118
|
+
}
|
|
119
|
+
/>
|
|
120
|
+
<FormControlLabel
|
|
121
|
+
label="E2E Test Functions"
|
|
122
|
+
style={{ paddingLeft: 15 }}
|
|
123
|
+
control={<Switch checked={e2e} onChange={() => setE2e(!e2e)} />}
|
|
124
|
+
/>
|
|
125
|
+
</FormControl>
|
|
126
|
+
<br />
|
|
127
|
+
<br />
|
|
128
|
+
<Button
|
|
129
|
+
component="a"
|
|
130
|
+
fullWidth
|
|
131
|
+
variant="contained"
|
|
132
|
+
color={"info"}
|
|
133
|
+
size="large"
|
|
134
|
+
disabled={progress === true || document === null}
|
|
135
|
+
onClick={() => generate()}
|
|
136
|
+
>
|
|
137
|
+
{progress ? "Generating..." : "Download Project"}
|
|
138
|
+
</Button>
|
|
139
|
+
</>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
export namespace NestiaEditorUploader {
|
|
143
|
+
export interface IProps {
|
|
144
|
+
onError?: (error: string) => void;
|
|
145
|
+
}
|
|
146
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from "./NestiaEditorApplication";
|
|
2
|
-
export * from "./NestiaEditorIframe";
|
|
3
|
-
export * from "./NestiaEditorUploader";
|
|
1
|
+
export * from "./NestiaEditorApplication";
|
|
2
|
+
export * from "./NestiaEditorIframe";
|
|
3
|
+
export * from "./NestiaEditorUploader";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { strToU8, zipSync } from "fflate";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Archives a composed project into a zip file and hands it to the browser.
|
|
5
|
+
*
|
|
6
|
+
* StackBlitz can no longer run nestia projects: the generated projects build
|
|
7
|
+
* through `ttsc`, whose TypeScript compiler is a native Go binary that a
|
|
8
|
+
* WebContainer cannot execute. The editor therefore delivers the composed
|
|
9
|
+
* project as a downloadable zip archive instead of an embedded StackBlitz
|
|
10
|
+
* workspace.
|
|
11
|
+
*/
|
|
12
|
+
export namespace NestiaEditorArchiver {
|
|
13
|
+
/** Pack the composed project files into a zip archive. */
|
|
14
|
+
export const pack = (files: Record<string, string>): Uint8Array => {
|
|
15
|
+
const entries: Record<string, Uint8Array> = {};
|
|
16
|
+
for (const [key, value] of Object.entries(files))
|
|
17
|
+
entries[key] = strToU8(value);
|
|
18
|
+
return zipSync(entries);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** Compose a safe archive file name from a package name. */
|
|
22
|
+
export const name = (packageName: string): string =>
|
|
23
|
+
`${packageName.replace(/^@/, "").replace(/[^A-Za-z0-9._-]+/g, "-")}.zip`;
|
|
24
|
+
|
|
25
|
+
/** Trigger a browser download of the packed archive. */
|
|
26
|
+
export const download = (props: {
|
|
27
|
+
name: string;
|
|
28
|
+
files: Record<string, string>;
|
|
29
|
+
}): void => {
|
|
30
|
+
const blob: Blob = new Blob(
|
|
31
|
+
[pack(props.files) as Uint8Array<ArrayBuffer>],
|
|
32
|
+
{
|
|
33
|
+
type: "application/zip",
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
const url: string = URL.createObjectURL(blob);
|
|
37
|
+
const anchor: HTMLAnchorElement = window.document.createElement("a");
|
|
38
|
+
anchor.href = url;
|
|
39
|
+
anchor.download = props.name;
|
|
40
|
+
anchor.click();
|
|
41
|
+
setTimeout(() => URL.revokeObjectURL(url), 30_000);
|
|
42
|
+
};
|
|
43
|
+
}
|