@deeblr/auth-core
v0.4.0
Published
The Deeblr Auth engine: configuration, plugin/hook system, adapter contracts, and the core authentication flows (register/login/logout). Framework- and database-agnostic.
Downloads
738
Readme
@deeblr/auth-core
The Deeblr Auth engine — configuration, plugin/hook system, adapter contracts, and the core authentication flows (register/login/logout). Framework-agnostic and database-agnostic: it has zero knowledge of Express, Next.js, Prisma, or MongoDB.
This package is the foundation every other @deeblr/auth-* capability
package (sessions, JWTs, OAuth, permissions, security) and every framework
integration (@deeblr/auth-nextjs, @deeblr/auth-express) builds on. See
the project's architecture document for the full ecosystem design.
Install
npm install @deeblr/auth-coreYou'll also need a DatabaseAdapter implementation — either one of the
official adapter packages (@deeblr/auth-adapter-prisma,
@deeblr/auth-adapter-mongodb) or your own object satisfying the
DatabaseAdapter contract exported from this package.
Quick start
import { DeeblrAuth } from "@deeblr/auth-core";
import { myAdapter } from "./my-adapter";
const auth = new DeeblrAuth({
adapter: myAdapter,
});
const { user } = await auth.register({
email: "[email protected]",
password: "correct-horse-battery-staple",
});
const { user: loggedInUser } = await auth.login({
email: "[email protected]",
password: "correct-horse-battery-staple",
});
await auth.logout({ userId: loggedInUser.id });DeeblrAuth and DeeblrAuthCore are the same class — DeeblrAuth is just
the name used in examples; both behave identically.
What this package does NOT do
By design, auth-core does not implement:
- Sessions (
@deeblr/auth-session) — database or stateless session strategies, device tracking. - Tokens (
@deeblr/auth-jwt) — JWT issuance, refresh rotation. - OAuth (
@deeblr/auth-oauth) — Google/GitHub/Discord/custom providers. - Authorization (
@deeblr/auth-permissions) — roles, permissions, RBAC. - Security hardening (
@deeblr/auth-security) — rate limiting, brute-force lockout, audit logging.
These are separate, independently-installable packages that extend the engine through plugins and services — core exposes the extension points; it never hardcodes the capabilities themselves.
Extending the engine: plugins
A plugin is an object with a name and a setup() method. setup()
receives a PluginContext giving access to the hook bus, the service
registry, a logger, and the resolved config:
import type { DeeblrPlugin } from "@deeblr/auth-core";
const auditLogPlugin: DeeblrPlugin = {
name: "audit-log",
setup(ctx) {
ctx.hooks.on("auth:afterLogin", ({ user }) => {
ctx.logger.info("login", { userId: user.id });
});
},
};
const auth = new DeeblrAuth({
adapter: myAdapter,
plugins: [auditLogPlugin],
});
// Equivalently:
auth.use(auditLogPlugin);Plugins are set up once, in registration order, the first time the engine
is used (or explicitly via await auth.initialize()). teardown() (if
defined) runs in reverse order during await auth.destroy().
Extending the engine: services
Internal dependencies (the password hasher, id generator, clock, and
anything a plugin provides) live in a typed ServiceRegistry. Core
registers its own defaults; a plugin can register new services other
plugins or flows can then depend on — this is how, for example, a future
@deeblr/auth-session plugin lets auth.login() return a session without
auth-core ever importing that package.
declare module "@deeblr/auth-types" {
interface DeeblrServiceMap {
session: MySessionStrategy;
}
}Events
Every flow emits typed lifecycle events on auth.hooks. before* events
are cancellable (a handler that throws aborts the flow); all other events
are notifications whose handler errors are isolated so one plugin can't
break another.
See AuthHookEventMap (re-exported from @deeblr/auth-types) for the full,
authoritative list of events and their payload shapes.
Errors
Every error thrown by this package (and the rest of the ecosystem) extends
AuthError and carries a stable code string. Switch on code, not on
instanceof or message text:
import { AuthError } from "@deeblr/auth-core";
try {
await auth.login({ email, password });
} catch (err) {
if (err instanceof AuthError && err.code === "INVALID_CREDENTIALS") {
// handle
}
}License
MIT
