A framework for real-time applications and REST API with JavaScript and TypeScript
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Service registration, retrieval, and lifecycle management within the Feathers application.
Register services or sub-applications at specific paths within the Feathers application.
/**
* Register a new service or a sub-app
* @param path - The path for the service to register
* @param service - The service object to register or another Feathers application to use as sub-app
* @param options - The options for this service
* @returns The application instance for chaining
*/
use<L extends keyof Services & string>(
path: L,
service: ServiceInterface | Application,
options?: ServiceOptions<keyof Services[L]>
): this;Usage Examples:
import { feathers, Service } from "@feathersjs/feathers";
const app = feathers();
// Register a service class
class MessageService implements Service {
async find() {
return [{ id: 1, text: "Hello" }];
}
async get(id: number) {
return { id, text: "Hello" };
}
}
app.use("messages", new MessageService());
// Register with options
app.use("todos", new TodoService(), {
events: ["customEvent"],
methods: ["find", "get", "create", "customMethod"]
});
// Register a sub-application
const subApp = feathers();
subApp.use("posts", new PostService());
app.use("api/v1", subApp);Get registered services by their path to interact with them directly.
/**
* Get the Feathers service instance for a path
* @param path - The name of the service
* @returns The enhanced Feathers service instance
*/
service<L extends keyof Services & string>(
path: L
): FeathersService<this, Services[L]>;Usage Examples:
// Get a service and use it
const messageService = app.service("messages");
const messages = await messageService.find();
const message = await messageService.get(1);
// Create new data
const newMessage = await messageService.create({
text: "New message"
});Remove services from the application and properly clean them up.
/**
* Unregister an existing service
* @param path - The name of the service to unregister
* @returns Promise resolving to the unregistered service
*/
unuse<L extends keyof Services & string>(
location: L
): Promise<FeathersService<this, Services[L]>>;Usage Example:
// Unregister a service
const removedService = await app.unuse("messages");Provides a fallback mechanism when requesting non-existent services.
/**
* Returns a fallback service instance that will be registered when no service was found
* @param location - The path of the service
* @returns A service interface (default implementation throws NotFound error)
*/
defaultService(location: string): ServiceInterface;Usage Example:
// Override default service behavior
app.defaultService = function(location: string) {
return {
async get(id: string) {
return { id, message: `Service ${location} not implemented` };
}
};
};
// Now accessing non-existent services won't throw errors
const result = await app.service("nonexistent").get("test");Configuration options for service registration.
interface ServiceOptions<MethodTypes = string> {
/**
* A list of custom events that this service emits to clients
*/
events?: string[] | readonly string[];
/**
* A list of service methods that should be available externally to clients
*/
methods?: MethodTypes[] | readonly MethodTypes[];
/**
* Provide a full list of events that this service should emit to clients.
* Unlike the events option, this will not be merged with the default events.
*/
serviceEvents?: string[] | readonly string[];
/**
* Initial data to always add as route params to this service
*/
routeParams?: { [key: string]: any };
}Usage Examples:
// Service with custom events and methods
app.use("messages", new MessageService(), {
events: ["messageRead", "messageArchived"],
methods: ["find", "get", "create", "markAsRead", "archive"],
routeParams: { tenant: "default" }
});
// Service with custom event list (not merged with defaults)
app.use("notifications", new NotificationService(), {
serviceEvents: ["sent", "delivered", "failed"] // Only these events, no defaults
});Internal utilities for enhancing services with Feathers functionality.
/**
* Wrap a service with Feathers functionality (hooks, events, etc.)
*/
function wrapService(location: string, service: any, options: ServiceOptions): any;
/**
* Get service options metadata from a wrapped service
*/
function getServiceOptions(service: any): ServiceOptions;
/**
* Normalize and validate service options
*/
function normalizeServiceOptions(service: any, options?: ServiceOptions): ServiceOptions;/**
* Default service methods that Feathers recognizes
*/
const defaultServiceMethods: string[];
/**
* Default service arguments mapping for each method
*/
const defaultServiceArguments: { [method: string]: string[] };
/**
* Default events emitted by service methods
*/
const defaultServiceEvents: string[];
/**
* Methods that cannot be used as custom service method names
*/
const protectedMethods: string[];Services enhanced with Feathers functionality including hooks and events.
type FeathersService<A = FeathersApplication, S = Service> = S &
ServiceAddons<A, S> &
OptionalPick<ServiceHookOverloads<S>, keyof S>;
interface ServiceAddons<A = Application, S = Service> extends EventEmitter {
id?: string;
hooks(options: HookOptions<A, S>): this;
}Usage Example:
const messageService = app.service("messages");
// Enhanced service has event functionality
messageService.on("created", (message, context) => {
console.log("New message created:", message);
});
// Enhanced service has hook functionality
messageService.hooks({
before: {
create: [
async (context) => {
context.data.createdAt = new Date();
}
]
}
});