@oclif/plugin-command-snapshot
Advanced tools
| import { Operation } from 'just-diff'; | ||
| import { flags } from '@oclif/command'; | ||
| import { SnapshotCommand } from '../../snapshot-command'; | ||
| export declare type SchemaComparison = Array<{ | ||
| op: Operation; | ||
| path: (string | number)[]; | ||
| value: any; | ||
| }>; | ||
| export default class SchemaCompare extends SnapshotCommand { | ||
| static flags: { | ||
| filepath: flags.IOptionFlag<string>; | ||
| }; | ||
| run(): Promise<SchemaComparison>; | ||
| private readExistingSchema; | ||
| private generateLatestSchema; | ||
| } |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| const path = require("path"); | ||
| const fs = require("fs"); | ||
| const semver = require("semver"); | ||
| const _ = require("lodash"); | ||
| const just_diff_1 = require("just-diff"); | ||
| const command_1 = require("@oclif/command"); | ||
| const snapshot_command_1 = require("../../snapshot-command"); | ||
| const generate_1 = require("./generate"); | ||
| const chalk_1 = require("chalk"); | ||
| class SchemaCompare extends snapshot_command_1.SnapshotCommand { | ||
| async run() { | ||
| const { flags } = this.parse(SchemaCompare); | ||
| const existingSchema = this.readExistingSchema(flags.filepath); | ||
| const latestSchema = await this.generateLatestSchema(); | ||
| const changes = just_diff_1.diff(latestSchema, existingSchema); | ||
| if (changes.length === 0) { | ||
| this.log('No changes have been detected.'); | ||
| return []; | ||
| } | ||
| const humandReadableChanges = {}; | ||
| for (const change of changes) { | ||
| const objPath = change.path.join('.'); | ||
| const existing = _.get(existingSchema, objPath); | ||
| const latest = _.get(latestSchema, objPath); | ||
| const [commandId] = objPath.split('.definitions'); | ||
| const readablePath = objPath.replace(`${commandId}.`, ''); | ||
| if (!humandReadableChanges[commandId]) { | ||
| humandReadableChanges[commandId] = []; | ||
| } | ||
| switch (change.op) { | ||
| case 'replace': | ||
| humandReadableChanges[commandId].push(`${chalk_1.underline(readablePath)} was changed from ${chalk_1.cyan(existing)} to ${chalk_1.cyan(latest)}`); | ||
| break; | ||
| case 'add': | ||
| humandReadableChanges[commandId].push(`${chalk_1.underline(readablePath)} was ${chalk_1.cyan('added')} to latest schema`); | ||
| break; | ||
| case 'remove': | ||
| humandReadableChanges[commandId].push(`${chalk_1.underline(readablePath)} was ${chalk_1.cyan('removed')} from latest schema`); | ||
| break; | ||
| default: | ||
| break; | ||
| } | ||
| } | ||
| this.log(); | ||
| this.log(chalk_1.bold(chalk_1.red('Found the following schema changes:'))); | ||
| for (const [commandId, changes] of Object.entries(humandReadableChanges)) { | ||
| this.log(); | ||
| this.log(chalk_1.bold(commandId)); | ||
| for (const change of changes) { | ||
| this.log(` - ${change}`); | ||
| } | ||
| } | ||
| this.log(); | ||
| this.log('If intended, please update the schema file(s) and run again.'); | ||
| process.exitCode = 1; | ||
| return changes; | ||
| } | ||
| readExistingSchema(filePath) { | ||
| const contents = fs.readdirSync(filePath); | ||
| const folderIsVersioned = contents.every(c => semver.valid(c)); | ||
| 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 = {}; | ||
| if (schemaFiles.length === 1 && schemaFiles[0].endsWith('schema.json')) { | ||
| schemas = JSON.parse(fs.readFileSync(schemaFiles[0]).toString('utf8')); | ||
| } | ||
| else { | ||
| for (const file of schemaFiles) { | ||
| const schema = JSON.parse(fs.readFileSync(file).toString('utf8')); | ||
| schemas[path.basename(file.replace(/-/g, ':')).replace('.json', '')] = schema; | ||
| } | ||
| } | ||
| return schemas; | ||
| } | ||
| async generateLatestSchema() { | ||
| const generator = new generate_1.SchemaGenerator(this); | ||
| return generator.generate(); | ||
| } | ||
| } | ||
| exports.default = SchemaCompare; | ||
| SchemaCompare.flags = { | ||
| filepath: command_1.flags.string({ | ||
| description: 'path of the generated snapshot file', | ||
| default: './schemas', | ||
| }), | ||
| }; |
| import { flags } from '@oclif/command'; | ||
| import { Schema } from 'ts-json-schema-generator'; | ||
| import { SnapshotCommand } from '../../snapshot-command'; | ||
| export declare type SchemasMap = { | ||
| [key: string]: Schema; | ||
| }; | ||
| export declare type GenerateResponse = string[]; | ||
| export declare class SchemaGenerator { | ||
| private base; | ||
| private classToId; | ||
| constructor(base: SnapshotCommand); | ||
| generate(): Promise<SchemasMap>; | ||
| private getAllCmdFiles; | ||
| private parseFile; | ||
| private validateReturnType; | ||
| private determineCommandId; | ||
| } | ||
| export default class SchemaGenerate extends SnapshotCommand { | ||
| static flags: { | ||
| filepath: flags.IOptionFlag<string>; | ||
| singlefile: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>; | ||
| }; | ||
| run(): Promise<GenerateResponse>; | ||
| } |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.SchemaGenerator = void 0; | ||
| const path = require("path"); | ||
| const fs = require("fs"); | ||
| const command_1 = require("@oclif/command"); | ||
| const ts_json_schema_generator_1 = require("ts-json-schema-generator"); | ||
| const snapshot_command_1 = require("../../snapshot-command"); | ||
| const chalk_1 = require("chalk"); | ||
| class SchemaGenerator { | ||
| constructor(base) { | ||
| this.base = base; | ||
| this.classToId = {}; | ||
| } | ||
| async generate() { | ||
| for (const cmd of this.base.commands) { | ||
| // eslint-disable-next-line no-await-in-loop | ||
| const loadedCmd = await cmd.load(); // commands are loaded async in oclif/core | ||
| this.classToId[loadedCmd.name] = loadedCmd.id; | ||
| } | ||
| const schemas = {}; | ||
| for (const file of this.getAllCmdFiles()) { | ||
| const { returnType, commandId } = this.parseFile(file); | ||
| try { | ||
| const config = { | ||
| path: file, | ||
| type: returnType, | ||
| skipTypeCheck: true, | ||
| }; | ||
| const schema = ts_json_schema_generator_1.createGenerator(config).createSchema(config.type); | ||
| schemas[commandId] = schema; | ||
| } | ||
| 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; | ||
| } | ||
| 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); | ||
| } | ||
| else if (file.endsWith('ts')) { | ||
| allFiles.push(fPath); | ||
| } | ||
| }); | ||
| return allFiles; | ||
| } | ||
| parseFile(file) { | ||
| const returnTypeRegex = /(?<=async\srun\(\):\sPromise<)(.*?)(>*)(?=>)/g; | ||
| const contents = fs.readFileSync(file, 'utf8'); | ||
| const [returnType] = returnTypeRegex.exec(contents) || []; | ||
| if (!returnType) { | ||
| throw new Error(`No return type found for file ${file}`); | ||
| } | ||
| this.validateReturnType(returnType); | ||
| const commandId = this.determineCommandId(contents); | ||
| if (!commandId) { | ||
| throw new Error(`No commandId found for file ${file}`); | ||
| } | ||
| return { returnType, commandId }; | ||
| } | ||
| validateReturnType(returnType) { | ||
| const notAllowed = ['any', 'unknown']; | ||
| const vaugeTypes = ['JsonMap', 'JsonCollection', 'AnyJson']; | ||
| if (notAllowed.includes(returnType)) { | ||
| throw new Error(`${returnType} is not allowed. Please use a more specific type.`); | ||
| } | ||
| else if (vaugeTypes.includes(returnType)) { | ||
| throw new Error(`${returnType} is too vauge. Please use a more specific type.`); | ||
| } | ||
| } | ||
| determineCommandId(contents) { | ||
| for (const [className, cmdId] of Object.entries(this.classToId)) { | ||
| const regex = new RegExp(` class ${className} `, 'g'); | ||
| if (regex.test(contents)) { | ||
| return cmdId; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| exports.SchemaGenerator = SchemaGenerator; | ||
| class SchemaGenerate extends snapshot_command_1.SnapshotCommand { | ||
| async run() { | ||
| const { flags } = this.parse(SchemaGenerate); | ||
| const generator = new SchemaGenerator(this); | ||
| const schemas = await generator.generate(); | ||
| const directory = flags.filepath.replace('{version}', this.config.version); | ||
| fs.mkdirSync(directory, { recursive: true }); | ||
| const files = []; | ||
| if (flags.singlefile) { | ||
| const filePath = path.join(directory, 'schema.json'); | ||
| fs.writeFileSync(filePath, JSON.stringify(schemas, null, 2)); | ||
| this.log(`Generated JSON schema file "${filePath}"`); | ||
| files.push(filePath); | ||
| } | ||
| else { | ||
| for (const [cmdId, schema] of Object.entries(schemas)) { | ||
| const fileName = `${cmdId.replace(/:/g, '-')}.json`; | ||
| const filePath = path.join(directory, fileName); | ||
| fs.writeFileSync(filePath, JSON.stringify(schema, null, 2)); | ||
| this.log(`Generated JSON schema file "${filePath}"`); | ||
| files.push(filePath); | ||
| } | ||
| } | ||
| return files; | ||
| } | ||
| } | ||
| exports.default = SchemaGenerate; | ||
| SchemaGenerate.flags = { | ||
| filepath: command_1.flags.string({ | ||
| description: 'directory to save the generated schema files; can use "{version}" to insert the current CLI/plugin version', | ||
| default: './schemas', | ||
| }), | ||
| singlefile: command_1.flags.boolean({ | ||
| description: 'put generated schema into a single file', | ||
| default: false, | ||
| }), | ||
| }; |
| import { flags } from '@oclif/command'; | ||
| import { SnapshotCommand, SnapshotEntry } from '../../snapshot-command'; | ||
| interface Change { | ||
| name: string; | ||
| removed?: boolean; | ||
| added?: boolean; | ||
| } | ||
| declare type CommandChange = { | ||
| plugin: string; | ||
| flags: Change[]; | ||
| } & Change; | ||
| export declare type CompareResponse = { | ||
| addedCommands?: string[]; | ||
| removedCommands?: string[]; | ||
| removedFlags?: string[]; | ||
| diffCommands?: CommandChange[]; | ||
| }; | ||
| export default class Compare extends SnapshotCommand { | ||
| static flags: { | ||
| filepath: flags.IOptionFlag<string>; | ||
| }; | ||
| /** | ||
| * Compare a snapshot with the current commands | ||
| * @param {CommandChange[]} initialCommands Command list from the snapshot | ||
| * @param {CommandChange[]} updatedCommands Command list from runtime | ||
| * @returns all the command differences | ||
| */ | ||
| compareSnapshot(initialCommands: SnapshotEntry[], updatedCommands: CommandChange[]): Promise<CompareResponse>; | ||
| /** | ||
| * Compares a flag snapshot with the current command's flags | ||
| * @param {string[]} initialFlags Flag list from the snapshot | ||
| * @param {string[]} updatedFlags Flag list from runtime | ||
| * @param {string} initialCommand Command the flags belong to | ||
| * @return {boolean} true if no changes, false otherwise | ||
| */ | ||
| diffCommandFlags(initialFlags: string[], updatedFlags: Change[]): { | ||
| addedFlags: string[]; | ||
| removedFlags: string[]; | ||
| updatedFlags: Change[]; | ||
| changedFlags: Change[]; | ||
| }; | ||
| get changed(): CommandChange[]; | ||
| run(): Promise<CompareResponse>; | ||
| } | ||
| export {}; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| const command_1 = require("@oclif/command"); | ||
| const _ = require("lodash"); | ||
| const fs = require("fs"); | ||
| const os_1 = require("os"); | ||
| const snapshot_command_1 = require("../../snapshot-command"); | ||
| const chalk = require("chalk"); | ||
| class Compare extends snapshot_command_1.SnapshotCommand { | ||
| /** | ||
| * Compare a snapshot with the current commands | ||
| * @param {CommandChange[]} initialCommands Command list from the snapshot | ||
| * @param {CommandChange[]} updatedCommands Command list from runtime | ||
| * @returns all the command differences | ||
| */ | ||
| async compareSnapshot(initialCommands, updatedCommands) { | ||
| const removedCommands = []; | ||
| const diffCommands = []; | ||
| initialCommands.forEach(initialCommand => { | ||
| const updatedCommand = updatedCommands.find(updatedCommand => { | ||
| // Protect against old snapshot files that don't have the plugin entry filled out. | ||
| const samePlugin = initialCommand.plugin ? initialCommand.plugin === updatedCommand.plugin : true; | ||
| return initialCommand.command === updatedCommand.name && samePlugin; | ||
| }); | ||
| if (updatedCommand) { | ||
| const { changedFlags } = this.diffCommandFlags(initialCommand.flags, updatedCommand.flags); | ||
| if (changedFlags.length > 0) { | ||
| diffCommands.push(updatedCommand); | ||
| } | ||
| } | ||
| else { | ||
| removedCommands.push(initialCommand.command); | ||
| } | ||
| }); | ||
| const initialCommandNames = initialCommands.map(initialCommand => initialCommand.command); | ||
| const updatedCommandNames = updatedCommands.map(updatedCommand => updatedCommand.name); | ||
| const addedCommands = _.difference(updatedCommandNames, initialCommandNames); | ||
| if (removedCommands.length === 0 && addedCommands.length === 0 && diffCommands.length === 0) { | ||
| this.log('No changes have been detected.'); | ||
| return {}; | ||
| } | ||
| // Fail the process since there are changes to the snapshot file | ||
| process.exitCode = 1; | ||
| this.log(`The following commands and flags have modified: (${chalk.green('+')} added, ${chalk.red('-')} removed)${os_1.EOL}`); | ||
| removedCommands.forEach(command => { | ||
| this.log(chalk.red(`\t-${command}`)); | ||
| }); | ||
| addedCommands.forEach(command => { | ||
| this.log(chalk.green(`\t+${command}`)); | ||
| }); | ||
| const removedFlags = []; | ||
| if (diffCommands.length > 0) { | ||
| diffCommands.forEach(command => { | ||
| this.log(`\t ${command.name}`); | ||
| command.flags.forEach(flag => { | ||
| if (flag.added || flag.removed) { | ||
| const color = flag.added ? chalk.green : chalk.red; | ||
| this.log(color(`\t\t${flag.added ? '+' : '-'}${flag.name}`)); | ||
| } | ||
| if (flag.removed) | ||
| removedFlags.push(); | ||
| }); | ||
| }); | ||
| } | ||
| this.log(`${os_1.EOL}Command or flag differences detected. If intended, please update the snapshot file and run again.`); | ||
| // Check if existent commands have been deleted | ||
| if (removedCommands.length > 0 || removedFlags.length > 0) { | ||
| this.log(chalk.red(`${os_1.EOL}Since there are deletions, a major version bump is required.`)); | ||
| } | ||
| return { addedCommands, removedCommands, removedFlags, diffCommands }; | ||
| } | ||
| /** | ||
| * Compares a flag snapshot with the current command's flags | ||
| * @param {string[]} initialFlags Flag list from the snapshot | ||
| * @param {string[]} updatedFlags Flag list from runtime | ||
| * @param {string} initialCommand Command the flags belong to | ||
| * @return {boolean} true if no changes, false otherwise | ||
| */ | ||
| diffCommandFlags(initialFlags, updatedFlags) { | ||
| const updatedFlagNames = updatedFlags.map(updatedFlag => updatedFlag.name); | ||
| const addedFlags = _.difference(updatedFlagNames, initialFlags); | ||
| const removedFlags = _.difference(initialFlags, updatedFlagNames); | ||
| const changedFlags = []; | ||
| updatedFlags.forEach(updatedFlag => { | ||
| if (addedFlags.includes(updatedFlag.name)) { | ||
| updatedFlag.added = true; | ||
| changedFlags.push(updatedFlag); | ||
| } | ||
| }); | ||
| removedFlags.forEach(removedFlag => { | ||
| changedFlags.push({ name: removedFlag, removed: true }); | ||
| // The removed flags in not included in the updated flags, but we want it to | ||
| // so it shows removed. | ||
| updatedFlags.push({ name: removedFlag, removed: true }); | ||
| }); | ||
| return { addedFlags, removedFlags, updatedFlags, changedFlags }; | ||
| } | ||
| get changed() { | ||
| return this.commands.map(command => { | ||
| return { | ||
| name: command.id, | ||
| plugin: command.pluginName || '', | ||
| flags: Object.entries(command.flags).map(flagName => ({ name: flagName[0] })), | ||
| }; | ||
| }); | ||
| } | ||
| async run() { | ||
| const { flags } = this.parse(Compare); | ||
| const oldCommandFlags = JSON.parse(fs.readFileSync(flags.filepath).toString('utf8')); | ||
| const resultnewCommandFlags = this.changed; | ||
| return this.compareSnapshot(oldCommandFlags, resultnewCommandFlags); | ||
| } | ||
| } | ||
| exports.default = Compare; | ||
| Compare.flags = { | ||
| filepath: command_1.flags.string({ | ||
| description: 'path of the generated snapshot file', | ||
| default: './command-snapshot.json', | ||
| }), | ||
| }; |
| import { flags } from '@oclif/command'; | ||
| import { SnapshotCommand } from '../../snapshot-command'; | ||
| export declare type Snapshots = { | ||
| command: string; | ||
| plugin: string; | ||
| flags: string[]; | ||
| }[]; | ||
| export default class Generate extends SnapshotCommand { | ||
| static flags: { | ||
| filepath: flags.IOptionFlag<string>; | ||
| }; | ||
| run(): Promise<Snapshots>; | ||
| } |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| const command_1 = require("@oclif/command"); | ||
| const fs = require("fs"); | ||
| const snapshot_command_1 = require("../../snapshot-command"); | ||
| class Generate extends snapshot_command_1.SnapshotCommand { | ||
| async run() { | ||
| const numberOfSpaceChar = 4; | ||
| const { flags } = this.parse(Generate); | ||
| const resultCommands = this.entries; | ||
| const filePath = flags.filepath.replace('{version}', this.config.version); | ||
| fs.writeFileSync(filePath, JSON.stringify(resultCommands, null, numberOfSpaceChar)); | ||
| this.log(`Generated snapshot file "${filePath}"`); | ||
| return resultCommands; | ||
| } | ||
| } | ||
| exports.default = Generate; | ||
| Generate.flags = { | ||
| filepath: command_1.flags.string({ | ||
| description: 'path to save the generated snapshot file; can use "{version}" to replace the current CLI/plugin version', | ||
| default: './command-snapshot.json', | ||
| }), | ||
| }; |
| declare const _default: {}; | ||
| export default _default; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.default = {}; |
| import { Command } from '@oclif/command'; | ||
| export declare type SnapshotEntry = { | ||
| command: string; | ||
| plugin: string; | ||
| flags: string[]; | ||
| }; | ||
| export declare abstract class SnapshotCommand extends Command { | ||
| get commands(): import("@oclif/config").Command.Plugin[]; | ||
| get entries(): SnapshotEntry[]; | ||
| } |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.SnapshotCommand = void 0; | ||
| const command_1 = require("@oclif/command"); | ||
| const _ = require("lodash"); | ||
| class SnapshotCommand extends command_1.Command { | ||
| get commands() { | ||
| var _a; | ||
| const devPlugins = (_a = this.config.pjson.oclif.devPlugins) !== null && _a !== void 0 ? _a : []; | ||
| const commands = this.config.commands | ||
| // Ignore dev plugins | ||
| .filter(command => { var _a; return !devPlugins.includes((_a = command.pluginName) !== null && _a !== void 0 ? _a : ''); }); | ||
| return _.sortBy(commands, 'id'); | ||
| } | ||
| get entries() { | ||
| return this.commands.map(command => { | ||
| return { | ||
| command: command.id, | ||
| plugin: command.pluginName, | ||
| flags: Object.keys(command.flags).sort(), | ||
| }; | ||
| }); | ||
| } | ||
| } | ||
| exports.SnapshotCommand = SnapshotCommand; |
+7
-0
@@ -5,2 +5,9 @@ # Changelog | ||
| ### [2.1.1](https://github.com/oclif/plugin-command-snapshot/compare/v2.1.0...v2.1.1) (2021-06-04) | ||
| ### Bug Fixes | ||
| * ensure lib files are published ([c54b061](https://github.com/oclif/plugin-command-snapshot/commit/c54b06183aa39eaed60869421d3dd02e90fa27c0)) | ||
| ## [2.1.0](https://github.com/oclif/plugin-command-snapshot/compare/v2.0.0...v2.1.0) (2021-06-03) | ||
@@ -7,0 +14,0 @@ |
@@ -1,1 +0,1 @@ | ||
| {"version":"2.1.0","commands":{"schema:compare":{"id":"schema:compare","pluginName":"@oclif/plugin-command-snapshot","pluginType":"core","aliases":[],"flags":{"filepath":{"name":"filepath","type":"option","description":"path of the generated snapshot file","default":"./schemas"}},"args":[]},"schema:generate":{"id":"schema:generate","pluginName":"@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","default":"./schemas"},"singlefile":{"name":"singlefile","type":"boolean","description":"put generated schema into a single file","allowNo":false}},"args":[]},"snapshot:compare":{"id":"snapshot:compare","pluginName":"@oclif/plugin-command-snapshot","pluginType":"core","aliases":[],"flags":{"filepath":{"name":"filepath","type":"option","description":"path of the generated snapshot file","default":"./command-snapshot.json"}},"args":[]},"snapshot:generate":{"id":"snapshot:generate","pluginName":"@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","default":"./command-snapshot.json"}},"args":[]}}} | ||
| {"version":"2.1.1","commands":{"schema:compare":{"id":"schema:compare","pluginName":"@oclif/plugin-command-snapshot","pluginType":"core","aliases":[],"flags":{"filepath":{"name":"filepath","type":"option","description":"path of the generated snapshot file","default":"./schemas"}},"args":[]},"schema:generate":{"id":"schema:generate","pluginName":"@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","default":"./schemas"},"singlefile":{"name":"singlefile","type":"boolean","description":"put generated schema into a single file","allowNo":false}},"args":[]},"snapshot:compare":{"id":"snapshot:compare","pluginName":"@oclif/plugin-command-snapshot","pluginType":"core","aliases":[],"flags":{"filepath":{"name":"filepath","type":"option","description":"path of the generated snapshot file","default":"./command-snapshot.json"}},"args":[]},"snapshot:generate":{"id":"snapshot:generate","pluginName":"@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","default":"./command-snapshot.json"}},"args":[]}}} |
+1
-1
| { | ||
| "name": "@oclif/plugin-command-snapshot", | ||
| "description": "generates and compares OCLIF plugins snapshot files", | ||
| "version": "2.1.0", | ||
| "version": "2.1.1", | ||
| "author": "Ramyasri @nramyasri-sf", | ||
@@ -6,0 +6,0 @@ "bugs": "https://github.com/oclif/plugin-command-snapshot/issues", |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
195738
11.69%22
120%654
313.92%1
-50%5
400%