メインコンテンツまでスキップ
バージョン: 0.9.0 (最新)

🏷️ 属性サービス

Testing Status

Attribute Serviceは、キーと値のペアを持つ属性グループを管理するための完全なREST APIを提供します。Nodeblocksの関数型コンポジションアプローチとMongoDB統合を使用して、製品属性、カテゴリプロパティ、その他の構造化メタデータを処理するように設計されています。


🚀 クイックスタート

import express from 'express';
import { middlewares, services, drivers } from '@nodeblocks/backend-sdk';

const { nodeBlocksErrorMiddleware } = middlewares;
const { attributesService } = services;
const { withMongo } = drivers;

const connectToDatabase = withMongo('mongodb://localhost:27017', 'dev', 'user', 'password');

express()
.use(
attributesService(
{
...(await connectToDatabase('attributes')),
...(await connectToDatabase('identities')),
},
{
authSecrets: {
authEncSecret: 'your-encryption-secret',
authSignSecret: 'your-signing-secret',
},
identity: {
typeIds: {
admin: '100',
guest: '000',
regular: '001'
}
}
}
)
)
.use(nodeBlocksErrorMiddleware())
.listen(8089, () => console.log('Server running'));

📋 エンドポイント概要

属性グループ操作

MethodPath説明認証が必要
POST/attributes新しい属性グループを作成✅ Admin
GET/attributes/:attributeIdIDで属性グループを取得❌ None
GET/attributes属性グループをリスト/フィルタ❌ None
PATCH/attributes/:attributeId属性グループを更新✅ Admin
DELETE/attributes/:attributeId属性グループを削除✅ Admin

🗄️ エンティティスキーマ

属性グループエンティティは、基本フィールド(自動生成)と属性固有のデータを組み合わせたものです:

{
"name": "string",
"items": [
{
"key": "string",
"value": "string"
}
],
"createdAt": "string (datetime)",
"id": "string",
"updatedAt": "string (datetime)"
}

フィールド詳細

FieldType自動生成必須説明
namestring属性グループ名
itemsarrayキーと値のペアの配列(最小1項目)
items[].keystring属性キー/名前
items[].valuestring属性値
createdAtdatetime作成タイムスタンプ
idstring一意の識別子(UUID)
updatedAtdatetime最終更新タイムスタンプ

📝 注意: 自動生成フィールドはサービスによって設定され、作成/更新リクエストに含めるべきではありません。items配列には少なくとも1つのキーと値のペアが含まれている必要があります。


🔐 認証ヘッダー

保護されたエンドポイントでは、次のヘッダーを含めてください:

Authorization: Bearer <admin_access_token>
x-nb-fingerprint: <device_fingerprint>

⚠️ 重要: x-nb-fingerprintヘッダーは、認証時にフィンガープリントが指定された場合、すべての認証済みリクエストで必須です。これがない場合、リクエストは401 Unauthorizedを返します。


🔧 APIエンドポイント

1. 属性グループの作成

提供された名前とキーと値のペアで新しい属性グループを作成します。

リクエスト:

  • Method: POST
  • Path: /attributes
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: 管理者ロールが必要

リクエストボディ:

FieldType必須説明
namestring属性グループ名
itemsarrayキーと値のペアの配列(最小1項目)
items[].keystring属性キー/名前
items[].valuestring属性値

レスポンスボディ:

FieldType説明
namestring属性グループ名
itemsarrayキーと値のペアの配列
items[].keystring属性キー/名前
items[].valuestring属性値
createdAtstring作成タイムスタンプ
idstring一意の属性グループ識別子
updatedAtstring最終更新タイムスタンプ

バリデーション:

  • スキーマバリデーション: 自動的に強制されます(name、items必須、追加プロパティなし)

  • ルートバリデーター:

    • 認証済みリクエストが必要(bearerトークン)
    • 管理者ロールが必要
  • アイテムバリデーション: 少なくとも1項目を含み、それぞれに必須のキーと値が必要

リクエスト例:

