@servicetitan/startup 34.0.0 → 34.0.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/review/rules/require-tsconfig-references.d.ts +2 -0
- package/dist/cli/commands/review/rules/require-tsconfig-references.d.ts.map +1 -1
- package/dist/cli/commands/review/rules/require-tsconfig-references.js +17 -7
- package/dist/cli/commands/review/rules/require-tsconfig-references.js.map +1 -1
- package/package.json +6 -6
- package/src/cli/commands/review/rules/__tests__/require-tsconfig-references.test.ts +124 -246
- package/src/cli/commands/review/rules/require-tsconfig-references.ts +24 -8
|
@@ -19,6 +19,8 @@ export declare class RequireTsconfigReferences implements PackageRule {
|
|
|
19
19
|
private collectTsConfigFiles;
|
|
20
20
|
private findMissingDependencyReferences;
|
|
21
21
|
private readonly checkTsConfigReferences;
|
|
22
|
+
private isDefaultTsConfig;
|
|
23
|
+
private isDirectory;
|
|
22
24
|
}
|
|
23
25
|
export {};
|
|
24
26
|
//# sourceMappingURL=require-tsconfig-references.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-tsconfig-references.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/review/rules/require-tsconfig-references.ts"],"names":[],"mappings":"AAIA,OAAO,EAAwB,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAOpF,UAAU,SAAS;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;AAEhD,qBAAa,yBAA0B,YAAW,WAAW;IACzD,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,qBAAqB,CAAe;IAE5C,IAAI,EAAE,WAEL;IAED,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE;IAYlC,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS;
|
|
1
|
+
{"version":3,"file":"require-tsconfig-references.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/review/rules/require-tsconfig-references.ts"],"names":[],"mappings":"AAIA,OAAO,EAAwB,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAOpF,UAAU,SAAS;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;AAEhD,qBAAa,yBAA0B,YAAW,WAAW;IACzD,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,qBAAqB,CAAe;IAE5C,IAAI,EAAE,WAEL;IAED,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE;IAYlC,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS;IAgBvB,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,qBAAqB;IAO7B,OAAO,CAAC,6BAA6B;IAwBrC,OAAO,CAAC,wBAAwB;IAWhC,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,+BAA+B;IA6BvC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAWtC;IAEF,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,WAAW;CAOtB"}
|
|
@@ -54,10 +54,7 @@ class RequireTsconfigReferences {
|
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
const { tsconfigPath, expectedPath } = data;
|
|
57
|
-
const tsconfig = (0, _utils.
|
|
58
|
-
if (!tsconfig) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
57
|
+
const tsconfig = (0, _utils.readJson)(tsconfigPath);
|
|
61
58
|
const references = (_tsconfig_references = tsconfig.references) !== null && _tsconfig_references !== void 0 ? _tsconfig_references : [];
|
|
62
59
|
references.push({
|
|
63
60
|
path: expectedPath
|
|
@@ -75,6 +72,9 @@ class RequireTsconfigReferences {
|
|
|
75
72
|
return Object.keys(dependencies).filter((dependency)=>this.workspacePackageNames.has(dependency));
|
|
76
73
|
}
|
|
77
74
|
normalizeTsConfigPath(filePath) {
|
|
75
|
+
if (this.isDirectory(filePath)) {
|
|
76
|
+
return _nodepath.default.join(filePath, 'tsconfig.json');
|
|
77
|
+
}
|
|
78
78
|
return filePath.endsWith('.json') ? filePath : `${filePath}.json`;
|
|
79
79
|
}
|
|
80
80
|
getTsConfigReferencedPackages(tsconfigPath) {
|
|
@@ -85,8 +85,7 @@ class RequireTsconfigReferences {
|
|
|
85
85
|
const tsconfigDir = _nodepath.default.dirname(tsconfigPath);
|
|
86
86
|
const referencedPackages = new Set();
|
|
87
87
|
for (const reference of config.references){
|
|
88
|
-
const
|
|
89
|
-
const resolvedRefPath = _nodepath.default.resolve(tsconfigDir, normalizedPath);
|
|
88
|
+
const resolvedRefPath = this.normalizeTsConfigPath(_nodepath.default.resolve(tsconfigDir, reference.path));
|
|
90
89
|
const refDir = _nodepath.default.dirname(resolvedRefPath);
|
|
91
90
|
const packageName = this.locationToPackageName.get(refDir);
|
|
92
91
|
if (packageName) {
|
|
@@ -99,7 +98,8 @@ class RequireTsconfigReferences {
|
|
|
99
98
|
const relativePath = _nodepath.default.relative(fromLocation, toLocation);
|
|
100
99
|
const tsconfigFile = (0, _utils.getTsConfig)(toLocation);
|
|
101
100
|
const tsconfigName = _nodepath.default.basename(tsconfigFile);
|
|
102
|
-
|
|
101
|
+
const referencePath = this.isDefaultTsConfig(tsconfigName) ? relativePath : _nodepath.default.join(relativePath, tsconfigName);
|
|
102
|
+
return referencePath.replaceAll('\\', '/');
|
|
103
103
|
}
|
|
104
104
|
collectTsConfigFiles(location) {
|
|
105
105
|
const tsconfigFiles = (0, _glob.globSync)([
|
|
@@ -128,6 +128,16 @@ class RequireTsconfigReferences {
|
|
|
128
128
|
};
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
|
+
isDefaultTsConfig(name) {
|
|
132
|
+
return name === 'tsconfig.json';
|
|
133
|
+
}
|
|
134
|
+
isDirectory(file) {
|
|
135
|
+
try {
|
|
136
|
+
return _nodefs.default.statSync(file).isDirectory();
|
|
137
|
+
} catch (unused) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
131
141
|
constructor(){
|
|
132
142
|
_define_property(this, "packageNameToLocation", void 0);
|
|
133
143
|
_define_property(this, "locationToPackageName", void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/cli/commands/review/rules/require-tsconfig-references.ts"],"sourcesContent":["import { globSync } from 'glob';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { getTsConfig, prettifySync, readJsonSafe } from '../../../../utils';\nimport { FixCategory, Package, PackageError, PackageRule, Project } from '../types';\nimport { checkPackages } from '../utils';\n\ninterface TsConfig {\n references?: { path: string }[];\n}\n\ninterface ErrorData {\n tsconfigPath: string;\n missingReference: string;\n expectedPath: string;\n}\n\nexport type RuleError = PackageError<ErrorData>;\n\nexport class RequireTsconfigReferences implements PackageRule {\n private packageNameToLocation!: Map<string, string>;\n private locationToPackageName!: Map<string, string>;\n private workspacePackageNames!: Set<string>;\n\n get id() {\n return 'require-tsconfig-references';\n }\n\n run(project: Project): RuleError[] {\n this.packageNameToLocation = new Map(\n project.packages.map(({ name, location }) => [name, location])\n );\n this.locationToPackageName = new Map(\n project.packages.map(({ name, location }) => [path.resolve(location), name])\n );\n this.workspacePackageNames = new Set(project.packages.map(({ name }) => name));\n\n return checkPackages(this, project, this.checkTsConfigReferences);\n }\n\n fix({ data }: RuleError) {\n if (!data) {\n return;\n }\n\n const { tsconfigPath, expectedPath } = data;\n const tsconfig = readJsonSafe<TsConfig>(tsconfigPath);\n if (!tsconfig) {\n return;\n }\n\n const references = tsconfig.references ?? [];\n references.push({ path: expectedPath });\n tsconfig.references = references;\n\n fs.writeFileSync(tsconfigPath, JSON.stringify(tsconfig) + '\\n', 'utf-8');\n prettifySync(tsconfigPath);\n }\n\n private getLocalDependencies(pkg: Package) {\n const dependencies = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n ...pkg.peerDependencies,\n };\n\n return Object.keys(dependencies).filter(dependency =>\n this.workspacePackageNames.has(dependency)\n );\n }\n\n private normalizeTsConfigPath(filePath: string): string {\n return filePath.endsWith('.json') ? filePath : `${filePath}.json`;\n }\n\n private getTsConfigReferencedPackages(tsconfigPath: string) {\n const config = readJsonSafe<TsConfig>(tsconfigPath);\n if (!config?.references) {\n return new Set<string>();\n }\n\n const tsconfigDir = path.dirname(tsconfigPath);\n const referencedPackages = new Set<string>();\n\n for (const reference of config.references) {\n const normalizedPath = this.normalizeTsConfigPath(reference.path);\n const resolvedRefPath = path.resolve(tsconfigDir, normalizedPath);\n const refDir = path.dirname(resolvedRefPath);\n const packageName = this.locationToPackageName.get(refDir);\n\n if (packageName) {\n referencedPackages.add(packageName);\n }\n }\n\n return referencedPackages;\n }\n\n private getExpectedReferencePath(fromLocation: string, toLocation: string) {\n const relativePath = path.relative(fromLocation, toLocation);\n const tsconfigFile = getTsConfig(toLocation);\n const tsconfigName = path.basename(tsconfigFile);\n\n return path.join(relativePath, tsconfigName).replaceAll('\\\\', '/');\n }\n\n private collectTsConfigFiles(location: string): string[] {\n const tsconfigFiles = globSync(['tsconfig.json', 'tsconfig.*.json'], {\n absolute: false,\n cwd: location,\n });\n\n return tsconfigFiles.map(tsconfigFile => path.join(location, tsconfigFile));\n }\n\n private findMissingDependencyReferences(\n pkg: Package,\n tsconfigPath: string,\n localDependencies: string[]\n ): RuleError[] {\n const referencedPackages = this.getTsConfigReferencedPackages(tsconfigPath);\n\n return localDependencies\n .filter(dependency => !referencedPackages.has(dependency))\n .map(dependency => {\n const dependencyLocation = this.packageNameToLocation.get(dependency)!;\n\n return {\n id: this.id,\n message: `missing reference for dependency: ${dependency}`,\n location: tsconfigPath,\n fixable: FixCategory.normal,\n data: {\n tsconfigPath,\n missingReference: dependency,\n expectedPath: this.getExpectedReferencePath(\n pkg.location,\n dependencyLocation\n ),\n },\n };\n });\n }\n\n private readonly checkTsConfigReferences = (pkg: Package) => {\n if (pkg.location === '.') {\n return [];\n }\n\n const tsconfigFiles = this.collectTsConfigFiles(pkg.location);\n const localDependencies = this.getLocalDependencies(pkg);\n\n return tsconfigFiles.flatMap(tsconfigPath =>\n this.findMissingDependencyReferences(pkg, tsconfigPath, localDependencies)\n );\n };\n}\n"],"names":["RequireTsconfigReferences","id","run","project","packageNameToLocation","Map","packages","map","name","location","locationToPackageName","path","resolve","workspacePackageNames","Set","checkPackages","checkTsConfigReferences","fix","data","tsconfig","tsconfigPath","expectedPath","readJsonSafe","references","push","fs","writeFileSync","JSON","stringify","prettifySync","getLocalDependencies","pkg","dependencies","devDependencies","peerDependencies","Object","keys","filter","dependency","has","normalizeTsConfigPath","filePath","endsWith","getTsConfigReferencedPackages","config","tsconfigDir","dirname","referencedPackages","reference","normalizedPath","resolvedRefPath","refDir","packageName","get","add","getExpectedReferencePath","fromLocation","toLocation","relativePath","relative","tsconfigFile","getTsConfig","tsconfigName","basename","join","replaceAll","collectTsConfigFiles","tsconfigFiles","globSync","absolute","cwd","findMissingDependencyReferences","localDependencies","dependencyLocation","message","fixable","FixCategory","normal","missingReference","flatMap"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/cli/commands/review/rules/require-tsconfig-references.ts"],"sourcesContent":["import { globSync } from 'glob';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { getTsConfig, prettifySync, readJson, readJsonSafe } from '../../../../utils';\nimport { FixCategory, Package, PackageError, PackageRule, Project } from '../types';\nimport { checkPackages } from '../utils';\n\ninterface TsConfig {\n references?: { path: string }[];\n}\n\ninterface ErrorData {\n tsconfigPath: string;\n missingReference: string;\n expectedPath: string;\n}\n\nexport type RuleError = PackageError<ErrorData>;\n\nexport class RequireTsconfigReferences implements PackageRule {\n private packageNameToLocation!: Map<string, string>;\n private locationToPackageName!: Map<string, string>;\n private workspacePackageNames!: Set<string>;\n\n get id() {\n return 'require-tsconfig-references';\n }\n\n run(project: Project): RuleError[] {\n this.packageNameToLocation = new Map(\n project.packages.map(({ name, location }) => [name, location])\n );\n this.locationToPackageName = new Map(\n project.packages.map(({ name, location }) => [path.resolve(location), name])\n );\n this.workspacePackageNames = new Set(project.packages.map(({ name }) => name));\n\n return checkPackages(this, project, this.checkTsConfigReferences);\n }\n\n fix({ data }: RuleError) {\n if (!data) {\n return;\n }\n\n const { tsconfigPath, expectedPath } = data;\n const tsconfig = readJson<TsConfig>(tsconfigPath);\n\n const references = tsconfig.references ?? [];\n references.push({ path: expectedPath });\n tsconfig.references = references;\n\n fs.writeFileSync(tsconfigPath, JSON.stringify(tsconfig) + '\\n', 'utf-8');\n prettifySync(tsconfigPath);\n }\n\n private getLocalDependencies(pkg: Package) {\n const dependencies = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n ...pkg.peerDependencies,\n };\n\n return Object.keys(dependencies).filter(dependency =>\n this.workspacePackageNames.has(dependency)\n );\n }\n\n private normalizeTsConfigPath(filePath: string): string {\n if (this.isDirectory(filePath)) {\n return path.join(filePath, 'tsconfig.json');\n }\n return filePath.endsWith('.json') ? filePath : `${filePath}.json`;\n }\n\n private getTsConfigReferencedPackages(tsconfigPath: string) {\n const config = readJsonSafe<TsConfig>(tsconfigPath);\n if (!config?.references) {\n return new Set<string>();\n }\n\n const tsconfigDir = path.dirname(tsconfigPath);\n const referencedPackages = new Set<string>();\n\n for (const reference of config.references) {\n const resolvedRefPath = this.normalizeTsConfigPath(\n path.resolve(tsconfigDir, reference.path)\n );\n const refDir = path.dirname(resolvedRefPath);\n const packageName = this.locationToPackageName.get(refDir);\n\n if (packageName) {\n referencedPackages.add(packageName);\n }\n }\n\n return referencedPackages;\n }\n\n private getExpectedReferencePath(fromLocation: string, toLocation: string) {\n const relativePath = path.relative(fromLocation, toLocation);\n const tsconfigFile = getTsConfig(toLocation);\n const tsconfigName = path.basename(tsconfigFile);\n const referencePath = this.isDefaultTsConfig(tsconfigName)\n ? relativePath\n : path.join(relativePath, tsconfigName);\n\n return referencePath.replaceAll('\\\\', '/');\n }\n\n private collectTsConfigFiles(location: string): string[] {\n const tsconfigFiles = globSync(['tsconfig.json', 'tsconfig.*.json'], {\n absolute: false,\n cwd: location,\n });\n\n return tsconfigFiles.map(tsconfigFile => path.join(location, tsconfigFile));\n }\n\n private findMissingDependencyReferences(\n pkg: Package,\n tsconfigPath: string,\n localDependencies: string[]\n ): RuleError[] {\n const referencedPackages = this.getTsConfigReferencedPackages(tsconfigPath);\n\n return localDependencies\n .filter(dependency => !referencedPackages.has(dependency))\n .map(dependency => {\n const dependencyLocation = this.packageNameToLocation.get(dependency)!;\n\n return {\n id: this.id,\n message: `missing reference for dependency: ${dependency}`,\n location: tsconfigPath,\n fixable: FixCategory.normal,\n data: {\n tsconfigPath,\n missingReference: dependency,\n expectedPath: this.getExpectedReferencePath(\n pkg.location,\n dependencyLocation\n ),\n },\n };\n });\n }\n\n private readonly checkTsConfigReferences = (pkg: Package) => {\n if (pkg.location === '.') {\n return [];\n }\n\n const tsconfigFiles = this.collectTsConfigFiles(pkg.location);\n const localDependencies = this.getLocalDependencies(pkg);\n\n return tsconfigFiles.flatMap(tsconfigPath =>\n this.findMissingDependencyReferences(pkg, tsconfigPath, localDependencies)\n );\n };\n\n private isDefaultTsConfig(name: string) {\n return name === 'tsconfig.json';\n }\n\n private isDirectory(file: string) {\n try {\n return fs.statSync(file).isDirectory();\n } catch {\n return false;\n }\n }\n}\n"],"names":["RequireTsconfigReferences","id","run","project","packageNameToLocation","Map","packages","map","name","location","locationToPackageName","path","resolve","workspacePackageNames","Set","checkPackages","checkTsConfigReferences","fix","data","tsconfig","tsconfigPath","expectedPath","readJson","references","push","fs","writeFileSync","JSON","stringify","prettifySync","getLocalDependencies","pkg","dependencies","devDependencies","peerDependencies","Object","keys","filter","dependency","has","normalizeTsConfigPath","filePath","isDirectory","join","endsWith","getTsConfigReferencedPackages","config","readJsonSafe","tsconfigDir","dirname","referencedPackages","reference","resolvedRefPath","refDir","packageName","get","add","getExpectedReferencePath","fromLocation","toLocation","relativePath","relative","tsconfigFile","getTsConfig","tsconfigName","basename","referencePath","isDefaultTsConfig","replaceAll","collectTsConfigFiles","tsconfigFiles","globSync","absolute","cwd","findMissingDependencyReferences","localDependencies","dependencyLocation","message","fixable","FixCategory","normal","missingReference","file","statSync","flatMap"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@servicetitan/startup",
|
|
3
|
-
"version": "34.0.
|
|
3
|
+
"version": "34.0.1",
|
|
4
4
|
"description": "CLI to create multi-package Lerna projects with TypeScript and React",
|
|
5
5
|
"homepage": "https://docs.st.dev/docs/frontend/uikit/startup",
|
|
6
6
|
"repository": {
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
"@jest/core": "~30.2.0",
|
|
55
55
|
"@jest/types": "~30.2.0",
|
|
56
56
|
"@jsdevtools/coverage-istanbul-loader": "^3.0.5",
|
|
57
|
-
"@servicetitan/eslint-config": "34.0.
|
|
58
|
-
"@servicetitan/install": "34.0.
|
|
59
|
-
"@servicetitan/startup-utils": "34.0.
|
|
60
|
-
"@servicetitan/stylelint-config": "34.0.
|
|
57
|
+
"@servicetitan/eslint-config": "34.0.1",
|
|
58
|
+
"@servicetitan/install": "34.0.1",
|
|
59
|
+
"@servicetitan/startup-utils": "34.0.1",
|
|
60
|
+
"@servicetitan/stylelint-config": "34.0.1",
|
|
61
61
|
"@svgr/webpack": "^8.1.0",
|
|
62
62
|
"@swc/cli": "^0.5.0",
|
|
63
63
|
"@swc/core": "1.15.10",
|
|
@@ -142,5 +142,5 @@
|
|
|
142
142
|
"cli": {
|
|
143
143
|
"webpack": false
|
|
144
144
|
},
|
|
145
|
-
"gitHead": "
|
|
145
|
+
"gitHead": "e42375d199bbc11b2f0b8881c26a8f0229446256"
|
|
146
146
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { fs, vol } from 'memfs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
import { mockProject } from '../__mocks__';
|
|
5
|
-
|
|
3
|
+
import { createPackage } from '../../../../../__mocks__';
|
|
6
4
|
import { prettifySync } from '../../../../../utils';
|
|
5
|
+
import { Package } from '../../types';
|
|
6
|
+
import { mockProject } from '../__mocks__';
|
|
7
7
|
import { RequireTsconfigReferences } from '../require-tsconfig-references';
|
|
8
8
|
|
|
9
9
|
jest.mock('node:fs', () => fs);
|
|
@@ -17,299 +17,177 @@ jest.mock('../../../../../utils', () => ({
|
|
|
17
17
|
|
|
18
18
|
describe(`[startup] Review ${RequireTsconfigReferences.name}`, () => {
|
|
19
19
|
let rule: RequireTsconfigReferences;
|
|
20
|
-
let config: ReviewConfiguration;
|
|
21
20
|
let packages: Package[];
|
|
22
21
|
|
|
23
22
|
beforeEach(() => {
|
|
24
23
|
rule = new RequireTsconfigReferences();
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
packages = [
|
|
25
|
+
// Note, tests assume the "app" that depends on local package(s) is first
|
|
26
|
+
createPackage({ name: 'app', dependencies: { utils: '1.0.0' } }),
|
|
27
|
+
createPackage({ name: 'utils' }),
|
|
28
|
+
];
|
|
27
29
|
});
|
|
28
30
|
|
|
29
31
|
afterEach(() => vol.reset());
|
|
30
32
|
|
|
31
|
-
const subject = () => rule.run(mockProject({
|
|
32
|
-
const fixSubject = () => {
|
|
33
|
-
const ruleErrors = subject();
|
|
33
|
+
const subject = () => rule.run(mockProject({ packages }));
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
function appTsConfig() {
|
|
36
|
+
return path.join(packages[0].location, 'tsconfig.json');
|
|
37
|
+
}
|
|
37
38
|
|
|
38
|
-
function
|
|
39
|
-
packages = pkgs;
|
|
39
|
+
function volFromJSON(json: Record<string, any>) {
|
|
40
40
|
vol.fromJSON(
|
|
41
41
|
Object.fromEntries(
|
|
42
|
-
Object.entries(
|
|
42
|
+
Object.entries(json).map(([filePath, content]) => [
|
|
43
43
|
filePath,
|
|
44
|
-
JSON.stringify(content
|
|
44
|
+
JSON.stringify(content),
|
|
45
45
|
])
|
|
46
46
|
)
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
beforeEach(() => {
|
|
52
|
-
setupPackages(
|
|
53
|
-
[
|
|
54
|
-
{
|
|
55
|
-
name: '@servicetitan/runtime',
|
|
56
|
-
location: path.normalize('packages/runtime'),
|
|
57
|
-
dependencies: {
|
|
58
|
-
'@servicetitan/log-service': '1.0.0',
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
name: '@servicetitan/log-service',
|
|
63
|
-
location: path.normalize('packages/log-service'),
|
|
64
|
-
},
|
|
65
|
-
],
|
|
66
|
-
{
|
|
67
|
-
[path.normalize('packages/runtime/tsconfig.json')]: {
|
|
68
|
-
references: [{ path: '../log-service/tsconfig.json' }],
|
|
69
|
-
},
|
|
70
|
-
[path.normalize('packages/log-service/tsconfig.json')]: {},
|
|
71
|
-
}
|
|
72
|
-
);
|
|
73
|
-
});
|
|
74
|
-
|
|
50
|
+
function itReportsNoErrors() {
|
|
75
51
|
test('reports no errors', () => {
|
|
76
52
|
expect(subject()).toEqual([]);
|
|
77
53
|
});
|
|
78
|
-
}
|
|
54
|
+
}
|
|
79
55
|
|
|
80
|
-
describe('when
|
|
56
|
+
describe('when package has correct tsconfig reference', () => {
|
|
81
57
|
beforeEach(() => {
|
|
82
|
-
|
|
83
|
-
[
|
|
84
|
-
|
|
85
|
-
name: '@servicetitan/runtime',
|
|
86
|
-
location: path.normalize('packages/runtime'),
|
|
87
|
-
dependencies: {
|
|
88
|
-
'@servicetitan/log-service': '1.0.0',
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
name: '@servicetitan/log-service',
|
|
93
|
-
location: path.normalize('packages/log-service'),
|
|
94
|
-
},
|
|
95
|
-
],
|
|
96
|
-
{
|
|
97
|
-
[path.normalize('packages/runtime/tsconfig.json')]: {},
|
|
98
|
-
[path.normalize('packages/runtime/tsconfig.build.json')]: {},
|
|
99
|
-
[path.normalize('packages/log-service/tsconfig.json')]: {},
|
|
100
|
-
}
|
|
101
|
-
);
|
|
58
|
+
volFromJSON({
|
|
59
|
+
[appTsConfig()]: { references: [{ path: '../utils/tsconfig.json' }] },
|
|
60
|
+
});
|
|
102
61
|
});
|
|
103
62
|
|
|
104
|
-
|
|
105
|
-
expect(subject()).toEqual(
|
|
106
|
-
expect.arrayContaining([
|
|
107
|
-
{
|
|
108
|
-
id: 'require-tsconfig-references',
|
|
109
|
-
message: 'missing reference for dependency: @servicetitan/log-service',
|
|
110
|
-
location: path.normalize('packages/runtime/tsconfig.json'),
|
|
111
|
-
fixable: 'normal',
|
|
112
|
-
data: {
|
|
113
|
-
tsconfigPath: path.normalize('packages/runtime/tsconfig.json'),
|
|
114
|
-
missingReference: '@servicetitan/log-service',
|
|
115
|
-
expectedPath: '../log-service/tsconfig.json',
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
id: 'require-tsconfig-references',
|
|
120
|
-
message: 'missing reference for dependency: @servicetitan/log-service',
|
|
121
|
-
location: path.normalize('packages/runtime/tsconfig.build.json'),
|
|
122
|
-
fixable: 'normal',
|
|
123
|
-
data: {
|
|
124
|
-
tsconfigPath: path.normalize('packages/runtime/tsconfig.build.json'),
|
|
125
|
-
missingReference: '@servicetitan/log-service',
|
|
126
|
-
expectedPath: '../log-service/tsconfig.json',
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
])
|
|
130
|
-
);
|
|
131
|
-
});
|
|
63
|
+
itReportsNoErrors();
|
|
132
64
|
});
|
|
133
65
|
|
|
134
|
-
describe('when
|
|
66
|
+
describe('when reference is build config', () => {
|
|
135
67
|
beforeEach(() => {
|
|
136
|
-
|
|
137
|
-
[
|
|
138
|
-
|
|
139
|
-
name: '@servicetitan/runtime',
|
|
140
|
-
location: path.normalize('packages/runtime'),
|
|
141
|
-
devDependencies: { '@servicetitan/log-service': '1.0.0' },
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
name: '@servicetitan/examples',
|
|
145
|
-
location: path.normalize('packages/examples'),
|
|
146
|
-
peerDependencies: { '@servicetitan/log-service': '1.0.0' },
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
name: '@servicetitan/log-service',
|
|
150
|
-
location: path.normalize('packages/log-service'),
|
|
151
|
-
},
|
|
152
|
-
],
|
|
153
|
-
{
|
|
154
|
-
[path.normalize('packages/runtime/tsconfig.json')]: {},
|
|
155
|
-
[path.normalize('packages/examples/tsconfig.json')]: {},
|
|
156
|
-
[path.normalize('packages/log-service/tsconfig.json')]: {},
|
|
157
|
-
}
|
|
158
|
-
);
|
|
68
|
+
volFromJSON({
|
|
69
|
+
[appTsConfig()]: { references: [{ path: '../utils/tsconfig.build.json ' }] },
|
|
70
|
+
});
|
|
159
71
|
});
|
|
160
72
|
|
|
161
|
-
|
|
162
|
-
expect(subject()).toEqual([
|
|
163
|
-
{
|
|
164
|
-
id: 'require-tsconfig-references',
|
|
165
|
-
message: 'missing reference for dependency: @servicetitan/log-service',
|
|
166
|
-
location: path.normalize('packages/runtime/tsconfig.json'),
|
|
167
|
-
fixable: 'normal',
|
|
168
|
-
data: {
|
|
169
|
-
tsconfigPath: path.normalize('packages/runtime/tsconfig.json'),
|
|
170
|
-
missingReference: '@servicetitan/log-service',
|
|
171
|
-
expectedPath: '../log-service/tsconfig.json',
|
|
172
|
-
},
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
id: 'require-tsconfig-references',
|
|
176
|
-
message: 'missing reference for dependency: @servicetitan/log-service',
|
|
177
|
-
location: path.normalize('packages/examples/tsconfig.json'),
|
|
178
|
-
fixable: 'normal',
|
|
179
|
-
data: {
|
|
180
|
-
tsconfigPath: path.normalize('packages/examples/tsconfig.json'),
|
|
181
|
-
missingReference: '@servicetitan/log-service',
|
|
182
|
-
expectedPath: '../log-service/tsconfig.json',
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
]);
|
|
186
|
-
});
|
|
73
|
+
itReportsNoErrors();
|
|
187
74
|
});
|
|
188
75
|
|
|
189
|
-
describe('when
|
|
190
|
-
const tsconfigPath = path.normalize('packages/nonexistent/tsconfig.json');
|
|
191
|
-
|
|
76
|
+
describe('when reference omits .json extension', () => {
|
|
192
77
|
beforeEach(() => {
|
|
193
|
-
|
|
194
|
-
[
|
|
195
|
-
|
|
196
|
-
name: '@servicetitan/runtime',
|
|
197
|
-
location: path.normalize('packages/runtime'),
|
|
198
|
-
devDependencies: { '@servicetitan/log-service': '1.0.0' },
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
name: '@servicetitan/log-service',
|
|
202
|
-
location: path.normalize('packages/log-service'),
|
|
203
|
-
},
|
|
204
|
-
],
|
|
205
|
-
{}
|
|
206
|
-
);
|
|
78
|
+
volFromJSON({
|
|
79
|
+
[appTsConfig()]: { references: [{ path: '../utils/tsconfig' }] },
|
|
80
|
+
});
|
|
207
81
|
});
|
|
208
82
|
|
|
209
|
-
|
|
210
|
-
|
|
83
|
+
itReportsNoErrors();
|
|
84
|
+
});
|
|
211
85
|
|
|
212
|
-
|
|
86
|
+
describe('when reference is directory', () => {
|
|
87
|
+
beforeEach(() => {
|
|
88
|
+
volFromJSON({
|
|
89
|
+
[appTsConfig()]: { references: [{ path: '../utils' }] },
|
|
90
|
+
'packages/utils/tsconfig.json': {}, // ensures directory exists
|
|
91
|
+
});
|
|
213
92
|
});
|
|
214
|
-
});
|
|
215
93
|
|
|
216
|
-
|
|
217
|
-
|
|
94
|
+
itReportsNoErrors();
|
|
95
|
+
});
|
|
218
96
|
|
|
97
|
+
describe('when package is missing reference', () => {
|
|
219
98
|
beforeEach(() => {
|
|
220
|
-
|
|
221
|
-
[
|
|
222
|
-
{
|
|
223
|
-
name: '@servicetitan/runtime',
|
|
224
|
-
location: path.normalize('packages/runtime'),
|
|
225
|
-
dependencies: {
|
|
226
|
-
'@servicetitan/log-service': '1.0.0',
|
|
227
|
-
},
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
name: '@servicetitan/log-service',
|
|
231
|
-
location: path.normalize('packages/log-service'),
|
|
232
|
-
},
|
|
233
|
-
],
|
|
234
|
-
{
|
|
235
|
-
[tsconfigFilePath]: {
|
|
236
|
-
references: [{ path: '../existing/tsconfig.json' }],
|
|
237
|
-
},
|
|
238
|
-
}
|
|
239
|
-
);
|
|
99
|
+
volFromJSON({ [appTsConfig()]: {} });
|
|
240
100
|
});
|
|
241
101
|
|
|
242
|
-
|
|
243
|
-
|
|
102
|
+
function itReportsError() {
|
|
103
|
+
test('reports error', () => {
|
|
104
|
+
expect(subject()).toEqual([
|
|
105
|
+
expect.objectContaining({
|
|
106
|
+
id: 'require-tsconfig-references',
|
|
107
|
+
message: 'missing reference for dependency: utils',
|
|
108
|
+
location: appTsConfig(),
|
|
109
|
+
fixable: 'normal',
|
|
110
|
+
}),
|
|
111
|
+
]);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
itReportsError();
|
|
116
|
+
|
|
117
|
+
describe.each(['devDependencies', 'peerDependencies'])(
|
|
118
|
+
'when dependency is in %s',
|
|
119
|
+
(key: keyof Package) => {
|
|
120
|
+
beforeEach(() => {
|
|
121
|
+
const appPackage = packages[0];
|
|
122
|
+
appPackage[key] = appPackage.dependencies;
|
|
123
|
+
delete appPackage.dependencies;
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
itReportsError();
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
describe('when package is workspace root', () => {
|
|
131
|
+
beforeEach(() => (packages[0].location = '.'));
|
|
244
132
|
|
|
245
|
-
|
|
246
|
-
expect(content.references).toContainEqual({ path: '../existing/tsconfig.json' });
|
|
247
|
-
expect(content.references).toContainEqual({ path: '../log-service/tsconfig.json' });
|
|
133
|
+
itReportsNoErrors();
|
|
248
134
|
});
|
|
249
135
|
|
|
250
|
-
|
|
251
|
-
fixSubject()
|
|
136
|
+
describe('fix', () => {
|
|
137
|
+
const fixSubject = () => {
|
|
138
|
+
const ruleErrors = subject();
|
|
139
|
+
ruleErrors.forEach(rule.fix);
|
|
140
|
+
};
|
|
252
141
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
142
|
+
function expectReferences(references: Record<string, string>[]) {
|
|
143
|
+
const json = fs.readFileSync(appTsConfig(), { encoding: 'utf-8' }).toString();
|
|
144
|
+
expect(JSON.parse(json)).toEqual({ references });
|
|
145
|
+
}
|
|
256
146
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
setupPackages(
|
|
260
|
-
[
|
|
261
|
-
{
|
|
262
|
-
name: '@servicetitan/runtime',
|
|
263
|
-
location: path.normalize('packages/runtime'),
|
|
264
|
-
dependencies: {
|
|
265
|
-
'@servicetitan/log-service': '1.0.0',
|
|
266
|
-
},
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
name: '@servicetitan/log-service',
|
|
270
|
-
location: path.normalize('packages/log-service'),
|
|
271
|
-
},
|
|
272
|
-
],
|
|
273
|
-
{
|
|
274
|
-
[path.normalize('packages/runtime/tsconfig.json')]: {
|
|
275
|
-
references: [{ path: '../log-service/tsconfig' }],
|
|
276
|
-
},
|
|
277
|
-
[path.normalize('packages/log-service/tsconfig.json')]: {},
|
|
278
|
-
}
|
|
279
|
-
);
|
|
280
|
-
});
|
|
147
|
+
test('fixes error', () => {
|
|
148
|
+
fixSubject();
|
|
281
149
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
});
|
|
285
|
-
});
|
|
150
|
+
expectReferences([{ path: '../utils' }]);
|
|
151
|
+
});
|
|
286
152
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
setupPackages(
|
|
290
|
-
[
|
|
291
|
-
{
|
|
292
|
-
name: 'my-monorepo',
|
|
293
|
-
location: '.',
|
|
294
|
-
workspaces: ['packages/*'],
|
|
295
|
-
dependencies: {
|
|
296
|
-
'@servicetitan/log-service': '1.0.0',
|
|
297
|
-
},
|
|
298
|
-
},
|
|
299
|
-
{
|
|
300
|
-
name: '@servicetitan/log-service',
|
|
301
|
-
location: path.normalize('packages/log-service'),
|
|
302
|
-
},
|
|
303
|
-
],
|
|
304
|
-
{
|
|
305
|
-
'tsconfig.json': {},
|
|
306
|
-
[path.normalize('packages/log-service/tsconfig.json')]: {},
|
|
307
|
-
}
|
|
308
|
-
);
|
|
309
|
-
});
|
|
153
|
+
test('prettifies output', () => {
|
|
154
|
+
fixSubject();
|
|
310
155
|
|
|
311
|
-
|
|
312
|
-
|
|
156
|
+
expect(prettifySync).toHaveBeenCalledWith(appTsConfig());
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
describe('when reference is build config', () => {
|
|
160
|
+
beforeEach(() => {
|
|
161
|
+
volFromJSON({
|
|
162
|
+
[appTsConfig()]: {},
|
|
163
|
+
'packages/utils/tsconfig.build.json': {},
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('references build config', () => {
|
|
168
|
+
fixSubject();
|
|
169
|
+
|
|
170
|
+
expectReferences([{ path: '../utils/tsconfig.build.json' }]);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
describe('when package has other references', () => {
|
|
175
|
+
const references = [{ path: '../foo' }];
|
|
176
|
+
|
|
177
|
+
beforeEach(() => {
|
|
178
|
+
volFromJSON({ [appTsConfig()]: { references } });
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test('preserves other references', () => {
|
|
182
|
+
fixSubject();
|
|
183
|
+
|
|
184
|
+
expectReferences([...references, { path: '../utils' }]);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test('ignores invalid data', () => {
|
|
189
|
+
expect(() => rule.fix({} as any)).not.toThrow();
|
|
190
|
+
});
|
|
313
191
|
});
|
|
314
192
|
});
|
|
315
193
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { globSync } from 'glob';
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import { getTsConfig, prettifySync, readJsonSafe } from '../../../../utils';
|
|
4
|
+
import { getTsConfig, prettifySync, readJson, readJsonSafe } from '../../../../utils';
|
|
5
5
|
import { FixCategory, Package, PackageError, PackageRule, Project } from '../types';
|
|
6
6
|
import { checkPackages } from '../utils';
|
|
7
7
|
|
|
@@ -44,10 +44,7 @@ export class RequireTsconfigReferences implements PackageRule {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
const { tsconfigPath, expectedPath } = data;
|
|
47
|
-
const tsconfig =
|
|
48
|
-
if (!tsconfig) {
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
47
|
+
const tsconfig = readJson<TsConfig>(tsconfigPath);
|
|
51
48
|
|
|
52
49
|
const references = tsconfig.references ?? [];
|
|
53
50
|
references.push({ path: expectedPath });
|
|
@@ -70,6 +67,9 @@ export class RequireTsconfigReferences implements PackageRule {
|
|
|
70
67
|
}
|
|
71
68
|
|
|
72
69
|
private normalizeTsConfigPath(filePath: string): string {
|
|
70
|
+
if (this.isDirectory(filePath)) {
|
|
71
|
+
return path.join(filePath, 'tsconfig.json');
|
|
72
|
+
}
|
|
73
73
|
return filePath.endsWith('.json') ? filePath : `${filePath}.json`;
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -83,8 +83,9 @@ export class RequireTsconfigReferences implements PackageRule {
|
|
|
83
83
|
const referencedPackages = new Set<string>();
|
|
84
84
|
|
|
85
85
|
for (const reference of config.references) {
|
|
86
|
-
const
|
|
87
|
-
|
|
86
|
+
const resolvedRefPath = this.normalizeTsConfigPath(
|
|
87
|
+
path.resolve(tsconfigDir, reference.path)
|
|
88
|
+
);
|
|
88
89
|
const refDir = path.dirname(resolvedRefPath);
|
|
89
90
|
const packageName = this.locationToPackageName.get(refDir);
|
|
90
91
|
|
|
@@ -100,8 +101,11 @@ export class RequireTsconfigReferences implements PackageRule {
|
|
|
100
101
|
const relativePath = path.relative(fromLocation, toLocation);
|
|
101
102
|
const tsconfigFile = getTsConfig(toLocation);
|
|
102
103
|
const tsconfigName = path.basename(tsconfigFile);
|
|
104
|
+
const referencePath = this.isDefaultTsConfig(tsconfigName)
|
|
105
|
+
? relativePath
|
|
106
|
+
: path.join(relativePath, tsconfigName);
|
|
103
107
|
|
|
104
|
-
return
|
|
108
|
+
return referencePath.replaceAll('\\', '/');
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
private collectTsConfigFiles(location: string): string[] {
|
|
@@ -154,4 +158,16 @@ export class RequireTsconfigReferences implements PackageRule {
|
|
|
154
158
|
this.findMissingDependencyReferences(pkg, tsconfigPath, localDependencies)
|
|
155
159
|
);
|
|
156
160
|
};
|
|
161
|
+
|
|
162
|
+
private isDefaultTsConfig(name: string) {
|
|
163
|
+
return name === 'tsconfig.json';
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private isDirectory(file: string) {
|
|
167
|
+
try {
|
|
168
|
+
return fs.statSync(file).isDirectory();
|
|
169
|
+
} catch {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
157
173
|
}
|