@platformos/platformos-check-common 0.0.12 → 0.0.16
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/CHANGELOG.md +59 -0
- package/dist/checks/circular-render/index.d.ts +2 -0
- package/dist/checks/circular-render/index.js +164 -0
- package/dist/checks/circular-render/index.js.map +1 -0
- package/dist/checks/index.d.ts +1 -1
- package/dist/checks/index.js +6 -0
- package/dist/checks/index.js.map +1 -1
- package/dist/checks/metadata-params/extract-undefined-variables.d.ts +8 -0
- package/dist/checks/metadata-params/extract-undefined-variables.js +213 -0
- package/dist/checks/metadata-params/extract-undefined-variables.js.map +1 -0
- package/dist/checks/metadata-params/index.js +48 -33
- package/dist/checks/metadata-params/index.js.map +1 -1
- package/dist/checks/missing-page/index.d.ts +2 -0
- package/dist/checks/missing-page/index.js +73 -0
- package/dist/checks/missing-page/index.js.map +1 -0
- package/dist/checks/missing-partial/index.js +31 -31
- package/dist/checks/missing-partial/index.js.map +1 -1
- package/dist/checks/missing-render-partial-arguments/index.d.ts +2 -0
- package/dist/checks/missing-render-partial-arguments/index.js +37 -0
- package/dist/checks/missing-render-partial-arguments/index.js.map +1 -0
- package/dist/checks/nested-graphql-query/index.d.ts +2 -0
- package/dist/checks/nested-graphql-query/index.js +146 -0
- package/dist/checks/nested-graphql-query/index.js.map +1 -0
- package/dist/checks/translation-key-exists/index.js +16 -19
- package/dist/checks/translation-key-exists/index.js.map +1 -1
- package/dist/checks/translation-utils.d.ts +16 -0
- package/dist/checks/translation-utils.js +51 -0
- package/dist/checks/translation-utils.js.map +1 -0
- package/dist/checks/undefined-object/index.js +32 -0
- package/dist/checks/undefined-object/index.js.map +1 -1
- package/dist/checks/unknown-property/index.js +64 -2
- package/dist/checks/unknown-property/index.js.map +1 -1
- package/dist/checks/unused-translation-key/index.d.ts +4 -0
- package/dist/checks/unused-translation-key/index.js +85 -0
- package/dist/checks/unused-translation-key/index.js.map +1 -0
- package/dist/checks/valid-render-partial-argument-types/index.js +2 -1
- package/dist/checks/valid-render-partial-argument-types/index.js.map +1 -1
- package/dist/context-utils.d.ts +2 -1
- package/dist/context-utils.js +31 -1
- package/dist/context-utils.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/liquid-doc/arguments.js +4 -0
- package/dist/liquid-doc/arguments.js.map +1 -1
- package/dist/liquid-doc/utils.d.ts +10 -2
- package/dist/liquid-doc/utils.js +26 -1
- package/dist/liquid-doc/utils.js.map +1 -1
- package/dist/to-source-code.d.ts +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.js.map +1 -1
- package/dist/url-helpers.d.ts +55 -0
- package/dist/url-helpers.js +334 -0
- package/dist/url-helpers.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/levenshtein.d.ts +3 -0
- package/dist/utils/levenshtein.js +39 -0
- package/dist/utils/levenshtein.js.map +1 -0
- package/package.json +2 -2
- package/src/checks/graphql/index.spec.ts +2 -2
- package/src/checks/index.ts +6 -0
- package/src/checks/metadata-params/extract-undefined-variables.spec.ts +115 -0
- package/src/checks/metadata-params/extract-undefined-variables.ts +286 -0
- package/src/checks/metadata-params/index.spec.ts +180 -26
- package/src/checks/metadata-params/index.ts +51 -34
- package/src/checks/missing-page/index.spec.ts +755 -0
- package/src/checks/missing-page/index.ts +89 -0
- package/src/checks/missing-partial/index.spec.ts +361 -0
- package/src/checks/missing-partial/index.ts +39 -47
- package/src/checks/missing-render-partial-arguments/index.spec.ts +74 -0
- package/src/checks/missing-render-partial-arguments/index.ts +44 -0
- package/src/checks/nested-graphql-query/index.spec.ts +175 -0
- package/src/checks/nested-graphql-query/index.ts +203 -0
- package/src/checks/parser-blocking-script/index.spec.ts +7 -3
- package/src/checks/translation-key-exists/index.spec.ts +79 -2
- package/src/checks/translation-key-exists/index.ts +18 -27
- package/src/checks/translation-utils.ts +63 -0
- package/src/checks/undefined-object/index.spec.ts +194 -35
- package/src/checks/undefined-object/index.ts +40 -1
- package/src/checks/unknown-property/index.spec.ts +62 -0
- package/src/checks/unknown-property/index.ts +73 -2
- package/src/checks/unused-assign/index.spec.ts +1 -1
- package/src/checks/unused-doc-param/index.spec.ts +4 -2
- package/src/checks/valid-doc-param-types/index.spec.ts +1 -1
- package/src/checks/valid-render-partial-argument-types/index.spec.ts +24 -1
- package/src/checks/valid-render-partial-argument-types/index.ts +3 -2
- package/src/checks/variable-name/index.spec.ts +1 -1
- package/src/context-utils.ts +33 -1
- package/src/disabled-checks/index.spec.ts +4 -4
- package/src/index.ts +3 -0
- package/src/liquid-doc/arguments.ts +6 -0
- package/src/liquid-doc/utils.ts +26 -2
- package/src/types.ts +9 -1
- package/src/url-helpers.spec.ts +386 -0
- package/src/url-helpers.ts +363 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/levenshtein.ts +41 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/checks/metadata-params/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/checks/metadata-params/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MissingPage = void 0;
|
|
4
|
+
const url_helpers_1 = require("../../url-helpers");
|
|
5
|
+
const types_1 = require("../../types");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
exports.MissingPage = {
|
|
8
|
+
meta: {
|
|
9
|
+
code: 'MissingPage',
|
|
10
|
+
name: 'Missing page for route',
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Reports links and form actions that point to routes with no corresponding platformOS page.',
|
|
13
|
+
recommended: true,
|
|
14
|
+
url: 'https://documentation.platformos.com/developer-guide/platformos-check/checks/missing-page',
|
|
15
|
+
},
|
|
16
|
+
type: types_1.SourceCodeType.LiquidHtml,
|
|
17
|
+
severity: types_1.Severity.WARNING,
|
|
18
|
+
schema: {},
|
|
19
|
+
targets: [],
|
|
20
|
+
},
|
|
21
|
+
create(context) {
|
|
22
|
+
let routeTable;
|
|
23
|
+
// Tracks {% assign %} variable mappings incrementally in document order.
|
|
24
|
+
// This means each <a> / <form> sees only the assigns that precede it,
|
|
25
|
+
// and reassignments correctly shadow earlier values at their position.
|
|
26
|
+
const variableMap = new Map();
|
|
27
|
+
function checkUrlAttribute(attr, method) {
|
|
28
|
+
const urlPattern = (0, url_helpers_1.extractUrlPattern)(attr, variableMap);
|
|
29
|
+
if (urlPattern === null)
|
|
30
|
+
return;
|
|
31
|
+
if ((0, url_helpers_1.shouldSkipUrl)(urlPattern))
|
|
32
|
+
return;
|
|
33
|
+
if (!routeTable.hasMatch(urlPattern, method)) {
|
|
34
|
+
const methodLabel = method.toUpperCase();
|
|
35
|
+
context.report({
|
|
36
|
+
message: `No page found for route '${urlPattern}' (${methodLabel})`,
|
|
37
|
+
startIndex: attr.value[0].position.start,
|
|
38
|
+
endIndex: attr.value[attr.value.length - 1].position.end,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
async onCodePathStart() {
|
|
44
|
+
// Front-load the route table build so individual HtmlElement visits don't wait.
|
|
45
|
+
routeTable = await context.getRouteTable();
|
|
46
|
+
},
|
|
47
|
+
async LiquidTag(node) {
|
|
48
|
+
const extracted = (0, url_helpers_1.tryExtractAssignUrl)(node);
|
|
49
|
+
if (extracted) {
|
|
50
|
+
variableMap.set(extracted.name, extracted.urlPattern);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
async HtmlElement(node) {
|
|
54
|
+
if ((0, utils_1.isHtmlTag)(node, 'a')) {
|
|
55
|
+
const hrefAttr = node.attributes.find((a) => (0, url_helpers_1.isValuedAttrNode)(a) && (0, url_helpers_1.getAttrName)(a) === 'href');
|
|
56
|
+
if (hrefAttr && (0, url_helpers_1.isValuedAttrNode)(hrefAttr)) {
|
|
57
|
+
checkUrlAttribute(hrefAttr, 'get');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if ((0, utils_1.isHtmlTag)(node, 'form')) {
|
|
61
|
+
const actionAttr = node.attributes.find((a) => (0, url_helpers_1.isValuedAttrNode)(a) && (0, url_helpers_1.getAttrName)(a) === 'action');
|
|
62
|
+
if (actionAttr && (0, url_helpers_1.isValuedAttrNode)(actionAttr)) {
|
|
63
|
+
const method = (0, url_helpers_1.getEffectiveMethod)(node);
|
|
64
|
+
if (method !== null) {
|
|
65
|
+
checkUrlAttribute(actionAttr, method);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/checks/missing-page/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,13 @@ const liquid_html_parser_1 = require("@platformos/liquid-html-parser");
|
|
|
5
5
|
const types_1 = require("../../types");
|
|
6
6
|
const platformos_common_1 = require("@platformos/platformos-common");
|
|
7
7
|
const vscode_uri_1 = require("vscode-uri");
|
|
8
|
+
function getTagName(ancestors) {
|
|
9
|
+
const parent = ancestors.at(-1);
|
|
10
|
+
if (parent?.type === liquid_html_parser_1.NodeTypes.LiquidTag && parent.name === liquid_html_parser_1.NamedTags.theme_render_rc) {
|
|
11
|
+
return 'theme_render_rc';
|
|
12
|
+
}
|
|
13
|
+
return 'render';
|
|
14
|
+
}
|
|
8
15
|
const schema = {
|
|
9
16
|
ignoreMissing: types_1.SchemaProp.array(types_1.SchemaProp.string(), []),
|
|
10
17
|
};
|
|
@@ -24,44 +31,37 @@ exports.MissingPartial = {
|
|
|
24
31
|
},
|
|
25
32
|
create(context) {
|
|
26
33
|
const locator = new platformos_common_1.DocumentsLocator(context.fs);
|
|
34
|
+
const rootUri = vscode_uri_1.URI.parse(context.config.rootUri);
|
|
35
|
+
let searchPathsPromise;
|
|
36
|
+
function getSearchPaths() {
|
|
37
|
+
searchPathsPromise ??= (0, platformos_common_1.loadSearchPaths)(context.fs, rootUri);
|
|
38
|
+
return searchPathsPromise;
|
|
39
|
+
}
|
|
40
|
+
async function reportIfMissing(docType, name, position) {
|
|
41
|
+
const searchPaths = docType === 'theme_render_rc' ? await getSearchPaths() : null;
|
|
42
|
+
const location = await locator.locate(rootUri, docType, name, searchPaths);
|
|
43
|
+
if (!location) {
|
|
44
|
+
context.report({
|
|
45
|
+
message: `'${name}' does not exist`,
|
|
46
|
+
startIndex: position.start,
|
|
47
|
+
endIndex: position.end,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
27
51
|
return {
|
|
28
|
-
async RenderMarkup(node) {
|
|
29
|
-
if (node.partial.type
|
|
30
|
-
|
|
31
|
-
const partial = node.partial;
|
|
32
|
-
const location = await locator.locate(vscode_uri_1.URI.parse(context.config.rootUri), 'render', partial.value);
|
|
33
|
-
if (!location) {
|
|
34
|
-
context.report({
|
|
35
|
-
message: `'${partial.value}' does not exist`,
|
|
36
|
-
startIndex: node.partial.position.start,
|
|
37
|
-
endIndex: node.partial.position.end,
|
|
38
|
-
});
|
|
52
|
+
async RenderMarkup(node, ancestors) {
|
|
53
|
+
if (node.partial.type !== liquid_html_parser_1.NodeTypes.VariableLookup) {
|
|
54
|
+
await reportIfMissing(getTagName(ancestors), node.partial.value, node.partial.position);
|
|
39
55
|
}
|
|
40
56
|
},
|
|
41
57
|
async FunctionMarkup(node) {
|
|
42
|
-
if (node.partial.type
|
|
43
|
-
|
|
44
|
-
const partial = node.partial;
|
|
45
|
-
const location = await locator.locate(vscode_uri_1.URI.parse(context.config.rootUri), 'function', partial.value);
|
|
46
|
-
if (!location) {
|
|
47
|
-
context.report({
|
|
48
|
-
message: `'${partial.value}' does not exist`,
|
|
49
|
-
startIndex: node.partial.position.start,
|
|
50
|
-
endIndex: node.partial.position.end,
|
|
51
|
-
});
|
|
58
|
+
if (node.partial.type !== liquid_html_parser_1.NodeTypes.VariableLookup) {
|
|
59
|
+
await reportIfMissing('function', node.partial.value, node.partial.position);
|
|
52
60
|
}
|
|
53
61
|
},
|
|
54
62
|
async GraphQLMarkup(node) {
|
|
55
|
-
if (node.graphql.type
|
|
56
|
-
|
|
57
|
-
const graphql = node.graphql;
|
|
58
|
-
const location = await locator.locate(vscode_uri_1.URI.parse(context.config.rootUri), 'graphql', graphql.value);
|
|
59
|
-
if (!location) {
|
|
60
|
-
context.report({
|
|
61
|
-
message: `'${graphql.value}' does not exist`,
|
|
62
|
-
startIndex: node.graphql.position.start,
|
|
63
|
-
endIndex: node.graphql.position.end,
|
|
64
|
-
});
|
|
63
|
+
if (node.graphql.type !== liquid_html_parser_1.NodeTypes.VariableLookup) {
|
|
64
|
+
await reportIfMissing('graphql', node.graphql.value, node.graphql.position);
|
|
65
65
|
}
|
|
66
66
|
},
|
|
67
67
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/checks/missing-partial/index.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/checks/missing-partial/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MissingRenderPartialArguments = void 0;
|
|
4
|
+
const types_1 = require("../../types");
|
|
5
|
+
const arguments_1 = require("../../liquid-doc/arguments");
|
|
6
|
+
exports.MissingRenderPartialArguments = {
|
|
7
|
+
meta: {
|
|
8
|
+
code: 'MissingRenderPartialArguments',
|
|
9
|
+
name: 'Missing Required Render Partial Arguments',
|
|
10
|
+
aliases: ['MissingRenderPartialParams'],
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'This check ensures that all required @param arguments declared by a partial are provided at the call site.',
|
|
13
|
+
recommended: true,
|
|
14
|
+
url: 'https://documentation.platformos.com/developer-guide/platformos-check/checks/missing-render-partial-arguments',
|
|
15
|
+
},
|
|
16
|
+
type: types_1.SourceCodeType.LiquidHtml,
|
|
17
|
+
severity: types_1.Severity.ERROR,
|
|
18
|
+
schema: {},
|
|
19
|
+
targets: [],
|
|
20
|
+
},
|
|
21
|
+
create(context) {
|
|
22
|
+
return {
|
|
23
|
+
async RenderMarkup(node) {
|
|
24
|
+
const partialName = (0, arguments_1.getPartialName)(node);
|
|
25
|
+
if (!partialName)
|
|
26
|
+
return;
|
|
27
|
+
const liquidDocParameters = await (0, arguments_1.getLiquidDocParams)(context, partialName);
|
|
28
|
+
if (!liquidDocParameters)
|
|
29
|
+
return;
|
|
30
|
+
const providedNames = new Set(node.args.map((a) => a.name));
|
|
31
|
+
const missingRequired = [...liquidDocParameters.values()].filter((p) => p.required && !providedNames.has(p.name));
|
|
32
|
+
(0, arguments_1.reportMissingArguments)(context, node, missingRequired, partialName);
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/checks/missing-render-partial-arguments/index.ts"],"names":[],"mappings":";;;AACA,uCAA8E;AAC9E,0DAIoC;AAEvB,QAAA,6BAA6B,GAA0B;IAClE,IAAI,EAAE;QACJ,IAAI,EAAE,+BAA+B;QACrC,IAAI,EAAE,2CAA2C;QACjD,OAAO,EAAE,CAAC,4BAA4B,CAAC;QACvC,IAAI,EAAE;YACJ,WAAW,EACT,4GAA4G;YAC9G,WAAW,EAAE,IAAI;YACjB,GAAG,EAAE,+GAA+G;SACrH;QACD,IAAI,EAAE,sBAAc,CAAC,UAAU;QAC/B,QAAQ,EAAE,gBAAQ,CAAC,KAAK;QACxB,MAAM,EAAE,EAAE;QACV,OAAO,EAAE,EAAE;KACZ;IAED,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,KAAK,CAAC,YAAY,CAAC,IAAkB;gBACnC,MAAM,WAAW,GAAG,IAAA,0BAAc,EAAC,IAAI,CAAC,CAAC;gBACzC,IAAI,CAAC,WAAW;oBAAE,OAAO;gBAEzB,MAAM,mBAAmB,GAAG,MAAM,IAAA,8BAAkB,EAAC,OAAO,EAAE,WAAW,CAAC,CAAC;gBAC3E,IAAI,CAAC,mBAAmB;oBAAE,OAAO;gBAEjC,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC5D,MAAM,eAAe,GAAG,CAAC,GAAG,mBAAmB,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAC9D,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAChD,CAAC;gBAEF,IAAA,kCAAsB,EAAC,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;YACtE,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NestedGraphQLQuery = void 0;
|
|
4
|
+
const liquid_html_parser_1 = require("@platformos/liquid-html-parser");
|
|
5
|
+
const platformos_common_1 = require("@platformos/platformos-common");
|
|
6
|
+
const vscode_uri_1 = require("vscode-uri");
|
|
7
|
+
const types_1 = require("../../types");
|
|
8
|
+
const utils_1 = require("../utils");
|
|
9
|
+
const SKIP_IF_ANCESTOR_TAGS = [liquid_html_parser_1.NamedTags.cache];
|
|
10
|
+
function findNodesInAST(ast) {
|
|
11
|
+
const results = [];
|
|
12
|
+
const stack = [...ast];
|
|
13
|
+
while (stack.length > 0) {
|
|
14
|
+
const node = stack.pop();
|
|
15
|
+
if (node.type === liquid_html_parser_1.NodeTypes.LiquidTag) {
|
|
16
|
+
if (node.name === liquid_html_parser_1.NamedTags.graphql) {
|
|
17
|
+
results.push({ type: 'graphql', partialChain: [] });
|
|
18
|
+
}
|
|
19
|
+
else if ((node.name === liquid_html_parser_1.NamedTags.function || node.name === liquid_html_parser_1.NamedTags.render) &&
|
|
20
|
+
typeof node.markup !== 'string' &&
|
|
21
|
+
'partial' in node.markup &&
|
|
22
|
+
node.markup.partial.type !== liquid_html_parser_1.NodeTypes.VariableLookup) {
|
|
23
|
+
results.push({ type: node.name, partialName: node.markup.partial.value });
|
|
24
|
+
}
|
|
25
|
+
if ('children' in node && Array.isArray(node.children)) {
|
|
26
|
+
stack.push(...node.children);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else if ('children' in node && Array.isArray(node.children)) {
|
|
30
|
+
stack.push(...node.children);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return results;
|
|
34
|
+
}
|
|
35
|
+
async function containsGraphQLTransitively(locator, fs, rootUri, partialName, tagType, visited) {
|
|
36
|
+
if (visited.has(partialName))
|
|
37
|
+
return null;
|
|
38
|
+
visited.add(partialName);
|
|
39
|
+
const location = await locator.locate(rootUri, tagType, partialName);
|
|
40
|
+
if (!location)
|
|
41
|
+
return null;
|
|
42
|
+
let source;
|
|
43
|
+
try {
|
|
44
|
+
source = await fs.readFile(location);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
let ast;
|
|
50
|
+
try {
|
|
51
|
+
ast = (0, liquid_html_parser_1.toLiquidHtmlAST)(source);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const nodes = findNodesInAST(ast.children);
|
|
57
|
+
for (const found of nodes) {
|
|
58
|
+
if (found.type === 'graphql') {
|
|
59
|
+
return [partialName];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
for (const found of nodes) {
|
|
63
|
+
if (found.type === 'function' || found.type === 'render') {
|
|
64
|
+
const chain = await containsGraphQLTransitively(locator, fs, rootUri, found.partialName, found.type, visited);
|
|
65
|
+
if (chain) {
|
|
66
|
+
return [partialName, ...chain];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
exports.NestedGraphQLQuery = {
|
|
73
|
+
meta: {
|
|
74
|
+
code: 'NestedGraphQLQuery',
|
|
75
|
+
name: 'Prevent N+1 GraphQL queries in loops',
|
|
76
|
+
docs: {
|
|
77
|
+
description: 'This check detects {% graphql %} tags placed inside loop tags ({% for %}, {% tablerow %}), which causes one database request per loop iteration (N+1 pattern). It also follows {% function %} and {% render %} calls transitively to detect indirect GraphQL queries.',
|
|
78
|
+
recommended: true,
|
|
79
|
+
url: 'https://documentation.platformos.com/developer-guide/platformos-check/checks/nested-graphql-query',
|
|
80
|
+
},
|
|
81
|
+
type: types_1.SourceCodeType.LiquidHtml,
|
|
82
|
+
severity: types_1.Severity.WARNING,
|
|
83
|
+
schema: {},
|
|
84
|
+
targets: [],
|
|
85
|
+
},
|
|
86
|
+
create(context) {
|
|
87
|
+
const locator = new platformos_common_1.DocumentsLocator(context.fs);
|
|
88
|
+
const rootUri = vscode_uri_1.URI.parse(context.config.rootUri);
|
|
89
|
+
function isInsideLoopWithoutCacheOrBackground(ancestors) {
|
|
90
|
+
const ancestorTags = ancestors.filter((a) => a.type === liquid_html_parser_1.NodeTypes.LiquidTag);
|
|
91
|
+
const loopAncestor = ancestorTags.find(utils_1.isLoopLiquidTag);
|
|
92
|
+
if (!loopAncestor)
|
|
93
|
+
return null;
|
|
94
|
+
const inBackground = ancestorTags.some((a) => a.name === liquid_html_parser_1.NamedTags.background);
|
|
95
|
+
if (inBackground)
|
|
96
|
+
return null;
|
|
97
|
+
const shouldSkip = ancestorTags.some((a) => SKIP_IF_ANCESTOR_TAGS.map((a) => a.toString()).includes(a.name));
|
|
98
|
+
if (shouldSkip)
|
|
99
|
+
return null;
|
|
100
|
+
return loopAncestor;
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
async LiquidTag(node, ancestors) {
|
|
104
|
+
if (node.name === liquid_html_parser_1.NamedTags.graphql) {
|
|
105
|
+
const loopAncestor = isInsideLoopWithoutCacheOrBackground(ancestors);
|
|
106
|
+
if (!loopAncestor)
|
|
107
|
+
return;
|
|
108
|
+
let resultName = '';
|
|
109
|
+
if (typeof node.markup !== 'string' &&
|
|
110
|
+
(node.markup.type === liquid_html_parser_1.NodeTypes.GraphQLMarkup ||
|
|
111
|
+
node.markup.type === liquid_html_parser_1.NodeTypes.GraphQLInlineMarkup)) {
|
|
112
|
+
resultName = node.markup.name ? ` result = '${node.markup.name}'` : '';
|
|
113
|
+
}
|
|
114
|
+
const graphqlStr = resultName ? `{% graphql${resultName} %}` : '{% graphql %}';
|
|
115
|
+
context.report({
|
|
116
|
+
message: `N+1 pattern: ${graphqlStr} is inside a {% ${loopAncestor.name} %} loop. This executes at least one database request per iteration. Move the query before the loop and pass data as a variable.`,
|
|
117
|
+
startIndex: node.position.start,
|
|
118
|
+
endIndex: node.position.end,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
else if (node.name === liquid_html_parser_1.NamedTags.function || node.name === liquid_html_parser_1.NamedTags.render) {
|
|
122
|
+
const loopAncestor = isInsideLoopWithoutCacheOrBackground(ancestors);
|
|
123
|
+
if (!loopAncestor)
|
|
124
|
+
return;
|
|
125
|
+
if (typeof node.markup === 'string' ||
|
|
126
|
+
!('partial' in node.markup) ||
|
|
127
|
+
node.markup.partial.type === liquid_html_parser_1.NodeTypes.VariableLookup) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const partialName = node.markup.partial.value;
|
|
131
|
+
const visited = new Set();
|
|
132
|
+
const chain = await containsGraphQLTransitively(locator, context.fs, rootUri, partialName, node.name, visited);
|
|
133
|
+
if (chain) {
|
|
134
|
+
const chainStr = chain.join(' → ');
|
|
135
|
+
context.report({
|
|
136
|
+
message: `N+1 pattern: {% ${node.name} '${partialName}' %} inside a {% ${loopAncestor.name} %} loop transitively calls a GraphQL query (${chainStr}). Move the query before the loop and pass data as a variable.`,
|
|
137
|
+
startIndex: node.position.start,
|
|
138
|
+
endIndex: node.position.end,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/checks/nested-graphql-query/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TranslationKeyExists = void 0;
|
|
4
|
-
const platformos_common_1 = require("@platformos/platformos-common");
|
|
5
4
|
const types_1 = require("../../types");
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
for (const token of key.split('.')) {
|
|
9
|
-
if (typeof pointer !== 'object') {
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
if (!pointer.hasOwnProperty(token)) {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
pointer = pointer[token];
|
|
16
|
-
}
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
5
|
+
const levenshtein_1 = require("../../utils/levenshtein");
|
|
6
|
+
const translation_utils_1 = require("../translation-utils");
|
|
19
7
|
exports.TranslationKeyExists = {
|
|
20
8
|
meta: {
|
|
21
9
|
code: 'TranslationKeyExists',
|
|
@@ -32,7 +20,6 @@ exports.TranslationKeyExists = {
|
|
|
32
20
|
},
|
|
33
21
|
create(context) {
|
|
34
22
|
const nodes = [];
|
|
35
|
-
const translationProvider = new platformos_common_1.TranslationProvider(context.fs);
|
|
36
23
|
return {
|
|
37
24
|
async LiquidVariable(node) {
|
|
38
25
|
if (node.expression.type !== 'String') {
|
|
@@ -48,16 +35,26 @@ exports.TranslationKeyExists = {
|
|
|
48
35
|
});
|
|
49
36
|
},
|
|
50
37
|
async onCodePathEnd() {
|
|
38
|
+
if (nodes.length === 0)
|
|
39
|
+
return;
|
|
40
|
+
// Load all defined keys (app + modules) once per file
|
|
41
|
+
const allDefinedKeys = await (0, translation_utils_1.loadAllDefinedKeys)(context);
|
|
42
|
+
const definedKeySet = new Set(allDefinedKeys);
|
|
51
43
|
for (const { translationKey, startIndex, endIndex } of nodes) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
44
|
+
if (definedKeySet.has(translationKey))
|
|
45
|
+
continue;
|
|
46
|
+
const nearest = (0, levenshtein_1.findNearestKeys)(translationKey, allDefinedKeys);
|
|
56
47
|
const message = `'${translationKey}' does not have a matching translation entry`;
|
|
57
48
|
context.report({
|
|
58
49
|
message,
|
|
59
50
|
startIndex,
|
|
60
51
|
endIndex,
|
|
52
|
+
suggest: nearest.length > 0
|
|
53
|
+
? nearest.map((key) => ({
|
|
54
|
+
message: `Did you mean '${key}'?`,
|
|
55
|
+
fix: (fixer) => fixer.replace(startIndex, endIndex, `'${key}'`),
|
|
56
|
+
}))
|
|
57
|
+
: undefined,
|
|
61
58
|
});
|
|
62
59
|
}
|
|
63
60
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/checks/translation-key-exists/index.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/checks/translation-key-exists/index.ts"],"names":[],"mappings":";;;AAAA,uCAA8E;AAC9E,yDAA0D;AAC1D,4DAA0D;AAE7C,QAAA,oBAAoB,GAA0B;IACzD,IAAI,EAAE;QACJ,IAAI,EAAE,sBAAsB;QAC5B,IAAI,EAAE,kCAAkC;QACxC,IAAI,EAAE;YACJ,WAAW,EAAE,kCAAkC;YAC/C,WAAW,EAAE,IAAI;YACjB,GAAG,EAAE,qGAAqG;SAC3G;QACD,IAAI,EAAE,sBAAc,CAAC,UAAU;QAC/B,QAAQ,EAAE,gBAAQ,CAAC,KAAK;QACxB,MAAM,EAAE,EAAE;QACV,OAAO,EAAE,EAAE;KACZ;IAED,MAAM,CAAC,OAAO;QACZ,MAAM,KAAK,GAAuE,EAAE,CAAC;QAErF,OAAO;YACL,KAAK,CAAC,cAAc,CAAC,IAAI;gBACvB,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACtC,OAAO;gBACT,CAAC;gBAED,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;oBACxE,OAAO;gBACT,CAAC;gBAED,KAAK,CAAC,IAAI,CAAC;oBACT,cAAc,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK;oBACrC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK;oBAC1C,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG;iBACvC,CAAC,CAAC;YACL,CAAC;YAED,KAAK,CAAC,aAAa;gBACjB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO;gBAE/B,sDAAsD;gBACtD,MAAM,cAAc,GAAG,MAAM,IAAA,sCAAkB,EAAC,OAAO,CAAC,CAAC;gBACzD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC;gBAE9C,KAAK,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,KAAK,EAAE,CAAC;oBAC7D,IAAI,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC;wBAAE,SAAS;oBAEhD,MAAM,OAAO,GAAG,IAAA,6BAAe,EAAC,cAAc,EAAE,cAAc,CAAC,CAAC;oBAChE,MAAM,OAAO,GAAG,IAAI,cAAc,8CAA8C,CAAC;oBAEjF,OAAO,CAAC,MAAM,CAAC;wBACb,OAAO;wBACP,UAAU;wBACV,QAAQ;wBACR,OAAO,EACL,OAAO,CAAC,MAAM,GAAG,CAAC;4BAChB,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gCACpB,OAAO,EAAE,iBAAiB,GAAG,IAAI;gCACjC,GAAG,EAAE,CAAC,KAAU,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE,IAAI,GAAG,GAAG,CAAC;6BACrE,CAAC,CAAC;4BACL,CAAC,CAAC,SAAS;qBAChB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AbstractFileSystem } from '@platformos/platformos-common';
|
|
2
|
+
/**
|
|
3
|
+
* Discovers all module names by listing app/modules/ and modules/ directories.
|
|
4
|
+
* Returns a deduplicated set of module names.
|
|
5
|
+
*/
|
|
6
|
+
export declare function discoverModules(fs: AbstractFileSystem, ...moduleDirUris: string[]): Promise<Set<string>>;
|
|
7
|
+
export interface TranslationContext {
|
|
8
|
+
fs: AbstractFileSystem;
|
|
9
|
+
toUri(relativePath: string): string;
|
|
10
|
+
getTranslationsForBase(uri: string, locale: string): Promise<Record<string, any>>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Loads all defined translation keys (app-level + module-level) and returns
|
|
14
|
+
* them as a flat string array. Module keys are prefixed with `modules/{name}/`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadAllDefinedKeys(context: TranslationContext): Promise<string[]>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.discoverModules = discoverModules;
|
|
4
|
+
exports.loadAllDefinedKeys = loadAllDefinedKeys;
|
|
5
|
+
const platformos_common_1 = require("@platformos/platformos-common");
|
|
6
|
+
const levenshtein_1 = require("../utils/levenshtein");
|
|
7
|
+
/**
|
|
8
|
+
* Discovers all module names by listing app/modules/ and modules/ directories.
|
|
9
|
+
* Returns a deduplicated set of module names.
|
|
10
|
+
*/
|
|
11
|
+
async function discoverModules(fs, ...moduleDirUris) {
|
|
12
|
+
const modules = new Set();
|
|
13
|
+
for (const dirUri of moduleDirUris) {
|
|
14
|
+
try {
|
|
15
|
+
const entries = await fs.readDirectory(dirUri);
|
|
16
|
+
for (const [entryUri, entryType] of entries) {
|
|
17
|
+
if (entryType === platformos_common_1.FileType.Directory) {
|
|
18
|
+
modules.add(entryUri.split('/').pop());
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Directory doesn't exist or isn't accessible — skip
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return modules;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Loads all defined translation keys (app-level + module-level) and returns
|
|
30
|
+
* them as a flat string array. Module keys are prefixed with `modules/{name}/`.
|
|
31
|
+
*/
|
|
32
|
+
async function loadAllDefinedKeys(context) {
|
|
33
|
+
const definedKeys = [];
|
|
34
|
+
// App-level translations
|
|
35
|
+
for (const base of platformos_common_1.TranslationProvider.getSearchPaths()) {
|
|
36
|
+
const translations = await context.getTranslationsForBase(context.toUri(base), 'en');
|
|
37
|
+
definedKeys.push(...(0, levenshtein_1.flattenTranslationKeys)(translations));
|
|
38
|
+
}
|
|
39
|
+
// Module translations
|
|
40
|
+
const modules = await discoverModules(context.fs, context.toUri('app/modules'), context.toUri('modules'));
|
|
41
|
+
for (const moduleName of modules) {
|
|
42
|
+
for (const base of platformos_common_1.TranslationProvider.getSearchPaths(moduleName)) {
|
|
43
|
+
const translations = await context.getTranslationsForBase(context.toUri(base), 'en');
|
|
44
|
+
for (const key of (0, levenshtein_1.flattenTranslationKeys)(translations)) {
|
|
45
|
+
definedKeys.push(`modules/${moduleName}/${key}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return definedKeys;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=translation-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translation-utils.js","sourceRoot":"","sources":["../../src/checks/translation-utils.ts"],"names":[],"mappings":";;AAOA,0CAkBC;AAYD,gDAyBC;AA9DD,qEAAkG;AAClG,sDAA8D;AAE9D;;;GAGG;AACI,KAAK,UAAU,eAAe,CACnC,EAAsB,EACtB,GAAG,aAAuB;IAE1B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAC/C,KAAK,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,OAAO,EAAE,CAAC;gBAC5C,IAAI,SAAS,KAAK,4BAAQ,CAAC,SAAS,EAAE,CAAC;oBACrC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAC,CAAC;gBAC1C,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAQD;;;GAGG;AACI,KAAK,UAAU,kBAAkB,CAAC,OAA2B;IAClE,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,yBAAyB;IACzB,KAAK,MAAM,IAAI,IAAI,uCAAmB,CAAC,cAAc,EAAE,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;QACrF,WAAW,CAAC,IAAI,CAAC,GAAG,IAAA,oCAAsB,EAAC,YAAY,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,sBAAsB;IACtB,MAAM,OAAO,GAAG,MAAM,eAAe,CACnC,OAAO,CAAC,EAAE,EACV,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,EAC5B,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CACzB,CAAC;IACF,KAAK,MAAM,UAAU,IAAI,OAAO,EAAE,CAAC;QACjC,KAAK,MAAM,IAAI,IAAI,uCAAmB,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;YAClE,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;YACrF,KAAK,MAAM,GAAG,IAAI,IAAA,oCAAsB,EAAC,YAAY,CAAC,EAAE,CAAC;gBACvD,WAAW,CAAC,IAAI,CAAC,WAAW,UAAU,IAAI,GAAG,EAAE,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC"}
|