62 lines
2.6 KiB
TypeScript
62 lines
2.6 KiB
TypeScript
// The port the inventory module's use cases are written against: the platform's Inventory service,
|
|
// in this module's own words. Core imports no client: adapters/service.ts is the one place that knows
|
|
// `@conusai-sdk/inventory` and `@conusai-kit/business` exist, and it turns every refusal into the
|
|
// kit's app errors (`businessAppError` of
|
|
// `@conusai-kit/business`) before core sees it.
|
|
|
|
import { token } from "@conusai-kit/core"
|
|
import type { AvailabilityView, ItemView, ReservationView } from "../contract/index.js"
|
|
|
|
/** One page of a service list: `after` asks for the next, absent on the last. */
|
|
export interface Page<T> {
|
|
readonly rows: T[]
|
|
readonly after?: string
|
|
}
|
|
|
|
/** What a `read` procedure may ask the service: nothing that changes a row. */
|
|
export interface InventoryReads {
|
|
/** The immutable app/environment binding UUID for project references. */
|
|
readonly bindingId: string
|
|
listItems(query: { q?: string; after?: string; limit: number }): Promise<Page<ItemView>>
|
|
getItem(itemId: string): Promise<ItemView>
|
|
availability(itemId: string): Promise<AvailabilityView>
|
|
listReservations(query: {
|
|
reference: string
|
|
status?: "open" | "closed"
|
|
after?: string
|
|
limit: number
|
|
}): Promise<Page<ReservationView>>
|
|
getReservation(reservationId: string): Promise<{ reservation: ReservationView; reference: string }>
|
|
}
|
|
|
|
export interface InventoryService extends InventoryReads {
|
|
createItem(input: { sku: string; name: string; unit: string; description?: string }): Promise<ItemView>
|
|
reserve(input: {
|
|
itemId: string
|
|
locationId: string
|
|
quantity: number
|
|
reference: string
|
|
key: string
|
|
}): Promise<ReservationView>
|
|
release(input: { reservationId: string; quantity?: number; key: string }): Promise<ReservationView>
|
|
}
|
|
|
|
/** The read view a `read` or `write` handler receives: the kind is a capability, not a label. */
|
|
export const inventoryReadsOf = (service: InventoryReads): InventoryReads => ({
|
|
bindingId: service.bindingId,
|
|
listItems: (query) => service.listItems(query),
|
|
getItem: (itemId) => service.getItem(itemId),
|
|
availability: (itemId) => service.availability(itemId),
|
|
listReservations: (query) => service.listReservations(query),
|
|
getReservation: (reservationId) => service.getReservation(reservationId),
|
|
})
|
|
|
|
/**
|
|
* Bound by a composition root or a test that brings its own client (another organization, the
|
|
* business-services fake). With nothing bound, the module calls the service of this deployment
|
|
* (adapters/service.ts).
|
|
*/
|
|
export const INVENTORY_SERVICE = token<InventoryService>("inventory.service", {
|
|
views: { read: inventoryReadsOf, write: inventoryReadsOf },
|
|
})
|