@devx-retailos/core
v0.0.2
Published
Shared types, interfaces, and errors for retailOS packages.
Keywords
Readme
@devx-retailos/core
Shared types, interfaces, and errors for retailOS packages: the Subject identity model, Logger, RetailOSError, IdentityResolver, and the permission/flag registries.
Part of retailOS, a Medusa v2 SDK for offline-store POS systems. Packages are installed independently and composed in a brand's Medusa backend; core is the dependency-free foundation every other @devx-retailos/* package builds on.
Installation
npm install @devx-retailos/corePure TypeScript, zero runtime dependencies, no Medusa requirement. Ships CJS + ESM with type declarations.
Key exports
Identity types
RBAC in retailOS is subject-agnostic: anything with an id and a type can hold roles.
import type { Subject, PermissionScope, IdentityContext } from "@devx-retailos/core"
const subject: Subject = { id: "user_123", type: "medusa_user" }
const scope: PermissionScope = { organization_id: "org_01", store_id: "store_01" }IdentityResolver
The seam that maps an incoming request to a subject. Implement it to plug a new auth mechanism (PIN, SSO, badge) into RBAC without schema changes.
import type { IdentityResolver, IdentityContext } from "@devx-retailos/core"
const pinResolver: IdentityResolver<MyRequest> = {
name: "pin",
async resolve(req): Promise<IdentityContext | null> {
const employee = await lookupByPin(req.headers["x-pin"])
if (!employee) return null
return {
subject: { id: employee.id, type: "employee" },
scope: { organization_id: employee.organization_id },
}
},
}Logger and withScope
All retailos packages log through this interface instead of console.*.
import { withScope, createNoopLogger, type Logger } from "@devx-retailos/core"
const log = withScope(injectedLogger, "discount")
log.info("discount applied", { discount_id, order_id }) // -> "[discount] discount applied"createNoopLogger() returns a silent logger, useful as a default in tests.
RetailOSError
Base class for every domain error in the SDK, with a stable code consumers can switch on.
import { RetailOSError, PermissionDeniedError } from "@devx-retailos/core"
class StockMismatchError extends RetailOSError {
constructor(readonly sku: string) {
super("RETAILOS_INVENTORY_STOCK_MISMATCH", `Stock mismatch for ${sku}.`)
this.name = "StockMismatchError"
}
}
try {
await doPosThing()
} catch (err) {
if (err instanceof RetailOSError) handle(err.code)
}Built-in subclasses: PermissionDeniedError (RETAILOS_PERMISSION_DENIED, carries subject + permission), UnknownPermissionError (RETAILOS_UNKNOWN_PERMISSION), IdentityResolutionError (RETAILOS_IDENTITY_RESOLUTION_FAILED).
PermissionRegistry
Permission keys are plain strings registered at boot. Modules export a PermissionRegistration[]; syncAllPermissions collects them and pushes them into a sync target (in practice the @devx-retailos/rbac module service).
import {
createInMemoryPermissionRegistry,
syncAllPermissions,
type PermissionRegistration,
} from "@devx-retailos/core"
const MY_PERMISSIONS: PermissionRegistration[] = [
{ key: "report.read", description: "View reports", registered_by: "reports" },
]
await syncAllPermissions(rbacService, MY_PERMISSIONS)FlagRegistry
Same pattern for boolean feature flags: FlagRegistration, createInMemoryFlagRegistry, syncAllFlags, each flag carrying a default_value.
DTOs
Plain data shapes shared across packages: OrganizationDTO, StoreDTO, PermissionDTO, RoleDTO, UserRoleDTO.
Related packages
@devx-retailos/rbac— org/store/role/permission RBAC Medusa module that consumes these types.@devx-retailos/employee— employee entity + anIdentityResolverimplementation for Medusa users.@devx-retailos/sdk-client— typed frontend client and React hooks.
License
MIT
