mirror of
https://github.com/feathersjs/feathers.git
synced 2026-02-01 17:37:38 +00:00
feat(cli): Improve generated application folder structure (#2678)
This commit is contained in:
parent
56f828fa85
commit
d114557721
@ -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'
|
||||
|
||||
@ -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')
|
||||
)
|
||||
)
|
||||
|
||||
@ -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 }
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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 = ({
|
||||
|
||||
@ -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', () => {
|
||||
${
|
||||
|
||||
@ -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 }
|
||||
)
|
||||
|
||||
@ -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 }
|
||||
)
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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
|
||||
}
|
||||
})
|
||||
|
||||
79
packages/cli/src/service/templates/class.tpl.ts
Normal file
79
packages/cli/src/service/templates/class.tpl.ts
Normal 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`
|
||||
])
|
||||
)
|
||||
)
|
||||
@ -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)
|
||||
)
|
||||
)
|
||||
|
||||
@ -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`
|
||||
])
|
||||
|
||||
@ -72,7 +72,7 @@ export const generate = (ctx: ServiceGeneratorContext) =>
|
||||
template,
|
||||
toFile(({ lib, folder, fileName }: ServiceGeneratorContext) => [
|
||||
lib,
|
||||
'schemas',
|
||||
'services',
|
||||
...folder,
|
||||
`${fileName}.schema`
|
||||
])
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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`
|
||||
])
|
||||
)
|
||||
)
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user