Skip to content

Commit af0e187

Browse files
authored
Merge pull request #228 from tkskto/feature/add-api-support
add API support
2 parents 1d8de33 + ca5bd28 commit af0e187

File tree

17 files changed

+202
-163
lines changed

17 files changed

+202
-163
lines changed

.eslintrc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"multiline-comment-style": 0,
1717
"@typescript-eslint/no-var-requires": 0,
1818
"no-console": 0,
19-
"no-new": 0
19+
"no-new": 0,
20+
"arrow-body-style": 0
2021
}
2122
}

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,22 @@ npm exec vca -- --dir .
4646
* `-o` or `--out` : output directory. JSON file will output here.
4747
* `-p` or `--port` : select a port number for the local server.
4848

49-
## License
49+
## API
5050

51-
MIT License.
51+
vue-component-analyzer is also available as an API from v0.6.0.
52+
53+
This API is intended to be used for testing.
54+
55+
```javascript
56+
import {getImportDeclarationTree} from '@tkskto/vue-component-analyzer';
57+
58+
const jsonOfTree = getImportDeclarationTree('entryFile.vue');
59+
```
60+
61+
See [index.d.ts](./types/index.d.ts) for details of types.
5262

63+
(`lastModifiedTime` can be noise. If you don't need it remove explicitly.)
5364

65+
## License
66+
67+
MIT License.

bin/analyze.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env node
22

3-
import {vueComponentAnalyze} from '../dist/index.mjs';
3+
import {analyzeFromCLI} from '../dist/index.mjs';
44

55
/**
66
* Catch and report unexpected error.
@@ -14,12 +14,12 @@ function onCatchError(error) {
1414
process.exit(1);
1515
}
1616

17-
(function main() {
17+
(async function main() {
1818
process.on('uncaughtException', onCatchError);
1919
process.on('unhandledRejection', onCatchError);
2020

2121
try {
22-
vueComponentAnalyze();
22+
await analyzeFromCLI();
2323
} catch (err) {
2424
onCatchError(err);
2525
}

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
"version": "0.5.2",
44
"description": "Analyze dependency tree for Vue.js SFC (Single File Component)",
55
"type": "module",
6+
"main": "./dist/index.mjs",
7+
"types": "./types/index.d.ts",
68
"bin": {
79
"vca": "bin/analyze.js"
810
},

src/client/Seed.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* Data Type of one of Vue File.
33
*/
4-
import FileReport = vueComponentAnalyzer.FileReport;
4+
import {FileReport} from '../../types';
55
import {Model} from './model';
66

77
export class Seed {

src/client/model.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import {AnalyzeReport} from '../../types';
12
import {CustomEventDispatcher} from './eventDispatcher';
2-
import AnalyzeReport = vueComponentAnalyzer.AnalyzeReport;
33

44
export type INFORMATION_TYPE = 'settings' | 'props' | 'fileSize' | 'lastUpdated' | 'referenceCount';
55
export type VIEW_TYPE = 'GRAPH' | 'TEXT';
@@ -38,11 +38,11 @@ export class Model extends CustomEventDispatcher {
3838
this._todayTime = this._today.getTime();
3939
}
4040

41-
get data(): vueComponentAnalyzer.AnalyzeReport {
41+
get data(): AnalyzeReport {
4242
return this._data;
4343
}
4444

45-
set data(value: vueComponentAnalyzer.AnalyzeReport) {
45+
set data(value: AnalyzeReport) {
4646
this._data = value;
4747
this.dispatchEvent(Model.EVENT.DATA_UPDATE);
4848
}

src/client/renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// for execute from browser.
22

3+
import {FileReport} from '../../types';
34
import {Seed} from './Seed';
45
import {Model} from './model';
5-
import FileReport = vueComponentAnalyzer.FileReport;
66

77
export class Renderer {
88
private readonly _app: HTMLElement | null;

src/server/Analyzer.ts

Lines changed: 53 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,74 @@
1-
import FileReport = vueComponentAnalyzer.FileReport;
1+
import {FileReport} from '../../types';
22
import {resolveFile} from './utils';
33
import {readFileSync, statSync} from 'fs';
44
import {resolve, extname} from 'path';
5-
import {FileCounter} from './FileCounter';
5+
import {fileCounter} from './FileCounter';
66
import {VueComponent} from './VueComponent';
77
import {model} from './Model';
88
const cwd = process.cwd();
99

10-
class Analyzer {
11-
private readonly _counter: FileCounter;
10+
/**
11+
* get import tree.
12+
* @param {string} fileName entry file name
13+
* @param {string[]} parents entries of file name
14+
* @param {boolean} isTest whether it through the test. if this doesn't exist lastModifiedTime will always fail on the GitHub Actions.
15+
*/
16+
export const getImportDeclarationTree = (fileName: string, parents: string[] = [], isTest = false): FileReport => {
17+
const filename = resolve(cwd, fileName);
18+
// get filename without current working directory.
19+
const shortFilename = filename.replace(cwd, '');
20+
// get file statistic
21+
const stat = statSync(filename);
22+
// make a filename list for detecting circular dependency.
23+
const ancestorList: string[] = parents.concat();
1224

13-
constructor() {
14-
this._counter = new FileCounter();
15-
}
16-
17-
/**
18-
* get import tree.
19-
* @param {string} fileName entry file name
20-
* @param {string[]} parents entries of file name
21-
* @param {boolean} isTest whether it through the test. if this doesn't exist lastModifiedTime will always fail on the GitHub Actions.
22-
*/
23-
public getImportDeclarationTree = (fileName: string, parents: string[], isTest = false): FileReport => {
24-
const filename = resolve(cwd, fileName);
25-
// get filename without current working directory.
26-
const shortFilename = filename.replace(cwd, '');
27-
// get file statistic
28-
const stat = statSync(filename);
29-
// make a filename list for detecting circular dependency.
30-
const ancestorList: string[] = parents.concat();
31-
32-
ancestorList.push(fileName);
25+
ancestorList.push(fileName);
3326

34-
if (!model.isSilentMode) {
35-
console.log(`read ${filename}`);
36-
}
27+
if (!model.isSilentMode) {
28+
console.log(`read ${filename}`);
29+
}
3730

38-
// increment count of this file.
39-
this._counter.add(shortFilename);
31+
// increment count of this file.
32+
fileCounter.add(shortFilename);
4033

41-
// if this file is not Vue Component file, return only filename and stat.
42-
if (extname(filename) === '' || extname(filename) !== '.vue') {
43-
return {
44-
name: shortFilename,
45-
props: '',
46-
size: stat.size,
47-
lastModifiedTime: isTest ? 0 : Number(stat.mtimeMs.toFixed(0)),
48-
children: [],
49-
};
50-
}
34+
// if this file is not Vue Component file, return only filename and stat.
35+
if (extname(filename) === '' || extname(filename) !== '.vue') {
36+
return {
37+
name: shortFilename,
38+
props: '',
39+
size: stat.size,
40+
lastModifiedTime: isTest ? 0 : Number(stat.mtimeMs.toFixed(0)),
41+
children: [],
42+
};
43+
}
5144

52-
const contents = readFileSync(filename, 'utf-8');
53-
const component = new VueComponent(shortFilename, contents, stat);
45+
const contents = readFileSync(filename, 'utf-8');
46+
const component = new VueComponent(shortFilename, contents, stat);
5447

55-
try {
56-
// if we get, read imported file recursive.
57-
for (let i = 0, len = component.importDeclaration.length; i < len; i++) {
58-
// TODO: support other types? (value might be RegExp, or number, boolean.)
59-
const source = String(component.importDeclaration[i].source.value);
48+
try {
49+
// if we get, read imported file recursive.
50+
for (let i = 0, len = component.importDeclaration.length; i < len; i++) {
51+
// TODO: support other types? (value might be RegExp, or number, boolean.)
52+
const source = String(component.importDeclaration[i].source.value);
6053

61-
if (source) {
62-
const nextFilename = resolveFile(source, filename);
54+
if (source) {
55+
const nextFilename = resolveFile(source, filename);
6356

64-
if (nextFilename) {
65-
if (parents.includes(nextFilename)) {
66-
console.warn(`Circular dependency detected between ${nextFilename} and ${filename}`);
67-
} else {
68-
component.addChildReport(this.getImportDeclarationTree(nextFilename, ancestorList, isTest));
69-
}
57+
if (nextFilename) {
58+
if (parents.includes(nextFilename)) {
59+
console.warn(`Circular dependency detected between ${nextFilename} and ${filename}`);
60+
} else {
61+
component.addChildReport(getImportDeclarationTree(nextFilename, ancestorList, isTest));
7062
}
7163
}
7264
}
73-
} catch (err) {
74-
console.error(`Something went wrong with reading ${filename}`);
75-
if (err instanceof Error) {
76-
console.error(err.message);
77-
}
7865
}
79-
80-
return component.getFileReport(isTest);
81-
};
82-
83-
get counter(): FileCounter {
84-
return this._counter;
66+
} catch (err) {
67+
console.error(`Something went wrong with reading ${filename}`);
68+
if (err instanceof Error) {
69+
console.error(err.message);
70+
}
8571
}
86-
}
8772

88-
export const analyzer = new Analyzer();
73+
return component.getFileReport(isTest);
74+
};

src/server/FileCounter.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ export class FileCounter {
1313
}
1414
}
1515

16-
public get count(): {[key: string]: number} {
16+
public clear(): void {
17+
this._count = {};
18+
}
19+
20+
public get result(): {[key: string]: number} {
1721
return this._count;
1822
}
1923
}
24+
25+
export const fileCounter = new FileCounter();

src/server/VueComponent.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import {FileReport} from '../../types';
12
import {parse} from 'vue-eslint-parser';
23
import {ESLintImportDeclaration, ESLintProgram} from 'vue-eslint-parser/ast/nodes';
34
import {Token} from 'vue-eslint-parser/ast/tokens';
45
import {getImportDeclaration, getDeclarationSyntax} from './utils';
5-
import FileReport = vueComponentAnalyzer.FileReport;
66
import {Stats} from 'fs';
77

88
const parserOption = {

0 commit comments

Comments
 (0)