mock-data-mcp 1.0.0

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.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +164 -0
  3. package/data/mock.db +0 -0
  4. package/dist/db.d.ts +17 -0
  5. package/dist/db.d.ts.map +1 -0
  6. package/dist/db.js +127 -0
  7. package/dist/db.js.map +1 -0
  8. package/dist/generators/address.d.ts +14 -0
  9. package/dist/generators/address.d.ts.map +1 -0
  10. package/dist/generators/address.js +44 -0
  11. package/dist/generators/address.js.map +1 -0
  12. package/dist/generators/gemini.d.ts +7 -0
  13. package/dist/generators/gemini.d.ts.map +1 -0
  14. package/dist/generators/gemini.js +121 -0
  15. package/dist/generators/gemini.js.map +1 -0
  16. package/dist/generators/identity.d.ts +3 -0
  17. package/dist/generators/identity.d.ts.map +1 -0
  18. package/dist/generators/identity.js +56 -0
  19. package/dist/generators/identity.js.map +1 -0
  20. package/dist/generators/index.d.ts +7 -0
  21. package/dist/generators/index.d.ts.map +1 -0
  22. package/dist/generators/index.js +160 -0
  23. package/dist/generators/index.js.map +1 -0
  24. package/dist/generators/name.d.ts +4 -0
  25. package/dist/generators/name.d.ts.map +1 -0
  26. package/dist/generators/name.js +30 -0
  27. package/dist/generators/name.js.map +1 -0
  28. package/dist/generators/phone.d.ts +3 -0
  29. package/dist/generators/phone.d.ts.map +1 -0
  30. package/dist/generators/phone.js +25 -0
  31. package/dist/generators/phone.js.map +1 -0
  32. package/dist/index.d.ts +3 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +242 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/types.d.ts +36 -0
  37. package/dist/types.d.ts.map +1 -0
  38. package/dist/types.js +3 -0
  39. package/dist/types.js.map +1 -0
  40. package/package.json +66 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 mock-data-mcp contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # mock-data-mcp
