Skip to content

Commit

Permalink
feat(schema): Make schemas validation library independent and add Typ…
Browse files Browse the repository at this point in the history
…eBox support (#2772)
  • Loading branch information
daffl committed Oct 7, 2022
1 parent b1844b1 commit 44172d9
Show file tree
Hide file tree
Showing 55 changed files with 1,702 additions and 1,061 deletions.
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"update-dependencies": "ncu -u && lerna exec -- ncu -u -x node-fetch -x chalk -x axios",
"clean": "find . -name node_modules -exec rm -rf '{}' + && find . -name package-lock.json -exec rm -rf '{}' +",
"test:deno": "deno test --config deno/tsconfig.json deno/test.ts",
"test": "npm run lint && npm run compile && c8 lerna run test"
"test": "npm run lint && npm run compile && c8 lerna run test --ignore @feathersjs/tests"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.39.0",
Expand Down
113 changes: 2 additions & 111 deletions packages/authentication/src/options.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FromSchema } from '@feathersjs/schema'
import { FromSchema, authenticationSettingsSchema } from '@feathersjs/schema'

export const defaultOptions = {
authStrategies: [] as string[],
Expand All @@ -11,115 +11,6 @@ export const defaultOptions = {
}
}

export const authenticationSettingsSchema = {
type: 'object',
required: ['secret', 'entity', 'authStrategies'],
properties: {
secret: {
type: 'string',
description: 'The JWT signing secret'
},
entity: {
oneOf: [
{
type: 'null'
},
{
type: 'string'
}
],
description: 'The name of the authentication entity (e.g. user)'
},
entityId: {
type: 'string',
description: 'The name of the authentication entity id property'
},
service: {
type: 'string',
description: 'The path of the entity service'
},
authStrategies: {
type: 'array',
items: { type: 'string' },
description: 'A list of authentication strategy names that are allowed to create JWT access tokens'
},
parseStrategies: {
type: 'array',
items: { type: 'string' },
description:
'A list of authentication strategy names that should parse HTTP headers for authentication information (defaults to `authStrategies`)'
},
jwtOptions: {
type: 'object'
},
jwt: {
type: 'object',
properties: {
header: {
type: 'string',
default: 'Authorization',
description: 'The HTTP header containing the JWT'
},
schemes: {
type: 'array',
items: { type: 'string' },
description: 'An array of schemes to support'
}
}
},
local: {
type: 'object',
required: ['usernameField', 'passwordField'],
properties: {
usernameField: {
type: 'string',
description: 'Name of the username field (e.g. `email`)'
},
passwordField: {
type: 'string',
description: 'Name of the password field (e.g. `password`)'
},
hashSize: {
type: 'number',
description: 'The BCrypt salt length'
},
errorMessage: {
type: 'string',
default: 'Invalid login',
description: 'The error message to return on errors'
},
entityUsernameField: {
type: 'string',
description:
'Name of the username field on the entity if authentication request data and entity field names are different'
},
entityPasswordField: {
type: 'string',
description:
'Name of the password field on the entity if authentication request data and entity field names are different'
}
}
},
oauth: {
type: 'object',
properties: {
redirect: {
type: 'string'
},
origins: {
type: 'array',
items: { type: 'string' }
},
defaults: {
type: 'object',
properties: {
key: { type: 'string' },
secret: { type: 'string' }
}
}
}
}
}
} as const
export { authenticationSettingsSchema }

