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

🆔 エンティティユーティリティ

Nodeblocks SDKは、自動フィールド生成を使用したデータベースエンティティの作成と管理のための必須ユーティリティを提供します。これらのユーティリティは、自動タイムスタンプと一意識別子を使用してアプリケーション全体で一貫したエンティティ構造を保証します。


🎯 概要

エンティティユーティリティは、自動フィールド生成を使用したデータベースエンティティの作成と更新のための標準化された関数を提供します。エンティティ構造の一貫性を保証し、ボイラープレートコードを削減します。

主要機能

  • 自動ID生成: エンティティ識別子用のUUID v4生成
  • タイムスタンプ管理: 自動createdAtupdatedAtフィールド生成
  • 一貫した構造: 標準化されたエンティティ作成と更新パターン
  • 型安全性: 適切な型付けによる完全なTypeScriptサポート

🆔 エンティティ作成

createBaseEntity

自動フィールド生成を使用して新しいエンティティを作成します。

import { utils } from '@nodeblocks/backend-sdk';

const { createBaseEntity } = utils;

const userData = {
email: 'user@example.com',
name: 'John Doe',
role: 'user'
};

const user = createBaseEntity(userData);

生成されるフィールド:

  • id: UUID v4文字列
  • createdAt: ISOタイムスタンプ文字列
  • updatedAt: ISOタイムスタンプ文字列

結果:

{
email: 'user@example.com',
name: 'John Doe',
role: 'user',
id: '550e8400-e29b-41d4-a716-446655440000',
createdAt: '2024-01-15T10:30:00.000Z',
updatedAt: '2024-01-15T10:30:00.000Z'
}

使用例

import { utils } from '@nodeblocks/backend-sdk';

const { createBaseEntity } = utils;

// ユーザーエンティティの作成
const newUser = createBaseEntity({
email: 'alice@example.com',
name: 'Alice Smith',
role: 'admin',
department: 'Engineering'
});

// 商品エンティティの作成
const newProduct = createBaseEntity({
name: 'ノートパソコン',
price: 1200.00,
category: 'electronics',
inStock: true
});

// 注文エンティティの作成
const newOrder = createBaseEntity({
userId: 'user-123',
items: [{ productId: 'prod-456', quantity: 2 }],
total: 2400.00,
status: 'pending'
});

🔄 エンティティ更新

updateBaseEntity

自動updatedAtタイムスタンプでエンティティを更新します。

import { utils } from '@nodeblocks/backend-sdk';

const { updateBaseEntity } = utils;

const existingUser = {
id: '550e8400-e29b-41d4-a716-446655440000',
email: 'user@example.com',
name: 'John Doe',
role: 'user',
createdAt: '2024-01-15T10:30:00.000Z',
updatedAt: '2024-01-15T10:30:00.000Z'
};

const updates = {
name: 'John Smith',
role: 'admin'
};

const updatedUser = updateBaseEntity(existingUser, updates);

結果:

{
id: '550e8400-e29b-41d4-a716-446655440000',
email: 'user@example.com',
name: 'John Smith', // 更新済み
role: 'admin', // 更新済み
createdAt: '2024-01-15T10:30:00.000Z',
updatedAt: '2024-01-15T11:45:00.000Z' // 自動更新
}

部分更新の例

import { utils } from '@nodeblocks/backend-sdk';

const { updateBaseEntity } = utils;

// ユーザープロフィールの更新
const updateUserProfile = (user: User, profileData: Partial<User>) => {
return updateBaseEntity(user, profileData);
};

// 商品価格の更新
const updateProductPrice = (product: Product, newPrice: number) => {
return updateBaseEntity(product, { price: newPrice });
};

// 注文ステータスの更新
const updateOrderStatus = (order: Order, status: string) => {
return updateBaseEntity(order, { status });
};

🔧 ハンドラーでの使用

作成ハンドラー

import { ok, err } from 'neverthrow';
import { utils, primitives } from '@nodeblocks/backend-sdk';

const { createBaseEntity } = utils;
const { NodeblocksError } = primitives;

