create-jwn-js 1.0.30 → 1.0.32
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/index.js +9 -3
- package/package.json +3 -2
- package/{template-lambda-api-ts → template-lambda-http-api-ts}/package.json +3 -1
- package/template-lambda-http-api-ts/src/backend/index.mts +8 -0
- package/{template-lambda-api-ts → template-lambda-http-api-ts}/src/scripts/test.setup.mts +1 -1
- package/{template-lambda-api-ts → template-lambda-http-api-ts}/src/scripts/vitest.global.setup.mts +1 -1
- package/{template-lambda-api-ts → template-lambda-http-api-ts}/tsconfig.json +1 -0
- package/{template-lambda-api-ts → template-lambda-http-api-ts}/vite.config.mts +40 -44
- package/{template-lambda-api-ts → template-lambda-http-api-ts}/yarn.lock +27 -0
- package/template-lambda-rest-api-ts/.gitignore +5 -0
- package/template-lambda-rest-api-ts/index.mts +0 -0
- package/template-lambda-rest-api-ts/package.json +30 -0
- package/template-lambda-rest-api-ts/src/backend/__its__/handler.spec.mts +9 -0
- package/template-lambda-rest-api-ts/src/scripts/test.setup.mts +21 -0
- package/template-lambda-rest-api-ts/src/scripts/vitest.global.setup.mts +26 -0
- package/template-lambda-rest-api-ts/tsconfig.json +47 -0
- package/template-lambda-rest-api-ts/vite.config.mts +188 -0
- package/template-lambda-rest-api-ts/vitest.config.mts +40 -0
- package/template-lambda-rest-api-ts/vitest.config.production.mts +38 -0
- package/template-lambda-rest-api-ts/yarn-error.log +1889 -0
- package/{template-lambda-api-ts/dist → template-lambda-rest-api-ts}/yarn.lock +1011 -0
- package/{template-vite-vue3-ts → template-vite-node-ts}/connect.json +1 -10
- package/template-vite-node-ts/src/backend/server/helpers/createConfigServer.ts +1 -1
- package/template-vite-node-ts/yarn.lock +4 -4
- package/template-vite-vue3-ts/src/backend/server/helpers/createConfigServer.ts +1 -1
- package/template-lambda-api-ts/dist/index.mjs +0 -9
- package/template-lambda-api-ts/dist/package.json +0 -11
- package/template-vite-node-ts/connect.json5 +0 -20
- /package/{template-lambda-api-ts → template-lambda-http-api-ts}/.gitignore +0 -0
- /package/{template-lambda-api-ts → template-lambda-http-api-ts}/index.mts +0 -0
- /package/{template-lambda-api-ts → template-lambda-http-api-ts}/src/backend/__its__/handler.spec.mts +0 -0
- /package/{template-lambda-api-ts → template-lambda-http-api-ts}/vitest.config.mts +0 -0
- /package/{template-lambda-api-ts → template-lambda-http-api-ts}/vitest.config.production.mts +0 -0
- /package/{template-lambda-api-ts → template-lambda-http-api-ts}/yarn-error.log +0 -0
- /package/{template-lambda-api-ts → template-lambda-rest-api-ts}/src/backend/index.mts +0 -0
package/index.js
CHANGED
|
@@ -5,6 +5,7 @@ const path = require('path')
|
|
|
5
5
|
const margv = require('margv')
|
|
6
6
|
const argv = margv();
|
|
7
7
|
const prompts = require('prompts');
|
|
8
|
+
const json5 = require('json5');
|
|
8
9
|
|
|
9
10
|
const {
|
|
10
11
|
yellow,
|
|
@@ -40,7 +41,12 @@ const FRAMEWORKS = [
|
|
|
40
41
|
color: yellow,
|
|
41
42
|
variants: [
|
|
42
43
|
{
|
|
43
|
-
name: 'lambda-api-ts',
|
|
44
|
+
name: 'lambda-rest-api-ts',
|
|
45
|
+
display: 'TypeScript',
|
|
46
|
+
color: blue
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'lambda-http-api-ts',
|
|
44
50
|
display: 'TypeScript',
|
|
45
51
|
color: blue
|
|
46
52
|
}
|
|
@@ -186,8 +192,8 @@ async function init() {
|
|
|
186
192
|
|
|
187
193
|
// connect.json5
|
|
188
194
|
if(fs.existsSync(path.join(templateDir, `connect-template.json5`))) {
|
|
189
|
-
const connect =
|
|
190
|
-
write('connect.json5',
|
|
195
|
+
const connect = json5.parse(fs.readFileSync(path.join(templateDir, `connect-template.json5`)).toString());
|
|
196
|
+
write('connect.json5', json5.stringify(connect, null, 2));
|
|
191
197
|
}
|
|
192
198
|
|
|
193
199
|
// package.json
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-jwn-js",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.32",
|
|
4
4
|
"license": "PRIVATE",
|
|
5
5
|
"author": "Webigorkiev",
|
|
6
6
|
"bin": {
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"homepage": "https://github.com/webigorkiev",
|
|
20
20
|
"dependencies": {
|
|
21
|
+
"json5": "^2.2.3",
|
|
21
22
|
"kolorist": "^1.5.0",
|
|
22
23
|
"margv": "^1.1.2",
|
|
23
24
|
"prompts": "^2.4.2"
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
"jsdom": "^24.0.0",
|
|
34
35
|
"memjs": "^1.3.2",
|
|
35
36
|
"typescript": "^5.3.3",
|
|
36
|
-
"vite": "
|
|
37
|
+
"vite": "5",
|
|
37
38
|
"vitepress": "0.22.4",
|
|
38
39
|
"vitest": "^1.2.2"
|
|
39
40
|
}
|
|
@@ -10,10 +10,12 @@
|
|
|
10
10
|
"serve": "vite",
|
|
11
11
|
"build": "vite build && cd ./dist && yarn",
|
|
12
12
|
"test": "vitest run",
|
|
13
|
-
"test:production": "vitest run -c vitest.config.production.mts"
|
|
13
|
+
"test:production": "vitest run -c vitest.config.production.mts",
|
|
14
|
+
"deploy": "yarn build && cd dist && zip -r ../dist.zip ."
|
|
14
15
|
},
|
|
15
16
|
"devDependencies": {
|
|
16
17
|
"@types/aws-lambda": "8",
|
|
18
|
+
"@types/fs-extra": "^11.0.4",
|
|
17
19
|
"@types/node": "20",
|
|
18
20
|
"chalk": "^5.3.0",
|
|
19
21
|
"fs-extra": "^11.2.0",
|
|
@@ -16,6 +16,6 @@ const defaultHeaders = {
|
|
|
16
16
|
const fetchWrapper = async(
|
|
17
17
|
input: RequestInfo,
|
|
18
18
|
init: RequestInit = {}
|
|
19
|
-
) =>
|
|
19
|
+
) => fetch(input, Object.assign({}, defaultHeaders, init));
|
|
20
20
|
|
|
21
21
|
export {fetchWrapper as fetch, testConfig};
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from "aws-lambda";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import {performance} from "node:perf_hooks";
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import {build, defineConfig, mergeConfig, Plugin, ResolvedConfig} from "vite";
|
|
6
6
|
import fs from "fs-extra";
|
|
7
|
-
import type {
|
|
8
|
-
import querystring from "node:querystring";
|
|
7
|
+
import type {Connect} from "vite";
|
|
9
8
|
|
|
10
9
|
interface Options {
|
|
11
10
|
entry: string
|
|
@@ -16,15 +15,11 @@ const cnf = {
|
|
|
16
15
|
host: "localhost",
|
|
17
16
|
port: 3000,
|
|
18
17
|
};
|
|
19
|
-
const
|
|
20
|
-
"content-type": "application/json"
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const readBody = (req: IncomingMessage) => {
|
|
18
|
+
const readBody = (req: Connect.IncomingMessage): Promise<string> => {
|
|
24
19
|
return new Promise(resolve => {
|
|
25
|
-
const body = [];
|
|
20
|
+
const body: Buffer[] = [];
|
|
26
21
|
req
|
|
27
|
-
.on('data', chunk => {
|
|
22
|
+
.on('data', (chunk: Buffer) => {
|
|
28
23
|
body.push(chunk);
|
|
29
24
|
})
|
|
30
25
|
.on('end', () => {
|
|
@@ -34,42 +29,42 @@ const readBody = (req: IncomingMessage) => {
|
|
|
34
29
|
};
|
|
35
30
|
|
|
36
31
|
// Адаптер для согласованности с AWS Lambda
|
|
37
|
-
const incomingMessageAdapter = async(req: IncomingMessage): Promise<
|
|
38
|
-
const urlPath = req.originalUrl.split("#")[0];
|
|
32
|
+
const incomingMessageAdapter = async(req: Connect.IncomingMessage): Promise<APIGatewayProxyEventV2> => {
|
|
33
|
+
const urlPath = (req.originalUrl || "").split("#")[0];
|
|
39
34
|
const path = urlPath.split('?')[0];
|
|
40
|
-
const
|
|
41
|
-
const queryStringParameters = Object.keys(multiValueQueryStringParameters).reduce((ac, key) => {
|
|
42
|
-
ac[key] = ac[key] || multiValueQueryStringParameters[key];
|
|
43
|
-
if(Array.isArray(ac[key])) {
|
|
44
|
-
ac[key] = ac[key][ac[key].length - 1];
|
|
45
|
-
}
|
|
46
|
-
return ac;
|
|
47
|
-
}, {})
|
|
35
|
+
const rawQueryString = urlPath.split('?')[1];
|
|
48
36
|
const headers = (req.rawHeaders || []).reduce((ac, v, index, all) => {
|
|
49
|
-
index % 2 === 0 ? (ac[v] = ac[v] || "") : (ac[all[index - 1]] = v);
|
|
37
|
+
index % 2 === 0 ? (ac[v] = (ac[v] || "").toLowerCase()) : (ac[all[index - 1]] = v);
|
|
50
38
|
return ac;
|
|
51
|
-
}, {});
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
return ac;
|
|
55
|
-
}, {});
|
|
39
|
+
}, {} as Record<string, string>);
|
|
40
|
+
const method = (req.method || "").toUpperCase();
|
|
41
|
+
const resourcePath = path.split("/").slice(1).join("/");
|
|
56
42
|
return {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// @ts-ignore
|
|
63
|
-
path,
|
|
64
|
-
pathParameters: null,
|
|
65
|
-
queryStringParameters,
|
|
66
|
-
multiValueQueryStringParameters,
|
|
67
|
-
stageVariables: null,
|
|
43
|
+
version: "2.0",
|
|
44
|
+
routeKey: `${method} ${resourcePath}`,
|
|
45
|
+
rawPath: path,
|
|
46
|
+
rawQueryString,
|
|
47
|
+
headers,
|
|
68
48
|
requestContext: {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
49
|
+
accountId: "",
|
|
50
|
+
apiId: "",
|
|
51
|
+
domainName: "",
|
|
52
|
+
domainPrefix: "",
|
|
53
|
+
http: {
|
|
54
|
+
method,
|
|
55
|
+
path,
|
|
56
|
+
protocol: "HTTP/1.1",
|
|
57
|
+
sourceIp: headers["x-forwarded-for"],
|
|
58
|
+
userAgent: headers["user-agent"],
|
|
59
|
+
},
|
|
60
|
+
requestId: "",
|
|
61
|
+
routeKey: `${method} ${resourcePath}`,
|
|
62
|
+
stage: "",
|
|
63
|
+
time: "",
|
|
64
|
+
timeEpoch: Math.round(new Date().getTime()/1000)
|
|
65
|
+
},
|
|
66
|
+
body: await readBody(req),
|
|
67
|
+
isBase64Encoded: false
|
|
73
68
|
}
|
|
74
69
|
}
|
|
75
70
|
const node = (opt: Options): Plugin => {
|
|
@@ -80,9 +75,10 @@ const node = (opt: Options): Plugin => {
|
|
|
80
75
|
async (req, res, next) => {
|
|
81
76
|
const ssrModule = await server.ssrLoadModule(path.join(server.config.root, opt.entry));
|
|
82
77
|
const render = ssrModule.handler || ssrModule.default || ssrModule;
|
|
83
|
-
const {statusCode, body,
|
|
84
|
-
const allHeaders = Object.assign({},
|
|
85
|
-
Object.entries(allHeaders).map(([key, value]) => res.setHeader(key, value));
|
|
78
|
+
const {headers, statusCode, body, cookies} = (await render(await incomingMessageAdapter(req), {})) as APIGatewayProxyStructuredResultV2;
|
|
79
|
+
const allHeaders = Object.assign({}, headers || {}) as Record<string, string|string[]>;
|
|
80
|
+
Object.entries(allHeaders).map(([key, value] : [string, string]) => res.setHeader(key, value));
|
|
81
|
+
(cookies || []).forEach((cookie) => res.setHeader("Set-Cookie", cookie));
|
|
86
82
|
res.statusCode = statusCode || 200;
|
|
87
83
|
res.end(body);
|
|
88
84
|
});
|
|
@@ -1329,6 +1329,28 @@
|
|
|
1329
1329
|
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
|
|
1330
1330
|
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
|
|
1331
1331
|
|
|
1332
|
+
"@types/fs-extra@^11.0.4":
|
|
1333
|
+
version "11.0.4"
|
|
1334
|
+
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-11.0.4.tgz#e16a863bb8843fba8c5004362b5a73e17becca45"
|
|
1335
|
+
integrity sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==
|
|
1336
|
+
dependencies:
|
|
1337
|
+
"@types/jsonfile" "*"
|
|
1338
|
+
"@types/node" "*"
|
|
1339
|
+
|
|
1340
|
+
"@types/jsonfile@*":
|
|
1341
|
+
version "6.1.4"
|
|
1342
|
+
resolved "https://registry.yarnpkg.com/@types/jsonfile/-/jsonfile-6.1.4.tgz#614afec1a1164e7d670b4a7ad64df3e7beb7b702"
|
|
1343
|
+
integrity sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==
|
|
1344
|
+
dependencies:
|
|
1345
|
+
"@types/node" "*"
|
|
1346
|
+
|
|
1347
|
+
"@types/node@*":
|
|
1348
|
+
version "22.7.4"
|
|
1349
|
+
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.4.tgz#e35d6f48dca3255ce44256ddc05dee1c23353fcc"
|
|
1350
|
+
integrity sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==
|
|
1351
|
+
dependencies:
|
|
1352
|
+
undici-types "~6.19.2"
|
|
1353
|
+
|
|
1332
1354
|
"@types/node@20":
|
|
1333
1355
|
version "20.14.12"
|
|
1334
1356
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.12.tgz#129d7c3a822cb49fc7ff661235f19cfefd422b49"
|
|
@@ -1952,6 +1974,11 @@ undici-types@~5.26.4:
|
|
|
1952
1974
|
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
|
1953
1975
|
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
|
1954
1976
|
|
|
1977
|
+
undici-types@~6.19.2:
|
|
1978
|
+
version "6.19.8"
|
|
1979
|
+
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
|
|
1980
|
+
integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
|
|
1981
|
+
|
|
1955
1982
|
universalify@^0.2.0:
|
|
1956
1983
|
version "0.2.0"
|
|
1957
1984
|
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
|
|
File without changes
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "template-lambda-api",
|
|
3
|
+
"private": true,
|
|
4
|
+
"author": "webigorkiev",
|
|
5
|
+
"license": "PRIVATE",
|
|
6
|
+
"version": "1.0.1",
|
|
7
|
+
"main": "./index.mts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "vite",
|
|
10
|
+
"serve": "vite",
|
|
11
|
+
"build": "vite build && cd ./dist && yarn",
|
|
12
|
+
"test": "vitest run",
|
|
13
|
+
"test:production": "vitest run -c vitest.config.production.mts",
|
|
14
|
+
"deploy": "yarn build && cd dist && zip -r ../dist.zip ."
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/aws-lambda": "8",
|
|
18
|
+
"@types/fs-extra": "^11.0.4",
|
|
19
|
+
"@types/node": "20",
|
|
20
|
+
"chalk": "^5.3.0",
|
|
21
|
+
"fs-extra": "^11.2.0",
|
|
22
|
+
"jsdom": "^24.1.1",
|
|
23
|
+
"typescript": "5",
|
|
24
|
+
"vite": "5",
|
|
25
|
+
"vitest": "^2.0.4"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@aws-sdk/client-s3": "3"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import {fetch, testConfig} from "../../scripts/test.setup";
|
|
2
|
+
|
|
3
|
+
describe("/", () => {
|
|
4
|
+
const url = new URL(testConfig.apiUrl + "/test-hello-world");
|
|
5
|
+
test(`request GET ${testConfig.apiUrl}/test-hello-world`, async() => {
|
|
6
|
+
const response = await fetch(url.toString());
|
|
7
|
+
expect(response.ok).toEqual(true);
|
|
8
|
+
})
|
|
9
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const env = process.env.TEST_MODE_APP as "test";
|
|
2
|
+
const entryDevelopment = "http://localhost:3000";
|
|
3
|
+
const entryProduction = "https://dpjhcqy0yj.execute-api.eu-central-1.amazonaws.com/default";
|
|
4
|
+
const apiUrl = env === "test" ? entryDevelopment : entryProduction;
|
|
5
|
+
const testConfig = {
|
|
6
|
+
apiUrl,
|
|
7
|
+
apiKey: "vOAwIEMvw01UHaJsVuYrD4Kjg6WzXyc6364dMBcX"
|
|
8
|
+
}
|
|
9
|
+
const defaultHeaders = {
|
|
10
|
+
headers: {
|
|
11
|
+
"user-agent": "fetch-tests",
|
|
12
|
+
"content-type": "application/json",
|
|
13
|
+
"x-api-key": testConfig.apiKey,
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const fetchWrapper = async(
|
|
17
|
+
input: RequestInfo,
|
|
18
|
+
init: RequestInit = {}
|
|
19
|
+
) => fetch(input, Object.assign({}, defaultHeaders, init));
|
|
20
|
+
|
|
21
|
+
export {fetchWrapper as fetch, testConfig};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {createServer, ViteDevServer} from "vite";
|
|
2
|
+
import {testConfig} from "./test.setup.mts";
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
var server: ViteDevServer;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const start = async(resolve: CallableFunction) => {
|
|
9
|
+
try {
|
|
10
|
+
await fetch(`${testConfig.apiUrl}/dev-start'`);
|
|
11
|
+
resolve();
|
|
12
|
+
} catch(e: any) {
|
|
13
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
14
|
+
await start(resolve);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export async function setup() {
|
|
19
|
+
global.server = await createServer();
|
|
20
|
+
await global.server.listen();
|
|
21
|
+
await new Promise(resolve => start(resolve));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function teardown() {
|
|
25
|
+
await global.server.close();
|
|
26
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "esnext",
|
|
4
|
+
"module": "esnext",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"noImplicitThis": true,
|
|
8
|
+
"jsx": "preserve",
|
|
9
|
+
"sourceMap": true,
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"allowSyntheticDefaultImports": true,
|
|
13
|
+
"allowJs": true,
|
|
14
|
+
"noImplicitAny": true,
|
|
15
|
+
"strictFunctionTypes": false,
|
|
16
|
+
"skipLibCheck": true,
|
|
17
|
+
"strictPropertyInitialization": false,
|
|
18
|
+
"experimentalDecorators": true,
|
|
19
|
+
"emitDecoratorMetadata": true,
|
|
20
|
+
"allowImportingTsExtensions": true,
|
|
21
|
+
"lib": [
|
|
22
|
+
"esnext",
|
|
23
|
+
"dom"
|
|
24
|
+
],
|
|
25
|
+
"types": [
|
|
26
|
+
"vite/client",
|
|
27
|
+
"node"
|
|
28
|
+
],
|
|
29
|
+
"baseUrl": ".",
|
|
30
|
+
"paths": {
|
|
31
|
+
"@/*": [
|
|
32
|
+
"./src/*"
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"include": [
|
|
37
|
+
"src/**/*.ts",
|
|
38
|
+
"src/**/*.mts",
|
|
39
|
+
"src/**/*.d.ts",
|
|
40
|
+
"src/**/*.tsx",
|
|
41
|
+
"src/**/*.vue",
|
|
42
|
+
"node_modules/vitest/globals.d.ts"
|
|
43
|
+
],
|
|
44
|
+
"exclude": [
|
|
45
|
+
"dist"
|
|
46
|
+
]
|
|
47
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import {performance} from "node:perf_hooks";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import {build, defineConfig, mergeConfig, Plugin, ResolvedConfig} from "vite";
|
|
6
|
+
import fs from "fs-extra";
|
|
7
|
+
import type {Connect} from "vite";
|
|
8
|
+
import querystring from "node:querystring";
|
|
9
|
+
|
|
10
|
+
interface Options {
|
|
11
|
+
entry: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const cnf = {
|
|
15
|
+
protocol: "http",
|
|
16
|
+
host: "localhost",
|
|
17
|
+
port: 3000,
|
|
18
|
+
};
|
|
19
|
+
const readBody = (req: Connect.IncomingMessage): Promise<string> => {
|
|
20
|
+
return new Promise(resolve => {
|
|
21
|
+
const body: Buffer[] = [];
|
|
22
|
+
req
|
|
23
|
+
.on('data', (chunk: Buffer) => {
|
|
24
|
+
body.push(chunk);
|
|
25
|
+
})
|
|
26
|
+
.on('end', () => {
|
|
27
|
+
resolve(Buffer.concat(body).toString());
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Адаптер для согласованности с AWS Lambda
|
|
33
|
+
const incomingMessageAdapter = async(req: Connect.IncomingMessage): Promise<APIGatewayProxyEvent> => {
|
|
34
|
+
const urlPath = (req.originalUrl || "").split("#")[0];
|
|
35
|
+
const path = urlPath.split('?')[0];
|
|
36
|
+
const queryStringParameters = querystring.parse(urlPath.split('?')[1]);
|
|
37
|
+
const queryStringParametersString = Object.keys(queryStringParameters).reduce((ac, key) => {
|
|
38
|
+
const value = queryStringParameters[key] as string|string[];
|
|
39
|
+
const valueString: string = !Array.isArray(value)
|
|
40
|
+
? value
|
|
41
|
+
: value[value.length - 1]
|
|
42
|
+
ac[key] = ac[key] || valueString;
|
|
43
|
+
return ac;
|
|
44
|
+
}, {} as Record<string, string>);
|
|
45
|
+
const multiValueQueryStringParameters = Object.keys(queryStringParameters).reduce((ac, key) => {
|
|
46
|
+
const value = Array.isArray(queryStringParameters[key]) ? queryStringParameters[key] : [queryStringParameters[key]]
|
|
47
|
+
ac[key] = ac[key] || value;
|
|
48
|
+
return ac;
|
|
49
|
+
}, {} as Record<string, string[]>);
|
|
50
|
+
const headers = (req.rawHeaders || []).reduce((ac, v, index, all) => {
|
|
51
|
+
index % 2 === 0 ? (ac[v] = ac[v] || "") : (ac[all[index - 1]] = v);
|
|
52
|
+
return ac;
|
|
53
|
+
}, {} as Record<string, any>);
|
|
54
|
+
const multiValueHeaders = (req.rawHeaders || []).reduce((ac, v, index, all) => {
|
|
55
|
+
index % 2 === 0 ? (ac[v] = ac[v] || []) : (ac[all[index - 1]].push(v));
|
|
56
|
+
return ac;
|
|
57
|
+
}, {} as Record<string, any>);
|
|
58
|
+
const headersLowerCase = Object.keys(headers).reduce((ac, key) => {
|
|
59
|
+
const value = headers[key];
|
|
60
|
+
ac[key.toLowerCase()] = value;
|
|
61
|
+
return ac;
|
|
62
|
+
}, {} as Record<string, string>);
|
|
63
|
+
return {
|
|
64
|
+
body: await readBody(req),
|
|
65
|
+
headers,
|
|
66
|
+
multiValueHeaders,
|
|
67
|
+
httpMethod: (req.method || "").toUpperCase(),
|
|
68
|
+
isBase64Encoded: false,
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
path,
|
|
71
|
+
pathParameters: null,
|
|
72
|
+
queryStringParameters: queryStringParametersString,
|
|
73
|
+
multiValueQueryStringParameters,
|
|
74
|
+
stageVariables: null,
|
|
75
|
+
requestContext: {
|
|
76
|
+
resourcePath: path.split("/").slice(1).join("/"),
|
|
77
|
+
httpMethod: (req.method || "").toUpperCase(),
|
|
78
|
+
accountId: "",
|
|
79
|
+
apiId: "",
|
|
80
|
+
authorizer: {},
|
|
81
|
+
protocol: "http",
|
|
82
|
+
identity: {
|
|
83
|
+
cognitoIdentityPoolId: null,
|
|
84
|
+
cognitoIdentityId: null,
|
|
85
|
+
apiKey: "",
|
|
86
|
+
principalOrgId: null,
|
|
87
|
+
cognitoAuthenticationType: null,
|
|
88
|
+
userArn: null,
|
|
89
|
+
apiKeyId: "",
|
|
90
|
+
userAgent: headersLowerCase["user-agent"],
|
|
91
|
+
accountId: null,
|
|
92
|
+
caller: null,
|
|
93
|
+
sourceIp: headersLowerCase["x-forwarded-for"],
|
|
94
|
+
accessKey: null,
|
|
95
|
+
cognitoAuthenticationProvider: null,
|
|
96
|
+
user: null,
|
|
97
|
+
clientCert: null
|
|
98
|
+
},
|
|
99
|
+
path,
|
|
100
|
+
stage: "",
|
|
101
|
+
requestId: "",
|
|
102
|
+
requestTimeEpoch: 0,
|
|
103
|
+
resourceId: ""
|
|
104
|
+
}, // Only for production
|
|
105
|
+
resource: path,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const node = (opt: Options): Plugin => {
|
|
109
|
+
return {
|
|
110
|
+
name: "vite-node-js",
|
|
111
|
+
async configureServer(server) {
|
|
112
|
+
return () => server.middlewares.use(
|
|
113
|
+
async (req, res, next) => {
|
|
114
|
+
const ssrModule = await server.ssrLoadModule(path.join(server.config.root, opt.entry));
|
|
115
|
+
const render = ssrModule.handler || ssrModule.default || ssrModule;
|
|
116
|
+
const {statusCode, body, headers, multiValueHeaders} = (await render(await incomingMessageAdapter(req), {})) as APIGatewayProxyResult;
|
|
117
|
+
const allHeaders = Object.assign({}, headers || {}, multiValueHeaders || {}) as Record<string, string|string[]>;
|
|
118
|
+
Object.entries(allHeaders).map(([key, value] : [string, string]) => res.setHeader(key, value));
|
|
119
|
+
res.statusCode = statusCode || 200;
|
|
120
|
+
res.end(body);
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
async configResolved(configVite:ResolvedConfig) {
|
|
124
|
+
const time = performance.now();
|
|
125
|
+
const start = async(resolve: CallableFunction) => {
|
|
126
|
+
try {
|
|
127
|
+
await fetch(`${cnf.protocol}://${cnf.host}:${cnf.port}/start-server`);
|
|
128
|
+
const interval = Math.round((performance.now() - time)/10)/100;
|
|
129
|
+
console.log(chalk.green('dev server running for ') + chalk.red(`${interval}s`) + chalk.green(' at:'));
|
|
130
|
+
console.log(`${cnf.protocol}://${cnf.host}:${cnf.port}`);
|
|
131
|
+
resolve();
|
|
132
|
+
} catch(e: any) {
|
|
133
|
+
await start(resolve);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
if(configVite.command === "build") {
|
|
137
|
+
|
|
138
|
+
// @ts-ignore
|
|
139
|
+
if(!configVite.build.isBuild) {
|
|
140
|
+
await build(mergeConfig({
|
|
141
|
+
build: {
|
|
142
|
+
isBuild: true,
|
|
143
|
+
outDir: path.resolve(configVite.root, `dist`),
|
|
144
|
+
ssr: path.join(configVite.root, opt.entry),
|
|
145
|
+
}
|
|
146
|
+
}, {}));
|
|
147
|
+
const packagePath = path.resolve(configVite.root, "./dist", "./package.json");
|
|
148
|
+
await fs.copy("./package.json", packagePath);
|
|
149
|
+
const pkg = await fs.readJson(packagePath);
|
|
150
|
+
delete(pkg.devDependencies);
|
|
151
|
+
delete(pkg.scripts);
|
|
152
|
+
await fs.writeJson(packagePath, pkg, {
|
|
153
|
+
spaces: 2
|
|
154
|
+
});
|
|
155
|
+
process.exit(0);
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
console.log();
|
|
159
|
+
console.log(chalk.green('dev server starting...'));
|
|
160
|
+
new Promise(resolve => start(resolve));
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
async closeBundle() {}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export default defineConfig({
|
|
168
|
+
resolve: {
|
|
169
|
+
alias: [
|
|
170
|
+
{
|
|
171
|
+
find: /@\/(.*)/,
|
|
172
|
+
replacement: path.resolve("./src") + "/$1"
|
|
173
|
+
}
|
|
174
|
+
],
|
|
175
|
+
},
|
|
176
|
+
server: {
|
|
177
|
+
host: cnf.host,
|
|
178
|
+
port: cnf.port
|
|
179
|
+
},
|
|
180
|
+
optimizeDeps: {
|
|
181
|
+
include:[]
|
|
182
|
+
},
|
|
183
|
+
plugins: [
|
|
184
|
+
node({
|
|
185
|
+
entry: "/src/backend/index.mts"
|
|
186
|
+
})
|
|
187
|
+
]
|
|
188
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/// <reference types="vitest" />
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { defineConfig } from 'vitest/config';
|
|
4
|
+
|
|
5
|
+
process.env.TEST_MODE_APP = "test";
|
|
6
|
+
|
|
7
|
+
export default defineConfig({
|
|
8
|
+
resolve: {
|
|
9
|
+
alias: [
|
|
10
|
+
{
|
|
11
|
+
find: /^~(.+)/,
|
|
12
|
+
replacement: path.resolve('./node_modules') + '/$1',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
find: /@\/(.*)/,
|
|
16
|
+
replacement: path.resolve('./src') + '/$1',
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
plugins: [
|
|
21
|
+
],
|
|
22
|
+
test: {
|
|
23
|
+
root: "./",
|
|
24
|
+
include: ["**/__its__/**/*.(m)?[jt]s?(x)", "**/__tests__/**/*.(m)?[jt]s?(x)", "**/?(*.)+(spec|test).(m)?[jt]s?(x)"],
|
|
25
|
+
exclude: ["**/node_modules/**", "./src/certs/**", "./src/scripts/**", "./src/sql/**", "./src/estimation-client/**"],
|
|
26
|
+
environment: "jsdom",
|
|
27
|
+
globals: true,
|
|
28
|
+
globalSetup: ["./src/scripts/vitest.global.setup.mts"],
|
|
29
|
+
testTimeout: 15000,
|
|
30
|
+
hookTimeout: 15000,
|
|
31
|
+
// threads: false
|
|
32
|
+
// @ts-ignore
|
|
33
|
+
singleThread: true,
|
|
34
|
+
poolOptions: {
|
|
35
|
+
threads: {
|
|
36
|
+
singleThread: true
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
});
|