@servicetitan/startup 24.0.4 → 24.1.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 (111) hide show
  1. package/dist/cli/commands/build.d.ts +1 -0
  2. package/dist/cli/commands/build.d.ts.map +1 -1
  3. package/dist/cli/commands/build.js +3 -0
  4. package/dist/cli/commands/build.js.map +1 -1
  5. package/dist/cli/commands/bundle-package.d.ts +1 -0
  6. package/dist/cli/commands/bundle-package.d.ts.map +1 -1
  7. package/dist/cli/commands/bundle-package.js +3 -0
  8. package/dist/cli/commands/bundle-package.js.map +1 -1
  9. package/dist/cli/commands/eslint.d.ts +1 -0
  10. package/dist/cli/commands/eslint.d.ts.map +1 -1
  11. package/dist/cli/commands/eslint.js +3 -0
  12. package/dist/cli/commands/eslint.js.map +1 -1
  13. package/dist/cli/commands/get-command.d.ts +6 -0
  14. package/dist/cli/commands/get-command.d.ts.map +1 -0
  15. package/dist/cli/commands/get-command.js +50 -0
  16. package/dist/cli/commands/get-command.js.map +1 -0
  17. package/dist/cli/commands/get-user-commands.d.ts +7 -0
  18. package/dist/cli/commands/get-user-commands.d.ts.map +1 -0
  19. package/dist/cli/commands/get-user-commands.js +17 -0
  20. package/dist/cli/commands/get-user-commands.js.map +1 -0
  21. package/dist/cli/commands/index.d.ts +3 -3
  22. package/dist/cli/commands/index.d.ts.map +1 -1
  23. package/dist/cli/commands/index.js +3 -0
  24. package/dist/cli/commands/index.js.map +1 -1
  25. package/dist/cli/commands/init.d.ts +2 -1
  26. package/dist/cli/commands/init.d.ts.map +1 -1
  27. package/dist/cli/commands/init.js +5 -2
  28. package/dist/cli/commands/init.js.map +1 -1
  29. package/dist/cli/commands/install.d.ts +1 -0
  30. package/dist/cli/commands/install.d.ts.map +1 -1
  31. package/dist/cli/commands/install.js +3 -0
  32. package/dist/cli/commands/install.js.map +1 -1
  33. package/dist/cli/commands/kendo-ui-license.d.ts +1 -0
  34. package/dist/cli/commands/kendo-ui-license.d.ts.map +1 -1
  35. package/dist/cli/commands/kendo-ui-license.js +3 -0
  36. package/dist/cli/commands/kendo-ui-license.js.map +1 -1
  37. package/dist/cli/commands/lint.d.ts +1 -0
  38. package/dist/cli/commands/lint.d.ts.map +1 -1
  39. package/dist/cli/commands/lint.js +3 -0
  40. package/dist/cli/commands/lint.js.map +1 -1
  41. package/dist/cli/commands/mfe-publish.d.ts +3 -0
  42. package/dist/cli/commands/mfe-publish.d.ts.map +1 -1
  43. package/dist/cli/commands/mfe-publish.js +14 -1
  44. package/dist/cli/commands/mfe-publish.js.map +1 -1
  45. package/dist/cli/commands/prepare-package.d.ts +1 -0
  46. package/dist/cli/commands/prepare-package.d.ts.map +1 -1
  47. package/dist/cli/commands/prepare-package.js +3 -0
  48. package/dist/cli/commands/prepare-package.js.map +1 -1
  49. package/dist/cli/commands/start.d.ts +1 -0
  50. package/dist/cli/commands/start.d.ts.map +1 -1
  51. package/dist/cli/commands/start.js +3 -0
  52. package/dist/cli/commands/start.js.map +1 -1
  53. package/dist/cli/commands/styles-check.d.ts +1 -0
  54. package/dist/cli/commands/styles-check.d.ts.map +1 -1
  55. package/dist/cli/commands/styles-check.js +3 -0
  56. package/dist/cli/commands/styles-check.js.map +1 -1
  57. package/dist/cli/commands/tests.d.ts +1 -0
  58. package/dist/cli/commands/tests.d.ts.map +1 -1
  59. package/dist/cli/commands/tests.js +3 -0
  60. package/dist/cli/commands/tests.js.map +1 -1
  61. package/dist/cli/commands/types.d.ts +5 -0
  62. package/dist/cli/commands/types.d.ts.map +1 -0
  63. package/dist/cli/commands/types.js +3 -0
  64. package/dist/cli/commands/types.js.map +1 -0
  65. package/dist/cli/index.js +24 -37
  66. package/dist/cli/index.js.map +1 -1
  67. package/dist/utils/find-packages.d.ts +6 -0
  68. package/dist/utils/find-packages.d.ts.map +1 -0
  69. package/dist/utils/find-packages.js +52 -0
  70. package/dist/utils/find-packages.js.map +1 -0
  71. package/dist/utils/get-configuration.d.ts +5 -4
  72. package/dist/utils/get-configuration.d.ts.map +1 -1
  73. package/dist/utils/get-configuration.js +15 -9
  74. package/dist/utils/get-configuration.js.map +1 -1
  75. package/dist/utils/get-packages.d.ts +1 -5
  76. package/dist/utils/get-packages.d.ts.map +1 -1
  77. package/dist/utils/get-packages.js +44 -26
  78. package/dist/utils/get-packages.js.map +1 -1
  79. package/package.json +14 -13
  80. package/src/cli/commands/__tests__/get-command.test.ts +17 -0
  81. package/src/cli/commands/__tests__/get-user-commands.test.ts +24 -0
  82. package/src/cli/commands/__tests__/init.test.ts +4 -4
  83. package/src/cli/commands/__tests__/mfe-package-publish.test.ts +8 -0
  84. package/src/cli/commands/build.ts +4 -0
  85. package/src/cli/commands/bundle-package.ts +4 -0
  86. package/src/cli/commands/eslint.ts +4 -0
  87. package/src/cli/commands/get-command.ts +50 -0
  88. package/src/cli/commands/get-user-commands.ts +19 -0
  89. package/src/cli/commands/index.ts +3 -4
  90. package/src/cli/commands/init.ts +7 -3
  91. package/src/cli/commands/install.ts +4 -0
  92. package/src/cli/commands/kendo-ui-license.ts +4 -0
  93. package/src/cli/commands/lint.ts +4 -0
  94. package/src/cli/commands/mfe-publish.ts +20 -1
  95. package/src/cli/commands/prepare-package.ts +4 -0
  96. package/src/cli/commands/start.ts +4 -0
  97. package/src/cli/commands/styles-check.ts +4 -0
  98. package/src/cli/commands/tests.ts +4 -0
  99. package/src/cli/commands/types.ts +4 -0
  100. package/src/cli/index.ts +27 -59
  101. package/src/utils/__tests__/get-configuration.test.ts +30 -8
  102. package/src/utils/__tests__/get-packages.test.ts +171 -93
  103. package/src/utils/find-packages.ts +61 -0
  104. package/src/utils/get-configuration.ts +18 -8
  105. package/src/utils/get-packages.ts +59 -42
  106. package/dist/utils/maybe-create-git-folder.d.ts +0 -10
  107. package/dist/utils/maybe-create-git-folder.d.ts.map +0 -1
  108. package/dist/utils/maybe-create-git-folder.js +0 -25
  109. package/dist/utils/maybe-create-git-folder.js.map +0 -1
  110. package/src/utils/__tests__/maybe-create-git-folder.test.ts +0 -41
  111. package/src/utils/maybe-create-git-folder.ts +0 -18
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/startup",
3
- "version": "24.0.4",
3
+ "version": "24.1.1",
4
4
  "description": "",
