@opennetwork/logistics
v1.0.0-alpha.168
Published
[//]: # (badges)
Downloads
15
Readme
@opennetwork/logistics
Support
Test Coverage
Client
import { Client } from "@opennetwork/logistics/client";
const client = new Client({
url: process.env.API_URL || "http://localhost:3000"
});
const products = await client.listProducts();
console.log({ products });
export interface ClientOptions {
partnerId?: string;
accessToken?: string;
version?: number;
prefix?: string;
url?: string | URL;
}
export interface Client {
addPartner(partner: PartnerData): Promise<Partner>;
listPartners(): Promise<Partner[]>;
addProduct(product: ProductData): Promise<Product>;
setProduct(product: Product): Promise<Product>;
patchProduct(product: Pick<Product, "productId"> & Partial<Product>): Promise<Product>;
listProducts(): Promise<Product[]>;
addOffer(offer: OfferData): Promise<Offer>;
setOffer(offer: Offer): Promise<Offer>;
patchOffer(offer: Pick<Offer, "offerId"> & Partial<Offer>): Promise<Offer>;
listOffers(): Promise<Offer[]>;
listSystemLogs(): Promise<SystemLog[]>;
background(query: Record<string, string> | URLSearchParams): Promise<void>;
}
export type AppointmentType =
| "appointment"
| string
export type AppointmentStatus =
| "pending"
| "confirmed"
| "scheduled"
| "deferred"
| "cancelled"
| "completed"
| string
export interface AppointmentHistoryItem extends HappeningEventData {
status: AppointmentStatus;
statusAt?: string;
updatedAt: string;
}
export interface AppointmentData extends HappeningData {
type: AppointmentType
organisationId?: string;
attendees: string[];
attended?: boolean;
attendedAt?: string;
status?: AppointmentStatus;
history?: AppointmentHistoryItem[];
locationId?: string;
}
export interface Appointment extends AppointmentData {
appointmentId: string;
createdAt: string;
updatedAt: string;
status: AppointmentStatus;
statusAt: string;
history: AppointmentHistoryItem[];
}
export interface AppointmentAvailabilityData extends AppointmentData {
}
export interface AppointmentAvailability extends AppointmentAvailabilityData {
appointmentAvailabilityId: string;
createdAt: string;
updatedAt: string;
}
export interface AttendeeData extends Record<string, unknown> {
reference: string;
name?: string;
email?: string;
}
export interface Attendee extends AttendeeData {
attendeeId: string;
createdAt: string;
createdByPartnerId?: string;
createdByUserId?: string;
}
export type PartialAttendee = AttendeeData & Partial<Attendee>;
export type SystemRole = "system";
declare global {
interface AuthenticationRoles extends Record<SystemRole, SystemRole> {
}
}
export type AuthenticationRole =
| "moderator"
| "admin"
| "owner"
| "member"
| "booster"
| "industry"
| "developer"
| "coordinator"
| "partner"
| "anonymous"
| SystemRole
// Allows typing of authentication roles from the global scope.
// keys from multiple interface definitions in global will merge together
| keyof AuthenticationRoles;
export interface UserAuthenticationRoleData extends Expiring {
userId: string;
roles: AuthenticationRole[];
}
export interface UserAuthenticationRole extends UserAuthenticationRoleData {
createdAt: string;
updatedAt: string;
}
export type PartialUserAuthenticationRole = UserAuthenticationRoleData & Partial<UserAuthenticationRole>
export type AttendeeAuthorisationType = "attendee";
export type HappeningAuthorisationType = "happening";
export type AuthorisationType = AttendeeAuthorisationType | HappeningAuthorisationType;
export interface AuthorisationData {
type: AuthorisationType;
attendeeId?: string;
happeningId?: string;
notifications?: AuthorisationNotificationData[];
}
export interface Authorisation extends AuthorisationData {
authorisationId: string;
createdAt: string;
updatedAt: string;
notifiedAt?: string;
declinedAt?: string;
authorisedAt?: string;
}
export type AuthorisationNotificationType = (
| "payment"
| "message"
);
export interface AuthorisationNotificationData extends Record<string, unknown> {
type: AuthorisationNotificationType;
}
export interface AuthorisationNotification extends AuthorisationNotificationData {
notificationId: string;
authorisationId: string;
createdAt: string;
stateId?: string;
}
export type ChangeStatus = "pending" | "applied" | "cancelled" | string;
export interface ChangeOptionData extends Record<string, unknown> {
type?: string;
}
export interface ChangeTargetType {
type: string;
}
export interface ChangeTarget extends ChangeTargetType {
id: string;
}
export interface ChangeTargetIdentifier {
type: string;
target: ChangeTargetType;
}
export interface ChangeData extends ChangeTargetIdentifier, Expiring {
target: ChangeTarget;
userId?: string;
options?: ChangeOptionData;
data?: Record<string, unknown>;
}
export interface Change extends ChangeData {
status: ChangeStatus;
changeId: string;
createdAt: string;
updatedAt: string;
appliedAt?: string;
}
export interface ChangeIdentifier extends ChangeTargetIdentifier {
changeId: string;
}
export interface DurableEventSchedule {
timezone?: string;
// For cases where we want an event triggered after a specific time
after?: string;
// For cases where we want an event triggered before a specific time
before?: string;
immediate?: boolean;
cron?: string;
delay?: number | string;
// Once delay has completed, repeat
repeat?: boolean;
}
export interface UnknownEvent {
type: unknown;
}
export interface DurableEventTypeData extends UnknownEvent {
type: string;
}
export interface DurableEventData extends Record<string, unknown>, DurableEventTypeData, Expiring {
timeStamp?: number;
durableEventId?: string;
schedule?: DurableEventSchedule;
retain?: boolean;
virtual?: boolean;
serviceWorkerId?: string;
createdAt?: string;
}
export interface DurableEvent extends DurableEventData {
durableEventId: string
}
export type DurableBodyLike = string | DurableBody;
export interface DurableRequestData extends Expiring {
url: string;
method?: string;
headers?: Record<string, string>
body?: DurableBodyLike;
response?: DurableResponseData;
}
export interface DurableResponseCache {
name: string;
}
export interface DurableBody {
type: "file" | "base64" | "cache";
value: string;
url?: string;
}
export interface DurableResponseData extends Pick<Response, "url" | "status" | "statusText"> {
headers?: Record<string, string>
body?: DurableBodyLike;
}
export interface DurableRequest extends DurableRequestData {
durableRequestId: string;
createdAt: string;
updatedAt: string;
}
export interface RequestQueryInfo extends DurableRequestData {
}
export type RequestQuery = RequestQueryInfo | RequestInfo | URL
export type PartialDurableRequest = DurableRequestData & Partial<DurableRequest>;
export interface Expiring {
expiresAt?: string;
}
export type BaseFileStoreType = "product" | "inventory" | "productFile" | "inventoryFile" | "offer" | "offerFile" | "inventoryItem" | "order" | "orderItem" | "service"
export type BaseFileRemoteSourceName = "discord" | BaseFileStoreType;
export type RemoteFileSourceName = BaseFileRemoteSourceName | `${BaseFileRemoteSourceName}_${number}`;
export type FileUploadedSynced = "r2" | "disk";
export type FileType = BaseFileStoreType | `${RemoteFileSourceName}_import`;
export interface ResolvedFilePart extends Record<string, unknown> {
}
export interface FileImageSize extends Expiring {
width: number;
height: number;
signed?: boolean;
fileName?: string;
checksum?: Record<string, string>
}
export interface FileSize extends FileImageSize {
url: string;
synced: FileUploadedSynced;
syncedAt: string;
version: number;
watermark?: boolean;
copyright?: string;
license?: string;
fileName?: string;
signed?: boolean;
}
export interface FileErrorDescription {
stack?: string;
message: string;
createdAt: string;
repeated?: number;
}
export interface FileData extends Record<string, unknown>, Partial<FileImageSize> {
fileName: string;
contentType?: string;
size?: number;
path?: string;
url?: string;
pinned?: boolean;
uploadedAt?: string;
uploadedByUsername?: string;
source?: RemoteFileSourceName;
sourceId?: string;
synced?: FileUploadedSynced;
syncedAt?: string;
version?: number;
type?: FileType | string;
sizes?: FileSize[];
/** @deprecated use remoteUrl */
externalUrl?: string;
remoteUrl?: string;
reactionCounts?: Record<string, number>;
reactionCountsUpdatedAt?: string;
resolved?: ResolvedFilePart[];
resolvedAt?: string;
errors?: FileErrorDescription[];
description?: string;
fileId?: string;
}
export interface File extends FileData {
fileId: string;
createdAt: string;
updatedAt: string;
uploadedAt: string;
}
export interface ResolvedFile extends File {
url: string;
synced: FileUploadedSynced;
}
export interface FormMetaData extends Record<string, unknown> {}
export interface FormMeta extends FormMetaData {
formMetaId: string;
userId?: string;
partnerId?: string;
createdAt: string;
updatedAt: string;
}
export type HappeningType = (
| "event"
| "ticket"
| "appointment"
| "poll"
| "payment"
| "bill"
| "activity"
| "report"
| "availability"
| "intent"
| "swap"
);
export interface HappeningTreeData extends HappeningEventData {
type?: HappeningType | string;
attendees?: (string | AttendeeData)[]
children?: (string | HappeningTreeData)[]
}
export interface HappeningOptionData extends Record<string, unknown> {
type?: HappeningType | string;
}
export interface HappeningEventData extends Expiring, Record<string, unknown> {
startAt?: string // Intended start time
startedAt?: string // Actual start time
endAt?: string // Intended end time
endedAt?: string // Actual end time
createdAt?: string
type?: HappeningType | string;
reference?: string;
url?: string;
title?: string;
description?: string;
timezone?: string;
options?: HappeningOptionData[];
}
export interface HappeningData extends HappeningEventData {
type?: HappeningType | string;
parent?: string
children?: string[];
attendees?: string[];
partnerId?: string;
organisationId?: string;
userId?: string;
}
export interface Happening extends HappeningData {
type: HappeningType | string;
happeningId: string;
}
export type PartialHappening = HappeningData & Partial<Happening>
export interface HappeningTreeNoKey extends HappeningEventData {
type: string;
parent?: HappeningTree;
children: HappeningTree[];
attendees: Attendee[];
partnerId?: string;
partner?: Partner;
organisation?: Organisation;
userId?: string;
}
export interface HappeningTree extends HappeningTreeNoKey {
id: string;
type: HappeningType | string;
}
export interface Identifier {
type: string;
identifier: string;
identifiedAt: string;
}
export type InventoryType =
| "inventory"
| "picking"
| "packing"
| "transit"
export interface InventoryData {
type: InventoryType
userId?: string;
organisationId?: string;
locationId?: string;
items?: (InventoryItemIdentifierData & Partial<InventoryItem>)[];
}
export interface Inventory extends InventoryData {
inventoryId: string;
createdAt: string;
updatedAt: string;
}
export type InventoryItemStatus =
| "pending"
| "available"
| "processing"
| "split"
| "void";
export interface InventoryItemIdentifierData {
productId?: string;
offerId?: string; // Allows a bundled offer to be stored as inventory
quantity?: number; // Default 1
identifiers?: Identifier[]; // Default []
}
export interface InventoryItemData extends InventoryItemIdentifierData {
inventoryId: string;
status?: InventoryItemStatus;
// Record where it came from and was sent to
from?: ShipmentFrom;
to?: ShipmentTo | ShipmentTo[];
}
export interface InventoryItem extends InventoryItemData {
inventoryItemId: string;
createdAt: string;
updatedAt: string;
}
export interface InventoryProduct extends InventoryItem {
productId: string;
}
export interface InventoryOffer extends InventoryItem {
offerId: string;
}
export type SetInventoryItem = InventoryItemData & Pick<InventoryItem, "inventoryId" | "inventoryItemId"> & Partial<InventoryItem>;
export type LocationType =
| "place"
| "inventory"
| "packing"
| "picking"
export interface LocationData extends Record<string, unknown> {
type: LocationType
locationName?: string;
address?: string[];
countryCode?: string;
organisationId?: string;
userId?: string;
}
export interface Location extends LocationData {
locationId: string;
createdAt: string;
updatedAt: string;
}
export type MembershipStatus = "active" | "inactive";
export interface MembershipHistoryItem {
status: MembershipStatus;
statusAt?: string;
updatedAt: string;
}
export interface MembershipData extends Record<string, unknown> {
status?: MembershipStatus;
reference?: string;
name?: string;
email?: string;
timezone?: string;
history?: MembershipHistoryItem[];
}
export interface Membership extends MembershipData {
status: MembershipStatus;
reference: string;
membershipId: string;
createdAt: string;
createdByPartnerId?: string;
createdByUserId?: string;
updatedAt: string;
}
export type PartialMembership = MembershipData & Partial<Membership>;
export type MaybeNumberString = `${number}` | string;
export interface OfferPrice {
price: MaybeNumberString;
locale?: string;
currency: string;
currencyCode?: string;
currencySymbol?: string;
countryCode?: string;
}
export interface TotalOfferPrice extends OfferPrice {
total?: MaybeNumberString;
}
export interface ProductOfferItem {
type: "product";
productId: string;
quantity?: number;
identifiers?: Identifier[];
}
export interface ServiceOfferItem {
type: "service";
serviceId: string;
quantity?: number;
identifiers?: Identifier[];
}
export type OfferItem =
| ProductOfferItem
| ServiceOfferItem
export type OfferItemType = OfferItem["type"];
export type OfferStatus =
| "speculative"
| "preSale"
| "preOrder"
| "onlineOnly"
| "storeOnly"
| "available"
| "backOrder"
| "limitedAvailability"
| "soldOut"
| "void"
| string;
export interface OfferData extends Record<string, unknown>, Partial<OfferPrice> {
status: OfferStatus;
items: OfferItem[];
// The user that is providing this offer
userId?: string;
// The organisation that is providing this offer
organisationId?: string;
offerName?: string;
// Is the offer publicly visible
public?: boolean;
countryCode?: string;
// Offer can be from one party to another
from?: ShipmentFrom;
to?: ShipmentTo;
}
export interface Offer extends OfferData {
offerId: string;
createdAt: string;
updatedAt: string;
}
export type OrderStatus = "pending" | "submitted" | "processing" | "complete" | string;
export interface OrderData {
status: OrderStatus;
reference?: string;
to?: ShipmentTo;
// Is it from a specific known location?
from?: ShipmentFrom;
// Partial in progress payment data, before the payment method is created or matched
paymentMethod?: Partial<PaymentMethodData>
// Partial in progress payment data, before the payment request is created or matched
paymentRequest?: Partial<PaymentRequestData>
paymentId?: string;
paymentRequestId?: string;
paymentMethodId?: string;
}
export interface Order extends OrderData, Partial<TotalOfferPrice> {
orderId: string;
createdAt: string;
updatedAt: string;
items?: OrderItem[];
products?: OrderProductItem[];
services?: OrderServiceItem[];
}
export interface OrderItemIdentifierData {
productId?: string;
serviceId?: string;
offerId?: string;
quantity?: number; // Default 1
identifiers?: Identifier[]; // Default []
}
export interface OrderItemData extends OrderItemIdentifierData, Record<string, unknown> {
orderId: string;
}
export interface OrderItem extends OrderItemData {
orderItemId: string;
createdAt: string;
updatedAt: string;
}
export interface OrderProductItem extends OrderItem {
productId: string;
}
export interface OrderServiceItem extends OrderItem {
serviceId: string;
}
export interface OrderOfferItem extends OrderItem {
offerId: string;
}
export type SetOrderItem = OrderItemData & Pick<OrderItem, "orderId" | "orderItemId"> & Partial<OrderItem>;
export interface OrganisationBaseData extends Record<string, unknown> {
countryCode?: string; // "NZ"
location?: string;
remote?: boolean;
onsite?: boolean;
pharmacy?: boolean;
delivery?: boolean;
clinic?: boolean;
website?: string;
associatedBrandingTerms?: string[]; // Eg common names used to refer to the organisation by way of brand
}
export interface OrganisationData extends OrganisationBaseData {
organisationName: string;
partnerId?: string;
approved?: boolean;
approvedAt?: string;
}
export interface Organisation extends OrganisationData {
organisationId: string;
createdAt: string;
updatedAt: string;
approvedByUserId?: string;
}
export type PartialOrganisation = OrganisationData & Partial<Organisation>;
export interface PartnerData extends Record<string, unknown> {
partnerName: string;
countryCode?: string;
}
export interface AddPartnerData extends PartnerData, OrganisationBaseData {}
export interface Partner extends PartnerData {
partnerId: string;
organisationId: string;
accessToken?: string;
createdAt: string;
updatedAt: string;
approved?: boolean;
approvedAt?: string;
approvedByUserId?: string;
}
export type PaymentType =
| "invoice"
| "realtime"
| string;
export type PaymentStatus =
| "pending"
| "processing"
| "processed"
| "paid"
| "void"
| string;
export interface Amount {
amount: string;
currency: string;
}
export interface PaymentData extends PaymentMethodIdentifier, Record<string, unknown> {
type: PaymentType;
status: PaymentStatus;
totalAmount?: Amount;
reference?: string;
userId?: string;
organisationId?: string;
paymentRequestId?: string;
}
export interface PaymentIdentifier extends PaymentMethodOwnerIdentifiers {
paymentId: string;
}
export interface Payment extends PaymentIdentifier, PaymentData {
createdAt: string;
updatedAt: string;
}
export type PaymentMethodType =
| "invoice"
| "realtime"
| string;
export type PaymentMethodStatus = "pending" | "available" | "expired" | "void";
export interface PaymentMethodOwnerIdentifiers {
userId?: string;
organisationId?: string;
}
export interface PaymentMethodIdentifier extends PaymentMethodOwnerIdentifiers {
paymentMethodId: string;
}
export interface PaymentMethodData extends Record<string, unknown>, PaymentMethodOwnerIdentifiers {
status: PaymentMethodStatus;
type: PaymentMethodType;
currency?: string;
paymentMethodName?: string;
issuerName?: string;
issuerId?: string;
issuerPaymentMethodId?: string;
to?: ShipmentTo;
}
export interface PaymentMethod extends PaymentMethodData, PaymentMethodIdentifier {
createdAt: string;
updatedAt: string;
}
export type PaymentRequestType =
| "invoice"
| "realtime"
| string;
export type PaymentRequestStatus = "pending" | "accepted" | "expired" | "void";
export interface PaymentRequestOwnerIdentifiers {
userId?: string;
organisationId?: string;
}
export interface PaymentRequestIdentifier extends PaymentRequestOwnerIdentifiers {
paymentRequestId: string;
}
export interface PaymentRequestData extends Record<string, unknown>, PaymentRequestOwnerIdentifiers {
status?: PaymentRequestStatus;
types?: PaymentRequestType[];
paymentMethodId?: string;
to?: ShipmentTo;
from?: ShipmentFrom;
totalAmount?: Amount;
}
export interface PaymentRequest extends PaymentRequestData, PaymentRequestIdentifier {
status: PaymentRequestStatus;
types: PaymentRequestType[];
createdAt: string;
updatedAt: string;
}
export interface ProductData extends Record<string, unknown> {
productName: string;
description?: string;
// Is the product publicly visible
public?: boolean;
// Is the related not to a specific brand
generic?: boolean;
// User provided organisation name associated with this product
organisationText?: string;
// System resolved organisation name associated with this product
organisationName?: string;
// System associated organisation name associated with this product
organisationId?: string;
}
export interface Product extends ProductData {
productId: string;
createdAt: string;
updatedAt: string;
}
export interface ServiceData extends Record<string, unknown> {
serviceName: string;
description?: string;
// Is the service publicly visible
public?: boolean;
// Is the related not to a specific brand
generic?: boolean;
// User provided organisation name associated with this service
organisationText?: string;
// System resolved organisation name associated with this service
organisationName?: string;
// System associated organisation name associated with this service
organisationId?: string;
}
export interface Service extends ServiceData {
serviceId: string;
createdAt: string;
updatedAt: string;
}
export type ShipmentStatus = "pending" | "processing" | "sent" | "delivered";
export interface ShipmentLocation {
userId?: string;
organisationId?: string;
organisationText?: string; // User given text
organisationName?: string; // Actual stored name
locationId?: string;
inventoryId?: string;
inventoryItemId?: string;
orderId?: string;
address?: string[]; // Human-readable address
countryCode?: string;
saveAsUserDefault?: boolean;
sameAsShipping?: boolean;
name?: string;
email?: string; // Yeah it is shipment information...
}
export interface ShipmentIdentifiers {
identifiers?: Identifier[];
}
export interface ShipmentFrom extends ShipmentLocation, ShipmentIdentifiers {
}
export interface ShipmentTo extends ShipmentLocation, ShipmentIdentifiers {
}
export interface ShipmentData extends Record<string, unknown> {
status: ShipmentStatus;
// from is optional as you might receive with no info
from?: ShipmentFrom;
// A shipment would always have a destination
to: ShipmentTo;
identifiers?: Identifier[];
}
export interface Shipment extends ShipmentData {
shipmentId: string;
createdAt: string;
updatedAt: string;
}
export interface SystemLogData extends Record<string, unknown> {
uniqueCode?: string;
value?: number;
partnerId: string;
message: string;
timestamp?: string;
action?: string;
}
export interface SystemLog extends SystemLogData {
systemLogId: string;
timestamp: string;
}
export type TaskType =
| "inventory"
| "packing"
| "picking"
| "order"
| "product"
| "offer"
export interface TaskData extends HappeningData {
type: TaskType
title: string;
organisationId?: string;
attendees: string[];
}
export interface Task extends TaskData {
taskId: string;
createdAt: string;
updatedAt: string;
}
Local Development
Dependencies
You will need to install the dependencies with yarn
Once you have yarn installed, use the command:
yarn
.env
First you will need to set up a .env
file in the same directory as this README.md file
Copy the .env.example
to make your .env
file
To setup reddit authentication, you will need to either be provided a client ID if you're working with the socialbaking team, or you will need to create a new application at the bottom of this screen
The local redirect url is http://localhost:3000/api/authentication/reddit/callback
Once created, copy the value under "web app" and set that as your REDDIT_CLIENT_ID
Copy the "secret" and set that as REDDIT_CLIENT_SECRET
Set the reddit community name, and associated flair, as you see fit:
REDDIT_NAME=MedicalCannabisNZ
REDDIT_FLAIR="Medical Patient"