@platformos/platformos-check-node 0.0.2
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 +9 -0
- package/configs/all.yml +214 -0
- package/configs/nothing.yml +3 -0
- package/configs/recommended.yml +192 -0
- package/dist/NodeFileSystem.d.ts +2 -0
- package/dist/NodeFileSystem.js +37 -0
- package/dist/autofix.d.ts +6 -0
- package/dist/autofix.js +18 -0
- package/dist/backfill-docs/argument-collector.d.ts +6 -0
- package/dist/backfill-docs/argument-collector.js +167 -0
- package/dist/backfill-docs/doc-generator.d.ts +18 -0
- package/dist/backfill-docs/doc-generator.js +31 -0
- package/dist/backfill-docs/doc-updater.d.ts +13 -0
- package/dist/backfill-docs/doc-updater.js +154 -0
- package/dist/backfill-docs/index.d.ts +14 -0
- package/dist/backfill-docs/index.js +233 -0
- package/dist/backfill-docs/types.d.ts +32 -0
- package/dist/backfill-docs/types.js +3 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +47 -0
- package/dist/commands/generate-docs.d.ts +24 -0
- package/dist/commands/generate-docs.js +136 -0
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.js +7 -0
- package/dist/config/find-config-path.d.ts +1 -0
- package/dist/config/find-config-path.js +22 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.js +8 -0
- package/dist/config/installation-location.d.ts +1 -0
- package/dist/config/installation-location.js +20 -0
- package/dist/config/load-config-description.d.ts +10 -0
- package/dist/config/load-config-description.js +97 -0
- package/dist/config/load-config.d.ts +18 -0
- package/dist/config/load-config.js +30 -0
- package/dist/config/load-third-party-checks.d.ts +16 -0
- package/dist/config/load-third-party-checks.js +69 -0
- package/dist/config/resolve/index.d.ts +1 -0
- package/dist/config/resolve/index.js +6 -0
- package/dist/config/resolve/merge-fragments.d.ts +11 -0
- package/dist/config/resolve/merge-fragments.js +52 -0
- package/dist/config/resolve/read-yaml.d.ts +11 -0
- package/dist/config/resolve/read-yaml.js +205 -0
- package/dist/config/resolve/resolve-config.d.ts +8 -0
- package/dist/config/resolve/resolve-config.js +37 -0
- package/dist/config/types.d.ts +35 -0
- package/dist/config/types.js +19 -0
- package/dist/config/validation.d.ts +2 -0
- package/dist/config/validation.js +85 -0
- package/dist/file-utils.d.ts +1 -0
- package/dist/file-utils.js +17 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +160 -0
- package/dist/temp.d.ts +2 -0
- package/dist/temp.js +3 -0
- package/dist/test/test-helpers.d.ts +14 -0
- package/dist/test/test-helpers.js +119 -0
- package/package.json +45 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateDocsCommand = generateDocsCommand;
|
|
7
|
+
exports.generateDocForFile = generateDocForFile;
|
|
8
|
+
const platformos_check_common_1 = require("@platformos/platformos-check-common");
|
|
9
|
+
const platformos_check_docs_updater_1 = require("@platformos/platformos-check-docs-updater");
|
|
10
|
+
const liquid_html_parser_1 = require("@platformos/liquid-html-parser");
|
|
11
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
12
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
13
|
+
const node_util_1 = require("node:util");
|
|
14
|
+
const vscode_uri_1 = require("vscode-uri");
|
|
15
|
+
const glob = require("glob");
|
|
16
|
+
const asyncGlob = (0, node_util_1.promisify)(glob);
|
|
17
|
+
/**
|
|
18
|
+
* Generate doc blocks for all partials and blocks in a theme.
|
|
19
|
+
*/
|
|
20
|
+
async function generateDocsCommand(root, options = {}) {
|
|
21
|
+
const { dryRun = false, output = 'inline' } = options;
|
|
22
|
+
const rootUri = platformos_check_common_1.path.normalize(vscode_uri_1.URI.file(root));
|
|
23
|
+
const themeLiquidDocsManager = new platformos_check_docs_updater_1.ThemeLiquidDocsManager(console.error.bind(console));
|
|
24
|
+
// Find all liquid files that support doc blocks (partials and blocks)
|
|
25
|
+
const partialsGlob = node_path_1.default
|
|
26
|
+
.normalize(node_path_1.default.join(root, 'app/views/partials/**/*.liquid'))
|
|
27
|
+
.replace(/\\/g, '/');
|
|
28
|
+
const blocksGlob = node_path_1.default
|
|
29
|
+
.normalize(node_path_1.default.join(root, 'blocks/**/*.liquid'))
|
|
30
|
+
.replace(/\\/g, '/');
|
|
31
|
+
const [partialPaths, blockPaths] = await Promise.all([
|
|
32
|
+
asyncGlob(partialsGlob, { absolute: true }),
|
|
33
|
+
asyncGlob(blocksGlob, { absolute: true }),
|
|
34
|
+
]);
|
|
35
|
+
const allPaths = [...partialPaths, ...blockPaths];
|
|
36
|
+
const results = [];
|
|
37
|
+
for (const absolutePath of allPaths) {
|
|
38
|
+
const uri = platformos_check_common_1.path.normalize(vscode_uri_1.URI.file(absolutePath));
|
|
39
|
+
// Double-check this file supports doc blocks
|
|
40
|
+
if (!(0, platformos_check_common_1.filePathSupportsLiquidDoc)(uri))
|
|
41
|
+
continue;
|
|
42
|
+
// Read and parse the file
|
|
43
|
+
const source = await promises_1.default.readFile(absolutePath, 'utf8');
|
|
44
|
+
const sourceCode = (0, platformos_check_common_1.toSourceCode)(uri, source);
|
|
45
|
+
if (!sourceCode || sourceCode.type !== platformos_check_common_1.SourceCodeType.LiquidHtml)
|
|
46
|
+
continue;
|
|
47
|
+
const ast = sourceCode.ast;
|
|
48
|
+
if (!(0, liquid_html_parser_1.isLiquidHtmlNode)(ast))
|
|
49
|
+
continue;
|
|
50
|
+
// Generate doc block
|
|
51
|
+
const docResult = await (0, platformos_check_common_1.generateDocBlock)(ast, uri, themeLiquidDocsManager);
|
|
52
|
+
const relativePath = node_path_1.default.relative(root, absolutePath);
|
|
53
|
+
const result = {
|
|
54
|
+
uri,
|
|
55
|
+
relativePath,
|
|
56
|
+
parameters: docResult.parameters,
|
|
57
|
+
docBlockText: docResult.docBlockText,
|
|
58
|
+
hasExistingDocBlock: docResult.hasExistingDocBlock,
|
|
59
|
+
updated: false,
|
|
60
|
+
};
|
|
61
|
+
// Skip files that already have doc blocks
|
|
62
|
+
if (docResult.hasExistingDocBlock) {
|
|
63
|
+
results.push(result);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// Skip files with no detected parameters
|
|
67
|
+
if (docResult.parameters.length === 0) {
|
|
68
|
+
results.push(result);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
// If not dry run and output is inline, write the doc block to the file
|
|
72
|
+
if (!dryRun && output === 'inline') {
|
|
73
|
+
const newSource = docResult.docBlockText + '\n\n' + source;
|
|
74
|
+
await promises_1.default.writeFile(absolutePath, newSource, 'utf8');
|
|
75
|
+
result.updated = true;
|
|
76
|
+
}
|
|
77
|
+
results.push(result);
|
|
78
|
+
}
|
|
79
|
+
// Output based on mode
|
|
80
|
+
if (output === 'stdout') {
|
|
81
|
+
for (const result of results) {
|
|
82
|
+
if (result.hasExistingDocBlock) {
|
|
83
|
+
console.log(`[SKIP] ${result.relativePath} - already has doc block`);
|
|
84
|
+
}
|
|
85
|
+
else if (result.parameters.length === 0) {
|
|
86
|
+
console.log(`[SKIP] ${result.relativePath} - no parameters detected`);
|
|
87
|
+
}
|
|
88
|
+
else if (dryRun) {
|
|
89
|
+
console.log(`[DRY-RUN] ${result.relativePath}`);
|
|
90
|
+
console.log(result.docBlockText);
|
|
91
|
+
console.log('');
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
console.log(`[UPDATED] ${result.relativePath}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else if (output === 'json') {
|
|
99
|
+
console.log(JSON.stringify(results, null, 2));
|
|
100
|
+
}
|
|
101
|
+
return results;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Generate doc block for a single file.
|
|
105
|
+
*/
|
|
106
|
+
async function generateDocForFile(absolutePath, options = {}) {
|
|
107
|
+
const { dryRun = false } = options;
|
|
108
|
+
const uri = platformos_check_common_1.path.normalize(vscode_uri_1.URI.file(absolutePath));
|
|
109
|
+
if (!(0, platformos_check_common_1.filePathSupportsLiquidDoc)(uri)) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const themeLiquidDocsManager = new platformos_check_docs_updater_1.ThemeLiquidDocsManager(console.error.bind(console));
|
|
113
|
+
const source = await promises_1.default.readFile(absolutePath, 'utf8');
|
|
114
|
+
const sourceCode = (0, platformos_check_common_1.toSourceCode)(uri, source);
|
|
115
|
+
if (!sourceCode || sourceCode.type !== platformos_check_common_1.SourceCodeType.LiquidHtml)
|
|
116
|
+
return null;
|
|
117
|
+
const ast = sourceCode.ast;
|
|
118
|
+
if (!(0, liquid_html_parser_1.isLiquidHtmlNode)(ast))
|
|
119
|
+
return null;
|
|
120
|
+
const docResult = await (0, platformos_check_common_1.generateDocBlock)(ast, uri, themeLiquidDocsManager);
|
|
121
|
+
const result = {
|
|
122
|
+
uri,
|
|
123
|
+
relativePath: absolutePath,
|
|
124
|
+
parameters: docResult.parameters,
|
|
125
|
+
docBlockText: docResult.docBlockText,
|
|
126
|
+
hasExistingDocBlock: docResult.hasExistingDocBlock,
|
|
127
|
+
updated: false,
|
|
128
|
+
};
|
|
129
|
+
if (!docResult.hasExistingDocBlock && docResult.parameters.length > 0 && !dryRun) {
|
|
130
|
+
const newSource = docResult.docBlockText + '\n\n' + source;
|
|
131
|
+
await promises_1.default.writeFile(absolutePath, newSource, 'utf8');
|
|
132
|
+
result.updated = true;
|
|
133
|
+
}
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=generate-docs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { generateDocsCommand, generateDocForFile, GenerateDocsOptions, GenerateDocsResult, } from './generate-docs';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateDocForFile = exports.generateDocsCommand = void 0;
|
|
4
|
+
var generate_docs_1 = require("./generate-docs");
|
|
5
|
+
Object.defineProperty(exports, "generateDocsCommand", { enumerable: true, get: function () { return generate_docs_1.generateDocsCommand; } });
|
|
6
|
+
Object.defineProperty(exports, "generateDocForFile", { enumerable: true, get: function () { return generate_docs_1.generateDocForFile; } });
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function findConfigPath(root: string): Promise<string | undefined>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.findConfigPath = findConfigPath;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const file_utils_1 = require("../file-utils");
|
|
9
|
+
const DiscoverableConfigFileNames = ['.platformos-check.yml'];
|
|
10
|
+
function findConfigPath(root) {
|
|
11
|
+
const paths = DiscoverableConfigFileNames.map((file) => node_path_1.default.join(root, file));
|
|
12
|
+
return find(paths, file_utils_1.fileExists);
|
|
13
|
+
}
|
|
14
|
+
async function find(array, pred) {
|
|
15
|
+
for (const el of array) {
|
|
16
|
+
if (await pred(el)) {
|
|
17
|
+
return el;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=find-config-path.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findConfigPath = exports.loadConfig = void 0;
|
|
4
|
+
var load_config_1 = require("./load-config");
|
|
5
|
+
Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return load_config_1.loadConfig; } });
|
|
6
|
+
var find_config_path_1 = require("./find-config-path");
|
|
7
|
+
Object.defineProperty(exports, "findConfigPath", { enumerable: true, get: function () { return find_config_path_1.findConfigPath; } });
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const thisNodeModuleRoot: () => string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.thisNodeModuleRoot = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
9
|
+
// This is used to load global checks (in the context where someone installed the CLI globally)
|
|
10
|
+
// This shouldn't be used by VS Code since it's baked into the extension with webpack.
|
|
11
|
+
const thisNodeModuleRoot = () => {
|
|
12
|
+
if (process.env.WEBPACK_MODE) {
|
|
13
|
+
return node_os_1.default.tmpdir();
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
return node_path_1.default.resolve(node_path_1.default.join(__dirname, '..', '..'));
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
exports.thisNodeModuleRoot = thisNodeModuleRoot;
|
|
20
|
+
//# sourceMappingURL=installation-location.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Config } from '@platformos/platformos-check-common';
|
|
2
|
+
import { AbsolutePath } from '../temp';
|
|
3
|
+
import { ConfigDescription } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* Creates the checks array, loads node modules checks and validates
|
|
6
|
+
* settings against the respective check schemas.
|
|
7
|
+
*
|
|
8
|
+
* Effectively "loads" a ConfigDescription into a Config.
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadConfigDescription(configDescription: ConfigDescription, root: AbsolutePath): Promise<Config>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadConfigDescription = loadConfigDescription;
|
|
7
|
+
const platformos_check_common_1 = require("@platformos/platformos-check-common");
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const file_utils_1 = require("../file-utils");
|
|
10
|
+
const installation_location_1 = require("./installation-location");
|
|
11
|
+
const load_third_party_checks_1 = require("./load-third-party-checks");
|
|
12
|
+
const vscode_uri_1 = require("vscode-uri");
|
|
13
|
+
const flatten = (arrs) => arrs.flat();
|
|
14
|
+
/**
|
|
15
|
+
* Creates the checks array, loads node modules checks and validates
|
|
16
|
+
* settings against the respective check schemas.
|
|
17
|
+
*
|
|
18
|
+
* Effectively "loads" a ConfigDescription into a Config.
|
|
19
|
+
*/
|
|
20
|
+
async function loadConfigDescription(configDescription, root) {
|
|
21
|
+
const nodeModuleRoot = await findNodeModuleRoot(root);
|
|
22
|
+
const thirdPartyChecksPaths = await Promise.all([
|
|
23
|
+
(0, load_third_party_checks_1.findThirdPartyChecks)((0, installation_location_1.thisNodeModuleRoot)()), // global checks
|
|
24
|
+
(0, load_third_party_checks_1.findThirdPartyChecks)(nodeModuleRoot),
|
|
25
|
+
]).then(flatten);
|
|
26
|
+
const thirdPartyChecks = (0, load_third_party_checks_1.loadThirdPartyChecks)([
|
|
27
|
+
...configDescription.require,
|
|
28
|
+
...thirdPartyChecksPaths,
|
|
29
|
+
]);
|
|
30
|
+
const checks = platformos_check_common_1.allChecks
|
|
31
|
+
.concat(thirdPartyChecks)
|
|
32
|
+
.filter(isEnabledBy(configDescription));
|
|
33
|
+
const rootUri = vscode_uri_1.URI.file(root);
|
|
34
|
+
return {
|
|
35
|
+
settings: unaliasedSettings(configDescription.checkSettings, checks),
|
|
36
|
+
context: configDescription.context ?? 'theme',
|
|
37
|
+
checks,
|
|
38
|
+
ignore: configDescription.ignore,
|
|
39
|
+
rootUri: resolveRoot(rootUri, configDescription.root),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* @param root - absolute path of the config file
|
|
44
|
+
* @param pathLike - resolved textual value of the `root` property from the config files
|
|
45
|
+
* @returns {string} resolved URI of the root property
|
|
46
|
+
*/
|
|
47
|
+
function resolveRoot(root, pathLike) {
|
|
48
|
+
if (pathLike === undefined) {
|
|
49
|
+
return platformos_check_common_1.path.normalize(root);
|
|
50
|
+
}
|
|
51
|
+
if (node_path_1.default.isAbsolute(pathLike)) {
|
|
52
|
+
throw new Error('the "root" property can only be relative');
|
|
53
|
+
}
|
|
54
|
+
return platformos_check_common_1.path.resolve(root, pathLike);
|
|
55
|
+
}
|
|
56
|
+
const isEnabledBy = (config) => (checkDefinition) => {
|
|
57
|
+
const checkSettings = config.checkSettings[checkDefinition.meta.code] ?? aliasedSettings(config, checkDefinition);
|
|
58
|
+
if (!checkSettings)
|
|
59
|
+
return false;
|
|
60
|
+
return checkSettings.enabled;
|
|
61
|
+
};
|
|
62
|
+
function aliasedSettings(config, checkDefinition) {
|
|
63
|
+
if (!checkDefinition.meta.aliases)
|
|
64
|
+
return undefined;
|
|
65
|
+
const usedAlias = checkDefinition.meta.aliases.find((alias) => config.checkSettings[alias]);
|
|
66
|
+
if (!usedAlias)
|
|
67
|
+
return undefined;
|
|
68
|
+
return config.checkSettings[usedAlias];
|
|
69
|
+
}
|
|
70
|
+
function unaliasedSettings(settings, checks) {
|
|
71
|
+
return Object.fromEntries(Object.entries(settings).map(([code, value]) => {
|
|
72
|
+
return [unaliasedCode(code, checks), value];
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
function unaliasedCode(code, checks) {
|
|
76
|
+
const check = checks.find((check) => check.meta.code === code || check.meta.aliases?.find((alias) => alias === code));
|
|
77
|
+
return check?.meta.code;
|
|
78
|
+
}
|
|
79
|
+
async function isNodeModuleRoot(root) {
|
|
80
|
+
// is absolute absolute root
|
|
81
|
+
if (node_path_1.default.dirname(root) === root) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
const [isNodeModuleRoot, isGitRoot] = await Promise.all([
|
|
85
|
+
(0, file_utils_1.fileExists)(node_path_1.default.join(root, 'node_modules')),
|
|
86
|
+
(0, file_utils_1.fileExists)(node_path_1.default.join(root, '.git')),
|
|
87
|
+
]);
|
|
88
|
+
return isNodeModuleRoot || isGitRoot;
|
|
89
|
+
}
|
|
90
|
+
async function findNodeModuleRoot(root) {
|
|
91
|
+
let curr = root;
|
|
92
|
+
while (!(await isNodeModuleRoot(curr))) {
|
|
93
|
+
curr = node_path_1.default.dirname(curr);
|
|
94
|
+
}
|
|
95
|
+
return curr;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=load-config-description.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Config } from '@platformos/platformos-check-common';
|
|
2
|
+
import { AbsolutePath } from '../temp';
|
|
3
|
+
import { ModernIdentifier } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* Given an absolute path to a config file, this function returns
|
|
6
|
+
* the validated Config object that it represents.
|
|
7
|
+
*
|
|
8
|
+
* In detail, it does the following:
|
|
9
|
+
* - resolves and merges extended config,
|
|
10
|
+
* - resolves the absolute path of the root,
|
|
11
|
+
* - loads community-provided checks,
|
|
12
|
+
* - validates check settings.
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadConfig(
|
|
15
|
+
/** The absolute path of config file */
|
|
16
|
+
configPath: AbsolutePath | ModernIdentifier | undefined,
|
|
17
|
+
/** The root of the platformOS project */
|
|
18
|
+
root: AbsolutePath): Promise<Config>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadConfig = loadConfig;
|
|
4
|
+
const load_config_description_1 = require("./load-config-description");
|
|
5
|
+
const resolve_1 = require("./resolve");
|
|
6
|
+
const validation_1 = require("./validation");
|
|
7
|
+
/**
|
|
8
|
+
* Given an absolute path to a config file, this function returns
|
|
9
|
+
* the validated Config object that it represents.
|
|
10
|
+
*
|
|
11
|
+
* In detail, it does the following:
|
|
12
|
+
* - resolves and merges extended config,
|
|
13
|
+
* - resolves the absolute path of the root,
|
|
14
|
+
* - loads community-provided checks,
|
|
15
|
+
* - validates check settings.
|
|
16
|
+
*/
|
|
17
|
+
async function loadConfig(
|
|
18
|
+
/** The absolute path of config file */
|
|
19
|
+
configPath,
|
|
20
|
+
/** The root of the platformOS project */
|
|
21
|
+
root) {
|
|
22
|
+
if (!root)
|
|
23
|
+
throw new Error('loadConfig cannot be called without a root argument');
|
|
24
|
+
const defaultChecks = 'platformos-check:recommended';
|
|
25
|
+
const configDescription = await (0, resolve_1.resolveConfig)(configPath ?? defaultChecks, true);
|
|
26
|
+
const config = await (0, load_config_description_1.loadConfigDescription)(configDescription, root);
|
|
27
|
+
(0, validation_1.validateConfig)(config);
|
|
28
|
+
return config;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=load-config.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CheckDefinition, SourceCodeType } from '@platformos/platformos-check-common';
|
|
2
|
+
import { AbsolutePath } from '../temp';
|
|
3
|
+
type ModulePath = string;
|
|
4
|
+
export declare function loadThirdPartyChecks(
|
|
5
|
+
/**
|
|
6
|
+
* An array of require()-able paths.
|
|
7
|
+
* @example
|
|
8
|
+
* [
|
|
9
|
+
* '@acme/theme-check-extension',
|
|
10
|
+
* '/absolute/path/to/checks.js',
|
|
11
|
+
* './lib/checks.js',
|
|
12
|
+
* ]
|
|
13
|
+
* */
|
|
14
|
+
modulePaths?: ModulePath[]): CheckDefinition<SourceCodeType>[];
|
|
15
|
+
export declare function findThirdPartyChecks(nodeModuleRoot: AbsolutePath): Promise<ModulePath[]>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadThirdPartyChecks = loadThirdPartyChecks;
|
|
7
|
+
exports.findThirdPartyChecks = findThirdPartyChecks;
|
|
8
|
+
const glob_1 = __importDefault(require("glob"));
|
|
9
|
+
const node_util_1 = require("node:util");
|
|
10
|
+
const asyncGlob = (0, node_util_1.promisify)(glob_1.default);
|
|
11
|
+
function loadThirdPartyChecks(
|
|
12
|
+
/**
|
|
13
|
+
* An array of require()-able paths.
|
|
14
|
+
* @example
|
|
15
|
+
* [
|
|
16
|
+
* '@acme/theme-check-extension',
|
|
17
|
+
* '/absolute/path/to/checks.js',
|
|
18
|
+
* './lib/checks.js',
|
|
19
|
+
* ]
|
|
20
|
+
* */
|
|
21
|
+
modulePaths = []) {
|
|
22
|
+
const checks = new Set();
|
|
23
|
+
for (const modulePath of modulePaths) {
|
|
24
|
+
try {
|
|
25
|
+
const moduleValue = require(/* webpackIgnore: true */ modulePath);
|
|
26
|
+
const moduleChecks = moduleValue.checks;
|
|
27
|
+
if (!Array.isArray(moduleChecks)) {
|
|
28
|
+
throw new Error(`Expected the 'checks' export to be an array and got ${typeof moduleChecks}`);
|
|
29
|
+
}
|
|
30
|
+
for (const check of moduleChecks) {
|
|
31
|
+
if (isCheckDefinition(check)) {
|
|
32
|
+
checks.add(check);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
console.error(`Expected ${check} to be a CheckDefinition, but it looks like it isn't`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
console.error(`Error loading ${modulePath}, ignoring it.\n${e}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return [...checks];
|
|
44
|
+
}
|
|
45
|
+
async function findThirdPartyChecks(nodeModuleRoot) {
|
|
46
|
+
const paths = [
|
|
47
|
+
globJoin(nodeModuleRoot.replace(/\\/g, '/'), '/node_modules/theme-check-*/'),
|
|
48
|
+
globJoin(nodeModuleRoot.replace(/\\/g, '/'), '/node_modules/@*/theme-check-*/'),
|
|
49
|
+
];
|
|
50
|
+
const results = await Promise.all(paths.map((path) => asyncGlob(path)));
|
|
51
|
+
return results
|
|
52
|
+
.flat()
|
|
53
|
+
.filter((x) => !/\@shopify\/theme-check-(node|common|browser|docs-updater)/.test(x) &&
|
|
54
|
+
!/theme-check-vscode/.test(x));
|
|
55
|
+
}
|
|
56
|
+
function globJoin(...parts) {
|
|
57
|
+
return parts.flatMap((x) => x.replace(/\\/g, '/').replace(/\/+$/, '')).join('/');
|
|
58
|
+
}
|
|
59
|
+
function isObjLiteral(thing) {
|
|
60
|
+
return thing !== null && typeof thing === 'object';
|
|
61
|
+
}
|
|
62
|
+
function isCheckDefinition(thing) {
|
|
63
|
+
return (isObjLiteral(thing) &&
|
|
64
|
+
'meta' in thing &&
|
|
65
|
+
'create' in thing &&
|
|
66
|
+
isObjLiteral(thing.meta) &&
|
|
67
|
+
'code' in thing.meta);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=load-third-party-checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { resolveConfig } from './resolve-config';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveConfig = void 0;
|
|
4
|
+
var resolve_config_1 = require("./resolve-config");
|
|
5
|
+
Object.defineProperty(exports, "resolveConfig", { enumerable: true, get: function () { return resolve_config_1.resolveConfig; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ConfigDescription, ConfigFragment } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Merges a set of ConfigDescription with a ConfigFragment to obtain a new ConfigDescription.
|
|
4
|
+
*
|
|
5
|
+
* Merge rules:
|
|
6
|
+
* - The latest `root` is selected, it is not resolved ('./dist' remains './dist')
|
|
7
|
+
* - `extends` becomes the empty array
|
|
8
|
+
* - top level `ignore` is extended by concatenation
|
|
9
|
+
* - checkSettings are deep merged
|
|
10
|
+
*/
|
|
11
|
+
export declare function mergeFragments(baseConfigs: ConfigDescription[], config: ConfigFragment): ConfigDescription;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergeFragments = mergeFragments;
|
|
4
|
+
/**
|
|
5
|
+
* Merges a set of ConfigDescription with a ConfigFragment to obtain a new ConfigDescription.
|
|
6
|
+
*
|
|
7
|
+
* Merge rules:
|
|
8
|
+
* - The latest `root` is selected, it is not resolved ('./dist' remains './dist')
|
|
9
|
+
* - `extends` becomes the empty array
|
|
10
|
+
* - top level `ignore` is extended by concatenation
|
|
11
|
+
* - checkSettings are deep merged
|
|
12
|
+
*/
|
|
13
|
+
function mergeFragments(baseConfigs, config) {
|
|
14
|
+
return {
|
|
15
|
+
// we use the last one defined
|
|
16
|
+
root: selectLatest(baseConfigs.map((b) => b.root), config.root),
|
|
17
|
+
// when we're done, there's nothing left to extend
|
|
18
|
+
extends: [],
|
|
19
|
+
// we merge the ignore configs by concatenation
|
|
20
|
+
ignore: baseConfigs.flatMap((b) => b.ignore).concat(config.ignore),
|
|
21
|
+
// we merge the require configs by concatenation
|
|
22
|
+
require: baseConfigs.flatMap((b) => b.require).concat(config.require),
|
|
23
|
+
// we merge deep the settings
|
|
24
|
+
checkSettings: baseConfigs
|
|
25
|
+
.map((b) => b.checkSettings)
|
|
26
|
+
.concat(config.checkSettings)
|
|
27
|
+
.reduce(mergeDeep),
|
|
28
|
+
// We use the last one defined, or default to 'theme'
|
|
29
|
+
context: selectLatest(baseConfigs.map((b) => b.context), config.context) ?? 'theme',
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function selectLatest(base, curr) {
|
|
33
|
+
return base.concat(curr).filter(Boolean).pop();
|
|
34
|
+
}
|
|
35
|
+
function mergeDeep(target, source) {
|
|
36
|
+
const output = { ...target };
|
|
37
|
+
for (const key in source) {
|
|
38
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
39
|
+
if (isObject(target[key]) && isObject(source[key])) {
|
|
40
|
+
output[key] = mergeDeep(target[key], source[key]);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
output[key] = source[key];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return output;
|
|
48
|
+
}
|
|
49
|
+
function isObject(item) {
|
|
50
|
+
return item !== null && typeof item === 'object' && !Array.isArray(item);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=merge-fragments.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AbsolutePath } from '../../temp';
|
|
2
|
+
import { ConfigFragment } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Takes an absolute path, parses the yaml at that path and turns it into a
|
|
5
|
+
* ConfigFragment object.
|
|
6
|
+
*/
|
|
7
|
+
export declare function readYamlConfigDescription(
|
|
8
|
+
/** the absolute path to a .platformos-check.yml file */
|
|
9
|
+
absolutePath: AbsolutePath,
|
|
10
|
+
/** only the root config has `extends: platformos-check:recommended` by default, it's nothing everywhere else */
|
|
11
|
+
isRootConfig?: boolean): Promise<ConfigFragment>;
|