Socket
Socket
Sign inDemoInstall

@tkskto/vue-component-analyzer

Package Overview
Dependencies
161
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.3 to 0.1.4

CHANGELOG.md

269

dist/index.js
/*!
@tkskto/vue-component-analyzer v0.1.3
@tkskto/vue-component-analyzer v0.1.4
https://github.com/tkskto/

@@ -17,7 +17,7 @@ Released under the MIT License.

var require$$0 = require('vue-eslint-parser');
var require$$1 = require('fs');
var path = require('path');
var fs_1 = require('fs');
var path_1 = require('path');
var vue_eslint_parser_1 = require('vue-eslint-parser');
var http = require('http');
var require$$0$1 = require('ejs');
var require$$0 = require('ejs');
var express = require('express');

@@ -32,7 +32,7 @@ var webSocket = require('ws');

var fs_1__default = /*#__PURE__*/_interopDefaultLegacy(fs_1);
var path_1__default = /*#__PURE__*/_interopDefaultLegacy(path_1);
var vue_eslint_parser_1__default = /*#__PURE__*/_interopDefaultLegacy(vue_eslint_parser_1);
var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
var require$$0__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$0$1);
var express__default = /*#__PURE__*/_interopDefaultLegacy(express);

@@ -61,33 +61,12 @@ var webSocket__default = /*#__PURE__*/_interopDefaultLegacy(webSocket);

