@plinthjs/contracts
v0.1.0
Published
Mason contracts: the interface-only foundation (the Illuminate\Contracts equivalent).
Maintainers
Readme
@plinthjs/contracts
Mason's interface-only foundation, the Illuminate\Contracts equivalent. It exports the structural
interfaces and type aliases that the other Mason packages depend on, so they can stay decoupled from
one another. The package is zero-runtime and dependency-free: the only value it exports is VERSION.
Install
npm install @plinthjs/contractsUsage
Depend on a contract instead of a concrete implementation. Because the interfaces are structural, any object with the right shape satisfies them, with no base class to extend.
import type { CacheRepository, Hasher } from '@plinthjs/contracts'
export class ReportService {
constructor(private readonly cache: CacheRepository) {}
async summary(): Promise<string> {
return this.cache.remember('report:summary', 300, async () => buildSummary())
}
}
// A tiny hasher for tests, satisfying the contract structurally.
const plainHasher: Hasher = {
make: (value) => `plain:${value}`,
check: (value, hash) => hash === `plain:${value}`,
needsRehash: () => false,
}What is included
| Area | Contracts |
| ---------- | ------------------------------------------------------------------------------------------ |
| Support | Arrayable, Objectable, Jsonable, Renderable |
| HTTP | HasHttpStatus, HasErrorBag |
| Hashing | Hasher, HashOptions |
| Encryption | Encrypter |
| Auth | Authenticatable, Credentials, Rememberable, UserProvider, Guard, StatefulGuard |
| Cache | CacheStore, CacheRepository |
| Queue | ShouldQueue, QueueJob, Queueable, JobMiddleware |
| Mail | Mailer, MailableContract |
| Filesystem | Disk |
| Container | Container, Identifier, Newable |
| Casts | Cast, CastEncrypter |
Examples
import type {
Authenticatable,
HasErrorBag,
HasHttpStatus,
JobMiddleware,
QueueJob,
} from '@plinthjs/contracts'
// An error that the HTTP layer can map to a 422 with a field bag.
class FormError extends Error implements HasHttpStatus, HasErrorBag {
readonly status = 422
constructor(readonly errors: Record<string, string[]>) {
super('The given data was invalid.')
}
}
// A user record the auth layer can work with.
const user: Authenticatable = {
getAuthIdentifier: () => 1,
getAuthIdentifierName: () => 'id',
getAuthPassword: () => '$2b$10$...',
}
// A queued job with per-job middleware.
const logTiming: JobMiddleware = async (job, next) => {
const started = Date.now()
await next()
console.log(`job took ${Date.now() - started}ms`)
}
const job: QueueJob = {
tries: 3,
handle: async () => sendWelcomeEmail(),
middleware: () => [logTiming],
}All exports other than VERSION are type-only, so importing them with import type adds nothing
to your bundle.
