メインコンテンツまでスキップ
バージョン: 🚧 Canary

🛒 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',
},
},
},
),
);
ConfigurationDefault / source behaviorEffect
dataStores.ordersRequiredRead and written by every Order route.
dataStores.identitiesRequiredRequired by checkIdentityType(['admin']) on the five administrator-or-self/owner routes.
dataStores.organizationsRequired by the organization-scoped route; optional in the service typehasOrgRole(...) reads it on GET /orders/organizations/:organizationId; that mounted route cannot authorize without it.
authSecrets.authEncSecret, authSecrets.authSignSecretRequiredUsed by the selected access-token authentication adapter.
identity.typeIds.adminRequired by the five administrator-alternative routesCompared with the caller identity by checkIdentityType(['admin']).
organization.roles.owner, organization.roles.admin, organization.roles.memberRequired by the organization-scoped routeUsed by hasOrgRole(['owner', 'admin', 'member'], ...).

Common tasks

TaskStart withContract
Create an ordercreateOrderFeaturecreateOrderFeature, createOrderRoute, and createOrderSchema
Read, update, or delete an ordergetOrderRoutegetOrderRoute, updateOrderRoute, and deleteOrderRoute with their linked schemas
List one identity's ordersfindOrdersRoutefindOrdersRoute and findOrdersSchema; the caller must be that identityId unless an administrator
List organization ordersfindOrdersByOrganizationIdRoutefindOrdersByOrganizationIdRoute 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.

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

PagePurpose
BlocksReusable order query block and errors.
FeaturesSchema-to-route composers.
HandlersRoute pipeline operations and terminators.
RoutesEndpoint, access, and response contracts.
SchemasField-level request validation.
ValidatorsLocal ownership and shared access rules.

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.