@konvert7/klint 0.10.0 → 0.11.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@konvert7/klint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Architecture-as-Code linter for TypeScript. Enforce layer boundaries, import rules, and singleton patterns in YAML.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"pack:check": "bun tests/pack-check.ts",
|
|
40
40
|
"native:stage": "bun tests/stage-native-binary.ts",
|
|
41
41
|
"native:smoke": "bun tests/smoke-native-binary.ts",
|
|
42
|
+
"native:release:dry-run": "bun tools/prepare-native-release.ts --version 0.0.0-dry-run",
|
|
42
43
|
"check": "biome check",
|
|
43
44
|
"check-write": "biome check --write",
|
|
44
45
|
"knip": "knip-bun",
|
|
@@ -59,6 +60,12 @@
|
|
|
59
60
|
"yaml": "^2.9.0",
|
|
60
61
|
"zod": "^4.4.3"
|
|
61
62
|
},
|
|
63
|
+
"optionalDependencies": {
|
|
64
|
+
"@konvert7/klint-darwin-arm64": "*",
|
|
65
|
+
"@konvert7/klint-darwin-x64": "*",
|
|
66
|
+
"@konvert7/klint-linux-x64": "*",
|
|
67
|
+
"@konvert7/klint-win32-x64": "*"
|
|
68
|
+
},
|
|
62
69
|
"devDependencies": {
|
|
63
70
|
"@biomejs/biome": "2.4.7",
|
|
64
71
|
"@commitlint/cli": "^20.5.3",
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import {
|
|
2
|
+
copyFileSync,
|
|
3
|
+
existsSync,
|
|
4
|
+
mkdirSync,
|
|
5
|
+
mkdtempSync,
|
|
6
|
+
readFileSync,
|
|
7
|
+
rmSync,
|
|
8
|
+
writeFileSync,
|
|
9
|
+
} from "node:fs";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
import { dirname, join, resolve } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { nativePackages } from "../core/native-binary";
|
|
14
|
+
|
|
15
|
+
interface PackageJson {
|
|
16
|
+
name: string;
|
|
17
|
+
version: string;
|
|
18
|
+
private?: boolean;
|
|
19
|
+
optionalDependencies?: Record<string, string>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface Options {
|
|
23
|
+
version: string;
|
|
24
|
+
outDir: string;
|
|
25
|
+
requireBinaries: boolean;
|
|
26
|
+
keep: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const root = fileURLToPath(new URL("..", import.meta.url));
|
|
30
|
+
const options = parseArgs();
|
|
31
|
+
|
|
32
|
+
if (existsSync(options.outDir)) {
|
|
33
|
+
rmSync(options.outDir, { recursive: true, force: true });
|
|
34
|
+
}
|
|
35
|
+
mkdirSync(options.outDir, { recursive: true });
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const releaseRootPackageJson = prepareRootPackageJson();
|
|
39
|
+
const nativeResults = nativePackages().map(prepareNativePackage);
|
|
40
|
+
|
|
41
|
+
validateRootPackageJson(releaseRootPackageJson);
|
|
42
|
+
for (const result of nativeResults) validateNativePackage(result.packageJson);
|
|
43
|
+
|
|
44
|
+
const missing = nativeResults
|
|
45
|
+
.filter((result) => !result.binaryCopied)
|
|
46
|
+
.map((result) => result.packageJson.name);
|
|
47
|
+
|
|
48
|
+
if (options.requireBinaries && missing.length > 0) {
|
|
49
|
+
fail(`Missing native release binaries:\n${missing.join("\n")}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
process.stdout.write(
|
|
53
|
+
`${[
|
|
54
|
+
`native release dry-run ok (${options.version})`,
|
|
55
|
+
`output: ${options.outDir}`,
|
|
56
|
+
`native packages: ${nativeResults.length}`,
|
|
57
|
+
missing.length > 0
|
|
58
|
+
? `missing binaries: ${missing.join(", ")}`
|
|
59
|
+
: "missing binaries: none",
|
|
60
|
+
].join("\n")}\n`
|
|
61
|
+
);
|
|
62
|
+
} finally {
|
|
63
|
+
if (!options.keep) {
|
|
64
|
+
rmSync(options.outDir, { recursive: true, force: true });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function prepareRootPackageJson(): PackageJson {
|
|
69
|
+
const packageJson = readPackageJson(join(root, "package.json"));
|
|
70
|
+
packageJson.version = options.version;
|
|
71
|
+
packageJson.optionalDependencies = Object.fromEntries(
|
|
72
|
+
nativePackages().map((nativePackage) => [nativePackage.packageName, options.version])
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const outPath = join(options.outDir, "package.json");
|
|
76
|
+
writeJson(outPath, packageJson);
|
|
77
|
+
return packageJson;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function prepareNativePackage(nativePackage: ReturnType<typeof nativePackages>[number]): {
|
|
81
|
+
binaryCopied: boolean;
|
|
82
|
+
packageJson: PackageJson;
|
|
83
|
+
} {
|
|
84
|
+
const packageDirName = `${nativePackage.platform}-${nativePackage.arch}`;
|
|
85
|
+
const sourceDir = join(root, "npm", "native", packageDirName);
|
|
86
|
+
const outDir = join(options.outDir, "npm", "native", packageDirName);
|
|
87
|
+
mkdirSync(outDir, { recursive: true });
|
|
88
|
+
|
|
89
|
+
const packageJson = readPackageJson(join(sourceDir, "package.json"));
|
|
90
|
+
packageJson.version = options.version;
|
|
91
|
+
packageJson.private = false;
|
|
92
|
+
writeJson(join(outDir, "package.json"), packageJson);
|
|
93
|
+
|
|
94
|
+
const sourceBinary = join(sourceDir, nativePackage.binaryPath);
|
|
95
|
+
const outBinary = join(outDir, nativePackage.binaryPath);
|
|
96
|
+
const binaryCopied = existsSync(sourceBinary);
|
|
97
|
+
if (binaryCopied) {
|
|
98
|
+
mkdirSync(dirname(outBinary), { recursive: true });
|
|
99
|
+
copyFileSync(sourceBinary, outBinary);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return { binaryCopied, packageJson };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function validateRootPackageJson(packageJson: PackageJson): void {
|
|
106
|
+
const optionalDependencies = packageJson.optionalDependencies ?? {};
|
|
107
|
+
for (const nativePackage of nativePackages()) {
|
|
108
|
+
if (optionalDependencies[nativePackage.packageName] !== options.version) {
|
|
109
|
+
fail(
|
|
110
|
+
`Root optional dependency ${nativePackage.packageName} is not pinned to ${options.version}`
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function validateNativePackage(packageJson: PackageJson): void {
|
|
117
|
+
if (packageJson.version !== options.version) {
|
|
118
|
+
fail(
|
|
119
|
+
`${packageJson.name} version is ${packageJson.version}, expected ${options.version}`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
if (packageJson.private !== false) {
|
|
123
|
+
fail(`${packageJson.name} private must be false in release prep output`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function readPackageJson(path: string): PackageJson {
|
|
128
|
+
return JSON.parse(readFileSync(path, "utf-8")) as PackageJson;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function writeJson(path: string, value: unknown): void {
|
|
132
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function parseArgs(): Options {
|
|
136
|
+
const args = process.argv.slice(2);
|
|
137
|
+
const version = valueAfter(args, "--version");
|
|
138
|
+
if (!version) {
|
|
139
|
+
fail(
|
|
140
|
+
"Usage: bun tools/prepare-native-release.ts --version <version> [--out <dir>] [--require-binaries] [--keep]"
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
version,
|
|
146
|
+
outDir: resolve(
|
|
147
|
+
valueAfter(args, "--out") ?? mkdtempSync(join(tmpdir(), "klint-native-release-"))
|
|
148
|
+
),
|
|
149
|
+
requireBinaries: args.includes("--require-binaries"),
|
|
150
|
+
keep: args.includes("--keep"),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function valueAfter(args: string[], name: string): string | undefined {
|
|
155
|
+
const index = args.indexOf(name);
|
|
156
|
+
return index >= 0 ? args[index + 1] : undefined;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function fail(message: string): never {
|
|
160
|
+
process.stderr.write(`${message}\n`);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
export async function verifyConditions(_, context) {
|
|
6
|
+
const cwd = context.cwd ?? process.cwd();
|
|
7
|
+
const packageJson = readPackageJson(cwd);
|
|
8
|
+
|
|
9
|
+
if (!packageJson.name) {
|
|
10
|
+
throw new Error("Root package.json must have a name before npm publish");
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function prepare(_, context) {
|
|
15
|
+
const cwd = context.cwd ?? process.cwd();
|
|
16
|
+
const version = context.nextRelease?.version;
|
|
17
|
+
|
|
18
|
+
if (!version) {
|
|
19
|
+
throw new Error("semantic-release did not provide nextRelease.version");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const packageJson = readPackageJson(cwd);
|
|
23
|
+
packageJson.version = version;
|
|
24
|
+
writePackageJson(cwd, packageJson);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function publish(_, context) {
|
|
28
|
+
const cwd = context.cwd ?? process.cwd();
|
|
29
|
+
|
|
30
|
+
if (context.options?.dryRun) {
|
|
31
|
+
context.logger?.log("Dry run: skipping npm publish");
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const result = spawnSync("npm", ["publish", "--access", "public"], {
|
|
36
|
+
cwd,
|
|
37
|
+
encoding: "utf-8",
|
|
38
|
+
stdio: "inherit",
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if ((result.status ?? -1) !== 0) {
|
|
42
|
+
throw new Error(`npm publish failed with exit code ${result.status ?? -1}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function readPackageJson(cwd) {
|
|
47
|
+
return JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8"));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function writePackageJson(cwd, packageJson) {
|
|
51
|
+
writeFileSync(join(cwd, "package.json"), `${JSON.stringify(packageJson, null, 2)}\n`);
|
|
52
|
+
}
|