@tramvai/cli 3.26.3 → 3.27.3

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.
Files changed (106) hide show
  1. package/lib/api/shared/providers/selfSignedCertificateProvider.d.ts +3 -0
  2. package/lib/api/shared/providers/selfSignedCertificateProvider.d.ts.map +1 -0
  3. package/lib/api/shared/providers/selfSignedCertificateProvider.js +27 -0
  4. package/lib/api/shared/providers/selfSignedCertificateProvider.js.map +1 -0
  5. package/lib/api/shared/types/base.d.ts +4 -0
  6. package/lib/api/shared/types/base.d.ts.map +1 -1
  7. package/lib/api/shared/utils/selfSignedCertificate/certificatedHostsList.d.ts +4 -0
  8. package/lib/api/shared/utils/selfSignedCertificate/certificatedHostsList.d.ts.map +1 -0
  9. package/lib/api/shared/utils/selfSignedCertificate/certificatedHostsList.js +22 -0
  10. package/lib/api/shared/utils/selfSignedCertificate/certificatedHostsList.js.map +1 -0
  11. package/lib/api/shared/utils/selfSignedCertificate/common.d.ts +3 -0
  12. package/lib/api/shared/utils/selfSignedCertificate/common.d.ts.map +1 -0
  13. package/lib/api/shared/utils/selfSignedCertificate/common.js +8 -0
  14. package/lib/api/shared/utils/selfSignedCertificate/common.js.map +1 -0
  15. package/lib/api/shared/utils/selfSignedCertificate/createSelfSignedCertificate.d.ts +9 -0
  16. package/lib/api/shared/utils/selfSignedCertificate/createSelfSignedCertificate.d.ts.map +1 -0
  17. package/lib/api/shared/utils/selfSignedCertificate/createSelfSignedCertificate.js +64 -0
  18. package/lib/api/shared/utils/selfSignedCertificate/createSelfSignedCertificate.js.map +1 -0
  19. package/lib/api/shared/utils/selfSignedCertificate/getHosts.d.ts +3 -0
  20. package/lib/api/shared/utils/selfSignedCertificate/getHosts.d.ts.map +1 -0
  21. package/lib/api/shared/utils/selfSignedCertificate/getHosts.js +32 -0
  22. package/lib/api/shared/utils/selfSignedCertificate/getHosts.js.map +1 -0
  23. package/lib/api/start/index.d.ts +3 -0
  24. package/lib/api/start/index.d.ts.map +1 -1
  25. package/lib/api/start/index.js.map +1 -1
  26. package/lib/api/start/providers/application/server.d.ts.map +1 -1
  27. package/lib/api/start/providers/application/server.js +14 -3
  28. package/lib/api/start/providers/application/server.js.map +1 -1
  29. package/lib/api/start/providers/application/shared.d.ts.map +1 -1
  30. package/lib/api/start/providers/application/shared.js +11 -1
  31. package/lib/api/start/providers/application/shared.js.map +1 -1
  32. package/lib/api/start/utils/banner.d.ts.map +1 -1
  33. package/lib/api/start/utils/banner.js +8 -2
  34. package/lib/api/start/utils/banner.js.map +1 -1
  35. package/lib/api/start/utils/createServer.d.ts +3 -1
  36. package/lib/api/start/utils/createServer.d.ts.map +1 -1
  37. package/lib/api/start/utils/createServer.js +16 -1
  38. package/lib/api/start/utils/createServer.js.map +1 -1
  39. package/lib/api/start-prod/providers/application.d.ts.map +1 -1
  40. package/lib/api/start-prod/providers/application.js +24 -3
  41. package/lib/api/start-prod/providers/application.js.map +1 -1
  42. package/lib/api/start-prod/providers/child-app.d.ts.map +1 -1
  43. package/lib/api/start-prod/providers/child-app.js +5 -0
  44. package/lib/api/start-prod/providers/child-app.js.map +1 -1
  45. package/lib/api/start-prod/providers/shared.d.ts.map +1 -1
  46. package/lib/api/start-prod/providers/shared.js +0 -5
  47. package/lib/api/start-prod/providers/shared.js.map +1 -1
  48. package/lib/builder/webpack/devServer/server.d.ts.map +1 -1
  49. package/lib/builder/webpack/devServer/server.js +6 -1
  50. package/lib/builder/webpack/devServer/server.js.map +1 -1
  51. package/lib/builder/webpack/tokens.d.ts +3 -0
  52. package/lib/builder/webpack/tokens.d.ts.map +1 -1
  53. package/lib/commands/start/command.d.ts.map +1 -1
  54. package/lib/commands/start/command.js +16 -0
  55. package/lib/commands/start/command.js.map +1 -1
  56. package/lib/commands/start-prod/command.d.ts.map +1 -1
  57. package/lib/commands/start-prod/command.js +16 -0
  58. package/lib/commands/start-prod/command.js.map +1 -1
  59. package/lib/commands/static/application.d.ts.map +1 -1
  60. package/lib/commands/static/application.js +1 -1
  61. package/lib/commands/static/application.js.map +1 -1
  62. package/lib/config/configManager.d.ts +2 -0
  63. package/lib/config/configManager.d.ts.map +1 -1
  64. package/lib/config/configManager.js +2 -2
  65. package/lib/config/configManager.js.map +1 -1
  66. package/lib/di/tokens/config.d.ts +1 -0
  67. package/lib/di/tokens/config.d.ts.map +1 -1
  68. package/lib/di/tokens/server.d.ts +6 -0
  69. package/lib/di/tokens/server.d.ts.map +1 -1
  70. package/lib/di/tokens/server.js +2 -1
  71. package/lib/di/tokens/server.js.map +1 -1
  72. package/lib/library/webpack/application/client/dev.d.ts.map +1 -1
  73. package/lib/library/webpack/application/client/dev.js +6 -1
  74. package/lib/library/webpack/application/client/dev.js.map +1 -1
  75. package/lib/library/webpack/application/server/dev.d.ts.map +1 -1
  76. package/lib/library/webpack/application/server/dev.js +6 -1
  77. package/lib/library/webpack/application/server/dev.js.map +1 -1
  78. package/lib/utils/getApplicationUrl.d.ts +6 -0
  79. package/lib/utils/getApplicationUrl.d.ts.map +1 -0
  80. package/lib/utils/getApplicationUrl.js +8 -0
  81. package/lib/utils/getApplicationUrl.js.map +1 -0
  82. package/package.json +2 -2
  83. package/src/api/shared/providers/selfSignedCertificateProvider.ts +29 -0
  84. package/src/api/shared/types/base.ts +5 -0
  85. package/src/api/shared/utils/selfSignedCertificate/certificatedHostsList.ts +22 -0
  86. package/src/api/shared/utils/selfSignedCertificate/common.ts +4 -0
  87. package/src/api/shared/utils/selfSignedCertificate/createSelfSignedCertificate.spec.ts +154 -0
  88. package/src/api/shared/utils/selfSignedCertificate/createSelfSignedCertificate.ts +99 -0
  89. package/src/api/shared/utils/selfSignedCertificate/getHosts.ts +31 -0
  90. package/src/api/start/index.ts +3 -0
  91. package/src/api/start/providers/application/server.ts +21 -5
  92. package/src/api/start/providers/application/shared.ts +12 -2
  93. package/src/api/start/utils/banner.ts +12 -4
  94. package/src/api/start/utils/createServer.ts +19 -1
  95. package/src/api/start-prod/providers/application.ts +27 -3
  96. package/src/api/start-prod/providers/child-app.ts +6 -0
  97. package/src/api/start-prod/providers/shared.ts +0 -5
  98. package/src/builder/webpack/devServer/server.ts +6 -1
  99. package/src/commands/start/command.ts +16 -0
  100. package/src/commands/start-prod/command.ts +16 -0
  101. package/src/commands/static/application.ts +3 -1
  102. package/src/config/configManager.ts +7 -4
  103. package/src/di/tokens/server.ts +5 -0
  104. package/src/library/webpack/application/client/dev.ts +6 -3
  105. package/src/library/webpack/application/server/dev.ts +6 -3
  106. package/src/utils/getApplicationUrl.ts +11 -0
@@ -0,0 +1,4 @@
1
+ import path from 'path';
2
+
3
+ export const certificateDirectory = 'certificates';
4
+ export const certificateDirectoryPath = path.resolve(process.cwd(), certificateDirectory);
@@ -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
+ };
@@ -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 { CONFIG_MANAGER_TOKEN, SERVER_TOKEN } from '../../../../di/tokens';
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: createServer,
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 { host, port } = configManager;
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: createServer,
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
- const server = `http://${config.host.replace('0.0.0.0', 'localhost')}:${config.port}`;
35
- const staticServer = `http://${config.staticHost.replace('0.0.0.0', 'localhost')}:${
36
- config.staticPort
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
- export const createServer = () => {
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 = `http://${configManager.staticHost}:${configManager.staticPort}/${configManager.output.server}/${file}`;
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 = `http://localhost:${envVariables.UTILITY_SERVER_PORT ?? port}/readyz`;
130
+ const readinessProbePath = `${clientConfigManager.httpProtocol}://localhost:${
131
+ envVariables.UTILITY_SERVER_PORT ?? port
132
+ }/readyz`;
131
133
 
132
134
  await Promise.race([
133
135
  server,