@amritk/lint 0.3.2 → 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/AI.md +55 -0
- package/dist/core/document.js +12 -10
- package/dist/core/formats.js +10 -13
- package/dist/core/glob.js +96 -118
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.js +30 -11
- package/dist/core/jsonpath.js +487 -561
- package/dist/core/lint.js +78 -85
- package/dist/core/plugin.js +21 -29
- package/dist/core/pointers.js +107 -151
- package/dist/core/ruleset.js +0 -0
- package/dist/core/runner.js +214 -272
- package/dist/core/types.js +4 -1
- package/dist/core/validate-ruleset.js +98 -112
- package/dist/fix/apply.d.ts +1 -1
- package/dist/fix/apply.js +58 -96
- package/dist/fix/index.js +7 -2
- package/dist/fix/plugin.js +15 -20
- package/dist/fix/types.d.ts +1 -1
- package/dist/functions/alphabetical.d.ts +1 -1
- package/dist/functions/alphabetical.js +39 -50
- package/dist/functions/casing.d.ts +1 -1
- package/dist/functions/casing.js +39 -45
- package/dist/functions/defined.d.ts +1 -1
- package/dist/functions/defined.js +7 -5
- package/dist/functions/enumeration.d.ts +1 -1
- package/dist/functions/enumeration.js +15 -25
- package/dist/functions/falsy.d.ts +1 -1
- package/dist/functions/falsy.js +7 -5
- package/dist/functions/index.d.ts +1 -1
- package/dist/functions/index.js +60 -44
- package/dist/functions/length.d.ts +1 -1
- package/dist/functions/length.js +22 -32
- package/dist/functions/or.d.ts +1 -1
- package/dist/functions/or.js +18 -24
- package/dist/functions/pattern.d.ts +1 -1
- package/dist/functions/pattern.js +39 -49
- package/dist/functions/schema.d.ts +1 -1
- package/dist/functions/schema.js +93 -119
- package/dist/functions/truthy.d.ts +1 -1
- package/dist/functions/truthy.js +7 -5
- package/dist/functions/typed-enum.d.ts +1 -1
- package/dist/functions/typed-enum.js +33 -36
- package/dist/functions/undefined.d.ts +1 -1
- package/dist/functions/undefined.js +7 -8
- package/dist/functions/unreferenced-reusable-object.d.ts +1 -1
- package/dist/functions/unreferenced-reusable-object.js +35 -47
- package/dist/functions/xor.d.ts +1 -1
- package/dist/functions/xor.js +13 -16
- package/dist/index.d.ts +17 -4
- package/dist/index.js +149 -164
- package/dist/parsers/edit-model.js +316 -444
- package/dist/parsers/index.d.ts +1 -1
- package/dist/parsers/index.js +23 -19
- package/dist/parsers/json.js +39 -37
- package/dist/parsers/lines.js +23 -26
- package/dist/parsers/types.js +9 -7
- package/dist/parsers/yaml.js +137 -204
- package/dist/rules/openapi/fixers.js +166 -221
- package/dist/rules/openapi/formats.js +26 -27
- package/dist/rules/openapi/functions/example-validation.d.ts +1 -1
- package/dist/rules/openapi/functions/example-validation.js +98 -138
- package/dist/rules/openapi/functions/helpers.js +8 -10
- package/dist/rules/openapi/functions/index.d.ts +1 -1
- package/dist/rules/openapi/functions/index.js +98 -72
- package/dist/rules/openapi/functions/oas-additional-operations.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-additional-operations.js +16 -22
- package/dist/rules/openapi/functions/oas-discriminator.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-discriminator.js +24 -22
- package/dist/rules/openapi/functions/oas-example-external-value.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-example-external-value.js +13 -21
- package/dist/rules/openapi/functions/oas-example-value.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-example-value.js +24 -27
- package/dist/rules/openapi/functions/oas-mutually-exclusive.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-mutually-exclusive.js +15 -19
- package/dist/rules/openapi/functions/oas-no-nullable.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-no-nullable.js +13 -21
- package/dist/rules/openapi/functions/oas-op-form-data-consume-check.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-op-form-data-consume-check.js +21 -19
- package/dist/rules/openapi/functions/oas-op-id-unique.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-op-id-unique.js +27 -27
- package/dist/rules/openapi/functions/oas-op-params.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-op-params.js +36 -42
- package/dist/rules/openapi/functions/oas-op-security-defined.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-op-security-defined.js +40 -39
- package/dist/rules/openapi/functions/oas-op-success-response.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-op-success-response.js +11 -13
- package/dist/rules/openapi/functions/oas-path-param.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-path-param.js +75 -96
- package/dist/rules/openapi/functions/oas-schema-example-deprecated.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-schema-example-deprecated.js +33 -40
- package/dist/rules/openapi/functions/oas-schema.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-schema.js +9 -14
- package/dist/rules/openapi/functions/oas-server-name-unique.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-server-name-unique.js +21 -19
- package/dist/rules/openapi/functions/oas-server-variables.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-server-variables.js +45 -49
- package/dist/rules/openapi/functions/oas-tag-defined.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-tag-defined.js +20 -20
- package/dist/rules/openapi/functions/oas-tag-kind.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-tag-kind.js +16 -16
- package/dist/rules/openapi/functions/oas-tag-parent-defined.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-tag-parent-defined.js +40 -43
- package/dist/rules/openapi/functions/oas-tags-unique.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-tags-unique.js +18 -16
- package/dist/rules/openapi/functions/oas-unused-component.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-unused-component.js +48 -58
- package/dist/rules/openapi/functions/ref-siblings.d.ts +1 -1
- package/dist/rules/openapi/functions/ref-siblings.js +13 -11
- package/dist/rules/openapi/index.d.ts +2 -1
- package/dist/rules/openapi/index.js +99 -117
- package/dist/rules/openapi/oas.d.ts +1 -1
- package/dist/rules/openapi/oas.js +524 -536
- package/dist/rules/openapi/schemas/index.js +17 -33
- package/dist/rules/openapi/schemas/oas20.json +1 -1592
- package/dist/rules/openapi/schemas/oas30.json +1 -1651
- package/dist/rules/openapi/schemas/oas31.json +1 -1412
- package/dist/rules/openapi/schemas/oas32.json +1 -1684
- package/package.json +11 -6
package/dist/index.js
CHANGED
|
@@ -1,176 +1,161 @@
|
|
|
1
|
-
import { readFileSync } from
|
|
2
|
-
import { createRequire } from
|
|
3
|
-
import { dirname, isAbsolute, resolve as resolvePath } from
|
|
4
|
-
import { createRuleset as createCoreRuleset, lintWithResult
|
|
5
|
-
import { createFixPlugin, FIX_PLUGIN_NAME } from
|
|
6
|
-
import { builtinFunctions } from
|
|
7
|
-
import { parseWithPointers } from
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
// `IDiagnostic[]`, and the caller decides how to display or serialize them.
|
|
14
|
-
export * from './core/index.js';
|
|
15
|
-
export * from './fix/index.js';
|
|
16
|
-
export * from './functions/index.js';
|
|
17
|
-
export { detectFormat, parseWithPointers } from './parsers/index.js';
|
|
18
|
-
const require = createRequire(import.meta.url);
|
|
19
|
-
/** Loads a ruleset definition from a file path by extension (YAML/JSON parsed, JS/CJS/MJS required). */
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { dirname, isAbsolute, resolve as resolvePath } from "node:path";
|
|
4
|
+
import { createRuleset as createCoreRuleset, lintWithResult } from "./core/index.js";
|
|
5
|
+
import { createFixPlugin, FIX_PLUGIN_NAME } from "./fix/index.js";
|
|
6
|
+
import { builtinFunctions } from "./functions/index.js";
|
|
7
|
+
import { parseWithPointers } from "./parsers/index.js";
|
|
8
|
+
import { compileQuery, createDocument, createLinter, detectFormats, globToRegExp, lint, lintWithResult as lintWithResult2, matchesGlob, pointerToPath, query, queryCompiled, queryMany, resolveSourceOrigin, resolveSourceOriginFromMap, resolveSourcePath, runPlugins, validateRuleset } from "./core/index.js";
|
|
9
|
+
import { applyFixes, createFixPlugin as createFixPlugin2, FIX_PLUGIN_NAME as FIX_PLUGIN_NAME2 } from "./fix/index.js";
|
|
10
|
+
import { alphabetical, builtinFunctions as builtinFunctions2, casing, defined, enumeration, falsy, length, or, pattern, schema, truthy, typedEnum, undefinedFn, unreferencedReusableObject, xor } from "./functions/index.js";
|
|
11
|
+
import { detectFormat, parseWithPointers as parseWithPointers2 } from "./parsers/index.js";
|
|
12
|
+
const require2 = createRequire(import.meta.url);
|
|
20
13
|
const loadRulesetFile = (file) => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
if (/\.(ya?ml|json)$/i.test(file)) {
|
|
15
|
+
return parseWithPointers(readFileSync(file, "utf8")).data;
|
|
16
|
+
}
|
|
17
|
+
const module = require2(file);
|
|
18
|
+
return module.default ?? module;
|
|
26
19
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
let file;
|
|
41
|
-
try {
|
|
42
|
-
file = require.resolve(name, { paths: [basePath] });
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
throw new Error(`Cannot resolve extended ruleset "${name}" from ${basePath}`);
|
|
46
|
-
}
|
|
47
|
-
return { definition: loadRulesetFile(file), basePath: dirname(file) };
|
|
20
|
+
const resolveNamedRuleset = (name, basePath = process.cwd()) => {
|
|
21
|
+
if (name.startsWith(".") || isAbsolute(name)) {
|
|
22
|
+
const file2 = resolvePath(basePath, name);
|
|
23
|
+
return { definition: loadRulesetFile(file2), basePath: dirname(file2) };
|
|
24
|
+
}
|
|
25
|
+
let file;
|
|
26
|
+
try {
|
|
27
|
+
file = require2.resolve(name, { paths: [basePath] });
|
|
28
|
+
} catch {
|
|
29
|
+
throw new Error(`Cannot resolve extended ruleset "${name}" from ${basePath}`);
|
|
30
|
+
}
|
|
31
|
+
return { definition: loadRulesetFile(file), basePath: dirname(file) };
|
|
48
32
|
};
|
|
49
|
-
/** Loads a single custom function module (`<dir>/<name>.{js,cjs,mjs}` or a bare path). */
|
|
50
33
|
const loadFunctionByName = (basePath, dir, name) => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
throw error;
|
|
64
|
-
}
|
|
34
|
+
const baseFile = resolvePath(basePath, dir, name);
|
|
35
|
+
for (const candidate of [baseFile, `${baseFile}.js`, `${baseFile}.cjs`, `${baseFile}.mjs`]) {
|
|
36
|
+
try {
|
|
37
|
+
const resolvedFile = require2.resolve(candidate);
|
|
38
|
+
const module = require2(resolvedFile);
|
|
39
|
+
const fn = module.default ?? module;
|
|
40
|
+
if (typeof fn !== "function")
|
|
41
|
+
throw new Error(`"${name}" did not export a function`);
|
|
42
|
+
return fn;
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (error.code !== "MODULE_NOT_FOUND")
|
|
45
|
+
throw error;
|
|
65
46
|
}
|
|
66
|
-
|
|
47
|
+
}
|
|
48
|
+
throw new Error(`Cannot resolve custom function "${name}" from ${resolvePath(basePath, dir)}`);
|
|
67
49
|
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
seen)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (typeof target === 'string') {
|
|
87
|
-
const key = `${basePath}\0${target}`;
|
|
88
|
-
if (seen.has(key))
|
|
89
|
-
continue;
|
|
90
|
-
seen.add(key);
|
|
91
|
-
const resolved = resolveNamedRuleset(target, basePath);
|
|
92
|
-
collectCustomFunctions(resolved.definition, resolved.basePath, into, seen);
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
collectCustomFunctions(target, basePath, into, seen);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
if (Array.isArray(definition.functions)) {
|
|
100
|
-
const dir = definition.functionsDir ?? 'functions';
|
|
101
|
-
for (const name of definition.functions)
|
|
102
|
-
into[name] = loadFunctionByName(basePath, dir, name);
|
|
50
|
+
const collectCustomFunctions = (definition, basePath, into, seen) => {
|
|
51
|
+
if (seen.has(definition))
|
|
52
|
+
return;
|
|
53
|
+
seen.add(definition);
|
|
54
|
+
if (definition.extends) {
|
|
55
|
+
const entries = Array.isArray(definition.extends) ? definition.extends : [definition.extends];
|
|
56
|
+
for (const entry of entries) {
|
|
57
|
+
const target = Array.isArray(entry) ? entry[0] : entry;
|
|
58
|
+
if (typeof target === "string") {
|
|
59
|
+
const key = `${basePath}\0${target}`;
|
|
60
|
+
if (seen.has(key))
|
|
61
|
+
continue;
|
|
62
|
+
seen.add(key);
|
|
63
|
+
const resolved = resolveNamedRuleset(target, basePath);
|
|
64
|
+
collectCustomFunctions(resolved.definition, resolved.basePath, into, seen);
|
|
65
|
+
} else {
|
|
66
|
+
collectCustomFunctions(target, basePath, into, seen);
|
|
67
|
+
}
|
|
103
68
|
}
|
|
69
|
+
}
|
|
70
|
+
if (Array.isArray(definition.functions)) {
|
|
71
|
+
const dir = definition.functionsDir ?? "functions";
|
|
72
|
+
for (const name of definition.functions)
|
|
73
|
+
into[name] = loadFunctionByName(basePath, dir, name);
|
|
74
|
+
}
|
|
104
75
|
};
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const custom = {};
|
|
118
|
-
collectCustomFunctions(resolved, basePath ?? process.cwd(), custom, new Set());
|
|
119
|
-
if (Object.keys(custom).length > 0)
|
|
120
|
-
functions = { ...builtinFunctions, ...custom };
|
|
121
|
-
return createCoreRuleset(resolved, {
|
|
122
|
-
functions,
|
|
123
|
-
resolve: resolveNamedRuleset,
|
|
124
|
-
...(basePath !== undefined ? { basePath } : {}),
|
|
125
|
-
});
|
|
76
|
+
const createRuleset = (definition, basePath) => {
|
|
77
|
+
const resolved = definition ?? {};
|
|
78
|
+
let functions = builtinFunctions;
|
|
79
|
+
const custom = {};
|
|
80
|
+
collectCustomFunctions(resolved, basePath ?? process.cwd(), custom, /* @__PURE__ */ new Set());
|
|
81
|
+
if (Object.keys(custom).length > 0)
|
|
82
|
+
functions = { ...builtinFunctions, ...custom };
|
|
83
|
+
return createCoreRuleset(resolved, {
|
|
84
|
+
functions,
|
|
85
|
+
resolve: resolveNamedRuleset,
|
|
86
|
+
...basePath !== void 0 ? { basePath } : {}
|
|
87
|
+
});
|
|
126
88
|
};
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
*/
|
|
138
|
-
export const lintDocumentWithResult = async (input, options = {}) => {
|
|
139
|
-
const { ruleset: rulesetDefinition, rulesetBasePath, resolve, plugins, ...documentOptions } = options;
|
|
140
|
-
const ruleset = createRuleset(rulesetDefinition, rulesetBasePath);
|
|
141
|
-
return lintWithResult(input, {
|
|
142
|
-
...documentOptions,
|
|
143
|
-
ruleset,
|
|
144
|
-
...(resolve ? { resolve } : {}),
|
|
145
|
-
...(plugins ? { plugins } : {}),
|
|
146
|
-
});
|
|
89
|
+
const lintDocument = async (input, options = {}) => (await lintDocumentWithResult(input, options)).diagnostics;
|
|
90
|
+
const lintDocumentWithResult = async (input, options = {}) => {
|
|
91
|
+
const { ruleset: rulesetDefinition, rulesetBasePath, resolve, plugins, ...documentOptions } = options;
|
|
92
|
+
const ruleset = createRuleset(rulesetDefinition, rulesetBasePath);
|
|
93
|
+
return lintWithResult(input, {
|
|
94
|
+
...documentOptions,
|
|
95
|
+
ruleset,
|
|
96
|
+
...resolve ? { resolve } : {},
|
|
97
|
+
...plugins ? { plugins } : {}
|
|
98
|
+
});
|
|
147
99
|
};
|
|
148
|
-
// One fix pass can unblock the next, so we lint-and-fix to a fixpoint. The cap is
|
|
149
|
-
// a safety net against a fixer that oscillates rather than converging — in
|
|
150
|
-
// practice a couple of passes is plenty.
|
|
151
100
|
const MAX_FIX_PASSES = 10;
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
101
|
+
const fixDocument = async (input, options = {}) => {
|
|
102
|
+
const { fixers = {}, safeOnly, ...lintOptions } = options;
|
|
103
|
+
const plugin = createFixPlugin(fixers, { safeOnly: safeOnly !== false });
|
|
104
|
+
let current = input;
|
|
105
|
+
const applied = [];
|
|
106
|
+
for (let pass = 0; pass < MAX_FIX_PASSES; pass++) {
|
|
107
|
+
const result = await lintDocumentWithResult(current, { ...lintOptions, plugins: [plugin] });
|
|
108
|
+
if (result.output === void 0 || result.output === current)
|
|
109
|
+
break;
|
|
110
|
+
current = result.output;
|
|
111
|
+
const data = result.pluginData[FIX_PLUGIN_NAME];
|
|
112
|
+
if (data)
|
|
113
|
+
applied.push(...data.applied);
|
|
114
|
+
}
|
|
115
|
+
const remaining = await lintDocument(current, lintOptions);
|
|
116
|
+
return { output: current, fixed: applied.length > 0, remaining, applied };
|
|
117
|
+
};
|
|
118
|
+
export {
|
|
119
|
+
FIX_PLUGIN_NAME2 as FIX_PLUGIN_NAME,
|
|
120
|
+
alphabetical,
|
|
121
|
+
applyFixes,
|
|
122
|
+
builtinFunctions2 as builtinFunctions,
|
|
123
|
+
casing,
|
|
124
|
+
compileQuery,
|
|
125
|
+
createDocument,
|
|
126
|
+
createFixPlugin2 as createFixPlugin,
|
|
127
|
+
createLinter,
|
|
128
|
+
createRuleset,
|
|
129
|
+
defined,
|
|
130
|
+
detectFormat,
|
|
131
|
+
detectFormats,
|
|
132
|
+
enumeration,
|
|
133
|
+
falsy,
|
|
134
|
+
fixDocument,
|
|
135
|
+
globToRegExp,
|
|
136
|
+
length,
|
|
137
|
+
lint,
|
|
138
|
+
lintDocument,
|
|
139
|
+
lintDocumentWithResult,
|
|
140
|
+
lintWithResult2 as lintWithResult,
|
|
141
|
+
matchesGlob,
|
|
142
|
+
or,
|
|
143
|
+
parseWithPointers2 as parseWithPointers,
|
|
144
|
+
pattern,
|
|
145
|
+
pointerToPath,
|
|
146
|
+
query,
|
|
147
|
+
queryCompiled,
|
|
148
|
+
queryMany,
|
|
149
|
+
resolveNamedRuleset,
|
|
150
|
+
resolveSourceOrigin,
|
|
151
|
+
resolveSourceOriginFromMap,
|
|
152
|
+
resolveSourcePath,
|
|
153
|
+
runPlugins,
|
|
154
|
+
schema,
|
|
155
|
+
truthy,
|
|
156
|
+
typedEnum,
|
|
157
|
+
undefinedFn,
|
|
158
|
+
unreferencedReusableObject,
|
|
159
|
+
validateRuleset,
|
|
160
|
+
xor
|
|
176
161
|
};
|