export type AuthenticationConfiguration = FromSchema<typeof authenticationSettingsSchema>
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"@feathersjs/koa": "^5.0.0-pre.29",
"@feathersjs/mongodb": "^5.0.0-pre.29",
"@feathersjs/schema": "^5.0.0-pre.29",
"@feathersjs/typebox": "^5.0.0-pre.29",
"@feathersjs/socketio": "^5.0.0-pre.29",
"@feathersjs/transport-commons": "^5.0.0-pre.29",
"@types/mocha": "^10.0.0",
Expand Down
50 changes: 34 additions & 16 deletions packages/cli/src/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,14 @@ export const generate = (ctx: AppGeneratorArguments) =>
type: 'input',
when: !ctx.name,
message: 'What is the name of your application?',
default: ctx.cwd.split(sep).pop()
default: ctx.cwd.split(sep).pop(),
validate: (input) => {
if (ctx.dependencyVersions[input]) {
return `Application can not have the same name as a dependency`
}

return true
}
},
{
name: 'description',
Expand Down Expand Up @@ -109,37 +116,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 All @@ -152,7 +166,7 @@ export const generate = (ctx: AppGeneratorArguments) =>
)
.then(
install<AppGeneratorContext>(
({ transports, framework, dependencyVersions, dependencies }) => {
({ transports, framework, dependencyVersions, dependencies, schema }) => {
const hasSocketio = transports.includes('websockets')

dependencies.push(
Expand All @@ -177,6 +191,10 @@ export const generate = (ctx: AppGeneratorArguments) =>
dependencies.push('@feathersjs/express', 'compression')
}

if (schema === 'typebox') {
dependencies.push('@feathersjs/typebox')
}

return addVersions(dependencies, dependencyVersions)
},
false,
Expand Down
10 changes: 5 additions & 5 deletions packages/cli/src/app/templates/app.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ import { koa, rest, bodyParser, errorHandler, parseAuthentication, cors } from '
${transports.includes('websockets') ? "import socketio from '@feathersjs/socketio'" : ''}
import type { Application } from './declarations'
import { configurationSchema } from './configuration'
import { configurationValidator } from './schemas/configuration'
import { logErrorHook } from './logger'
import { services } from './services/index'
import { channels } from './channels'
const app: Application = koa(feathers())
// Load our app configuration (see config/ folder)
app.configure(configuration(configurationSchema))
app.configure(configuration(configurationValidator))
// Set up Koa middleware
app.use(cors())
app.use(serveStatic(app.get('public')))
app.use(errorHandler())
app.use(cors())
app.use(parseAuthentication())
app.use(bodyParser())
Expand Down Expand Up @@ -69,15 +69,15 @@ import configuration from '@feathersjs/configuration'
${transports.includes('websockets') ? "import socketio from '@feathersjs/socketio'" : ''}
import type { Application } from './declarations'
import { configurationSchema } from './configuration'
import { configurationValidator } from './schemas/configuration'
import { logger, logErrorHook } from './logger'
import { services } from './services/index'
import { channels } from './channels'
const app: Application = express(feathers())
// Load app configuration
app.configure(configuration(configurationSchema))
app.configure(configuration(configurationValidator))
app.use(cors())
app.use(compress())
app.use(json())
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/app/templates/client.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const template = ({}: AppGeneratorContext) => /* ts */ `import { feathers } from
import type { Paginated, ClientService, TransportConnection, Params } from '@feathersjs/feathers'
export interface ServiceTypes {
// A mapping of client side services
//
}
export const createClient = <Configuration = any> (connection: TransportConnection<ServiceTypes>) => {
Expand Down
49 changes: 0 additions & 49 deletions packages/cli/src/app/templates/configuration.tpl.ts

This file was deleted.

4 changes: 2 additions & 2 deletions packages/cli/src/app/templates/declarations.tpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ const template = ({
framework
}: AppGeneratorContext) => /* ts */ `import { HookContext as FeathersHookContext, NextFunction } from '@feathersjs/feathers'
import { Application as FeathersApplication } from '@feathersjs/${framework}'
import { ConfigurationSchema } from './configuration'
import { ApplicationConfiguration } from './schemas/configuration'
export { NextFunction }
export interface Configuration extends ConfigurationSchema {}
export interface Configuration extends ApplicationConfiguration {}
// A mapping of service names to types. Will be extended in service files.
export interface ServiceTypes {}
Expand Down
Loading

0 comments on commit 44172d9

Please sign in to comment.