Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: no longer use tsconfck #892

Merged
merged 6 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
windows-unit-tests:
needs: linux-unit-tests
uses: salesforcecli/github-workflows/.github/workflows/unitTestsWindows.yml@main
e2e:
integration:
needs: linux-unit-tests
strategy:
matrix:
Expand All @@ -33,10 +33,10 @@ jobs:
- uses: salesforcecli/github-workflows/.github/actions/yarnInstallWithRetries@main
- run: yarn build
- if: runner.os == 'Windows'
run: yarn mocha --forbid-only "test/**/*.e2e.ts" --exclude "test/integration/sf.e2e.ts" --parallel --timeout 1200000
run: yarn mocha --forbid-only "test/**/*.integration.ts" --exclude "test/integration/sf.integration.ts" --parallel --timeout 1200000
- if: runner.os == 'Linux'
run: yarn test:e2e
windows-sf-e2e:
run: yarn test:integration
windows-sf-integration:
# For whatever reason the windows-latest runner doesn't like it when you shell yarn commands in the sf repo
# which is an integral part of the setup for the tests. Instead, we replicate the setup here.
needs: linux-unit-tests
Expand All @@ -52,8 +52,8 @@ jobs:
- uses: salesforcecli/github-workflows/.github/actions/yarnInstallWithRetries@main
- run: yarn build
- run: yarn link
- run: New-Item -Path D:\a -Name "e2e" -ItemType "directory"
- run: New-Item -Path D:\a\e2e -Name "sf.e2e.ts" -ItemType "directory"
- run: New-Item -Path D:\a -Name "integration" -ItemType "directory"
- run: New-Item -Path D:\a\integration -Name "sf.integration.ts" -ItemType "directory"
- run: |
git clone https://github.com/salesforcecli/cli.git
cd cli
Expand All @@ -66,12 +66,12 @@ jobs:
yarn install --network-timeout 600000
yarn link @oclif/core
yarn build
working-directory: D:\a\e2e\sf.e2e.ts
- run: yarn mocha --forbid-only "test/integration/sf.e2e.ts" --parallel --timeout 1200000
working-directory: D:\a\integration\sf.integration.ts
- run: yarn mocha --forbid-only "test/integration/sf.integration.ts" --parallel --timeout 1200000
env:
OCLIF_CORE_E2E_SKIP_SETUP: true
OCLIF_CORE_E2E_TEST_DIR: D:\a\e2e
DEBUG: e2e:*
OCLIF_CORE_INTEGRATION_SKIP_SETUP: true
OCLIF_CORE_INTEGRATION_TEST_DIR: D:\a\integration
DEBUG: integration:*
esm-cjs-interop:
needs: linux-unit-tests
strategy:
Expand Down Expand Up @@ -108,13 +108,13 @@ jobs:
- https://github.com/salesforcecli/plugin-schema
- https://github.com/salesforcecli/plugin-user
with:
packageName: "@oclif/core"
packageName: '@oclif/core'
externalProjectGitUrl: ${{ matrix.externalProjectGitUrl }}
command: "yarn test:nuts"
command: 'yarn test:nuts'
os: ${{ matrix.os }}
useCache: false
preSwapCommands: "npx yarn-deduplicate; yarn install"
preExternalBuildCommands: "shx rm -rf node_modules/@salesforce/sf-plugins-core/node_modules/@oclif/core"
preSwapCommands: 'npx yarn-deduplicate; yarn install'
preExternalBuildCommands: 'shx rm -rf node_modules/@salesforce/sf-plugins-core/node_modules/@oclif/core'
ignoreScripts: true
secrets:
TESTKIT_AUTH_URL: ${{ secrets.TESTKIT_AUTH_URL }}
Expand Down Expand Up @@ -142,7 +142,7 @@ jobs:
with:
repo: ${{ matrix.repo }}
os: ${{ matrix.os }}
command: "yarn mocha test/**/*.test.ts --timeout 1200000"
command: 'yarn mocha test/**/*.test.ts --timeout 1200000'
plugin-plugins-integration:
needs: linux-unit-tests
strategy:
Expand All @@ -153,7 +153,7 @@ jobs:
with:
repo: oclif/plugin-plugins
os: ${{ matrix.os }}
command: "yarn test:integration"
command: 'yarn test:integration'
# plugin-plugins integration tests depend on sf being installed globally
other-setup: npm install -g @salesforce/cli@nightly
plugin-update-integration:
Expand All @@ -166,4 +166,4 @@ jobs:
with:
repo: oclif/plugin-update
os: ${{ matrix.os }}
command: "yarn test:integration:sf"
command: 'yarn test:integration:sf'
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@
/test/tmp
.DS_Store
.idea
/test/**/node_modules
/test/**/yarn.lock
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
"strip-ansi": "^6.0.1",
"supports-color": "^8.1.1",
"supports-hyperlinks": "^2.2.0",
"tsconfck": "^3.0.0",
"widest-line": "^3.1.0",
"wordwrap": "^1.0.0",
"wrap-ansi": "^7.0.0"
Expand Down Expand Up @@ -121,8 +120,8 @@
"pretest": "yarn build && tsc -p test --noEmit --skipLibCheck",
"test:circular-deps": "madge lib/ -c",
"test:debug": "nyc mocha --debug-brk --inspect \"test/**/*.test.ts\"",
"test:e2e": "mocha --forbid-only \"test/**/*.e2e.ts\" --parallel --timeout 1200000",
"test:esm-cjs": "cross-env DEBUG=e2e:* ts-node test/integration/esm-cjs.ts",
"test:integration": "mocha --forbid-only \"test/**/*.integration.ts\" --parallel --timeout 1200000",
"test:esm-cjs": "cross-env DEBUG=integration:* ts-node test/integration/esm-cjs.ts",
"test:perf": "ts-node test/perf/parser.perf.ts",
"test:dev": "nyc mocha \"test/**/*.test.ts\"",
"test": "nyc mocha --forbid-only \"test/**/*.test.ts\""
Expand Down
7 changes: 4 additions & 3 deletions src/config/ts-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import * as TSNode from 'ts-node'
import {memoizedWarn} from '../errors'
import {Plugin, TSConfig} from '../interfaces'
import {settings} from '../settings'
import {existsSync, readTSConfig} from '../util/fs'
import {existsSync} from '../util/fs'
import {readTSConfig} from '../util/read-tsconfig'
import {isProd} from '../util/util'
import Cache from './cache'
import {Debug} from './util'
// eslint-disable-next-line new-cap
const debug = Debug('ts-node')

