pasika 0.7.3 → 0.7.5
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/README.md +8 -8
- package/dist/eslint/pasika/index.d.ts +2 -2
- package/dist/eslint/pasika/index.js +80 -53
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -198,14 +198,14 @@ Applied to `src/**/globals.css` (and other stylesheets) through `@eslint/css` wi
|
|
|
198
198
|
|
|
199
199
|
### Package.json rules
|
|
200
200
|
|
|
201
|
-
Applied to `package.json` through `@eslint/json`. The framework-agnostic
|
|
202
|
-
|
|
203
|
-
| Rule
|
|
204
|
-
|
|
|
205
|
-
| `pasika/
|
|
206
|
-
| `pasika/
|
|
207
|
-
| `pasika/
|
|
208
|
-
| `pasika/vulyk-docs`
|
|
201
|
+
Applied to `package.json` through `@eslint/json`. The framework-agnostic `exact-version` rule applies to any repository, including pasika itself; `nextjs-stack` applies to a Next.js/React application, and the Vulyk rules apply to a repository adopting the framework.
|
|
202
|
+
|
|
203
|
+
| Rule | Enforces |
|
|
204
|
+
| ------------------------- | ----------------------------------------------------------------------------------- |
|
|
205
|
+
| `pasika/exact-version` | Dependency and devDependency versions are pinned exactly, never ranges |
|
|
206
|
+
| `pasika/nextjs-stack` | All Tech Stack Reference packages are listed in `package.json` (Next.js/React apps) |
|
|
207
|
+
| `pasika/vulyk-dependency` | `vulyk` is listed in `devDependencies`, not `dependencies` |
|
|
208
|
+
| `pasika/vulyk-docs` | `vulyk.config.ts` tracks the framework's docs from pasika and `AGENTS.md` exists |
|
|
209
209
|
|
|
210
210
|
### Documentation rules
|
|
211
211
|
|
|
@@ -118,7 +118,6 @@ declare const tailwindRules: {
|
|
|
118
118
|
|
|
119
119
|
/** Framework-agnostic package.json rules any repository should follow. */
|
|
120
120
|
declare const repoPackageJsonRules: {
|
|
121
|
-
"no-vulyk-dependency": _eslint_json.JSONRuleDefinition;
|
|
122
121
|
"exact-version": _eslint_json.JSONRuleDefinition;
|
|
123
122
|
"lint-setup": _eslint_json.JSONRuleDefinition;
|
|
124
123
|
"vitest-coverage": _eslint_json.JSONRuleDefinition;
|
|
@@ -133,6 +132,7 @@ declare const huskyRules: {
|
|
|
133
132
|
};
|
|
134
133
|
|
|
135
134
|
declare const vulykRules: {
|
|
135
|
+
"vulyk-dependency": _eslint_json.JSONRuleDefinition;
|
|
136
136
|
"vulyk-docs": _eslint_json.JSONRuleDefinition;
|
|
137
137
|
};
|
|
138
138
|
|
|
@@ -145,10 +145,10 @@ declare const vulykRules: {
|
|
|
145
145
|
*/
|
|
146
146
|
declare const pasikaPlugin: {
|
|
147
147
|
rules: {
|
|
148
|
+
"vulyk-dependency": _eslint_json.JSONRuleDefinition;
|
|
148
149
|
"vulyk-docs": _eslint_json.JSONRuleDefinition;
|
|
149
150
|
"husky-hook": _eslint_json.JSONRuleDefinition;
|
|
150
151
|
"nextjs-stack": _eslint_json.JSONRuleDefinition;
|
|
151
|
-
"no-vulyk-dependency": _eslint_json.JSONRuleDefinition;
|
|
152
152
|
"exact-version": _eslint_json.JSONRuleDefinition;
|
|
153
153
|
"lint-setup": _eslint_json.JSONRuleDefinition;
|
|
154
154
|
"vitest-coverage": _eslint_json.JSONRuleDefinition;
|
|
@@ -6100,39 +6100,6 @@ var lintSetupRule = {
|
|
|
6100
6100
|
}
|
|
6101
6101
|
};
|
|
6102
6102
|
|
|
6103
|
-
// eslint/rules/package-json/no-vulyk-dependency.ts
|
|
6104
|
-
function memberName3(member) {
|
|
6105
|
-
return member.name.type === "String" ? member.name.value : member.name.name;
|
|
6106
|
-
}
|
|
6107
|
-
var noVulykDependencyRule = {
|
|
6108
|
-
meta: {
|
|
6109
|
-
schema: [],
|
|
6110
|
-
type: "problem",
|
|
6111
|
-
docs: {
|
|
6112
|
-
description: "Require vulyk to run as an ephemeral command, not a package.json dependency."
|
|
6113
|
-
}
|
|
6114
|
-
},
|
|
6115
|
-
create(context) {
|
|
6116
|
-
return {
|
|
6117
|
-
Document(node) {
|
|
6118
|
-
const root = node.body;
|
|
6119
|
-
if (root.type !== "Object") return;
|
|
6120
|
-
for (const key of ["dependencies", "devDependencies"]) {
|
|
6121
|
-
const section = root.members.find((member) => memberName3(member) === key);
|
|
6122
|
-
if (section?.value.type !== "Object") continue;
|
|
6123
|
-
const vulyk = section.value.members.find((member) => memberName3(member) === "vulyk");
|
|
6124
|
-
if (vulyk) {
|
|
6125
|
-
context.report({
|
|
6126
|
-
node: vulyk,
|
|
6127
|
-
message: 'Vulyk must not be a package.json dependency. Run it as "npx vulyk@latest" instead.'
|
|
6128
|
-
});
|
|
6129
|
-
}
|
|
6130
|
-
}
|
|
6131
|
-
}
|
|
6132
|
-
};
|
|
6133
|
-
}
|
|
6134
|
-
};
|
|
6135
|
-
|
|
6136
6103
|
// eslint/rules/package-json/nextjs-stack.ts
|
|
6137
6104
|
var NEXTJS_STACK_DEPENDENCIES = [
|
|
6138
6105
|
"next",
|
|
@@ -6156,13 +6123,13 @@ var NEXTJS_STACK_DEV_DEPENDENCIES = [
|
|
|
6156
6123
|
"@testing-library/react",
|
|
6157
6124
|
"@testing-library/dom"
|
|
6158
6125
|
];
|
|
6159
|
-
function
|
|
6126
|
+
function memberName3(member) {
|
|
6160
6127
|
return member.name.type === "String" ? member.name.value : member.name.name;
|
|
6161
6128
|
}
|
|
6162
6129
|
function sectionPackages(root, section) {
|
|
6163
|
-
const member = root.type === "Object" ? root.members.find((entry) =>
|
|
6130
|
+
const member = root.type === "Object" ? root.members.find((entry) => memberName3(entry) === section) : void 0;
|
|
6164
6131
|
if (member?.value.type !== "Object") return /* @__PURE__ */ new Set();
|
|
6165
|
-
return new Set(member.value.members.map(
|
|
6132
|
+
return new Set(member.value.members.map(memberName3));
|
|
6166
6133
|
}
|
|
6167
6134
|
var nextjsStackRule = {
|
|
6168
6135
|
meta: {
|
|
@@ -6201,7 +6168,7 @@ var nextjsStackRule = {
|
|
|
6201
6168
|
// eslint/rules/package-json/vitest-coverage.ts
|
|
6202
6169
|
import { existsSync as existsSync4, readFileSync as readFileSync9 } from "fs";
|
|
6203
6170
|
import path47 from "path";
|
|
6204
|
-
function
|
|
6171
|
+
function memberName4(member) {
|
|
6205
6172
|
return member.name.type === "String" ? member.name.value : member.name.name;
|
|
6206
6173
|
}
|
|
6207
6174
|
function memberValue3(member) {
|
|
@@ -6238,9 +6205,9 @@ var vitestCoverageRule = {
|
|
|
6238
6205
|
Document(node) {
|
|
6239
6206
|
const root = node.body;
|
|
6240
6207
|
if (root.type !== "Object") return;
|
|
6241
|
-
const devDependencies = root.members.find((member) =>
|
|
6208
|
+
const devDependencies = root.members.find((member) => memberName4(member) === "devDependencies");
|
|
6242
6209
|
const devDependencyNames = new Set(
|
|
6243
|
-
devDependencies?.value.type === "Object" ? devDependencies.value.members.map(
|
|
6210
|
+
devDependencies?.value.type === "Object" ? devDependencies.value.members.map(memberName4) : []
|
|
6244
6211
|
);
|
|
6245
6212
|
if (!devDependencyNames.has("vitest")) {
|
|
6246
6213
|
context.report({ node, message: "vitest must be listed in package.json as a devDependency." });
|
|
@@ -6251,9 +6218,9 @@ var vitestCoverageRule = {
|
|
|
6251
6218
|
message: "@vitest/coverage-v8 must be listed in package.json as a devDependency."
|
|
6252
6219
|
});
|
|
6253
6220
|
}
|
|
6254
|
-
const scripts = root.members.find((member) =>
|
|
6221
|
+
const scripts = root.members.find((member) => memberName4(member) === "scripts");
|
|
6255
6222
|
const scriptMembers = scripts?.value.type === "Object" ? scripts.value.members : [];
|
|
6256
|
-
const unit = scriptMembers.find((member) =>
|
|
6223
|
+
const unit = scriptMembers.find((member) => memberName4(member) === "test:unit");
|
|
6257
6224
|
const unitCommand = memberValue3(unit);
|
|
6258
6225
|
if (unitCommand === void 0 || !/\bvitest\b/.test(unitCommand) || COVERAGE_FLAG_PATTERN.test(unitCommand)) {
|
|
6259
6226
|
context.report({
|
|
@@ -6261,7 +6228,7 @@ var vitestCoverageRule = {
|
|
|
6261
6228
|
message: 'package.json must declare a "test:unit" script that runs Vitest without coverage.'
|
|
6262
6229
|
});
|
|
6263
6230
|
}
|
|
6264
|
-
const coverage = scriptMembers.find((member) =>
|
|
6231
|
+
const coverage = scriptMembers.find((member) => memberName4(member) === "test:unit:coverage");
|
|
6265
6232
|
const coverageCommand = memberValue3(coverage);
|
|
6266
6233
|
if (coverageCommand === void 0 || !/\bvitest\b/.test(coverageCommand) || !COVERAGE_FLAG_PATTERN.test(coverageCommand)) {
|
|
6267
6234
|
context.report({
|
|
@@ -6289,7 +6256,7 @@ var vitestCoverageRule = {
|
|
|
6289
6256
|
message: `${configName} must set coverage.thresholds.autoUpdate to true.`
|
|
6290
6257
|
});
|
|
6291
6258
|
}
|
|
6292
|
-
const stagedTests = scriptMembers.find((member) =>
|
|
6259
|
+
const stagedTests = scriptMembers.find((member) => memberName4(member) === "test:unit:staged");
|
|
6293
6260
|
const stagedTestsCommand = memberValue3(stagedTests);
|
|
6294
6261
|
if (stagedTestsCommand === void 0 || !/\bvitest\b/.test(stagedTestsCommand) || !RELATED_PATTERN.test(stagedTestsCommand) || COVERAGE_FLAG_PATTERN.test(stagedTestsCommand)) {
|
|
6295
6262
|
context.report({
|
|
@@ -6297,9 +6264,9 @@ var vitestCoverageRule = {
|
|
|
6297
6264
|
message: 'package.json must declare a "test:unit:staged" script that runs vitest related without coverage.'
|
|
6298
6265
|
});
|
|
6299
6266
|
}
|
|
6300
|
-
const lintStaged = root.members.find((member) =>
|
|
6267
|
+
const lintStaged = root.members.find((member) => memberName4(member) === "lint-staged");
|
|
6301
6268
|
const hasStagedTests = lintStaged?.value.type === "Object" && lintStaged.value.members.some(
|
|
6302
|
-
(member) => SOURCE_GLOB_PATTERN2.test(
|
|
6269
|
+
(member) => SOURCE_GLOB_PATTERN2.test(memberName4(member)) && stringValues2(member.value).some((command) => command.includes("npm run test:unit:staged"))
|
|
6303
6270
|
);
|
|
6304
6271
|
if (!hasStagedTests) {
|
|
6305
6272
|
context.report({
|
|
@@ -6314,7 +6281,6 @@ var vitestCoverageRule = {
|
|
|
6314
6281
|
|
|
6315
6282
|
// eslint/rules/package-json/index.ts
|
|
6316
6283
|
var repoPackageJsonRules = {
|
|
6317
|
-
"no-vulyk-dependency": noVulykDependencyRule,
|
|
6318
6284
|
"exact-version": exactVersionRule,
|
|
6319
6285
|
"lint-setup": lintSetupRule,
|
|
6320
6286
|
"vitest-coverage": vitestCoverageRule
|
|
@@ -6326,7 +6292,15 @@ var nextjsPackageJsonRules = {
|
|
|
6326
6292
|
// eslint/rules/husky/husky-hook.ts
|
|
6327
6293
|
import { existsSync as existsSync5, readFileSync as readFileSync10 } from "fs";
|
|
6328
6294
|
import path48 from "path";
|
|
6329
|
-
|
|
6295
|
+
var VITEST_CONFIG_NAMES2 = [
|
|
6296
|
+
"vitest.config.ts",
|
|
6297
|
+
"vitest.config.mts",
|
|
6298
|
+
"vitest.config.cts",
|
|
6299
|
+
"vitest.config.js",
|
|
6300
|
+
"vitest.config.mjs",
|
|
6301
|
+
"vitest.config.cjs"
|
|
6302
|
+
];
|
|
6303
|
+
function memberName5(member) {
|
|
6330
6304
|
return member.name.type === "String" ? member.name.value : member.name.name;
|
|
6331
6305
|
}
|
|
6332
6306
|
var huskyHookRule = {
|
|
@@ -6334,7 +6308,7 @@ var huskyHookRule = {
|
|
|
6334
6308
|
schema: [],
|
|
6335
6309
|
type: "problem",
|
|
6336
6310
|
docs: {
|
|
6337
|
-
description: "Require a pre-commit hook that runs lint-staged
|
|
6311
|
+
description: "Require a pre-commit hook that runs lint-staged, typecheck, coverage with local threshold staging, suppression pruning when applicable, and the libyear drift check."
|
|
6338
6312
|
}
|
|
6339
6313
|
},
|
|
6340
6314
|
create(context) {
|
|
@@ -6352,8 +6326,8 @@ var huskyHookRule = {
|
|
|
6352
6326
|
return;
|
|
6353
6327
|
}
|
|
6354
6328
|
const content = readFileSync10(hookPath, "utf8");
|
|
6355
|
-
const scripts = root.members.find((member) =>
|
|
6356
|
-
const scriptNames = new Set(scripts?.value.type === "Object" ? scripts.value.members.map(
|
|
6329
|
+
const scripts = root.members.find((member) => memberName5(member) === "scripts");
|
|
6330
|
+
const scriptNames = new Set(scripts?.value.type === "Object" ? scripts.value.members.map(memberName5) : []);
|
|
6357
6331
|
const requireNamedScript = (name) => {
|
|
6358
6332
|
if (!scriptNames.has(name)) {
|
|
6359
6333
|
context.report({ node, message: `package.json must declare a "${name}" script.` });
|
|
@@ -6366,6 +6340,18 @@ var huskyHookRule = {
|
|
|
6366
6340
|
context.report({ node, message: ".husky/pre-commit must run lint-staged." });
|
|
6367
6341
|
}
|
|
6368
6342
|
requireNamedScript("typecheck");
|
|
6343
|
+
requireNamedScript("test:unit:coverage");
|
|
6344
|
+
const vitestConfigName = VITEST_CONFIG_NAMES2.find((name) => existsSync5(path48.join(context.cwd, name)));
|
|
6345
|
+
if (vitestConfigName !== void 0) {
|
|
6346
|
+
const coverageIndex = content.indexOf("npm run test:unit:coverage");
|
|
6347
|
+
const localAddIndex = content.indexOf(`git add ${vitestConfigName}`);
|
|
6348
|
+
if (localAddIndex <= coverageIndex) {
|
|
6349
|
+
context.report({
|
|
6350
|
+
node,
|
|
6351
|
+
message: `.husky/pre-commit must stage an auto-updated ${vitestConfigName} after coverage.`
|
|
6352
|
+
});
|
|
6353
|
+
}
|
|
6354
|
+
}
|
|
6369
6355
|
if (!content.includes("libyear --limit-major-individual=1")) {
|
|
6370
6356
|
context.report({ node, message: ".husky/pre-commit must run npx libyear --limit-major-individual=1." });
|
|
6371
6357
|
}
|
|
@@ -6374,7 +6360,7 @@ var huskyHookRule = {
|
|
|
6374
6360
|
requireNamedScript("lint:prune");
|
|
6375
6361
|
}
|
|
6376
6362
|
if (scripts?.value.type === "Object") {
|
|
6377
|
-
const prepare = scripts.value.members.find((member) =>
|
|
6363
|
+
const prepare = scripts.value.members.find((member) => memberName5(member) === "prepare");
|
|
6378
6364
|
if (prepare?.value.type === "String" && !prepare.value.value.includes("husky")) {
|
|
6379
6365
|
context.report({
|
|
6380
6366
|
node: prepare,
|
|
@@ -6392,6 +6378,46 @@ var huskyRules = {
|
|
|
6392
6378
|
"husky-hook": huskyHookRule
|
|
6393
6379
|
};
|
|
6394
6380
|
|
|
6381
|
+
// eslint/rules/vulyk/vulyk-dependency.ts
|
|
6382
|
+
function memberName6(member) {
|
|
6383
|
+
return member.name.type === "String" ? member.name.value : member.name.name;
|
|
6384
|
+
}
|
|
6385
|
+
function dependency(root, sectionName) {
|
|
6386
|
+
if (root.type !== "Object") return void 0;
|
|
6387
|
+
const section = root.members.find((member) => memberName6(member) === sectionName);
|
|
6388
|
+
if (section?.value.type !== "Object") return void 0;
|
|
6389
|
+
return section.value.members.find((member) => memberName6(member) === "vulyk");
|
|
6390
|
+
}
|
|
6391
|
+
var vulykDependencyRule = {
|
|
6392
|
+
meta: {
|
|
6393
|
+
schema: [],
|
|
6394
|
+
type: "problem",
|
|
6395
|
+
docs: {
|
|
6396
|
+
description: "Require vulyk in devDependencies so its typed config and CLI use the pinned package."
|
|
6397
|
+
}
|
|
6398
|
+
},
|
|
6399
|
+
create(context) {
|
|
6400
|
+
return {
|
|
6401
|
+
Document(node) {
|
|
6402
|
+
const runtimeDependency = dependency(node.body, "dependencies");
|
|
6403
|
+
const developmentDependency = dependency(node.body, "devDependencies");
|
|
6404
|
+
if (runtimeDependency) {
|
|
6405
|
+
context.report({
|
|
6406
|
+
node: runtimeDependency,
|
|
6407
|
+
message: "vulyk must be listed in devDependencies, not dependencies."
|
|
6408
|
+
});
|
|
6409
|
+
}
|
|
6410
|
+
if (!developmentDependency && !runtimeDependency) {
|
|
6411
|
+
context.report({
|
|
6412
|
+
node,
|
|
6413
|
+
message: "vulyk must be listed in package.json as a devDependency."
|
|
6414
|
+
});
|
|
6415
|
+
}
|
|
6416
|
+
}
|
|
6417
|
+
};
|
|
6418
|
+
}
|
|
6419
|
+
};
|
|
6420
|
+
|
|
6395
6421
|
// eslint/rules/vulyk/vulyk-docs.ts
|
|
6396
6422
|
import { existsSync as existsSync6, readFileSync as readFileSync11 } from "fs";
|
|
6397
6423
|
import path49 from "path";
|
|
@@ -6432,7 +6458,7 @@ var vulykDocsRule = {
|
|
|
6432
6458
|
if (!existsSync6(configPath)) {
|
|
6433
6459
|
context.report({
|
|
6434
6460
|
node,
|
|
6435
|
-
message: "No vulyk.config.ts found. Run npx vulyk
|
|
6461
|
+
message: "No vulyk.config.ts found. Run npx vulyk init to create one that tracks the framework's docs."
|
|
6436
6462
|
});
|
|
6437
6463
|
return;
|
|
6438
6464
|
}
|
|
@@ -6457,7 +6483,7 @@ var vulykDocsRule = {
|
|
|
6457
6483
|
if (!existsSync6(agentsPath)) {
|
|
6458
6484
|
context.report({
|
|
6459
6485
|
node,
|
|
6460
|
-
message: "No AGENTS.md found. Run npx vulyk
|
|
6486
|
+
message: "No AGENTS.md found. Run npx vulyk agents to generate the agent file that routes to the tracked docs."
|
|
6461
6487
|
});
|
|
6462
6488
|
}
|
|
6463
6489
|
}
|
|
@@ -6467,6 +6493,7 @@ var vulykDocsRule = {
|
|
|
6467
6493
|
|
|
6468
6494
|
// eslint/rules/vulyk/index.ts
|
|
6469
6495
|
var vulykRules = {
|
|
6496
|
+
"vulyk-dependency": vulykDependencyRule,
|
|
6470
6497
|
"vulyk-docs": vulykDocsRule
|
|
6471
6498
|
};
|
|
6472
6499
|
|