5
5
  "homepage": "https://docs.st.dev/docs/frontend/startup",
6
6
  "repository": {
@@ -28,7 +28,7 @@
28
28
  "@types/eslint": "~8.56.3",
29
29
  "@types/less": "~3.0.3",
30
30
  "@types/moment-locales-webpack-plugin": "~1.2.2",
31
- "@types/sass": "~1.43.1",
31
+ "@types/sass": "~1.45.0",
32
32
  "@types/webpack-assets-manifest": "~5.1.4",
33
33
  "@types/webpack-dev-server": "~3.11.5",
34
34
  "@types/yargs": "~17.0.24"
@@ -37,10 +37,10 @@
37
37
  "@babel/preset-env": "~7.24.7",
38
38
  "@jest/core": "~29.7.0",
39
39
  "@jest/types": "~29.6.3",
40
- "@servicetitan/eslint-config": "24.0.4",
41
- "@servicetitan/stylelint-config": "24.0.4",
40
+ "@servicetitan/eslint-config": "24.1.1",
41
+ "@servicetitan/stylelint-config": "24.1.1",
42
42
  "@svgr/webpack": "^8.1.0",
43
- "@swc/core": "1.5.27",
43
+ "@swc/core": "1.6.5",
44
44
  "@types/debug": "^4.1.12",
45
45
  "@types/jest": "~29.5.12",
46
46
  "chalk": "~4.1.2",
@@ -49,41 +49,42 @@
49
49
  "css-loader": "~7.1.2",
50
50
  "debug": "^4.3.5",
51
51
  "deepmerge": "~4.3.1",
52
- "esbuild-loader": "~4.1.0",
52
+ "esbuild-loader": "~4.2.0",
53
53
  "eslint": "~8.57.0",
54
54
  "execa": "~5.1.1",
55
55
  "fork-ts-checker-webpack-plugin": "~9.0.2",
56
- "glob": "~10.4.1",
56
+ "glob": "~10.4.2",
57
57
  "html-webpack-plugin": "~5.6.0",
58
58
  "identity-obj-proxy": "~3.0.0",
59
59
  "jest": "~29.7.0",
60
60
  "jest-circus": "~29.7.0",
61
61
  "jest-environment-jsdom": "^29.7.0",
62
62
  "jest-fetch-mock": "~3.0.3",
63
- "lerna": "~8.1.3",
63
+ "lerna": "~8.1.5",
64
64
  "less": "~4.2.0",
65
65
  "less-loader": "~12.2.0",
66
66
  "less-plugin-npm-import": "~2.1.0",
67
- "memfs": "~4.9.2",
67
+ "memfs": "~4.9.3",
68
68
  "mini-css-extract-plugin": "~2.9.0",
69
69
  "moment": "^2.30.1",
70
70
  "moment-locales-webpack-plugin": "~1.2.0",
71
+ "multimatch": "~5.0.0",
71
72
  "portfinder": "~1.0.32",
72
73
  "postcss": "~8.4.38",
73
74
  "prettier": "~2.7.1",
74
- "sass": "~1.77.4",
75
+ "sass": "~1.77.6",
75
76
  "sass-loader": "~14.2.1",
76
77
  "source-map-loader": "~5.0.0",
77
78
  "style-loader": "~4.0.0",
78
79
  "stylelint": "~14.16.1",
79
80
  "swc-loader": "0.2.6",
80
- "ts-jest": "~29.1.4",
81
+ "ts-jest": "~29.1.5",
81
82
  "ts-loader": "~9.5.1",
82
83
  "ts-node": "~10.9.2",
83
84
  "typed-css-modules": "~0.9.1",
84
85
  "typescript": "~5.4.5",
85
86
  "username": "~5.1.0",
86
- "webpack": "~5.91.0",
87
+ "webpack": "~5.92.1",
87
88
  "webpack-assets-manifest": "~5.2.1",
88
89
  "webpack-bundle-analyzer": "^4.10.2",
89
90
  "webpack-dev-server": "~3.11.2",
@@ -100,5 +101,5 @@
100
101
  "cli": {
101
102
  "webpack": false
102
103
  },
103
- "gitHead": "fb08cd20968e5ae1a57527bd8aa39d3e257750be"
104
+ "gitHead": "ffae5820df5a370516c3e6a8b71d44cc3bacd06e"
104
105
  }
