cachelint 0.1.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/LICENSE +27 -0
- package/LICENSE-PRO.md +67 -0
- package/README.md +298 -0
- package/dist/check-2ONJCYKP.js +23 -0
- package/dist/chunk-2JSY5BQA.js +340 -0
- package/dist/chunk-4GHSUBAY.js +28 -0
- package/dist/chunk-4LB5LF2P.js +51 -0
- package/dist/chunk-BUZCVKMZ.js +246 -0
- package/dist/chunk-DYQPXD3G.js +92 -0
- package/dist/chunk-GXASKZ4Z.js +182 -0
- package/dist/chunk-JZU4PCTS.js +80 -0
- package/dist/chunk-MW7BXKPR.js +593 -0
- package/dist/chunk-O7ZE6CFI.js +32 -0
- package/dist/chunk-SQ4IAMTX.js +65 -0
- package/dist/chunk-UUVSBJ62.js +77 -0
- package/dist/chunk-VWE5TDL5.js +91 -0
- package/dist/chunk-WKFGRNYK.js +494 -0
- package/dist/chunk-WPJYUQMU.js +26 -0
- package/dist/chunk-XKRPGMZT.js +197 -0
- package/dist/chunk-ZSEZQ422.js +286 -0
- package/dist/cli.d.ts +46 -0
- package/dist/cli.js +199 -0
- package/dist/gate-63NKQRXL.js +16 -0
- package/dist/hash-XUTGK6SB.js +15 -0
- package/dist/index.d.ts +1200 -0
- package/dist/index.js +184 -0
- package/dist/license-GFDBTQHG.js +19 -0
- package/dist/lint-PQHIDWOY.js +19 -0
- package/dist/sarif-EQ6VJNGN.js +63 -0
- package/dist/step-summary-NKD4N7AY.js +160 -0
- package/dist/store-KZIQANIT.js +14 -0
- package/package.json +85 -0
- package/schema/cachelint.config.schema.json +114 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import {
|
|
2
|
+
check,
|
|
3
|
+
renderCheckHuman,
|
|
4
|
+
renderCheckJson
|
|
5
|
+
} from "./chunk-ZSEZQ422.js";
|
|
6
|
+
import {
|
|
7
|
+
activate,
|
|
8
|
+
deactivate,
|
|
9
|
+
licenseStatus
|
|
10
|
+
} from "./chunk-JZU4PCTS.js";
|
|
11
|
+
import "./chunk-UUVSBJ62.js";
|
|
12
|
+
import {
|
|
13
|
+
KNOWN_PACK_IDS,
|
|
14
|
+
estimateCosts,
|
|
15
|
+
heuristicTokens,
|
|
16
|
+
lint,
|
|
17
|
+
renderLintHuman,
|
|
18
|
+
renderLintJson,
|
|
19
|
+
usdPer1kCalls
|
|
20
|
+
} from "./chunk-2JSY5BQA.js";
|
|
21
|
+
import {
|
|
22
|
+
PRICING_AS_OF,
|
|
23
|
+
PRICING_TABLE_VERSION,
|
|
24
|
+
REFERENCE_MODEL,
|
|
25
|
+
getModelPricing,
|
|
26
|
+
referencePricing,
|
|
27
|
+
wastePerTokenUsd
|
|
28
|
+
} from "./chunk-O7ZE6CFI.js";
|
|
29
|
+
import {
|
|
30
|
+
GRACE_PERIOD_DAYS,
|
|
31
|
+
activeLicenseInfo,
|
|
32
|
+
isPro,
|
|
33
|
+
requirePro,
|
|
34
|
+
verifyLicenseToken
|
|
35
|
+
} from "./chunk-GXASKZ4Z.js";
|
|
36
|
+
import "./chunk-4LB5LF2P.js";
|
|
37
|
+
import {
|
|
38
|
+
allRules,
|
|
39
|
+
getRule,
|
|
40
|
+
ruleDocsUrl
|
|
41
|
+
} from "./chunk-WKFGRNYK.js";
|
|
42
|
+
import {
|
|
43
|
+
diffLockfiles,
|
|
44
|
+
isRegression
|
|
45
|
+
} from "./chunk-DYQPXD3G.js";
|
|
46
|
+
import {
|
|
47
|
+
COST_LINE_OVERLAPPED,
|
|
48
|
+
RECEIPT_EXACT_FALLBACK_LINE,
|
|
49
|
+
buildReceiptLines,
|
|
50
|
+
costLabel,
|
|
51
|
+
costLineAtRisk,
|
|
52
|
+
costLineInvalidates,
|
|
53
|
+
costLineWasted,
|
|
54
|
+
costSummary,
|
|
55
|
+
formatTokens,
|
|
56
|
+
formatUsdPer1k,
|
|
57
|
+
receiptAllBelowMinimumLine,
|
|
58
|
+
receiptProtectedLine,
|
|
59
|
+
receiptWarnQualifier,
|
|
60
|
+
receiptWontEngageLine
|
|
61
|
+
} from "./chunk-VWE5TDL5.js";
|
|
62
|
+
import {
|
|
63
|
+
hash,
|
|
64
|
+
renderHashHuman,
|
|
65
|
+
renderHashJson
|
|
66
|
+
} from "./chunk-SQ4IAMTX.js";
|
|
67
|
+
import {
|
|
68
|
+
DEFAULT_LOCKFILE_NAME,
|
|
69
|
+
LOCKFILE_FORMAT_VERSION,
|
|
70
|
+
canonicalJsonStringify,
|
|
71
|
+
parseLockfile,
|
|
72
|
+
serializeLockfile
|
|
73
|
+
} from "./chunk-BUZCVKMZ.js";
|
|
74
|
+
import {
|
|
75
|
+
CONFIG_FILENAMES,
|
|
76
|
+
configJsonSchema,
|
|
77
|
+
configSchema,
|
|
78
|
+
defineConfig,
|
|
79
|
+
loadConfig,
|
|
80
|
+
parseConfig,
|
|
81
|
+
resolveConfigArg
|
|
82
|
+
} from "./chunk-MW7BXKPR.js";
|
|
83
|
+
import {
|
|
84
|
+
DEFAULT_RULE_SEVERITY,
|
|
85
|
+
DEFAULT_RULE_VOLATILITY,
|
|
86
|
+
RULE_IDS
|
|
87
|
+
} from "./chunk-4GHSUBAY.js";
|
|
88
|
+
import {
|
|
89
|
+
CACHELINT_VERSION,
|
|
90
|
+
COST_MODEL_VERSION,
|
|
91
|
+
NORMALIZATION_POLICY_VERSION,
|
|
92
|
+
RULE_TABLE_VERSION
|
|
93
|
+
} from "./chunk-WPJYUQMU.js";
|
|
94
|
+
import {
|
|
95
|
+
AdapterError,
|
|
96
|
+
COST_UNAVAILABLE_CODE,
|
|
97
|
+
CachelintError,
|
|
98
|
+
ConfigError,
|
|
99
|
+
ExactCountUnavailableError,
|
|
100
|
+
LicenseError,
|
|
101
|
+
LockCorruptError,
|
|
102
|
+
LockError,
|
|
103
|
+
LockMissingError,
|
|
104
|
+
RuleError,
|
|
105
|
+
SourceError
|
|
106
|
+
} from "./chunk-XKRPGMZT.js";
|
|
107
|
+
export {
|
|
108
|
+
AdapterError,
|
|
109
|
+
CACHELINT_VERSION,
|
|
110
|
+
CONFIG_FILENAMES,
|
|
111
|
+
COST_LINE_OVERLAPPED,
|
|
112
|
+
COST_MODEL_VERSION,
|
|
113
|
+
COST_UNAVAILABLE_CODE,
|
|
114
|
+
CachelintError,
|
|
115
|
+
ConfigError,
|
|
116
|
+
DEFAULT_LOCKFILE_NAME,
|
|
117
|
+
DEFAULT_RULE_SEVERITY,
|
|
118
|
+
DEFAULT_RULE_VOLATILITY,
|
|
119
|
+
ExactCountUnavailableError,
|
|
120
|
+
GRACE_PERIOD_DAYS,
|
|
121
|
+
KNOWN_PACK_IDS,
|
|
122
|
+
LOCKFILE_FORMAT_VERSION,
|
|
123
|
+
LicenseError,
|
|
124
|
+
LockCorruptError,
|
|
125
|
+
LockError,
|
|
126
|
+
LockMissingError,
|
|
127
|
+
NORMALIZATION_POLICY_VERSION,
|
|
128
|
+
PRICING_AS_OF,
|
|
129
|
+
PRICING_TABLE_VERSION,
|
|
130
|
+
RECEIPT_EXACT_FALLBACK_LINE,
|
|
131
|
+
REFERENCE_MODEL,
|
|
132
|
+
RULE_IDS,
|
|
133
|
+
RULE_TABLE_VERSION,
|
|
134
|
+
RuleError,
|
|
135
|
+
SourceError,
|
|
136
|
+
activate,
|
|
137
|
+
activeLicenseInfo,
|
|
138
|
+
allRules,
|
|
139
|
+
buildReceiptLines,
|
|
140
|
+
canonicalJsonStringify,
|
|
141
|
+
check,
|
|
142
|
+
configJsonSchema,
|
|
143
|
+
configSchema,
|
|
144
|
+
costLabel,
|
|
145
|
+
costLineAtRisk,
|
|
146
|
+
costLineInvalidates,
|
|
147
|
+
costLineWasted,
|
|
148
|
+
costSummary,
|
|
149
|
+
deactivate,
|
|
150
|
+
defineConfig,
|
|
151
|
+
diffLockfiles,
|
|
152
|
+
estimateCosts,
|
|
153
|
+
formatTokens,
|
|
154
|
+
formatUsdPer1k,
|
|
155
|
+
getModelPricing,
|
|
156
|
+
getRule,
|
|
157
|
+
hash,
|
|
158
|
+
heuristicTokens,
|
|
159
|
+
isPro,
|
|
160
|
+
isRegression,
|
|
161
|
+
licenseStatus,
|
|
162
|
+
lint,
|
|
163
|
+
loadConfig,
|
|
164
|
+
parseConfig,
|
|
165
|
+
parseLockfile,
|
|
166
|
+
receiptAllBelowMinimumLine,
|
|
167
|
+
receiptProtectedLine,
|
|
168
|
+
receiptWarnQualifier,
|
|
169
|
+
receiptWontEngageLine,
|
|
170
|
+
referencePricing,
|
|
171
|
+
renderCheckHuman,
|
|
172
|
+
renderCheckJson,
|
|
173
|
+
renderHashHuman,
|
|
174
|
+
renderHashJson,
|
|
175
|
+
renderLintHuman,
|
|
176
|
+
renderLintJson,
|
|
177
|
+
requirePro,
|
|
178
|
+
resolveConfigArg,
|
|
179
|
+
ruleDocsUrl,
|
|
180
|
+
serializeLockfile,
|
|
181
|
+
usdPer1kCalls,
|
|
182
|
+
verifyLicenseToken,
|
|
183
|
+
wastePerTokenUsd
|
|
184
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
activate,
|
|
3
|
+
deactivate,
|
|
4
|
+
licenseStatus,
|
|
5
|
+
renderActivateHuman,
|
|
6
|
+
renderDeactivateHuman,
|
|
7
|
+
renderLicenseStatusHuman
|
|
8
|
+
} from "./chunk-JZU4PCTS.js";
|
|
9
|
+
import "./chunk-GXASKZ4Z.js";
|
|
10
|
+
import "./chunk-4LB5LF2P.js";
|
|
11
|
+
import "./chunk-XKRPGMZT.js";
|
|
12
|
+
export {
|
|
13
|
+
activate,
|
|
14
|
+
deactivate,
|
|
15
|
+
licenseStatus,
|
|
16
|
+
renderActivateHuman,
|
|
17
|
+
renderDeactivateHuman,
|
|
18
|
+
renderLicenseStatusHuman
|
|
19
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
lint,
|
|
3
|
+
renderLintHuman,
|
|
4
|
+
renderLintJson
|
|
5
|
+
} from "./chunk-2JSY5BQA.js";
|
|
6
|
+
import "./chunk-O7ZE6CFI.js";
|
|
7
|
+
import "./chunk-GXASKZ4Z.js";
|
|
8
|
+
import "./chunk-4LB5LF2P.js";
|
|
9
|
+
import "./chunk-WKFGRNYK.js";
|
|
10
|
+
import "./chunk-VWE5TDL5.js";
|
|
11
|
+
import "./chunk-MW7BXKPR.js";
|
|
12
|
+
import "./chunk-4GHSUBAY.js";
|
|
13
|
+
import "./chunk-WPJYUQMU.js";
|
|
14
|
+
import "./chunk-XKRPGMZT.js";
|
|
15
|
+
export {
|
|
16
|
+
lint,
|
|
17
|
+
renderLintHuman,
|
|
18
|
+
renderLintJson
|
|
19
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
allRules,
|
|
3
|
+
ruleDocsUrl
|
|
4
|
+
} from "./chunk-WKFGRNYK.js";
|
|
5
|
+
import "./chunk-4GHSUBAY.js";
|
|
6
|
+
import {
|
|
7
|
+
CACHELINT_VERSION
|
|
8
|
+
} from "./chunk-WPJYUQMU.js";
|
|
9
|
+
import "./chunk-XKRPGMZT.js";
|
|
10
|
+
|
|
11
|
+
// src/adapters/sarif.ts
|
|
12
|
+
var SARIF_SCHEMA = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json";
|
|
13
|
+
var INFORMATION_URI = "https://github.com/davioe/cachelint";
|
|
14
|
+
function toSarif(diagnostics) {
|
|
15
|
+
const rules = allRules().map((r) => ({
|
|
16
|
+
id: r.id,
|
|
17
|
+
name: r.id,
|
|
18
|
+
shortDescription: { text: r.title },
|
|
19
|
+
helpUri: ruleDocsUrl(r.id),
|
|
20
|
+
defaultConfiguration: { level: r.defaultSeverity === "error" ? "error" : "warning" }
|
|
21
|
+
}));
|
|
22
|
+
const results = diagnostics.map((d) => ({
|
|
23
|
+
ruleId: d.rule,
|
|
24
|
+
level: d.severity === "error" ? "error" : "warning",
|
|
25
|
+
message: { text: d.fixHint ? `${d.message} \u2014 ${d.fixHint}` : d.message },
|
|
26
|
+
locations: [
|
|
27
|
+
{
|
|
28
|
+
physicalLocation: {
|
|
29
|
+
artifactLocation: { uri: d.file },
|
|
30
|
+
region: {
|
|
31
|
+
startLine: d.line,
|
|
32
|
+
startColumn: d.column,
|
|
33
|
+
...d.snippet ? { snippet: { text: d.snippet } } : {}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}));
|
|
39
|
+
return {
|
|
40
|
+
$schema: SARIF_SCHEMA,
|
|
41
|
+
version: "2.1.0",
|
|
42
|
+
runs: [
|
|
43
|
+
{
|
|
44
|
+
tool: {
|
|
45
|
+
driver: {
|
|
46
|
+
name: "cachelint",
|
|
47
|
+
informationUri: INFORMATION_URI,
|
|
48
|
+
version: CACHELINT_VERSION,
|
|
49
|
+
rules
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
results
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function sarifString(diagnostics) {
|
|
58
|
+
return JSON.stringify(toSarif(diagnostics), null, 2) + "\n";
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
sarifString,
|
|
62
|
+
toSarif
|
|
63
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import {
|
|
2
|
+
renderDiffHuman
|
|
3
|
+
} from "./chunk-DYQPXD3G.js";
|
|
4
|
+
import {
|
|
5
|
+
buildReceiptLines,
|
|
6
|
+
costLabel,
|
|
7
|
+
costLineAtRisk,
|
|
8
|
+
costSummary
|
|
9
|
+
} from "./chunk-VWE5TDL5.js";
|
|
10
|
+
import {
|
|
11
|
+
redactSecrets
|
|
12
|
+
} from "./chunk-XKRPGMZT.js";
|
|
13
|
+
|
|
14
|
+
// src/ci/step-summary.ts
|
|
15
|
+
import { appendFileSync } from "fs";
|
|
16
|
+
function stepSummaryPath(env = process.env) {
|
|
17
|
+
const optOut = env["CACHELINT_NO_STEP_SUMMARY"];
|
|
18
|
+
if (optOut !== void 0 && optOut.trim() !== "") return null;
|
|
19
|
+
const path = env["GITHUB_STEP_SUMMARY"];
|
|
20
|
+
if (path === void 0 || path.trim() === "") return null;
|
|
21
|
+
return path;
|
|
22
|
+
}
|
|
23
|
+
function mdEscapeHtml(s) {
|
|
24
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
25
|
+
}
|
|
26
|
+
function mdCell(s) {
|
|
27
|
+
return mdEscapeHtml(s).replace(/\|/g, "\\|").replace(/\r?\n/g, " ");
|
|
28
|
+
}
|
|
29
|
+
function fencedBlock(text) {
|
|
30
|
+
let longestRun = 0;
|
|
31
|
+
for (const m of text.matchAll(/`+/g)) {
|
|
32
|
+
if (m[0].length > longestRun) longestRun = m[0].length;
|
|
33
|
+
}
|
|
34
|
+
const fence = "`".repeat(Math.max(3, longestRun + 1));
|
|
35
|
+
return [`${fence}text`, text, fence];
|
|
36
|
+
}
|
|
37
|
+
function findingsTableLines(diagnostics) {
|
|
38
|
+
if (diagnostics.length === 0) return ["No rule findings."];
|
|
39
|
+
const lines = ["| location | severity | rule | message |", "| --- | --- | --- | --- |"];
|
|
40
|
+
for (const d of diagnostics) {
|
|
41
|
+
const severity = d.severity === "error" ? "error" : "warning";
|
|
42
|
+
lines.push(`| \`${mdCell(`${d.file}:${d.line}:${d.column}`)}\` | ${severity} | ${mdCell(d.rule)} | ${mdCell(d.message)} |`);
|
|
43
|
+
}
|
|
44
|
+
return lines;
|
|
45
|
+
}
|
|
46
|
+
function problemTally(diagnostics) {
|
|
47
|
+
let errors = 0;
|
|
48
|
+
let warns = 0;
|
|
49
|
+
for (const d of diagnostics) {
|
|
50
|
+
if (d.severity === "error") errors++;
|
|
51
|
+
else warns++;
|
|
52
|
+
}
|
|
53
|
+
const parts = [];
|
|
54
|
+
if (errors > 0) parts.push(`${errors} error${errors === 1 ? "" : "s"}`);
|
|
55
|
+
if (warns > 0) parts.push(`${warns} warning${warns === 1 ? "" : "s"}`);
|
|
56
|
+
const total = diagnostics.length;
|
|
57
|
+
return `${total} problem${total === 1 ? "" : "s"} (${parts.join(", ")})`;
|
|
58
|
+
}
|
|
59
|
+
function costTotalsLines(cost) {
|
|
60
|
+
if (cost === void 0) return [];
|
|
61
|
+
const label = costLabel({ model: cost.pricing.referenceModel }, cost.pricing.asOf);
|
|
62
|
+
const summary = costSummary(cost.totals, label);
|
|
63
|
+
if (summary !== null) return [`**Cost:** ${summary}`];
|
|
64
|
+
if (cost.totals.atRiskTokens > 0) return [`**Cost:** ${costLineAtRisk(cost.totals.atRiskTokens)}`];
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
function renderLintSection(result) {
|
|
68
|
+
const lines = ["## cachelint lint", ""];
|
|
69
|
+
lines.push(...findingsTableLines(result.diagnostics));
|
|
70
|
+
lines.push("");
|
|
71
|
+
lines.push(
|
|
72
|
+
result.diagnostics.length === 0 ? "**Result:** no problems found (exit code 0)" : `**Result:** ${problemTally(result.diagnostics)} \u2014 exit code ${result.exitCode}`
|
|
73
|
+
);
|
|
74
|
+
const cost = costTotalsLines(result.cost);
|
|
75
|
+
if (cost.length > 0) {
|
|
76
|
+
lines.push("");
|
|
77
|
+
lines.push(...cost);
|
|
78
|
+
}
|
|
79
|
+
return lines.join("\n");
|
|
80
|
+
}
|
|
81
|
+
function receiptLines(cost, label) {
|
|
82
|
+
return buildReceiptLines(cost, label).map((l) => `- ${mdEscapeHtml(l)}`);
|
|
83
|
+
}
|
|
84
|
+
function renderCheckSection(r) {
|
|
85
|
+
const lines = ["## cachelint check", ""];
|
|
86
|
+
if (r.regression) {
|
|
87
|
+
lines.push("**Bundle stability:** REGRESSION \u2014 `cachelint.lock` is out of date:", "", ...fencedBlock(renderDiffHuman(r.diff)));
|
|
88
|
+
} else {
|
|
89
|
+
lines.push("**Bundle stability:** lock OK \u2014 `cachelint.lock` matches the current sources.");
|
|
90
|
+
}
|
|
91
|
+
lines.push("");
|
|
92
|
+
lines.push(...findingsTableLines(r.diagnostics));
|
|
93
|
+
lines.push("");
|
|
94
|
+
lines.push(`**Result:** ${r.exitCode === 0 ? "PASSED (exit code 0)" : "FAILED (exit code 1)"}`);
|
|
95
|
+
if (r.cost !== void 0) {
|
|
96
|
+
const label = costLabel({ model: r.cost.pricing.referenceModel }, r.cost.pricing.asOf);
|
|
97
|
+
const cost = r.exitCode === 0 ? receiptLines(r.cost, label) : costTotalsLines(r.cost);
|
|
98
|
+
if (cost.length > 0) {
|
|
99
|
+
lines.push("");
|
|
100
|
+
lines.push(...cost);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return lines.join("\n");
|
|
104
|
+
}
|
|
105
|
+
function renderFailureSection(command, exitCode, err) {
|
|
106
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
107
|
+
const headline = message.split("\n")[0] ?? "";
|
|
108
|
+
return [
|
|
109
|
+
`## cachelint ${command} \u2014 error`,
|
|
110
|
+
"",
|
|
111
|
+
`\`cachelint ${command}\` did not complete (exit code ${exitCode}): ${headline === "" ? "unknown error" : mdEscapeHtml(headline)}`
|
|
112
|
+
].join("\n");
|
|
113
|
+
}
|
|
114
|
+
function appendStepSummary(markdown, env = process.env) {
|
|
115
|
+
const path = stepSummaryPath(env);
|
|
116
|
+
if (path === null) return;
|
|
117
|
+
try {
|
|
118
|
+
appendFileSync(path, redactSecrets(markdown) + "\n\n", "utf8");
|
|
119
|
+
} catch (e) {
|
|
120
|
+
noteFailure(e);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function noteFailure(e) {
|
|
124
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
125
|
+
try {
|
|
126
|
+
process.stderr.write(redactSecrets(`cachelint: could not append the CI step summary (${msg}) \u2014 continuing
|
|
127
|
+
`));
|
|
128
|
+
} catch {
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function writeSection(render, env) {
|
|
132
|
+
if (stepSummaryPath(env) === null) return;
|
|
133
|
+
let markdown;
|
|
134
|
+
try {
|
|
135
|
+
markdown = render();
|
|
136
|
+
} catch (e) {
|
|
137
|
+
noteFailure(e);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
appendStepSummary(markdown, env);
|
|
141
|
+
}
|
|
142
|
+
function writeLintStepSummary(result, env = process.env) {
|
|
143
|
+
writeSection(() => renderLintSection(result), env);
|
|
144
|
+
}
|
|
145
|
+
function writeCheckStepSummary(result, env = process.env) {
|
|
146
|
+
writeSection(() => renderCheckSection(result), env);
|
|
147
|
+
}
|
|
148
|
+
function writeFailureStepSummary(context, exitCode, err, env = process.env) {
|
|
149
|
+
writeSection(() => renderFailureSection(context.command, exitCode, err), env);
|
|
150
|
+
}
|
|
151
|
+
export {
|
|
152
|
+
appendStepSummary,
|
|
153
|
+
renderCheckSection,
|
|
154
|
+
renderFailureSection,
|
|
155
|
+
renderLintSection,
|
|
156
|
+
stepSummaryPath,
|
|
157
|
+
writeCheckStepSummary,
|
|
158
|
+
writeFailureStepSummary,
|
|
159
|
+
writeLintStepSummary
|
|
160
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
clearStoredLicense,
|
|
3
|
+
hasEnvLicense,
|
|
4
|
+
licenseFilePath,
|
|
5
|
+
readStoredLicense,
|
|
6
|
+
writeStoredLicense
|
|
7
|
+
} from "./chunk-4LB5LF2P.js";
|
|
8
|
+
export {
|
|
9
|
+
clearStoredLicense,
|
|
10
|
+
hasEnvLicense,
|
|
11
|
+
licenseFilePath,
|
|
12
|
+
readStoredLicense,
|
|
13
|
+
writeStoredLicense
|
|
14
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cachelint",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A linter + CI gate for LLM prompt-cache regressions. Catches the silent-invalidator class (interpolated timestamps, unsorted JSON, BOM, mixed line endings) and fails PRs when a committed prompt's stable-prefix hash moves.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "cachelint contributors",
|
|
7
|
+
"homepage": "https://github.com/davioe/cachelint",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/davioe/cachelint.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/davioe/cachelint/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"llm",
|
|
17
|
+
"prompt",
|
|
18
|
+
"prompt-cache",
|
|
19
|
+
"prompt-caching",
|
|
20
|
+
"anthropic",
|
|
21
|
+
"claude",
|
|
22
|
+
"openai",
|
|
23
|
+
"linter",
|
|
24
|
+
"ci",
|
|
25
|
+
"cache-control",
|
|
26
|
+
"cachelint",
|
|
27
|
+
"developer-tools",
|
|
28
|
+
"lint"
|
|
29
|
+
],
|
|
30
|
+
"type": "module",
|
|
31
|
+
"bin": {
|
|
32
|
+
"cachelint": "./dist/cli.js"
|
|
33
|
+
},
|
|
34
|
+
"main": "./dist/index.js",
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"exports": {
|
|
37
|
+
".": {
|
|
38
|
+
"types": "./dist/index.d.ts",
|
|
39
|
+
"default": "./dist/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./package.json": "./package.json"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=22.0.0"
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"dist/",
|
|
48
|
+
"schema/",
|
|
49
|
+
"README.md",
|
|
50
|
+
"LICENSE",
|
|
51
|
+
"LICENSE-PRO.md"
|
|
52
|
+
],
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsup",
|
|
55
|
+
"dev": "tsup --watch",
|
|
56
|
+
"typecheck": "tsc --noEmit",
|
|
57
|
+
"test": "vitest run",
|
|
58
|
+
"test:watch": "vitest",
|
|
59
|
+
"lint": "tsc --noEmit",
|
|
60
|
+
"clean": "node -e \"for (const d of ['dist','coverage']) require('node:fs').rmSync(d,{recursive:true,force:true})\"",
|
|
61
|
+
"pack:check": "node scripts/check-pack-allowlist.mjs",
|
|
62
|
+
"prepublishOnly": "npm run build && npm run pack:check"
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"acorn": "^8.16.0",
|
|
66
|
+
"acorn-walk": "^8.3.5",
|
|
67
|
+
"commander": "^14.0.0",
|
|
68
|
+
"yaml": "^2.9.0",
|
|
69
|
+
"zod": "^4.4.3"
|
|
70
|
+
},
|
|
71
|
+
"peerDependencies": {
|
|
72
|
+
"@anthropic-ai/sdk": "^0.30.0"
|
|
73
|
+
},
|
|
74
|
+
"peerDependenciesMeta": {
|
|
75
|
+
"@anthropic-ai/sdk": {
|
|
76
|
+
"optional": true
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"devDependencies": {
|
|
80
|
+
"@types/node": "^22.10.0",
|
|
81
|
+
"tsup": "^8.5.0",
|
|
82
|
+
"typescript": "^5.6.0",
|
|
83
|
+
"vitest": "^2.1.0"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"$schema": {
|
|
6
|
+
"type": "string"
|
|
7
|
+
},
|
|
8
|
+
"prompt_globs": {
|
|
9
|
+
"type": "array",
|
|
10
|
+
"items": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"minLength": 1
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"exclude": {
|
|
16
|
+
"type": "array",
|
|
17
|
+
"items": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"minLength": 1
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"disable": {
|
|
23
|
+
"type": "array",
|
|
24
|
+
"items": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"enum": [
|
|
27
|
+
"R001",
|
|
28
|
+
"R002",
|
|
29
|
+
"R003",
|
|
30
|
+
"R004",
|
|
31
|
+
"R005"
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"rules": {
|
|
36
|
+
"type": "object",
|
|
37
|
+
"propertyNames": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"enum": [
|
|
40
|
+
"R001",
|
|
41
|
+
"R002",
|
|
42
|
+
"R003",
|
|
43
|
+
"R004",
|
|
44
|
+
"R005"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"additionalProperties": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"enum": [
|
|
50
|
+
"off",
|
|
51
|
+
"warn",
|
|
52
|
+
"error"
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"bundles": {
|
|
57
|
+
"type": "array",
|
|
58
|
+
"items": {
|
|
59
|
+
"type": "object",
|
|
60
|
+
"properties": {
|
|
61
|
+
"name": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"minLength": 1
|
|
64
|
+
},
|
|
65
|
+
"files": {
|
|
66
|
+
"minItems": 1,
|
|
67
|
+
"type": "array",
|
|
68
|
+
"items": {
|
|
69
|
+
"type": "string",
|
|
70
|
+
"minLength": 1
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"required": [
|
|
75
|
+
"name",
|
|
76
|
+
"files"
|
|
77
|
+
],
|
|
78
|
+
"additionalProperties": false,
|
|
79
|
+
"description": "A named, ordered group of files hashed together as one cache prefix."
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"max_file_bytes": {
|
|
83
|
+
"type": "integer",
|
|
84
|
+
"exclusiveMinimum": 0,
|
|
85
|
+
"maximum": 9007199254740991
|
|
86
|
+
},
|
|
87
|
+
"max_total_bytes": {
|
|
88
|
+
"type": "integer",
|
|
89
|
+
"exclusiveMinimum": 0,
|
|
90
|
+
"maximum": 9007199254740991
|
|
91
|
+
},
|
|
92
|
+
"pro": {
|
|
93
|
+
"type": "object",
|
|
94
|
+
"properties": {
|
|
95
|
+
"exact_limit": {
|
|
96
|
+
"type": "integer",
|
|
97
|
+
"exclusiveMinimum": 0,
|
|
98
|
+
"maximum": 9007199254740991
|
|
99
|
+
},
|
|
100
|
+
"packs": {
|
|
101
|
+
"type": "array",
|
|
102
|
+
"items": {
|
|
103
|
+
"type": "string",
|
|
104
|
+
"minLength": 1
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"additionalProperties": false,
|
|
109
|
+
"description": "Pro-tier settings (only consulted when a Pro feature is invoked with a valid license)."
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"additionalProperties": false,
|
|
113
|
+
"description": "cachelint configuration (cachelint.config.json / .yaml / .yml)."
|
|
114
|
+
}
|