Skip to content
Merged
Prev Previous commit
Next Next commit
Allow to generate services without schema
  • Loading branch information
daffl committed Oct 4, 2022
commit aeeb0d2507628d84883604c09cec77768d1d134d
35 changes: 21 additions & 14 deletions packages/cli/src/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,37 +109,44 @@ export const generate = (ctx: AppGeneratorArguments) =>
{ value: 'pnpm', name: 'pnpm' }
]
},
{
type: 'list',
name: 'schema',
when: !ctx.schema,
message: 'What is your preferred schema (model) definition format?',
choices: [
{ value: 'typebox', name: `TypeBox ${chalk.grey('(recommended)')}` },
{ value: 'json', name: 'JSON schema' }
]
},
...connectionPrompts(ctx),
...authenticationPrompts({
...ctx,
service: 'users',
service: 'user',
path: 'users',
entity: 'user'
})
])
)
.then(runGenerators(__dirname, 'templates'))
.then(copyFiles(fromFile(__dirname, 'static'), toFile('.')))
.then(initializeBaseContext())
.then(
when<AppGeneratorContext>(
({ authStrategies }) => authStrategies.length > 0,
async (ctx) => {
const { dependencies } = await connectionGenerator(ctx)
.then(async (ctx) => {
const { dependencies } = await connectionGenerator(ctx)

return {
...ctx,
dependencies
}
}
)
)
return {
...ctx,
dependencies
}
})
.then(
when<AppGeneratorContext>(
({ authStrategies }) => authStrategies.length > 0,
async (ctx) => {
const { dependencies } = await authenticationGenerator({
...ctx,
service: 'users',
service: 'user',
path: 'users',
entity: 'user'
})

Expand Down
6 changes: 4 additions & 2 deletions packages/cli/src/app/templates/package.json.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ const packageJson = ({
framework,
transports,
lib,
test
test,
schema
}: AppGeneratorContext) => ({
name,
description,
Expand All @@ -52,7 +53,8 @@ const packageJson = ({
packager,
database,
framework,
transports
transports,
schema
},
directories: {
lib,
Expand Down
10 changes: 8 additions & 2 deletions packages/cli/src/authentication/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface AuthenticationGeneratorContext extends ServiceGeneratorContext
}

export type AuthenticationGeneratorArguments = FeathersBaseContext &
Partial<Pick<AuthenticationGeneratorContext, 'service' | 'authStrategies' | 'entity'>>
Partial<Pick<AuthenticationGeneratorContext, 'service' | 'authStrategies' | 'entity' | 'path'>>

export const prompts = (ctx: AuthenticationGeneratorArguments) => [
{
Expand Down Expand Up @@ -59,6 +59,13 @@ export const prompts = (ctx: AuthenticationGeneratorArguments) => [
type: 'input',
when: !ctx.service,
message: 'What is your authentication service name?',
default: 'user'
Comment thread
marshallswain marked this conversation as resolved.
},
{
name: 'path',
type: 'input',
when: !ctx.path,
message: 'What path should the service be registered on?',
default: 'users'
},
{
Expand All @@ -80,7 +87,6 @@ export const generate = (ctx: AuthenticationGeneratorArguments) =>
const serviceContext = await serviceGenerator({
...ctx,
name: ctx.service,
path: ctx.service,
isEntityService: true,
type: getDatabaseAdapter(ctx.feathers?.database)
})
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/authentication/templates/config.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const generate = (ctx: AuthenticationGeneratorContext) =>
mergeJSON<AuthenticationGeneratorContext>(({ authStrategies }) => {
const authentication: any = {
entity: ctx.entity,
service: ctx.service,
service: ctx.path,
secret: crypto.randomBytes(24).toString('base64'),
authStrategies: ['jwt'],
jwtOptions: {
Expand Down
3 changes: 2 additions & 1 deletion packages/cli/src/authentication/templates/test.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { AuthenticationGeneratorContext } from '../index'

const template = ({
authStrategies,
path,
lib
}: AuthenticationGeneratorContext) => /* ts */ `import assert from 'assert';
import { app } from '../${lib}/app';
Expand All @@ -19,7 +20,7 @@ describe('authentication', () => {

before(async () => {
try {
await app.service('users').create(userInfo)
await app.service('${path}').create(userInfo)
} catch (error) {
// Do nothing, it just means the user already exists and can be tested
}
Expand Down
4 changes: 4 additions & 0 deletions packages/cli/src/commons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ export type FeathersAppInfo = {
* The HTTP framework used
*/
framework: 'koa' | 'express'
/**
* The main schema definition format
*/
schema: 'typebox' | 'json'
}

export interface AppPackageJson extends PackageJson {
Expand Down
31 changes: 29 additions & 2 deletions packages/cli/src/service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ export interface ServiceGeneratorContext extends FeathersBaseContext {
* The chosen service type
*/
type: 'knex' | 'mongodb' | 'custom'
/**
* Which schema definition format to use
*/
schema: 'typebox' | 'json' | false
/**
* Wether this service uses authentication
Comment thread
marshallswain marked this conversation as resolved.
*/
Expand All @@ -63,15 +67,17 @@ export interface ServiceGeneratorContext extends FeathersBaseContext {
* Parameters the generator is called with
*/
export type ServiceGeneratorArguments = FeathersBaseContext &
Partial<Pick<ServiceGeneratorContext, 'name' | 'path' | 'type' | 'authentication' | 'isEntityService'>>
Partial<
Pick<ServiceGeneratorContext, 'name' | 'path' | 'type' | 'authentication' | 'isEntityService' | 'schema'>
>

export const generate = (ctx: ServiceGeneratorArguments) =>
generator(ctx)
.then(initializeBaseContext())
.then(checkPreconditions())
.then(
prompt<ServiceGeneratorArguments, ServiceGeneratorContext>(
({ name, path, type, authentication, isEntityService }) => [
({ name, path, type, schema, authentication, isEntityService }) => [
{
name: 'name',
type: 'input',
Expand Down Expand Up @@ -111,6 +117,27 @@ export const generate = (ctx: ServiceGeneratorArguments) =>
name: 'A custom service'
}
]
},
{
name: 'schema',
type: 'list',
when: schema === undefined,
message: 'Which schema definition format do you want to use?',
Comment thread
marshallswain marked this conversation as resolved.
choices: [
{
value: 'json',
name: 'JSON schema'
},
{
value: 'typebox',
name: 'TypeBox',
disabled: true
},
{
value: false,
name: 'No schema'
}
]
}
]
)
Expand Down
43 changes: 33 additions & 10 deletions packages/cli/src/service/service.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,17 @@ export const serviceImportTemplate = ({
camelName,
upperName,
fileName,
relative
relative,
schema
}: ServiceGeneratorContext) => `
${authentication || isEntityService ? `import { authenticate } from '@feathersjs/authentication'` : ''}
import { schemaHooks } from '@feathersjs/schema'
${schema ? `import { hooks as schemaHooks } from '@feathersjs/schema'` : ''}

import type { Application } from '${relative}/declarations'

import {
${
schema
? `import {
${camelName}DataValidator,
${camelName}QueryValidator,
${camelName}Resolver,
Expand All @@ -48,15 +51,25 @@ import type {
${upperName},
${upperName}Data,
${upperName}Query
} from './${fileName}.schema'`
} from './${fileName}.schema'

export * from './${fileName}.schema'
`
: `
export type ${upperName} = any
export type ${upperName}Data = any
export type ${upperName}Query = any
`
}`

export const serviceRegistrationTemplate = ({
camelName,
authentication,
isEntityService,
path,
className,
relative
relative,
schema
}: ServiceGeneratorContext) => /* ts */ `
export const ${camelName}Hooks = {
around: {
Expand All @@ -79,20 +92,30 @@ export const ${camelName}Hooks = {
}
},
before: {
all: [
all: [${
schema
? `
schemaHooks.validateQuery(${camelName}QueryValidator),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏

It's much clearer how it works and how to customize it.

schemaHooks.validateData(${camelName}DataValidator),
schemaHooks.resolveQuery(${camelName}QueryResolver),
schemaHooks.resolveData(${camelName}DataResolver)
]
`
: ''
}]
},
after: {
all: [
all: [${
schema
? `
schemaHooks.resolveResult(${camelName}Resolver),
schemaHooks.resolveExternal(${camelName}ExternalResolver)
Comment thread
marshallswain marked this conversation as resolved.
Outdated
]
`
: ''
}]
},
error: {}
error: {
all: []
}
}

// A configure function that registers the service and its hooks via \`app.configure\`
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/service/templates/client.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const schemaImports = ({ upperName, folder, fileName }: ServiceGeneratorContext)
${upperName},
${upperName}Data,
${upperName}Query,
} from './services/${folder.join('/')}/${fileName}.schema'
} from './services/${folder.join('/')}/${fileName}.service'

Comment thread
marshallswain marked this conversation as resolved.
export type {
${upperName},
Expand Down
21 changes: 12 additions & 9 deletions packages/cli/src/service/templates/schema.tpl.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { generator, toFile } from '@feathershq/pinion'
import { generator, toFile, when } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'

Expand Down Expand Up @@ -79,13 +79,16 @@ export const ${camelName}QueryResolver = resolve<${upperName}Query, HookContext>

export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx).then(
renderSource(
template,
toFile(({ lib, folder, fileName }: ServiceGeneratorContext) => [
lib,
'services',
...folder,
`${fileName}.schema`
])
when<ServiceGeneratorContext>(
({ schema }) => schema !== false,
renderSource(
template,
toFile(({ lib, folder, fileName }: ServiceGeneratorContext) => [
lib,
'services',
...folder,
`${fileName}.schema`
])
)
)
)
13 changes: 6 additions & 7 deletions packages/cli/test/generators.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('@feathersjs/cli', () => {
connectionString: `${name}.sqlite`,
transports: ['rest', 'websockets'],
authStrategies: ['local', 'github'],
_: ['generate', 'app']
schema: 'typebox'
},
{ cwd }
)
Expand All @@ -73,8 +73,7 @@ describe('@feathersjs/cli', () => {
{
dependencyVersions,
database: 'mongodb' as const,
connectionString: `mongodb://localhost:27017/${name}`,
_: ['generate', 'connection']
connectionString: `mongodb://localhost:27017/${name}`
},
{ cwd }
)
Expand All @@ -87,7 +86,7 @@ describe('@feathersjs/cli', () => {
path: 'path/to/test',
authentication: true,
type: 'mongodb',
_: ['generate', 'service']
schema: false
},
{ cwd }
)
Expand All @@ -104,11 +103,11 @@ describe('@feathersjs/cli', () => {
getContext<ServiceGeneratorArguments>(
{
dependencyVersions,
name: 'Custom Service',
path: 'custom',
name: 'Custom',
path: 'customized',
authentication: false,
type: 'custom',
_: ['generate', 'service']
schema: 'typebox'
},
{ cwd }
)
Expand Down
2 changes: 1 addition & 1 deletion packages/schema/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export * from './resolver'
export * from './hooks'
export * from './json-schema'

export * as schemaHooks from './hooks'
export * as hooks from './hooks'
export * as jsonSchema from './json-schema'

export type Infer<S extends { _type: any }> = S['_type']
Expand Down