Unified CRUD service interface providing standardized methods for data operations across all transport layers with consistent parameter handling and response formatting.
Retrieve multiple records with optional query parameters for filtering, pagination, and sorting.
/**
* Find/list resources with optional filtering and pagination
* @param params - Optional query parameters and context
* @returns Promise resolving to paginated results or array of items
*/
find(params?: Params): Promise<Paginated<T> | T[]>;
interface Paginated<T> {
total: number;
limit: number;
skip: number;
data: T[];
}Usage Examples:
const userService = app.service("users");
// Find all users
const allUsers = await userService.find();
// Find with pagination
const paginatedUsers = await userService.find({
query: {
$limit: 10,
$skip: 20
}
});
// Find with filtering
const activeUsers = await userService.find({
query: {
active: true,
age: { $gte: 18 }
}
});
// Find with sorting
const sortedUsers = await userService.find({
query: {
$sort: { name: 1, createdAt: -1 }
}
});Retrieve a single record by its unique identifier.
/**
* Get single resource by ID
* @param id - Resource identifier (string or number)
* @param params - Optional query parameters and context
* @returns Promise resolving to the resource
*/
get(id: Id, params?: Params): Promise<T>;
type Id = number | string;Usage Examples:
// Get user by ID
const user = await userService.get(123);
const userById = await userService.get("user-uuid");
// Get with additional query parameters
const userWithProfile = await userService.get(123, {
query: {
$populate: "profile"
}
});Create one or more new records.
/**
* Create new resource(s)
* @param data - Data for new resource or array of resources
* @param params - Optional context parameters
* @returns Promise resolving to created resource(s)
*/
create(data: D, params?: Params): Promise<T>;
create(data: D[], params?: Params): Promise<T[]>;Usage Examples:
// Create single user
const newUser = await userService.create({
name: "John Doe",
email: "john@example.com",
age: 25
});
// Create multiple users
const newUsers = await userService.create([
{ name: "Alice", email: "alice@example.com" },
{ name: "Bob", email: "bob@example.com" }
]);
// Create with context
const userWithContext = await userService.create({
name: "Jane",
email: "jane@example.com"
}, {
user: currentUser,
provider: "rest"
});Replace a resource completely (PUT-style operation).
/**
* Replace resource(s) completely
* @param id - Resource ID (null for bulk operations)
* @param data - Complete replacement data
* @param params - Optional query parameters and context
* @returns Promise resolving to updated resource(s)
*/
update(id: NullableId, data: D, params?: Params): Promise<T | T[]>;
type NullableId = Id | null;Usage Examples:
// Update single user (replace completely)
const updatedUser = await userService.update(123, {
name: "John Smith",
email: "johnsmith@example.com",
age: 26,
active: true
});
// Bulk update (when id is null)
const updatedUsers = await userService.update(null, {
active: false
}, {
query: { lastLogin: { $lt: "2023-01-01" } }
});Partially update a resource (PATCH-style operation).
/**
* Update resource(s) partially
* @param id - Resource ID (null for bulk operations)
* @param data - Partial data to update
* @param params - Optional query parameters and context
* @returns Promise resolving to updated resource(s)
*/
patch(id: NullableId, data: Partial<D>, params?: Params): Promise<T | T[]>;Usage Examples:
// Patch single user (partial update)
const patchedUser = await userService.patch(123, {
age: 27,
lastLogin: new Date()
});
// Bulk patch
const patchedUsers = await userService.patch(null, {
verified: true
}, {
query: { email: { $ne: null } }
});Delete one or more resources.
/**
* Delete resource(s)
* @param id - Resource ID (null for bulk operations)
* @param params - Optional query parameters and context
* @returns Promise resolving to removed resource(s)
*/
remove(id: NullableId, params?: Params): Promise<T | T[]>;Usage Examples:
// Remove single user
const removedUser = await userService.remove(123);
// Bulk remove
const removedUsers = await userService.remove(null, {
query: { active: false }
});Service initialization and cleanup methods.
/**
* Initialize service when application starts up
* @param app - Application instance
* @param path - Service path
* @returns Promise completing when setup is done
*/
setup?(app: Application, path: string): Promise<void>;
/**
* Clean up service when application shuts down
* @param app - Application instance
* @param path - Service path
* @returns Promise completing when teardown is done
*/
teardown?(app: Application, path: string): Promise<void>;Usage Examples:
// Custom service with lifecycle methods
const customService = {
async setup(app, path) {
console.log(`Setting up service at ${path}`);
// Initialize connections, caches, etc.
},
async teardown(app, path) {
console.log(`Tearing down service at ${path}`);
// Clean up resources
},
async find(params) {
return [{ id: 1, name: "test" }];
}
};
app.use("custom", customService);Services can define custom methods beyond the standard CRUD operations.
/**
* Add custom methods to service
* @param names - Array of method names to expose
* @returns Service instance for chaining
*/
methods(...names: string[]): this;Usage Examples:
// REST service with custom methods
const userService = app.service("users");
// Add custom methods to service
userService.methods("resetPassword", "sendWelcomeEmail");
// Custom methods become available on service
await userService.resetPassword({ userId: 123, newPassword: "secret" });
await userService.sendWelcomeEmail({ userId: 123 });
// Method chaining
userService
.methods("activate", "deactivate", "archive")
.methods("sendNotification");
// Use newly added methods
await userService.activate({ userId: 456 });
await userService.sendNotification({ userId: 456, message: "Welcome!" });interface Params<Q = Query> {
query?: Q;
provider?: string;
user?: any;
authenticated?: boolean;
headers?: { [key: string]: any };
connection?: any;
[key: string]: any;
}
interface Query {
[key: string]: any;
$limit?: number;
$skip?: number;
$sort?: { [key: string]: 1 | -1 };
$select?: string[];
$populate?: any;
$or?: Query[];
$and?: Query[];
$in?: any[];
$nin?: any[];
$lt?: any;
$lte?: any;
$gt?: any;
$gte?: any;
$ne?: any;
}
interface ServiceInterface<Result = any, Data = Partial<Result>, ServiceParams extends Params = Params> {
find?(params?: ServiceParams): Promise<Result | Result[]>;
get?(id: Id, params?: ServiceParams): Promise<Result>;
create?(data: Data, params?: ServiceParams): Promise<Result>;
create?(data: Data[], params?: ServiceParams): Promise<Result[]>;
update?(id: NullableId, data: Data, params?: ServiceParams): Promise<Result | Result[]>;
patch?(id: NullableId, data: Partial<Data>, params?: ServiceParams): Promise<Result | Result[]>;
remove?(id: NullableId, params?: ServiceParams): Promise<Result | Result[]>;
setup?(app: Application, path: string): Promise<void>;
teardown?(app: Application, path: string): Promise<void>;
}
interface FeathersService<T = any, D = Partial<T>, P extends Params = Params> extends ServiceInterface<T, D, P> {
hooks(map: any): this;
mixin(fn: ServiceMixin): this;
methods(...names: string[]): this;
}
type ServiceMixin = (service: any, location: string, options: ServiceOptions) => void;