curl -X POST {{host}}/attributes \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <admin_token>" \
-H "x-nb-fingerprint: test-device-fingerprint" \
-d '{
"name": "Product Specifications",
"items": [
{
"key": "Color",
"value": "Blue"
},
{
"key": "Size",
"value": "Large"
},
{
"key": "Material",
"value": "Cotton"
}
]
}'

成功レスポンス:

HTTP/1.1 201 Created
Content-Type: application/json

{
"name": "Product Specifications",
"items": [
{
"key": "Color",
"value": "Blue"
},
{
"key": "Size",
"value": "Large"
},
{
"key": "Material",
"value": "Cotton"
}
],
"createdAt": "2025-07-07T08:52:49.796Z",
"id": "69b013c9-cb20-4a7e-9c1f-59a55db1d949",
"updatedAt": "2025-07-07T08:52:49.796Z"
}

エラーレスポンス:

必須フィールドがリクエストボディにない場合:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'items'"
]
}
}

items配列が空の場合:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
"error": {
"message": "Validation Error",
"data": [
"request body must NOT have fewer than 1 items"
]
}
}

認証が失敗した場合:

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
"error": {
"message": "Authentication failed"
}
}

2. IDで属性グループを取得

一意のIDで特定の属性グループを取得します。

リクエスト:

  • Method: GET
  • Path: /attributes/:attributeId
  • Headers: なし
  • Authorization: 不要

URLパラメータ:

ParameterType必須説明
attributeIdstring一意の属性グループ識別子

レスポンスボディ:

FieldType説明
namestring属性グループ名
itemsarrayキーと値のペアの配列
items[].keystring属性キー/名前
items[].valuestring属性値
createdAtstring作成タイムスタンプ
idstring一意の属性グループ識別子
updatedAtstring最終更新タイムスタンプ

バリデーション:

  • スキーマバリデーション: attributeIdのパスパラメータ検証
  • ルートバリデーター: なし

リクエスト例:

curl {{host}}/attributes/69b013c9-cb20-4a7e-9c1f-59a55db1d949

成功レスポンス:

HTTP/1.1 200 OK
Content-Type: application/json

{
"name": "Product Specifications",
"items": [
{
"key": "Color",
"value": "Blue"
},
{
"key": "Size",
"value": "Large"
},
{
"key": "Material",
"value": "Cotton"
}
],
"createdAt": "2025-07-07T08:52:49.796Z",
"id": "69b013c9-cb20-4a7e-9c1f-59a55db1d949",
"updatedAt": "2025-07-07T08:52:49.796Z"
}

エラーレスポンス:

提供されたIDの属性グループが存在しない場合:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Attribute group not found"
}
}

3. 属性グループのリスト取得

オプションのフィルタリングとページネーションを使用して属性グループのリストを取得します。

リクエスト:

  • Method: GET
  • Path: /attributes
  • Headers: なし
  • Authorization: 不要

クエリパラメータ:

ParameterType必須説明
namestring属性グループ名でフィルタ
pagenumberページネーションのページ番号(1-1000)
limitnumberページあたりの項目数(1-50)

レスポンスボディ: 属性グループの配列とメタデータを含むページネーション付きレスポンス。

レスポンス構造:

{
"data": [
{
"name": "string",
"items": [
{
"key": "string",
"value": "string"
}
],
"createdAt": "string",
"id": "string",
"updatedAt": "string"
}
],
"metadata": {
"pagination": {
"page": number,
"limit": number,
"total": number,
"totalPages": number,
"hasNext": boolean,
"hasPrev": boolean
}
}
}

バリデーション:

  • スキーマバリデーション: 名前とページネーション(page、limit)のクエリパラメータ検証
  • ルートバリデーター: なし

リクエスト例:

すべての属性グループをリスト:

curl {{host}}/attributes

名前でフィルタ:

curl "{{host}}/attributes?name=Product"

成功レスポンス:

HTTP/1.1 200 OK
Content-Type: application/json