@@ -0,0 +1,17 @@
1
+ import { CommandName } from '../../../utils';
2
+
3
+ import { getCommand } from '../get-command';
4
+
5
+ describe(`${getCommand.name}`, () => {
6
+ const subject = (name: CommandName) => getCommand(name);
7
+
8
+ test('retrieves known commands', () => {
9
+ Object.values(CommandName).forEach(name => {
10
+ expect(subject(name)).toBeDefined();
11
+ });
12
+ });
13
+
14
+ test('returns undefined when command is unknown', () => {
15
+ expect(subject('foo' as CommandName)).toBeUndefined();
16
+ });
17
+ });
@@ -0,0 +1,24 @@
1
+ import { CommandName } from '../../../utils';
2
+ import { getCommand } from '../get-command';
3
+ import { getUserCommands } from '../get-user-commands';
4
+
5
+ describe(`${getUserCommands.name}`, () => {
6
+ const subject = () => getUserCommands();
7
+
8
+ test('returns commands with descriptions', () => {
9
+ const descriptions = Object.values(CommandName)
10
+ .map(name => {
11
+ const Command = getCommand(name)!;
12
+ // eslint-disable-next-line @typescript-eslint/naming-convention
13
+ return new Command({ _: [] }).description();
14
+ })
15
+ .filter(description => !!description);
16
+
17
+ expect(subject().length).toBe(descriptions.length);
18
+ });
19
+
20
+ test('returns commands in ascending order by name', () => {
21
+ const names = subject().map(({ name }) => name);
22
+ expect(names).toEqual([...names].sort((a, b) => a.localeCompare(b)));
23
+ });
24
+ });
@@ -39,12 +39,12 @@ describe(`[startup] ${Init.name}`, () => {
39
39
  });
