diff --git a/.changeset/kind-zoos-bathe.md b/.changeset/kind-zoos-bathe.md new file mode 100644 index 000000000..b65e63e0b --- /dev/null +++ b/.changeset/kind-zoos-bathe.md @@ -0,0 +1,7 @@ +--- +'providence-analytics': patch +--- + +- correctly dedupe match-imports exportSpecifiers +- windows compatibility +- example conf file esm compatible diff --git a/.changeset/polite-hairs-shave.md b/.changeset/polite-hairs-shave.md new file mode 100644 index 000000000..cca5e8b60 --- /dev/null +++ b/.changeset/polite-hairs-shave.md @@ -0,0 +1,5 @@ +--- +'rocket-preset-extend-lion-docs': patch +--- + +windows compatibility diff --git a/packages-node/providence-analytics/package.json b/packages-node/providence-analytics/package.json index 0baf424d8..a1171a30b 100644 --- a/packages-node/providence-analytics/package.json +++ b/packages-node/providence-analytics/package.json @@ -21,7 +21,7 @@ "scripts": { "dashboard": "node ./dashboard/src/server.js --serve-from-package-root", "match-lion-imports": "npm run providence analyze match-imports --search-target-collection @lion-targets --reference-collection @lion-references", - "providence": "node --max-old-space-size=8192 ./src/cli/index.js", + "providence": "node --max-old-space-size=8192 ./src/cli/index.mjs", "publish-docs": "node ../../packages-node/publish-docs/src/cli.js --github-url https://github.com/ing-bank/lion/ --git-root-dir ../../", "prepublishOnly": "npm run publish-docs", "test:node": "mocha './test-node/**/*.test.js'", diff --git a/packages-node/providence-analytics/providence.conf.mjs b/packages-node/providence-analytics/providence.conf.mjs index aad770c56..d59e9fe30 100644 --- a/packages-node/providence-analytics/providence.conf.mjs +++ b/packages-node/providence-analytics/providence.conf.mjs @@ -1,5 +1,8 @@ -import pathLib from 'path'; +import pathLib, { dirname } from 'path'; import fs from 'fs'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); // This file is read by dashboard and cli and needs to be present under process.cwd() // It mainly serves as an example and it allows to run the dashboard locally diff --git a/packages-node/providence-analytics/src/cli/cli-helpers.js b/packages-node/providence-analytics/src/cli/cli-helpers.js index c2abc55ed..cd38bc49a 100644 --- a/packages-node/providence-analytics/src/cli/cli-helpers.js +++ b/packages-node/providence-analytics/src/cli/cli-helpers.js @@ -115,7 +115,12 @@ async function appendProjectDependencyPaths(rootPaths, matchPattern, modes = ['n let matchFn; if (matchPattern) { if (matchPattern.startsWith('/') && matchPattern.endsWith('/')) { - matchFn = (_, d) => new RegExp(matchPattern.slice(1, -1)).test(d); + matchFn = (_, d) => { + const reString = matchPattern.slice(1, -1); + const result = new RegExp(reString).test(d); + LogService.debug(`[appendProjectDependencyPaths]: /${reString}/.test(${d} => ${result})`); + return result; + }; } else { LogService.error( `[appendProjectDependencyPaths] Please provide a matchPattern enclosed by '/'. Found: ${matchPattern}`, diff --git a/packages-node/providence-analytics/src/cli/prompt-analyzer-menu.js b/packages-node/providence-analytics/src/cli/prompt-analyzer-menu.js index 58d81a462..8a9d18d1f 100644 --- a/packages-node/providence-analytics/src/cli/prompt-analyzer-menu.js +++ b/packages-node/providence-analytics/src/cli/prompt-analyzer-menu.js @@ -8,10 +8,10 @@ const { LogService } = require('../program/services/LogService.js'); const JsdocCommentParser = require('../program/utils/jsdoc-comment-parser.js'); /** - * @desc extracts name, defaultValue, optional, type, desc from JsdocCommentParser.parse method + * Extracts name, defaultValue, optional, type, desc from JsdocCommentParser.parse method * result - * @param {array} jsdoc - * @returns {object} + * @param {string[]} jsdoc + * @returns {{ name:string, defaultValue:string, optional:boolean, type:string, desc:string }} */ function getPropsFromParsedJsDoc(jsdoc) { const jsdocProps = jsdoc.filter(p => p.tagName === '@property'); diff --git a/packages-node/providence-analytics/src/program/analyzers/match-imports.js b/packages-node/providence-analytics/src/program/analyzers/match-imports.js index 853efedc2..703d0cea3 100644 --- a/packages-node/providence-analytics/src/program/analyzers/match-imports.js +++ b/packages-node/providence-analytics/src/program/analyzers/match-imports.js @@ -237,7 +237,9 @@ async function matchImportsPostprocess(exportsAnalyzerResult, importsAnalyzerRes * Add it to the results array */ const id = `${exportEntry.specifier}::${exportEntry.file}::${exportsAnalyzerResult.analyzerMeta.targetProject.name}`; - const resultForCurrentExport = conciseResultsArray.find(entry => entry.id === id); + const resultForCurrentExport = conciseResultsArray.find( + entry => entry.exportSpecifier && entry.exportSpecifier.id === id, + ); if (resultForCurrentExport) { resultForCurrentExport.importProjectFiles.push(importEntry.file); } else { diff --git a/packages-node/providence-analytics/src/program/utils/resolve-import-path.js b/packages-node/providence-analytics/src/program/utils/resolve-import-path.js index 05ae48f00..d9422a11b 100644 --- a/packages-node/providence-analytics/src/program/utils/resolve-import-path.js +++ b/packages-node/providence-analytics/src/program/utils/resolve-import-path.js @@ -12,6 +12,8 @@ const pathLib = require('path'); const { nodeResolve } = require('@rollup/plugin-node-resolve'); const { LogService } = require('../services/LogService.js'); +const { memoizeAsync } = require('./memoize.js'); +const { toPosixPath } = require('./to-posix-path.js'); const fakePluginContext = { meta: { @@ -27,15 +29,6 @@ const fakePluginContext = { }, }; -/** - * Based on importee (in a statement "import {x} from '@lion/core'", "@lion/core" is an - * importee), which can be a bare module specifier, a filename without extension, or a folder - * name without an extension. - * @param {SpecifierSource} importee source like '@lion/core' or '../helpers/index.js' - * @param {PathFromSystemRoot} importer importing file, like '/my/project/importing-file.js' - * @param {{customResolveOptions?: {preserveSymlinks:boolean}}} [opts] nodeResolve options - * @returns {Promise} the resolved file system path, like '/my/project/node_modules/@lion/core/index.js' - */ async function resolveImportPath(importee, importer, opts = {}) { const rollupResolve = nodeResolve({ rootDir: pathLib.dirname(importer), @@ -59,7 +52,18 @@ async function resolveImportPath(importee, importer, opts = {}) { return null; } // @ts-ignore - return result.id; + return toPosixPath(result.id); } -module.exports = { resolveImportPath }; +/** + * Based on importee (in a statement "import {x} from '@lion/core'", "@lion/core" is an + * importee), which can be a bare module specifier, a filename without extension, or a folder + * name without an extension. + * @param {SpecifierSource} importee source like '@lion/core' or '../helpers/index.js' + * @param {PathFromSystemRoot} importer importing file, like '/my/project/importing-file.js' + * @param {{customResolveOptions?: {preserveSymlinks:boolean}}} [opts] nodeResolve options + * @returns {Promise} the resolved file system path, like '/my/project/node_modules/@lion/core/index.js' + */ +const resolveImportPathMemoized = memoizeAsync(resolveImportPath); + +module.exports = { resolveImportPath: resolveImportPathMemoized }; diff --git a/packages-node/providence-analytics/test-helpers/project-mocks-analyzer-outputs/find-classes.json b/packages-node/providence-analytics/test-helpers/project-mocks-analyzer-outputs/find-classes.json index 413e223a5..49a3d0e11 100644 --- a/packages-node/providence-analytics/test-helpers/project-mocks-analyzer-outputs/find-classes.json +++ b/packages-node/providence-analytics/test-helpers/project-mocks-analyzer-outputs/find-classes.json @@ -92,57 +92,41 @@ { "name": "getterSetter", "accessType": "public", - "kind": [ - "get", - "set" - ] + "kind": ["get", "set"] }, { "name": "staticGetterSetter", "accessType": "public", "static": true, - "kind": [ - "get", - "set" - ] + "kind": ["get", "set"] }, { "name": "attributes", "accessType": "public", "static": true, - "kind": [ - "get" - ] + "kind": ["get"] }, { "name": "styles", "accessType": "public", "static": true, - "kind": [ - "get" - ] + "kind": ["get"] }, { "name": "updateComplete", "accessType": "public", - "kind": [ - "get" - ] + "kind": ["get"] }, { "name": "localizeNamespaces", "accessType": "public", "static": true, - "kind": [ - "get" - ] + "kind": ["get"] }, { "name": "slots", "accessType": "public", - "kind": [ - "get" - ] + "kind": ["get"] } ], "methods": [ @@ -180,7 +164,7 @@ }, { "name": "requestUpdate", - "accessType": "protected" + "accessType": "public" }, { "name": "createRenderRoot", diff --git a/packages-node/providence-analytics/test-node/cli/cli.test.js b/packages-node/providence-analytics/test-node/cli/cli.test.js index 007a0b77c..24aa2cffb 100644 --- a/packages-node/providence-analytics/test-node/cli/cli.test.js +++ b/packages-node/providence-analytics/test-node/cli/cli.test.js @@ -484,8 +484,18 @@ describe('CLI helpers', () => { }); it('allows a regex filter', async () => { - const result = await appendProjectDependencyPaths(['/mocked/path/example-project'], '/b$/'); + const result = await appendProjectDependencyPaths( + ['/mocked/path/example-project'], + '/^dependency-/', + ); expect(result).to.eql([ + '/mocked/path/example-project/node_modules/dependency-a', + '/mocked/path/example-project/bower_components/dependency-b', + '/mocked/path/example-project', + ]); + + const result2 = await appendProjectDependencyPaths(['/mocked/path/example-project'], '/b$/'); + expect(result2).to.eql([ '/mocked/path/example-project/bower_components/dependency-b', '/mocked/path/example-project', ]); diff --git a/packages-node/providence-analytics/test-node/program/analyzers/match-imports.test.js b/packages-node/providence-analytics/test-node/program/analyzers/match-imports.test.js index 4d97fcc42..6bb7fd078 100644 --- a/packages-node/providence-analytics/test-node/program/analyzers/match-imports.test.js +++ b/packages-node/providence-analytics/test-node/program/analyzers/match-imports.test.js @@ -441,6 +441,32 @@ describe('Analyzer "match-imports"', () => { ]); }); + it(`correctly merges/dedupes double found exports`, async () => { + const refProject = { + path: '/target/node_modules/ref', + name: 'ref', + files: [{ file: './index.js', code: `export default function x() {};` }], + }; + const targetProject = { + path: '/target', + name: 'target', + files: [ + { file: './importDefault1.js', code: `import myFn1 from 'ref/index.js';` }, + { file: './importDefault2.js', code: `import myFn2 from 'ref/index.js';` }, + ], + }; + mockTargetAndReferenceProject(targetProject, refProject); + await providence(matchImportsQueryConfig, { + targetProjectPaths: [targetProject.path], + referenceProjectPaths: [refProject.path], + }); + const queryResult = queryResults[0]; + expect(queryResult.queryOutput[0].exportSpecifier.name).to.equal('[default]'); + expect(queryResult.queryOutput[0].matchesPerProject).to.eql([ + { files: ['./importDefault1.js', './importDefault2.js'], project: 'target' }, + ]); + }); + describe('Inside small example project', () => { it(`produces a list of all matches, sorted by project`, async () => { mockTargetAndReferenceProject(searchTargetProject, referenceProject); diff --git a/packages-node/rocket-preset-extend-lion-docs/src/remarkUrlToLocal.js b/packages-node/rocket-preset-extend-lion-docs/src/remarkUrlToLocal.js index 694678f59..d249e6aa6 100644 --- a/packages-node/rocket-preset-extend-lion-docs/src/remarkUrlToLocal.js +++ b/packages-node/rocket-preset-extend-lion-docs/src/remarkUrlToLocal.js @@ -12,15 +12,26 @@ import visit from 'unist-util-visit'; /** @typedef {Node & UrlProperty} UrlNode */ +/** + * @param {string} pathStr C:\Example\path/like/this + * @returns {string} /Example/path/like/this + */ +function toPosixPath(pathStr) { + if (process.platform === 'win32') { + return pathStr.replace(/^.:/, '').replace(/\\/g, '/'); + } + return pathStr; +} + /** * @param {object} opts * @param {string} opts.gitHubUrl - * @param {object} opts.page - * @param {string} opts.page.inputPath + * @param {{inputPath:string}} opts.page * @param {string} opts.rootDir - * @returns */ export function remarkUrlToLocal({ gitHubUrl, page, rootDir }) { + const inputPath = toPosixPath(page.inputPath); + /** * @param {UrlNode} node */ @@ -34,10 +45,9 @@ export function remarkUrlToLocal({ gitHubUrl, page, rootDir }) { urlParts.shift(); urlParts.shift(); const fullUrlPath = path.join(rootDir, urlParts.join('/')); - const fullInputPath = - page.inputPath[0] === '/' ? page.inputPath : path.join(rootDir, page.inputPath); + const fullInputPath = inputPath[0] === '/' ? inputPath : path.join(rootDir, inputPath); const newPath = path.relative(path.dirname(fullInputPath), fullUrlPath); - node.url = newPath; + node.url = toPosixPath(newPath); } } }