🛒 Order
Order provides authenticated creation, retrieval, search, update, deletion, and organization-scoped order listing through orderService.
Start here
orderService(dataStores, configuration) returns an Express router. The typed service store includes orders and identities; include organizations when mounting the organization-scoped listing route. Its router already installs express.json(), so no additional JSON parser is required for this service mount.
import express from 'express';
import {services} from '@nodeblocks/backend-sdk';
const app = express();
app.use(
'/api',
services.orderService(
{identities, orders, organizations},
{
authSecrets: {
authEncSecret: 'replace-with-a-secret',
authSignSecret: 'replace-with-a-secret',
},
identity: {
typeIds: {
admin: '00000000-0000-4000-8000-000000000001',
guest: '00000000-0000-4000-8000-000000000002',
regular: '00000000-0000-4000-8000-000000000003',
},
},
organization: {
roles: {
admin: 'admin',
member: 'member',
owner: 'owner',
},
},
},
),
);
| Configuration | Default / source behavior | Effect |
|---|---|---|
dataStores.orders | Required | Read and written by every Order route. |
dataStores.identities | Required | Required by checkIdentityType(['admin']) on the five administrator-or-self/owner routes. |
dataStores.organizations | Required by the organization-scoped route; optional in the service type | hasOrgRole(...) reads it on GET /orders/organizations/:organizationId; that mounted route cannot authorize without it. |
authSecrets.authEncSecret, authSecrets.authSignSecret | Required | Used by the selected access-token authentication adapter. |
identity.typeIds.admin | Required by the five administrator-alternative routes | Compared with the caller identity by checkIdentityType(['admin']). |
organization.roles.owner, organization.roles.admin, organization.roles.member | Required by the organization-scoped route | Used by hasOrgRole(['owner', 'admin', 'member'], ...). |
Common tasks
| Task | Start with | Contract |
|---|---|---|
| Create an order | createOrderFeature | createOrderFeature, createOrderRoute, and createOrderSchema |
| Read, update, or delete an order | getOrderRoute | getOrderRoute, updateOrderRoute, and deleteOrderRoute with their linked schemas |
| List one identity's orders | findOrdersRoute | findOrdersRoute and findOrdersSchema; the caller must be that identityId unless an administrator |
| List organization orders | findOrdersByOrganizationIdRoute | findOrdersByOrganizationIdRoute and cross-domain findByOrganizationIdSchema |
Bearer HTTP workflow
With the default mode, send an access token in Authorization. This request targets the protected createOrderRoute and conforms to createOrderSchema; its body identityId must match the caller unless the caller is an administrator.
curl --request POST 'http://localhost:3000/api/orders' \
--header 'Authorization: Bearer <access-token>' \
--header 'Content-Type: application/json' \
--data '{"identityId":"00000000-0000-4000-8000-000000000010","items":[{"productId":"00000000-0000-4000-8000-000000000011","quantity":1,"price":19.99}],"total":19.99}'
On success it returns 201 and the created order without MongoDB _id. A missing/invalid access token fails authentication; a different body identity fails the self branch unless the administrator branch passes.
Cookie HTTP workflow
For cookie transport, this host fragment must run before the service mount; cookie-parser supplies the accessToken read by the selected authentication function.
import cookieParser from 'cookie-parser';
app.use(cookieParser());
app.use('/api', services.orderService({identities, orders}, {...configuration, authMode: 'cookie'}));
Then send the same createOrderSchema JSON body to createOrderRoute with the cookie rather than an Authorization header:
ACCESS_TOKEN='replace-with-a-valid-access-token'
curl --request POST 'http://localhost:3000/api/orders' \
--header "Cookie: accessToken=$ACCESS_TOKEN" \
--header 'Content-Type: application/json' \
--data '{"identityId":"00000000-0000-4000-8000-000000000010","items":[{"productId":"00000000-0000-4000-8000-000000000011","quantity":1,"price":19.99}],"total":19.99}'
The success response remains 201 with the created order and no MongoDB _id; the caller must be an administrator or match the body identityId. A missing accessToken cookie is 401.
Custom feature composition
This is a complete Bearer-mode service fragment. dataStores must contain the collections required by the selected features, and configuration must contain authSecrets, identity.typeIds.admin, plus organization.roles when the final feature is retained.
import {partial} from 'ramda';
import {features, primitives, utils} from '@nodeblocks/backend-sdk';
const orderRouter = primitives.defService(
partial(
primitives.compose(
features.createOrderFeature,
features.updateOrderFeature,
features.getOrderFeature,
features.findOrdersFeature,
features.deleteOrderFeature,
features.findOrdersByOrganizationIdFeature,
),
[
{
authenticate: utils.getBearerTokenInfo,
configuration,
dataStores,
},
],
),
);
app.use('/api', orderRouter);
This composer registers the same schema/route pairs as orderService. Remove the organization-list feature only when the host intentionally does not provide its organization dependencies.
Reference map
| Page | Purpose |
|---|---|
| Blocks | Reusable order query block and errors. |
| Features | Schema-to-route composers. |
| Handlers | Route pipeline operations and terminators. |
| Routes | Endpoint, access, and response contracts. |
| Schemas | Field-level request validation. |
| Validators | Local ownership and shared access rules. |
Related modules
Order service is the service-level integration reference. Common validators provide authentication, some(...), and administrator checks. Organization blocks supply the organization filter used by the scoped route, while Organization schemas attach its request validation. Mongo blocks provide the underlying paginated query primitive for findOrders.