Skip to content

Commit

Permalink
doc: resolvers & builtins
Browse files Browse the repository at this point in the history
  • Loading branch information
nullishamy committed Aug 30, 2023
1 parent de490e5 commit a6626da
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 7 deletions.
10 changes: 8 additions & 2 deletions examples/05-application-config/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,14 @@ class UserConfigResolver extends Resolver {
return this.data[key] !== undefined
}

resolveKey (key: string): string | undefined {
return this.data[key]
resolveKey (key: string): string {
const value = this.data[key]

if (value === undefined) {
throw new TypeError()
}

return value
}
}

Expand Down
35 changes: 34 additions & 1 deletion src/builder/builtin.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,63 @@
import { Args } from '../args'

/**
* Represents a builtin command (such as help, version information) within a parser configuration.
*
* These are contained separately from {@link Command}s because they may be triggered by flags, and will always require
* special casing when being executed.
*
* A builtin match will always override user commands, and will halt argument coercion.
*/
export abstract class Builtin {
public commandTriggers: string[] = []
public argumentTriggers: string[] = []

public constructor (public readonly id: string) {}

/**
* Adds a command to the known command triggers for this builtin
* @param command - The command to trigger this builtin on
* @returns this
*/
public onCommand (command: string): Builtin {
this.commandTriggers.push(command)
return this
}

/**
* Adds a flag to the known argument triggers for this builtin
* @param command - The flag to trigger this builtin on
* @returns this
*/
public onArgument (argument: string): Builtin {
this.argumentTriggers.push(argument)
return this
}

/**
* Clear all known triggers from this builtin
* @returns this
*/
public clearTriggers (): Builtin {
this.commandTriggers = []
this.argumentTriggers = []
return this
}

/**
* Execute a builtin.
* @param parser - The current parser
* @param flags - The raw flag arguments
* @param positionals - The raw positional arguments
* @param trigger - The flag / command that triggered this builtin
*/
abstract run (parser: Args<{}>, flags: Record<string, string[]>, positionals: string[], trigger: string): Promise<void>

helpInfo (): string {
/**
* Generate the help string for this builtin. Describes the triggers which this builtin runs on.
* @returns The generated help string
*/
public helpInfo (): string {
return `${this.commandTriggers.map(cmd => `${cmd} <...args>`).join(', ')} | ${this.argumentTriggers.map(arg => `--${arg}`).join(', ')}`
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/builder/default-resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ export class EnvironmentResolver extends Resolver {
return platform.getEnv(envKey) !== undefined
}

resolveKey (key: string, opts: StoredParserOpts): string | undefined {
resolveKey (key: string, opts: StoredParserOpts): string {
const envKey = `${opts.environmentPrefix}_${key.toUpperCase()}`
const platform = currentPlatform()
return platform.getEnv(envKey)
const value = platform.getEnv(envKey)
if (value === undefined) {
throw new TypeError('value was undefined, but keyExists must have been true')
}
return value
}
}
19 changes: 18 additions & 1 deletion src/builder/resolver.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
import { StoredParserOpts } from '../opts'

/**
* Represents a secondary resolution source (after user arguments) for which argument values can be obtained.
*
* These sources may be from a network, from the file system, or from the environment.
*/
export abstract class Resolver {
public constructor (
public readonly identifier: string
) {}

/**
* Determine whether this resolver can resolve the provided key.
* @param key - The key to check
* @param opts - The parser opts
*/
abstract keyExists (key: string, opts: StoredParserOpts): boolean
abstract resolveKey (key: string, opts: StoredParserOpts): string | undefined
/**
* Resolve the provided key to its string value.
*
* This value should not be validated in any way other than ensuring it is not nullish.
* @param key - The key to resolve
* @param opts - The parser opts
*/
abstract resolveKey (key: string, opts: StoredParserOpts): string
}
2 changes: 1 addition & 1 deletion test/integrations/resolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { runArgsExecution } from './utils'
class MockResolver extends Resolver {
constructor (
public readonly keyExists: (key: string) => boolean,
public readonly resolveKey: (key: string) => string | undefined,
public readonly resolveKey: (key: string) => string,
id = 'mock'
) {
super(id)
Expand Down

0 comments on commit a6626da

Please sign in to comment.