40
40
  }
41
41
 
42
- itCopies('template');
42
+ itCopies('template', 'template-react18');
43
43
 
44
- describe('when instructed to create React 18 template', () => {
45
- beforeEach(() => (args.react18 = true));
44
+ describe('when instructed to create React 17 template', () => {
45
+ beforeEach(() => (args.react17 = true));
46
46
 
47
- itCopies('template', 'template-react18');
47
+ itCopies('template');
48
48
  });
49
49
 
50
50
  describe('with an output location', () => {
@@ -171,6 +171,14 @@ describe(`[startup] ${MFEPackagePublish.name}`, () => {
171
171
  itLogsMessageAndSkipsPublishing(/is already published/);
172
172
  });
173
173
 
174
+ describe('when package is private', () => {
175
+ beforeEach(() =>
176
+ vol.fromJSON({ 'package.json': JSON.stringify({ name: packageName, private: true }) })
177
+ );
178
+
179
+ itLogsMessageAndSkipsPublishing(/private package - skip publishing/);
180
+ });
181
+
174
182
  describe('with unrecognized branch', () => {
175
183
  beforeEach(() => jest.mocked(gitGetBranch).mockReturnValue('foo'));
176
184
 
@@ -16,6 +16,10 @@ interface Args {
16
16
  export class Build implements Command {
17
17
  constructor(private args: Args) {}
18
18
 
19
+ description() {
20
+ return 'build project for production';
21
+ }
22
+
19
23
  @logErrors
20
24
  async execute() {
21
25
  const packages = splitPackagesByType(
@@ -16,6 +16,10 @@ interface Args {
16
16
  export class BundlePackage implements Command {
17
17
  constructor(private args: Args) {}
18
18
 
19
+ description() {
20
+ return undefined;
21
+ }
22
+
19
23
  @logErrors
20
24
  async execute() {
21
25
  const { config, stat = false, watch } = this.args;
@@ -11,6 +11,10 @@ interface Args {
11
11
  export class ESLintCommand implements Command {
12
12
  constructor(private args: Args) {}
13
13
 
14
+ description() {
15
+ return undefined;
16
+ }
17
+
14
18
  @logErrors
15
19
  async execute(): Promise<void> {
16
20
  const { _: paths, fix } = this.args;
@@ -0,0 +1,50 @@
1
+ import { CommandName } from '../../utils';
2
+
3
+ import { Build } from './build';
4
+ import { BundlePackage } from './bundle-package';
5
+ import { ESLintCommand } from './eslint';
6
+ import { Init } from './init';
7
+ import { Install } from './install';
8
+ import { KendoUILicense } from './kendo-ui-license';
9
+ import { Lint } from './lint';
10
+ import { MFEPackageClean, MFEPackagePublish, MFEPublish } from './mfe-publish';
11
+ import { PreparePackage } from './prepare-package';
12
+ import { Start } from './start';
13
+ import { StylesCheck } from './styles-check';
14
+ import { Tests } from './tests';
15
+ import { Command } from './types';
16
+
17
+ type Newable<T> = new (...args: any[]) => T;
18
+
19
+ export function getCommand(name: CommandName): Newable<Command> | undefined {
20
+ switch (name) {
21
+ case CommandName.build:
22
+ return Build;
23
+ case CommandName['bundle-package']:
24
+ return BundlePackage;
25
+ case CommandName.eslint:
26
+ return ESLintCommand;
27
+ case CommandName.init:
28
+ return Init;
29
+ case CommandName.install:
30
+ return Install;
31
+ case CommandName['kendo-ui-license']:
32
+ return KendoUILicense;
33
+ case CommandName.lint:
34
+ return Lint;
35
+ case CommandName['mfe-package-clean']:
36
+ return MFEPackageClean;
37
+ case CommandName['mfe-package-publish']:
38
+ return MFEPackagePublish;
39
+ case CommandName['mfe-publish']:
40
+ return MFEPublish;
41
+ case CommandName['prepare-package']:
42
+ return PreparePackage;
43
+ case CommandName.start:
44
+ return Start;
45
+ case CommandName['styles-check']:
46
+ return StylesCheck;
47
+ case CommandName.test:
48
+ return Tests;
49
+ }
50
+ }
@@ -0,0 +1,19 @@
1
+ import { CommandName } from '../../utils';
2
+
3
+ import { getCommand } from './get-command';
4
+
5
+ interface UserCommand {
6
+ name: string;
7
+ description: string;
8
+ }
9
+
10
+ export function getUserCommands() {
11
+ return Object.values(CommandName)
12
+ .sort((a, b) => a.localeCompare(b))
13
+ .map(name => {
14
+ const Command = getCommand(name)!;
15
+ // eslint-disable-next-line @typescript-eslint/naming-convention
16
+ return { name, description: new Command({ _: [] }).description() };
17
+ })
18
+ .filter(({ description }) => !!description) as UserCommand[];
19
+ }
@@ -1,6 +1,8 @@
1
1
  export * from './build';
2
2
  export * from './bundle-package';
3
3
  export * from './eslint';
4
+ export * from './get-command';
5
+ export * from './get-user-commands';
4
6
  export * from './init';
5
7
  export * from './install';
6
8
  export * from './kendo-ui-license';
@@ -10,7 +12,4 @@ export * from './start';
10
12
  export * from './tests';
11
13
  export * from './styles-check';
12
14
  export * from './mfe-publish';
13
-
14
- export interface Command {
15
- execute(): Promise<void>;
16
- }
15
+ export * from './types';
@@ -7,13 +7,17 @@ import { log, logErrors } from '../../utils';
7
7
  import { Command } from './';
8
8
 
9
9
  interface Args {
10
- react18?: boolean;
10
+ react17?: boolean;
11
11
  output?: string;
12
12
  }
13
13
 
14
14
  export class Init implements Command {
15
15
  constructor(private args: Args) {}
16
16
 
17
+ description() {
18
+ return 'generate empty project';
19
+ }
20
+
17
21
  @logErrors
18
22
  async execute() {
19
23
  const destination = path.resolve(this.args.output ?? '.');
@@ -25,11 +29,11 @@ export class Init implements Command {
25
29
 
26
30
  await copyFiles('template', destination);
27
31
 
28
- if (this.args.react18) {
32
+ if (!this.args.react17) {
29
33
  await copyFiles('template-react18', destination);
30
34
  }
31
35
 
32
- log.info(`copied${this.args.react18 ? ' React 18' : ''} template to ${destination}`);
36
+ log.info(`copied${this.args.react17 ? ' React 17' : ''} template to ${destination}`);
33
37
  }
34
38
  }
35
39
 
@@ -4,6 +4,10 @@ import { log, logErrors, getStartupVersion } from '../../utils';
4
4
  import { Command } from '.';
5
5
 
6
6
  export class Install implements Command {
7
+ description() {
8
+ return 'install project dependencies';
9
+ }
10
+
7
11
  @logErrors
8
12
  async execute() {
9
13
  const installCommand = process.env.CI ? 'ci' : 'i';
@@ -30,6 +30,10 @@ const LICENSE = Buffer.from(ENCODED_LICENSE, 'base64').toString('ascii');
30
30
  const LICENSING_PACKAGE = '@progress/kendo-licensing';
31
31
 
32
32
  export class KendoUILicense implements Command {
33
+ description() {
34
+ return 'install KendoReact license key';
35
+ }
36
+
33
37
  async execute() {
34
38
  if (!isModuleInstalled(LICENSING_PACKAGE)) {
35
39
  return;
@@ -32,6 +32,10 @@ export class Lint implements Command {
32
32
  this.paths = [...args._];
33
33
  }
34
34
 
35
+ description() {
36
+ return 'run eslint and stylelint';
37
+ }
38
+
35
39
  async execute() {
36
40
  await this.checkStyles();
37
41
  await this.eslint();
@@ -45,6 +45,10 @@ interface Args extends ArgsPackagePublish, ArgsPackageClean {
45
45
  export class MFEPublish implements Command {
46
46
  constructor(private args: Args) {}
47
47
 
48
+ description() {
49
+ return 'publish or unpublish MFE packages';
50
+ }
51
+
48
52
  @logErrors
49
53
  async execute() {
50
54
  let packages = splitPackagesByType(getPackages())[PackageType.Webpack] ?? [];
@@ -93,14 +97,25 @@ export class MFEPublish implements Command {
93
97
  export class MFEPackagePublish implements Command {
94
98
  constructor(private args: ArgsPackagePublish) {}
95
99
 
100
+ description() {
101
+ return undefined;
102
+ }
103
+
96
104
  @logErrors
97
105
  async execute() {
98
106
  if (!isWebComponent()) {
99
107
  throw new Error('only web-components can be published');
100
108
  }
101
109
 
102
- const data = this.getPublishData();
103
110
  const packageJson = readJson('package.json');
111
+
112
+ if (packageJson.private) {
113
+ log.info('private package - skip publishing');
114
+
115
+ return;
116
+ }
117
+
118
+ const data = this.getPublishData();
104
119
  const packageName = packageJson.name;
105
120
 
106
121
  if (!data.version) {
@@ -197,6 +212,10 @@ export class MFEPackagePublish implements Command {
197
212
  export class MFEPackageClean implements Command {
198
213
  constructor(private args: ArgsPackageClean) {}
199
214
 
215
+ description() {
216
+ return undefined;
217
+ }
218
+
200
219
  @logErrors
201
220
  async execute() {
202
221
  if (!isWebComponent()) {
@@ -9,6 +9,10 @@ interface Args {
9
9
  export class PreparePackage implements Command {
10
10
  constructor(private args: Args) {}
11
11
 
12
+ description() {
13
+ return undefined;
14
+ }
15
+
12
16
  @logErrors
13
17
  async execute() {
14
18
  if (!this.args.watch) {
@@ -14,6 +14,10 @@ interface Args {
14
14
  export class Start implements Command {
15
15
  constructor(private args: Args) {}
16
16
 
17
+ description() {
18
+ return 'run project in development mode';
19
+ }
20
+
17
21
  @logErrors
18
22
  async execute() {
19
23
  const packages = splitPackagesByType(
@@ -121,6 +121,10 @@ function checkStylesWebComponent(files: FileInfo[]) {
121
121
  }
122
122
 
123
123
  export class StylesCheck implements Command {
124
+ description() {
125
+ return undefined;
126
+ }
127
+
124
128
  // eslint-disable-next-line @typescript-eslint/require-await
125
129
  async execute() {
126
130
  if (isLegacy()) {
@@ -9,6 +9,10 @@ import { Command } from '.';
9
9
  export class Tests implements Command {
10
10
  constructor(private args: Config.Argv) {}
11
11
 
12
+ description() {
13
+ return 'run tests';
14
+ }
15
+
12
16
  @logErrors
13
17
  async execute() {
14
18
  const jestConfig = getJestConfigCLI(this.args);
@@ -0,0 +1,4 @@
1
+ export interface Command {
2
+ execute(): Promise<void>;
3
+ description(): string | undefined;
4
+ }
package/src/cli/index.ts CHANGED
@@ -1,69 +1,23 @@
1
1
  import execa from 'execa';
2
2
  import { argv, Arguments } from 'yargs';
3
-
4
- import { CommandName, log } from '../utils';
5
- import {
6
- Build,
7
- BundlePackage,
8
- Command,
9
- ESLintCommand,
10
- Init,
11
- Install,
12
- KendoUILicense,
13
- Lint,
14
- MFEPackageClean,
15
- MFEPackagePublish,
16
- MFEPublish,
17
- PreparePackage,
18
- Start,
19
- StylesCheck,
20
- Tests,
21
- } from './commands';
3
+ import { CommandName, getStartupVersion, log } from '../utils';
4
+ import { getCommand, getUserCommands } from './commands';
22
5
  import { setNodeOptions } from './utils';
23
6
 
24
- interface Newable<T> {
25
- new (...args: any[]): T;
26
- }
27
-
28
- function getCommand(name: CommandName): Newable<Command> {
29
- switch (name) {
30
- case CommandName.build:
31
- return Build;
32
- case CommandName['bundle-package']:
33
- return BundlePackage;
34
- case CommandName.eslint:
35
- return ESLintCommand;
36
- case CommandName.init:
37
- return Init;
38
- case CommandName.install:
39
- return Install;
40
- case CommandName['kendo-ui-license']:
41
- return KendoUILicense;
42
- case CommandName.lint:
43
- return Lint;
44
- case CommandName['mfe-package-clean']:
45
- return MFEPackageClean;
46
- case CommandName['mfe-package-publish']:
47
- return MFEPackagePublish;
48
- case CommandName['mfe-publish']:
49
- return MFEPublish;
50
- case CommandName['prepare-package']:
51
- return PreparePackage;
52
- case CommandName.start:
53
- return Start;
54
- case CommandName['styles-check']:
55
- return StylesCheck;
56
- case CommandName.test:
57
- return Tests;
58
- default:
59
- log.error(`${name}: command not found!`);
60
- process.exit(127);
61
- }
7
+ const argvSync = argv as Arguments;
8
+ const name = argvSync._[0]?.toString() as CommandName;
9
+ if (!name) {
10
+ log.info(`startup cli v${getStartupVersion()}`);
11
+ usage();
12
+ process.exit(0);
62
13
  }
63
14
 
64
- const argvSync = argv as Arguments;
65
- const name = argvSync._[0].toString() as CommandName;
66
15
  const Command = getCommand(name);
16
+ if (!Command) {
17
+ log.error(`Unknown command: "${name}"`);
18
+ usage();
19
+ process.exit(127);
20
+ }
67
21
 
68
22
  if (setNodeOptions(name)) {
69
23
  // Run command in child process with amended NODE_OPTIONS
@@ -77,3 +31,17 @@ if (setNodeOptions(name)) {
77
31
  process.exit(1);
78
32
  });
79
33
  }
34
+
35
+ function usage() {
36
+ write('\nUsage:\n');
37
+
38
+ const commands = getUserCommands().filter(({ name }) => !!name);
39
+ const maxNameLength = commands.reduce((result, { name }) => Math.max(result, name.length), 0);
40
+ commands.forEach(({ name, description }) => {
41
+ write(`startup ${name.padEnd(maxNameLength, ' ')} ${description}`);
42
+ });
43
+ }
44
+
45
+ function write(text: string) {
46
+ return console.info(text); // eslint-disable-line no-console
47
+ }
@@ -40,11 +40,11 @@ describe('[startup] Utils', () => {
40
40
  afterEach(() => jest.resetAllMocks());
41
41
 
42
42
  describe(`${getConfiguration.name}`, () => {
43
- let location: string | undefined;
43
+ let locationOrJson: string | Record<string, any> | undefined;
44
44
 
45
- beforeEach(() => (location = undefined));
45
+ beforeEach(() => (locationOrJson = undefined));
46
46
 
47
- const subject = () => getConfiguration(location);
47
+ const subject = () => getConfiguration(locationOrJson);
48
48
 
49
49
  itReturns(subject, {});
50
50
 
@@ -60,7 +60,7 @@ describe('[startup] Utils', () => {
60
60
  const cli = { baz: 'qux' };
61
61
 
62
62
  beforeEach(() => {
63
- location = 'packages/foo';
63
+ locationOrJson = 'packages/foo';
64
64
  vol.fromJSON({ [`packages/foo/${packageJson}`]: JSON.stringify({ cli }) });
65
65
  });
66
66
 
@@ -69,6 +69,18 @@ describe('[startup] Utils', () => {
69
69
  });
70
70
  });
71
71
 
72
+ describe('with JSON', () => {
73
+ const cli = { baz: 'qux' };
74
+
75
+ beforeEach(() => {
76
+ locationOrJson = { cli };
77
+ });
78
+
79
+ test("returns location's cli", () => {
80
+ expect(subject()).toEqual(cli);
81
+ });
82
+ });
83
+
72
84
  describe('with no package.json', () => {
73
85
  beforeEach(() => vol.reset());
74
86
 
@@ -79,11 +91,11 @@ describe('[startup] Utils', () => {
79
91
  });
80
92
 
81
93
  describe(`${getConfigurationSafe.name}`, () => {
82
- let location: string | undefined;
94
+ let locationOrJson: string | Record<string, any> | undefined;
83
95
 
84
- beforeEach(() => (location = undefined));
96
+ beforeEach(() => (locationOrJson = undefined));
85
97
 
86
- const subject = () => getConfigurationSafe(location);
98
+ const subject = () => getConfigurationSafe(locationOrJson);
87
99
 
88
100
  itReturns(subject, {});
89
101
 
@@ -99,7 +111,7 @@ describe('[startup] Utils', () => {
99
111
  const cli = { baz: 'qux' };
100
112
 
101
113
  beforeEach(() => {
102
- location = 'packages/foo';
114
+ locationOrJson = 'packages/foo';
103
115
  vol.fromJSON({ [`packages/foo/${packageJson}`]: JSON.stringify({ cli }) });
104
116
  });
105
117
 
@@ -108,6 +120,16 @@ describe('[startup] Utils', () => {
108
120
  });
109
121
  });
110
122
 
123
+ describe('with JSON', () => {
124
+ const cli = { baz: 'qux' };
125
+
126
+ beforeEach(() => (locationOrJson = { cli }));
127
+
128
+ test("returns location's cli", () => {
129
+ expect(subject()).toEqual(cli);
130
+ });
131
+ });
132
+
111
133
  describe('with no package.json', () => {
112
134
  beforeEach(() => vol.reset());
113
135