Skip to content

Commit

Permalink
feat(cli): Improve generated application folder structure (#2678)
Browse files Browse the repository at this point in the history
  • Loading branch information
daffl authored Jun 24, 2022
1 parent 56f828f commit d114557
Show file tree
Hide file tree
Showing 21 changed files with 262 additions and 231 deletions.
4 changes: 2 additions & 2 deletions packages/cli/src/app/templates/app.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { koa, rest, bodyParser, errorHandler, parseAuthentication } from '@feath
${transports.includes('websockets') ? "import socketio from '@feathersjs/socketio'" : ''}
import type { Application } from './declarations'
import { configurationSchema } from './schemas/configuration.schema'
import { configurationSchema } from './configuration'
import { logErrorHook } from './logger'
import { services } from './services/index'
import { channels } from './channels'
Expand Down Expand Up @@ -63,7 +63,7 @@ import configuration from '@feathersjs/configuration'
${transports.includes('websockets') ? "import socketio from '@feathersjs/socketio'" : ''}
import type { Application } from './declarations'
import { configurationSchema } from './schemas/configuration.schema'
import { configurationSchema } from './configuration'
import { logger, logErrorHook } from './logger'
import { services } from './services/index'
import { channels } from './channels'
Expand Down
43 changes: 23 additions & 20 deletions packages/cli/src/app/templates/configuration.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,30 @@ const template = ({}: AppGeneratorContext) =>
import type { Infer } from '@feathersjs/schema'
import { authenticationSettingsSchema } from '@feathersjs/authentication'
export const configurationSchema = schema({
$id: 'ApplicationConfiguration',
type: 'object',
additionalProperties: false,
required: [ 'host', 'port', 'public', 'paginate' ],
properties: {
host: { type: 'string' },
port: { type: 'number' },
public: { type: 'string' },
authentication: authenticationSettingsSchema,
paginate: {
type: 'object',
additionalProperties: false,
required: [ 'default', 'max' ],
properties: {
default: { type: 'number' },
max: { type: 'number' }
export const configurationSchema = schema(
{
$id: 'ApplicationConfiguration',
type: 'object',
additionalProperties: false,
required: [ 'host', 'port', 'public', 'paginate' ],
properties: {
host: { type: 'string' },
port: { type: 'number' },
public: { type: 'string' },
authentication: authenticationSettingsSchema,
paginate: {
type: 'object',
additionalProperties: false,
required: [ 'default', 'max' ],
properties: {
default: { type: 'number' },
max: { type: 'number' }
}
}
}
}
} as const, new Ajv())
} as const,
new Ajv()
)
export type ConfigurationSchema = Infer<typeof configurationSchema>
`
Expand All @@ -36,6 +39,6 @@ export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(
renderSource(
template,
toFile<AppGeneratorContext>(({ lib }) => lib, 'schemas', 'configuration.schema')
toFile<AppGeneratorContext>(({ lib }) => lib, 'configuration')
)
)
2 changes: 1 addition & 1 deletion packages/cli/src/app/templates/declarations.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AppGeneratorContext } from '../index'
const template = ({ framework }: AppGeneratorContext) =>
`import { HookContext as FeathersHookContext, NextFunction } from '@feathersjs/feathers'
import { Application as FeathersApplication } from '@feathersjs/${framework}'
import { ConfigurationSchema } from './schemas/configuration.schema'
import { ConfigurationSchema } from './configuration'
export { NextFunction }
Expand Down
10 changes: 5 additions & 5 deletions packages/cli/src/authentication/templates/authentication.tpl.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { generator, inject, before, toFile } from '@feathershq/pinion'
import { getSource, renderSource } from '../../commons'
import { generator, before, toFile } from '@feathershq/pinion'
import { injectSource, renderSource } from '../../commons'
import { AuthenticationGeneratorContext } from '../index'

const template = ({ authStrategies, feathers }: AuthenticationGeneratorContext) =>
Expand Down Expand Up @@ -39,7 +39,7 @@ export const authentication = (app: Application) => {

const importTemplate = "import { authentication } from './authentication'"
const configureTemplate = 'app.configure(authentication)'
const toAppFile = toFile<AuthenticationGeneratorContext>(({ lib, language }) => [lib, `app.${language}`])
const toAppFile = toFile<AuthenticationGeneratorContext>(({ lib }) => [lib, 'app'])

export const generate = (ctx: AuthenticationGeneratorContext) =>
generator(ctx)
Expand All @@ -49,5 +49,5 @@ export const generate = (ctx: AuthenticationGeneratorContext) =>
toFile<AuthenticationGeneratorContext>(({ lib }) => lib, 'authentication')
)
)
.then(inject(getSource(importTemplate), before('import { services } from'), toAppFile))
.then(inject(getSource(configureTemplate), before('app.configure(services)'), toAppFile))
.then(injectSource(importTemplate, before('import { services } from'), toAppFile))
.then(injectSource(configureTemplate, before('app.configure(services)'), toAppFile))
4 changes: 2 additions & 2 deletions packages/cli/src/authentication/templates/declarations.tpl.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { generator, inject, before, toFile, when, append } from '@feathershq/pinion'
import { AuthenticationGeneratorContext } from '../index'

const importTemplate = ({ upperName, schemaPath }: AuthenticationGeneratorContext) =>
`import { ${upperName}Result } from './${schemaPath}'
const importTemplate = ({ upperName, folder, fileName }: AuthenticationGeneratorContext) =>
`import { ${upperName}Result } from './services/${folder.join('/')}/${fileName}.schema'
`

const paramsTemplate = ({
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/authentication/templates/test.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { generator, toFile } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { AuthenticationGeneratorContext } from '../index'

const template = ({ authStrategies, relative, lib }: AuthenticationGeneratorContext) =>
const template = ({ authStrategies, lib }: AuthenticationGeneratorContext) =>
`import assert from 'assert';
import { app } from '${relative}/${lib}/app';
import { app } from '../${lib}/app';
describe('authentication', () => {
${
Expand Down
12 changes: 6 additions & 6 deletions packages/cli/src/authentication/templates/user.resolver.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const template = ({
relative,
authStrategies,
type,
schemaPath
fileName
}: AuthenticationGeneratorContext) =>
`import { resolve } from '@feathersjs/schema'
${authStrategies.includes('local') ? `import { passwordHash } from '@feathersjs/authentication-local'` : ''}
Expand All @@ -18,13 +18,13 @@ import type {
${upperName}Patch,
${upperName}Result,
${upperName}Query,
} from '../${schemaPath}'
} from './${fileName}.schema'
import {
${camelName}DataSchema,
${camelName}PatchSchema,
${camelName}ResultSchema,
${camelName}QuerySchema
} from '../${schemaPath}'
} from './${fileName}.schema'
// Resolver for the basic data model (e.g. creating new entries)
Expand Down Expand Up @@ -98,11 +98,11 @@ export const generate = (ctx: AuthenticationGeneratorContext) =>
generator(ctx).then(
renderSource(
template,
toFile(({ lib, folder, kebabName }: AuthenticationGeneratorContext) => [
toFile(({ lib, folder, fileName }: AuthenticationGeneratorContext) => [
lib,
'resolvers',
'services',
...folder,
`${kebabName}.resolver`
`${fileName}.resolver`
]),
{ force: true }
)
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/authentication/templates/user.schema.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ export const generate = (ctx: AuthenticationGeneratorContext) =>
generator(ctx).then(
renderSource(
template,
toFile(({ lib, folder, kebabName }: AuthenticationGeneratorContext) => [
toFile(({ lib, folder, fileName }: AuthenticationGeneratorContext) => [
lib,
'schemas',
'services',
...folder,
`${kebabName}.schema`
`${fileName}.schema`
]),
{ force: true }
)
Expand Down
43 changes: 29 additions & 14 deletions packages/cli/src/commons.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { PackageJson } from 'type-fest'
import { Callable, PinionContext, loadJSON, fromFile, getCallable, renderTemplate } from '@feathershq/pinion'
import {
Callable,
PinionContext,
loadJSON,
fromFile,
getCallable,
renderTemplate,
inject,
Location
} from '@feathershq/pinion'
import * as ts from 'typescript'
import prettier from 'prettier'
import path from 'path'
Expand Down Expand Up @@ -145,8 +154,7 @@ export const getJavaScript = (typescript: string, options: ts.TranspileOptions =
}

/**
* Render a source file template for the language set in the context. Will do nothing
* it there is no template for the selected language.
* Render a source file template for the language set in the context.
*
* @param templates The JavaScript and TypeScript template to render
* @param toFile The target filename without extension (will be added based on language)
Expand All @@ -159,10 +167,6 @@ export const renderSource =
options?: { force: boolean }
) =>
async (ctx: C) => {
if (!template) {
return ctx
}

const { language } = ctx
const fileName = await getCallable<string, C>(toFile, ctx)
const content = language === 'js' ? getJavaScript(await getCallable<string, C>(template, ctx)) : template
Expand All @@ -172,16 +176,27 @@ export const renderSource =
}

/**
* Returns the TypeScript or transpiled JavaScript source code
* Inject a source template as the language set in the context.
*
* @param template The source template
* @param template The source template to render
* @param location The location to inject the code to. Must use the target language.
* @param target The target file name
* @param transpile Set to `false` if the code should not be transpiled to JavaScript
* @returns
*/
export const getSource =
<C extends PinionContext & { language: 'js' | 'ts' }>(template: Callable<string, C>) =>
async <T extends C>(ctx: T) => {
export const injectSource =
<C extends PinionContext & { language: 'js' | 'ts' }>(
template: Callable<string, C>,
location: Location<C>,
target: Callable<string, C>,
transpile = true
) =>
async (ctx: C) => {
const { language } = ctx
const source = await getCallable<string, C>(template, ctx)
const source =
language === 'js' && transpile ? getJavaScript(await getCallable<string, C>(template, ctx)) : template
const toFile = await getCallable<string, C>(target, ctx)
const injector = inject(source, location, `${toFile}.${language}`)

return language === 'js' ? getJavaScript(source) : source
return injector(ctx)
}
33 changes: 15 additions & 18 deletions packages/cli/src/connection/templates/knex.tpl.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { generator, toFile, inject, before, mergeJSON } from '@feathershq/pinion'
import { generator, toFile, before, mergeJSON } from '@feathershq/pinion'
import { ConnectionGeneratorContext } from '../index'
import { getSource, renderSource } from '../../commons'
import { injectSource, renderSource } from '../../commons'

const template = ({ database }: ConnectionGeneratorContext) =>
`import knex from 'knex'
Expand Down Expand Up @@ -30,18 +30,18 @@ const config = app.get('${database}')
${language === 'js' ? 'export default config' : 'module.exports = config'}
`

const configurationTemplate = ({ database }: ConnectionGeneratorContext) => ` ${database}: {
type: 'object',
properties: {
client: { type: 'string' },
connection: { type: 'string' }
}
},`
const configurationTemplate = ({ database }: ConnectionGeneratorContext) => ` ${database}: {
type: 'object',
properties: {
client: { type: 'string' },
connection: { type: 'string' }
}
},`

const importTemplate = ({ database }: ConnectionGeneratorContext) =>
`import { ${database} } from './${database}'`
const configureTemplate = ({ database }: ConnectionGeneratorContext) => `app.configure(${database})`
const toAppFile = toFile<ConnectionGeneratorContext>(({ lib, language }) => [lib, `app.${language}`])
const toAppFile = toFile<ConnectionGeneratorContext>(({ lib }) => [lib, 'app'])

export const generate = (ctx: ConnectionGeneratorContext) =>
generator(ctx)
Expand All @@ -65,15 +65,12 @@ export const generate = (ctx: ConnectionGeneratorContext) =>
)
)
.then(
inject(
injectSource(
configurationTemplate,
before('authentication: authenticationSettingsSchema'),
toFile<ConnectionGeneratorContext>(({ lib, language }) => [
lib,
'schemas',
`configuration.schema.${language}`
])
toFile<ConnectionGeneratorContext>(({ lib }) => [lib, 'configuration']),
false
)
)
.then(inject(getSource(importTemplate), before('import { services } from'), toAppFile))
.then(inject(getSource(configureTemplate), before('app.configure(services)'), toAppFile))
.then(injectSource(importTemplate, before('import { services } from'), toAppFile))
.then(injectSource(configureTemplate, before('app.configure(services)'), toAppFile))
22 changes: 10 additions & 12 deletions packages/cli/src/connection/templates/mongodb.tpl.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { generator, toFile, inject, before } from '@feathershq/pinion'
import { generator, toFile, before } from '@feathershq/pinion'
import { ConnectionGeneratorContext } from '../index'
import { getSource, renderSource } from '../../commons'
import { injectSource, renderSource } from '../../commons'

const template = ({}: ConnectionGeneratorContext) =>
`import { MongoClient } from 'mongodb'
Expand All @@ -22,11 +22,12 @@ export const mongodb = (app: Application) => {
app.set('mongodbClient', mongoClient)
}
`

const configurationTemplate = ({ database }: ConnectionGeneratorContext) =>
` ${database}: { type: 'string' },`
` ${database}: { type: 'string' },`
const importTemplate = "import { mongodb } from './mongodb'"
const configureTemplate = 'app.configure(mongodb)'
const toAppFile = toFile<ConnectionGeneratorContext>(({ lib, language }) => [lib, `app.${language}`])
const toAppFile = toFile<ConnectionGeneratorContext>(({ lib }) => [lib, 'app'])

export const generate = (ctx: ConnectionGeneratorContext) =>
generator(ctx)
Expand All @@ -37,15 +38,12 @@ export const generate = (ctx: ConnectionGeneratorContext) =>
)
)
.then(
inject(
injectSource(
configurationTemplate,
before('authentication: authenticationSettingsSchema'),
toFile<ConnectionGeneratorContext>(({ lib, language }) => [
lib,
'schemas',
`configuration.schema.${language}`
])
toFile<ConnectionGeneratorContext>(({ lib }) => [lib, 'configuration']),
false
)
)
.then(inject(getSource(importTemplate), before('import { services } from'), toAppFile))
.then(inject(getSource(configureTemplate), before('app.configure(services)'), toAppFile))
.then(injectSource(importTemplate, before('import { services } from'), toAppFile))
.then(injectSource(configureTemplate, before('app.configure(services)'), toAppFile))
Loading

0 comments on commit d114557

Please # to comment.