Skip to main content

Overview

The feathers generate service command creates a complete service implementation with database adapter, schema validation, type definitions, and test files. Services are the core building blocks of Feathers applications that handle data operations.

Usage

feathers generate service [options]
Or using the shorthand:
feathers g service [options]

Options

--name
string
The name of the service. This will be used for class names, file names, and variable names.
feathers generate service --name messages
Validation: Cannot be empty or “authentication”
--path
string
The path where the service will be registered on the API. Defaults to kebab-case of the service name.
feathers generate service --name messages --path api/messages
Default: kebab-case(name) (e.g., “userProfiles” becomes “user-profiles”)Validation: Cannot be empty or “authentication”
--type
string
The service type/database adapter to use.
feathers generate service --type mongodb
Choices:
  • knex - SQL databases (PostgreSQL, MySQL, SQLite, MSSQL)
  • mongodb - MongoDB database
  • custom - Custom service without database
Note: SQL and MongoDB options are only available if you have configured the respective database connection.

Interactive Prompts

Service Name

Prompt: “What is the name of your service?” Validation: Cannot be empty or “authentication” The name will be transformed into various formats:
  • camelCase for variables (e.g., userMessages)
  • PascalCase for classes (e.g., UserMessagesService)
  • kebab-case for files (e.g., user-messages.ts)

Service Path

Prompt: “Which path should the service be registered on?” Default: kebab-case version of the service name Example: Service name “messages” defaults to path “messages”, accessible at /messages Nested paths: You can use slashes for nested paths like api/v1/messages

Authentication

Prompt: “Does this service require authentication?” Default: No If enabled, the service will require users to be authenticated before accessing it.

Database Type

Prompt: “What database is the service using?” Choices:
  • SQL - Uses Knex.js adapter for PostgreSQL, MySQL, SQLite, or MSSQL
  • MongoDB - Uses MongoDB adapter
  • A custom service - No database, implement custom methods
Note: SQL and MongoDB options are disabled if the connection is not configured.

Schema Format

Prompt: “Which schema definition format do you want to use?” Choices:
  • TypeBox (recommended) - Type-safe schema with excellent TypeScript support
  • JSON schema - Standard JSON schema format
  • No schema - Not recommended with a database
Schemas allow you to type, validate, secure, and populate data.

Generated Files

For a service named “messages” with MongoDB and TypeBox:
src/
├── services/
│   ├── messages/
│   │   ├── messages.schema.ts    # Schema definitions
│   │   ├── messages.class.ts     # Service class
│   │   └── messages.ts           # Service registration
│   └── index.ts                  # Updated to register service
test/
└── services/
    └── messages.test.ts          # Service tests

With Nested Paths

For path api/v1/messages:
src/
├── services/
│   ├── api/
│   │   └── v1/
│   │       └── messages/
│   │           ├── messages.schema.ts
│   │           ├── messages.class.ts
│   │           └── messages.ts
│   └── index.ts

Generated Code Examples

Service Class (TypeScript + MongoDB)

import { MongoDBService } from '@feathersjs/mongodb'
import type { Application } from '../../declarations'
import type { Message, MessageData, MessageQuery } from './messages.schema'

export type MessageParams = Params<MessageQuery>

export class MessageService extends MongoDBService<
  Message,
  MessageData,
  MessageParams
> {}

export const getOptions = (app: Application) => {
  return {
    paginate: app.get('paginate'),
    Model: app.get('mongodbClient').db().collection('messages')
  }
}

Schema Definition (TypeBox)

import { Type } from '@feathersjs/typebox'
import { TypeCompiler } from '@feathersjs/typebox'
import type { Static } from '@feathersjs/typebox'

export const messageSchema = Type.Object(
  {
    _id: Type.String(),
    text: Type.String(),
    createdAt: Type.Number(),
    userId: Type.String()
  },
  { $id: 'Message', additionalProperties: false }
)

export const messageDataSchema = Type.Pick(
  messageSchema,
  ['text'],
  { $id: 'MessageData' }
)

export const messageQuerySchema = Type.Partial(
  messageSchema,
  { $id: 'MessageQuery' }
)

export type Message = Static<typeof messageSchema>
export type MessageData = Static<typeof messageDataSchema>
export type MessageQuery = Static<typeof messageQuerySchema>

Service Registration

import { authenticate } from '@feathersjs/authentication'
import { MessageService, getOptions } from './messages.class'
import { messagePath, messageMethods } from './messages.schema'

export * from './messages.class'
export * from './messages.schema'

export const message = (app: Application) => {
  app.use(messagePath, new MessageService(getOptions(app)), {
    methods: messageMethods,
    events: []
  })

  app.service(messagePath).hooks({
    around: {
      all: [authenticate('jwt')]
    },
    before: {},
    after: {},
    error: {}
  })
}

Terminal Output Example

$ feathers generate service
? What is the name of your service? messages
? Which path should the service be registered on? messages
? Does this service require authentication? Yes
? What database is the service using? MongoDB
? Which schema definition format do you want to use? TypeBox (recommended)

Generating service...
 Created src/services/messages/messages.schema.ts
 Created src/services/messages/messages.class.ts
 Created src/services/messages/messages.ts
 Updated src/services/index.ts
 Created test/services/messages.test.ts

Service 'messages' registered on path '/messages'

Service Naming Conventions

The generator creates multiple variations of your service name:
name
string
Original input name (e.g., “UserMessage”)
camelName
string
Camel case starting with lowercase (e.g., “userMessage”)
upperName
string
Camel case starting with uppercase (e.g., “UserMessage”)
className
string
Class name with “Service” suffix (e.g., “UserMessageService”)
kebabName
string
Kebab case for files (e.g., “user-message”)
fileName
string
The last element of the path (e.g., “messages”)
kebabPath
string
Kebab case of the full path (e.g., “api-v1-messages”)

Database Adapters

The generator supports multiple database adapters:

Knex (SQL Databases)

Supports:
  • PostgreSQL
  • MySQL/MariaDB
  • SQLite
  • Microsoft SQL Server
Generates a service using @feathersjs/knex adapter with migrations support.

MongoDB

Generates a service using @feathersjs/mongodb adapter with native MongoDB driver.

Custom

Generates a service with custom methods that you implement yourself. Useful for:
  • External APIs
  • Business logic without database
  • Non-standard data sources

Authentication Integration

When authentication is enabled, the generator:
  1. Adds authenticate('jwt') hook to all methods
  2. Restricts access to authenticated users only
  3. Populates user information in the hook context

Schema Validation

  • Full TypeScript type inference
  • Runtime validation
  • OpenAPI/JSON Schema compatible
  • Excellent developer experience

JSON Schema

  • Standard JSON Schema format
  • Works with any validation library
  • More verbose than TypeBox

No Schema

  • No validation or typing
  • Not recommended for production
  • Use only for prototyping

Testing

The generator creates a test file with basic CRUD tests:
import assert from 'assert'
import app from '../../src/app'

describe('messages service', () => {
  it('registered the service', () => {
    const service = app.service('messages')
    assert.ok(service, 'Registered the service')
  })

  it('creates a message', async () => {
    const message = await app.service('messages').create({
      text: 'Hello world'
    })
    
    assert.ok(message._id)
    assert.strictEqual(message.text, 'Hello world')
  })
})

Next Steps

Generate a hook

Add custom logic to your service

Add authentication

Secure your services with authentication
Services are automatically registered in src/services/index.ts and available immediately after generation.

Build docs developers (and LLMs) love