Skip to content

Commit

Permalink
cli: type src/lib
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkPollmann committed May 19, 2020
1 parent ff73a53 commit 0b08663
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 66 deletions.
2 changes: 2 additions & 0 deletions packages/cli/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ declare module 'pascalcase' {
function pascalcase(input: string): string
export default pascalcase
}

declare module 'listr-verbose-renderer'
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
},
"devDependencies": {
"@types/listr": "^0.14.2",
"@types/lodash": "^4.14.151",
"@types/node-fetch": "^2.5.5",
"@types/pluralize": "^0.0.29",
"@types/yargs": "^15.0.5",
Expand Down
8 changes: 4 additions & 4 deletions packages/cli/src/commands/generate/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import Listr from 'listr'
import pascalcase from 'pascalcase'
import { paramCase } from 'param-case'
import { CommandModule } from 'yargs'

import { generateTemplate, getPaths, writeFilesTask } from 'src/lib'
import c from 'src/lib/colors'
import { Paths } from '@redwoodjs/internal/src/types'

/**
* Reduces boilerplate for generating an output path and content to write to disk
Expand All @@ -31,8 +31,8 @@ export const templateForComponentFile = ({
name: string
suffix?: string
extension?: string
webPathSection?: string
apiPathSection?: string
webPathSection?: keyof Paths['web']
apiPathSection?: keyof Paths['api']
generator: string
templatePath: string
templateVars?: {}
Expand Down Expand Up @@ -93,7 +93,7 @@ export const createYargsForComponentGeneration = ({
},
},
],
{ exitOnError: true }
{ collapse: false, exitOnError: true }
)

try {
Expand Down
2 changes: 0 additions & 2 deletions packages/cli/src/lib/__tests__/fixtures/code.js

This file was deleted.

2 changes: 2 additions & 0 deletions packages/cli/src/lib/__tests__/fixtures/code.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const line1 = 'The quick brown ${pluralCamelName} jumps over the lazy ${foo}.'
const line2 = 'Sphinx of black quartz, judge my vow.'
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ test('generateTemplate returns a lodash-templated string', () => {
// Be careful when editing the code.js fixture as the prettifier.config.js will cause it to get
// prettified and then it already match the expected output, with no changes
test('generateTemplate returns prettified JS code', () => {
const output = index.generateTemplate(path.join('fixtures', 'code.js'), {
const output = index.generateTemplate(path.join('fixtures', 'code.ts'), {
root: __dirname,
name: 'fox',
foo: 'dog',
Expand Down
File renamed without changes.
121 changes: 69 additions & 52 deletions packages/cli/src/lib/index.js → packages/cli/src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fs from 'fs'
import path from 'path'

import lodash from 'lodash/string'
import lodash from 'lodash'
import camelcase from 'camelcase'
import pascalcase from 'pascalcase'
import pluralize from 'pluralize'
Expand All @@ -16,18 +16,57 @@ import { format } from 'prettier'

import c from './colors'

export const asyncForEach = async (array, callback) => {
export const asyncForEach = async (array: any[], callback: Function) => {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array)
}
}

export const readFile = (target: Parameters<typeof fs['readFileSync']>[0]) =>
fs.readFileSync(target)

/**
* This wraps the core version of getPaths into something that catches the exception
* and displays a helpful error message.
*/
export const getPaths = () => {
try {
return getRedwoodPaths()
} catch (e) {
console.error(c.error(e.message))
process.exit(0)
}
}

/*
* Returns the DMMF defined by `prisma` resolving the relevant `shema.prisma` path.
*/
export const getSchemaDefinitions = async () => {
const schemaPath = path.join(getPaths().api.db, 'schema.prisma')
const metadata = await getDMMF({
datamodel: readFile(schemaPath).toString(),
})

return metadata
}

/**
* This returns the config present in `prettier.config.js` of a Redwood project.
*/
export const prettierOptions = () => {
try {
return require(path.join(getPaths().base, 'prettier.config.js'))
} catch (e) {
return undefined
}
}

/**
* Returns the database schema for the given `name` database table parsed from
* the schema.prisma of the target applicaiton. If no `name` is given then the
* entire schema is returned.
*/
export const getSchema = async (name) => {
export const getSchema = async (name: string) => {
const schema = await getSchemaDefinitions()

if (name) {
Expand All @@ -49,10 +88,10 @@ export const getSchema = async (name) => {

/**
* Returns the enum defined with the given `name` parsed from
* the schema.prisma of the target applicaiton. If no `name` is given then the
* the schema.prisma of the target application. If no `name` is given then the
* all enum definitions are returned
*/
export const getEnum = async (name) => {
export const getEnum = async (name: string) => {
const schema = await getSchemaDefinitions()

if (name) {
Expand All @@ -72,18 +111,6 @@ export const getEnum = async (name) => {
return schema.metadata.datamodel.enums
}

/*
* Returns the DMMF defined by `prisma` resolving the relevant `shema.prisma` path.
*/
export const getSchemaDefinitions = async () => {
const schemaPath = path.join(getPaths().api.db, 'schema.prisma')
const metadata = await getDMMF({
datamodel: readFile(schemaPath.toString()),
})

return metadata
}

/**
* Returns variants of the passed `name` for usage in templates. If the given
* name was "fooBar" then these would be:
Expand All @@ -98,7 +125,7 @@ export const getSchemaDefinitions = async () => {
* singularConstantName: FOO_BAR
* pluralConstantName: FOO_BARS
*/
export const nameVariants = (name) => {
export const nameVariants = (name: string) => {
const normalizedName = pascalcase(paramCase(pluralize.singular(name)))

return {
Expand All @@ -117,7 +144,10 @@ export const nameVariants = (name) => {

export const templateRoot = path.resolve(__dirname, '../commands/generate')

export const generateTemplate = (templateFilename, { name, root, ...rest }) => {
export const generateTemplate = (
templateFilename: string,
{ name, root, ...rest }: { [key: string]: any }
) => {
const templatePath = path.join(root || templateRoot, templateFilename)
const template = lodash.template(readFile(templatePath).toString())

Expand All @@ -133,7 +163,7 @@ export const generateTemplate = (templateFilename, { name, root, ...rest }) => {
const parser = {
'.css': 'css',
'.js': 'babel',
}[path.extname(templateFilename)]
}[path.extname(templateFilename) as '.css' | '.js']

if (typeof parser === 'undefined') {
return renderedTemplate
Expand All @@ -145,11 +175,9 @@ export const generateTemplate = (templateFilename, { name, root, ...rest }) => {
})
}

export const readFile = (target) => fs.readFileSync(target)

export const writeFile = async (
target,
contents,
target: string,
contents: string | object,
{ overwriteExisting = false } = {}
) => {
if (!overwriteExisting && fs.existsSync(target)) {
Expand All @@ -162,38 +190,18 @@ export const writeFile = async (
fs.writeFileSync(target, contents)
}

export const bytes = (contents) => Buffer.byteLength(contents, 'utf8')

/**
* This wraps the core version of getPaths into something that catches the exception
* and displays a helpful error message.
*/
export const getPaths = () => {
try {
return getRedwoodPaths()
} catch (e) {
console.error(c.error(e.message))
process.exit(0)
}
}

/**
* This returns the config present in `prettier.config.js` of a Redwood project.
*/
export const prettierOptions = () => {
try {
return require(path.join(getPaths().base, 'prettier.config.js'))
} catch (e) {
return undefined
}
}
export const bytes = (contents: Parameters<typeof Buffer['byteLength']>[0]) =>
Buffer.byteLength(contents, 'utf8')

/**
* Creates a list of tasks that write files to the disk.
*
* @param files - {[filepath]: contents}
*/
export const writeFilesTask = (files, options) => {
export const writeFilesTask = (
files: { [filepath: string]: string },
options: { overwriteExisting: boolean }
) => {
const { base } = getPaths()
return new Listr(
Object.keys(files).map((file) => {
Expand All @@ -209,7 +217,7 @@ export const writeFilesTask = (files, options) => {
/**
* Update the project's routes file.
*/
export const addRoutesToRouterTask = (routes) => {
export const addRoutesToRouterTask = (routes: string[]) => {
const redwoodPaths = getPaths()
const routesContent = readFile(redwoodPaths.web.routes).toString()
const newRoutesContent = routes.reverse().reduce((content, route) => {
Expand All @@ -223,7 +231,15 @@ export const addRoutesToRouterTask = (routes) => {
})
}

export const runCommandTask = async (commands, { verbose }) => {
export const runCommandTask = async (
commands: {
title: string
cmd: string
args: string[]
opts: execa.Options
}[],
{ verbose }: { verbose: boolean }
) => {
const tasks = new Listr(
commands.map(({ title, cmd, args, opts = {} }) => ({
title,
Expand All @@ -240,6 +256,7 @@ export const runCommandTask = async (commands, { verbose }) => {
})),
{
renderer: verbose && VerboseRenderer,
// @ts-ignore TODO dateFormat comes from listr-verbose-renderer
dateFormat: false,
}
)
Expand Down
12 changes: 6 additions & 6 deletions packages/cli/src/lib/test.js → packages/cli/src/lib/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,19 @@ export const generatorsRootPath = path.join(
'generate'
)

// Returns the contents of a text file suffixed with ".fixture"
export const loadFixture = (filepath: string) => {
return fs.readFileSync(filepath).toString()
}

// Loads the fixture for a generator by assuming a lot of the path structure automatically:
//
// loadGeneratorFixture('scaffold', 'NamePage.js')
//
// will return the contents of:
//
// cli/src/commands/generate/scaffold/test/fixtures/NamePage.js.fixture
export const loadGeneratorFixture = (generator, name) => {
export const loadGeneratorFixture = (generator: string, name: string) => {
return loadFixture(
path.join(
__dirname,
Expand All @@ -64,8 +69,3 @@ export const loadGeneratorFixture = (generator, name) => {
)
)
}

// Returns the contents of a text file suffixed with ".fixture"
export const loadFixture = (filepath) => {
return fs.readFileSync(filepath).toString()
}
3 changes: 2 additions & 1 deletion packages/cli/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"compilerOptions": {
"baseUrl": ".",
"rootDir": "src",
"outDir": "dist"
"outDir": "dist",
"esModuleInterop": true
},
"include": ["src", "index.d.ts"],
}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2722,6 +2722,11 @@
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.150.tgz#649fe44684c3f1fcb6164d943c5a61977e8cf0bd"
integrity sha512-kMNLM5JBcasgYscD9x/Gvr6lTAv2NVgsKtet/hm93qMyf/D1pt+7jeEZklKJKxMVmXjxbRVQQGfqDSfipYCO6w==

"@types/lodash@^4.14.151":
version "4.14.151"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.151.tgz#7d58cac32bedb0ec37cb7f99094a167d6176c9d5"
integrity sha512-Zst90IcBX5wnwSu7CAS0vvJkTjTELY4ssKbHiTnGcJgi170uiS8yQDdc3v6S77bRqYQIN1App5a1Pc2lceE5/g==

"@types/long@^4.0.0":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
Expand Down

0 comments on commit 0b08663

Please sign in to comment.