@valbuild/eslint-plugin 0.46.0 → 0.47.1
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/dist/valbuild-eslint-plugin.cjs.dev.js +77 -37
- package/dist/valbuild-eslint-plugin.cjs.prod.js +77 -37
- package/dist/valbuild-eslint-plugin.esm.js +77 -37
- package/package.json +3 -2
- package/src/index.js +5 -24
- package/src/rules/exportContentMustBeValid.js +44 -0
- package/src/rules/noIllegalImports.js +48 -0
- package/src/rules/noIllegalModuleIds.js +2 -3
- package/test/rules/exportContentMustBeValid.test.js +56 -0
- package/test/rules/noIllegalImports.test.js +100 -0
- package/test/rules/noIllegalModuleIds.test.js +2 -2
@@ -46,8 +46,7 @@ var noIllegalModuleIds = {
|
|
46
46
|
meta: {
|
47
47
|
type: "problem",
|
48
48
|
docs: {
|
49
|
-
description: "Check that the first argument of export default declaration matches the string from val.config.
|
50
|
-
category: "Best Practices",
|
49
|
+
description: "Check that the first argument of export default declaration matches the string from val.config.{j,t}s file.",
|
51
50
|
recommended: true
|
52
51
|
},
|
53
52
|
fixable: "code",
|
@@ -106,7 +105,7 @@ var noIllegalModuleIds = {
|
|
106
105
|
if (rawArg) {
|
107
106
|
context.report({
|
108
107
|
node: firstArg,
|
109
|
-
message: "Val: val.content
|
108
|
+
message: "Val: val.content id should match the filename. Expected: '".concat(expectedValue, "'. Found: '").concat(firstArg.value, "'"),
|
110
109
|
fix: function fix(fixer) {
|
111
110
|
return fixer.replaceText(firstArg, "".concat(rawArg).concat(expectedValue).concat(rawArg));
|
112
111
|
}
|
@@ -123,49 +122,90 @@ var noIllegalModuleIds = {
|
|
123
122
|
// @ts-check
|
124
123
|
|
125
124
|
/**
|
126
|
-
* @type {
|
125
|
+
* @type {import('eslint').Rule.RuleModule}
|
127
126
|
*/
|
128
|
-
var
|
129
|
-
|
127
|
+
var noIllegalImports = {
|
128
|
+
meta: {
|
129
|
+
type: "problem",
|
130
|
+
docs: {
|
131
|
+
description: "Check that val files only has valid imports.",
|
132
|
+
recommended: true
|
133
|
+
},
|
134
|
+
schema: []
|
135
|
+
},
|
136
|
+
create: function create(context) {
|
137
|
+
return {
|
138
|
+
ImportDeclaration: function ImportDeclaration(node) {
|
139
|
+
var importSource = node.source.value;
|
140
|
+
var filename = context.filename || context.getFilename();
|
141
|
+
var isValFile = filename.endsWith(".val.ts") || filename.endsWith(".val.js");
|
142
|
+
// only allow: .val files, @valbuild packages, and val config
|
143
|
+
if (isValFile && typeof importSource === "string" && !importSource.match(/\.val(\.ts|\.js|)$/) && !importSource.match(/^@valbuild/) && !importSource.match(/val\.config(\.ts|\.js|)$/)) {
|
144
|
+
if ("importKind" in node && node["importKind"] !== "type" && !node.specifiers.every(function (s) {
|
145
|
+
return "importKind" in s && s["importKind"] === "type";
|
146
|
+
})) {
|
147
|
+
var message = "Val: can only 'import type' or import from source that is either: a .val.{j,t}s file, a @valbuild package, or val.config.{j,t}s.";
|
148
|
+
context.report({
|
149
|
+
node: node.source,
|
150
|
+
message: message
|
151
|
+
});
|
152
|
+
}
|
153
|
+
}
|
154
|
+
}
|
155
|
+
};
|
156
|
+
}
|
130
157
|
};
|
131
158
|
|
159
|
+
// @ts-check
|
160
|
+
|
132
161
|
/**
|
133
|
-
* @type {
|
162
|
+
* @type {import('eslint').Rule.RuleModule}
|
134
163
|
*/
|
135
|
-
var
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
text: text,
|
145
|
-
filename: filename
|
146
|
-
});
|
147
|
-
return [{
|
148
|
-
text: text,
|
149
|
-
filename: filename
|
150
|
-
}];
|
164
|
+
var exportContentMustBeValid = {
|
165
|
+
meta: {
|
166
|
+
type: "problem",
|
167
|
+
docs: {
|
168
|
+
description: "Export val.content should only happen in .val files.",
|
169
|
+
recommended: true
|
170
|
+
},
|
171
|
+
messages: {
|
172
|
+
"val/export-content-must-be-valid": "Val: val.content should only be exported from .val files"
|
151
173
|
},
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
174
|
+
schema: []
|
175
|
+
},
|
176
|
+
create: function create(context) {
|
177
|
+
return {
|
178
|
+
ExportDefaultDeclaration: function ExportDefaultDeclaration(node) {
|
179
|
+
if (node.declaration && node.declaration.type === "CallExpression" && node.declaration.callee.type === "MemberExpression" && node.declaration.callee.object.type === "Identifier" && node.declaration.callee.object.name === "val" && node.declaration.callee.property.type === "Identifier" && node.declaration.callee.property.name === "content") {
|
180
|
+
var filename = context.filename || context.getFilename();
|
181
|
+
if (!(filename !== null && filename !== void 0 && filename.endsWith(".val.ts") || filename !== null && filename !== void 0 && filename.endsWith(".val.js"))) {
|
182
|
+
context.report({
|
183
|
+
node: node.declaration.callee,
|
184
|
+
messageId: "val/export-content-must-be-valid"
|
185
|
+
});
|
186
|
+
}
|
187
|
+
}
|
188
|
+
}
|
189
|
+
};
|
166
190
|
}
|
167
191
|
};
|
168
192
|
|
193
|
+
// @ts-check
|
194
|
+
|
195
|
+
/**
|
196
|
+
* @type {Plugin["rules"]}
|
197
|
+
*/
|
198
|
+
var rules = {
|
199
|
+
"no-illegal-module-ids": noIllegalModuleIds,
|
200
|
+
"no-illegal-imports": noIllegalImports,
|
201
|
+
"export-content-must-be-valid": exportContentMustBeValid
|
202
|
+
};
|
203
|
+
|
204
|
+
/**
|
205
|
+
* @type {Plugin["processors"]}
|
206
|
+
*/
|
207
|
+
var processors = {};
|
208
|
+
|
169
209
|
/**
|
170
210
|
* @type {Plugin}
|
171
211
|
*/
|
@@ -46,8 +46,7 @@ var noIllegalModuleIds = {
|
|
46
46
|
meta: {
|
47
47
|
type: "problem",
|
48
48
|
docs: {
|
49
|
-
description: "Check that the first argument of export default declaration matches the string from val.config.
|
50
|
-
category: "Best Practices",
|
49
|
+
description: "Check that the first argument of export default declaration matches the string from val.config.{j,t}s file.",
|
51
50
|
recommended: true
|
52
51
|
},
|
53
52
|
fixable: "code",
|
@@ -106,7 +105,7 @@ var noIllegalModuleIds = {
|
|
106
105
|
if (rawArg) {
|
107
106
|
context.report({
|
108
107
|
node: firstArg,
|
109
|
-
message: "Val: val.content
|
108
|
+
message: "Val: val.content id should match the filename. Expected: '".concat(expectedValue, "'. Found: '").concat(firstArg.value, "'"),
|
110
109
|
fix: function fix(fixer) {
|
111
110
|
return fixer.replaceText(firstArg, "".concat(rawArg).concat(expectedValue).concat(rawArg));
|
112
111
|
}
|
@@ -123,49 +122,90 @@ var noIllegalModuleIds = {
|
|
123
122
|
// @ts-check
|
124
123
|
|
125
124
|
/**
|
126
|
-
* @type {
|
125
|
+
* @type {import('eslint').Rule.RuleModule}
|
127
126
|
*/
|
128
|
-
var
|
129
|
-
|
127
|
+
var noIllegalImports = {
|
128
|
+
meta: {
|
129
|
+
type: "problem",
|
130
|
+
docs: {
|
131
|
+
description: "Check that val files only has valid imports.",
|
132
|
+
recommended: true
|
133
|
+
},
|
134
|
+
schema: []
|
135
|
+
},
|
136
|
+
create: function create(context) {
|
137
|
+
return {
|
138
|
+
ImportDeclaration: function ImportDeclaration(node) {
|
139
|
+
var importSource = node.source.value;
|
140
|
+
var filename = context.filename || context.getFilename();
|
141
|
+
var isValFile = filename.endsWith(".val.ts") || filename.endsWith(".val.js");
|
142
|
+
// only allow: .val files, @valbuild packages, and val config
|
143
|
+
if (isValFile && typeof importSource === "string" && !importSource.match(/\.val(\.ts|\.js|)$/) && !importSource.match(/^@valbuild/) && !importSource.match(/val\.config(\.ts|\.js|)$/)) {
|
144
|
+
if ("importKind" in node && node["importKind"] !== "type" && !node.specifiers.every(function (s) {
|
145
|
+
return "importKind" in s && s["importKind"] === "type";
|
146
|
+
})) {
|
147
|
+
var message = "Val: can only 'import type' or import from source that is either: a .val.{j,t}s file, a @valbuild package, or val.config.{j,t}s.";
|
148
|
+
context.report({
|
149
|
+
node: node.source,
|
150
|
+
message: message
|
151
|
+
});
|
152
|
+
}
|
153
|
+
}
|
154
|
+
}
|
155
|
+
};
|
156
|
+
}
|
130
157
|
};
|
131
158
|
|
159
|
+
// @ts-check
|
160
|
+
|
132
161
|
/**
|
133
|
-
* @type {
|
162
|
+
* @type {import('eslint').Rule.RuleModule}
|
134
163
|
*/
|
135
|
-
var
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
text: text,
|
145
|
-
filename: filename
|
146
|
-
});
|
147
|
-
return [{
|
148
|
-
text: text,
|
149
|
-
filename: filename
|
150
|
-
}];
|
164
|
+
var exportContentMustBeValid = {
|
165
|
+
meta: {
|
166
|
+
type: "problem",
|
167
|
+
docs: {
|
168
|
+
description: "Export val.content should only happen in .val files.",
|
169
|
+
recommended: true
|
170
|
+
},
|
171
|
+
messages: {
|
172
|
+
"val/export-content-must-be-valid": "Val: val.content should only be exported from .val files"
|
151
173
|
},
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
174
|
+
schema: []
|
175
|
+
},
|
176
|
+
create: function create(context) {
|
177
|
+
return {
|
178
|
+
ExportDefaultDeclaration: function ExportDefaultDeclaration(node) {
|
179
|
+
if (node.declaration && node.declaration.type === "CallExpression" && node.declaration.callee.type === "MemberExpression" && node.declaration.callee.object.type === "Identifier" && node.declaration.callee.object.name === "val" && node.declaration.callee.property.type === "Identifier" && node.declaration.callee.property.name === "content") {
|
180
|
+
var filename = context.filename || context.getFilename();
|
181
|
+
if (!(filename !== null && filename !== void 0 && filename.endsWith(".val.ts") || filename !== null && filename !== void 0 && filename.endsWith(".val.js"))) {
|
182
|
+
context.report({
|
183
|
+
node: node.declaration.callee,
|
184
|
+
messageId: "val/export-content-must-be-valid"
|
185
|
+
});
|
186
|
+
}
|
187
|
+
}
|
188
|
+
}
|
189
|
+
};
|
166
190
|
}
|
167
191
|
};
|
168
192
|
|
193
|
+
// @ts-check
|
194
|
+
|
195
|
+
/**
|
196
|
+
* @type {Plugin["rules"]}
|
197
|
+
*/
|
198
|
+
var rules = {
|
199
|
+
"no-illegal-module-ids": noIllegalModuleIds,
|
200
|
+
"no-illegal-imports": noIllegalImports,
|
201
|
+
"export-content-must-be-valid": exportContentMustBeValid
|
202
|
+
};
|
203
|
+
|
204
|
+
/**
|
205
|
+
* @type {Plugin["processors"]}
|
206
|
+
*/
|
207
|
+
var processors = {};
|
208
|
+
|
169
209
|
/**
|
170
210
|
* @type {Plugin}
|
171
211
|
*/
|
@@ -38,8 +38,7 @@ var noIllegalModuleIds = {
|
|
38
38
|
meta: {
|
39
39
|
type: "problem",
|
40
40
|
docs: {
|
41
|
-
description: "Check that the first argument of export default declaration matches the string from val.config.
|
42
|
-
category: "Best Practices",
|
41
|
+
description: "Check that the first argument of export default declaration matches the string from val.config.{j,t}s file.",
|
43
42
|
recommended: true
|
44
43
|
},
|
45
44
|
fixable: "code",
|
@@ -98,7 +97,7 @@ var noIllegalModuleIds = {
|
|
98
97
|
if (rawArg) {
|
99
98
|
context.report({
|
100
99
|
node: firstArg,
|
101
|
-
message: "Val: val.content
|
100
|
+
message: "Val: val.content id should match the filename. Expected: '".concat(expectedValue, "'. Found: '").concat(firstArg.value, "'"),
|
102
101
|
fix: function fix(fixer) {
|
103
102
|
return fixer.replaceText(firstArg, "".concat(rawArg).concat(expectedValue).concat(rawArg));
|
104
103
|
}
|
@@ -115,49 +114,90 @@ var noIllegalModuleIds = {
|
|
115
114
|
// @ts-check
|
116
115
|
|
117
116
|
/**
|
118
|
-
* @type {
|
117
|
+
* @type {import('eslint').Rule.RuleModule}
|
119
118
|
*/
|
120
|
-
var
|
121
|
-
|
119
|
+
var noIllegalImports = {
|
120
|
+
meta: {
|
121
|
+
type: "problem",
|
122
|
+
docs: {
|
123
|
+
description: "Check that val files only has valid imports.",
|
124
|
+
recommended: true
|
125
|
+
},
|
126
|
+
schema: []
|
127
|
+
},
|
128
|
+
create: function create(context) {
|
129
|
+
return {
|
130
|
+
ImportDeclaration: function ImportDeclaration(node) {
|
131
|
+
var importSource = node.source.value;
|
132
|
+
var filename = context.filename || context.getFilename();
|
133
|
+
var isValFile = filename.endsWith(".val.ts") || filename.endsWith(".val.js");
|
134
|
+
// only allow: .val files, @valbuild packages, and val config
|
135
|
+
if (isValFile && typeof importSource === "string" && !importSource.match(/\.val(\.ts|\.js|)$/) && !importSource.match(/^@valbuild/) && !importSource.match(/val\.config(\.ts|\.js|)$/)) {
|
136
|
+
if ("importKind" in node && node["importKind"] !== "type" && !node.specifiers.every(function (s) {
|
137
|
+
return "importKind" in s && s["importKind"] === "type";
|
138
|
+
})) {
|
139
|
+
var message = "Val: can only 'import type' or import from source that is either: a .val.{j,t}s file, a @valbuild package, or val.config.{j,t}s.";
|
140
|
+
context.report({
|
141
|
+
node: node.source,
|
142
|
+
message: message
|
143
|
+
});
|
144
|
+
}
|
145
|
+
}
|
146
|
+
}
|
147
|
+
};
|
148
|
+
}
|
122
149
|
};
|
123
150
|
|
151
|
+
// @ts-check
|
152
|
+
|
124
153
|
/**
|
125
|
-
* @type {
|
154
|
+
* @type {import('eslint').Rule.RuleModule}
|
126
155
|
*/
|
127
|
-
var
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
text: text,
|
137
|
-
filename: filename
|
138
|
-
});
|
139
|
-
return [{
|
140
|
-
text: text,
|
141
|
-
filename: filename
|
142
|
-
}];
|
156
|
+
var exportContentMustBeValid = {
|
157
|
+
meta: {
|
158
|
+
type: "problem",
|
159
|
+
docs: {
|
160
|
+
description: "Export val.content should only happen in .val files.",
|
161
|
+
recommended: true
|
162
|
+
},
|
163
|
+
messages: {
|
164
|
+
"val/export-content-must-be-valid": "Val: val.content should only be exported from .val files"
|
143
165
|
},
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
166
|
+
schema: []
|
167
|
+
},
|
168
|
+
create: function create(context) {
|
169
|
+
return {
|
170
|
+
ExportDefaultDeclaration: function ExportDefaultDeclaration(node) {
|
171
|
+
if (node.declaration && node.declaration.type === "CallExpression" && node.declaration.callee.type === "MemberExpression" && node.declaration.callee.object.type === "Identifier" && node.declaration.callee.object.name === "val" && node.declaration.callee.property.type === "Identifier" && node.declaration.callee.property.name === "content") {
|
172
|
+
var filename = context.filename || context.getFilename();
|
173
|
+
if (!(filename !== null && filename !== void 0 && filename.endsWith(".val.ts") || filename !== null && filename !== void 0 && filename.endsWith(".val.js"))) {
|
174
|
+
context.report({
|
175
|
+
node: node.declaration.callee,
|
176
|
+
messageId: "val/export-content-must-be-valid"
|
177
|
+
});
|
178
|
+
}
|
179
|
+
}
|
180
|
+
}
|
181
|
+
};
|
158
182
|
}
|
159
183
|
};
|
160
184
|
|
185
|
+
// @ts-check
|
186
|
+
|
187
|
+
/**
|
188
|
+
* @type {Plugin["rules"]}
|
189
|
+
*/
|
190
|
+
var rules = {
|
191
|
+
"no-illegal-module-ids": noIllegalModuleIds,
|
192
|
+
"no-illegal-imports": noIllegalImports,
|
193
|
+
"export-content-must-be-valid": exportContentMustBeValid
|
194
|
+
};
|
195
|
+
|
196
|
+
/**
|
197
|
+
* @type {Plugin["processors"]}
|
198
|
+
*/
|
199
|
+
var processors = {};
|
200
|
+
|
161
201
|
/**
|
162
202
|
* @type {Plugin}
|
163
203
|
*/
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@valbuild/eslint-plugin",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.47.1",
|
4
4
|
"description": "ESLint rules for val",
|
5
5
|
"keywords": [
|
6
6
|
"eslint",
|
@@ -27,7 +27,8 @@
|
|
27
27
|
},
|
28
28
|
"devDependencies": {
|
29
29
|
"@types/jest": "^29.5.11",
|
30
|
-
"eslint": "^
|
30
|
+
"@typescript-eslint/rule-tester": "^6.15.0",
|
31
|
+
"eslint": "^8.56.0",
|
31
32
|
"jest": "^29.6"
|
32
33
|
},
|
33
34
|
"scripts": {
|
package/src/index.js
CHANGED
@@ -7,41 +7,22 @@
|
|
7
7
|
*/
|
8
8
|
|
9
9
|
import noIllegalModuleIds from "./rules/noIllegalModuleIds";
|
10
|
+
import noIllegalImports from "./rules/noIllegalImports";
|
11
|
+
import exportContentMustBeValid from "./rules/exportContentMustBeValid";
|
10
12
|
|
11
13
|
/**
|
12
14
|
* @type {Plugin["rules"]}
|
13
15
|
*/
|
14
16
|
export let rules = {
|
15
17
|
"no-illegal-module-ids": noIllegalModuleIds,
|
18
|
+
"no-illegal-imports": noIllegalImports,
|
19
|
+
"export-content-must-be-valid": exportContentMustBeValid,
|
16
20
|
};
|
17
21
|
|
18
22
|
/**
|
19
23
|
* @type {Plugin["processors"]}
|
20
24
|
*/
|
21
|
-
export const processors = {
|
22
|
-
val: {
|
23
|
-
/**
|
24
|
-
* @param {string} text
|
25
|
-
* @param {string} filename
|
26
|
-
* @returns {{ filename: string, text: string }[]}
|
27
|
-
*/
|
28
|
-
preprocess: (text, filename) => {
|
29
|
-
console.log("preprocess", { text, filename });
|
30
|
-
return [{ text, filename }];
|
31
|
-
},
|
32
|
-
/**
|
33
|
-
* Transforms generated messages for output.
|
34
|
-
* @param {LintMessage[][]} messages An array containing one array of messages
|
35
|
-
* for each code block returned from `preprocess`.
|
36
|
-
* @param {string} filename The filename of the file
|
37
|
-
* @returns {LintMessage[]} A flattened array of messages with mapped locations.
|
38
|
-
*/
|
39
|
-
postprocess: (messages, filename) => {
|
40
|
-
console.log({ messages, filename });
|
41
|
-
return messages.flat();
|
42
|
-
},
|
43
|
-
},
|
44
|
-
};
|
25
|
+
export const processors = {};
|
45
26
|
|
46
27
|
/**
|
47
28
|
* @type {Plugin}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
// @ts-check
|
2
|
+
|
3
|
+
/**
|
4
|
+
* @type {import('eslint').Rule.RuleModule}
|
5
|
+
*/
|
6
|
+
export default {
|
7
|
+
meta: {
|
8
|
+
type: "problem",
|
9
|
+
docs: {
|
10
|
+
description: "Export val.content should only happen in .val files.",
|
11
|
+
recommended: true,
|
12
|
+
},
|
13
|
+
messages: {
|
14
|
+
"val/export-content-must-be-valid":
|
15
|
+
"Val: val.content should only be exported from .val files",
|
16
|
+
},
|
17
|
+
schema: [],
|
18
|
+
},
|
19
|
+
create: function (context) {
|
20
|
+
return {
|
21
|
+
ExportDefaultDeclaration(node) {
|
22
|
+
if (
|
23
|
+
node.declaration &&
|
24
|
+
node.declaration.type === "CallExpression" &&
|
25
|
+
node.declaration.callee.type === "MemberExpression" &&
|
26
|
+
node.declaration.callee.object.type === "Identifier" &&
|
27
|
+
node.declaration.callee.object.name === "val" &&
|
28
|
+
node.declaration.callee.property.type === "Identifier" &&
|
29
|
+
node.declaration.callee.property.name === "content"
|
30
|
+
) {
|
31
|
+
const filename = context.filename || context.getFilename();
|
32
|
+
if (
|
33
|
+
!(filename?.endsWith(".val.ts") || filename?.endsWith(".val.js"))
|
34
|
+
) {
|
35
|
+
context.report({
|
36
|
+
node: node.declaration.callee,
|
37
|
+
messageId: "val/export-content-must-be-valid",
|
38
|
+
});
|
39
|
+
}
|
40
|
+
}
|
41
|
+
},
|
42
|
+
};
|
43
|
+
},
|
44
|
+
};
|
@@ -0,0 +1,48 @@
|
|
1
|
+
// @ts-check
|
2
|
+
|
3
|
+
/**
|
4
|
+
* @type {import('eslint').Rule.RuleModule}
|
5
|
+
*/
|
6
|
+
export default {
|
7
|
+
meta: {
|
8
|
+
type: "problem",
|
9
|
+
docs: {
|
10
|
+
description: "Check that val files only has valid imports.",
|
11
|
+
recommended: true,
|
12
|
+
},
|
13
|
+
schema: [],
|
14
|
+
},
|
15
|
+
create: function (context) {
|
16
|
+
return {
|
17
|
+
ImportDeclaration(node) {
|
18
|
+
const importSource = node.source.value;
|
19
|
+
const filename = context.filename || context.getFilename();
|
20
|
+
|
21
|
+
const isValFile =
|
22
|
+
filename.endsWith(".val.ts") || filename.endsWith(".val.js");
|
23
|
+
// only allow: .val files, @valbuild packages, and val config
|
24
|
+
if (
|
25
|
+
isValFile &&
|
26
|
+
typeof importSource === "string" &&
|
27
|
+
!importSource.match(/\.val(\.ts|\.js|)$/) &&
|
28
|
+
!importSource.match(/^@valbuild/) &&
|
29
|
+
!importSource.match(/val\.config(\.ts|\.js|)$/)
|
30
|
+
) {
|
31
|
+
if (
|
32
|
+
"importKind" in node &&
|
33
|
+
node["importKind"] !== "type" &&
|
34
|
+
!node.specifiers.every(
|
35
|
+
(s) => "importKind" in s && s["importKind"] === "type"
|
36
|
+
)
|
37
|
+
) {
|
38
|
+
const message = `Val: can only 'import type' or import from source that is either: a .val.{j,t}s file, a @valbuild package, or val.config.{j,t}s.`;
|
39
|
+
context.report({
|
40
|
+
node: node.source,
|
41
|
+
message,
|
42
|
+
});
|
43
|
+
}
|
44
|
+
}
|
45
|
+
},
|
46
|
+
};
|
47
|
+
},
|
48
|
+
};
|
@@ -9,8 +9,7 @@ export default {
|
|
9
9
|
type: "problem",
|
10
10
|
docs: {
|
11
11
|
description:
|
12
|
-
"Check that the first argument of export default declaration matches the string from val.config.
|
13
|
-
category: "Best Practices",
|
12
|
+
"Check that the first argument of export default declaration matches the string from val.config.{j,t}s file.",
|
14
13
|
recommended: true,
|
15
14
|
},
|
16
15
|
fixable: "code",
|
@@ -92,7 +91,7 @@ export default {
|
|
92
91
|
if (rawArg) {
|
93
92
|
context.report({
|
94
93
|
node: firstArg,
|
95
|
-
message: `Val: val.content
|
94
|
+
message: `Val: val.content id should match the filename. Expected: '${expectedValue}'. Found: '${firstArg.value}'`,
|
96
95
|
fix: (fixer) =>
|
97
96
|
fixer.replaceText(
|
98
97
|
firstArg,
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import { RuleTester } from "@typescript-eslint/rule-tester";
|
2
|
+
import { rules as valRules } from "@valbuild/eslint-plugin";
|
3
|
+
import path from "path";
|
4
|
+
|
5
|
+
const rule = valRules["export-content-must-be-valid"];
|
6
|
+
|
7
|
+
RuleTester.setDefaultConfig({
|
8
|
+
parserOptions: {
|
9
|
+
ecmaVersion: 2018,
|
10
|
+
sourceType: "module",
|
11
|
+
ecmaFeatures: {},
|
12
|
+
},
|
13
|
+
});
|
14
|
+
|
15
|
+
const ruleTester = new RuleTester();
|
16
|
+
|
17
|
+
ruleTester.run("export-content-must-be-valid", rule, {
|
18
|
+
valid: [
|
19
|
+
{
|
20
|
+
filename: path.join(process.cwd(), "./foo/test.val.ts"),
|
21
|
+
code: `
|
22
|
+
import { val, s } from '../val.config';
|
23
|
+
|
24
|
+
export const schema = s.string();
|
25
|
+
export default val.content('/foo/test', schema, '')`,
|
26
|
+
},
|
27
|
+
],
|
28
|
+
invalid: [
|
29
|
+
{
|
30
|
+
filename: path.join(process.cwd(), "./foo/test.ts"),
|
31
|
+
code: `
|
32
|
+
import { val, s } from '../val.config';
|
33
|
+
|
34
|
+
export const schema = s.string();
|
35
|
+
export default val.content('/foo/test', schema, '')`,
|
36
|
+
errors: [
|
37
|
+
{
|
38
|
+
message: "Val: val.content should only be exported from .val files",
|
39
|
+
},
|
40
|
+
],
|
41
|
+
},
|
42
|
+
{
|
43
|
+
filename: path.join(process.cwd(), "./foo/test.js"),
|
44
|
+
code: `
|
45
|
+
import { val, s } from '../val.config';
|
46
|
+
|
47
|
+
export const schema = s.string();
|
48
|
+
export default val.content('/foo/test', schema, '')`,
|
49
|
+
errors: [
|
50
|
+
{
|
51
|
+
message: "Val: val.content should only be exported from .val files",
|
52
|
+
},
|
53
|
+
],
|
54
|
+
},
|
55
|
+
],
|
56
|
+
});
|
@@ -0,0 +1,100 @@
|
|
1
|
+
import { RuleTester } from "@typescript-eslint/rule-tester";
|
2
|
+
import { rules as valRules } from "@valbuild/eslint-plugin";
|
3
|
+
import path from "path";
|
4
|
+
|
5
|
+
const rule = valRules["no-illegal-imports"];
|
6
|
+
|
7
|
+
RuleTester.setDefaultConfig({
|
8
|
+
parserOptions: {
|
9
|
+
ecmaVersion: 2018,
|
10
|
+
sourceType: "module",
|
11
|
+
|
12
|
+
ecmaFeatures: {},
|
13
|
+
},
|
14
|
+
});
|
15
|
+
|
16
|
+
const ruleTester = new RuleTester();
|
17
|
+
|
18
|
+
ruleTester.run("no-illegal-imports", rule, {
|
19
|
+
valid: [
|
20
|
+
{
|
21
|
+
filename: path.join(process.cwd(), "./foo/test.val.ts"),
|
22
|
+
code: `
|
23
|
+
import { val, s } from '../val.config';
|
24
|
+
import { eventSchema } from './event.val';
|
25
|
+
|
26
|
+
export const schema = s.array(eventSchema);
|
27
|
+
export default val.content('/foo/test', schema, [])`,
|
28
|
+
},
|
29
|
+
{
|
30
|
+
filename: path.join(process.cwd(), "./foo/test.val.ts"),
|
31
|
+
code: `
|
32
|
+
import { val, s } from '../val.config.ts';
|
33
|
+
import { eventSchema } from './event.val.ts';
|
34
|
+
|
35
|
+
export const schema = s.array(eventSchema);
|
36
|
+
export default val.content('/foo/test', schema, [])`,
|
37
|
+
},
|
38
|
+
{
|
39
|
+
filename: path.join(process.cwd(), "./foo/test.val.ts"),
|
40
|
+
code: `
|
41
|
+
import { val, s } from '../val.config.ts';
|
42
|
+
import type { Event } from './eventSchema';
|
43
|
+
|
44
|
+
export const schema = s.array(s.string());
|
45
|
+
type Test = Event;
|
46
|
+
export default val.content('/foo/test', schema, [])`,
|
47
|
+
},
|
48
|
+
{
|
49
|
+
filename: path.join(process.cwd(), "./foo/test.val.ts"),
|
50
|
+
code: `
|
51
|
+
import { val, s } from '../val.config.ts';
|
52
|
+
import { type Event } from './eventSchema';
|
53
|
+
|
54
|
+
export const schema = s.array(s.string());
|
55
|
+
type Test = Event;
|
56
|
+
export default val.content('/foo/test', schema, [])`,
|
57
|
+
},
|
58
|
+
{
|
59
|
+
filename: path.join(process.cwd(), "./foo/test.val.ts"),
|
60
|
+
code: `
|
61
|
+
import { val, s } from '../val.config.ts';
|
62
|
+
|
63
|
+
export const schema = s.string();
|
64
|
+
export default val.content('/foo/test', schema, 'String')`,
|
65
|
+
},
|
66
|
+
],
|
67
|
+
invalid: [
|
68
|
+
{
|
69
|
+
filename: path.join(process.cwd(), "./foo/test.val.ts"),
|
70
|
+
code: `
|
71
|
+
import { val, s } from '../val.config';
|
72
|
+
import { eventSchema } from './event';
|
73
|
+
|
74
|
+
export const schema = s.array(eventSchema);
|
75
|
+
export default val.content('/foo/test', schema, [])`,
|
76
|
+
errors: [
|
77
|
+
{
|
78
|
+
message:
|
79
|
+
"Val: can only 'import type' or import from source that is either: a .val.{j,t}s file, a @valbuild package, or val.config.{j,t}s.",
|
80
|
+
},
|
81
|
+
],
|
82
|
+
},
|
83
|
+
{
|
84
|
+
filename: path.join(process.cwd(), "./foo/test.val.ts"),
|
85
|
+
code: `
|
86
|
+
import { val, s } from '../val.config';
|
87
|
+
import { eventSchema, type Unused } from './event';
|
88
|
+
|
89
|
+
export const schema = s.array(eventSchema);
|
90
|
+
type Event = Unused;
|
91
|
+
export default val.content('/foo/test', schema, [])`,
|
92
|
+
errors: [
|
93
|
+
{
|
94
|
+
message:
|
95
|
+
"Val: can only 'import type' or import from source that is either: a .val.{j,t}s file, a @valbuild package, or val.config.{j,t}s.",
|
96
|
+
},
|
97
|
+
],
|
98
|
+
},
|
99
|
+
],
|
100
|
+
});
|
@@ -34,7 +34,7 @@ ruleTester.run("no-illegal-module-ids", rule, {
|
|
34
34
|
errors: [
|
35
35
|
{
|
36
36
|
message:
|
37
|
-
"Val: val.content
|
37
|
+
"Val: val.content id should match the filename. Expected: '/foo/test'. Found: 'foo'",
|
38
38
|
},
|
39
39
|
],
|
40
40
|
output: `import { val, s } from '../val.config.ts';
|
@@ -49,7 +49,7 @@ ruleTester.run("no-illegal-module-ids", rule, {
|
|
49
49
|
errors: [
|
50
50
|
{
|
51
51
|
message:
|
52
|
-
"Val: val.content
|
52
|
+
"Val: val.content id should match the filename. Expected: '/foo/test'. Found: 'foo'",
|
53
53
|
},
|
54
54
|
],
|
55
55
|
output: `import { val, s } from "../val.config.ts";
|