ansuko 2.0.0 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,79 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ For changes prior to v2.0.0, see the [git history](https://github.com/sera4am/ansuko/commits/main).
9
+
10
+ ## [Unreleased]
11
+
12
+ ## [2.0.3] - 2026-05-08
13
+
14
+ ## [2.0.2] - 2026-05-08
15
+
16
+ ## [2.0.1] - 2026-05-08
17
+
18
+ ### Added
19
+ - Added `_.isValidEmail` for strict email format validation in core utilities.
20
+ - Added documentation and examples for `_.isValidEmail` in README files.
21
+ - Added GitHub Actions workflow (`test.yml`) to run the test suite on every push and pull request.
22
+ - Added CI test status badge and npm version badge to all README files (EN/JA/ZH).
23
+
24
+ ## [2.0.1] - 2026-05-08
25
+
26
+ ### Added
27
+ - `CHANGELOG.md` based on the [Keep a Changelog](https://keepachangelog.com/) format.
28
+ - `scripts/promote-changelog.sh` and an `npm version` lifecycle hook that
29
+ promotes the `[Unreleased]` section to a versioned heading on every
30
+ release. CHANGELOG updates are bundled into the same commit as the
31
+ version bump automatically.
32
+ - `CLAUDE.md` documenting the release flow, plugin architecture, and
33
+ conventions for future contributors (and for Claude Code sessions).
34
+
35
+ ## [2.0.0] - 2026-05-08
36
+
37
+ ### Removed (BREAKING)
38
+ - `_.extend(plugin)` API. Plugins are now loaded via side-effect imports
39
+ (`import "ansuko/plugins/ja"`).
40
+
41
+ ### Changed (BREAKING)
42
+ - Plugin loading: side-effect imports + TypeScript `declare module` merging.
43
+ IDE autocompletion now works directly on `_` for all plugin methods —
44
+ the previous `_.extend(plugin)` returned a new type but left the original
45
+ `_` reference's type unchanged, so plugin methods never appeared in
46
+ suggestions.
47
+ - `AnsukoType` now extends `Omit<LoDashStatic, "isEmpty" | "toNumber" |
48
+ "castArray" | "extend">` instead of enumerating ~330 lodash methods by
49
+ hand. lodash generics are preserved and `@types/lodash` updates flow
50
+ through automatically.
51
+
52
+ ### Added
53
+ - `_.__plugins: Set<string>` registry. Each plugin registers itself once
54
+ and skips re-registration when imported from multiple modules.
55
+
56
+ ### Migration
57
+
58
+ ```ts
59
+ // v1
60
+ import _ from "ansuko"
61
+ import jaPlugin from "ansuko/plugins/ja"
62
+ const ansuko = _.extend(jaPlugin)
63
+ ansuko.kanaToFull("ガ")
64
+
65
+ // v2
66
+ import _ from "ansuko"
67
+ import "ansuko/plugins/ja"
68
+ _.kanaToFull("ガ")
69
+ ```
70
+
71
+ If you previously chained `_.extend(a).extend(b)`, replace it with two
72
+ side-effect imports.
73
+
74
+ [Unreleased]: https://github.com/sera4am/ansuko/compare/v2.0.3...HEAD
75
+ [2.0.3]: https://github.com/sera4am/ansuko/releases/tag/v2.0.3
76
+ [2.0.2]: https://github.com/sera4am/ansuko/releases/tag/v2.0.2
77
+ [2.0.1]: https://github.com/sera4am/ansuko/releases/tag/v2.0.1
78
+ [2.0.1]: https://github.com/sera4am/ansuko/releases/tag/v2.0.1
79
+ [2.0.0]: https://github.com/sera4am/ansuko/releases/tag/v2.0.0
package/README.ja.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # ansuko
2
2
 
3
+ [![Tests](https://github.com/sera4am/ansuko/actions/workflows/test.yml/badge.svg)](https://github.com/sera4am/ansuko/actions/workflows/test.yml)
4
+ [![npm version](https://img.shields.io/npm/v/ansuko)](https://www.npmjs.com/package/ansuko)
3
5
 
4
6
  lodashを拡張した、実用的で直感的な動作を提供するモダンなJavaScript/TypeScriptユーティリティライブラリ。
5
7
 
@@ -122,6 +124,10 @@ const value = await _.valueOr(
122
124
  // 安全なJSONパース
123
125
  const data = _.parseJSON('{ "a": 1, /* comment */ }') // JSON5対応!
124
126
 
127
+ // メールアドレス検証
128
+ _.isValidEmail('user@example.com') // true
129
+ _.isValidEmail(' user@example.com ') // false
130
+
125
131
  // データベース更新用のオブジェクト変更追跡
126
132
  const diff = _.changes(
127
133
  original,
@@ -249,6 +255,7 @@ v1 で `_.extend(a).extend(b)` のように chain していた場合は、2回
249
255
  - **`toBool`** - スマートな真偽値変換("yes"/"no"/"true"/"false"/数値)、未検出時の動作を設定可能
250
256
  - **`boolIf`** - フォールバック付き安全な真偽値変換
251
257
  - **`isValidStr`** - 非空文字列検証
258
+ - **`isValidEmail`** - メールアドレス形式の検証(前後に空白がある値は無効)
252
259
 
253
260
  ### JSON処理
254
261
 
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # ansuko
2
2
 
3
+ [![Tests](https://github.com/sera4am/ansuko/actions/workflows/test.yml/badge.svg)](https://github.com/sera4am/ansuko/actions/workflows/test.yml)
4
+ [![npm version](https://img.shields.io/npm/v/ansuko)](https://www.npmjs.com/package/ansuko)
3
5
 
4
6
  A modern JavaScript/TypeScript utility library that extends lodash with practical, intuitive behaviors.
5
7
 
@@ -111,6 +113,7 @@ const value = _.equalsOr(a, b, defaultValue) // null == undefined
111
113
  - **`toBool`** - Smart boolean conversion ("yes"/"no"/"true"/"false"/numbers) with configurable undetected handling
112
114
  - **`boolIf`** - Safe boolean conversion with fallback
113
115
  - **`isValidStr`** - Non-empty string validation
116
+ - **`isValidEmail`** - Email format validation (strict: values with surrounding spaces are invalid)
114
117
 
115
118
  ### JSON Processing
116
119
 
@@ -201,6 +204,10 @@ const value = await _.valueOr(
201
204
  // Safe JSON parsing
202
205
  const data = _.parseJSON('{ "a": 1, /* comment */ }') // Works with JSON5!
203
206
 
207
+ // Email validation
208
+ _.isValidEmail('user@example.com') // true
209
+ _.isValidEmail(' user@example.com ') // false
210
+
204
211
  // Track object changes for database updates
205
212
  const diff = _.changes(
206
213
  original,
package/README.zh.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # ansuko
2
2
 
3
+ [![Tests](https://github.com/sera4am/ansuko/actions/workflows/test.yml/badge.svg)](https://github.com/sera4am/ansuko/actions/workflows/test.yml)
4
+ [![npm version](https://img.shields.io/npm/v/ansuko)](https://www.npmjs.com/package/ansuko)
5
+
3
6
  在lodash基础上扩展、提供实用且直观易懂的现代JavaScript/TypeScript工具库。
4
7
 
5
8
  [English](./README.md) | [日本語](./README.ja.md) | [简体中文](./README.zh.md)
@@ -108,6 +111,7 @@ const value = _.equalsOr(a, b, defaultValue) // null == undefined
108
111
  - **`toBool`** - 智能布尔值转换(支持 "yes"/"no"/"true"/"false"/数字),可配置未检测到时的行为检测处理
109
112
  - **`boolIf`** - 带有回退机制的安全布尔值转换
110
113
  - **`isValidStr`** - 非空字符串验证
114
+ - **`isValidEmail`** - 邮箱格式校验(严格模式:前后包含空格视为无效)
111
115
 
112
116
  ### JSON 处理
113
117
 
@@ -196,6 +200,10 @@ const value = await _.valueOr(
196
200
  // 安全的 JSON 解析
197
201
  const data = _.parseJSON('{ "a": 1, /* 注释 */ }') // 支持 JSON5!
198
202
 
203
+ // 邮箱格式校验
204
+ _.isValidEmail('user@example.com') // true
205
+ _.isValidEmail(' user@example.com ') // false
206
+
199
207
  // 跟踪对象更改以进行数据库更新
200
208
  const diff = _.changes(
201
209
  original,
package/dist/index.d.ts CHANGED
@@ -209,6 +209,19 @@ declare const swallowMap: <T, U>(array: T[] | undefined | null, fn: (item: T, in
209
209
  * @category Array Utilities
210
210
  */
211
211
  declare const arrayDepth: (ary: unknown) => number;
212
+ /**
213
+ * Validates whether the input is a syntactically valid email address.
214
+ * - Returns false for null/undefined/empty values.
215
+ * - Values containing leading/trailing spaces are treated as invalid.
216
+ * - Case-insensitive for the domain/local-part check.
217
+ * @param email - Value to validate
218
+ * @returns true if the input is a valid email format
219
+ * @example isValidEmail('user@example.com') // true
220
+ * @example isValidEmail(' user@example.com ') // false
221
+ * @example isValidEmail('not-an-email') // false
222
+ * @category Type Guards
223
+ */
224
+ declare const isValidEmail: (email: unknown) => boolean;
212
225
  export type ChangesOptions = {
213
226
  keyExcludes?: boolean;
214
227
  };
@@ -238,6 +251,7 @@ export interface AnsukoType extends Omit<LoDashStatic, AnsukoOverriddenKeys> {
238
251
  swallowMap: typeof swallowMap;
239
252
  arrayDepth: typeof arrayDepth;
240
253
  strWrap: typeof strWrap;
254
+ isValidEmail: typeof isValidEmail;
241
255
  isEmpty: typeof isEmpty;
242
256
  toNumber: typeof toNumber;
243
257
  castArray: typeof castArray;
@@ -254,4 +268,4 @@ export interface AnsukoType extends Omit<LoDashStatic, AnsukoOverriddenKeys> {
254
268
  }
255
269
  declare const _: AnsukoType;
256
270
  export default _;
257
- export { isEmpty, toNumber, boolIf, isValidStr, valueOr, equalsOr, waited, parseJSON, jsonStringify, castArray, changes, strWrap, swallow, swallowMap, arrayDepth, };
271
+ export { isEmpty, toNumber, boolIf, isValidStr, valueOr, equalsOr, waited, parseJSON, jsonStringify, castArray, changes, strWrap, swallow, swallowMap, arrayDepth, isValidEmail, };
package/dist/index.js CHANGED
@@ -564,6 +564,29 @@ const arrayDepth = (ary) => {
564
564
  }
565
565
  return 1 + Math.min(...ary.map(arrayDepth));
566
566
  };
567
+ /**
568
+ * Validates whether the input is a syntactically valid email address.
569
+ * - Returns false for null/undefined/empty values.
570
+ * - Values containing leading/trailing spaces are treated as invalid.
571
+ * - Case-insensitive for the domain/local-part check.
572
+ * @param email - Value to validate
573
+ * @returns true if the input is a valid email format
574
+ * @example isValidEmail('user@example.com') // true
575
+ * @example isValidEmail(' user@example.com ') // false
576
+ * @example isValidEmail('not-an-email') // false
577
+ * @category Type Guards
578
+ */
579
+ const isValidEmail = (email) => {
580
+ if (isEmpty(email)) {
581
+ return false;
582
+ }
583
+ const str = String(email).toLowerCase();
584
+ if (isEmpty(str)) {
585
+ return false;
586
+ }
587
+ const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
588
+ return re.test(str);
589
+ };
567
590
  // 変数名を _ にすることで、VS Code の auto import 候補が `_` として表示される
568
591
  const _ = {
569
592
  ...lodash,
@@ -588,8 +611,9 @@ const _ = {
588
611
  swallow,
589
612
  swallowMap,
590
613
  arrayDepth,
614
+ isValidEmail,
591
615
  __plugins: new Set(),
592
616
  };
593
617
  export default _;
594
618
  // 個別エクスポートはそのまま
595
- export { isEmpty, toNumber, boolIf, isValidStr, valueOr, equalsOr, waited, parseJSON, jsonStringify, castArray, changes, strWrap, swallow, swallowMap, arrayDepth, };
619
+ export { isEmpty, toNumber, boolIf, isValidStr, valueOr, equalsOr, waited, parseJSON, jsonStringify, castArray, changes, strWrap, swallow, swallowMap, arrayDepth, isValidEmail, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ansuko",
3
- "version": "2.0.0",
3
+ "version": "2.0.3",
4
4
  "description": "A modern JavaScript/TypeScript utility library that extends lodash with practical, intuitive behaviors. Fixes lodash quirks, adds Promise support, Japanese text processing, and GeoJSON utilities.",
5
5
  "keywords": [
6
6
  "lodash",
@@ -34,6 +34,7 @@
34
34
  "files": [
35
35
  "dist",
36
36
  "README.md",
37
+ "CHANGELOG.md",
37
38
  "LICENSE"
38
39
  ],
39
40
  "exports": {
@@ -48,7 +49,8 @@
48
49
  "test": "npm run build && vitest run",
49
50
  "test:watch": "vitest",
50
51
  "typecheck": "tsc --noEmit",
51
- "lint": "eslint src --ext .ts,.tsx"
52
+ "lint": "eslint src --ext .ts,.tsx",
53
+ "version": "bash ./scripts/promote-changelog.sh && git add CHANGELOG.md"
52
54
  },
53
55
  "dependencies": {
54
56
  "@turf/turf": "^7.3.1",