npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

loopback4-prisma

v0.0.19

Published

loopback4-prisma

Downloads

11

Readme

loopback4-prisma

This package enables Prisma integration with LoopBack 4.

Installation

To install loopback4-prisma:

$ [npm install | yarn add] loopback4-prisma

Integration Scope

This package adds the following integration capabilities:

  • Binding of Prisma models to context
  • Connection lifecycle integration
  • Integration with @loopback/logging

The following are not supported yet, but are being considered:

  • OpenAPI 3.0 schema generation
  • Prisma Middleware Providers
  • Prisma query filter like loopback4 query filter
  • Prisma generator for loopback models, repositories and crud controllers

Considerations

When using Prisma integration for LoopBack 4, there may be some important factors or changes that should be considered:

  • lazyConnect is disabled by default.

    This is to ensure that LoopBack fails fast with database connection issues.

  • Limited support for architectures or operating systems

    The Prisma engines are binary blobs that has its own list of supported platforms, separate from Node.js itself.

Basic Use

Configure and load LoopbackPrismaComponent in the application constructor as shown below.

import {PrismaComponent, PrismaOptions} from 'loopback4-prisma';

export class MyApplication extends RepositoryMixin(
  // This can be replaced with any `*Application`
  // (e.g. `RestApplication` if needed.
  Application
)) {
  constructor(options: ApplicationConfig = {}) {
    const opts: PrismaOptions = {/* Config here */}

    this.configure(PrismaBindings.COMPONENT).to(opts);
    this.component(PrismaComponent);
  }
}

Configuring Prisma Client and Component

The Prisma Component and Prisma Client accepts custom configuration, which can be configured as follows:

import {PrismaBindings, PrismaComponent, PrismaOptions} from 'loopback4-prisma';

export class MyApplication extends RepositoryMixin(RestApplication)) {
  constructor(options: ApplicationConfig = {}) {
    const opts: PrismaOptions = {
      prismaClient: {
        /* Prisma Client options go here */
      }

      // Prisma Component configuration
      enableLoggingIntegration: true,
      lazyConnect: false,
      models: {
        namespace: 'customPrismaModelNamespace',
        tags: ['customPrismaModelTag'],
      },
    };

    // The order does not matter as long as `app.init()` hasn't been called.
    this.configure(PrismaBindings.COMPONENT).to(opts);
    this.component(PrismaComponent);
    // ...
  }
}

After .init(), the configuration binding will be locked. Manual unlocking and modification will not be honored.

Registering Prisma middleware

Extension points are a LoopBack 4 concept which allows extending functionality through a common interface. In the case, it is also useful as a bill-of-material of registered Prisma middleware.

import {Binding, BindingKey} from '@loopback/core';
import {
  asPrismaMiddleware,
  PrismaBindings,
  PrismaComponent
} from 'loopback4-prisma';

// Replace this to import your own middleware.
import {myPrismaMiddleware} from '.';

export class MyApplication extends RepositoryMixin(RestApplication)) {
  constructor(options: ApplicationConfig = {}) {
    // BindingKey.generate() creates a unique binding key.
    // It can be replaced with your own binding key to allow identification of
    // the middleware.
    this.bind(new Binding(BindingKey.generate()))
      .to(myPrismaMiddleware)
      .apply(asPrismaMiddleware);

    this.component(LoopbackPrismaComponent);
    // ...
  }
}

Prisma middleware can be registered at any point in time (with some caveats), and its binding will be automatically locked immediately when and after .init().

Registering Prisma Middleware after init

When registerin Prisma Middleware After .init() is called, it is necessary to call process.nextTick() to guarantee that the middleware registation is complete. Otherwise, there is a risk of a race condition.

In asynchronous functions, it is possible to adapt process.nextTick() as follows:

// Avoid "callback hell" in asynchronous functions
await new Promise(resolve => process.nextTick(resolve));

Injecting Prisma models

During initialization, Prisma models are discovered and bound to Context as Constant Singletons.

For example, to constructor-inject a Prisma model named User into a Controller:

import {inject} from '@loopback/core';
import {DefaultPrismaCrudRepository, PrismaBindings} from 'loopback4-prisma';
import {Prisma, PrismaClient} from '@prisma/client';

export class MyController {
  constructor(
    @inject(`${PrismaBindings.PRISMA_MODEL_NAMESPACE}.${Prisma.ModelName.User}`)
    private _userModel: PrismaClient.prototype.user,
  ) {}
}

Injecting PrismaClient instance

After initialization, a PrismaClient instance will be bound to Context. To retrieve the instance:

class MyClass {
  constructor(
    @inject(PrismaBindings.PRISMA_CLIENT_INSTANCE)
    private _prismaClient: PrismaClient,
  ) {}
}

It is usually not recommended to inject the PrismaClient instance unless if the API is not exposed through this extension. Please consider submitting it as a new GitHub "Idea" Discussion.

@loopback/logging integration

The @loopback/logging integration a quick bootstrap helper that configures and binds event listeners to PrismaClient.

Quick start

  • Install a compatible version of @loopback/logging:

    $ [npm install | yarn add] @loopback/logging
  • Register LoggingComponent:

    import {LoggingComponent} from '@loopback/logging';
    // ...
    app.component(LoggingComponent);
  • Register and configure PrismaComponent:

    import {
      PrismaBindings,
      PrismaComponent,
      PrismaOptions,
    } from 'loopback4-prisma';
    // ...
    app.component(PrismaComponent);
    app.configure<PrismaOptions>(PrismaBindings.COMPONENT).to({
      enableLoggingIntegration: true,
    });

Advanced Use

Custom Prisma Client instance

Before .init() is called, it is possible to provide a custom instance of the Prisma Client:

import {PrismaBindings, PrismaComponent} from 'loopback4-prisma';
import {PrismaClient} from '@prisma/client';

export class MyApplication extends RepositoryMixin(RestApplication)) {
  constructor(options: ApplicationConfig = {}) {
    const prismaClient = new PrismaClient();

    this.bind(PrismaBindings.PRISMA_CLIENT_INSTANCE).to(prismaClient);
    this.component(LoopbackPrismaComponent);
    // ...
  }
}

In most cases, it's usually not necessary to provide your own instance of the Prisma Client. Also note that the instance MUST be bound as a constant (i.e. using Binding.to()); Otherwise, an error will be thrown during .init() and .start().

Informational

This section is for deeper, informational reference.

Pre- & Post-initialization Restrictions

Before .init() is called, the configuration and Prisma Client instance binding can be modified, and it is not necessary to call .configure() before .component().

After initialization, both bindings will be locked and any changes (even after manual unlocking) will not be honored.

Bad Binding Protections

At certain stages, this extension will check and validate if the relevant bound Bindings meet their respective requirements (e.g. Binding scope, binding type, etc.). Afterwards, these Bindings will be locked (i.e. through Binding.lock()) to discourage unwanted modifications and allow for quick, easy-to-spot errors.

After the bindings are locked, no additional checks will be performed, and Binding modification may cause additional unhandled errors deeper within the code.

Furthermore, behavior on interactions on the Bindings and the Bindings themselves are not tested or documented.

Hence, it is strongly discouraged to modify Bindings after they're locked, of which they should be considered "read-only".

Please refer to this documentation for more information on when certain Bindings are locked.