Skip to content

Commit

Permalink
feat: handle default option values with zod
Browse files Browse the repository at this point in the history
  • Loading branch information
ivomurrell committed Mar 6, 2023
1 parent 940876b commit 7c03517
Show file tree
Hide file tree
Showing 17 changed files with 51 additions and 87 deletions.
16 changes: 12 additions & 4 deletions core/create/src/prompts/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ export interface OptionsParams {
configPath: string
}

type ZodPartial = z.ZodOptional<z.ZodTypeAny> | z.ZodDefault<z.ZodTypeAny>

const isPartialOptional = (partial: ZodPartial): partial is z.ZodOptional<z.ZodTypeAny> =>
typeof (partial as z.ZodOptional<z.ZodTypeAny>).unwrap === 'function'

export default async ({ logger, config, toolKitConfig, configPath }: OptionsParams): Promise<boolean> => {
for (const plugin of Object.keys(config.plugins)) {
let options: z.AnyZodObject
Expand All @@ -163,9 +168,9 @@ export default async ({ logger, config, toolKitConfig, configPath }: OptionsPara
continue
}

const [optional, required] = partition<[string, z.ZodTypeAny], [string, z.ZodOptional<z.ZodTypeAny>]>(
const [partial, required] = partition<[string, z.ZodTypeAny], [string, ZodPartial]>(
Object.entries(options.shape),
(schema): schema is [string, z.ZodOptionalType<z.ZodTypeAny>] => schema[1].isOptional()
(schema): schema is [string, ZodPartial] => schema[1].isOptional()
)
const anyRequired = required.length > 0

Expand Down Expand Up @@ -196,7 +201,7 @@ export default async ({ logger, config, toolKitConfig, configPath }: OptionsPara
}
}

if (optional.length > 0) {
if (partial.length > 0) {
const { confirm } = await prompt({
name: 'confirm',
type: 'confirm',
Expand All @@ -211,7 +216,10 @@ export default async ({ logger, config, toolKitConfig, configPath }: OptionsPara
await optionsPromptForPlugin(
toolKitConfig,
plugin,
optional.map(([name, optionType]) => [name, optionType.unwrap()])
partial.map(([name, partialType]) => [
name,
isPartialOptional(partialType) ? partialType.unwrap() : partialType.removeDefault()
])
)
} else if (!anyRequired) {
delete toolKitConfig.options[plugin]
Expand Down
7 changes: 3 additions & 4 deletions lib/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,14 @@ export abstract class Task<O extends z.ZodTypeAny = z.ZodTypeAny> extends Base {
return taskSymbol
}

static defaultOptions: Record<string, unknown> = {}
options: z.infer<O>
options: z.output<O>
logger: Logger

constructor(logger: Logger, options: Partial<z.infer<O>> = {}) {
constructor(logger: Logger, options: z.output<O>) {
super()

const staticThis = this.constructor as typeof Task
this.options = Object.assign({}, staticThis.defaultOptions as z.infer<O>, options)
this.options = options
this.logger = logger.child({ task: staticThis.id })
}

Expand Down
2 changes: 1 addition & 1 deletion lib/types/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type PromptGenerators<T> = T extends z.ZodObject<infer Shape>
? {
[option in keyof Shape as Shape[option] extends z.ZodType
? option
: never]?: Shape[option] extends z.ZodType ? SchemaPromptGenerator<z.infer<Shape[option]>> : never
: never]?: Shape[option] extends z.ZodType ? SchemaPromptGenerator<z.output<Shape[option]>> : never
}
: never

Expand Down
2 changes: 1 addition & 1 deletion lib/types/src/schema/eslint.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { z } from 'zod'

export const ESLintSchema = z.object({
files: z.string().array(),
files: z.string().array().default(['**/*.js']),
config: z.record(z.unknown()).optional(), // @deprecated: use options instead
options: z.record(z.unknown()).optional()
})
Expand Down
2 changes: 1 addition & 1 deletion lib/types/src/schema/mocha.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { z } from 'zod'

export const MochaSchema = z.object({
files: z.string(),
files: z.string().default('test/**/*.js'),
configPath: z.string().optional()
})
export type MochaOptions = z.infer<typeof MochaSchema>
Expand Down
6 changes: 3 additions & 3 deletions lib/types/src/schema/node.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { z } from 'zod'

export const NodeSchema = z.object({
entry: z.string().optional(),
entry: z.string().default('./server/app.js'),
args: z.string().array().optional(),
useVault: z.boolean().optional(),
ports: z.number().array().optional()
useVault: z.boolean().default(true),
ports: z.number().array().default([3001, 3002, 3003])
})
export type NodeOptions = z.infer<typeof NodeSchema>

Expand Down
6 changes: 3 additions & 3 deletions lib/types/src/schema/nodemon.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { z } from 'zod'

export const NodemonSchema = z.object({
entry: z.string().optional(),
entry: z.string().default('./server/app.js'),
configPath: z.string().optional(),
useVault: z.boolean().optional(),
ports: z.number().array().optional()
useVault: z.boolean().default(true),
ports: z.number().array().default([3001, 3002, 3003])
})
export type NodemonOptions = z.infer<typeof NodemonSchema>

Expand Down
12 changes: 9 additions & 3 deletions lib/types/src/schema/prettier.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { z } from 'zod'

export const PrettierSchema = z.object({
files: z.string().array(),
files: z.string().array().default(['**/*.{js,jsx,ts,tsx}']),
configFile: z.string().optional(),
ignoreFile: z.string().optional(),
configOptions: z.record(z.unknown())
ignoreFile: z.string().default('.prettierignore'),
configOptions: z.record(z.unknown()).default({
singleQuote: true,
useTabs: true,
bracketSpacing: true,
arrowParens: 'always',
trailingComma: 'none'
})
})
export type PrettierOptions = z.infer<typeof PrettierSchema>

Expand Down
4 changes: 2 additions & 2 deletions lib/types/src/schema/serverless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { z } from 'zod'

export const ServerlessSchema = z.object({
configPath: z.string().optional(),
useVault: z.boolean().optional(),
ports: z.number().array().optional()
useVault: z.boolean().default(true),
ports: z.number().array().default([3001, 3002, 3003])
})
export type ServerlessOptions = z.infer<typeof ServerlessSchema>

Expand Down
18 changes: 9 additions & 9 deletions lib/types/src/schema/upload-assets-to-s3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { z } from 'zod'
export const UploadAssetsToS3Schema = z.object({
accessKeyIdEnvVar: z.string().optional(),
secretAccessKeyEnvVar: z.string().optional(),
accessKeyId: z.string().optional(), // @deprecated: use accessKeyIdEnvVar instead
secretAccessKey: z.string().optional(), // @deprecated: use secretAccessKeyEnvVar instead
directory: z.string(),
reviewBucket: z.string().array(),
prodBucket: z.string().array(),
region: z.string(),
destination: z.string(),
extensions: z.string(),
cacheControl: z.string()
accessKeyId: z.string().default('aws_access_hashed_assets'), // @deprecated: use accessKeyIdEnvVar instead
secretAccessKey: z.string().default('aws_secret_hashed_assets'), // @deprecated: use secretAccessKeyEnvVar instead
directory: z.string().default('public'),
reviewBucket: z.string().array().default(['ft-next-hashed-assets-preview']),
prodBucket: z.string().array().default(['ft-next-hashed-assets-prod']),
region: z.string().default('eu-west-1'),
destination: z.string().default('hashed-assets/page-kit'),
extensions: z.string().default('js,css,map,gz,br,png,jpg,jpeg,gif,webp,svg,ico,json'),
cacheControl: z.string().default('public, max-age=31536000, stale-while-revalidate=60, stale-if-error=3600')
})
export type UploadAssetsToS3Options = z.infer<typeof UploadAssetsToS3Schema>

Expand Down
6 changes: 1 addition & 5 deletions plugins/eslint/src/tasks/eslint.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import { ToolKitError } from '@dotcom-tool-kit/error'
import { styles } from '@dotcom-tool-kit/logger'
import { Task } from '@dotcom-tool-kit/types'
import { ESLintOptions, ESLintSchema } from '@dotcom-tool-kit/types/lib/schema/eslint'
import { ESLintSchema } from '@dotcom-tool-kit/types/lib/schema/eslint'
import { ESLint } from 'eslint'

export default class Eslint extends Task<typeof ESLintSchema> {
static description = ''

static defaultOptions: ESLintOptions = {
files: ['**/*.js']
}

async run(files?: string[]): Promise<void> {
const eslint = new ESLint(this.options.options)
const results = await eslint.lintFiles(files ?? this.options.files)
Expand Down
6 changes: 1 addition & 5 deletions plugins/mocha/src/tasks/mocha.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger'
import { Task } from '@dotcom-tool-kit/types'
import { glob } from 'glob'
import { MochaOptions, MochaSchema } from '@dotcom-tool-kit/types/lib/schema/mocha'
import { MochaSchema } from '@dotcom-tool-kit/types/lib/schema/mocha'
import { fork } from 'child_process'
import { promisify } from 'util'
const mochaCLIPath = require.resolve('mocha/bin/mocha')

export default class Mocha extends Task<typeof MochaSchema> {
static description = ''

static defaultOptions: MochaOptions = {
files: 'test/**/*.js'
}

async run(): Promise<void> {
const files = await promisify(glob)(this.options.files)

Expand Down
8 changes: 1 addition & 7 deletions plugins/node/src/tasks/node.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Task } from '@dotcom-tool-kit/types'
import { NodeOptions, NodeSchema } from '@dotcom-tool-kit/types/lib/schema/node'
import { NodeSchema } from '@dotcom-tool-kit/types/lib/schema/node'
import { ToolKitError } from '@dotcom-tool-kit/error'
import { fork } from 'child_process'
import { VaultEnvVars } from '@dotcom-tool-kit/vault'
Expand All @@ -11,12 +11,6 @@ import waitPort from 'wait-port'
export default class Node extends Task<typeof NodeSchema> {
static description = ''

static defaultOptions: NodeOptions = {
entry: './server/app.js',
useVault: true,
ports: [3001, 3002, 3003]
}

async run(): Promise<void> {
const { entry, args, useVault, ports } = this.options

Expand Down
8 changes: 1 addition & 7 deletions plugins/nodemon/src/tasks/nodemon.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ToolKitError } from '@dotcom-tool-kit/error'
import { hookFork, styles } from '@dotcom-tool-kit/logger'
import { Task } from '@dotcom-tool-kit/types'
import { NodemonOptions, NodemonSchema } from '@dotcom-tool-kit/types/lib/schema/nodemon'
import { NodemonSchema } from '@dotcom-tool-kit/types/lib/schema/nodemon'
import { writeState } from '@dotcom-tool-kit/state'
import { VaultEnvVars } from '@dotcom-tool-kit/vault'
import getPort from 'get-port'
Expand All @@ -11,12 +11,6 @@ import { Readable } from 'stream'
export default class Nodemon extends Task<typeof NodemonSchema> {
static description = ''

static defaultOptions: NodemonOptions = {
entry: './server/app.js',
useVault: true,
ports: [3001, 3002, 3003]
}

async run(): Promise<void> {
const { entry, configPath, useVault, ports } = this.options

Expand Down
12 changes: 0 additions & 12 deletions plugins/prettier/src/tasks/prettier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,6 @@ import { ToolKitError } from '@dotcom-tool-kit/error'
export default class Prettier extends Task<typeof PrettierSchema> {
static description = ''

static defaultOptions: PrettierOptions = {
files: ['**/*.{js,jsx,ts,tsx}'],
ignoreFile: '.prettierignore',
configOptions: {
singleQuote: true,
useTabs: true,
bracketSpacing: true,
arrowParens: 'always',
trailingComma: 'none'
}
}

async run(files?: string[]): Promise<void> {
try {
const filepaths = await fg(files ?? this.options.files)
Expand Down
7 changes: 1 addition & 6 deletions plugins/serverless/src/tasks/run.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Task } from '@dotcom-tool-kit/types'
import { ServerlessOptions, ServerlessSchema } from '@dotcom-tool-kit/types/lib/schema/serverless'
import { ServerlessSchema } from '@dotcom-tool-kit/types/lib/schema/serverless'
import { spawn } from 'child_process'
import { VaultEnvVars } from '@dotcom-tool-kit/vault'
import { hookConsole, hookFork } from '@dotcom-tool-kit/logger'
Expand All @@ -9,11 +9,6 @@ import waitPort from 'wait-port'
export default class ServerlessRun extends Task<typeof ServerlessSchema> {
static description = 'Run serverless functions locally'

static defaultOptions: ServerlessOptions = {
useVault: true,
ports: [3001, 3002, 3003]
}

async run(): Promise<void> {
const { useVault, ports, configPath } = this.options

Expand Down
16 changes: 2 additions & 14 deletions plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,6 @@ import {
export default class UploadAssetsToS3 extends Task<typeof UploadAssetsToS3Schema> {
static description = ''

static defaultOptions: UploadAssetsToS3Options = {
accessKeyId: 'aws_access_hashed_assets',
secretAccessKey: 'aws_secret_hashed_assets',
directory: 'public',
reviewBucket: ['ft-next-hashed-assets-preview'],
prodBucket: ['ft-next-hashed-assets-prod'],
region: 'eu-west-1',
destination: 'hashed-assets/page-kit',
extensions: 'js,css,map,gz,br,png,jpg,jpeg,gif,webp,svg,ico,json',
cacheControl: 'public, max-age=31536000, stale-while-revalidate=60, stale-if-error=3600'
}

async run(): Promise<void> {
await this.uploadAssetsToS3(this.options)
}
Expand Down Expand Up @@ -94,10 +82,10 @@ export default class UploadAssetsToS3 extends Task<typeof UploadAssetsToS3Schema
credentials: {
accessKeyId:
/* eslint-disable-next-line */
process.env[options.accessKeyIdEnvVar ?? options.accessKeyId!]!,
process.env[options.accessKeyIdEnvVar ?? options.accessKeyId]!,
secretAccessKey:
/* eslint-disable-next-line */
process.env[options.secretAccessKeyEnvVar ?? options.secretAccessKey!]!
process.env[options.secretAccessKeyEnvVar ?? options.secretAccessKey]!
}
})

Expand Down

0 comments on commit 7c03517

Please sign in to comment.