Skip to content

findOrCreate ​

Category
Tags
Export size
min 8.71 kB · gzip 3.59 kB

A before:create (or around:create) hook that looks for an existing record before creating one.

It builds a query from the uniqueBy paths read out of context.data, runs find({ paginate: false }) with $limit: 2 on the target service, and if exactly one record matches, sets context.result to that record — short-circuiting the create. With zero matches (or array data) the create proceeds; with multiple matches the onMultiple option decides.

ts
  import { 
findOrCreate
} from 'feathers-utils/hooks';

Example ​

ts
import { findOrCreate } from 'feathers-utils/hooks'

app.service('tags').hooks({
  before: {
    create: [findOrCreate({ service: 'tags', uniqueBy: 'name' })]
  }
})

Options ​

serviceSrequired

The service to search before creating. Must be a service registered on the app.

uniqueByMaybeArray<UniqueByPath<Service>>required

One or more property paths (dot-notation supported) read from context.data to build the lookup query — the upsert "conflict target". A path whose value is undefined in the data is skipped.

params(context: H) => InferFindParams<Service>

Optional function returning extra find params. query is merged with (and overridden by) the uniqueBy values; paginate is always forced to false. Its $limit defaults to 2: telling one match from several needs no more.

onMultiple'create' | 'throw' | 'first'default'create'

What to do when more than one record matches the uniqueBy query.

  • 'create' (default): proceed to create a new record.
  • 'throw': throw a BadRequest.
  • 'first': short-circuit with the first match.

Type declaration ​

Show Type Declarations
ts
/**
 * The valid `uniqueBy` paths for a service's create data. Falls back to a plain
 * `string` when the create data type can't be inferred (e.g. an untyped app), so
 * the hook stays usable without a strongly-typed `feathers()` instance.
 */
type UniqueByPath<S> = NeverFallback<
  KeyOfOrDotNotation<InferCreateDataSingle<S>>,
  string
>
export interface FindOrCreateOptions<
  H extends HookContext = HookContext,
  Services extends H["app"]["services"] = H["app"]["services"],
  S extends keyof Services = keyof Services,
  Service = Services[S],
> {
  /** The service to search before creating. Must be a service registered on the app. */
  service: S
  /**
   * One or more property paths (dot-notation supported) read from `context.data` to build
   * the lookup query — the upsert "conflict target". A path whose value is `undefined` in
   * the data is skipped.
   */
  uniqueBy: MaybeArray<UniqueByPath<Service>>
  /**
   * Optional function returning extra `find` params. `query` is merged with (and overridden
   * by) the `uniqueBy` values; `paginate` is always forced to `false`. Its `$limit` defaults
   * to `2`: telling one match from several needs no more.
   */
  params?: (context: H) => InferFindParams<Service>
  /**
   * What to do when more than one record matches the `uniqueBy` query.
   * - `'create'` (default): proceed to create a new record.
   * - `'throw'`: throw a `BadRequest`.
   * - `'first'`: short-circuit with the first match.
   *
   * @default 'create'
   */
  onMultiple?: "create" | "throw" | "first"
}
/**
 * A `before:create` (or `around:create`) hook that looks for an existing record before creating one.
 *
 * It builds a query from the `uniqueBy` paths read out of `context.data`, runs
 * `find({ paginate: false })` with `$limit: 2` on the target service, and if **exactly one** record matches, sets
 * `context.result` to that record — short-circuiting the create. With zero matches (or array data)
 * the create proceeds; with multiple matches the `onMultiple` option decides.
 *
 * @example
 * ```ts
 *
 *
 * app.service('tags').hooks({
 *   before: {
 *     create: [findOrCreate({ service: 'tags', uniqueBy: 'name' })]
 *   }
 * })
 * ```
 *
 * @see https://utils.feathersjs.com/hooks/find-or-create.html
 */
export declare function findOrCreate<H extends HookContext = HookContext>(
  options: FindOrCreateOptions<H>,
): (context: H, next?: NextFunction) => Promise<void>
ArgumentTypeDescription
optionsFindOrCreateOptions<H>
typemethodsmulti
before, aroundcreateno

Released under the MIT License.