Skip to content

Commit

Permalink
Merge branch 'main' into mdonnalley/shrinkwrap
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonnalley committed Mar 4, 2024
2 parents a8a7ce0 + 0e8f741 commit 2896289
Show file tree
Hide file tree
Showing 6 changed files with 277 additions and 69 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
# [5.1.0](https://github.com/oclif/plugin-command-snapshot/compare/5.0.10...5.1.0) (2024-03-04)

### Features

- support pattern strategy ([#482](https://github.com/oclif/plugin-command-snapshot/issues/482)) ([687e764](https://github.com/oclif/plugin-command-snapshot/commit/687e764a8dda7a4b984d8eec92910fd41734df57))

## [5.0.10](https://github.com/oclif/plugin-command-snapshot/compare/5.0.9...5.0.10) (2024-03-03)

### Bug Fixes

- **deps:** bump @oclif/core from 3.19.6 to 3.20.0 ([#494](https://github.com/oclif/plugin-command-snapshot/issues/494)) ([fee5d09](https://github.com/oclif/plugin-command-snapshot/commit/fee5d0974ef2fdb55701833da608c0d39fa44f52))

## [5.0.9](https://github.com/oclif/plugin-command-snapshot/compare/5.0.8...5.0.9) (2024-02-18)

### Bug Fixes
Expand Down
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
{
"name": "@oclif/plugin-command-snapshot",
"description": "generates and compares OCLIF plugins snapshot files",
"version": "5.0.9",
"version": "5.1.0",
"author": "Salesforce",
"bugs": "https://github.com/oclif/plugin-command-snapshot/issues",
"dependencies": {
"@oclif/core": "^3.19.2",
"@oclif/core": "3.21.0",
"@types/lodash.difference": "^4.5.9",
"chalk": "^5.3.0",
"globby": "^14.0.1",
"just-diff": "^5.2.0",
"lodash.difference": "^4.5.0",
"lodash.get": "^4.4.2",
Expand All @@ -19,13 +20,13 @@
"@commitlint/config-conventional": "^18.6.2",
"@oclif/plugin-help": "^6",
"@oclif/prettier-config": "^0.2.1",
"@oclif/test": "^3.1.12",
"@oclif/test": "^3.2.1",
"@types/chai": "^4.3.11",
"@types/lodash.get": "^4.4.9",
"@types/lodash.sortby": "^4.7.9",
"@types/mocha": "^10.0.6",
"@types/node": "^18",
"@types/semver": "^7.5.7",
"@types/semver": "^7.5.8",
"chai": "^4",
"commitlint": "^18.6.1",
"eslint": "^8.57.0",
Expand All @@ -36,7 +37,7 @@
"lint-staged": "^15.2.2",
"mocha": "^10.2.0",
"nyc": "^15",
"oclif": "^4.4.17",
"oclif": "^4.4.19",
"prettier": "^3.2.5",
"shx": "^0.3.4",
"sinon": "^17.0.1",
Expand Down
33 changes: 24 additions & 9 deletions src/commands/schema/compare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import * as semver from 'semver'
import {Schema} from 'ts-json-schema-generator'

import SnapshotCommand from '../../snapshot-command.js'
import {getKeyNameFromFilename} from '../../util.js'
import {SchemaGenerator, Schemas, getAllFiles} from './generate.js'
import {GLOB_PATTERNS, getAllFiles, getKeyNameFromFilename} from '../../util.js'
import {SchemaGenerator, Schemas} from './generate.js'

export type SchemaComparison = Array<{op: Operation; path: (number | string)[]; value: unknown}>

Expand All @@ -32,6 +32,25 @@ export default class SchemaCompare extends SnapshotCommand {
}

public async run(): Promise<SchemaComparison> {
const strategy =
typeof this.config.pjson.oclif?.commands === 'string' ? 'pattern' : this.config.pjson.oclif?.commands?.strategy
const commandsDir =
typeof this.config.pjson.oclif?.commands === 'string'
? this.config.pjson.oclif?.commands
: this.config.pjson.oclif?.commands?.target
const commandGlobs =
typeof this.config.pjson.oclif?.commands === 'string'
? GLOB_PATTERNS
: this.config.pjson.oclif?.commands?.globPatterns

if (strategy === 'single') {
this.error('This command is not supported for single command CLIs')
}

if (strategy === 'explicit') {
this.error('This command is not supported for explicit command discovery')
}

const {flags} = await this.parse(SchemaCompare)

try {
Expand All @@ -42,7 +61,8 @@ export default class SchemaCompare extends SnapshotCommand {
}

const existingSchema = this.readExistingSchema(flags.filepath)
const latestSchema = await this.generateLatestSchema()
const generator = new SchemaGenerator({base: this, commandGlobs, commandsDir})
const latestSchema = await generator.generate()
this.debug('existingSchema', existingSchema)
this.debug('latestSchema', latestSchema)
const changes = diff(latestSchema, existingSchema)
Expand Down Expand Up @@ -113,7 +133,7 @@ export default class SchemaCompare extends SnapshotCommand {
}

this.log()
const bin = process.platform === 'win32' ? 'bin\\dev.cmd' : 'bin/dev'
const bin = process.platform === 'win32' ? 'bin\\dev.cmd' : 'bin/dev.js'
this.log(
'If intended, please update the schema file(s) and run again:',
chalk.bold(`${bin} ${toConfiguredId('schema:generate', this.config)}`),
Expand All @@ -122,11 +142,6 @@ export default class SchemaCompare extends SnapshotCommand {
return changes
}

private async generateLatestSchema(): Promise<Schemas> {
const generator = new SchemaGenerator(this)
return generator.generate()
}

private readExistingSchema(filePath: string): Schemas {
const contents = fs.readdirSync(filePath)
const folderIsVersioned = contents.every((c) => semver.valid(c))
Expand Down
68 changes: 44 additions & 24 deletions src/commands/schema/generate.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import {Flags} from '@oclif/core'
import chalk from 'chalk'
import {globbySync} from 'globby'
import * as fs from 'node:fs'
import * as path from 'node:path'
import {Schema, createGenerator} from 'ts-json-schema-generator'

import SnapshotCommand from '../../snapshot-command.js'
import {getSchemaFileName} from '../../util.js'
import {GLOB_PATTERNS, getAllFiles, getSchemaFileName} from '../../util.js'

export type SchemasMap = {
[key: string]: Schema
Expand All @@ -15,31 +16,26 @@ export type Schemas = {commands: SchemasMap; hooks: SchemasMap}

export type GenerateResponse = string[]

export function getAllFiles(dirPath: string, ext: string, allFiles: string[] = []): string[] {
let files: string[] = []
try {
files = fs.readdirSync(dirPath)
} catch {}

for (const file of files) {
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
type SchemaGenerateOptions = {
base: SnapshotCommand
commandGlobs?: string[]
commandsDir?: string
ignoreVoid?: boolean
}

export class SchemaGenerator {
private base: SnapshotCommand
private classToId: Record<string, string> = {}

constructor(
private base: SnapshotCommand,
private ignoreVoid = true,
) {}
private commandGlobs: string[]
private commandsDir: string | undefined
private ignoreVoid: boolean

constructor(options: SchemaGenerateOptions) {
this.base = options.base
this.ignoreVoid = options.ignoreVoid ?? true
this.commandsDir = options.commandsDir
this.commandGlobs = options.commandGlobs ?? GLOB_PATTERNS
}

public async generate(): Promise<Schemas> {
for (const cmd of this.base.commands) {
Expand Down Expand Up @@ -101,7 +97,12 @@ export class SchemaGenerator {
}

private getAllCmdFiles(): string[] {
const {rootDir} = this.getDirs()
const {outDir, rootDir} = this.getDirs()
if (this.commandsDir) {
const commandsSrcDir = path.resolve(this.base.config.root, this.commandsDir).replace(outDir, rootDir)
return globbySync(this.commandGlobs, {absolute: true, cwd: commandsSrcDir})
}

return getAllFiles(path.join(rootDir, 'commands'), '.ts')
}

Expand Down Expand Up @@ -216,8 +217,27 @@ export default class SchemaGenerate extends SnapshotCommand {
}

public async run(): Promise<GenerateResponse> {
const strategy =
typeof this.config.pjson.oclif?.commands === 'string' ? 'pattern' : this.config.pjson.oclif?.commands?.strategy
const commandsDir =
typeof this.config.pjson.oclif?.commands === 'string'
? this.config.pjson.oclif?.commands
: this.config.pjson.oclif?.commands?.target
const commandGlobs =
typeof this.config.pjson.oclif?.commands === 'string'
? GLOB_PATTERNS
: this.config.pjson.oclif?.commands?.globPatterns

if (strategy === 'single') {
this.error('This command is not supported for single command CLIs')
}

if (strategy === 'explicit') {
this.error('This command is not supported for explicit command discovery')
}

const {flags} = await this.parse(SchemaGenerate)
const generator = new SchemaGenerator(this, flags.ignorevoid)
const generator = new SchemaGenerator({base: this, commandGlobs, commandsDir, ignoreVoid: flags.ignorevoid})

const schemas = await generator.generate()

Expand Down
24 changes: 24 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import fs from 'node:fs'
import path from 'node:path'

/**
* Get the file name for a given command ID replacing "-" with "__" and ":" with "-"
* @param cmdId - command ID
Expand All @@ -15,3 +18,24 @@ export const getSchemaFileName = (cmdId: string): string => {
*/
export const getKeyNameFromFilename = (file: string): string =>
file.replaceAll('-', ':').replaceAll('__', '-').replace('.json', '')

export const getAllFiles = (dirPath: string, ext: string, allFiles: string[] = []): string[] =>
safeReadDirSync(dirPath)
.flatMap((f) =>
f.isDirectory() ? getAllFiles(path.join(dirPath, f.name), ext, allFiles) : path.join(dirPath, f.name),
)
.filter((f) => f.endsWith(ext))

const safeReadDirSync = (dirPath: string): fs.Dirent[] => {
try {
// TODO: use recursive option when available in Node 20
return fs.readdirSync(dirPath, {withFileTypes: true})
} catch {
return []
}
}

export const GLOB_PATTERNS = [
'**/*.+(js|cjs|mjs|ts|tsx|mts|cts)',
'!**/*.+(d.ts|test.ts|test.js|spec.ts|spec.js|d.mts|d.cts)?(x)',
]
Loading

0 comments on commit 2896289

Please sign in to comment.