feat(cli): Improve generated application folder structure (#2678)

This commit is contained in:
David Luecke 2022-06-24 07:21:03 -07:00 committed by GitHub
parent 56f828fa85
commit d114557721
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 262 additions and 231 deletions

View File

@ -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'
@ -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'

View File

@ -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>
`
@ -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')
)
)

View File

@ -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 }

View File

@ -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) =>
@ -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)
@ -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))

View File

@ -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 = ({

View File

@ -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', () => {
${

View File

@ -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'` : ''}
@ -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)
@ -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 }
)

View File

@ -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 }
)

View File

@ -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'
@ -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)
@ -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
@ -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)
}

View File

@ -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'
@ -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)
@ -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))

View File

@ -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'
@ -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)
@ -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))

View File

@ -52,14 +52,6 @@ export interface ServiceGeneratorContext extends FeathersBaseContext {
* Set to true if this service is for an authentication entity
*/
isEntityService?: boolean
/**
* The name of the schema file
*/
schemaPath: string
/**
* The name of the resolver file
*/
resolverPath: string
}
/**
@ -123,12 +115,9 @@ export const generate = (ctx: ServiceGeneratorArguments) =>
const upperName = _.upperFirst(camelName)
const className = `${upperName}Service`
const pathElements = path.split('/').filter((el) => el !== '')
const relative = pathElements.map(() => '..').join('/')
const folder = _.initial(pathElements)
const fileName = _.last(pathElements)
const schemaPath = ['schemas', ...folder, `${fileName}.schema`].join('/')
const resolverPath = ['resolvers', ...folder, `${fileName}.resolver`].join('/')
const folder = path.split('/').filter((el) => el !== '')
const relative = ['', ...folder].map(() => '..').join('/')
const fileName = _.last(folder)
return {
name,
@ -141,8 +130,6 @@ export const generate = (ctx: ServiceGeneratorArguments) =>
kebabName,
camelName,
relative,
resolverPath,
schemaPath,
...ctx
}
})

View File

@ -0,0 +1,79 @@
import { generator, toFile } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
const template = ({
camelName,
upperName,
fileName,
isEntityService,
authentication
}: ServiceGeneratorContext) =>
`import { resolveAll } from '@feathersjs/schema'
${isEntityService || authentication ? `import { authenticate } from '@feathersjs/authentication'` : ''}
import type {
${upperName}Data,
${upperName}Result,
${upperName}Query,
} from './${fileName}.schema'
import { ${camelName}Resolvers } from './${fileName}.resolver'
export const ${camelName}Hooks = {
around: {
all: [${
authentication
? `
authenticate('jwt'),`
: ''
} ${
!isEntityService
? `
resolveAll(${camelName}Resolvers)`
: ''
}
]${
isEntityService
? `,
get: [
authenticate('jwt'),
resolveAll(${camelName}Resolvers)
],
find: [
authenticate('jwt'),
resolveAll(${camelName}Resolvers)
],
create: [
resolveAll(${camelName}Resolvers)
],
patch: [
authenticate('jwt'),
resolveAll(${camelName}Resolvers)
],
update: [
authenticate('jwt'),
resolveAll(${camelName}Resolvers)
],
remove: [
authenticate('jwt'),
resolveAll(${camelName}Resolvers)
]`
: ''
}
},
before: {},
after: {},
error: {}
}
`
export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx).then(
renderSource(
template,
toFile<ServiceGeneratorContext>(({ lib, folder, fileName }) => [
lib,
'services',
...folder,
`${fileName}.class`
])
)
)

View File

@ -1,27 +1,22 @@
import { generator, inject, toFile, when, after } from '@feathershq/pinion'
import { ServiceGeneratorContext } from '../index'
const schemaImports = ({ upperName, schemaPath }: ServiceGeneratorContext) => `import type {
const schemaImports = ({ upperName, folder, fileName }: ServiceGeneratorContext) => `import type {
${upperName}Data,
${upperName}Result,
${upperName}Query,
} from './${schemaPath}'`
} from './services/${folder.join('/')}/${fileName}.schema'`
const declarationTemplate = ({ path, upperName }: ServiceGeneratorContext) =>
` '${path}': Service<${upperName}Data, ${upperName}Result, Params<${upperName}Query>>`
const toClientFile = toFile<ServiceGeneratorContext>(({ lib, language }) => [lib, `client.${language}`])
const toClientFile = toFile<ServiceGeneratorContext>(({ lib }) => [lib, 'client.ts'])
export const generate = async (ctx: ServiceGeneratorContext) =>
generator(ctx)
.then(
when(
(ctx) => ctx.language === 'ts',
inject(schemaImports, after("from '@feathersjs/feathers'"), toClientFile)
)
)
.then(
when(
(ctx) => ctx.language === 'ts',
inject(declarationTemplate, after('export interface ServiceTypes'), toClientFile)
)
generator(ctx).then(
when(
(ctx) => ctx.language === 'ts',
inject(schemaImports, after("from '@feathersjs/feathers'"), toClientFile),
inject(declarationTemplate, after('export interface ServiceTypes'), toClientFile)
)
)

View File

@ -2,7 +2,7 @@ import { generator, toFile } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
const template = ({ camelName, upperName, relative, schemaPath }: ServiceGeneratorContext) =>
const template = ({ camelName, upperName, relative, fileName }: ServiceGeneratorContext) =>
`import { resolve } from '@feathersjs/schema'
import type { HookContext } from '${relative}/declarations'
@ -11,13 +11,13 @@ import type {
${upperName}Patch,
${upperName}Result,
${upperName}Query,
} from '${relative}/${schemaPath}'
} from './${fileName}.schema'
import {
${camelName}DataSchema,
${camelName}PatchSchema,
${camelName}ResultSchema,
${camelName}QuerySchema
} from '${relative}/${schemaPath}'
} from './${fileName}.schema'
// Resolver for the basic data model (e.g. creating new entries)
@ -70,7 +70,7 @@ export const generate = (ctx: ServiceGeneratorContext) =>
template,
toFile(({ lib, folder, fileName }: ServiceGeneratorContext) => [
lib,
'resolvers',
'services',
...folder,
`${fileName}.resolver`
])

View File

@ -72,7 +72,7 @@ export const generate = (ctx: ServiceGeneratorContext) =>
template,
toFile(({ lib, folder, fileName }: ServiceGeneratorContext) => [
lib,
'schemas',
'services',
...folder,
`${fileName}.schema`
])

View File

@ -1,74 +1,11 @@
import { generator, inject, prepend, toFile, after } from '@feathershq/pinion'
import { getSource, renderSource } from '../../commons'
import { generator, prepend, toFile, after } from '@feathershq/pinion'
import { injectSource, renderSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
const template = ({
relative,
path,
className,
schemaPath,
resolverPath,
camelName,
upperName,
isEntityService,
authentication
}: ServiceGeneratorContext) =>
`import { resolveAll } from '@feathersjs/schema'
${isEntityService || authentication ? `import { authenticate } from '@feathersjs/authentication'` : ''}
import type { Application } from '${relative}/declarations'
import type {
${upperName}Data,
${upperName}Result,
${upperName}Query,
} from '${relative}/${schemaPath}'
import { ${camelName}Resolvers } from '${relative}/${resolverPath}'
const template = ({ relative, path, className, camelName, fileName }: ServiceGeneratorContext) =>
`import type { Application } from '${relative}/declarations'
export const hooks = {
around: {
all: [${
authentication
? `
authenticate('jwt'),`
: ''
} ${
!isEntityService
? `
resolveAll(${camelName}Resolvers)`
: ''
}
]${
isEntityService
? `,
get: [
authenticate('jwt'),
resolveAll(${camelName}Resolvers)
],
find: [
authenticate('jwt'),
resolveAll(${camelName}Resolvers)
],
create: [
resolveAll(${camelName}Resolvers)
],
patch: [
authenticate('jwt'),
resolveAll(${camelName}Resolvers)
],
update: [
authenticate('jwt'),
resolveAll(${camelName}Resolvers)
],
remove: [
authenticate('jwt'),
resolveAll(${camelName}Resolvers)
]`
: ''
}
},
before: {},
after: {},
error: {}
}
import { ${className}, ${camelName}Hooks } from './${fileName}.class'
// A configure function that registers the service and its hooks via \`app.configure\`
export function ${camelName} (app: Application) {
@ -83,7 +20,7 @@ export function ${camelName} (app: Application) {
events: []
})
// Initialize hooks
app.service('${path}').hooks(hooks)
app.service('${path}').hooks(${camelName}Hooks)
}
// Add this service to the service type index
@ -94,24 +31,25 @@ declare module '${relative}/declarations' {
}
`
const importTemplate = ({ camelName, path }: ServiceGeneratorContext) =>
`import { ${camelName} } from './${path}'`
const importTemplate = ({ camelName, folder, fileName }: ServiceGeneratorContext) =>
`import { ${camelName} } from './${folder.join('/')}/${fileName}.service'`
const configureTemplate = ({ camelName }: ServiceGeneratorContext) => ` app.configure(${camelName})`
const toServiceIndex = toFile(({ lib, language }: ServiceGeneratorContext) => [
lib,
'services',
`index.${language}`
])
const toServiceIndex = toFile(({ lib }: ServiceGeneratorContext) => [lib, 'services', `index`])
export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx)
.then(
renderSource(
template,
toFile<ServiceGeneratorContext>(({ lib, folder, fileName }) => [lib, 'services', ...folder, fileName])
toFile<ServiceGeneratorContext>(({ lib, folder, fileName }) => [
lib,
'services',
...folder,
`${fileName}.service`
])
)
)
.then(inject(getSource(importTemplate), prepend(), toServiceIndex))
.then(inject(configureTemplate, after('export const services'), toServiceIndex))
.then(injectSource(importTemplate, prepend(), toServiceIndex))
.then(injectSource(configureTemplate, after('export const services'), toServiceIndex))

View File

@ -2,11 +2,11 @@ import { generator, toFile } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
const template = ({ relative, lib, path, name }: ServiceGeneratorContext) =>
const template = ({ relative, lib, path }: ServiceGeneratorContext) =>
`import assert from 'assert'
import { app } from '../${relative}/${lib}/app'
describe('${name} service', () => {
describe('${path} service', () => {
it('registered the service', () => {
const service = app.service('${path}')
@ -19,11 +19,11 @@ export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx).then(
renderSource(
template,
toFile<ServiceGeneratorContext>(({ test, folder, kebabName }) => [
toFile<ServiceGeneratorContext>(({ test, folder, fileName }) => [
test,
'services',
...folder,
`${kebabName}.test`
`${fileName}.test`
])
)
)

View File

@ -1,9 +1,11 @@
import { generator, inject, toFile, after, before, prepend } from '@feathershq/pinion'
import { getSource } from '../../commons'
import { generator, toFile, after, prepend, append } from '@feathershq/pinion'
import { injectSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
export const template = ({ className, upperName }: ServiceGeneratorContext) =>
`export interface ${className}Options {
export const template = ({ className, upperName, relative }: ServiceGeneratorContext) =>
`import type { Application } from '${relative}/declarations'
export interface ${className}Options {
app: Application
}
@ -67,15 +69,22 @@ export const importTemplate = "import type { Id, NullableId, Params } from '@fea
const optionTemplate = ({}: ServiceGeneratorContext) => ` app`
const toServiceFile = toFile<ServiceGeneratorContext>(({ lib, language, folder, fileName }) => [
const toServiceFile = toFile<ServiceGeneratorContext>(({ lib, folder, fileName }) => [
lib,
'services',
...folder,
`${fileName}.${language}`
`${fileName}.service`
])
const toClassFile = toFile<ServiceGeneratorContext>(({ lib, folder, fileName }) => [
lib,
'services',
...folder,
`${fileName}.class`
])
export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx)
.then(inject(getSource(template), before<ServiceGeneratorContext>('export const hooks ='), toServiceFile))
.then(inject(getSource(importTemplate), prepend(), toServiceFile))
.then(inject(optionTemplate, after('const options ='), toServiceFile))
.then(injectSource(template, append(), toClassFile))
.then(injectSource(importTemplate, prepend(), toClassFile))
.then(injectSource(optionTemplate, after('const options ='), toServiceFile, false))

View File

@ -1,5 +1,5 @@
import { generator, inject, toFile, before, after, prepend } from '@feathershq/pinion'
import { getSource, renderSource } from '../../commons'
import { generator, toFile, after, prepend, append } from '@feathershq/pinion'
import { injectSource, renderSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
const migrationTemplate = ({ kebabName }: ServiceGeneratorContext) => `import type { Knex } from 'knex'
@ -33,20 +33,25 @@ export const optionTemplate = ({ kebabName, feathers }: ServiceGeneratorContext)
Model: app.get('${feathers.database}Client'),
name: '${kebabName}'`
const toServiceFile = toFile<ServiceGeneratorContext>(({ lib, folder, fileName, language }) => [
const toServiceFile = toFile<ServiceGeneratorContext>(({ lib, folder, fileName }) => [
lib,
'services',
...folder,
`${fileName}.${language}`
`${fileName}.service`
])
const toClassFile = toFile<ServiceGeneratorContext>(({ lib, folder, fileName }) => [
lib,
'services',
...folder,
`${fileName}.class`
])
export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx)
.then(
inject(getSource(classCode), before<ServiceGeneratorContext>('export const hooks ='), toServiceFile)
)
.then(inject(getSource(importTemplate), prepend(), toServiceFile))
.then(inject(optionTemplate, after('const options ='), toServiceFile))
.then(injectSource(classCode, append(), toClassFile))
.then(injectSource(importTemplate, prepend(), toClassFile))
.then(injectSource(optionTemplate, after('const options ='), toServiceFile, false))
.then(
renderSource(
migrationTemplate,

View File

@ -1,5 +1,5 @@
import { generator, inject, toFile, before, after, prepend } from '@feathershq/pinion'
import { getSource } from '../../commons'
import { generator, toFile, after, prepend, append } from '@feathershq/pinion'
import { injectSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
export const importTemplate = `import { MongoDBService } from \'@feathersjs/mongodb\'
@ -18,17 +18,22 @@ const optionTemplate = ({ kebabName }: ServiceGeneratorContext) =>
` paginate: app.get('paginate'),
Model: app.get('mongodbClient').then(db => db.collection('${kebabName}'))`
const toServiceFile = toFile<ServiceGeneratorContext>(({ lib, folder, fileName, language }) => [
const toServiceFile = toFile<ServiceGeneratorContext>(({ lib, folder, fileName }) => [
lib,
'services',
...folder,
`${fileName}.${language}`
`${fileName}.service`
])
const toClassFile = toFile<ServiceGeneratorContext>(({ lib, folder, fileName }) => [
lib,
'services',
...folder,
`${fileName}.class`
])
export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx)
.then(
inject(getSource(classCode), before<ServiceGeneratorContext>('export const hooks ='), toServiceFile)
)
.then(inject(getSource(importTemplate), prepend(), toServiceFile))
.then(inject(optionTemplate, after('const options ='), toServiceFile))
.then(injectSource(classCode, append(), toClassFile))
.then(injectSource(importTemplate, prepend(), toClassFile))
.then(injectSource(optionTemplate, after('const options ='), toServiceFile, false))