🏷️ Attribute
Attribute manages named groups of string key-value items through the attributesService CRUD API.
Start here
attributesService needs attributes and identities collections. List and read routes are public; create, update, and delete require an authenticated identity whose type matches the configured administrator ID.
attributesService(dataStores, configuration) composes createAttributeFeature, getAttributeFeature, findAttributesFeature, updateAttributeFeature, and deleteAttributeFeature in that order. It injects the selected authentication adapter, configuration, and datastore into every route pipeline. See the Attribute service, auth utility, and cookie utility.
import express from 'express';
import cookieParser from 'cookie-parser';
import {services} from '@nodeblocks/backend-sdk';
const app = express();
app.use(express.json());
app.use(cookieParser()); // Required only for authMode: 'cookie'.
app.use('/api', services.attributesService(
{attributes, identities},
{
authSecrets: {
authEncSecret: process.env.AUTH_ENC_SECRET!,
authSignSecret: process.env.AUTH_SIGN_SECRET!,
},
authMode: 'bearer',
identity: {typeIds: {admin: 'admin', guest: 'guest', regular: 'regular'}},
},
));
| Configuration | Default / source behavior | Effect |
|---|---|---|
authSecrets.authEncSecret, authSecrets.authSignSecret | Required for protected routes; no default in this service | Verifies access tokens. |
authMode | Omitted or 'bearer' selects getBearerTokenInfo | Protected routes read the Authorization header. |
authMode: 'cookie' | Selects getCookieTokenInfo when set | Protected routes read access-token cookies; register cookie-parser first. |
identity.typeIds.admin | Required for protected routes; read by checkIdentityType(['admin']) | Identifies administrator identities. |
| Export | Contract |
|---|---|
AttributesServiceDataStore | Requires MongoDB attributes and identities collections. |
AttributesServiceConfiguration | Requires authSecrets; optionally selects authMode and supplies identity type IDs. |
AttributesService | Service<AttributesServiceDataStore, AttributesServiceConfiguration>. |
attributesService | Creates the mounted Express router from the five Attribute feature composers. |
View service composition source
export interface AttributesServiceDataStore {
attributes: Collection;
identities: Collection;
}
export interface AttributesServiceConfiguration {
authSecrets: {
authEncSecret: string;
authSignSecret: string;
};
authMode?: 'bearer' | 'cookie';
identity?: {
typeIds?: {
admin: string;
guest: string;
regular: string;
};
};
}
export type AttributesService = Service<
AttributesServiceDataStore,
AttributesServiceConfiguration
>;
export const attributesService: AttributesService = (dataStores, configuration) => {
return defService(
partial(
compose(
createAttributeFeature,
getAttributeFeature,
findAttributesFeature,
updateAttributeFeature,
deleteAttributeFeature
),
[{
authenticate: configuration.authMode === 'cookie'
? getCookieTokenInfo
: getBearerTokenInfo,
configuration,
dataStores,
}]
)
);
};
Common tasks
| Task | Start with | Contract |
|---|---|---|
| List attribute groups | findAttributesFeature | List route and query schema |
| Read one group | getAttributeFeature | Get route and path schema |
| Create a group | createAttributeFeature | Create route and create schema |
| Rename a group | updateAttributeFeature | Update route; only name is accepted |
| Delete a group | deleteAttributeFeature | Delete route and path schema |
| Build a selected API | Feature composers | Composite-service guide |
Bearer HTTP workflow
API_BASE_URL='http://localhost:8080/api'
ATTRIBUTE_ID='replace-with-an-existing-attribute-id'
ADMIN_ACCESS_TOKEN='replace-with-an-administrator-access-token'
curl "$API_BASE_URL/attributes?name=Product&page=1&limit=20"
curl "$API_BASE_URL/attributes/$ATTRIBUTE_ID"
curl -X POST "$API_BASE_URL/attributes" \
-H "authorization: Bearer $ADMIN_ACCESS_TOKEN" \
-H 'content-type: application/json' \
-d '{"name":"Product options","items":[{"key":"color","value":"red"}]}'
The list and read routes return 200. Create returns 201 with the created group; an invalid/missing administrator credential fails before the pipeline. The linked create schema, create route, and validators define the full contract.
Cookie HTTP workflow
Set authMode: 'cookie', register cookie-parser before the service, and obtain an access-cookie jar through the Authentication login route. The credentials below must belong to an administrator identity.
API_BASE_URL='http://localhost:8080/api'
ATTRIBUTE_ID='replace-with-an-existing-attribute-id'
ADMIN_EMAIL='admin@example.com'
ADMIN_PASSWORD='replace-with-the-admin-password'
curl -c cookies.txt -X POST "$API_BASE_URL/auth/login" \
-H 'content-type: application/json' \
-d "{\"email\":\"$ADMIN_EMAIL\",\"password\":\"$ADMIN_PASSWORD\"}"
curl -b cookies.txt -X PATCH "$API_BASE_URL/attributes/$ATTRIBUTE_ID" \
-H 'content-type: application/json' \
-d '{"name":"Updated product options"}'
The request still requires an administrator identity. The update schema accepts an empty object, but the handler rejects an empty body with 400. See the Authentication cookie workflow for session refresh and logout.
Custom feature composition
This complete fragment builds a router containing only create and list routes. It assumes populated attributes, identities, authSecrets, and typeIds variables.
import {partial} from 'ramda';
import {features, primitives, utils} from '@nodeblocks/backend-sdk';
const attributeFeatureComposer = primitives.compose(
features.createAttributeFeature,
features.findAttributesFeature,
);
const attributeRouter = primitives.defService(partial(attributeFeatureComposer, [{
authenticate: utils.getBearerTokenInfo,
configuration: {authSecrets, identity: {typeIds}},
dataStores: {attributes, identities},
}]));
app.use('/api', attributeRouter);
Reference map
| Page | Purpose |
|---|---|
| Features | Schema-to-route composers. |
| Handlers | Pipeline operations and terminators. |
| Routes | HTTP contracts and full route source. |
| Schemas | Field-level request contracts. |
| Validators | Shared administrator access checks used by mutations. |
Attribute has no blocks.md page because the SDK exports no Attribute-specific block layer.
Related modules
Use the Attribute service for the broader service reference, Authentication to issue sessions, schema component for shared schema behavior, and error handling for application-level errors.