class FileCounter {
constructor() {
this._count = {};
}
add(filename) {
if (Object.prototype.hasOwnProperty.call(this._count, filename)) {
this._count[filename]++;
}
else {
this._count[filename] = 1;
}
}
get count() {
return this._count;
}
}
var FileCounter_1 = FileCounter;
var utils = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
const { parse } = require$$0__default['default'];
const { readFileSync, existsSync, statSync } = require$$1__default['default'];
const { resolve, extname, dirname } = path__default['default'];
const cwd = process.cwd();
const counter = new FileCounter_1();
const getImportDeclaration = (nodeArr) => {
exports.resolveFile = exports.getDeclarationSyntax = exports.getImportDeclaration = void 0;
const { existsSync } = fs_1__default['default'];
const { resolve, extname, dirname } = path_1__default['default'];
exports.getImportDeclaration = (nodeArr) => {
return nodeArr.filter((node) => node.type === 'ImportDeclaration');
};
const getPropsDeclaration = (tokens) => {
let isPropsToken = false;
exports.getDeclarationSyntax = (tokens, targetKeyName) => {
let isTargetToken = false;
let result = '{';

@@ -98,5 +77,5 @@ let closedCount = 0;

const { type, value } = token;
if (isPropsToken || (type === 'Identifier' && value === 'props')) {
if (isTargetToken || (!isTargetToken && type === 'Identifier' && value === targetKeyName)) {
const needQuoting = needQuotingTypes.includes(type);
isPropsToken = true;
isTargetToken = true;
if (type === 'Punctuator') {

@@ -128,3 +107,3 @@ if (value === '{') {

};
const resolveFile = (_filename, _currentFileName) => {
exports.resolveFile = (_filename, _currentFileName) => {
let filename = '';

@@ -141,4 +120,12 @@ if (_filename.startsWith('../')) {

if (filename) {
if (extname(filename) === '' && existsSync(`${filename}.vue`)) {
return `${filename}.vue`;
if (extname(filename) === '') {
if (existsSync(`${filename}.vue`)) {
return `${filename}.vue`;
}
else if (existsSync(`${filename}.js`)) {
return `${filename}.js`;
}
else if (existsSync(`${filename}.ts`)) {
return `${filename}.ts`;
}
}

@@ -148,58 +135,147 @@ }

};
const getImportDeclarationTree = (fileName, isTest = false) => {
const filename = resolve(cwd, fileName);
const shortFilename = filename.replace(cwd, '');
const children = [];
const result = {
name: shortFilename,
props: '',
size: 0,
lastModifiedTime: 0,
children,
};
console.log(`read ${filename}.`);
counter.add(shortFilename);
if (extname(filename) === '') {
return result;
});
var FileCounter_1 = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileCounter = void 0;
class FileCounter {
constructor() {
this._count = {};
}
const stat = statSync(filename);
if (!isTest) {
result.lastModifiedTime = Number(stat.mtimeMs.toFixed(0));
add(_filename) {
const filename = path_1__default['default'].resolve(_filename);
if (Object.prototype.hasOwnProperty.call(this._count, filename)) {
this._count[filename]++;
}
else {
this._count[filename] = 1;
}
}
result.size = stat.size;
if (extname(filename) !== '.vue') {
return result;
get count() {
return this._count;
}
try {
const file = readFileSync(filename, 'utf-8');
const parserOption = {
ecmaVersion: 2018,
sourceType: 'module',
}
exports.FileCounter = FileCounter;
});
var VueComponent_1 = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.VueComponent = void 0;
const parserOption = {
ecmaVersion: 2018,
sourceType: 'module',
};
class VueComponent {
constructor(filename, contents, stats) {
var _a, _b, _c;
this._filename = '';
this._lastModifiedTime = 0;
this._size = 0;
this._template = '';
this._style = '';
this._props = '';
this._children = [];
this._importDeclaration = [];
this.getProps = (tokens) => {
try {
const propsDeclaration = JSON.parse(utils.getDeclarationSyntax(tokens, 'props'));
if (propsDeclaration && propsDeclaration.props) {
return propsDeclaration.props;
}
return '';
}
catch (err) {
console.warn('failed to analyze props.');
return '';
}
};
const esLintProgram = parse(file, parserOption);
this._filename = filename;
this._lastModifiedTime = (stats === null || stats === void 0 ? void 0 : stats.mtimeMs) || 0;
this._size = (stats === null || stats === void 0 ? void 0 : stats.size) || 0;
const templateBody = contents.match(/(?<template><template>[\s\S]*<\/template>)/u);
const scriptBody = contents.match(/(?<script><script>[\s\S]*<\/script>)/u);
const styleBody = contents.match(/(?<style><style>[\s\S]*<\/style>)/u);
this._template = ((_a = templateBody === null || templateBody === void 0 ? void 0 : templateBody.groups) === null || _a === void 0 ? void 0 : _a.template) || '';
this._style = ((_b = styleBody === null || styleBody === void 0 ? void 0 : styleBody.groups) === null || _b === void 0 ? void 0 : _b.template) || '';
const scriptString = ((_c = scriptBody === null || scriptBody === void 0 ? void 0 : scriptBody.groups) === null || _c === void 0 ? void 0 : _c.script) || '';
const esLintProgram = vue_eslint_parser_1__default['default'].parse(scriptString, parserOption);
if (esLintProgram.tokens) {
const propsDeclaration = JSON.parse(getPropsDeclaration(esLintProgram.tokens));
if (propsDeclaration && propsDeclaration.props) {
result.props = propsDeclaration.props;
this._props = this.getProps(esLintProgram.tokens);
}
this._importDeclaration = utils.getImportDeclaration(esLintProgram.body);
}
addChildReport(report) {
this._children.push(report);
}
get importDeclaration() {
return this._importDeclaration;
}
getFileReport(isTest) {
return {
name: this._filename,
props: this._props,
size: this._size,
lastModifiedTime: isTest ? 0 : Number(this._lastModifiedTime.toFixed(0)),
children: this._children,
};
}
}
exports.VueComponent = VueComponent;
});
var Analyzer_1 = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.Analyzer = void 0;
const cwd = process.cwd();
class Analyzer {
constructor() {
this.getImportDeclarationTree = (fileName, isTest = false) => {
const filename = path_1__default['default'].resolve(cwd, fileName);
const shortFilename = filename.replace(cwd, '');
const stat = fs_1__default['default'].statSync(filename);
console.log(`read ${filename}.`);
this._counter.add(shortFilename);
if (path_1__default['default'].extname(filename) === '' || path_1__default['default'].extname(filename) !== '.vue') {
return {
name: shortFilename,
props: '',
size: stat.size,
lastModifiedTime: isTest ? 0 : Number(stat.mtimeMs.toFixed(0)),
children: [],
};
}
}
const body = getImportDeclaration(esLintProgram.body);
for (let i = 0, len = body.length; i < len; i++) {
const source = String(body[i].source.value);
if (source) {
const nextFilename = resolveFile(source, filename);
if (nextFilename) {
children.push(getImportDeclarationTree(nextFilename, isTest));
const contents = fs_1__default['default'].readFileSync(filename, 'utf-8');
const component = new VueComponent_1.VueComponent(shortFilename, contents, stat);
try {
for (let i = 0, len = component.importDeclaration.length; i < len; i++) {
const source = String(component.importDeclaration[i].source.value);
if (source) {
const nextFilename = utils.resolveFile(source, filename);
if (nextFilename) {
component.addChildReport(this.getImportDeclarationTree(nextFilename, isTest));
}
}
}
}
}
catch (err) {
console.error(`Something went wrong with reading ${filename}`);
console.error(err.message);
}
return component.getFileReport(isTest);
};
this._counter = new FileCounter_1.FileCounter();
}
catch (err) {
console.error(`Something went wrong with reading ${filename}`);
console.error(err.message);
get counter() {
return this._counter;
}
return result;
};
exports.counter = counter;
exports.getImportDeclarationTree = getImportDeclarationTree;
}
exports.Analyzer = Analyzer;
});

@@ -211,7 +287,7 @@

const { renderFile } = require$$0__default$1['default'];
const { renderFile } = require$$0__default['default'];
const projectRoot = path__default['default'].resolve(__dirname, '..');
const projectRoot = path_1__default['default'].resolve(__dirname, '..');
const startServer = (port, json) => {

@@ -263,5 +339,5 @@ const HOST = '127.0.0.1';

};
const { getImportDeclarationTree, counter } = utils;
const { Analyzer } = Analyzer_1;
const { startServer } = server;
const { writeFileSync } = require$$1__default['default'];
const { writeFileSync } = fs_1__default['default'];

@@ -277,3 +353,3 @@

function writeFileExtra(filename, data) {
mkdirp__default['default'](path__default['default'].dirname(filename)).then(() => {
mkdirp__default['default'](path_1__default['default'].dirname(filename)).then(() => {
writeFileSync(filename, data);

@@ -296,2 +372,3 @@ }).catch((err) => {

}
const analyzer = new Analyzer();
const entries = yield globby__default['default']([argv.dir], {

@@ -305,3 +382,3 @@ expandDirectories: {

const entryFile = entries[i];
const children = getImportDeclarationTree(entryFile);
const children = analyzer.getImportDeclarationTree(entryFile);
entriesData.push(children);

@@ -311,7 +388,7 @@ }

entries: entriesData,
count: counter.count,
count: analyzer.counter.count,
};
if (argv.format === FORMAT.BOTH) {
startServer(argv.port, result);
writeFileExtra(path__default['default'].resolve(process.cwd(), `${argv.out}/result.json`), JSON.stringify(result, null, 4));
writeFileExtra(path_1__default['default'].resolve(process.cwd(), `${argv.out}/result.json`), JSON.stringify(result, null, 4));
}

@@ -322,3 +399,3 @@ else if (argv.format === FORMAT.BROWSER) {

else if (argv.format === FORMAT.JSON) {
writeFileExtra(path__default['default'].resolve(process.cwd(), `${argv.out}/result.json`), JSON.stringify(result, null, 4));
writeFileExtra(path_1__default['default'].resolve(process.cwd(), `${argv.out}/result.json`), JSON.stringify(result, null, 4));
}

@@ -325,0 +402,0 @@ console.log('finished analyzing.');

{
"name": "@tkskto/vue-component-analyzer",
"version": "0.1.3",
"version": "0.1.4",
"description": "Analyze dependency tree for Vue.js SFC (Single File Component)",

@@ -11,3 +11,4 @@ "main": "dist/index.js",

"scripts": {
"build": "tsc -p tsconfig.json && rollup --config",
"dev": "tsc -p src/server/tsconfig.json -w",
"build": "tsc -p src/server/tsconfig.json && rollup --config",
"lint": "eslint -c .eslintrc.json src",

@@ -14,0 +15,0 @@ "cover": "npm run cover:test && npm run cover:report",

@@ -9,2 +9,8 @@ # vue-component-analyzer

## Why?
When you try to change the behavior of components, it will help you to investigate the influence range. Because it is hard to know where the component is used.
When you join a new big project using Vue.js, it will help you to understand dependencies.
## installation and usage

@@ -35,3 +41,3 @@

- `--dir` : analyze target directory. default is `src`.
- `-f` or `--format` : report type. choose one from [browser | json | both]. default is `browser'.
- `-f` or `--format` : report type. choose one from [browser | json | both]. default is `browser`.
- `-o` or `--out` : output directory. JSON file will output here.

@@ -38,0 +44,0 @@ - `-p` or `--port` : select a port number for the local server.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc