File size: 4,405 Bytes
68f7925
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/**
 * 文字列キーから余分な記号を除去する汎用関数
 * @param key - 正規化する文字列
 * @param options - 正規化オプション
 * @returns 正規化された文字列
 */
export function normalizeKey(
  key: string,
  options: {
    removeSymbols?: boolean;
    unicodeNormalize?: boolean | 'NFC' | 'NFD' | 'NFKC' | 'NFKD';
    trim?: boolean;
  } = {},
): string {
  if (!key || typeof key !== 'string') return key;

  const { removeSymbols = true, unicodeNormalize = false, trim = true } = options;

  let result = key;

  // 記号除去
  if (removeSymbols) {
    result = result
      .replace(/^["']?\[['"]?/, '') // 先頭の"[' や [' や ["などを削除
      .replace(/['"]?\]?["']?$/, '') // 末尾の'] や "]や '"などを削除
      .replace(/^['"]/, '') // 先頭の' または "を削除
      .replace(/['"]$/, ''); // 末尾の' または "を削除
  }

  // 空白除去
  if (trim) {
    result = result.trim();
  }

  // Unicode正規化
  if (unicodeNormalize) {
    const normalizationForm = typeof unicodeNormalize === 'string' ? unicodeNormalize : 'NFKC';
    result = result.normalize(normalizationForm);
  }

  return result;
}

/**
 * オブジェクトのキーを正規化する汎用関数
 * @param data - 正規化対象のデータ
 * @param keyNormalizer - キー正規化関数(デフォルト: normalizeKey)
 * @returns キーが正規化されたデータ
 */
export function normalizeObjectKeys(data: unknown, keyNormalizer: (key: string) => string = normalizeKey): unknown {
  if (!data || typeof data !== 'object') {
    return data;
  }

  // 配列の場合は各要素を再帰的に処理
  if (Array.isArray(data)) {
    return data.map((item) => normalizeObjectKeys(item, keyNormalizer));
  }

  // オブジェクトの場合はキーを正規化
  const normalized: Record<string, unknown> = {};
  for (const [key, value] of Object.entries(data)) {
    const cleanKey = keyNormalizer(key);
    // 値も再帰的に処理
    normalized[cleanKey] = normalizeObjectKeys(value, keyNormalizer);
  }

  return normalized;
}

/**
 * @deprecated normalizeObjectKeysを使用してください
 */
export function normalizeStrategyKeys(strategyData: unknown): unknown {
  return normalizeObjectKeys(strategyData);
}

/**
 * 配列の特定インデックスの要素を正規化する汎用関数
 * @param array - 対象の配列
 * @param indices - 正規化するインデックスの配列
 * @param normalizer - 正規化関数(デフォルト: normalizeObjectKeys)
 * @returns 指定インデックスが正規化された配列
 */
export function normalizeArrayAtIndices(
  array: unknown[],
  indices: number[],
  normalizer: (data: unknown) => unknown = normalizeObjectKeys,
): unknown[] {
  if (!Array.isArray(array)) {
    return array as unknown[];
  }

  const normalized = [...array];
  indices.forEach((index) => {
    if (index >= 0 && index < array.length) {
      normalized[index] = normalizer(array[index]);
    }
  });

  return normalized;
}

/**
 * @deprecated normalizeArrayAtIndicesを使用してください
 */
export function normalizeThemeByMomentResponse(response: unknown): unknown {
  if (!Array.isArray(response) || response.length < 3) {
    return response;
  }
  // response[2]がstrategy_x_moment
  return normalizeArrayAtIndices(response, [2]);
}

/**
 * 正規化されたキーでオブジェクトから値を検索する汎用関数
 * @param data - 検索対象のオブジェクト
 * @param originalKey - 検索するキー
 * @param normalizeOptions - 正規化オプション
 * @returns マッチした値、見つからない場合はundefined
 */
export function findWithNormalizedKey<T>(
  data: Record<string, T> | undefined,
  originalKey: string,
  normalizeOptions: Parameters<typeof normalizeKey>[1] = {
    removeSymbols: true,
    unicodeNormalize: 'NFKC',
    trim: true,
  },
): T | undefined {
  if (!data) {
    return undefined;
  }

  // まず元のキーで検索
  if (data[originalKey]) {
    return data[originalKey];
  }

  // 正規化したキーで検索
  const normalizedKey = normalizeKey(originalKey, normalizeOptions);

  for (const [key, value] of Object.entries(data)) {
    const normalizedDataKey = normalizeKey(key, normalizeOptions);
    if (normalizedDataKey === normalizedKey) {
      return value;
    }
  }

  return undefined;
}