lintcn 0.2.0 → 0.4.0
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/CHANGELOG.md +33 -0
- package/dist/cache.d.ts +1 -1
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +85 -46
- package/dist/codegen.d.ts +4 -9
- package/dist/codegen.d.ts.map +1 -1
- package/dist/codegen.js +27 -506
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +29 -16
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +2 -5
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +3 -4
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +2 -5
- package/dist/discover.d.ts.map +1 -1
- package/dist/discover.js +8 -1
- package/dist/hash.d.ts.map +1 -1
- package/dist/hash.js +6 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/paths.d.ts +6 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +23 -1
- package/package.json +2 -1
- package/src/cache.ts +95 -51
- package/src/codegen.ts +27 -512
- package/src/commands/add.ts +34 -19
- package/src/commands/lint.ts +2 -5
- package/src/commands/list.ts +3 -4
- package/src/commands/remove.ts +2 -6
- package/src/discover.ts +10 -1
- package/src/hash.ts +7 -2
- package/src/index.ts +1 -0
- package/src/paths.ts +25 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
## 0.4.0
|
|
2
|
+
|
|
3
|
+
1. **Simpler rule imports** — rules now import from `pkg/rule`, `pkg/utils`, etc. instead of `internal/rule`. The `internal/` child-module-path hack is gone. Your `.go` files use clean import paths:
|
|
4
|
+
```go
|
|
5
|
+
import (
|
|
6
|
+
"github.com/typescript-eslint/tsgolint/pkg/rule"
|
|
7
|
+
"github.com/typescript-eslint/tsgolint/pkg/utils"
|
|
8
|
+
)
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
2. **Simpler codegen** — uses a tsgolint fork with `pkg/runner.Run()`, eliminating all regex surgery on main.go. The generated binary entry point is a 15-line template instead of a patched copy of tsgolint's main.go.
|
|
12
|
+
|
|
13
|
+
## 0.3.0
|
|
14
|
+
|
|
15
|
+
1. **Only custom rules run by default** — previously the binary included all 44 built-in tsgolint rules, producing thousands of noisy errors. Now only your `.lintcn/` rules run. True shadcn model: explicitly add each rule you want.
|
|
16
|
+
|
|
17
|
+
Before (0.2.0): `Found 2315 errors (linted 193 files with 45 rules)`
|
|
18
|
+
After (0.3.0): `Found 8 errors (linted 193 files with 1 rule)`
|
|
19
|
+
|
|
20
|
+
2. **Run `lintcn lint` from any subdirectory** — uses `find-up` to walk parent directories for `.lintcn/`. You no longer need to be at the project root:
|
|
21
|
+
```bash
|
|
22
|
+
cd packages/my-app
|
|
23
|
+
lintcn lint # finds .lintcn/ in parent
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
3. **No git required** — tsgolint source is now downloaded as a tarball from GitHub instead of cloned. Patches applied with `patch -p1`. Faster first setup, works without git installed.
|
|
27
|
+
|
|
28
|
+
4. **Fixed stale binary cache** — added `CACHE_SCHEMA_VERSION` to the content hash. Upgrading lintcn now correctly invalidates cached binaries built by older versions.
|
|
29
|
+
|
|
30
|
+
5. **Fixed partial download corruption** — if the tsgolint download fails midway, the partial directory is cleaned up so the next run starts fresh instead of failing repeatedly.
|
|
31
|
+
|
|
32
|
+
6. **Fixed GitHub URLs with `/` in branch names** — `lintcn add` now correctly handles branch names like `feature/my-branch` in GitHub blob URLs.
|
|
33
|
+
|
|
1
34
|
## 0.2.0
|
|
2
35
|
|
|
3
36
|
1. **Pinned tsgolint version** — each lintcn release bundles a specific tsgolint version (`v0.9.2`). Builds are now reproducible: everyone on the same lintcn version compiles against the same tsgolint API. Previously used `main` branch which was non-deterministic.
|
package/dist/cache.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const DEFAULT_TSGOLINT_VERSION = "
|
|
1
|
+
export declare const DEFAULT_TSGOLINT_VERSION = "a93604379da2631b70332a65bc47eb5ced689a3b";
|
|
2
2
|
export declare function getCacheDir(): string;
|
|
3
3
|
export declare function getTsgolintSourceDir(version: string): string;
|
|
4
4
|
export declare function getBinDir(): string;
|
package/dist/cache.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,wBAAwB,6CAA6C,CAAA;AAQlF,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAqCD,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA2D3E;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAQ/D"}
|
package/dist/cache.js
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
|
-
// Manage cached tsgolint source
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// Manage cached tsgolint source and compiled binaries.
|
|
2
|
+
// Downloads tsgolint fork + typescript-go as tarballs from GitHub,
|
|
3
|
+
// applies tsgolint's patches to typescript-go, and copies collections.
|
|
4
|
+
//
|
|
5
|
+
// Cache layout:
|
|
6
|
+
// ~/.cache/lintcn/tsgolint/<version>/ — extracted source (read-only)
|
|
7
|
+
// ~/.cache/lintcn/bin/<content-hash> — compiled binaries
|
|
5
8
|
import fs from 'node:fs';
|
|
6
9
|
import os from 'node:os';
|
|
7
10
|
import path from 'node:path';
|
|
11
|
+
import { pipeline } from 'node:stream/promises';
|
|
8
12
|
import { execAsync } from "./exec.js";
|
|
9
|
-
// Pinned tsgolint
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
// Pinned tsgolint fork commit — updated with each lintcn release.
|
|
14
|
+
// Uses remorses/tsgolint fork which exposes pkg/runner.Run() and
|
|
15
|
+
// moves internal/ packages to pkg/ for clean external imports.
|
|
16
|
+
export const DEFAULT_TSGOLINT_VERSION = 'a93604379da2631b70332a65bc47eb5ced689a3b';
|
|
17
|
+
// Pinned typescript-go base commit from microsoft/typescript-go (before patches).
|
|
18
|
+
// Patches from tsgolint/patches/ are applied on top during setup.
|
|
19
|
+
// This is the upstream commit the tsgolint submodule was forked from.
|
|
20
|
+
// Must be updated when DEFAULT_TSGOLINT_VERSION changes.
|
|
21
|
+
const TYPESCRIPT_GO_COMMIT = '1b7eabe122e1575a0df9c77eccdf4e063c623224';
|
|
14
22
|
export function getCacheDir() {
|
|
15
23
|
return path.join(os.homedir(), '.cache', 'lintcn');
|
|
16
24
|
}
|
|
@@ -26,54 +34,85 @@ export function getBinaryPath(contentHash) {
|
|
|
26
34
|
export function getBuildDir() {
|
|
27
35
|
return path.join(getCacheDir(), 'build');
|
|
28
36
|
}
|
|
37
|
+
/** Download a tarball from URL and extract it to targetDir.
|
|
38
|
+
* GitHub tarballs have a top-level directory like `repo-ref/`,
|
|
39
|
+
* so we strip the first path component during extraction. */
|
|
40
|
+
async function downloadAndExtract(url, targetDir) {
|
|
41
|
+
const response = await fetch(url);
|
|
42
|
+
if (!response.ok || !response.body) {
|
|
43
|
+
throw new Error(`Failed to download ${url}: ${response.status} ${response.statusText}`);
|
|
44
|
+
}
|
|
45
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
46
|
+
const tmpTarGz = path.join(os.tmpdir(), `lintcn-${Date.now()}.tar.gz`);
|
|
47
|
+
const fileStream = fs.createWriteStream(tmpTarGz);
|
|
48
|
+
// @ts-ignore ReadableStream vs NodeJS.ReadableStream mismatch
|
|
49
|
+
await pipeline(response.body, fileStream);
|
|
50
|
+
await execAsync('tar', ['xzf', tmpTarGz, '--strip-components=1', '-C', targetDir]);
|
|
51
|
+
fs.rmSync(tmpTarGz, { force: true });
|
|
52
|
+
}
|
|
53
|
+
/** Apply git-format patches using `patch -p1` (no git required).
|
|
54
|
+
* Patches are standard unified diff format, `patch` ignores the git metadata. */
|
|
55
|
+
async function applyPatches(patchesDir, targetDir) {
|
|
56
|
+
const patches = fs.readdirSync(patchesDir)
|
|
57
|
+
.filter((f) => { return f.endsWith('.patch'); })
|
|
58
|
+
.sort();
|
|
59
|
+
for (const patchFile of patches) {
|
|
60
|
+
const patchPath = path.join(patchesDir, patchFile);
|
|
61
|
+
await execAsync('patch', ['-p1', '--batch', '-i', patchPath], { cwd: targetDir });
|
|
62
|
+
}
|
|
63
|
+
return patches.length;
|
|
64
|
+
}
|
|
29
65
|
export async function ensureTsgolintSource(version) {
|
|
30
66
|
const sourceDir = getTsgolintSourceDir(version);
|
|
31
67
|
const readyMarker = path.join(sourceDir, '.lintcn-ready');
|
|
32
68
|
if (fs.existsSync(readyMarker)) {
|
|
33
69
|
return sourceDir;
|
|
34
70
|
}
|
|
35
|
-
|
|
36
|
-
fs.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
71
|
+
// clean up any partial previous attempt so we start fresh
|
|
72
|
+
if (fs.existsSync(sourceDir)) {
|
|
73
|
+
fs.rmSync(sourceDir, { recursive: true });
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
// download tsgolint fork tarball
|
|
77
|
+
console.log(`Downloading tsgolint@${version.slice(0, 8)}...`);
|
|
78
|
+
const tsgolintUrl = `https://github.com/remorses/tsgolint/archive/${version}.tar.gz`;
|
|
79
|
+
await downloadAndExtract(tsgolintUrl, sourceDir);
|
|
80
|
+
// download typescript-go from microsoft (base commit before patches)
|
|
81
|
+
const tsGoDir = path.join(sourceDir, 'typescript-go');
|
|
82
|
+
console.log('Downloading typescript-go...');
|
|
83
|
+
const tsGoUrl = `https://github.com/microsoft/typescript-go/archive/${TYPESCRIPT_GO_COMMIT}.tar.gz`;
|
|
84
|
+
await downloadAndExtract(tsGoUrl, tsGoDir);
|
|
85
|
+
// apply tsgolint's patches to typescript-go
|
|
86
|
+
const patchesDir = path.join(sourceDir, 'patches');
|
|
87
|
+
if (fs.existsSync(patchesDir)) {
|
|
88
|
+
const count = await applyPatches(patchesDir, tsGoDir);
|
|
89
|
+
if (count > 0) {
|
|
90
|
+
console.log(`Applied ${count} patches`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// copy internal/collections from typescript-go (required by tsgolint, done by `just init`)
|
|
94
|
+
const collectionsDir = path.join(sourceDir, 'internal', 'collections');
|
|
95
|
+
const tsGoCollections = path.join(tsGoDir, 'internal', 'collections');
|
|
96
|
+
if (fs.existsSync(tsGoCollections)) {
|
|
97
|
+
fs.mkdirSync(collectionsDir, { recursive: true });
|
|
98
|
+
const files = fs.readdirSync(tsGoCollections).filter((f) => {
|
|
99
|
+
return f.endsWith('.go') && !f.endsWith('_test.go');
|
|
58
100
|
});
|
|
101
|
+
for (const file of files) {
|
|
102
|
+
fs.copyFileSync(path.join(tsGoCollections, file), path.join(collectionsDir, file));
|
|
103
|
+
}
|
|
59
104
|
}
|
|
105
|
+
// write ready marker
|
|
106
|
+
fs.writeFileSync(readyMarker, new Date().toISOString());
|
|
107
|
+
console.log('tsgolint source ready');
|
|
60
108
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
fs.mkdirSync(collectionsDir, { recursive: true });
|
|
66
|
-
const files = fs.readdirSync(tsGoCollections).filter((f) => {
|
|
67
|
-
return f.endsWith('.go') && !f.endsWith('_test.go');
|
|
68
|
-
});
|
|
69
|
-
for (const file of files) {
|
|
70
|
-
fs.copyFileSync(path.join(tsGoCollections, file), path.join(collectionsDir, file));
|
|
109
|
+
catch (err) {
|
|
110
|
+
// clean up partial download so next run starts fresh
|
|
111
|
+
if (fs.existsSync(sourceDir)) {
|
|
112
|
+
fs.rmSync(sourceDir, { recursive: true });
|
|
71
113
|
}
|
|
72
|
-
|
|
114
|
+
throw err;
|
|
73
115
|
}
|
|
74
|
-
// write ready marker
|
|
75
|
-
fs.writeFileSync(readyMarker, new Date().toISOString());
|
|
76
|
-
console.log('tsgolint source ready');
|
|
77
116
|
return sourceDir;
|
|
78
117
|
}
|
|
79
118
|
export function cachedBinaryExists(contentHash) {
|
package/dist/codegen.d.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import type { RuleMetadata } from './discover.ts';
|
|
2
|
-
/** Generate .lintcn/go.work and .lintcn/go.mod for editor/gopls support.
|
|
3
|
-
*
|
|
4
|
-
* Key learnings from testing:
|
|
5
|
-
* - Module name MUST be a child path of github.com/typescript-eslint/tsgolint
|
|
6
|
-
* so Go allows importing internal/ packages across the module boundary.
|
|
7
|
-
* - go.work must `use` both .tsgolint AND .tsgolint/typescript-go since
|
|
8
|
-
* tsgolint's own go.work (which does this) is ignored by the outer workspace.
|
|
9
|
-
* - go.mod should be minimal (no requires) — the workspace resolves everything. */
|
|
2
|
+
/** Generate .lintcn/go.work and .lintcn/go.mod for editor/gopls support. */
|
|
10
3
|
export declare function generateEditorGoFiles(lintcnDir: string): void;
|
|
11
|
-
/** Generate build workspace
|
|
4
|
+
/** Generate build workspace for compiling the custom binary.
|
|
5
|
+
* With pkg/runner.Run(), the generated main.go is a static template —
|
|
6
|
+
* no regex surgery or file copying needed. */
|
|
12
7
|
export declare function generateBuildWorkspace({ buildDir, tsgolintDir, lintcnDir, rules, }: {
|
|
13
8
|
buildDir: string;
|
|
14
9
|
tsgolintDir: string;
|
package/dist/codegen.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AA2BjD,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAkC7D;AAED;;+CAE+C;AAC/C,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,WAAW,EACX,SAAS,EACT,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,YAAY,EAAE,CAAA;CACtB,GAAG,IAAI,CA2CP"}
|