@servicetitan/startup 22.1.0 → 22.2.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.
- package/dist/cli/commands/index.d.ts +2 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +2 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/lint.d.ts +3 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +19 -0
- package/dist/cli/commands/lint.js.map +1 -1
- package/dist/cli/commands/mfe-publish.d.ts +36 -0
- package/dist/cli/commands/mfe-publish.d.ts.map +1 -0
- package/dist/cli/commands/mfe-publish.js +268 -0
- package/dist/cli/commands/mfe-publish.js.map +1 -0
- package/dist/cli/commands/styles-check.d.ts +5 -0
- package/dist/cli/commands/styles-check.d.ts.map +1 -0
- package/dist/cli/commands/styles-check.js +124 -0
- package/dist/cli/commands/styles-check.js.map +1 -0
- package/dist/cli/index.js +8 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils/cli-git.d.ts +3 -0
- package/dist/cli/utils/cli-git.d.ts.map +1 -0
- package/dist/cli/utils/cli-git.js +13 -0
- package/dist/cli/utils/cli-git.js.map +1 -0
- package/dist/cli/utils/cli-npm.d.ts +7 -0
- package/dist/cli/utils/cli-npm.d.ts.map +1 -0
- package/dist/cli/utils/cli-npm.js +55 -0
- package/dist/cli/utils/cli-npm.js.map +1 -0
- package/dist/cli/utils/cli-os.d.ts +4 -0
- package/dist/cli/utils/cli-os.d.ts.map +1 -0
- package/dist/cli/utils/cli-os.js +56 -0
- package/dist/cli/utils/cli-os.js.map +1 -0
- package/dist/utils/get-configuration.d.ts +2 -0
- package/dist/utils/get-configuration.d.ts.map +1 -1
- package/dist/utils/get-configuration.js +10 -1
- package/dist/utils/get-configuration.js.map +1 -1
- package/package.json +9 -9
- package/src/cli/commands/index.ts +2 -0
- package/src/cli/commands/lint.ts +19 -0
- package/src/cli/commands/mfe-publish.ts +317 -0
- package/src/cli/commands/styles-check.ts +141 -0
- package/src/cli/index.ts +16 -0
- package/src/cli/utils/cli-git.ts +9 -0
- package/src/cli/utils/cli-npm.ts +55 -0
- package/src/cli/utils/cli-os.ts +76 -0
- package/src/utils/get-configuration.ts +11 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import process from 'process';
|
|
4
|
+
import {
|
|
5
|
+
getFolders,
|
|
6
|
+
isBundle,
|
|
7
|
+
isLegacy,
|
|
8
|
+
isStyleCheckDisabled,
|
|
9
|
+
isWebComponent,
|
|
10
|
+
log,
|
|
11
|
+
} from '../../utils';
|
|
12
|
+
import { Command } from './index';
|
|
13
|
+
|
|
14
|
+
interface FileInfo {
|
|
15
|
+
path: string;
|
|
16
|
+
relativePath: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const styleCheckError = [
|
|
20
|
+
'!!!!!!!!!!!!! STYLE CHECK ERROR !!!!!!!!!!!!!',
|
|
21
|
+
'Style check failed with following errors:',
|
|
22
|
+
];
|
|
23
|
+
const designSystem = 'design-system.css';
|
|
24
|
+
|
|
25
|
+
enum PackageType {
|
|
26
|
+
App = 'app',
|
|
27
|
+
WebComponent = 'web_component',
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function readDir(startPath: string, filter: string[]): string[] {
|
|
31
|
+
let out: string[] = [];
|
|
32
|
+
|
|
33
|
+
if (!fs.existsSync(startPath)) {
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const files = fs.readdirSync(startPath);
|
|
38
|
+
for (const file of files) {
|
|
39
|
+
const filename = path.join(startPath, file);
|
|
40
|
+
const stat = fs.lstatSync(filename);
|
|
41
|
+
|
|
42
|
+
if (stat.isDirectory()) {
|
|
43
|
+
out = [...out, ...readDir(filename, filter)];
|
|
44
|
+
} else if (filter.some(f => filename.endsWith(f))) {
|
|
45
|
+
out.push(filename);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const findStyleFiles = (basePath: string, sourceFolder: string): FileInfo[] => {
|
|
53
|
+
const sourcePath = path.join(basePath, sourceFolder);
|
|
54
|
+
const files = readDir(sourcePath, ['.css', '.less']);
|
|
55
|
+
|
|
56
|
+
return files.map(f => ({
|
|
57
|
+
path: f,
|
|
58
|
+
relativePath: f.replace(sourcePath, '').substring(1),
|
|
59
|
+
}));
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const checkStyleFiles = (files: FileInfo[], packageType: PackageType): string[] | undefined => {
|
|
63
|
+
const errors = [];
|
|
64
|
+
const patterns = [
|
|
65
|
+
"@import '~@servicetitan/tokens/core/tokens.css';",
|
|
66
|
+
"@import '~@servicetitan/anvil-fonts/dist/css/anvil-fonts.css';",
|
|
67
|
+
"@import '~@servicetitan/design-system/dist/system.min.css';",
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
for (const file of files) {
|
|
71
|
+
if (
|
|
72
|
+
[PackageType.App, PackageType.WebComponent].includes(packageType) &&
|
|
73
|
+
file.relativePath === designSystem
|
|
74
|
+
) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const content = fs.readFileSync(file.path);
|
|
79
|
+
|
|
80
|
+
for (const pattern of patterns) {
|
|
81
|
+
if (content.includes(pattern)) {
|
|
82
|
+
errors.push(`file ${file.relativePath} contains link to "${pattern}"`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return errors.length ? errors : undefined;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const checkErrors = (errors: string[] | undefined) => {
|
|
91
|
+
if (!errors) {
|
|
92
|
+
log.info('style check: OK');
|
|
93
|
+
} else {
|
|
94
|
+
log.error([...styleCheckError, ...errors].join('\n'));
|
|
95
|
+
throw new Error('style check error, please check logs above');
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
function checkStylesLib(_files: FileInfo[]) {
|
|
100
|
+
/* ToDo: add checks for libraries */
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function checkStylesApp(files: FileInfo[]) {
|
|
104
|
+
if (!files.some(f => f.relativePath === designSystem)) {
|
|
105
|
+
log.warning(
|
|
106
|
+
"application doesn't have design-system.css. Please check https://docs.st.dev/docs/frontend/micro-frontends#host-configuration"
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
checkErrors(checkStyleFiles(files, PackageType.App));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function checkStylesWebComponent(files: FileInfo[]) {
|
|
114
|
+
checkErrors(checkStyleFiles(files, PackageType.WebComponent));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export class StylesCheck implements Command {
|
|
118
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
119
|
+
async execute() {
|
|
120
|
+
if (isLegacy()) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (isStyleCheckDisabled()) {
|
|
125
|
+
log.info('style check is disabled');
|
|
126
|
+
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const projectFolders = getFolders();
|
|
131
|
+
const files = findStyleFiles(process.cwd(), projectFolders.source);
|
|
132
|
+
|
|
133
|
+
if (!isBundle()) {
|
|
134
|
+
checkStylesLib(files);
|
|
135
|
+
} else if (isWebComponent()) {
|
|
136
|
+
checkStylesWebComponent(files);
|
|
137
|
+
} else {
|
|
138
|
+
checkStylesApp(files);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
package/src/cli/index.ts
CHANGED
|
@@ -10,6 +10,10 @@ import {
|
|
|
10
10
|
BundlePackage,
|
|
11
11
|
Lint,
|
|
12
12
|
Tests,
|
|
13
|
+
StylesCheck,
|
|
14
|
+
MFEPackageClean,
|
|
15
|
+
MFEPackagePublish,
|
|
16
|
+
MFEPublish,
|
|
13
17
|
} from './commands';
|
|
14
18
|
|
|
15
19
|
interface Newable<T> {
|
|
@@ -39,6 +43,18 @@ function getCommand(name: string): Newable<Command> {
|
|
|
39
43
|
case 'test':
|
|
40
44
|
return Tests;
|
|
41
45
|
|
|
46
|
+
case 'styles-check':
|
|
47
|
+
return StylesCheck;
|
|
48
|
+
|
|
49
|
+
case 'mfe-publish':
|
|
50
|
+
return MFEPublish;
|
|
51
|
+
|
|
52
|
+
case 'mfe-package-publish':
|
|
53
|
+
return MFEPackagePublish;
|
|
54
|
+
|
|
55
|
+
case 'mfe-package-clean':
|
|
56
|
+
return MFEPackageClean;
|
|
57
|
+
|
|
42
58
|
default:
|
|
43
59
|
log.error(`${name}: command not found!`);
|
|
44
60
|
process.exit(127);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { runCommandOutput } from './cli-os';
|
|
2
|
+
|
|
3
|
+
export const gitGetBranch = (): string => {
|
|
4
|
+
return runCommandOutput('git rev-parse --abbrev-ref HEAD').trim();
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const gitGetCommitHash = (): string => {
|
|
8
|
+
return runCommandOutput('git rev-parse --short HEAD').trim();
|
|
9
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { runCommand, runCommandOutput } from './cli-os';
|
|
2
|
+
|
|
3
|
+
export const npmGetPackageVersions = (registry: string, packageName: string): string[] => {
|
|
4
|
+
try {
|
|
5
|
+
const v = runCommandOutput(
|
|
6
|
+
`npm show ${packageName} versions --registry ${registry} --json`,
|
|
7
|
+
{ timeout: 10000 }
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
return JSON.parse(v);
|
|
11
|
+
} catch {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const npmGetPackageVersionDates = (
|
|
17
|
+
registry: string,
|
|
18
|
+
packageName: string
|
|
19
|
+
): [string, Date][] => {
|
|
20
|
+
try {
|
|
21
|
+
const v = runCommandOutput(`npm view ${packageName} time --registry ${registry} --json`, {
|
|
22
|
+
timeout: 10000,
|
|
23
|
+
});
|
|
24
|
+
const map = JSON.parse(v);
|
|
25
|
+
|
|
26
|
+
return Object.keys(map).reduce(
|
|
27
|
+
(out, version) => [...out, [version, new Date(map[version])]],
|
|
28
|
+
[]
|
|
29
|
+
);
|
|
30
|
+
} catch {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const npmUnpublish = async (
|
|
36
|
+
registry: string,
|
|
37
|
+
packageName: string,
|
|
38
|
+
packageVersion: string
|
|
39
|
+
) => {
|
|
40
|
+
await runCommand(`npm unpublish ${packageName}@${packageVersion} --registry ${registry}`, {
|
|
41
|
+
timeout: 10000,
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const npmPublishDry = async () => {
|
|
46
|
+
await runCommand('npm publish --dry-run');
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const npmPublish = async (tag?: string) => {
|
|
50
|
+
await runCommand(['npm publish', !!tag && `--tag ${tag}`]);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const npmPackageSet = async (key: string, value: string) => {
|
|
54
|
+
await runCommand(`npm pkg set ${key}=${value}`);
|
|
55
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
execSync,
|
|
3
|
+
ExecSyncOptionsWithBufferEncoding,
|
|
4
|
+
spawn,
|
|
5
|
+
SpawnOptionsWithoutStdio,
|
|
6
|
+
} from 'child_process';
|
|
7
|
+
import { log } from '../../utils';
|
|
8
|
+
|
|
9
|
+
export const runCommand = (
|
|
10
|
+
command: string | (string | false)[],
|
|
11
|
+
opts?: SpawnOptionsWithoutStdio
|
|
12
|
+
): Promise<void> => {
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
const commandArray: string[] = Array.isArray(command)
|
|
15
|
+
? command
|
|
16
|
+
.filter(c => !!c)
|
|
17
|
+
.map(c => c.toString())
|
|
18
|
+
.join(' ')
|
|
19
|
+
.split(' ')
|
|
20
|
+
: command.split(' ');
|
|
21
|
+
const fullCommand = commandArray.join(' ');
|
|
22
|
+
|
|
23
|
+
const commandName = commandArray.shift();
|
|
24
|
+
|
|
25
|
+
if (!commandName) {
|
|
26
|
+
reject();
|
|
27
|
+
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
log.info(`run command ${fullCommand}`);
|
|
32
|
+
|
|
33
|
+
const proc = spawn(commandName, commandArray, opts);
|
|
34
|
+
|
|
35
|
+
proc.stdout.pipe(process.stdout);
|
|
36
|
+
proc.stderr.pipe(process.stderr);
|
|
37
|
+
|
|
38
|
+
proc.on('exit', function (code: any) {
|
|
39
|
+
log.info(`command finished with code ${code}`, fullCommand);
|
|
40
|
+
|
|
41
|
+
if (code) {
|
|
42
|
+
reject();
|
|
43
|
+
} else {
|
|
44
|
+
resolve();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const runCommandOutput = (
|
|
51
|
+
command: string | (string | false)[],
|
|
52
|
+
options?: ExecSyncOptionsWithBufferEncoding
|
|
53
|
+
): string => {
|
|
54
|
+
const commandArray: string[] = Array.isArray(command)
|
|
55
|
+
? command
|
|
56
|
+
.filter(c => !!c)
|
|
57
|
+
.map(c => c.toString())
|
|
58
|
+
.join(' ')
|
|
59
|
+
.split(' ')
|
|
60
|
+
: command.split(' ');
|
|
61
|
+
const fullCommand = commandArray.join(' ');
|
|
62
|
+
|
|
63
|
+
const commandName = commandArray.shift();
|
|
64
|
+
|
|
65
|
+
if (!commandName) {
|
|
66
|
+
throw new Error();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
log.info(`run command ${fullCommand}`);
|
|
70
|
+
|
|
71
|
+
const result = execSync(fullCommand, options).toString();
|
|
72
|
+
|
|
73
|
+
log.info('command finished', result);
|
|
74
|
+
|
|
75
|
+
return result;
|
|
76
|
+
};
|
|
@@ -19,6 +19,7 @@ export interface WebpackConfiguration
|
|
|
19
19
|
> {
|
|
20
20
|
'custom-style-rules'?: boolean;
|
|
21
21
|
'expose-shared-dependencies'?: boolean;
|
|
22
|
+
'disable-style-check'?: boolean;
|
|
22
23
|
'proxy'?: WebpackDevServerConfiguration['proxy'] | string;
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -122,3 +123,13 @@ export function getStylelintConfiguration() {
|
|
|
122
123
|
export function getJestConfiguration() {
|
|
123
124
|
return getConfiguration().test ?? {};
|
|
124
125
|
}
|
|
126
|
+
|
|
127
|
+
export function isStyleCheckDisabled() {
|
|
128
|
+
const configuration = getConfiguration();
|
|
129
|
+
|
|
130
|
+
if (typeof configuration.webpack !== 'object') {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return configuration.webpack?.['disable-style-check'] === true;
|
|
135
|
+
}
|