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

🔧 Common ユーティリティ

Nodeblocks SDK は、一般的な操作のための汎用ユーティリティ関数を提供します。これらのユーティリティは、アプリケーション全体で頻繁に使う UUID 生成や型チェックなどの基本的なタスクを扱います。


🎯 概要

Common ユーティリティは、日常的なプログラミングタスクに不可欠なヘルパー関数を提供します。よくある操作に対する単純さと信頼性に焦点を当てています。

主な機能

  • UUID 生成: uuid パッケージによる信頼性の高い UUID v4 生成
  • 型チェック: オブジェクト、エラー、neverthrow Result の検証
  • 軽量: 最小限の依存関係(uuidramdaneverthrow

このモジュールは generateUUIDisObjectisErrorisResult の 4 関数をエクスポートします。


🆔 UUID 生成

generateUUID

一意識別子用の UUID v4 文字列を生成します。

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

const { generateUUID } = utils;

const id = generateUUID();
// 戻り値: "550e8400-e29b-41d4-a716-446655440000"

使用例

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

const { generateUUID } = utils;

// 一意 ID を生成
const userId = generateUUID();
const sessionId = generateUUID();
const requestId = generateUUID();

// オブジェクトで使用
const user = {
id: generateUUID(),
name: 'John Doe',
email: 'john@example.com'
};

// 複数の ID を生成
const ids = Array.from({ length: 5 }, () => generateUUID());

エンティティユーティリティとの統合

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

const { generateUUID, createBaseEntity } = utils;

// 追加の UUID フィールドを持つカスタムエンティティ作成
const createOrder = (orderData: OrderData) => {
const baseEntity = createBaseEntity(orderData);

return {
...baseEntity,
orderNumber: generateUUID(), // 追加 UUID フィールド
trackingId: generateUUID() // 別の UUID フィールド
};
};

注記: createBaseEntity はエンティティの id を内部で自動生成します(これも UUID v4 です)。基本エンティティ以外に一意フィールドが必要な場合は generateUUID を使用してください。


🔍 型チェック

isObject

値がオブジェクト型かどうかを確認します(関数を含む)。

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

const { isObject, isError } = utils;

// オブジェクトチェック
isObject({}); // true
isObject([]); // true
isObject(() => {}); // true
isObject(null); // false
isObject(undefined); // false
isObject('string'); // false
isObject(123); // false
isObject(true); // false

注記: isObject は TypeScript の型述語ではなく、プレーンな boolean を返します。コンパイル時の絞り込みには、カスタム型ガードを作成してください(高度な使用方法を参照)。

isError

値が Error インスタンスかどうかを確認します。

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

const { isError } = utils;

// エラーチェック
isError(new Error('message')); // true
isError(new TypeError('type')); // true
isError(new ReferenceError()); // true
isError('error string'); // false
isError({}); // false
isError(null); // false
isError(undefined); // false

isResult

値が neverthrowOk または Err インスタンスかどうかを確認します。これは TypeScript の型ガードです。

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

const { isResult } = utils;

isResult(ok(42)); // true
isResult(err('failed')); // true
isResult({ ok: true }); // false
isResult(null); // false

パラメーター:

  • value: チェック対象の値

戻り値:

  • boolean: 値が Ok<T, E> または Err<T, E> のインスタンスなら true

使用方法: ハンドラー結果をログ記録またはサニタイズするときに内部で使用されます。.isOk() / .isErr() を呼ぶ前に値が Result かどうかで分岐するときに便利です。

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

const { isResult } = utils;

const handleValue = (value: unknown) => {
if (isResult(value)) {
return value.isOk() ? value.value : value.error;
}
return value;
};

使用例

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

const { isObject, isError } = utils;

// 関数パラメーターを検証
const processData = (data: unknown) => {
if (!isObject(data)) {
throw new Error('Data must be an object');
}

return Object.keys(data as Record<string, unknown>);
};

// 安全なオブジェクト操作
const safeMerge = (target: unknown, source: unknown) => {
if (!isObject(target) || !isObject(source)) {
return target;
}

return { ...target, ...source };
};

// 条件付き処理
const processValue = (value: unknown) => {
if (isObject(value)) {
// オブジェクトを処理
return JSON.stringify(value);
} else {
// プリミティブを処理
return String(value);
}
};

エラー処理の例

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

const { isError } = utils;

// isError を用いたエラー処理
const safeAsyncOperation = async () => {
try {
return await riskyOperation();
} catch (error) {
if (isError(error)) {
// Error インスタンスを処理
return { error: error.message };
} else {
// その他のスローされた値を処理
return { error: 'Unknown error occurred' };
}
}
};

// エラー処理の型ガード
const handleResult = (result: unknown) => {
if (isError(result)) {
console.error('Operation failed:', result.message);
return false;
}

return result;
};

🔧 高度な使用方法

以下の例は SDK ユーティリティを基にした説明用のパターンであり、追加の SDK エクスポートではありません。

カスタム型ガード

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

const { isObject, isError } = utils;

// カスタム型ガードを作成
const isUserObject = (value: unknown): value is User => {
return isObject(value) &&
'id' in value &&
'name' in value &&
'email' in value;
};

const isProductObject = (value: unknown): value is Product => {
return isObject(value) &&
'id' in value &&
'name' in value &&
'price' in value;
};

// 使用方法
const validateUser = (data: unknown) => {
if (!isUserObject(data)) {
throw new Error('Invalid user data');
}

// TypeScript は data が User 型だと認識する
return data.name;
};

// エラー型ガード
const isApiError = (error: unknown): error is ApiError => {
return isError(error) &&
'statusCode' in error &&
'message' in error;
};

const isValidationError = (error: unknown): error is ValidationError => {
return isError(error) &&
'field' in error &&
'value' in error;
};

// エラー型ガードの使用
const handleApiResponse = (result: unknown) => {
if (isApiError(result)) {
// TypeScript は result が ApiError だと認識する
console.error(`API Error ${result.statusCode}: ${result.message}`);
} else if (isValidationError(result)) {
// TypeScript は result が ValidationError だと認識する
console.error(`Validation Error in ${result.field}: ${result.value}`);
} else {
console.log('Success:', result);
}
};

UUID ユーティリティ(パターン例)

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

const { generateUUID } = utils;

// UUID 検証
const isValidUUID = (uuid: string): boolean => {
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
return uuidRegex.test(uuid);
};

// 接頭辞付き UUID を生成
const generatePrefixedUUID = (prefix: string): string => {
return `${prefix}-${generateUUID()}`;
};

// 短い UUID を生成(先頭 8 文字)
const generateShortUUID = (): string => {
return generateUUID().split('-')[0];
};

// 使用方法
const orderId = generatePrefixedUUID('order'); // "order-550e8400-e29b-41d4-a716-446655440000"
const shortId = generateShortUUID(); // "550e8400"

オブジェクトユーティリティ(パターン例)

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

const { isObject, isError } = utils;

// 深いオブジェクト検証
const isDeepObject = (value: unknown): boolean => {
if (!isObject(value)) return false;

// すべての値がオブジェクトまたはプリミティブか確認
return Object.values(value).every(val =>
isObject(val) || typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean'
);
};

// 安全なオブジェクトアクセス
const safeGet = (obj: unknown, path: string): unknown => {
if (!isObject(obj)) return undefined;

return path.split('.').reduce((current, key) => {
return isObject(current) ? current[key] : undefined;
}, obj);
};

// 使用方法
const data = { user: { profile: { name: 'John' } } };
const userName = safeGet(data, 'user.profile.name'); // "John"
const invalid = safeGet(data, 'user.profile.age'); // undefined

エラー処理ユーティリティ(パターン例)

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

const { isError } = utils;

// エラー処理ユーティリティ
const createErrorResult = (error: unknown): ErrorResult => {
if (isError(error)) {
return {
success: false,
error: error.message,
type: error.name
};
}

return {
success: false,
error: String(error),
type: 'UnknownError'
};
};

const logError = (error: unknown): void => {
if (isError(error)) {
console.error(`[${error.name}] ${error.message}`);
if (error.stack) {
console.error(error.stack);
}
} else {
console.error('Unknown error:', error);
}
};

📊 パフォーマンスに関する考慮事項

UUID 生成

  • 標準の uuid v4 実装を使用します。
  • 一般的なアプリケーションワークロードでは衝突の可能性が極めて低くなります。

型チェック

  • isObject: 軽量な typeof チェック
  • isError: Ramda の is(Error)instanceof チェック)
  • isResult: instanceof Ok / instanceof Err チェック
  • nullundefined、配列、関数、Error サブクラスなどのエッジケースを扱います。

