@tramvai/cli 3.26.3 → 3.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/shared/providers/selfSignedCertificateProvider.d.ts +3 -0
- package/lib/api/shared/providers/selfSignedCertificateProvider.d.ts.map +1 -0
- package/lib/api/shared/providers/selfSignedCertificateProvider.js +27 -0
- package/lib/api/shared/providers/selfSignedCertificateProvider.js.map +1 -0
- package/lib/api/shared/types/base.d.ts +4 -0
- package/lib/api/shared/types/base.d.ts.map +1 -1
- package/lib/api/shared/utils/selfSignedCertificate/certificatedHostsList.d.ts +4 -0
- package/lib/api/shared/utils/selfSignedCertificate/certificatedHostsList.d.ts.map +1 -0
- package/lib/api/shared/utils/selfSignedCertificate/certificatedHostsList.js +22 -0
- package/lib/api/shared/utils/selfSignedCertificate/certificatedHostsList.js.map +1 -0
- package/lib/api/shared/utils/selfSignedCertificate/common.d.ts +3 -0
- package/lib/api/shared/utils/selfSignedCertificate/common.d.ts.map +1 -0
- package/lib/api/shared/utils/selfSignedCertificate/common.js +8 -0
- package/lib/api/shared/utils/selfSignedCertificate/common.js.map +1 -0
- package/lib/api/shared/utils/selfSignedCertificate/createSelfSignedCertificate.d.ts +9 -0
- package/lib/api/shared/utils/selfSignedCertificate/createSelfSignedCertificate.d.ts.map +1 -0
- package/lib/api/shared/utils/selfSignedCertificate/createSelfSignedCertificate.js +64 -0
- package/lib/api/shared/utils/selfSignedCertificate/createSelfSignedCertificate.js.map +1 -0
- package/lib/api/shared/utils/selfSignedCertificate/getHosts.d.ts +3 -0
- package/lib/api/shared/utils/selfSignedCertificate/getHosts.d.ts.map +1 -0
- package/lib/api/shared/utils/selfSignedCertificate/getHosts.js +32 -0
- package/lib/api/shared/utils/selfSignedCertificate/getHosts.js.map +1 -0
- package/lib/api/start/index.d.ts +3 -0
- package/lib/api/start/index.d.ts.map +1 -1
- package/lib/api/start/index.js.map +1 -1
- package/lib/api/start/providers/application/server.d.ts.map +1 -1
- package/lib/api/start/providers/application/server.js +14 -3
- package/lib/api/start/providers/application/server.js.map +1 -1
- package/lib/api/start/providers/application/shared.d.ts.map +1 -1
- package/lib/api/start/providers/application/shared.js +11 -1
- package/lib/api/start/providers/application/shared.js.map +1 -1
- package/lib/api/start/utils/banner.d.ts.map +1 -1
- package/lib/api/start/utils/banner.js +8 -2
- package/lib/api/start/utils/banner.js.map +1 -1
- package/lib/api/start/utils/createServer.d.ts +3 -1
- package/lib/api/start/utils/createServer.d.ts.map +1 -1
- package/lib/api/start/utils/createServer.js +16 -1
- package/lib/api/start/utils/createServer.js.map +1 -1
- package/lib/api/start-prod/providers/application.d.ts.map +1 -1
- package/lib/api/start-prod/providers/application.js +24 -3
- package/lib/api/start-prod/providers/application.js.map +1 -1
- package/lib/api/start-prod/providers/child-app.d.ts.map +1 -1
- package/lib/api/start-prod/providers/child-app.js +5 -0
- package/lib/api/start-prod/providers/child-app.js.map +1 -1
- package/lib/api/start-prod/providers/shared.d.ts.map +1 -1
- package/lib/api/start-prod/providers/shared.js +0 -5
- package/lib/api/start-prod/providers/shared.js.map +1 -1
- package/lib/builder/webpack/devServer/server.d.ts.map +1 -1
- package/lib/builder/webpack/devServer/server.js +6 -1
- package/lib/builder/webpack/devServer/server.js.map +1 -1
- package/lib/builder/webpack/tokens.d.ts +3 -0
- package/lib/builder/webpack/tokens.d.ts.map +1 -1
- package/lib/commands/start/command.d.ts.map +1 -1
- package/lib/commands/start/command.js +16 -0
- package/lib/commands/start/command.js.map +1 -1
- package/lib/commands/start-prod/command.d.ts.map +1 -1
- package/lib/commands/start-prod/command.js +16 -0
- package/lib/commands/start-prod/command.js.map +1 -1
- package/lib/commands/static/application.d.ts.map +1 -1
- package/lib/commands/static/application.js +1 -1
- package/lib/commands/static/application.js.map +1 -1
- package/lib/config/configManager.d.ts +2 -0
- package/lib/config/configManager.d.ts.map +1 -1
- package/lib/config/configManager.js +2 -2
- package/lib/config/configManager.js.map +1 -1
- package/lib/di/tokens/config.d.ts +1 -0
- package/lib/di/tokens/config.d.ts.map +1 -1
- package/lib/di/tokens/server.d.ts +6 -0
- package/lib/di/tokens/server.d.ts.map +1 -1
- package/lib/di/tokens/server.js +2 -1
- package/lib/di/tokens/server.js.map +1 -1
- package/lib/library/webpack/application/client/dev.d.ts.map +1 -1
- package/lib/library/webpack/application/client/dev.js +6 -1
- package/lib/library/webpack/application/client/dev.js.map +1 -1
- package/lib/library/webpack/application/server/dev.d.ts.map +1 -1
- package/lib/library/webpack/application/server/dev.js +6 -1
- package/lib/library/webpack/application/server/dev.js.map +1 -1
- package/lib/utils/getApplicationUrl.d.ts +6 -0
- package/lib/utils/getApplicationUrl.d.ts.map +1 -0
- package/lib/utils/getApplicationUrl.js +8 -0
- package/lib/utils/getApplicationUrl.js.map +1 -0
- package/package.json +2 -2
- package/src/api/shared/providers/selfSignedCertificateProvider.ts +29 -0
- package/src/api/shared/types/base.ts +5 -0
- package/src/api/shared/utils/selfSignedCertificate/certificatedHostsList.ts +22 -0
- package/src/api/shared/utils/selfSignedCertificate/common.ts +4 -0
- package/src/api/shared/utils/selfSignedCertificate/createSelfSignedCertificate.spec.ts +154 -0
- package/src/api/shared/utils/selfSignedCertificate/createSelfSignedCertificate.ts +99 -0
- package/src/api/shared/utils/selfSignedCertificate/getHosts.ts +31 -0
- package/src/api/start/index.ts +3 -0
- package/src/api/start/providers/application/server.ts +21 -5
- package/src/api/start/providers/application/shared.ts +12 -2
- package/src/api/start/utils/banner.ts +12 -4
- package/src/api/start/utils/createServer.ts +19 -1
- package/src/api/start-prod/providers/application.ts +27 -3
- package/src/api/start-prod/providers/child-app.ts +6 -0
- package/src/api/start-prod/providers/shared.ts +0 -5
- package/src/builder/webpack/devServer/server.ts +6 -1
- package/src/commands/start/command.ts +16 -0
- package/src/commands/start-prod/command.ts +16 -0
- package/src/commands/static/application.ts +3 -1
- package/src/config/configManager.ts +7 -4
- package/src/di/tokens/server.ts +5 -0
- package/src/library/webpack/application/client/dev.ts +6 -3
- package/src/library/webpack/application/server/dev.ts +6 -3
- package/src/utils/getApplicationUrl.ts +11 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import os from 'os';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import child_process from 'child_process';
|
|
5
|
+
|
|
6
|
+
import { createSelfSignedCertificate } from './createSelfSignedCertificate';
|
|
7
|
+
import { certificatedHostsListFilePath } from './certificatedHostsList';
|
|
8
|
+
import { certificateDirectoryPath } from './common';
|
|
9
|
+
|
|
10
|
+
const defaultKeyPath = path.resolve(certificateDirectoryPath, 'localhost-key.pem');
|
|
11
|
+
const defaultCertificatePath = path.resolve(certificateDirectoryPath, 'localhost.pem');
|
|
12
|
+
const gitignorePath = path.resolve(process.cwd(), '.gitignore');
|
|
13
|
+
const customHost = 'localhost.domain.com';
|
|
14
|
+
|
|
15
|
+
jest.mock('os', () => {
|
|
16
|
+
return {
|
|
17
|
+
networkInterfaces: (param: string) => {
|
|
18
|
+
return [];
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const existsSyncSpy = jest.spyOn(fs, 'existsSync');
|
|
24
|
+
const mkdirSyncSpy = jest.spyOn(fs, 'mkdirSync');
|
|
25
|
+
const writeFileSyncSpy = jest.spyOn(fs, 'writeFileSync');
|
|
26
|
+
const readFileSyncSpy = jest.spyOn(fs, 'readFileSync');
|
|
27
|
+
const execSyncSpy = jest.spyOn(child_process, 'execSync');
|
|
28
|
+
const appendFileSyncSpy = jest.spyOn(fs, 'appendFileSync');
|
|
29
|
+
|
|
30
|
+
describe('shared/utils/selfSignedCertificate', () => {
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
writeFileSyncSpy.mockImplementation(() => undefined);
|
|
33
|
+
mkdirSyncSpy.mockImplementation(() => {
|
|
34
|
+
return undefined;
|
|
35
|
+
});
|
|
36
|
+
execSyncSpy.mockImplementation((command) => {
|
|
37
|
+
if (command === 'mkcert -CAROOT') return '/location';
|
|
38
|
+
return '';
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
readFileSyncSpy.mockImplementation((path) => {
|
|
42
|
+
if (path === gitignorePath) return '';
|
|
43
|
+
return `localhost,${customHost}`;
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
afterEach(() => {
|
|
47
|
+
jest.clearAllMocks();
|
|
48
|
+
existsSyncSpy.mockReset();
|
|
49
|
+
mkdirSyncSpy.mockReset();
|
|
50
|
+
writeFileSyncSpy.mockReset();
|
|
51
|
+
execSyncSpy.mockReset();
|
|
52
|
+
});
|
|
53
|
+
it('should generate certificate', async () => {
|
|
54
|
+
existsSyncSpy.mockImplementation((path) => {
|
|
55
|
+
if (path === certificatedHostsListFilePath || path === gitignorePath) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const result = createSelfSignedCertificate({});
|
|
62
|
+
|
|
63
|
+
expect(execSyncSpy).toHaveBeenNthCalledWith(
|
|
64
|
+
1,
|
|
65
|
+
`mkcert -install -key-file "${defaultKeyPath}" -cert-file "${defaultCertificatePath}" localhost`
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
expect(result).toEqual({
|
|
69
|
+
keyPath: defaultKeyPath,
|
|
70
|
+
certificatePath: defaultCertificatePath,
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
it('should generate certificate for provided host', async () => {
|
|
74
|
+
existsSyncSpy.mockImplementation((path) => {
|
|
75
|
+
if (path === certificatedHostsListFilePath || path === gitignorePath) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
});
|
|
80
|
+
const result = createSelfSignedCertificate({ host: customHost });
|
|
81
|
+
expect(execSyncSpy).toHaveBeenNthCalledWith(
|
|
82
|
+
1,
|
|
83
|
+
`mkcert -install -key-file "${defaultKeyPath}" -cert-file "${defaultCertificatePath}" localhost ${customHost}`
|
|
84
|
+
);
|
|
85
|
+
expect(result).toEqual({
|
|
86
|
+
keyPath: defaultKeyPath,
|
|
87
|
+
certificatePath: defaultCertificatePath,
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should return already existed certificate if it was generated previously', async () => {
|
|
92
|
+
existsSyncSpy.mockImplementation((path) => {
|
|
93
|
+
if (path === gitignorePath) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
});
|
|
98
|
+
const result = createSelfSignedCertificate({ host: customHost });
|
|
99
|
+
expect(execSyncSpy).toHaveBeenCalledTimes(0);
|
|
100
|
+
|
|
101
|
+
expect(result).toEqual({
|
|
102
|
+
keyPath: defaultKeyPath,
|
|
103
|
+
certificatePath: defaultCertificatePath,
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('should use custom certificate if provided', () => {
|
|
108
|
+
const customCertificate = {
|
|
109
|
+
certificatePath: path.resolve('path-to-custom-certificate/cert.pem'),
|
|
110
|
+
keyPath: path.resolve('path-to-custom-certificate/key.pem'),
|
|
111
|
+
};
|
|
112
|
+
const result = createSelfSignedCertificate({
|
|
113
|
+
host: customHost,
|
|
114
|
+
...customCertificate,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
expect(execSyncSpy).toHaveBeenCalledTimes(0);
|
|
118
|
+
|
|
119
|
+
expect(result).toEqual({
|
|
120
|
+
keyPath: customCertificate.keyPath,
|
|
121
|
+
certificatePath: customCertificate.certificatePath,
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
it('if a new host be provided, a new certificate should be generated even if a certificate already exists.', () => {
|
|
125
|
+
existsSyncSpy.mockImplementation((path) => {
|
|
126
|
+
if (path === gitignorePath) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
});
|
|
131
|
+
const result = createSelfSignedCertificate({ host: 'new.localhost.domain' });
|
|
132
|
+
expect(execSyncSpy).toHaveBeenNthCalledWith(
|
|
133
|
+
1,
|
|
134
|
+
`mkcert -install -key-file "${defaultKeyPath}" -cert-file "${defaultCertificatePath}" localhost new.localhost.domain`
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
expect(result).toEqual({
|
|
138
|
+
keyPath: defaultKeyPath,
|
|
139
|
+
certificatePath: defaultCertificatePath,
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
it('should add certificates folder to .gitignore if .gitignore file exist', () => {
|
|
143
|
+
existsSyncSpy.mockImplementation((path) => {
|
|
144
|
+
return true;
|
|
145
|
+
});
|
|
146
|
+
const result = createSelfSignedCertificate({ host: 'new.localhost.domain' });
|
|
147
|
+
expect(appendFileSyncSpy).toBeCalledTimes(1);
|
|
148
|
+
|
|
149
|
+
expect(result).toEqual({
|
|
150
|
+
keyPath: defaultKeyPath,
|
|
151
|
+
certificatePath: defaultCertificatePath,
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
});
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import type { Certificate } from '../../types/base';
|
|
6
|
+
import { getHosts } from './getHosts';
|
|
7
|
+
import { certificateDirectoryPath, certificateDirectory } from './common';
|
|
8
|
+
import {
|
|
9
|
+
createCertificatedHostsListFile,
|
|
10
|
+
readCertificatedHostsListFile,
|
|
11
|
+
} from './certificatedHostsList';
|
|
12
|
+
|
|
13
|
+
interface CreateSelfSignedCertificateOptions {
|
|
14
|
+
host?: string;
|
|
15
|
+
keyPath?: string;
|
|
16
|
+
certificatePath?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// eslint-disable-next-line max-statements
|
|
20
|
+
export const createSelfSignedCertificate = (
|
|
21
|
+
options: CreateSelfSignedCertificateOptions
|
|
22
|
+
): Certificate => {
|
|
23
|
+
try {
|
|
24
|
+
const { host } = options;
|
|
25
|
+
const hosts = getHosts(host === '0.0.0.0' ? null : host);
|
|
26
|
+
const hostsFile = readCertificatedHostsListFile();
|
|
27
|
+
|
|
28
|
+
const defaultKeyPath = path.resolve(certificateDirectoryPath, 'localhost-key.pem');
|
|
29
|
+
const defaultCertificatePath = path.resolve(certificateDirectoryPath, 'localhost.pem');
|
|
30
|
+
|
|
31
|
+
const keyPath = options.keyPath ? path.resolve(options.keyPath) : defaultKeyPath;
|
|
32
|
+
const certificatePath = options.certificatePath
|
|
33
|
+
? path.resolve(options.certificatePath)
|
|
34
|
+
: defaultCertificatePath;
|
|
35
|
+
|
|
36
|
+
// check if certificates are already generated, in this case we simply skip step
|
|
37
|
+
|
|
38
|
+
const isExternalCertificateProvided = options.certificatePath && options.keyPath;
|
|
39
|
+
|
|
40
|
+
const isCertificateAlreadyExist =
|
|
41
|
+
!isExternalCertificateProvided &&
|
|
42
|
+
fs.existsSync(keyPath) &&
|
|
43
|
+
fs.existsSync(certificatePath) &&
|
|
44
|
+
hostsFile &&
|
|
45
|
+
hosts.every((h) => hostsFile.has(h));
|
|
46
|
+
|
|
47
|
+
const gitignorePath = path.resolve(process.cwd(), '.gitignore');
|
|
48
|
+
if (
|
|
49
|
+
fs.existsSync(gitignorePath) &&
|
|
50
|
+
!fs.readFileSync(gitignorePath, 'utf-8').includes(certificateDirectory)
|
|
51
|
+
) {
|
|
52
|
+
fs.appendFileSync(gitignorePath, `\n${certificateDirectory}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (isExternalCertificateProvided || isCertificateAlreadyExist) {
|
|
56
|
+
console.log(
|
|
57
|
+
chalk.blue(
|
|
58
|
+
'Certificates for https environment are already exist, skipping step with certificate generation'
|
|
59
|
+
)
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
keyPath,
|
|
64
|
+
certificatePath,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
fs.mkdirSync(certificateDirectoryPath, { recursive: true });
|
|
69
|
+
createCertificatedHostsListFile(hosts);
|
|
70
|
+
|
|
71
|
+
// TODO: maybe it is better to install mkcert for users for better dx
|
|
72
|
+
// check https://github.com/liuweiGL/vite-plugin-mkcert/blob/main/plugin/index.ts and https://github.com/vercel/next.js/blob/28fdc367b1f6d41245ea036bc40d1035a8a4d0e4/packages/next/src/lib/mkcert.ts#L68
|
|
73
|
+
execSync(
|
|
74
|
+
`mkcert -install -key-file "${keyPath}" -cert-file "${certificatePath}" ${hosts.join(' ')}`
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
if (!fs.existsSync(keyPath) || !fs.existsSync(certificatePath)) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
'Error occured while certificate creation. Generated certificate files not found'
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const CAROOTFileLocation = execSync('mkcert -CAROOT').toString().trim();
|
|
84
|
+
|
|
85
|
+
console.log(chalk.green(`Root certificate located in ${chalk.blue(CAROOTFileLocation)}`));
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
keyPath,
|
|
89
|
+
certificatePath,
|
|
90
|
+
};
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error(
|
|
93
|
+
chalk.red(
|
|
94
|
+
`Error while generating the certificate. The mkcert tool may not be installed please check and install it if that is the case.`
|
|
95
|
+
)
|
|
96
|
+
);
|
|
97
|
+
throw new Error(error);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import os from 'os';
|
|
2
|
+
|
|
3
|
+
export const getDefaultHosts = () => {
|
|
4
|
+
const defaultHosts = ['localhost'];
|
|
5
|
+
const networkInterfaces = os.networkInterfaces();
|
|
6
|
+
|
|
7
|
+
for (const networkInterfaceKey in networkInterfaces) {
|
|
8
|
+
const networkInterfacesInfo = networkInterfaces[networkInterfaceKey];
|
|
9
|
+
|
|
10
|
+
if (networkInterfacesInfo) {
|
|
11
|
+
for (const info of networkInterfacesInfo) {
|
|
12
|
+
// https://github.com/nodejs/node/issues/42787
|
|
13
|
+
//@ts-expect-error
|
|
14
|
+
if (info.family === 'IPv4' || info.family === '4') {
|
|
15
|
+
defaultHosts.push(info.address);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return defaultHosts;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const getHosts = (host?: string) => {
|
|
25
|
+
const hosts = new Set([...getDefaultHosts()]);
|
|
26
|
+
|
|
27
|
+
if (host && !hosts.has(host)) {
|
|
28
|
+
hosts.add(host);
|
|
29
|
+
}
|
|
30
|
+
return Array.from(hosts);
|
|
31
|
+
};
|
package/src/api/start/index.ts
CHANGED
|
@@ -11,6 +11,9 @@ import type { Builder } from '../../typings/build/Builder';
|
|
|
11
11
|
|
|
12
12
|
export type Params = WithConfig<{
|
|
13
13
|
buildType?: 'server' | 'client' | 'all';
|
|
14
|
+
https?: boolean;
|
|
15
|
+
httpsKey?: string;
|
|
16
|
+
httpsCert?: string;
|
|
14
17
|
host?: string;
|
|
15
18
|
port?: number;
|
|
16
19
|
staticPort?: number;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import type { Provider } from '@tinkoff/dippy';
|
|
2
2
|
import { provide } from '@tinkoff/dippy';
|
|
3
|
-
|
|
3
|
+
import { readFileSync } from 'fs';
|
|
4
|
+
import { createProxyServer } from 'http-proxy';
|
|
4
5
|
import { INIT_HANDLER_TOKEN, CLOSE_HANDLER_TOKEN } from '../../tokens';
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
CONFIG_MANAGER_TOKEN,
|
|
8
|
+
SELF_SIGNED_CERTIFICATE_TOKEN,
|
|
9
|
+
SERVER_TOKEN,
|
|
10
|
+
} from '../../../../di/tokens';
|
|
6
11
|
import { stopServer } from '../../utils/stopServer';
|
|
7
12
|
import { createServer } from '../../utils/createServer';
|
|
8
13
|
import { listenServer } from '../../utils/listenServer';
|
|
@@ -10,14 +15,24 @@ import { listenServer } from '../../utils/listenServer';
|
|
|
10
15
|
export const serverProviders: readonly Provider[] = [
|
|
11
16
|
provide({
|
|
12
17
|
provide: SERVER_TOKEN,
|
|
13
|
-
useFactory:
|
|
18
|
+
useFactory: ({ selfSignedCertificate }) => {
|
|
19
|
+
return createServer(selfSignedCertificate);
|
|
20
|
+
},
|
|
21
|
+
deps: {
|
|
22
|
+
selfSignedCertificate: {
|
|
23
|
+
token: SELF_SIGNED_CERTIFICATE_TOKEN,
|
|
24
|
+
optional: true,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
14
27
|
}),
|
|
15
28
|
provide({
|
|
16
29
|
provide: INIT_HANDLER_TOKEN,
|
|
17
30
|
multi: true,
|
|
18
|
-
useFactory: ({ server, configManager }) => {
|
|
31
|
+
useFactory: ({ server, configManager, selfSignedCertificate }) => {
|
|
19
32
|
return async function staticServerListen() {
|
|
20
|
-
const {
|
|
33
|
+
const { https } = configManager;
|
|
34
|
+
const port = https && configManager.host !== '0.0.0.0' ? 443 : configManager.port;
|
|
35
|
+
const host = https ? '0.0.0.0' : configManager.host;
|
|
21
36
|
|
|
22
37
|
await listenServer(server, host, port);
|
|
23
38
|
};
|
|
@@ -25,6 +40,7 @@ export const serverProviders: readonly Provider[] = [
|
|
|
25
40
|
deps: {
|
|
26
41
|
server: SERVER_TOKEN,
|
|
27
42
|
configManager: CONFIG_MANAGER_TOKEN,
|
|
43
|
+
selfSignedCertificate: SELF_SIGNED_CERTIFICATE_TOKEN,
|
|
28
44
|
},
|
|
29
45
|
}),
|
|
30
46
|
provide({
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Provider } from '@tinkoff/dippy';
|
|
2
2
|
import { provide } from '@tinkoff/dippy';
|
|
3
|
-
|
|
4
3
|
import { CLOSE_HANDLER_TOKEN, INIT_HANDLER_TOKEN } from '../../tokens';
|
|
5
4
|
import {
|
|
6
5
|
CONFIG_MANAGER_TOKEN,
|
|
@@ -8,14 +7,17 @@ import {
|
|
|
8
7
|
COMMAND_PARAMETERS_TOKEN,
|
|
9
8
|
STATIC_SERVER_TOKEN,
|
|
10
9
|
PORT_MANAGER_TOKEN,
|
|
10
|
+
SELF_SIGNED_CERTIFICATE_TOKEN,
|
|
11
11
|
} from '../../../../di/tokens';
|
|
12
12
|
import { stopServer } from '../../utils/stopServer';
|
|
13
13
|
import type { ApplicationConfigEntry } from '../../../../typings/configEntry/application';
|
|
14
14
|
import { createConfigManager } from '../../../../config/configManager';
|
|
15
15
|
import { createServer } from '../../utils/createServer';
|
|
16
16
|
import { listenServer } from '../../utils/listenServer';
|
|
17
|
+
import { selfSignedCertificateProvider } from '../../../shared/providers/selfSignedCertificateProvider';
|
|
17
18
|
|
|
18
19
|
export const sharedProviders: readonly Provider[] = [
|
|
20
|
+
...selfSignedCertificateProvider,
|
|
19
21
|
provide({
|
|
20
22
|
provide: CONFIG_MANAGER_TOKEN,
|
|
21
23
|
useFactory: ({ configEntry, parameters, portManager }) =>
|
|
@@ -34,7 +36,15 @@ export const sharedProviders: readonly Provider[] = [
|
|
|
34
36
|
}),
|
|
35
37
|
provide({
|
|
36
38
|
provide: STATIC_SERVER_TOKEN,
|
|
37
|
-
useFactory:
|
|
39
|
+
useFactory: ({ selfSignedCertificate }) => {
|
|
40
|
+
return createServer(selfSignedCertificate);
|
|
41
|
+
},
|
|
42
|
+
deps: {
|
|
43
|
+
selfSignedCertificate: {
|
|
44
|
+
token: SELF_SIGNED_CERTIFICATE_TOKEN,
|
|
45
|
+
optional: true,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
38
48
|
}),
|
|
39
49
|
provide({
|
|
40
50
|
provide: INIT_HANDLER_TOKEN,
|
|
@@ -8,6 +8,7 @@ import { isApplication } from '../../../config/validate';
|
|
|
8
8
|
const label = (name) => chalk.bold.cyan(`▸ ${name}:`);
|
|
9
9
|
const link = (url) => chalk.underline.blue(url);
|
|
10
10
|
|
|
11
|
+
// eslint-disable-next-line max-statements
|
|
11
12
|
export function showBanner(di: Container) {
|
|
12
13
|
if (!di.get({ token: UI_SHOW_BANNER_TOKEN, optional: true })) {
|
|
13
14
|
return;
|
|
@@ -31,14 +32,21 @@ export function showBanner(di: Container) {
|
|
|
31
32
|
titleLines.push(`${label('FileSystemPages')} true`);
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
// TODO: add information about hosted url !
|
|
36
|
+
const baseServerUrl = `${config.httpProtocol}://${config.host.replace('0.0.0.0', 'localhost')}`;
|
|
37
|
+
const server = `${baseServerUrl}:${config.port}`;
|
|
38
|
+
|
|
39
|
+
const staticServer = `${config.httpProtocol}://${config.staticHost.replace(
|
|
40
|
+
'0.0.0.0',
|
|
41
|
+
'localhost'
|
|
42
|
+
)}:${config.staticPort}`;
|
|
38
43
|
|
|
39
44
|
if (config.type === 'application') {
|
|
40
45
|
// Listeners
|
|
41
46
|
messageLines.push(chalk.bold('Static: ') + link(staticServer));
|
|
47
|
+
if (config.host !== '0.0.0.0' && config.https) {
|
|
48
|
+
messageLines.push(chalk.bold('App: ') + link(baseServerUrl));
|
|
49
|
+
}
|
|
42
50
|
messageLines.push(chalk.bold('App: ') + link(server));
|
|
43
51
|
}
|
|
44
52
|
|
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import { createServer as httpCreateServer } from 'http';
|
|
2
|
+
import { createServer as httpsCreateServer } from 'https';
|
|
3
|
+
import { readFileSync } from 'fs';
|
|
2
4
|
import stoppable from 'stoppable';
|
|
5
|
+
import type { Certificate } from '../../shared/types/base';
|
|
3
6
|
|
|
4
|
-
|
|
7
|
+
const createHttpsServer = ({ keyPath, certificatePath }: Certificate) => {
|
|
8
|
+
const options = {
|
|
9
|
+
key: readFileSync(keyPath),
|
|
10
|
+
cert: readFileSync(certificatePath),
|
|
11
|
+
};
|
|
12
|
+
const httpsServer = httpsCreateServer(options);
|
|
13
|
+
return stoppable(httpsServer, 0);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const createHttpServer = () => {
|
|
5
17
|
const server = httpCreateServer();
|
|
6
18
|
|
|
7
19
|
return stoppable(server, 0);
|
|
8
20
|
};
|
|
21
|
+
|
|
22
|
+
export const createServer = (certificate?: Certificate) => {
|
|
23
|
+
return certificate && certificate?.certificatePath && certificate?.keyPath
|
|
24
|
+
? createHttpsServer(certificate)
|
|
25
|
+
: createHttpServer();
|
|
26
|
+
};
|
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
CONFIG_ENTRY_TOKEN,
|
|
8
8
|
CONFIG_MANAGER_TOKEN,
|
|
9
9
|
PORT_MANAGER_TOKEN,
|
|
10
|
+
SELF_SIGNED_CERTIFICATE_TOKEN,
|
|
11
|
+
STATIC_SERVER_TOKEN,
|
|
10
12
|
} from '../../../di/tokens';
|
|
11
13
|
import type { ApplicationConfigEntry } from '../../../typings/configEntry/application';
|
|
12
14
|
import { CLOSE_HANDLER_TOKEN, SERVER_PROCESS_TOKEN } from '../tokens';
|
|
@@ -14,8 +16,23 @@ import { DEBUG_ARGV } from '../../../config/constants';
|
|
|
14
16
|
import { safeRequire } from '../../../utils/safeRequire';
|
|
15
17
|
import type { ConfigManager } from '../../../config/configManager';
|
|
16
18
|
import { createConfigManager } from '../../../config/configManager';
|
|
19
|
+
import { selfSignedCertificateProvider } from '../../shared/providers/selfSignedCertificateProvider';
|
|
20
|
+
import { createServer } from '../../start/utils/createServer';
|
|
17
21
|
|
|
18
22
|
export const applicationsProviders: readonly Provider[] = [
|
|
23
|
+
...selfSignedCertificateProvider,
|
|
24
|
+
provide({
|
|
25
|
+
provide: STATIC_SERVER_TOKEN,
|
|
26
|
+
useFactory: ({ selfSignedCertificate }) => {
|
|
27
|
+
return createServer(selfSignedCertificate);
|
|
28
|
+
},
|
|
29
|
+
deps: {
|
|
30
|
+
selfSignedCertificate: {
|
|
31
|
+
token: SELF_SIGNED_CERTIFICATE_TOKEN,
|
|
32
|
+
optional: true,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
}),
|
|
19
36
|
provide({
|
|
20
37
|
provide: CONFIG_MANAGER_TOKEN,
|
|
21
38
|
useFactory: ({ configEntry, parameters, portManager }) =>
|
|
@@ -35,16 +52,15 @@ export const applicationsProviders: readonly Provider[] = [
|
|
|
35
52
|
}),
|
|
36
53
|
provide({
|
|
37
54
|
provide: SERVER_PROCESS_TOKEN,
|
|
38
|
-
useFactory: ({ configManager, parameters }) => {
|
|
55
|
+
useFactory: ({ configManager, parameters, selfSignedCertificate }) => {
|
|
39
56
|
const { env } = parameters;
|
|
40
57
|
const serverConfigManager = (
|
|
41
58
|
configManager as ConfigManager<ApplicationConfigEntry>
|
|
42
59
|
).withSettings({
|
|
43
60
|
buildType: 'server',
|
|
44
61
|
});
|
|
45
|
-
const { debug, port, assetsPrefix } = serverConfigManager;
|
|
62
|
+
const { debug, port, assetsPrefix, https } = serverConfigManager;
|
|
46
63
|
const root = serverConfigManager.buildPath;
|
|
47
|
-
|
|
48
64
|
return fork(path.resolve(root, 'server.js'), [], {
|
|
49
65
|
execArgv: debug ? DEBUG_ARGV : [],
|
|
50
66
|
cwd: root,
|
|
@@ -58,12 +74,20 @@ export const applicationsProviders: readonly Provider[] = [
|
|
|
58
74
|
PORT: `${port}`,
|
|
59
75
|
PORT_SERVER: `${port}`,
|
|
60
76
|
ASSETS_PREFIX: assetsPrefix,
|
|
77
|
+
HOST: serverConfigManager.host,
|
|
78
|
+
HTTPS: serverConfigManager.https
|
|
79
|
+
? JSON.stringify({
|
|
80
|
+
key: selfSignedCertificate.keyPath,
|
|
81
|
+
cert: selfSignedCertificate.certificatePath,
|
|
82
|
+
})
|
|
83
|
+
: null,
|
|
61
84
|
},
|
|
62
85
|
});
|
|
63
86
|
},
|
|
64
87
|
deps: {
|
|
65
88
|
configManager: CONFIG_MANAGER_TOKEN,
|
|
66
89
|
parameters: COMMAND_PARAMETERS_TOKEN,
|
|
90
|
+
selfSignedCertificate: SELF_SIGNED_CERTIFICATE_TOKEN,
|
|
67
91
|
},
|
|
68
92
|
}),
|
|
69
93
|
provide({
|
|
@@ -5,11 +5,17 @@ import {
|
|
|
5
5
|
CONFIG_ENTRY_TOKEN,
|
|
6
6
|
CONFIG_MANAGER_TOKEN,
|
|
7
7
|
PORT_MANAGER_TOKEN,
|
|
8
|
+
STATIC_SERVER_TOKEN,
|
|
8
9
|
} from '../../../di/tokens';
|
|
9
10
|
import { createConfigManager } from '../../../config/configManager';
|
|
10
11
|
import type { ChildAppConfigEntry } from '../../../typings/configEntry/child-app';
|
|
12
|
+
import { createServer } from '../../start/utils/createServer';
|
|
11
13
|
|
|
12
14
|
export const childAppProviders: readonly Provider[] = [
|
|
15
|
+
provide({
|
|
16
|
+
provide: STATIC_SERVER_TOKEN,
|
|
17
|
+
useFactory: createServer,
|
|
18
|
+
}),
|
|
13
19
|
provide({
|
|
14
20
|
provide: CONFIG_MANAGER_TOKEN,
|
|
15
21
|
useFactory: ({ configEntry, parameters, portManager }) =>
|
|
@@ -6,16 +6,11 @@ import fastifyStatic from '@fastify/static';
|
|
|
6
6
|
import zlib from 'zlib';
|
|
7
7
|
import { CLOSE_HANDLER_TOKEN, INIT_HANDLER_TOKEN, PROCESS_HANDLER_TOKEN } from '../tokens';
|
|
8
8
|
import { CONFIG_MANAGER_TOKEN, PORT_MANAGER_TOKEN, STATIC_SERVER_TOKEN } from '../../../di/tokens';
|
|
9
|
-
import { createServer } from '../../start/utils/createServer';
|
|
10
9
|
import { stopServer } from '../../start/utils/stopServer';
|
|
11
10
|
import { listenServer } from '../../start/utils/listenServer';
|
|
12
11
|
import { isApplication, isChildApp } from '../../../config/validate';
|
|
13
12
|
|
|
14
13
|
export const sharedProviders: readonly Provider[] = [
|
|
15
|
-
provide({
|
|
16
|
-
provide: STATIC_SERVER_TOKEN,
|
|
17
|
-
useFactory: createServer,
|
|
18
|
-
}),
|
|
19
14
|
provide({
|
|
20
15
|
provide: INIT_HANDLER_TOKEN,
|
|
21
16
|
multi: true,
|
|
@@ -17,6 +17,7 @@ import { ThreadWorkerBridge } from './pool/thread/pool';
|
|
|
17
17
|
import { createWorkerPool } from './pool/pool';
|
|
18
18
|
import type { SERVER_TOKEN } from '../../../di/tokens';
|
|
19
19
|
import { CLOSE_HANDLER_TOKEN } from '../tokens';
|
|
20
|
+
import { getApplicationUrl } from '../../../utils/getApplicationUrl';
|
|
20
21
|
|
|
21
22
|
const EXITED_UNEXPECTEDLY = `
|
|
22
23
|
|
|
@@ -59,7 +60,11 @@ export const serverRunner = ({
|
|
|
59
60
|
const file = `${Object.keys(config.entryPoints.entries())[0]}.js`;
|
|
60
61
|
const filename = path.resolve(config.output.get('path'), file);
|
|
61
62
|
// настоящая ссылка на файл используется для отладки в debug режиме
|
|
62
|
-
const realFilename =
|
|
63
|
+
const realFilename = `${getApplicationUrl({
|
|
64
|
+
host: configManager.staticHost,
|
|
65
|
+
port: configManager.staticPort,
|
|
66
|
+
protocol: configManager.httpProtocol,
|
|
67
|
+
})}/${configManager.output.server}/${file}`;
|
|
63
68
|
const serverCompiler = compiler.compilers.find((comp) => comp.name === 'server');
|
|
64
69
|
|
|
65
70
|
if (!serverCompiler) {
|
|
@@ -111,6 +111,22 @@ export class StartCommand extends CLICommand<Params> {
|
|
|
111
111
|
transformer: (value: string) => value !== 'false',
|
|
112
112
|
description: 'Enable/disable persistent file cache for used cli builder',
|
|
113
113
|
},
|
|
114
|
+
{
|
|
115
|
+
name: '--https',
|
|
116
|
+
value: '[https]',
|
|
117
|
+
transformer: (value: string) => value !== 'false',
|
|
118
|
+
description: 'Enable/disable https protocol for application',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: '--httpsKey',
|
|
122
|
+
value: '[httpsKey]',
|
|
123
|
+
description: 'Path to https key certificate',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: '--httpsCert',
|
|
127
|
+
value: '[httpsCert]',
|
|
128
|
+
description: 'Path to https certificate',
|
|
129
|
+
},
|
|
114
130
|
];
|
|
115
131
|
|
|
116
132
|
alias = 's';
|
|
@@ -85,6 +85,22 @@ export class StartProdCommand extends CLICommand<Params> {
|
|
|
85
85
|
transformer: (value: string) => value !== 'false',
|
|
86
86
|
description: 'Enable/disable persistent file cache for used cli builder',
|
|
87
87
|
},
|
|
88
|
+
{
|
|
89
|
+
name: '--https',
|
|
90
|
+
value: '[https]',
|
|
91
|
+
transformer: (value: string) => value !== 'false',
|
|
92
|
+
description: 'Enable/disable https protocol for application',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: '--httpsKey',
|
|
96
|
+
value: '[httpsKey]',
|
|
97
|
+
description: 'Path to https key certificate',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: '--httpsCert',
|
|
101
|
+
value: '[httpsCert]',
|
|
102
|
+
description: 'Path to https certificate',
|
|
103
|
+
},
|
|
88
104
|
];
|
|
89
105
|
|
|
90
106
|
alias = 'sp';
|
|
@@ -127,7 +127,9 @@ export const staticApp = async (
|
|
|
127
127
|
handleServerOutput(context.logger, chunk);
|
|
128
128
|
});
|
|
129
129
|
|
|
130
|
-
const readinessProbePath =
|
|
130
|
+
const readinessProbePath = `${clientConfigManager.httpProtocol}://localhost:${
|
|
131
|
+
envVariables.UTILITY_SERVER_PORT ?? port
|
|
132
|
+
}/readyz`;
|
|
131
133
|
|
|
132
134
|
await Promise.race([
|
|
133
135
|
server,
|