{
"data": [
{
"name": "Product Specifications",
"items": [
{
"key": "Color",
"value": "Blue"
},
{
"key": "Size",
"value": "Large"
}
],
"createdAt": "2025-07-07T08:52:49.796Z",
"id": "69b013c9-cb20-4a7e-9c1f-59a55db1d949",
"updatedAt": "2025-07-07T08:52:49.796Z"
},
{
"name": "Technical Details",
"items": [
{
"key": "Weight",
"value": "2.5kg"
},
{
"key": "Dimensions",
"value": "30x20x15cm"
}
],
"createdAt": "2025-07-07T08:20:45.456Z",
"id": "b2c3d4e5-f6g7-8901-bcde-f23456789012",
"updatedAt": "2025-07-07T08:20:45.456Z"
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 10,
"total": 2,
"totalPages": 1,
"hasNext": false,
"hasPrev": false
}
}
}

ページネーション付きリクエスト例:

curl "{{host}}/attributes?page=1&limit=10"

4. 属性グループの更新

既存の属性グループを更新します。注意: スキーマによると、nameフィールドのみを更新できます - items配列は更新エンドポイントを通じて変更できません。

リクエスト:

  • Method: PATCH
  • Path: /attributes/:attributeId
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: 管理者ロールが必要

URLパラメータ:

ParameterType必須説明
attributeIdstring一意の属性グループ識別子

リクエストボディ:

FieldType必須説明
namestring新しい属性グループ名

レスポンスボディ:

FieldType説明
namestring更新された属性グループ名
itemsarrayキーと値のペアの配列(変更なし)
items[].keystring属性キー/名前
items[].valuestring属性値
createdAtstring作成タイムスタンプ
idstring一意の属性グループ識別子
updatedAtstring最終更新タイムスタンプ

バリデーション:

  • スキーマバリデーション: 自動的に強制されます(nameフィールドのみ許可、追加プロパティなし)
  • ルートバリデーター:
    • 認証済みリクエストが必要(bearerトークン)
    • 管理者ロールが必要

⚠️ 重要: 更新スキーマではnameフィールドのみの更新が許可されています。items配列を変更するには、属性グループを削除して再作成する必要があります。

リクエスト例:

curl -X PATCH {{host}}/attributes/69b013c9-cb20-4a7e-9c1f-59a55db1d949 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <admin_token>" \
-H "x-nb-fingerprint: test-device-fingerprint" \
-d '{"name": "Updated Product Specifications"}'

成功レスポンス:

HTTP/1.1 200 OK
Content-Type: application/json

{
"name": "Updated Product Specifications",
"items": [
{
"key": "Color",
"value": "Blue"
},
{
"key": "Size",
"value": "Large"
},
{
"key": "Material",
"value": "Cotton"
}
],
"createdAt": "2025-07-07T08:52:49.796Z",
"id": "69b013c9-cb20-4a7e-9c1f-59a55db1d949",
"updatedAt": "2025-07-07T08:54:07.406Z"
}

エラーレスポンス:

提供されたIDの属性グループが存在しない場合:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Attribute group not found"
}
}

認証が失敗した場合:

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
"error": {
"message": "Authentication failed"
}
}

5. 属性グループの削除

システムから属性グループを永続的に削除します。

リクエスト:

  • Method: DELETE
  • Path: /attributes/:attributeId
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: 管理者ロールが必要

URLパラメータ:

ParameterType必須説明
attributeIdstring一意の属性グループ識別子

レスポンスボディ:

FieldType説明
レスポンスボディなし-削除エンドポイントは成功時にレスポンスボディを返しません

バリデーション:

  • スキーマバリデーション: attributeIdのパスパラメータ検証
  • ルートバリデーター:
    • 認証済みリクエストが必要(bearerトークン)
    • 管理者ロールが必要

リクエスト例:

curl -X DELETE {{host}}/attributes/69b013c9-cb20-4a7e-9c1f-59a55db1d949 \
-H "Authorization: Bearer <admin_token>" \
-H "x-nb-fingerprint: test-device-fingerprint"

成功レスポンス:

HTTP/1.1 204 No Content

エラーレスポンス:

提供されたIDの属性グループが存在しない場合:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Attribute group not found"
}
}