📐️ ベストプラクティス

1. 一貫した UUID 使用

// ✅ 良い例: すべての一意識別子に generateUUID を使用
const userId = generateUUID();
const orderId = generateUUID();
const sessionId = generateUUID();

// ❌ 避ける: 異なる ID 生成方法を混在させる
const userId = generateUUID();
const orderId = Date.now().toString(); // 一貫性がない

2. isObject による実行時検証

// ✅ 良い例: 実行時チェックに isObject を使い、必要に応じて手動で絞り込む
const processData = (data: unknown) => {
if (!isObject(data)) {
throw new Error('Expected object');
}
return Object.keys(data as Record<string, unknown>);
};

// ✅ より良い例: コンパイル時の絞り込みが必要ならカスタム型ガードを使う
const isRecord = (value: unknown): value is Record<string, unknown> =>
isObject(value) && !Array.isArray(value);

// ❌ 避ける: 検証なしの直接的な型アサーション
const processData = (data: unknown) => {
const obj = data as object; // 安全ではない
return Object.keys(obj);
};

3. エラー処理

// ✅ 良い例: 型チェックを伴う適切なエラー処理
const safeProcess = (data: unknown) => {
try {
if (!isObject(data)) {
return { error: 'Invalid data type' };
}
return { success: true, data };
} catch (error) {
if (isError(error)) {
// Error インスタンスを特別に処理
return { error: error.message, type: error.name };
} else {
// その他のスローされた値を処理
return { error: String(error), type: 'UnknownError' };
}
}
};

// ✅ 良い例: 型安全なエラー処理
const handleAsyncOperation = async (): Promise<Result> => {
try {
const result = await riskyAsyncOperation();
return { success: true, data: result };
} catch (error) {
if (isError(error)) {
return { success: false, error: error.message };
}
return { success: false, error: 'Unknown error' };
}
};

🔗 関連項目