export const TS_CONFIGS: Record<string, TSConfig> = {}
export const TS_CONFIGS: Record<string, TSConfig | undefined> = {}
const REGISTERED = new Set<string>()

function isErrno(error: any): error is NodeJS.ErrnoException {
Expand All @@ -22,7 +23,7 @@ async function loadTSConfig(root: string): Promise<TSConfig | undefined> {
try {
if (TS_CONFIGS[root]) return TS_CONFIGS[root]

TS_CONFIGS[root] = await readTSConfig(join(root, 'tsconfig.json'))
TS_CONFIGS[root] = await readTSConfig(root)

return TS_CONFIGS[root]
} catch (error) {
Expand Down
98 changes: 65 additions & 33 deletions src/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,23 @@ import {BooleanFlag, CustomOptions, FlagDefinition, OptionFlag} from './interfac
import {dirExists, fileExists} from './util/fs'

type NotArray<T> = T extends Array<any> ? never : T

/**
* Create a custom flag.
*
* @example
* type Id = string
* type IdOpts = { startsWith: string; length: number }
*
* export const myFlag = custom<Id, IdOpts>({
* parse: async (input, opts) => {
* if (input.startsWith(opts.startsWith) && input.length === opts.length) {
* return input
* }
*
* throw new Error('Invalid id')
* },
* })
*/
export function custom<T = string, P extends CustomOptions = CustomOptions>(
defaults: Partial<OptionFlag<T[], P>> & {
multiple: true
Expand Down Expand Up @@ -40,23 +56,7 @@ export function custom<T = string, P extends CustomOptions = CustomOptions>(): F
P,
{multiple: false; requiredOrDefaulted: false}
>
/**
* Create a custom flag.
*
* @example
* type Id = string
* type IdOpts = { startsWith: string; length: number };
*
* export const myFlag = custom<Id, IdOpts>({
* parse: async (input, opts) => {
* if (input.startsWith(opts.startsWith) && input.length === opts.length) {
* return input
* }
*
* throw new Error('Invalid id')
* },
* })
*/

export function custom<T = string, P extends CustomOptions = CustomOptions>(
defaults?: Partial<OptionFlag<T, P>>,
): FlagDefinition<T, P, {multiple: boolean; requiredOrDefaulted: boolean}> {
Expand All @@ -70,6 +70,11 @@ export function custom<T = string, P extends CustomOptions = CustomOptions>(
})
}

/**
* A boolean flag. Defaults to `false` unless default is set to `true`.
*
* - `allowNo` option allows `--no-` prefix to negate boolean flag.
*/
export function boolean<T = boolean>(options: Partial<BooleanFlag<T>> = {}): BooleanFlag<T> {
return {
parse: async (b, _) => b,
Expand All @@ -79,6 +84,12 @@ export function boolean<T = boolean>(options: Partial<BooleanFlag<T>> = {}): Boo
} as BooleanFlag<T>
}

/**
* An integer flag. Throws an error if the provided value is not a valid integer.
*
* - `min` option allows to set a minimum value.
* - `max` option allows to set a maximum value.
*/
export const integer = custom<number, {max?: number; min?: number}>({
async parse(input, _, opts) {
if (!/^-?\d+$/.test(input)) throw new CLIError(`Expected an integer but received: ${input}`)
Expand All @@ -91,6 +102,11 @@ export const integer = custom<number, {max?: number; min?: number}>({
},
})

/**
* A directory flag.
*
* - `exists` option allows you to throw an error if the directory does not exist.
*/
export const directory = custom<string, {exists?: boolean}>({
async parse(input, _, opts) {
if (opts.exists) return dirExists(input)
Expand All @@ -99,6 +115,11 @@ export const directory = custom<string, {exists?: boolean}>({
},
})

/**
* A flag flag.
mdonnalley marked this conversation as resolved.
Show resolved Hide resolved
*
* - `exists` option allows you to throw an error if the file does not exist.
*/
export const file = custom<string, {exists?: boolean}>({
async parse(input, _, opts) {
if (opts.exists) return fileExists(input)
Expand All @@ -108,8 +129,9 @@ export const file = custom<string, {exists?: boolean}>({
})

/**
* Initializes a string as a URL. Throws an error
* if the string is not a valid URL.
* A URL flag that converts the provided value is a string.
*
* Throws an error if the string is not a valid URL.
*/
export const url = custom<URL>({
async parse(input) {
Expand All @@ -121,8 +143,14 @@ export const url = custom<URL>({
},
})

/**
* A string flag.
*/
export const string = custom()

/**
* Version flag that will print the CLI version and exit.
*/
export const version = (opts: Partial<BooleanFlag<boolean>> = {}): BooleanFlag<void> =>
boolean({
description: 'Show CLI version.',
Expand All @@ -133,6 +161,9 @@ export const version = (opts: Partial<BooleanFlag<boolean>> = {}): BooleanFlag<v
},
})

/**
* A help flag that will print the CLI help and exit.
*/
export const help = (opts: Partial<BooleanFlag<boolean>> = {}): BooleanFlag<void> =>
boolean({
description: 'Show CLI help.',
Expand All @@ -147,7 +178,20 @@ export const help = (opts: Partial<BooleanFlag<boolean>> = {}): BooleanFlag<void
})

type ReadonlyElementOf<T extends ReadonlyArray<unknown>> = T[number]

/**
* Create a custom flag that infers the flag type from the provided options.
*
* The provided `options` must be a readonly array in order for type inference to work.
*
* @example
* export default class MyCommand extends Command {
* static flags = {
* name: Flags.option({
* options: ['foo', 'bar'] as const,
* })(),
* }
* }
*/
export function option<T extends readonly string[], P extends CustomOptions>(
defaults: Partial<OptionFlag<ReadonlyElementOf<T>[], P>> & {
multiple: true
Expand Down Expand Up @@ -185,18 +229,6 @@ export function option<T extends readonly string[], P extends CustomOptions>(
},
): FlagDefinition<(typeof defaults.options)[number], P, {multiple: true; requiredOrDefaulted: false}>

/**
* Create a custom flag that infers the flag type from the provided options.
*
* @example
* export default class MyCommand extends Command {
* static flags = {
* name: Flags.option({
* options: ['foo', 'bar'] as const,
* })(),
* }
* }
*/
export function option<T extends readonly string[], P extends CustomOptions>(
defaults: Partial<OptionFlag<ReadonlyElementOf<T>, P>> & {options: T},
): FlagDefinition<(typeof defaults.options)[number], P, {multiple: boolean; requiredOrDefaulted: boolean}> {
Expand Down
9 changes: 0 additions & 9 deletions src/util/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import {Stats, existsSync as fsExistsSync, readFileSync} from 'node:fs'
import {readFile, stat} from 'node:fs/promises'
import {join} from 'node:path'

import {mergeNestedObjects} from './util'

export function requireJson<T>(...pathParts: string[]): T {
return JSON.parse(readFileSync(join(...pathParts), 'utf8'))
}
Expand Down Expand Up @@ -71,10 +69,3 @@ export async function safeReadJson<T>(path: string): Promise<T | undefined> {
export function existsSync(path: string): boolean {
return fsExistsSync(path)
}

export async function readTSConfig(path: string) {
const {parse} = await import('tsconfck')
const result = await parse(path)
const tsNodeOpts = mergeNestedObjects(result.extended ?? [result], 'tsconfig.ts-node')
return {...result.tsconfig, 'ts-node': tsNodeOpts}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think anyone in the oclifverse would be using this util? Removing it would be a breaking change. You could leave the export and have it call readTSConfig from src/util/read-tsconfig.ts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was never export from src/index.ts so we're able to remove it without it being a breaking change

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. They could grab the export from this file but what we export from src/index is our "contract".

Loading
Loading