認証が失敗した場合:

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
"error": {
"message": "Authentication failed"
}
}

⚙️ 設定オプション

サービス設定

interface AttributesServiceConfiguration {
authSecrets: {
authEncSecret: string; // JWT encryption secret
authSignSecret: string; // JWT signing secret
};
identity?: {
typeIds?: {
admin: string; // Admin user type identifier
guest: string; // Guest user type identifier
regular: string; // Regular user type identifier
};
};
}

設定詳細

属性サービス設定は、セキュリティとユーザータイプ管理のために論理的なグループに整理されています。

🔐 セキュリティ設定

authSecrets - JWTトークンセキュリティシークレット

  • Type: { authEncSecret: string; authSignSecret: string }
  • Description: JWT暗号化と署名のためのシークレットキー(トークン検証に使用)
  • Required: はい(本番環境用)
  • 子プロパティ:
    • authEncSecret: JWTペイロード暗号化のためのシークレットキー
    • authSignSecret: JWT署名検証のためのシークレットキー

👥 ユーザータイプ設定

identity.typeIds - ユーザータイプ識別子設定

  • Type: { admin?: string; guest?: string; regular?: string }
  • Description: ロールベースアクセス制御のためのカスタムユーザータイプ識別子
  • Default: undefined(デフォルトのタイプ検証を使用)
  • 子プロパティ:
    • admin: 管理者ユーザータイプ識別子
      • Type: string
      • Description: 管理者ユーザーのカスタム識別子
      • 使用例: 管理操作のためのロールベースアクセス制御
      • : "admin", "administrator", "superuser"
    • guest: ゲストユーザータイプ識別子
      • Type: string
      • Description: ゲストユーザーのカスタム識別子
      • 使用例: 未認証または一時的なユーザーの限定アクセス
      • : "guest", "visitor", "anonymous"
    • regular: 通常ユーザータイプ識別子
      • Type: string
      • Description: 通常ユーザーのカスタム識別子
      • 使用例: 標準的なユーザーアクセス権限
      • : "user", "member", "customer"

設定例

const attributesConfig = {
authSecrets: {
authEncSecret: process.env.AUTH_ENC_SECRET || 'your-enc-secret',
authSignSecret: process.env.AUTH_SIGN_SECRET || 'your-sign-secret'
},
identity: {
typeIds: {
admin: 'administrator',
guest: 'visitor',
regular: 'member'
}
}
};

🚨 エラーハンドリング

すべての属性サービスエラーは、適切なHTTPステータスコードとJSON形式で返されます:

一般的なエラーコード

StatusError Message説明
400Validation Error無効なリクエストボディ形式または必須フィールドの欠落
400request body must have required property 'name'リクエストボディにnameフィールドがない
400request body must have required property 'items'リクエストボディにitems配列がない
400request body must NOT have fewer than 1 itemsitems配列が空(最小1項目が必要)
400request body must NOT have additional propertiesリクエストにサポートされていないフィールドが含まれている
400Failed to create attribute groupデータベース挿入操作が挿入されたIDを返さなかった
400Failed to update attribute group更新操作がデータを変更しない(変更が検出されない)
401Authentication failed認証トークンがないか無効
401token could not be verified認証トークンがないか無効
403User is not authorized to access this resourceユーザーに必要な権限がない(管理者アクセス)
404Attribute group not found要求された操作に対して属性グループが存在しない
500Failed to create attribute作成中のデータベース接続の問題または予期しない障害
500Failed to get attribute group取得中のデータベース接続の問題または予期しない障害
500Failed to find attributesリスト取得中のデータベース接続の問題、無効なフィルター構文、または予期しない障害
500Failed to update attribute更新中のデータベース接続の問題または予期しない障害
500Failed to delete attribute削除中のデータベース接続の問題または予期しない障害

エラーレスポンス形式

{
"error": {
"message": "Error message description",
"data": ["Additional error details"]
}
}

バリデーションエラーには追加の詳細が含まれます:

{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'name'",
"request body must have required property 'items'",
"request body must NOT have fewer than 1 items"
]
}
}

🔗 関連ドキュメント