🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@oclif/plugin-command-snapshot

Package Overview
Dependencies
Maintainers
7
Versions
163
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@oclif/plugin-command-snapshot - npm Package Compare versions

Comparing version
3.0.0
to
3.1.0
+13
-0
CHANGELOG.md

@@ -5,2 +5,15 @@ # Changelog

## [3.1.0](https://github.com/oclif/plugin-command-snapshot/compare/v3.0.0...v3.1.0) (2021-10-08)
### Features
* generate schema for hooks ([266b832](https://github.com/oclif/plugin-command-snapshot/commit/266b83242fab1961b036998119791b999a08ee19))
### Bug Fixes
* ignore hooks with no return type ([070ed41](https://github.com/oclif/plugin-command-snapshot/commit/070ed41902268d48034fdaa2b96f9a4a54eefd2c))
* schema:compare with hooks ([508549a](https://github.com/oclif/plugin-command-snapshot/commit/508549a372e56b3d79dec970e62477d9905dec13))
### [2.2.2](https://github.com/oclif/plugin-command-snapshot/compare/v2.2.1...v2.2.2) (2021-06-30)

@@ -7,0 +20,0 @@

+16
-5

@@ -23,3 +23,5 @@ "use strict";

const existingSchema = this.readExistingSchema(flags.filepath);
const latestSchema = await this.generateLatestSchema();
const latestSchema = (await this.generateLatestSchema());
this.debug('existingSchema', existingSchema);
this.debug('latestSchema', latestSchema);
const changes = just_diff_1.diff(latestSchema, existingSchema);

@@ -48,3 +50,3 @@ if (changes.length === 0) {

case 'remove':
humandReadableChanges[commandId].push(`${chalk_1.underline(readablePath)} was ${chalk_1.cyan('removed')} from latest schema`);
humandReadableChanges[commandId].push(`${chalk_1.underline(readablePath)} was ${chalk_1.cyan('not found')} in latest schema`);
break;

@@ -73,4 +75,7 @@ default:

const schemasDir = folderIsVersioned ? path.join(filePath, semver.rsort(contents)[0] || '') : filePath;
const schemaFiles = fs.readdirSync(schemasDir).map(f => path.join(schemasDir, f)).filter(f => !fs.statSync(f).isDirectory());
let schemas = {};
const schemaFiles = generate_1.getAllFiles(schemasDir, '.json');
let schemas = {
commands: {},
hooks: {},
};
if (schemaFiles.length === 1 && schemaFiles[0].endsWith('schema.json')) {

@@ -82,3 +87,9 @@ schemas = JSON.parse(fs.readFileSync(schemaFiles[0]).toString('utf8'));

const schema = JSON.parse(fs.readFileSync(file).toString('utf8'));
schemas[path.basename(file.replace(/-/g, ':')).replace('.json', '')] = schema;
const key = path.basename(file.replace(/-/g, ':')).replace('.json', '');
if (file.split(path.sep).includes('hooks')) {
schemas.hooks[key] = schema;
}
else {
schemas.commands[key] = schema;
}
}

@@ -85,0 +96,0 @@ }

@@ -6,3 +6,8 @@ import { Schema } from 'ts-json-schema-generator';

};
export declare type Schemas = {
commands: SchemasMap;
hooks: SchemasMap;
};
export declare type GenerateResponse = string[];
export declare function getAllFiles(dirPath: string, ext: string, allFiles?: string[]): string[];
export declare class SchemaGenerator {

@@ -13,7 +18,22 @@ private base;

constructor(base: SnapshotCommand, ignorevoid?: boolean);
generate(): Promise<SchemasMap>;
generate(): Promise<Schemas>;
private generateSchema;
private getAllCmdFiles;
private parseFile;
private getAllHookFiles;
/**
* Use regex to find the typescript type being returned by the command's
* `run` method.
* @param file the file to parse
* @returns Returns the name of the return type and the command id.
*/
private parseCmdFile;
/**
* Use regex to find the typescript type being returned by the hook
* @param file the file to parse
* @returns Returns the name of the return type and the hook id.
*/
private parseHookFile;
private validateReturnType;
private determineCommandId;
private getDirs;
}

@@ -20,0 +40,0 @@ export default class SchemaGenerate extends SnapshotCommand {

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SchemaGenerator = void 0;
exports.SchemaGenerator = exports.getAllFiles = void 0;
const path = require("path");

@@ -10,2 +10,20 @@ const fs = require("fs");

const chalk_1 = require("chalk");
function getAllFiles(dirPath, ext, allFiles = []) {
let files = [];
try {
files = fs.readdirSync(dirPath);
}
catch (_a) { }
files.forEach(file => {
const fPath = path.join(dirPath, file);
if (fs.statSync(fPath).isDirectory()) {
allFiles = getAllFiles(fPath, ext, allFiles);
}
else if (file.endsWith(ext)) {
allFiles.push(fPath);
}
});
return allFiles;
}
exports.getAllFiles = getAllFiles;
class SchemaGenerator {

@@ -23,41 +41,55 @@ constructor(base, ignorevoid = true) {

}
const schemas = {};
const cmdSchemas = {};
for (const file of this.getAllCmdFiles()) {
const { returnType, commandId } = this.parseFile(file);
const { returnType, commandId } = this.parseCmdFile(file);
if (this.ignorevoid && returnType === 'void')
continue;
try {
const config = {
path: file,
type: returnType,
skipTypeCheck: true,
};
const schema = ts_json_schema_generator_1.createGenerator(config).createSchema(config.type);
schemas[commandId] = schema;
cmdSchemas[commandId] = this.generateSchema(returnType, file);
}
const hookSchemas = {};
for (const file of this.getAllHookFiles()) {
const { returnType, hookId } = this.parseHookFile(file);
if (returnType && hookId) {
hookSchemas[hookId] = this.generateSchema(returnType, file);
}
catch (error) {
if (error.message.toLowerCase().includes('no root type')) {
throw new Error(`Schema generator could not find the ${chalk_1.red(returnType)} type. Please make sure that ${chalk_1.red(returnType)} is exported.`);
}
else {
throw error;
}
}
}
return schemas;
return { commands: cmdSchemas, hooks: hookSchemas };
}
getAllCmdFiles(dirPath = path.join(this.base.config.root, 'src', 'commands'), allFiles = []) {
const files = fs.readdirSync(dirPath);
files.forEach(file => {
const fPath = path.join(dirPath, file);
if (fs.statSync(fPath).isDirectory()) {
allFiles = this.getAllCmdFiles(fPath, allFiles);
generateSchema(returnType, file) {
try {
const config = {
path: file,
type: returnType,
skipTypeCheck: true,
};
return ts_json_schema_generator_1.createGenerator(config).createSchema(config.type);
}
catch (error) {
if (error.message.toLowerCase().includes('no root type')) {
throw new Error(`Schema generator could not find the ${chalk_1.red(returnType)} type. Please make sure that ${chalk_1.red(returnType)} is exported.`);
}
else if (file.endsWith('ts')) {
allFiles.push(fPath);
else {
throw error;
}
});
return allFiles;
}
}
parseFile(file) {
getAllCmdFiles() {
const { rootDir } = this.getDirs();
return getAllFiles(path.join(rootDir, 'commands'), '.ts');
}
getAllHookFiles() {
var _a, _b;
const hookFiles = Object.values((_b = (_a = this.base.config.pjson.oclif) === null || _a === void 0 ? void 0 : _a.hooks) !== null && _b !== void 0 ? _b : {}).reduce((x, y) => {
return Array.isArray(y) ? x.concat(y) : x.concat([y]);
}, []);
const { rootDir, outDir } = this.getDirs();
return hookFiles.map(h => `${path.resolve(h)}.ts`.replace(outDir, rootDir));
}
/**
* Use regex to find the typescript type being returned by the command's
* `run` method.
* @param file the file to parse
* @returns Returns the name of the return type and the command id.
*/
parseCmdFile(file) {
const returnTypeRegex = /(?<=async\srun\(\):\sPromise<)(.*?)(>*)(?=>)/g;

@@ -76,2 +108,28 @@ const contents = fs.readFileSync(file, 'utf8');

}
/**
* Use regex to find the typescript type being returned by the hook
* @param file the file to parse
* @returns Returns the name of the return type and the hook id.
*/
parseHookFile(file) {
var _a, _b;
const returnTypeRegex = /(?<=const\shook:\s(.*?)<)(.*?)(>*)(?=>)/g;
const contents = fs.readFileSync(file, 'utf8');
const [returnType] = returnTypeRegex.exec(contents) || [];
if (!returnType) {
return { returnType: null, hookId: null };
}
const hooks = (_b = (_a = this.base.config.pjson.oclif) === null || _a === void 0 ? void 0 : _a.hooks) !== null && _b !== void 0 ? _b : {};
const hookId = Object.keys(hooks).find(key => {
const hookFiles = (Array.isArray(hooks[key]) ? hooks[key] : [hooks[key]]);
const hookFileNames = hookFiles.map(f => path.basename(f).split('.')[0]);
const currentFileName = path.basename(file).split('.')[0];
return hookFileNames.includes(currentFileName);
});
if (!hookId) {
return { returnType: null, hookId: null };
}
this.validateReturnType(returnType, hookId);
return { returnType, hookId };
}
validateReturnType(returnType, commandId) {

@@ -95,2 +153,20 @@ const notAllowed = this.ignorevoid ? ['any', 'unknown'] : ['any', 'unknown', 'void'];

}
getDirs() {
const dirs = {
rootDir: path.join(this.base.config.root, 'src'),
outDir: path.join(this.base.config.root, 'lib'),
};
try {
const tsConfig = JSON.parse(fs.readFileSync(path.join(this.base.config.root, 'tsconfig.json'), 'utf-8'));
if (tsConfig.compilerOptions.rootDir) {
dirs.rootDir = path.join(this.base.config.root, tsConfig.compilerOptions.rootDir);
}
if (tsConfig.compilerOptions.outDir) {
dirs.outDir = path.join(this.base.config.root, tsConfig.compilerOptions.outDir);
}
return dirs;
}
catch (_a) { }
return dirs;
}
}

@@ -113,3 +189,3 @@ exports.SchemaGenerator = SchemaGenerator;

else {
for (const [cmdId, schema] of Object.entries(schemas)) {
for (const [cmdId, schema] of Object.entries(schemas.commands)) {
const fileName = `${cmdId.replace(/:/g, '-')}.json`;

@@ -121,2 +197,13 @@ const filePath = path.join(directory, fileName);

}
if (Object.values(schemas.hooks).length > 0) {
const hooksDir = path.join(directory, 'hooks');
fs.mkdirSync(hooksDir, { recursive: true });
for (const [hookId, schema] of Object.entries(schemas.hooks)) {
const fileName = `${hookId.replace(/:/g, '-')}.json`;
const filePath = path.join(hooksDir, fileName);
fs.writeFileSync(filePath, JSON.stringify(schema, null, 2));
this.log(`Generated JSON schema file "${filePath}"`);
files.push(filePath);
}
}
}

@@ -123,0 +210,0 @@ return files;

@@ -1,1 +0,1 @@

{"version":"3.0.0","commands":{"schema:compare":{"id":"schema:compare","strict":true,"pluginName":"@oclif/plugin-command-snapshot","pluginAlias":"@oclif/plugin-command-snapshot","pluginType":"core","aliases":[],"flags":{"filepath":{"name":"filepath","type":"option","description":"path of the generated snapshot file","multiple":false,"default":"./schemas"}},"args":[]},"schema:generate":{"id":"schema:generate","strict":true,"pluginName":"@oclif/plugin-command-snapshot","pluginAlias":"@oclif/plugin-command-snapshot","pluginType":"core","aliases":[],"flags":{"filepath":{"name":"filepath","type":"option","description":"directory to save the generated schema files; can use \"{version}\" to insert the current CLI/plugin version","multiple":false,"default":"./schemas"},"singlefile":{"name":"singlefile","type":"boolean","description":"put generated schema into a single file","allowNo":false},"ignorevoid":{"name":"ignorevoid","type":"boolean","description":"ignore commands that return void","allowNo":false}},"args":[]},"snapshot:compare":{"id":"snapshot:compare","strict":true,"pluginName":"@oclif/plugin-command-snapshot","pluginAlias":"@oclif/plugin-command-snapshot","pluginType":"core","aliases":[],"flags":{"filepath":{"name":"filepath","type":"option","description":"path of the generated snapshot file","multiple":false,"default":"./command-snapshot.json"}},"args":[]},"snapshot:generate":{"id":"snapshot:generate","strict":true,"pluginName":"@oclif/plugin-command-snapshot","pluginAlias":"@oclif/plugin-command-snapshot","pluginType":"core","aliases":[],"flags":{"filepath":{"name":"filepath","type":"option","description":"path to save the generated snapshot file; can use \"{version}\" to replace the current CLI/plugin version","multiple":false,"default":"./command-snapshot.json"}},"args":[]}}}
{"version":"3.1.0","commands":{"schema:compare":{"id":"schema:compare","strict":true,"pluginName":"@oclif/plugin-command-snapshot","pluginAlias":"@oclif/plugin-command-snapshot","pluginType":"core","aliases":[],"flags":{"filepath":{"name":"filepath","type":"option","description":"path of the generated snapshot file","multiple":false,"default":"./schemas"}},"args":[]},"schema:generate":{"id":"schema:generate","strict":true,"pluginName":"@oclif/plugin-command-snapshot","pluginAlias":"@oclif/plugin-command-snapshot","pluginType":"core","aliases":[],"flags":{"filepath":{"name":"filepath","type":"option","description":"directory to save the generated schema files; can use \"{version}\" to insert the current CLI/plugin version","multiple":false,"default":"./schemas"},"singlefile":{"name":"singlefile","type":"boolean","description":"put generated schema into a single file","allowNo":false},"ignorevoid":{"name":"ignorevoid","type":"boolean","description":"ignore commands that return void","allowNo":false}},"args":[]},"snapshot:compare":{"id":"snapshot:compare","strict":true,"pluginName":"@oclif/plugin-command-snapshot","pluginAlias":"@oclif/plugin-command-snapshot","pluginType":"core","aliases":[],"flags":{"filepath":{"name":"filepath","type":"option","description":"path of the generated snapshot file","multiple":false,"default":"./command-snapshot.json"}},"args":[]},"snapshot:generate":{"id":"snapshot:generate","strict":true,"pluginName":"@oclif/plugin-command-snapshot","pluginAlias":"@oclif/plugin-command-snapshot","pluginType":"core","aliases":[],"flags":{"filepath":{"name":"filepath","type":"option","description":"path to save the generated snapshot file; can use \"{version}\" to replace the current CLI/plugin version","multiple":false,"default":"./command-snapshot.json"}},"args":[]}}}
{
"name": "@oclif/plugin-command-snapshot",
"description": "generates and compares OCLIF plugins snapshot files",
"version": "3.0.0",
"version": "3.1.0",
"author": "Ramyasri @nramyasri-sf",
"bugs": "https://github.com/oclif/plugin-command-snapshot/issues",
"dependencies": {
"@oclif/core": "^0.5.39",
"@oclif/core": "^1.0.1",
"chalk": "^4.1.1",

@@ -10,0 +10,0 @@ "just-diff": "^3.1.1",

Sorry, the diff of this file is too big to display