@tramvai/cli 2.148.0 → 2.148.1

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 (78) hide show
  1. package/README.md +3 -3
  2. package/lib/api/build/providers/shared.js +4 -3
  3. package/lib/api/build/providers/shared.js.map +1 -1
  4. package/lib/api/start/application.js.map +1 -1
  5. package/lib/api/start/index.js +5 -2
  6. package/lib/api/start/index.js.map +1 -1
  7. package/lib/api/start/providers/application/shared.js +2 -5
  8. package/lib/api/start/providers/application/shared.js.map +1 -1
  9. package/lib/api/start/providers/child-app/shared.js +2 -2
  10. package/lib/api/start/providers/child-app/shared.js.map +1 -1
  11. package/lib/api/start/providers/module/shared.js +2 -2
  12. package/lib/api/start/providers/module/shared.js.map +1 -1
  13. package/lib/api/start/utils/createServer.d.ts +1 -1
  14. package/lib/api/start-prod/application.js +2 -0
  15. package/lib/api/start-prod/application.js.map +1 -1
  16. package/lib/api/start-prod/index.js +5 -2
  17. package/lib/api/start-prod/index.js.map +1 -1
  18. package/lib/api/start-prod/providers/application.js +2 -5
  19. package/lib/api/start-prod/providers/application.js.map +1 -1
  20. package/lib/api/start-prod/providers/child-app.js +2 -5
  21. package/lib/api/start-prod/providers/child-app.js.map +1 -1
  22. package/lib/commands/createApp.js +1 -0
  23. package/lib/commands/createApp.js.map +1 -1
  24. package/lib/commands/static/application.js +4 -1
  25. package/lib/commands/static/application.js.map +1 -1
  26. package/lib/config/configManager.d.ts +0 -3
  27. package/lib/config/configManager.js +5 -5
  28. package/lib/config/configManager.js.map +1 -1
  29. package/lib/di/providers/config.js +1 -1
  30. package/lib/di/providers/config.js.map +1 -1
  31. package/lib/di/providers/index.d.ts +1 -0
  32. package/lib/di/providers/index.js +1 -0
  33. package/lib/di/providers/index.js.map +1 -1
  34. package/lib/di/providers/network.d.ts +2 -0
  35. package/lib/di/providers/network.js +17 -0
  36. package/lib/di/providers/network.js.map +1 -0
  37. package/lib/di/tokens/index.d.ts +1 -0
  38. package/lib/di/tokens/index.js +1 -0
  39. package/lib/di/tokens/index.js.map +1 -1
  40. package/lib/di/tokens/network.d.ts +4 -0
  41. package/lib/di/tokens/network.js +6 -0
  42. package/lib/di/tokens/network.js.map +1 -0
  43. package/lib/di/tokens/server.d.ts +2 -2
  44. package/lib/library/webpack/constants/stats.d.ts +1 -1
  45. package/lib/library/webpack/utils/threadLoader.js +1 -1
  46. package/lib/library/webpack/utils/threadLoader.js.map +1 -1
  47. package/lib/models/port-manager.d.ts +30 -0
  48. package/lib/models/port-manager.js +72 -0
  49. package/lib/models/port-manager.js.map +1 -0
  50. package/lib/schema/autogeneratedSchema.json +15 -15
  51. package/lib/utils/detectPortSync.d.ts +0 -13
  52. package/lib/utils/detectPortSync.js +0 -21
  53. package/lib/utils/detectPortSync.js.map +1 -1
  54. package/package.json +2 -3
  55. package/schema.json +15 -15
  56. package/src/api/build/providers/shared.ts +5 -11
  57. package/src/api/start/__integration__/start.test.ts +3 -3
  58. package/src/api/start/application.ts +1 -0
  59. package/src/api/start/index.ts +5 -2
  60. package/src/api/start/providers/application/shared.ts +6 -12
  61. package/src/api/start/providers/child-app/shared.ts +5 -4
  62. package/src/api/start/providers/module/shared.ts +5 -4
  63. package/src/api/start-prod/application.ts +5 -1
  64. package/src/api/start-prod/index.ts +5 -2
  65. package/src/api/start-prod/providers/application.ts +8 -16
  66. package/src/api/start-prod/providers/child-app.ts +6 -7
  67. package/src/commands/createApp.ts +2 -0
  68. package/src/commands/static/application.ts +7 -0
  69. package/src/config/configManager.ts +6 -5
  70. package/src/di/providers/config.ts +1 -1
  71. package/src/di/providers/index.ts +1 -0
  72. package/src/di/providers/network.ts +16 -0
  73. package/src/di/tokens/index.ts +1 -0
  74. package/src/di/tokens/network.ts +5 -0
  75. package/src/library/webpack/utils/threadLoader.ts +1 -1
  76. package/src/models/port-manager.ts +79 -0
  77. package/src/schema/autogeneratedSchema.json +15 -15
  78. package/src/utils/detectPortSync.ts +0 -24
@@ -6,39 +6,31 @@ import {
6
6
  COMMAND_PARAMETERS_TOKEN,
7
7
  CONFIG_ENTRY_TOKEN,
8
8
  CONFIG_MANAGER_TOKEN,
9
+ PORT_MANAGER_TOKEN,
9
10
  } from '../../../di/tokens';
10
- import type { Params } from '../index';
11
- import type { ConfigEntry } from '../../../typings/configEntry/common';
11
+ import type { ApplicationConfigEntry } from '../../../typings/configEntry/application';
12
12
  import { CLOSE_HANDLER_TOKEN, SERVER_PROCESS_TOKEN } from '../tokens';
13
13
  import { DEBUG_ARGV } from '../../../config/constants';
14
- import { detectPortSync } from '../../../utils/detectPortSync';
15
14
  import { safeRequire } from '../../../utils/safeRequire';
16
15
  import type { ConfigManager } from '../../../config/configManager';
17
- import {
18
- createConfigManager,
19
- DEFAULT_PORT,
20
- DEFAULT_STATIC_PORT,
21
- } from '../../../config/configManager';
22
- import type { ApplicationConfigEntry } from '../../../typings/configEntry/application';
16
+ import { createConfigManager } from '../../../config/configManager';
23
17
 
24
18
  export const applicationsProviders: readonly Provider[] = [
25
19
  provide({
26
20
  provide: CONFIG_MANAGER_TOKEN,
27
- useFactory: ({ configEntry, parameters }: { configEntry: ConfigEntry; parameters: Params }) =>
28
- createConfigManager(configEntry, {
21
+ useFactory: ({ configEntry, parameters, portManager }) =>
22
+ createConfigManager(configEntry as ApplicationConfigEntry, {
29
23
  ...parameters,
30
24
  appEnv: parameters.env,
31
25
  env: 'production',
32
26
  buildType: 'client',
33
- port: detectPortSync({ request: parameters.port, fallback: DEFAULT_PORT }),
34
- staticPort: detectPortSync({
35
- request: parameters.staticPort,
36
- fallback: DEFAULT_STATIC_PORT,
37
- }),
27
+ port: portManager.port,
28
+ staticPort: portManager.staticPort,
38
29
  }),
39
30
  deps: {
40
31
  configEntry: CONFIG_ENTRY_TOKEN,
41
32
  parameters: COMMAND_PARAMETERS_TOKEN,
33
+ portManager: PORT_MANAGER_TOKEN,
42
34
  },
43
35
  }),
44
36
  provide({
@@ -4,28 +4,27 @@ import {
4
4
  COMMAND_PARAMETERS_TOKEN,
5
5
  CONFIG_ENTRY_TOKEN,
6
6
  CONFIG_MANAGER_TOKEN,
7
+ PORT_MANAGER_TOKEN,
7
8
  } from '../../../di/tokens';
8
- import { createConfigManager, DEFAULT_STATIC_MODULE_PORT } from '../../../config/configManager';
9
+ import { createConfigManager } from '../../../config/configManager';
9
10
  import type { ChildAppConfigEntry } from '../../../typings/configEntry/child-app';
10
- import { detectPortSync } from '../../../utils/detectPortSync';
11
11
 
12
12
  export const childAppProviders: readonly Provider[] = [
13
13
  provide({
14
14
  provide: CONFIG_MANAGER_TOKEN,
15
- useFactory: ({ configEntry, parameters }) =>
15
+ useFactory: ({ configEntry, parameters, portManager }) =>
16
16
  createConfigManager(configEntry as ChildAppConfigEntry, {
17
17
  ...parameters,
18
18
  appEnv: parameters.env,
19
19
  env: 'production',
20
20
  buildType: 'client',
21
- staticPort: detectPortSync({
22
- request: parameters.staticPort,
23
- fallback: DEFAULT_STATIC_MODULE_PORT,
24
- }),
21
+ port: portManager.port,
22
+ staticPort: portManager.staticPort,
25
23
  }),
26
24
  deps: {
27
25
  configEntry: CONFIG_ENTRY_TOKEN,
28
26
  parameters: COMMAND_PARAMETERS_TOKEN,
27
+ portManager: PORT_MANAGER_TOKEN,
29
28
  },
30
29
  }),
31
30
  ] as const;
@@ -8,6 +8,7 @@ import {
8
8
  configProviders,
9
9
  packageManagerProviders,
10
10
  stdProviders,
11
+ networkProviders,
11
12
  } from '../di/providers';
12
13
  import { COMMAND_MAP_TOKEN, COMMAND_PARAMETERS_TOKEN, COMMAND_RUNNER_TOKEN } from '../di/tokens';
13
14
 
@@ -25,6 +26,7 @@ export const createApp = ({
25
26
  ...commandsProviders,
26
27
  ...packageManagerProviders,
27
28
  ...builderProviders,
29
+ ...networkProviders,
28
30
  ...providers,
29
31
  {
30
32
  provide: COMMAND_PARAMETERS_TOKEN,
@@ -17,6 +17,7 @@ import { startStaticServer } from './staticServer';
17
17
  import { startServer } from './server';
18
18
  import { handleServerOutput } from './utils/handle-server-output';
19
19
  import { appBundleInfo } from '../../utils/dev-app/request';
20
+ import { PortManager } from '../../models/port-manager';
20
21
 
21
22
  // eslint-disable-next-line max-statements
22
23
  export const staticApp = async (
@@ -24,11 +25,17 @@ export const staticApp = async (
24
25
  configEntry: ApplicationConfigEntry,
25
26
  options: Params
26
27
  ): Promise<CommandResult> => {
28
+ const network = new PortManager({ configEntry, commandParams: options });
29
+
30
+ await network.computeAvailablePorts();
31
+
27
32
  const clientConfigManager = createConfigManager(configEntry, {
28
33
  env: 'production',
29
34
  ...options,
30
35
  buildType: 'client',
31
36
  modern: false,
37
+ port: network.port,
38
+ staticPort: network.staticPort,
32
39
  });
33
40
  const serverConfigManager = clientConfigManager.withSettings({ buildType: 'server' });
34
41
 
@@ -13,6 +13,7 @@ import moduleVersion from '../utils/moduleVersion';
13
13
  import { packageVersion } from '../utils/packageVersion';
14
14
  import { showConfig } from './showConfig';
15
15
  import type { Target } from '../typings/target';
16
+ import { PortManager } from '../models/port-manager';
16
17
 
17
18
  // @TODO: maybe split settings depending on env?
18
19
  export interface Settings<E extends Env> {
@@ -92,10 +93,7 @@ export type ConfigManager<
92
93
  assetsPrefix?: string;
93
94
  };
94
95
 
95
- export const DEFAULT_PORT = 3000;
96
96
  export const DEFAULT_STATIC_HOST = 'localhost';
97
- export const DEFAULT_STATIC_PORT = 4000;
98
- export const DEFAULT_STATIC_MODULE_PORT = 4040;
99
97
 
100
98
  // eslint-disable-next-line max-statements, complexity
101
99
  export const createConfigManager = <C extends ConfigEntry = ConfigEntry, E extends Env = Env>(
@@ -153,10 +151,13 @@ export const createConfigManager = <C extends ConfigEntry = ConfigEntry, E exten
153
151
  rootDir,
154
152
  buildType,
155
153
  debug,
156
- port: Number(settings.port ?? DEFAULT_PORT),
154
+ port: Number(settings.port ?? PortManager.DEFAULT_PORT),
157
155
  staticHost: settings.staticHost ?? DEFAULT_STATIC_HOST,
158
156
  staticPort: Number(
159
- settings.staticPort ?? (type === 'module' ? DEFAULT_STATIC_MODULE_PORT : DEFAULT_STATIC_PORT)
157
+ settings.staticPort ??
158
+ (type === 'module'
159
+ ? PortManager.DEFAULT_MODULE_STATIC_PORT
160
+ : PortManager.DEFAULT_STATIC_PORT)
160
161
  ),
161
162
  modern,
162
163
  // eslint-disable-next-line no-nested-ternary
@@ -57,7 +57,7 @@ export const configProviders: readonly Provider[] = [
57
57
  const { content, isSuccessful } = getTramvaiConfig(rootDir);
58
58
 
59
59
  if (!isSuccessful) {
60
- throw new Error('Config neither passed as parameter or found in file system');
60
+ throw new Error('Config neither passed as parameter nor found in file system');
61
61
  }
62
62
 
63
63
  const manager = new ConfigManager({ config: content, syncConfigFile: syncJsonFile });
@@ -4,3 +4,4 @@ export * from './config';
4
4
  export * from './commands';
5
5
  export * from './packageManager';
6
6
  export * from './builder';
7
+ export * from './network';
@@ -0,0 +1,16 @@
1
+ import { provide } from '@tinkoff/dippy';
2
+ import type { Provider } from '@tinkoff/dippy';
3
+
4
+ import { COMMAND_PARAMETERS_TOKEN, CONFIG_ENTRY_TOKEN, PORT_MANAGER_TOKEN } from '../tokens';
5
+ import { PortManager } from '../../models/port-manager';
6
+
7
+ export const networkProviders: readonly Provider[] = [
8
+ provide({
9
+ provide: PORT_MANAGER_TOKEN,
10
+ useClass: PortManager,
11
+ deps: {
12
+ configEntry: CONFIG_ENTRY_TOKEN,
13
+ commandParams: COMMAND_PARAMETERS_TOKEN,
14
+ },
15
+ }),
16
+ ] as const;
@@ -7,3 +7,4 @@ export * from './config';
7
7
  export * from './packageManager';
8
8
  export * from './builder';
9
9
  export * from './server';
10
+ export * from './network';
@@ -0,0 +1,5 @@
1
+ import { createToken } from '@tinkoff/dippy';
2
+
3
+ import type { PortManager } from '../../models/port-manager';
4
+
5
+ export const PORT_MANAGER_TOKEN = createToken<PortManager>('portManager');
@@ -23,7 +23,7 @@ const createWorkerPoolConfig = (configManager: ConfigManager<CliConfigEntry>) =>
23
23
 
24
24
  const isApplicable = (configManager: ConfigManager<CliConfigEntry>) => {
25
25
  return (
26
- // thread-loader uses child_process.fork underhood, and sometimes (50/50) work in these processes does not get into inspector.Session profile
26
+ // thread-loader uses child_process.fork under the hood, and sometimes (50/50) work in these processes does not get into inspector.Session profile
27
27
  !process.env.TRAMVAI_CPU_PROFILE &&
28
28
  // TODO: check that there is still issue with windows systems and thread-loader
29
29
  process.platform !== 'win32' &&
@@ -0,0 +1,79 @@
1
+ import detectPort from 'detect-port';
2
+
3
+ import type { ConfigEntry } from '../typings/configEntry/common';
4
+ import type { Params as StartParams } from '../api/start';
5
+ import type { Params as StartProdParams } from '../api/start-prod';
6
+
7
+ interface NetworkConstructorPayload {
8
+ configEntry: ConfigEntry;
9
+ commandParams: StartParams | StartProdParams;
10
+ }
11
+
12
+ export class PortManager {
13
+ static DEFAULT_PORT = 3000;
14
+ static DEFAULT_MODULE_PORT = 4040;
15
+ static DEFAULT_STATIC_PORT = 4000;
16
+ static DEFAULT_MODULE_STATIC_PORT = 4040;
17
+
18
+ private configEntry: ConfigEntry;
19
+ private commandParams: StartParams | StartProdParams;
20
+
21
+ public port: number | null = null;
22
+ public staticPort: number | null = null;
23
+
24
+ constructor({ configEntry, commandParams }: NetworkConstructorPayload) {
25
+ this.configEntry = configEntry;
26
+ this.commandParams = commandParams;
27
+ }
28
+
29
+ /**
30
+ * Try to detect port considering the fact, that if user requests
31
+ * a port explicitly, we should not try to detect a free one.
32
+ *
33
+ * Also, handle zero port (it means any random port) as the edge case,
34
+ * because we must pass a final number to the config manager.
35
+ */
36
+ public async computeAvailablePorts(): Promise<void> {
37
+ if (this.commandParams.port !== undefined && this.commandParams.port !== 0) {
38
+ // @ts-expect-error There is a string actually
39
+ this.port = parseInt(this.commandParams.port, 10);
40
+ }
41
+
42
+ if (this.commandParams.staticPort !== undefined && this.commandParams.staticPort !== 0) {
43
+ // @ts-expect-error There is a string actually
44
+ this.staticPort = parseInt(this.commandParams.staticPort, 10);
45
+ }
46
+
47
+ switch (this.configEntry.type) {
48
+ case 'child-app':
49
+ await this.forChildApp();
50
+ break;
51
+
52
+ case 'module':
53
+ await this.forModule();
54
+ break;
55
+
56
+ case 'application':
57
+ await this.forApplication();
58
+ break;
59
+
60
+ default:
61
+ break;
62
+ }
63
+ }
64
+
65
+ private async forApplication(): Promise<void> {
66
+ this.port = this.port ?? (await detectPort(PortManager.DEFAULT_PORT));
67
+ this.staticPort = this.staticPort ?? (await detectPort(PortManager.DEFAULT_STATIC_PORT));
68
+ }
69
+
70
+ private async forModule(): Promise<void> {
71
+ this.port = this.port ?? (await detectPort(PortManager.DEFAULT_MODULE_PORT));
72
+ this.staticPort = this.staticPort ?? (await detectPort(PortManager.DEFAULT_MODULE_STATIC_PORT));
73
+ }
74
+
75
+ private async forChildApp(): Promise<void> {
76
+ this.port = this.port ?? (await detectPort(PortManager.DEFAULT_MODULE_PORT));
77
+ this.staticPort = this.staticPort ?? (await detectPort(PortManager.DEFAULT_MODULE_STATIC_PORT));
78
+ }
79
+ }
@@ -1141,23 +1141,23 @@
1141
1141
  "dotAll": {
1142
1142
  "type": "boolean"
1143
1143
  },
1144
- "__@match@8260": {
1144
+ "__@match@8264": {
1145
1145
  "type": "object",
1146
1146
  "additionalProperties": false
1147
1147
  },
1148
- "__@replace@8262": {
1148
+ "__@replace@8266": {
1149
1149
  "type": "object",
1150
1150
  "additionalProperties": false
1151
1151
  },
1152
- "__@search@8265": {
1152
+ "__@search@8269": {
1153
1153
  "type": "object",
1154
1154
  "additionalProperties": false
1155
1155
  },
1156
- "__@split@8267": {
1156
+ "__@split@8271": {
1157
1157
  "type": "object",
1158
1158
  "additionalProperties": false
1159
1159
  },
1160
- "__@matchAll@8269": {
1160
+ "__@matchAll@8273": {
1161
1161
  "type": "object",
1162
1162
  "additionalProperties": false
1163
1163
  }
@@ -1802,23 +1802,23 @@
1802
1802
  "dotAll": {
1803
1803
  "type": "boolean"
1804
1804
  },
1805
- "__@match@8260": {
1805
+ "__@match@8264": {
1806
1806
  "type": "object",
1807
1807
  "additionalProperties": false
1808
1808
  },
1809
- "__@replace@8262": {
1809
+ "__@replace@8266": {
1810
1810
  "type": "object",
1811
1811
  "additionalProperties": false
1812
1812
  },
1813
- "__@search@8265": {
1813
+ "__@search@8269": {
1814
1814
  "type": "object",
1815
1815
  "additionalProperties": false
1816
1816
  },
1817
- "__@split@8267": {
1817
+ "__@split@8271": {
1818
1818
  "type": "object",
1819
1819
  "additionalProperties": false
1820
1820
  },
1821
- "__@matchAll@8269": {
1821
+ "__@matchAll@8273": {
1822
1822
  "type": "object",
1823
1823
  "additionalProperties": false
1824
1824
  }
@@ -2463,23 +2463,23 @@
2463
2463
  "dotAll": {
2464
2464
  "type": "boolean"
2465
2465
  },
2466
- "__@match@8260": {
2466
+ "__@match@8264": {
2467
2467
  "type": "object",
2468
2468
  "additionalProperties": false
2469
2469
  },
2470
- "__@replace@8262": {
2470
+ "__@replace@8266": {
2471
2471
  "type": "object",
2472
2472
  "additionalProperties": false
2473
2473
  },
2474
- "__@search@8265": {
2474
+ "__@search@8269": {
2475
2475
  "type": "object",
2476
2476
  "additionalProperties": false
2477
2477
  },
2478
- "__@split@8267": {
2478
+ "__@split@8271": {
2479
2479
  "type": "object",
2480
2480
  "additionalProperties": false
2481
2481
  },
2482
- "__@matchAll@8269": {
2482
+ "__@matchAll@8273": {
2483
2483
  "type": "object",
2484
2484
  "additionalProperties": false
2485
2485
  }
@@ -1,24 +0,0 @@
1
- import { execSync } from 'child_process';
2
- import stripAnsi from 'strip-ansi';
3
-
4
- interface Payload {
5
- request?: number;
6
- fallback: number;
7
- }
8
-
9
- /**
10
- * Try to detect port synchronously considering the fact, that if user requests
11
- * a port explicitly, we should not try to detect a free one.
12
- *
13
- * Also, handle zero port (it means any random port) as the edge case,
14
- * because we must pass a final number to the config manager.
15
- */
16
- export const detectPortSync = ({ request, fallback }: Payload): number => {
17
- if (request !== undefined && request !== 0) {
18
- return request;
19
- }
20
-
21
- const commandResult = execSync(`npx detect-port ${request ?? fallback}`, { encoding: 'utf-8' });
22
-
23
- return parseInt(stripAnsi(commandResult.toString()), 10);
24
- };