2
+
3
+ > Ultra-fast mock data generator MCP server — Taiwan locale, schema-driven, SQLite cache, Gemini AI fallback.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/mock-data-mcp)](https://www.npmjs.com/package/mock-data-mcp)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
7
+
8
+ ## Features
9
+
10
+ - **Blazing fast**: 1000 records in ~9ms (batch pre-load optimization)
11
+ - **Taiwan locale**: name, phone, ID number (with checksum), address, county/district
12
+ - **Schema-driven**: define fields as JSON, get back an array of objects
13
+ - **14 field types**: name, phone, id_number, county, district, address, email, company, job_title, boolean, uuid, number, date, string, ai
14
+ - **Gemini AI fallback**: use `ai` type for complex data (product categories, etc.)
15
+ - **SQLite seed data**: 346 regions, 4000 name combos, 250 streets, 400 companies, 36 job titles
16
+
17
+ ## Quick Start
18
+
19
+ ### Install & Run
20
+
21
+ ```bash
22
+ npx -y mock-data-mcp@latest
23
+ ```
24
+
25
+ ### MCP Client Configuration
26
+
27
+ Add to your `claude_desktop_config.json` (or equivalent):
28
+
29
+ ```json
30
+ {
31
+ "mcpServers": {
32
+ "mock-data": {
33
+ "command": "npx",
34
+ "args": ["-y", "mock-data-mcp@latest"],
35
+ "env": {
36
+ "GEMINI_API_KEY": "your-api-key-here"
37
+ }
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ Bun users (faster startup):
44
+ ```json
45
+ {
46
+ "command": "bunx",
47
+ "args": ["mock-data-mcp@latest"]
48
+ }
49
+ ```
50
+
51
+ ## Usage
52
+
53
+ ### `generate_mock_data`
54
+
55
+ Generate an array of fake records from a JSON schema.
56
+
57
+ **Input:**
58
+ ```json
59
+ {
60
+ "schema": {
61
+ "name": "name",
62
+ "phone": "phone",
63
+ "id_number": "id_number",
64
+ "county": "county",
65
+ "address": "address",
66
+ "age": { "type": "number", "min": 18, "max": 65 },
67
+ "salary": { "type": "number", "min": 30000, "max": 120000 },
68
+ "birth_date": { "type": "date", "min": "1960-01-01", "max": "2005-12-31" },
69
+ "active": "boolean",
70
+ "user_id": { "type": "string", "prefix": "USR_", "length": 8 },
71
+ "product_category": { "type": "ai", "prompt": "台灣常見電商商品分類" }
72
+ },
73
+ "count": 10
74
+ }
75
+ ```
76
+
77
+ **Output:**
78
+ ```json
79
+ [
80
+ {
81
+ "name": "王小明",
82
+ "phone": "0912345678",
83
+ "id_number": "A123456789",
84
+ "county": "台北市",
85
+ "address": "100 台北市中正區中山路12巷34號5樓",
86
+ "age": 35,
87
+ "salary": 72000,
88
+ "birth_date": "1990-05-15",
89
+ "active": true,
90
+ "user_id": "USR_xK9mP2nQ",
91
+ "product_category": "3C 電子產品"
92
+ }
93
+ ]
94
+ ```
95
+
96
+ ### Supported Field Types
97
+
98
+ | Type | Description | Parameters |
99
+ |------|-------------|------------|
100
+ | `name` | Taiwan full name (surname + given) | — |
101
+ | `phone` | Taiwan mobile (09XXXXXXXX) | — |
102
+ | `id_number` | Taiwan ID card number (with checksum) | — |
103
+ | `county` | County/city (22 Taiwan counties) | — |
104
+ | `district` | District/township | — |
105
+ | `address` | Full address (zip + county + district + street) | — |
106
+ | `email` | Email address | — |
107
+ | `company` | Company name | — |
108
+ | `job_title` | Job title | — |
109
+ | `boolean` | true/false | — |
110
+ | `uuid` | UUID v4 | — |
111
+ | `number` | Integer | `min`, `max` |
112
+ | `date` | YYYY-MM-DD | `min`, `max` (string) |
113
+ | `string` | Random alphanumeric | `length`, `prefix` |
114
+ | `ai` | Gemini AI-generated | `prompt` (required) |
115
+
116
+ ### `get_field_types`
117
+
118
+ Returns all supported field type descriptions.
119
+
120
+ ### `get_db_stats`
121
+
122
+ Returns SQLite database statistics (region count, name count, etc.).
123
+
124
+ ## Development
125
+
126
+ ```bash
127
+ # Install dependencies
128
+ bun install
129
+
130
+ # Seed SQLite database
131
+ bun run seed
132
+
133
+ # Run in dev mode
134
+ bun run dev
135
+
136
+ # Run tests
137
+ bun run test
138
+
139
+ # Benchmark
140
+ bun run bench
141
+
142
+ # Build for npm
143
+ bun run build
144
+ ```
145
+
146
+ ## Performance
147
+
148
+ | Records | Time | Per Record |
149
+ |---------|------|------------|
150
+ | 100 | ~5ms | 50μs |
151
+ | 1000 | ~9ms | 9μs |
152
+ | 10000 | ~90ms | 9μs |
153
+
154
+ Strategy: batch pre-load all SQLite data into memory, then use in-memory array random selection (no per-record DB queries).
155
+
156
+ ## Environment Variables
157
+
158
+ | Variable | Required | Description |
159
+ |----------|----------|-------------|
160
+ | `GEMINI_API_KEY` | No | Google Gemini API key for `ai` field type |
161
+
162
+ ## License
163
+
164
+ MIT
package/data/mock.db ADDED
Binary file
package/dist/db.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ interface PreparedStmt {
2
+ all(...params: unknown[]): unknown[];
3
+ get(...params: unknown[]): unknown;
4
+ run(...params: unknown[]): unknown;
5
+ }
6
+ interface WrappedDb {
7
+ exec(sql: string): void;
8
+ prepare(sql: string): PreparedStmt;
9
+ transaction<T extends (...args: unknown[]) => unknown>(fn: T): T & {
10
+ run: (...args: Parameters<T>) => void;
11
+ };
12
+ close(): void;
13
+ }
14
+ export declare function getDb(): WrappedDb;
15
+ export declare function closeDb(): void;
16
+ export {};
17
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAYA,UAAU,YAAY;IACpB,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;IACrC,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACnC,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;CACpC;AAED,UAAU,SAAS;IACjB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC;IACnC,WAAW,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG;QAAE,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;KAAE,CAAC;IAC7G,KAAK,IAAI,IAAI,CAAC;CACf;AAmED,wBAAgB,KAAK,IAAI,SAAS,CAcjC;AAyCD,wBAAgB,OAAO,IAAI,IAAI,CAK9B"}
package/dist/db.js ADDED
@@ -0,0 +1,127 @@
1
+ // src/db.ts — SQLite database layer (Bun/Node runtime auto-detect)
2
+ // Bun → bun:sqlite (zero native dependencies)
3
+ // Node → better-sqlite3 (npm published)
4
+ import { dirname, join } from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import { existsSync, mkdirSync } from 'fs';
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ const DATA_DIR = join(__dirname, '..', 'data');
9
+ const DB_PATH = join(DATA_DIR, 'mock.db');
10
+ let _db = null;
11
+ // ── Runtime detection ──
12
+ function isBun() {
13
+ return typeof globalThis.Bun !== 'undefined';
14
+ }
15
+ function createDb(dbPath) {
16
+ if (isBun()) {
17
+ return createBunDb(dbPath);
18
+ }
19
+ return createNodeDb(dbPath);
20
+ }
21
+ // ── Bun: bun:sqlite ──
22
+ function createBunDb(dbPath) {
23
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
24
+ const { Database } = require('bun:sqlite');
25
+ const raw = new Database(dbPath, { create: true });
26
+ return {
27
+ exec: (sql) => raw.exec(sql),
28
+ prepare: (sql) => {
29
+ const stmt = raw.prepare(sql);
30
+ return {
31
+ all: (...p) => stmt.all(...p),
32
+ get: (...p) => stmt.get(...p),
33
+ run: (...p) => stmt.run(...p),
34
+ };
35
+ },
36
+ transaction(fn) {
37
+ const tx = raw.transaction(fn);
38
+ const wrapped = (...args) => fn(...args);
39
+ wrapped.run = (...args) => { tx(...args); };
40
+ return wrapped;
41
+ },
42
+ close: () => raw.close(),
43
+ };
44
+ }
45
+ // ── Node.js: better-sqlite3 ──
46
+ function createNodeDb(dbPath) {
47
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
48
+ const BetterSqlite3 = require('better-sqlite3');
49
+ const raw = new BetterSqlite3(dbPath);
50
+ return {
51
+ exec: (sql) => raw.exec(sql),
52
+ prepare: (sql) => {
53
+ const stmt = raw.prepare(sql);
54
+ return {
55
+ all: (...p) => stmt.all(...p),
56
+ get: (...p) => stmt.get(...p),
57
+ run: (...p) => stmt.run(...p),
58
+ };
59
+ },
60
+ transaction(fn) {
61
+ const tx = raw.transaction(fn);
62
+ const wrapped = (...args) => fn(...args);
63
+ wrapped.run = (...args) => { tx(...args); };
64
+ return wrapped;
65
+ },
66
+ close: () => raw.close(),
67
+ };
68
+ }
69
+ // ── Public API ──
70
+ export function getDb() {
71
+ if (_db)
72
+ return _db;
73
+ if (!existsSync(DATA_DIR)) {
74
+ mkdirSync(DATA_DIR, { recursive: true });
75
+ }
76
+ _db = createDb(DB_PATH);
77
+ _db.exec('PRAGMA journal_mode = WAL');
78
+ _db.exec('PRAGMA synchronous = NORMAL');
79
+ _db.exec('PRAGMA cache_size = -64000');
80
+ initSchema(_db);
81
+ return _db;
82
+ }
83
+ function initSchema(db) {
84
+ db.exec(`
85
+ CREATE TABLE IF NOT EXISTS regions (
86
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
87
+ county TEXT NOT NULL,
88
+ district TEXT NOT NULL,
89
+ zip_code TEXT NOT NULL,
90
+ UNIQUE(county, district)
91
+ );
92
+ CREATE INDEX IF NOT EXISTS idx_regions_county ON regions(county);
93
+
94
+ CREATE TABLE IF NOT EXISTS names (
95
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
96
+ surname TEXT NOT NULL,
97
+ given_name TEXT NOT NULL,
98
+ gender TEXT NOT NULL CHECK(gender IN ('M', 'F', 'N'))
99
+ );
100
+ CREATE INDEX IF NOT EXISTS idx_names_gender ON names(gender);
101
+
102
+ CREATE TABLE IF NOT EXISTS streets (
103
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
104
+ name TEXT NOT NULL,
105
+ type TEXT NOT NULL DEFAULT '路'
106
+ );
107
+
108
+ CREATE TABLE IF NOT EXISTS companies (
109
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
110
+ name TEXT NOT NULL,
111
+ industry TEXT
112
+ );
113
+
114
+ CREATE TABLE IF NOT EXISTS job_titles (
115
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
116
+ title TEXT NOT NULL,
117
+ level TEXT
118
+ );
119
+ `);
120
+ }
121
+ export function closeDb() {
122
+ if (_db) {
123
+ _db.close();
124
+ _db = null;
125
+ }
126
+ }
127
+ //# sourceMappingURL=db.js.map
package/dist/db.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,+CAA+C;AAC/C,wCAAwC;AACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAE3C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAgB1C,IAAI,GAAG,GAAqB,IAAI,CAAC;AAEjC,0BAA0B;AAC1B,SAAS,KAAK;IACZ,OAAO,OAAQ,UAAkB,CAAC,GAAG,KAAK,WAAW,CAAC;AACxD,CAAC;AAED,SAAS,QAAQ,CAAC,MAAc;IAC9B,IAAI,KAAK,EAAE,EAAE,CAAC;QACZ,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;AAC9B,CAAC;AAED,wBAAwB;AACxB,SAAS,WAAW,CAAC,MAAc;IACjC,iEAAiE;IACjE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,OAAO;QACL,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;QACpC,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE;YACvB,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC9B,OAAO;gBACL,GAAG,EAAE,CAAC,GAAG,CAAY,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACxC,GAAG,EAAE,CAAC,GAAG,CAAY,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACxC,GAAG,EAAE,CAAC,GAAG,CAAY,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;aACzC,CAAC;QACJ,CAAC;QACD,WAAW,CAA4C,EAAK;YAC1D,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,CAAC,EAAkC,CAAC,CAAC;YAC/D,MAAM,OAAO,GAAG,CAAC,GAAG,IAAmB,EAAE,EAAE,CAAE,EAAE,CAAC,GAAG,IAAI,CAAa,CAAC;YACpE,OAAe,CAAC,GAAG,GAAG,CAAC,GAAG,IAAmB,EAAE,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACpE,OAAO,OAAwD,CAAC;QAClE,CAAC;QACD,KAAK,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE;KACzB,CAAC;AACJ,CAAC;AAED,gCAAgC;AAChC,SAAS,YAAY,CAAC,MAAc;IAClC,iEAAiE;IACjE,MAAM,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,OAAO;QACL,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;QACpC,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE;YACvB,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC9B,OAAO;gBACL,GAAG,EAAE,CAAC,GAAG,CAAY,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACxC,GAAG,EAAE,CAAC,GAAG,CAAY,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACxC,GAAG,EAAE,CAAC,GAAG,CAAY,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;aACzC,CAAC;QACJ,CAAC;QACD,WAAW,CAA4C,EAAK;YAC1D,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,CAAC,EAAkC,CAAC,CAAC;YAC/D,MAAM,OAAO,GAAG,CAAC,GAAG,IAAmB,EAAE,EAAE,CAAE,EAAE,CAAC,GAAG,IAAI,CAAa,CAAC;YACpE,OAAe,CAAC,GAAG,GAAG,CAAC,GAAG,IAAmB,EAAE,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACpE,OAAO,OAAwD,CAAC;QAClE,CAAC;QACD,KAAK,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE;KACzB,CAAC;AACJ,CAAC;AAED,mBAAmB;AACnB,MAAM,UAAU,KAAK;IACnB,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC;IAEpB,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxB,GAAG,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACtC,GAAG,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IACxC,GAAG,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IAEvC,UAAU,CAAC,GAAG,CAAC,CAAC;IAChB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,EAAa;IAC/B,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCP,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,IAAI,GAAG,EAAE,CAAC;QACR,GAAG,CAAC,KAAK,EAAE,CAAC;QACZ,GAAG,GAAG,IAAI,CAAC;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ export declare function generateCounty(): string;
2
+ export declare function generateDistrict(county?: string): {
3
+ county: string;
4
+ district: string;
5
+ zipCode: string;
6
+ };
7
+ export declare function generateAddress(): {
8
+ county: string;
9
+ district: string;
10
+ zipCode: string;
11
+ street: string;
12
+ fullAddress: string;
13
+ };
14
+ //# sourceMappingURL=address.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address.d.ts","sourceRoot":"","sources":["../../src/generators/address.ts"],"names":[],"mappings":"AAIA,wBAAgB,cAAc,IAAI,MAAM,CAIvC;AAED,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CASvG;AAED,wBAAgB,eAAe,IAAI;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CA6B5H"}
@@ -0,0 +1,44 @@
1
+ // src/generators/address.ts - 台灣地址產生器
2
+ import { getDb } from '../db.js';
3
+ export function generateCounty() {
4
+ const db = getDb();
5
+ const row = db.prepare('SELECT DISTINCT county FROM regions ORDER BY RANDOM() LIMIT 1').get();
6
+ return row?.county || '台北市';
7
+ }
8
+ export function generateDistrict(county) {
9
+ const db = getDb();
10
+ let query = 'SELECT * FROM regions ORDER BY RANDOM() LIMIT 1';
11
+ if (county) {
12
+ query = 'SELECT * FROM regions WHERE county = ? ORDER BY RANDOM() LIMIT 1';
13
+ }
14
+ const row = db.prepare(query).get(...(county ? [county] : []));
15
+ if (!row)
16
+ return { county: '台北市', district: '中正區', zipCode: '100' };
17
+ return { county: row.county, district: row.district, zipCode: row.zip_code };
18
+ }
19
+ export function generateAddress() {
20
+ const db = getDb();
21
+ const region = db.prepare('SELECT * FROM regions ORDER BY RANDOM() LIMIT 1').get();
22
+ const street = db.prepare('SELECT * FROM streets ORDER BY RANDOM() LIMIT 1').get();
23
+ const streetName = street ? `${street.name}${street.type}` : '中山路';
24
+ const lane = Math.floor(Math.random() * 50) + 1;
25
+ const alley = Math.floor(Math.random() * 30) + 1;
26
+ const num = Math.floor(Math.random() * 200) + 1;
27
+ const floor = Math.floor(Math.random() * 15) + 1;
28
+ const formats = [
29
+ `${streetName}${lane}巷${num}號`,
30
+ `${streetName}${lane}巷${alley}弄${num}號`,
31
+ `${streetName}${lane}巷${num}號${floor}樓`,
32
+ `${streetName}${num}號`,
33
+ `${streetName}${lane}巷${num}之${Math.floor(Math.random() * 20) + 1}號`,
34
+ ];
35
+ const streetPart = formats[Math.floor(Math.random() * formats.length)];
36
+ return {
37
+ county: region.county,
38
+ district: region.district,
39
+ zipCode: region.zip_code,
40
+ street: streetPart,
41
+ fullAddress: `${region.zip_code} ${region.county}${region.district}${streetPart}`,
42
+ };
43
+ }
44
+ //# sourceMappingURL=address.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address.js","sourceRoot":"","sources":["../../src/generators/address.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAGjC,MAAM,UAAU,cAAc;IAC5B,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,+DAA+D,CAAC,CAAC,GAAG,EAAoC,CAAC;IAChI,OAAO,GAAG,EAAE,MAAM,IAAI,KAAK,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAe;IAC9C,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,IAAI,KAAK,GAAG,iDAAiD,CAAC;IAC9D,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,GAAG,kEAAkE,CAAC;IAC7E,CAAC;IACD,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAA0B,CAAC;IACxF,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACpE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IAEnB,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,EAAe,CAAC;IAChG,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,EAAgD,CAAC;IAEjI,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IACnE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IAEjD,MAAM,OAAO,GAAG;QACd,GAAG,UAAU,GAAG,IAAI,IAAI,GAAG,GAAG;QAC9B,GAAG,UAAU,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,GAAG;QACvC,GAAG,UAAU,GAAG,IAAI,IAAI,GAAG,IAAI,KAAK,GAAG;QACvC,GAAG,UAAU,GAAG,GAAG,GAAG;QACtB,GAAG,UAAU,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG;KACrE,CAAC;IAEF,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAEvE,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,OAAO,EAAE,MAAM,CAAC,QAAQ;QACxB,MAAM,EAAE,UAAU;QAClB,WAAW,EAAE,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ,GAAG,UAAU,EAAE;KAClF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import 'dotenv/config';
2
+ export declare function generateWithAI(prompt: string, count: number): Promise<string[]>;
3
+ export declare function generateBatchWithAI(fields: Array<{
4
+ fieldName: string;
5
+ prompt: string;
6
+ }>, count: number): Promise<Record<string, string[]>>;
7
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/generators/gemini.ts"],"names":[],"mappings":"AACA,OAAO,eAAe,CAAC;AAiBvB,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA4DrF;AAGD,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EACpD,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CA0DnC"}
@@ -0,0 +1,121 @@
1
+ // src/generators/gemini.ts - Gemini AI 整合 (複雜資料產生)
2
+ import 'dotenv/config';
3
+ const GEMINI_API_KEY = process.env.GEMINI_API_KEY || '';
4
+ const GEMINI_MODEL = 'gemini-2.5-flash';
5
+ const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent`;
6
+ // 簡單快取避免重複呼叫
7
+ const cache = new Map();
8
+ export async function generateWithAI(prompt, count) {
9
+ const cacheKey = `${prompt}:${count}`;
10
+ if (cache.has(cacheKey)) {
11
+ return cache.get(cacheKey);
12
+ }
13
+ if (!GEMINI_API_KEY) {
14
+ console.error('[Gemini] No API key set, returning placeholder data');
15
+ return Array.from({ length: count }, (_, i) => `${prompt} #${i + 1}`);
16
+ }
17
+ try {
18
+ const response = await fetch(`${GEMINI_URL}?key=${GEMINI_API_KEY}`, {
19
+ method: 'POST',
20
+ headers: { 'Content-Type': 'application/json' },
21
+ body: JSON.stringify({
22
+ contents: [{
23
+ role: 'user',
24
+ parts: [{
25
+ text: `Generate exactly ${count} realistic fake data items for: "${prompt}".
26
+ Rules:
27
+ - Return ONLY a JSON array of strings, no explanation.
28
+ - Each item should be unique and realistic.
29
+ - Use Taiwan/Chinese context where appropriate.
30
+ - Example format: ["item1", "item2", ...]
31
+
32
+ Generate ${count} items now:`
33
+ }]
34
+ }],
35
+ generationConfig: {
36
+ temperature: 0.9,
37
+ maxOutputTokens: 2048,
38
+ responseMimeType: 'application/json',
39
+ }
40
+ }),
41
+ signal: AbortSignal.timeout(15000),
42
+ });
43
+ if (!response.ok) {
44
+ const errText = await response.text();
45
+ console.error(`[Gemini] API error ${response.status}: ${errText}`);
46
+ return Array.from({ length: count }, (_, i) => `${prompt} #${i + 1}`);
47
+ }
48
+ const data = await response.json();
49
+ const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
50
+ if (!text) {
51
+ return Array.from({ length: count }, (_, i) => `${prompt} #${i + 1}`);
52
+ }
53
+ // 嘗試解析 JSON 陣列
54
+ const parsed = JSON.parse(text);
55
+ const result = Array.isArray(parsed) ? parsed.slice(0, count) : Array.from({ length: count }, (_, i) => `${prompt} #${i + 1}`);
56
+ cache.set(cacheKey, result);
57
+ return result;
58
+ }
59
+ catch (err) {
60
+ console.error('[Gemini] Error:', err);
61
+ return Array.from({ length: count }, (_, i) => `${prompt} #${i + 1}`);
62
+ }
63
+ }
64
+ // 批次產生多個欄位的 AI 資料 (一次性請求,減少 API 呼叫)
65
+ export async function generateBatchWithAI(fields, count) {
66
+ if (!GEMINI_API_KEY) {
67
+ const result = {};
68
+ for (const f of fields) {
69
+ result[f.fieldName] = Array.from({ length: count }, (_, i) => `${f.prompt} #${i + 1}`);
70
+ }
71
+ return result;
72
+ }
73
+ const fieldsDescription = fields.map(f => `"${f.fieldName}": (${f.prompt})`).join('\n');
74
+ try {
75
+ const response = await fetch(`${GEMINI_URL}?key=${GEMINI_API_KEY}`, {
76
+ method: 'POST',
77
+ headers: { 'Content-Type': 'application/json' },
78
+ body: JSON.stringify({
79
+ contents: [{
80
+ role: 'user',
81
+ parts: [{
82
+ text: `Generate ${count} realistic fake data items for EACH of these fields (Taiwan context):
83
+ ${fieldsDescription}
84
+
85
+ Return ONLY a JSON object where each key is the field name and value is an array of ${count} strings.
86
+ Example format:
87
+ {
88
+ "fieldName1": ["val1", "val2"],
89
+ "fieldName2": ["val1", "val2"]
90
+ }
91
+
92
+ Generate now:`
93
+ }]
94
+ }],
95
+ generationConfig: {
96
+ temperature: 0.9,
97
+ maxOutputTokens: 4096,
98
+ responseMimeType: 'application/json',
99
+ }
100
+ }),
101
+ signal: AbortSignal.timeout(30000),
102
+ });
103
+ if (!response.ok) {
104
+ throw new Error(`Gemini API ${response.status}`);
105
+ }
106
+ const data = await response.json();
107
+ const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
108
+ if (!text)
109
+ throw new Error('No response text');
110
+ return JSON.parse(text);
111
+ }
112
+ catch (err) {
113
+ console.error('[Gemini] Batch error:', err);
114
+ const result = {};
115
+ for (const f of fields) {
116
+ result[f.fieldName] = Array.from({ length: count }, (_, i) => `${f.prompt} #${i + 1}`);
117
+ }
118
+ return result;
119
+ }
120
+ }
121
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/generators/gemini.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,OAAO,eAAe,CAAC;AAEvB,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC;AACxD,MAAM,YAAY,GAAG,kBAAkB,CAAC;AACxC,MAAM,UAAU,GAAG,2DAA2D,YAAY,kBAAkB,CAAC;AAU7G,aAAa;AACb,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAc,EAAE,KAAa;IAChE,MAAM,QAAQ,GAAG,GAAG,MAAM,IAAI,KAAK,EAAE,CAAC;IACtC,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;IAC9B,CAAC;IAED,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACrE,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,UAAU,QAAQ,cAAc,EAAE,EAAE;YAClE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,QAAQ,EAAE,CAAC;wBACT,IAAI,EAAE,MAAM;wBACZ,KAAK,EAAE,CAAC;gCACN,IAAI,EAAE,oBAAoB,KAAK,oCAAoC,MAAM;;;;;;;WAO1E,KAAK,aAAa;6BAClB,CAAC;qBACH,CAAC;gBACF,gBAAgB,EAAE;oBAChB,WAAW,EAAE,GAAG;oBAChB,eAAe,EAAE,IAAI;oBACrB,gBAAgB,EAAE,kBAAkB;iBACrC;aACF,CAAC;YACF,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;SACnC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACtC,OAAO,CAAC,KAAK,CAAC,sBAAsB,QAAQ,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC;YACnE,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAoB,CAAC;QACrD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QAC7D,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,eAAe;QACf,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAa,CAAC;QAC5C,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAE/H,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC5B,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QACtC,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;AACH,CAAC;AAED,oCAAoC;AACpC,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAoD,EACpD,KAAa;IAEb,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,MAAM,GAA6B,EAAE,CAAC;QAC5C,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAExF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,UAAU,QAAQ,cAAc,EAAE,EAAE;YAClE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,QAAQ,EAAE,CAAC;wBACT,IAAI,EAAE,MAAM;wBACZ,KAAK,EAAE,CAAC;gCACN,IAAI,EAAE,YAAY,KAAK;EACjC,iBAAiB;;sFAEmE,KAAK;;;;;;;cAO7E;6BACH,CAAC;qBACH,CAAC;gBACF,gBAAgB,EAAE;oBAChB,WAAW,EAAE,GAAG;oBAChB,eAAe,EAAE,IAAI;oBACrB,gBAAgB,EAAE,kBAAkB;iBACrC;aACF,CAAC;YACF,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;SACnC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,cAAc,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACnD,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAoB,CAAC;QACrD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QAC7D,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAE/C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAA6B,CAAC;IACtD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;QAC5C,MAAM,MAAM,GAA6B,EAAE,CAAC;QAC5C,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function generateIdNumber(gender?: 'M' | 'F'): string;
2
+ export declare function generateIdNumberForCounty(county: string, gender?: 'M' | 'F'): string;
3
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/generators/identity.ts"],"names":[],"mappings":"AAyBA,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,CAoB3D;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,CAkBpF"}
@@ -0,0 +1,56 @@
1
+ // src/generators/identity.ts - 台灣身份證字號產生器
2
+ // 身份證格式: 1 英文字母 (縣市代碼) + 1 碼性別 (1=男, 2=女) + 8 碼流水號 + 1 碼檢查碼
3
+ // 驗證演算法: 每個字母對應兩位數字,加上各碼加權後 mod 10 == 0
4
+ const LETTER_MAP = {
5
+ 'A': [1, 0], 'B': [1, 1], 'C': [1, 2], 'D': [1, 3], 'E': [1, 4],
6
+ 'F': [1, 5], 'G': [1, 6], 'H': [1, 7], 'I': [3, 4], 'J': [1, 8],
7
+ 'K': [1, 9], 'L': [2, 0], 'M': [2, 1], 'N': [2, 2], 'O': [3, 5],
8
+ 'P': [2, 3], 'Q': [2, 4], 'R': [2, 5], 'S': [2, 6], 'T': [2, 7],
9
+ 'U': [2, 8], 'V': [2, 9], 'W': [3, 2], 'X': [3, 0], 'Y': [3, 1],
10
+ 'Z': [3, 3],
11
+ };
12
+ // 縣市對應首字母 (出生地)
13
+ const COUNTY_LETTERS = {
14
+ '台北市': ['A'], '台中市': ['B'], '基隆市': ['C'], '台南市': ['D'],
15
+ '高雄市': ['E'], '新北市': ['F', 'G', 'H'], '宜蘭縣': ['J'],
16
+ '桃園市': ['H', 'I'], '嘉義市': ['I'], '嘉義縣': ['J'], '新竹縣': ['K'],
17
+ '苗栗縣': ['M'], '南投縣': ['N'], '彰化縣': ['P'], '新竹市': ['O'],
18
+ '雲林縣': ['Q'], '屏東縣': ['T'], '花蓮縣': ['U'], '台東縣': ['V'],
19
+ '金門縣': ['W'], '澎湖縣': ['X'], '連江縣': ['Z'],
20
+ };
21
+ const WEIGHTS = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1];
22
+ export function generateIdNumber(gender) {
23
+ const letters = Object.keys(LETTER_MAP);
24
+ const letter = letters[Math.floor(Math.random() * letters.length)];
25
+ const genderDigit = gender === 'F' ? '2' : (Math.random() > 0.5 ? '1' : '2');
26
+ // 產生 7 位隨機數字 (中間碼)
27
+ let serial = '';
28
+ for (let i = 0; i < 7; i++) {
29
+ serial += Math.floor(Math.random() * 10).toString();
30
+ }
31
+ // 計算檢查碼
32
+ const digits = [...LETTER_MAP[letter].map(String), genderDigit, ...serial.split('')];
33
+ let sum = 0;
34
+ for (let i = 0; i < digits.length; i++) {
35
+ sum += parseInt(digits[i]) * WEIGHTS[i];
36
+ }
37
+ const checkDigit = (10 - (sum % 10)) % 10;
38
+ return `${letter}${genderDigit}${serial}${checkDigit}`;
39
+ }
40
+ export function generateIdNumberForCounty(county, gender) {
41
+ const letters = COUNTY_LETTERS[county] || Object.keys(LETTER_MAP);
42
+ const letter = letters[Math.floor(Math.random() * letters.length)];
43
+ const genderDigit = gender === 'F' ? '2' : (Math.random() > 0.5 ? '1' : '2');
44
+ let serial = '';
45
+ for (let i = 0; i < 7; i++) {
46
+ serial += Math.floor(Math.random() * 10).toString();
47
+ }
48
+ const digits = [...LETTER_MAP[letter].map(String), genderDigit, ...serial.split('')];
49
+ let sum = 0;
50
+ for (let i = 0; i < digits.length; i++) {
51
+ sum += parseInt(digits[i]) * WEIGHTS[i];
52
+ }
53
+ const checkDigit = (10 - (sum % 10)) % 10;
54
+ return `${letter}${genderDigit}${serial}${checkDigit}`;
55
+ }
56
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/generators/identity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { SchemaField } from '../types.js';
2
+ export declare function generateLocal(schema: Record<string, SchemaField>, count: number): Record<string, unknown>[];
3
+ export declare function generateWithAIEnhanced(schema: Record<string, SchemaField>, count: number): Promise<{
4
+ data: Record<string, unknown>[];
5
+ aiUsed: boolean;
6
+ }>;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generators/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAA0B,MAAM,aAAa,CAAC;AAsIvE,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAe3G;AAGD,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACnC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC,CA+B/D"}