export const createUserHandler = async (payload: RouteHandlerPayload) => {
const { params, context } = payload;

if (!params.requestBody || Object.keys(params.requestBody).length === 0) {
return err(new NodeblocksError(400, 'リクエストボディが必要です'));
}

// ベースエンティティを作成(自動ID、タイムスタンプ付き)
const userEntity = createBaseEntity(params.requestBody);

try {
const result = await context.db.users.insertOne(userEntity);

if (!result.insertedId) {
return err(new NodeblocksError(500, 'ユーザーの作成に失敗しました'));
}

return ok(mergeData(payload, { userId: userEntity.id, user: userEntity }));
} catch (error) {
return err(new NodeblocksError(500, 'データベースエラー'));
}
};

更新ハンドラー

import { ok, err } from 'neverthrow';
import { utils, primitives } from '@nodeblocks/backend-sdk';

const { updateBaseEntity } = utils;
const { NodeblocksError } = primitives;

export const updateUserHandler = async (payload: RouteHandlerPayload) => {
const { params, context } = payload;
const userId = params.requestParams?.userId;

if (!userId) {
return err(new NodeblocksError(400, 'ユーザーIDが必要です'));
}

try {
// 既存ユーザーを取得
const existingUser = await context.db.users.findOne({ id: userId });

if (!existingUser) {
return err(new NodeblocksError(404, 'ユーザーが見つかりません'));
}

// ベースエンティティを更新(自動updatedAt付き)
const updatedUser = updateBaseEntity(existingUser, params.requestBody);

const result = await context.db.users.replaceOne(
{ id: userId },
updatedUser
);

if (!result.modifiedCount) {
return err(new NodeblocksError(500, 'ユーザーの更新に失敗しました'));
}

return ok(mergeData(payload, { user: updatedUser }));
} catch (error) {
return err(new NodeblocksError(500, 'データベースエラー'));
}
};

🎯 高度な使用パターン

カスタムID生成

import { utils } from '@nodeblocks/backend-sdk';

const { generateUUID } = utils;

// カスタムIDプレフィックス付きエンティティ
const createEntityWithPrefix = (data: any, prefix: string) => {
const entity = {
...data,
id: `${prefix}-${generateUUID()}`,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};

return entity;
};

// 使用例
const user = createEntityWithPrefix(userData, 'user');
const product = createEntityWithPrefix(productData, 'prod');
const order = createEntityWithPrefix(orderData, 'order');

条件付き更新

import { utils } from '@nodeblocks/backend-sdk';

const { updateBaseEntity } = utils;

const conditionalUpdate = (entity: any, updates: any, condition: boolean) => {
if (!condition) {
return entity; // 変更なし
}

return updateBaseEntity(entity, updates);
};

// 使用例
const updatedUser = conditionalUpdate(
user,
{ lastLoginAt: new Date().toISOString() },
user.status === 'active'
);

バッチエンティティ作成

import { utils } from '@nodeblocks/backend-sdk';

const { createBaseEntity } = utils;

const createMultipleEntities = (dataArray: any[]) => {
return dataArray.map(data => createBaseEntity(data));
};

// 使用例
const usersData = [
{ email: 'user1@example.com', name: 'User 1' },
{ email: 'user2@example.com', name: 'User 2' },
{ email: 'user3@example.com', name: 'User 3' }
];

const newUsers = createMultipleEntities(usersData);

🎯 ベストプラクティス

1. 一貫したエンティティ作成

// 良い - createBaseEntityを使用
const user = createBaseEntity({
email: 'user@example.com',
name: 'John Doe'
});

// 悪い - 手動フィールド生成
const user = {
id: Math.random().toString(), // 一意性が保証されない
email: 'user@example.com',
name: 'John Doe',
createdAt: Date.now() // 不一貫な形式
};

2. 適切な更新パターン

// 良い - updateBaseEntityを使用
const updatedUser = updateBaseEntity(existingUser, changes);

// 悪い - 手動updatedAt設定
const updatedUser = {
...existingUser,
...changes,
updatedAt: new Date().toISOString() // 忘れやすく、エラーが発生しやすい
};

3. 型安全性の維持

// 良い - 型定義を使用
interface User {
id: string;
email: string;
name: string;
role: string;
createdAt: string;
updatedAt: string;
}

const createUser = (userData: Omit<User, 'id' | 'createdAt' | 'updatedAt'>): User => {
return createBaseEntity(userData);
};

// 悪い - any型の使用
const createUser = (userData: any): any => {
return createBaseEntity(userData);
};

➡️ 次へ

共通ユーティリティについて学習して、UUID生成や型チェックなどの汎用ヘルパー関数を理解しましょう!