Skip to content

Commit

Permalink
Upgrade oclif to v3 (#3896)
Browse files Browse the repository at this point in the history
* Update create command

* Update remaining commands

* Don't use fileTransform in Jest

* Use data URL for PNGs

* Remove unneeded mocks from tests

* Add exit code cleanup to CLI tests

* Add comment to exitCode cleanup
  • Loading branch information
garrettjstevens authored Sep 14, 2023
1 parent 4fc2e2c commit 0128d1f
Show file tree
Hide file tree
Showing 40 changed files with 1,750 additions and 962 deletions.
32 changes: 0 additions & 32 deletions config/jest/fileTransform.js

This file was deleted.

2 changes: 0 additions & 2 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ module.exports = {
transform: {
'^.+\\.(ts|tsx|js|jsx)$': '<rootDir>/config/jest/babelTransform.js',
'^.+\\.css$': '<rootDir>/config/jest/cssTransform.js',
'^(?!.*\\.(ts|js|tsx|jsx|css|json)$)':
'<rootDir>/config/jest/fileTransform.js',
},
transformIgnorePatterns: [
'[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$',
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@
"@mui/system": "^5.14.4",
"@mui/x-data-grid": "^6.0.1",
"@node-oauth/express-oauth-server": "^3.0.0",
"@oclif/dev-cli": "^1.26.9",
"@oclif/test": "^1.2.7",
"@oclif/test": "^2.4.8",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
"@storybook/addon-essentials": "^7.0.0",
"@storybook/node-logger": "^7.0.0",
Expand Down Expand Up @@ -138,6 +137,7 @@
"nock": "^13.2.1",
"node-polyfill-webpack-plugin": "^2.0.1",
"npm-run-all": "^4.1.5",
"oclif": "^3.15.0",
"postcss": "^8.4.4",
"postcss-flexbugs-fixes": "^5.0.2",
"postcss-loader": "^7.3.3",
Expand Down
460 changes: 264 additions & 196 deletions products/jbrowse-cli/README.md

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions products/jbrowse-cli/bin/dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env node

const oclif = require('@oclif/core')

const path = require('path')
const project = path.join(__dirname, '..', 'tsconfig.json')

// In dev mode -> use ts-node and dev plugins
process.env.NODE_ENV = 'development'

require('ts-node').register({ project })

// In dev mode, always show stack traces
oclif.settings.debug = true

// Start the CLI
oclif.run().then(oclif.flush).catch(oclif.Errors.handle)
3 changes: 3 additions & 0 deletions products/jbrowse-cli/bin/dev.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@echo off

node "%~dp0\dev" %*
9 changes: 6 additions & 3 deletions products/jbrowse-cli/bin/run
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#!/usr/bin/env node

require('@oclif/command').run()
.then(require('@oclif/command/flush'))
.catch(require('@oclif/errors/handle'))
const oclif = require('@oclif/core')

oclif
.run()
.then(require('@oclif/core/flush'))
.catch(require('@oclif/core/handle'))
17 changes: 7 additions & 10 deletions products/jbrowse-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,23 @@
"/oclif.manifest.json"
],
"engines": {
"node": ">=10.4.0"
"node": ">=16"
},
"scripts": {
"build": "oclif-dev pack",
"build:typescript": "tsc --build",
"build": "tsc --build",
"postpack": "rimraf oclif.manifest.json",
"clean": "rimraf lib",
"prepack": "npm run clean && npm run build:typescript && npm run manifest && npm run docs",
"manifest": "oclif-dev manifest",
"prepack": "npm run clean && npm run build && npm run manifest && npm run docs",
"manifest": "oclif manifest",
"version": "npm run docs && npm run docs:version:add",
"docs": "npm run docs:create && npm run docs:format",
"docs:create": "oclif-dev readme",
"docs:create": "oclif readme",
"docs:format": "prettier --write README.md",
"docs:version:add": "git add README.md"
},
"dependencies": {
"@oclif/command": "^1.8.11",
"@oclif/config": "^1.18.2",
"@oclif/errors": "^1",
"@oclif/plugin-help": "3.2.14",
"@oclif/core": "^2.12.0",
"@oclif/plugin-help": "^5.2.18",
"boxen": "^4.2.0",
"chalk": "^4.1.0",
"cli-progress": "^3.9.0",
Expand Down
2 changes: 1 addition & 1 deletion products/jbrowse-cli/src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* By convention, exit codes in this base class are below 100
*/

import Command from '@oclif/command'
import { Command } from '@oclif/core'
import { promises as fsPromises } from 'fs'
import path from 'path'
import parseJSON from 'json-parse-better-errors'
Expand Down
6 changes: 5 additions & 1 deletion products/jbrowse-cli/src/commands/add-assembly.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ const baseSequence = {
adapter: {},
}

// Cleaning up exitCode in Node.js 20, xref https://github.com/jestjs/jest/issues/14501
afterAll(() => (process.exitCode = 0))

describe('add-assembly', () => {
setup
.command(['add-assembly', '{}'])
Expand Down Expand Up @@ -443,6 +446,7 @@ describe('add-assembly', () => {
})

setup
.only()
.command([
'add-assembly',
'{"type":"CustomAdapter"}',
Expand All @@ -454,7 +458,7 @@ describe('add-assembly', () => {
'copy',
])
.it('can specify a custom name and alias', async ctx => {
expect(ctx.stdoutWrite).toHaveBeenCalledWith(
expect(ctx.stdout).toContain(
'Added assembly "customName" to config.json\n',
)
expect(readConf(ctx)).toEqual({
Expand Down
47 changes: 23 additions & 24 deletions products/jbrowse-cli/src/commands/add-assembly.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { flags } from '@oclif/command'
import { Args, Flags } from '@oclif/core'
import fs from 'fs'
import path from 'path'
import JBrowseCommand, { Assembly, Sequence, Config } from '../base'
Expand Down Expand Up @@ -46,21 +46,20 @@ export default class AddAssembly extends JBrowseCommand {
'$ jbrowse add-assembly myfile.fa.gz --load copy',
]

static args = [
{
name: 'sequence',
static args = {
sequence: Args.string({
required: true,
description: `sequence file or URL
If TYPE is indexedFasta or bgzipFasta, the index file defaults to <location>.fai
and can be optionally specified with --faiLocation
If TYPE is bgzipFasta, the gzip index file defaults to <location>.gzi and can be
optionally specified with --gziLocation`,
},
]
}),
}

static flags = {
type: flags.string({
type: Flags.string({
char: 't',
description: `type of sequence, by default inferred from sequence file
Expand All @@ -79,73 +78,73 @@ custom Either a JSON file location or inline JSON that defines a custom

options: ['indexedFasta', 'bgzipFasta', 'twoBit', 'chromSizes', 'custom'],
}),
name: flags.string({
name: Flags.string({
char: 'n',
description:
'Name of the assembly; if not specified, will be guessed using the sequence file name',
}),
alias: flags.string({
alias: Flags.string({
char: 'a',
description:
'An alias for the assembly name (e.g. "hg38" if the name of the assembly is "GRCh38");\ncan be specified multiple times',
multiple: true,
}),
displayName: flags.string({
displayName: Flags.string({
description:
'The display name to specify for the assembly, e.g. "Homo sapiens (hg38)" while the name can be a shorter identifier like "hg38"',
}),
faiLocation: flags.string({
faiLocation: Flags.string({
description: '[default: <fastaLocation>.fai] FASTA index file or URL',
}),
gziLocation: flags.string({
gziLocation: Flags.string({
description:
'[default: <fastaLocation>.gzi] FASTA gzip index file or URL',
}),
refNameAliases: flags.string({
refNameAliases: Flags.string({
description:
'Reference sequence name aliases file or URL; assumed to be a tab-separated aliases\nfile unless --refNameAliasesType is specified',
}),
refNameAliasesType: flags.string({
refNameAliasesType: Flags.string({
description:
'Type of aliases defined by --refNameAliases; if "custom", --refNameAliases is either\na JSON file location or inline JSON that defines a custom sequence adapter',
options: ['aliases', 'custom'],
dependsOn: ['refNameAliases'],
}),
refNameColors: flags.string({
refNameColors: Flags.string({
description:
'A comma-separated list of color strings for the reference sequence names; will cycle\nthrough colors if there are fewer colors than sequences',
}),
target: flags.string({
target: Flags.string({
description:
'path to config file in JB2 installation directory to write out to.\nCreates ./config.json if nonexistent',
}),
out: flags.string({
out: Flags.string({
description: 'synonym for target',
}),
help: flags.help({ char: 'h' }),
load: flags.string({
help: Flags.help({ char: 'h' }),
load: Flags.string({
char: 'l',
description:
'Required flag when using a local file. Choose how to manage the data directory. Copy, symlink, or move the data directory to the JBrowse directory. Or use inPlace to modify the config without doing any file operations',
options: ['copy', 'symlink', 'move', 'inPlace'],
}),
skipCheck: flags.boolean({
skipCheck: Flags.boolean({
description:
"Don't check whether or not the sequence file or URL exists or if you are in a JBrowse directory",
}),
overwrite: flags.boolean({
overwrite: Flags.boolean({
description:
'Overwrite existing assembly if one with the same name exists',
}),
force: flags.boolean({
force: Flags.boolean({
char: 'f',
description: 'Equivalent to `--skipCheck --overwrite`',
}),
}

async getAssembly(): Promise<Assembly> {
let sequence: Sequence
const { args: runArgs, flags: runFlags } = this.parse(AddAssembly)
const { args: runArgs, flags: runFlags } = await this.parse(AddAssembly)
const { sequence: argsSequence } = runArgs as { sequence: string }

if (this.needLoadData(argsSequence) && !runFlags.load) {
Expand Down Expand Up @@ -379,7 +378,7 @@ custom Either a JSON file location or inline JSON that defines a custom
const exists = (s: string) =>
new Promise(r => fs.access(s, fs.constants.F_OK, e => r(!e)))

const { args: runArgs, flags: runFlags } = this.parse(AddAssembly)
const { args: runArgs, flags: runFlags } = await this.parse(AddAssembly)

const output = runFlags.target || runFlags.out || '.'

Expand Down
3 changes: 3 additions & 0 deletions products/jbrowse-cli/src/commands/add-connection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ const setupWithDateMock = setup
Date.now = originalDateNow
})

// Cleaning up exitCode in Node.js 20, xref https://github.com/jestjs/jest/issues/14501
afterAll(() => (process.exitCode = 0))

describe('add-connection', () => {
setup
.nock('https://example.com', site => site.head('/hub.txt').reply(200))
Expand Down
35 changes: 17 additions & 18 deletions products/jbrowse-cli/src/commands/add-connection.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { flags } from '@oclif/command'
import { Args, Flags } from '@oclif/core'
import fs from 'fs'
import path from 'path'
import parseJSON from 'json-parse-better-errors'
Expand Down Expand Up @@ -37,60 +37,59 @@ export default class AddConnection extends JBrowseCommand {
'$ jbrowse add-connection https://mysite.com/path/to/hub.txt --connectionId newId --name newName --target /path/to/jb2/installation/config.json',
]

static args = [
{
name: 'connectionUrlOrPath',
static args = {
connectionUrlOrPath: Args.string({
required: true,
description: `URL of data directory\nFor hub file, usually called hub.txt\nFor JBrowse 1, location of JB1 data directory similar to http://mysite.com/jbrowse/data/ `,
},
]
}),
}

static flags = {
type: flags.string({
type: Flags.string({
char: 't',
description:
'type of connection, ex. JBrowse1Connection, UCSCTrackHubConnection, custom',
}),
assemblyNames: flags.string({
assemblyNames: Flags.string({
char: 'a',
description:
'For UCSC, optional: Comma separated list of assembly name(s) to filter from this connection. For JBrowse: a single assembly name',
}),
config: flags.string({
config: Flags.string({
char: 'c',
description: `Any extra config settings to add to connection in JSON object format, such as '{"uri":"url":"https://sample.com"}, "locationType": "UriLocation"}'`,
}),
connectionId: flags.string({
connectionId: Flags.string({
description: `Id for the connection that must be unique to JBrowse. Defaults to 'connectionType-assemblyName-currentTime'`,
}),
name: flags.string({
name: Flags.string({
char: 'n',
description:
'Name of the connection. Defaults to connectionId if not provided',
}),
target: flags.string({
target: Flags.string({
description:
'path to config file in JB2 installation directory to write out to.',
}),
out: flags.string({
out: Flags.string({
description: 'synonym for target',
}),
help: flags.help({ char: 'h' }),
skipCheck: flags.boolean({
help: Flags.help({ char: 'h' }),
skipCheck: Flags.boolean({
description:
"Don't check whether or not the data directory URL exists or if you are in a JBrowse directory",
}),
overwrite: flags.boolean({
overwrite: Flags.boolean({
description: 'Overwrites any existing connections if same connection id',
}),
force: flags.boolean({
force: Flags.boolean({
char: 'f',
description: 'Equivalent to `--skipCheck --overwrite`',
}),
}

async run() {
const { args: runArgs, flags: runFlags } = this.parse(AddConnection)
const { args: runArgs, flags: runFlags } = await this.parse(AddConnection)

const output = runFlags.target || runFlags.out || '.'
const isDir = fs.lstatSync(output).isDirectory()
Expand Down
Loading

0 comments on commit 0128d1f

Please sign in to comment.