loredata 0.1.0 → 0.3.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 (95) hide show
  1. package/README.md +72 -21
  2. package/data/avengers/addresses.json +27 -0
  3. package/data/avengers/characters.json +178 -0
  4. package/data/avengers/meta.json +13 -0
  5. package/data/better-call-saul/addresses.json +37 -0
  6. package/data/better-call-saul/characters.json +156 -0
  7. package/data/better-call-saul/meta.json +13 -0
  8. package/data/big-bang-theory/addresses.json +31 -0
  9. package/data/big-bang-theory/characters.json +121 -0
  10. package/data/big-bang-theory/meta.json +13 -0
  11. package/data/breaking-bad/characters.json +49 -13
  12. package/data/breaking-bad/meta.json +10 -1
  13. package/data/fast-and-furious/characters.json +39 -13
  14. package/data/fast-and-furious/meta.json +15 -1
  15. package/data/friends/characters.json +138 -22
  16. package/data/friends/meta.json +13 -1
  17. package/data/game-of-thrones/characters.json +61 -16
  18. package/data/game-of-thrones/meta.json +10 -1
  19. package/data/guardians-of-the-galaxy/addresses.json +17 -0
  20. package/data/guardians-of-the-galaxy/characters.json +124 -0
  21. package/data/guardians-of-the-galaxy/meta.json +13 -0
  22. package/data/harry-potter/characters.json +37 -7
  23. package/data/harry-potter/meta.json +10 -1
  24. package/data/house-md/characters.json +79 -25
  25. package/data/house-md/meta.json +13 -1
  26. package/data/lost/characters.json +144 -36
  27. package/data/lost/meta.json +13 -1
  28. package/data/matrix/characters.json +133 -34
  29. package/data/matrix/meta.json +18 -1
  30. package/data/peaky-blinders/characters.json +44 -11
  31. package/data/peaky-blinders/meta.json +13 -1
  32. package/data/prison-break/addresses.json +24 -0
  33. package/data/prison-break/characters.json +116 -0
  34. package/data/prison-break/meta.json +13 -0
  35. package/data/sherlock/characters.json +116 -27
  36. package/data/sherlock/meta.json +13 -1
  37. package/data/simpsons/addresses.json +21 -0
  38. package/data/simpsons/characters.json +219 -0
  39. package/data/simpsons/meta.json +13 -0
  40. package/data/sopranos/addresses.json +37 -0
  41. package/data/sopranos/characters.json +184 -0
  42. package/data/sopranos/meta.json +13 -0
  43. package/data/south-park/addresses.json +31 -0
  44. package/data/south-park/characters.json +230 -0
  45. package/data/south-park/meta.json +13 -0
  46. package/data/spider-man/addresses.json +31 -0
  47. package/data/spider-man/characters.json +134 -0
  48. package/data/spider-man/meta.json +13 -0
  49. package/data/star-wars/addresses.json +19 -0
  50. package/data/star-wars/characters.json +153 -0
  51. package/data/star-wars/meta.json +13 -0
  52. package/data/supernatural/addresses.json +25 -0
  53. package/data/supernatural/characters.json +113 -0
  54. package/data/supernatural/meta.json +13 -0
  55. package/data/the-office/characters.json +84 -29
  56. package/data/the-office/meta.json +10 -1
  57. package/data/the-walking-dead/addresses.json +25 -0
  58. package/data/the-walking-dead/characters.json +114 -0
  59. package/data/the-walking-dead/meta.json +13 -0
  60. package/data/westworld/addresses.json +19 -0
  61. package/data/westworld/characters.json +108 -0
  62. package/data/westworld/meta.json +13 -0
  63. package/data/x-men/addresses.json +24 -0
  64. package/data/x-men/characters.json +158 -0
  65. package/data/x-men/meta.json +18 -0
  66. package/dist/browser.cjs +114 -69
  67. package/dist/browser.cjs.map +1 -1
  68. package/dist/browser.d.cts +7 -3
  69. package/dist/browser.d.ts +7 -3
  70. package/dist/browser.js +110 -69
  71. package/dist/browser.js.map +1 -1
  72. package/dist/cli/cli.cjs +131 -70
  73. package/dist/cli/cli.cjs.map +1 -1
  74. package/dist/cli/cli.js +132 -71
  75. package/dist/cli/cli.js.map +1 -1
  76. package/dist/index.cjs +132 -68
  77. package/dist/index.cjs.map +1 -1
  78. package/dist/index.d.cts +15 -4
  79. package/dist/index.d.ts +15 -4
  80. package/dist/index.js +132 -69
  81. package/dist/index.js.map +1 -1
  82. package/dist/{universe-store-DJrm7bP7.d.cts → universe-store-CWhCn3U6.d.cts} +31 -19
  83. package/dist/{universe-store-DJrm7bP7.d.ts → universe-store-CWhCn3U6.d.ts} +31 -19
  84. package/package.json +12 -4
  85. package/data/breaking-bad/domains.json +0 -6
  86. package/data/fast-and-furious/domains.json +0 -6
  87. package/data/friends/domains.json +0 -6
  88. package/data/game-of-thrones/domains.json +0 -6
  89. package/data/harry-potter/domains.json +0 -6
  90. package/data/house-md/domains.json +0 -6
  91. package/data/lost/domains.json +0 -6
  92. package/data/matrix/domains.json +0 -6
  93. package/data/peaky-blinders/domains.json +0 -6
  94. package/data/sherlock/domains.json +0 -6
  95. package/data/the-office/domains.json +0 -6
package/dist/index.cjs CHANGED
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
+ PersonFactory: () => PersonFactory,
23
24
  UniverseLoader: () => UniverseLoader,
24
25
  UniverseStore: () => UniverseStore,
25
26
  group: () => group,
@@ -31,34 +32,106 @@ module.exports = __toCommonJS(src_exports);
31
32
 
32
33
  // src/universes/loader.ts
33
34
  var import_fs = require("fs");
35
+ var import_module = require("module");
34
36
  var import_path = require("path");
35
37
  var import_meta = {};
36
- var dataDir = (0, import_path.join)(import_meta.dirname, "../data");
38
+ var require2 = (0, import_module.createRequire)(import_meta.url);
39
+ var packageRoot = (0, import_path.dirname)(require2.resolve("loredata/package.json"));
40
+ var dataDir = (0, import_path.join)(packageRoot, "data");
37
41
  var UniverseLoader = class {
38
42
  static cache = /* @__PURE__ */ new Map();
39
43
  static register(data) {
40
44
  this.cache.set(data.id, data);
41
45
  }
42
46
  static load(universeId) {
43
- const cached = this.cache.get(universeId);
44
- if (cached) {
45
- return cached;
47
+ if (process.env.NODE_ENV !== "development") {
48
+ const cached = this.cache.get(universeId);
49
+ if (cached) {
50
+ return cached;
51
+ }
46
52
  }
47
53
  const universeDir = (0, import_path.join)(dataDir, universeId);
48
54
  const meta = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(universeDir, "meta.json"), "utf-8"));
49
55
  const characters = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(universeDir, "characters.json"), "utf-8"));
50
56
  const addresses = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(universeDir, "addresses.json"), "utf-8"));
51
- const domains = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(universeDir, "domains.json"), "utf-8"));
52
57
  const universeData = {
53
58
  id: meta.id,
54
59
  name: meta.name,
60
+ genre: meta.genre,
61
+ description: meta.description,
55
62
  characters,
56
63
  addresses,
57
- domains
64
+ ...meta.tmdbId !== void 0 && { tmdbId: meta.tmdbId },
65
+ ...meta.mediaType !== void 0 && { mediaType: meta.mediaType },
66
+ ...meta.rating !== void 0 && { rating: meta.rating },
67
+ ...meta.year !== void 0 && { year: meta.year },
68
+ ...meta.networks !== void 0 && { networks: meta.networks },
69
+ ...meta.posterPath !== void 0 && { posterPath: meta.posterPath },
70
+ ...meta.backdropPath !== void 0 && { backdropPath: meta.backdropPath }
58
71
  };
59
72
  this.cache.set(universeId, universeData);
60
73
  return universeData;
61
74
  }
75
+ static getManifest() {
76
+ const ids = this.listAvailable();
77
+ const result = ids.map((id) => {
78
+ const universeDir = (0, import_path.join)(dataDir, id);
79
+ return JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(universeDir, "meta.json"), "utf-8"));
80
+ });
81
+ return result;
82
+ }
83
+ static getAllInterests() {
84
+ const ids = this.listAvailable();
85
+ const interestSet = /* @__PURE__ */ new Set();
86
+ for (const id of ids) {
87
+ const universe = this.load(id);
88
+ for (const character of universe.characters) {
89
+ for (const interest of character.interests) {
90
+ interestSet.add(interest);
91
+ }
92
+ }
93
+ }
94
+ const result = Array.from(interestSet).sort();
95
+ return result;
96
+ }
97
+ static getAllLocations() {
98
+ const ids = this.listAvailable();
99
+ const seen = /* @__PURE__ */ new Map();
100
+ for (const id of ids) {
101
+ const universe = this.load(id);
102
+ for (const address of universe.addresses) {
103
+ if (address.city && !seen.has(`city:${address.city}`)) {
104
+ seen.set(`city:${address.city}`, { name: address.city, type: "city" });
105
+ }
106
+ if (address.state && !seen.has(`state:${address.state}`)) {
107
+ seen.set(`state:${address.state}`, { name: address.state, type: "state" });
108
+ }
109
+ if (address.country && !seen.has(`country:${address.country}`)) {
110
+ seen.set(`country:${address.country}`, { name: address.country, type: "country" });
111
+ }
112
+ }
113
+ }
114
+ return Array.from(seen.values()).sort((a, b) => a.name.localeCompare(b.name));
115
+ }
116
+ static buildCharacterIndex() {
117
+ const ids = this.listAvailable();
118
+ const entries = [];
119
+ for (const id of ids) {
120
+ const universe = this.load(id);
121
+ for (const character of universe.characters) {
122
+ entries.push({
123
+ characterId: character.id,
124
+ universeId: universe.id,
125
+ universeName: universe.name,
126
+ firstName: character.firstName ?? "",
127
+ lastName: character.lastName ?? "",
128
+ interests: character.interests,
129
+ profession: character.profession
130
+ });
131
+ }
132
+ }
133
+ return entries;
134
+ }
62
135
  static listAvailable() {
63
136
  const entries = (0, import_fs.readdirSync)(dataDir, { withFileTypes: true });
64
137
  const ids = entries.filter((entry) => {
@@ -97,55 +170,12 @@ function pickRandom(array, rng) {
97
170
 
98
171
  // src/generators/email.ts
99
172
  var EmailGenerator = class {
100
- static generate(firstName, lastName, domains, rng) {
101
- const domain = pickRandom(domains.emailDomains, rng);
102
- const first = firstName.toLowerCase();
103
- const last = lastName.toLowerCase();
104
- return `${first}.${last}@${domain}`;
105
- }
106
- static generateFromUsername(username, domains, rng) {
107
- const domain = pickRandom(domains.emailDomains, rng);
173
+ static generateFromUsername(username, emailDomains, rng) {
174
+ const domain = pickRandom(emailDomains, rng);
108
175
  return `${username}@${domain}`;
109
176
  }
110
177
  };
111
178
 
112
- // src/generators/phone.ts
113
- var PhoneGenerator = class {
114
- static generate(domains, rng) {
115
- if (domains.phoneEasterEggs && domains.phoneEasterEggs.length > 0 && rng() < 0.2) {
116
- return pickRandom(domains.phoneEasterEggs, rng);
117
- }
118
- const prefix = pickRandom(domains.phonePrefixes, rng);
119
- const suffix = this.randomDigits(7, rng);
120
- return `${prefix}-${suffix.slice(0, 3)}-${suffix.slice(3)}`;
121
- }
122
- static randomDigits(count, rng) {
123
- let result = "";
124
- for (let i = 0; i < count; i++) {
125
- result += Math.floor(rng() * 10).toString();
126
- }
127
- return result;
128
- }
129
- };
130
-
131
- // src/generators/password.ts
132
- var PasswordGenerator = class {
133
- static generate(domains, rng) {
134
- if (domains.passwordEasterEggs && domains.passwordEasterEggs.length > 0 && rng() < 0.3) {
135
- return pickRandom(domains.passwordEasterEggs, rng);
136
- }
137
- return this.randomPassword(12, rng);
138
- }
139
- static randomPassword(length, rng) {
140
- const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$";
141
- let result = "";
142
- for (let i = 0; i < length; i++) {
143
- result += chars[Math.floor(rng() * chars.length)];
144
- }
145
- return result;
146
- }
147
- };
148
-
149
179
  // src/engine/person-factory.ts
150
180
  var PersonFactory = class {
151
181
  static build(universe, seed) {
@@ -161,16 +191,45 @@ var PersonFactory = class {
161
191
  const rng = createRng(seed);
162
192
  return this.buildFromCharacter(character, universe, rng);
163
193
  }
194
+ static buildCanonical(characterId, universe) {
195
+ const character = universe.characters.find((c) => c.id === characterId);
196
+ if (!character) {
197
+ throw new Error(`Character "${characterId}" not found in universe "${universe.id}"`);
198
+ }
199
+ const address = character.address ?? universe.addresses[0];
200
+ const username = character.usernames[0];
201
+ const rng = createRng(0);
202
+ const email = EmailGenerator.generateFromUsername(username, character.emailDomains, rng);
203
+ const quote = character.quotes[0];
204
+ const person2 = {
205
+ id: crypto.randomUUID(),
206
+ characterId: character.id,
207
+ firstName: character.firstName,
208
+ lastName: character.lastName,
209
+ username,
210
+ email,
211
+ address: {
212
+ street: address.street,
213
+ city: address.city,
214
+ state: address.state ?? "",
215
+ zip: address.zip ?? "",
216
+ country: address.country
217
+ },
218
+ profession: character.profession,
219
+ interests: character.interests,
220
+ quote,
221
+ universe: universe.id,
222
+ universeName: universe.name,
223
+ ...character.symbol ? { symbol: character.symbol } : {},
224
+ ...character.color ? { color: character.color } : {}
225
+ };
226
+ return person2;
227
+ }
164
228
  static buildFromCharacter(character, universe, rng) {
165
229
  const address = character.address ?? pickRandom(universe.addresses, rng);
166
230
  const username = pickRandom(character.usernames, rng);
167
- const domains = character.emailDomain ? { ...universe.domains, emailDomains: [character.emailDomain] } : universe.domains;
168
- const email = EmailGenerator.generateFromUsername(username, domains, rng);
169
- const phone = PhoneGenerator.generate(universe.domains, rng);
170
- const password = PasswordGenerator.generate(universe.domains, rng);
231
+ const email = EmailGenerator.generateFromUsername(username, character.emailDomains, rng);
171
232
  const quote = pickRandom(character.quotes, rng);
172
- const avatarName = encodeURIComponent(`${character.firstName} ${character.lastName}`);
173
- const avatar = `https://ui-avatars.com/api/?name=${avatarName}&background=random`;
174
233
  const person2 = {
175
234
  id: crypto.randomUUID(),
176
235
  characterId: character.id,
@@ -178,8 +237,6 @@ var PersonFactory = class {
178
237
  lastName: character.lastName,
179
238
  username,
180
239
  email,
181
- password,
182
- phone,
183
240
  address: {
184
241
  street: address.street,
185
242
  city: address.city,
@@ -192,7 +249,8 @@ var PersonFactory = class {
192
249
  quote,
193
250
  universe: universe.id,
194
251
  universeName: universe.name,
195
- avatar
252
+ ...character.symbol ? { symbol: character.symbol } : {},
253
+ ...character.color ? { color: character.color } : {}
196
254
  };
197
255
  return person2;
198
256
  }
@@ -219,12 +277,13 @@ var PersonaBuilder = class {
219
277
  const ids = UniverseLoader.listAvailable();
220
278
  const result = ids.map((id) => {
221
279
  const data = UniverseLoader.load(id);
222
- const info = {
280
+ const meta = {
223
281
  id,
224
282
  name: data.name,
225
- characterCount: data.characters.length
283
+ genre: data.genre,
284
+ description: data.description
226
285
  };
227
- return info;
286
+ return meta;
228
287
  });
229
288
  return result;
230
289
  }
@@ -253,11 +312,15 @@ var UniverseStore = class {
253
312
  return result;
254
313
  }
255
314
  getUniverses() {
256
- const result = this.universes.map((u) => ({
257
- id: u.id,
258
- name: u.name,
259
- characterCount: u.characters.length
260
- }));
315
+ const result = this.universes.map((u) => {
316
+ const meta = {
317
+ id: u.id,
318
+ name: u.name,
319
+ genre: u.genre,
320
+ description: u.description
321
+ };
322
+ return meta;
323
+ });
261
324
  return result;
262
325
  }
263
326
  findCharacters(query) {
@@ -346,6 +409,7 @@ function universes() {
346
409
  }
347
410
  // Annotate the CommonJS export names for ESM import in node:
348
411
  0 && (module.exports = {
412
+ PersonFactory,
349
413
  UniverseLoader,
350
414
  UniverseStore,
351
415
  group,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/universes/loader.ts","../src/generators/random.ts","../src/generators/email.ts","../src/generators/phone.ts","../src/generators/password.ts","../src/engine/person-factory.ts","../src/engine/persona-builder.ts","../src/engine/universe-store.ts"],"sourcesContent":["import { PersonaBuilder } from '@/engine';\n\nimport type { Person, UniverseInfo, PersonOptions, GroupOptions, UniverseData } from '@/types';\n\nexport function person(options: PersonOptions): Person {\n\treturn PersonaBuilder.buildPerson(options);\n}\n\nexport function personFromData(universe: UniverseData, seed?: number): Person {\n\treturn PersonaBuilder.buildPersonFromData(universe, { seed });\n}\n\nexport function group(options: GroupOptions): Person[] {\n\treturn PersonaBuilder.buildGroup(options);\n}\n\nexport function universes(): UniverseInfo[] {\n\treturn PersonaBuilder.listUniverses();\n}\n\nexport { UniverseLoader } from '@/universes';\nexport { UniverseStore } from '@/engine';\n\nexport type { Person, UniverseInfo, PersonOptions, GroupOptions } from '@/types';\nexport type { Address, UniverseData, CharacterData, AddressData, DomainsData } from '@/types';\nexport type { CharacterEntry, CharacterQuery } from '@/types';\n","import { readFileSync, readdirSync } from 'fs';\nimport { join } from 'path';\n\nimport type { UniverseData, CharacterData, AddressData, DomainsData } from '@/types';\n\nconst dataDir = join(import.meta.dirname, '../data');\n\nexport class UniverseLoader {\n\tprivate static cache = new Map<string, UniverseData>();\n\n\tstatic register(data: UniverseData): void {\n\t\tthis.cache.set(data.id, data);\n\t}\n\n\tstatic load(universeId: string): UniverseData {\n\t\tconst cached = this.cache.get(universeId);\n\n\t\tif (cached) {\n\t\t\treturn cached;\n\t\t}\n\n\t\tconst universeDir = join(dataDir, universeId);\n\t\tconst meta = JSON.parse(readFileSync(join(universeDir, 'meta.json'), 'utf-8')) as {\n\t\t\tid: string;\n\t\t\tname: string;\n\t\t};\n\n\t\tconst characters = JSON.parse(readFileSync(join(universeDir, 'characters.json'), 'utf-8')) as CharacterData[];\n\n\t\tconst addresses = JSON.parse(readFileSync(join(universeDir, 'addresses.json'), 'utf-8')) as AddressData[];\n\n\t\tconst domains = JSON.parse(readFileSync(join(universeDir, 'domains.json'), 'utf-8')) as DomainsData;\n\n\t\tconst universeData: UniverseData = {\n\t\t\tid: meta.id,\n\t\t\tname: meta.name,\n\t\t\tcharacters,\n\t\t\taddresses,\n\t\t\tdomains\n\t\t};\n\n\t\tthis.cache.set(universeId, universeData);\n\n\t\treturn universeData;\n\t}\n\n\tstatic listAvailable(): string[] {\n\t\tconst entries = readdirSync(dataDir, { withFileTypes: true });\n\n\t\tconst ids = entries\n\t\t\t.filter((entry) => {\n\t\t\t\tif (!entry.isDirectory()) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\treadFileSync(join(dataDir, entry.name, 'meta.json'), 'utf-8');\n\n\t\t\t\t\treturn true;\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t})\n\t\t\t.map((entry) => entry.name);\n\n\t\treturn ids;\n\t}\n}\n","/**\n * Seeded pseudo-random number generator (mulberry32).\n * Returns a function that produces values in [0, 1).\n */\nexport function createRng(seed?: number): () => number {\n\tif (seed === undefined) {\n\t\treturn Math.random;\n\t}\n\n\tlet s = seed;\n\n\treturn function rng(): number {\n\t\ts += 0x6d2b79f5;\n\t\tlet z = s;\n\t\tz = Math.imul(z ^ (z >>> 15), z | 1);\n\t\tz ^= z + Math.imul(z ^ (z >>> 7), z | 61);\n\n\t\treturn ((z ^ (z >>> 14)) >>> 0) / 4294967296;\n\t};\n}\n\nexport function pickRandom<T>(array: T[], rng: () => number): T {\n\tconst index = Math.floor(rng() * array.length);\n\n\treturn array[index];\n}\n","import { pickRandom } from './random';\n\nimport type { DomainsData } from '@/types';\n\nexport class EmailGenerator {\n\tstatic generate(firstName: string, lastName: string, domains: DomainsData, rng: () => number): string {\n\t\tconst domain = pickRandom(domains.emailDomains, rng);\n\t\tconst first = firstName.toLowerCase();\n\t\tconst last = lastName.toLowerCase();\n\n\t\treturn `${first}.${last}@${domain}`;\n\t}\n\n\tstatic generateFromUsername(username: string, domains: DomainsData, rng: () => number): string {\n\t\tconst domain = pickRandom(domains.emailDomains, rng);\n\n\t\treturn `${username}@${domain}`;\n\t}\n}\n","import { pickRandom } from './random';\n\nimport type { DomainsData } from '@/types';\n\nexport class PhoneGenerator {\n\tstatic generate(domains: DomainsData, rng: () => number): string {\n\t\tif (domains.phoneEasterEggs && domains.phoneEasterEggs.length > 0 && rng() < 0.2) {\n\t\t\treturn pickRandom(domains.phoneEasterEggs, rng);\n\t\t}\n\n\t\tconst prefix = pickRandom(domains.phonePrefixes, rng);\n\t\tconst suffix = this.randomDigits(7, rng);\n\n\t\treturn `${prefix}-${suffix.slice(0, 3)}-${suffix.slice(3)}`;\n\t}\n\n\tprivate static randomDigits(count: number, rng: () => number): string {\n\t\tlet result = '';\n\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tresult += Math.floor(rng() * 10).toString();\n\t\t}\n\n\t\treturn result;\n\t}\n}\n","import { pickRandom } from './random';\n\nimport type { DomainsData } from '@/types';\n\nexport class PasswordGenerator {\n\tstatic generate(domains: DomainsData, rng: () => number): string {\n\t\tif (domains.passwordEasterEggs && domains.passwordEasterEggs.length > 0 && rng() < 0.3) {\n\t\t\treturn pickRandom(domains.passwordEasterEggs, rng);\n\t\t}\n\n\t\treturn this.randomPassword(12, rng);\n\t}\n\n\tprivate static randomPassword(length: number, rng: () => number): string {\n\t\tconst chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$';\n\t\tlet result = '';\n\n\t\tfor (let i = 0; i < length; i++) {\n\t\t\tresult += chars[Math.floor(rng() * chars.length)];\n\t\t}\n\n\t\treturn result;\n\t}\n}\n","import { createRng, pickRandom, EmailGenerator, PhoneGenerator, PasswordGenerator } from '@/generators';\n\nimport type { Person, UniverseData, CharacterData } from '@/types';\n\nexport class PersonFactory {\n\tstatic build(universe: UniverseData, seed?: number): Person {\n\t\tconst rng = createRng(seed);\n\n\t\tconst character = pickRandom(universe.characters, rng);\n\n\t\treturn this.buildFromCharacter(character, universe, rng);\n\t}\n\n\tstatic buildByCharacterId(characterId: string, universe: UniverseData, seed?: number): Person {\n\t\tconst character = universe.characters.find((c) => c.id === characterId);\n\n\t\tif (!character) {\n\t\t\tthrow new Error(`Character \"${characterId}\" not found in universe \"${universe.id}\"`);\n\t\t}\n\n\t\tconst rng = createRng(seed);\n\n\t\treturn this.buildFromCharacter(character, universe, rng);\n\t}\n\n\tprivate static buildFromCharacter(character: CharacterData, universe: UniverseData, rng: () => number): Person {\n\t\tconst address = character.address ?? pickRandom(universe.addresses, rng);\n\n\t\tconst username = pickRandom(character.usernames, rng);\n\n\t\tconst domains = character.emailDomain ? { ...universe.domains, emailDomains: [character.emailDomain] } : universe.domains;\n\n\t\tconst email = EmailGenerator.generateFromUsername(username, domains, rng);\n\t\tconst phone = PhoneGenerator.generate(universe.domains, rng);\n\t\tconst password = PasswordGenerator.generate(universe.domains, rng);\n\t\tconst quote = pickRandom(character.quotes, rng);\n\t\tconst avatarName = encodeURIComponent(`${character.firstName} ${character.lastName}`);\n\t\tconst avatar = `https://ui-avatars.com/api/?name=${avatarName}&background=random`;\n\n\t\tconst person: Person = {\n\t\t\tid: crypto.randomUUID(),\n\t\t\tcharacterId: character.id,\n\t\t\tfirstName: character.firstName,\n\t\t\tlastName: character.lastName,\n\t\t\tusername,\n\t\t\temail,\n\t\t\tpassword,\n\t\t\tphone,\n\t\t\taddress: {\n\t\t\t\tstreet: address.street,\n\t\t\t\tcity: address.city,\n\t\t\t\tstate: address.state ?? '',\n\t\t\t\tzip: address.zip ?? '',\n\t\t\t\tcountry: address.country\n\t\t\t},\n\t\t\tprofession: character.profession,\n\t\t\tinterests: character.interests,\n\t\t\tquote,\n\t\t\tuniverse: universe.id,\n\t\t\tuniverseName: universe.name,\n\t\t\tavatar\n\t\t};\n\n\t\treturn person;\n\t}\n}\n","import { UniverseLoader } from '@/universes';\n\nimport { PersonFactory } from './person-factory';\n\nimport type { Person, PersonOptions, GroupOptions, UniverseInfo, UniverseData } from '@/types';\n\nexport class PersonaBuilder {\n\tstatic buildPersonFromData(universe: UniverseData, options: Omit<PersonOptions, 'universe'>): Person {\n\t\treturn PersonFactory.build(universe, options.seed);\n\t}\n\n\tstatic buildPerson(options: PersonOptions): Person {\n\t\tconst universe = UniverseLoader.load(options.universe);\n\n\t\treturn PersonFactory.build(universe, options.seed);\n\t}\n\n\tstatic buildGroup(options: GroupOptions): Person[] {\n\t\tconst persons: Person[] = [];\n\n\t\tfor (let i = 0; i < options.size; i++) {\n\t\t\tconst seed = options.seed !== undefined ? options.seed + i : undefined;\n\n\t\t\tpersons.push(this.buildPerson({ universe: options.universe, seed }));\n\t\t}\n\n\t\treturn persons;\n\t}\n\n\tstatic listUniverses(): UniverseInfo[] {\n\t\tconst ids = UniverseLoader.listAvailable();\n\n\t\tconst result: UniverseInfo[] = ids.map((id) => {\n\t\t\tconst data = UniverseLoader.load(id);\n\n\t\t\tconst info: UniverseInfo = {\n\t\t\t\tid,\n\t\t\t\tname: data.name,\n\t\t\t\tcharacterCount: data.characters.length\n\t\t\t};\n\n\t\t\treturn info;\n\t\t});\n\n\t\treturn result;\n\t}\n}\n","import { createRng } from '@/generators';\n\nimport { PersonFactory } from './person-factory';\n\nimport type { UniverseData, Person, CharacterEntry, CharacterQuery } from '@/types';\n\nexport class UniverseStore {\n\tprivate universes: UniverseData[];\n\tprivate characterIndex: CharacterEntry[];\n\n\tconstructor(universes: UniverseData[]) {\n\t\tthis.universes = universes;\n\t\tthis.characterIndex = this.buildIndex(universes);\n\t}\n\n\tget index(): CharacterEntry[] {\n\t\treturn this.characterIndex;\n\t}\n\n\tgetInterests(universeIds?: string[]): string[] {\n\t\tconst entries =\n\t\t\tuniverseIds && universeIds.length > 0\n\t\t\t\t? this.characterIndex.filter((e) => universeIds.includes(e.universeId))\n\t\t\t\t: this.characterIndex;\n\n\t\tconst interestSet = new Set<string>();\n\n\t\tfor (const entry of entries) {\n\t\t\tfor (const interest of entry.interests) {\n\t\t\t\tinterestSet.add(interest);\n\t\t\t}\n\t\t}\n\n\t\tconst result = Array.from(interestSet).sort();\n\n\t\treturn result;\n\t}\n\n\tgetUniverses(): { id: string; name: string; characterCount: number }[] {\n\t\tconst result = this.universes.map((u) => ({\n\t\t\tid: u.id,\n\t\t\tname: u.name,\n\t\t\tcharacterCount: u.characters.length\n\t\t}));\n\n\t\treturn result;\n\t}\n\n\tfindCharacters(query: CharacterQuery): CharacterEntry[] {\n\t\tlet entries = this.characterIndex;\n\n\t\tif (query.universes && query.universes.length > 0) {\n\t\t\tentries = entries.filter((e) => query.universes!.includes(e.universeId));\n\t\t}\n\n\t\tif (query.name && query.name.trim().length > 0) {\n\t\t\tconst needle = query.name.toLowerCase();\n\n\t\t\tentries = entries.filter((e) => {\n\t\t\t\tconst fullName = `${e.firstName} ${e.lastName}`.toLowerCase();\n\n\t\t\t\treturn fullName.includes(needle);\n\t\t\t});\n\t\t}\n\n\t\tif (query.interests && query.interests.length > 0) {\n\t\t\tconst mode = query.interestsMode ?? 'or';\n\n\t\t\tif (mode === 'and') {\n\t\t\t\tentries = entries.filter((e) => query.interests!.every((interest) => e.interests.includes(interest)));\n\t\t\t} else {\n\t\t\t\tentries = entries.filter((e) => query.interests!.some((interest) => e.interests.includes(interest)));\n\t\t\t}\n\t\t}\n\n\t\treturn entries;\n\t}\n\n\tpersonByCharacterId(characterId: string, seed?: number): Person {\n\t\tconst entry = this.characterIndex.find((e) => e.characterId === characterId);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Character \"${characterId}\" not found in store`);\n\t\t}\n\n\t\tconst universe = this.universes.find((u) => u.id === entry.universeId);\n\n\t\tif (!universe) {\n\t\t\tthrow new Error(`Universe \"${entry.universeId}\" not found in store`);\n\t\t}\n\n\t\treturn PersonFactory.buildByCharacterId(characterId, universe, seed);\n\t}\n\n\tgeneratePersonas(query: CharacterQuery, count: number, seed?: number): Person[] {\n\t\tconst matching = this.findCharacters(query);\n\n\t\tif (matching.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst rng = createRng(seed);\n\t\tconst actualCount = Math.min(count, matching.length);\n\n\t\tconst shuffled = [...matching].sort(() => rng() - 0.5);\n\t\tconst selected = shuffled.slice(0, actualCount);\n\t\tconst personas: Person[] = [];\n\n\t\tfor (let i = 0; i < selected.length; i++) {\n\t\t\tconst entry = selected[i];\n\t\t\tconst universe = this.universes.find((u) => u.id === entry.universeId)!;\n\t\t\tconst personSeed = seed !== undefined ? seed + i : undefined;\n\n\t\t\tpersonas.push(PersonFactory.buildByCharacterId(entry.characterId, universe, personSeed));\n\t\t}\n\n\t\treturn personas;\n\t}\n\n\tprivate buildIndex(universes: UniverseData[]): CharacterEntry[] {\n\t\tconst index: CharacterEntry[] = [];\n\n\t\tfor (const universe of universes) {\n\t\t\tfor (const character of universe.characters) {\n\t\t\t\tconst entry: CharacterEntry = {\n\t\t\t\t\tcharacterId: character.id,\n\t\t\t\t\tuniverseId: universe.id,\n\t\t\t\t\tuniverseName: universe.name,\n\t\t\t\t\tfirstName: character.firstName,\n\t\t\t\t\tlastName: character.lastName,\n\t\t\t\t\tinterests: character.interests,\n\t\t\t\t\tprofession: character.profession\n\t\t\t\t};\n\n\t\t\t\tindex.push(entry);\n\t\t\t}\n\t\t}\n\n\t\treturn index;\n\t}\n}\n"],"mappings":"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","names":["person","universes"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/universes/loader.ts","../src/generators/random.ts","../src/generators/email.ts","../src/engine/person-factory.ts","../src/engine/persona-builder.ts","../src/engine/universe-store.ts"],"sourcesContent":["import { PersonaBuilder } from '@/engine';\n\nimport type { Person, UniverseMeta, PersonOptions, GroupOptions, UniverseData } from '@/types';\n\nexport function person(options: PersonOptions): Person {\n\treturn PersonaBuilder.buildPerson(options);\n}\n\nexport function personFromData(universe: UniverseData, seed?: number): Person {\n\treturn PersonaBuilder.buildPersonFromData(universe, { seed });\n}\n\nexport function group(options: GroupOptions): Person[] {\n\treturn PersonaBuilder.buildGroup(options);\n}\n\nexport function universes(): UniverseMeta[] {\n\treturn PersonaBuilder.listUniverses();\n}\n\nexport { UniverseLoader } from '@/universes';\nexport { UniverseStore, PersonFactory } from '@/engine';\n\nexport type { Person, UniverseMeta, PersonOptions, GroupOptions } from '@/types';\nexport type { Address, UniverseData, CharacterData, AddressData } from '@/types';\nexport type { CharacterEntry, CharacterQuery, LocationEntry, LocationType } from '@/types';\n","import { readFileSync, readdirSync } from 'fs';\nimport { createRequire } from 'module';\nimport { dirname, join } from 'path';\n\nimport type { UniverseData, UniverseMeta, CharacterData, AddressData, CharacterEntry, LocationEntry } from '@/types';\n\nconst require = createRequire(import.meta.url);\nconst packageRoot = dirname(require.resolve('loredata/package.json'));\nconst dataDir = join(packageRoot, 'data');\n\nexport class UniverseLoader {\n\tprivate static cache = new Map<string, UniverseData>();\n\n\tstatic register(data: UniverseData): void {\n\t\tthis.cache.set(data.id, data);\n\t}\n\n\tstatic load(universeId: string): UniverseData {\n\t\tif (process.env.NODE_ENV !== 'development') {\n\t\t\tconst cached = this.cache.get(universeId);\n\n\t\t\tif (cached) {\n\t\t\t\treturn cached;\n\t\t\t}\n\t\t}\n\n\t\tconst universeDir = join(dataDir, universeId);\n\t\tconst meta = JSON.parse(readFileSync(join(universeDir, 'meta.json'), 'utf-8')) as UniverseMeta;\n\n\t\tconst characters = JSON.parse(readFileSync(join(universeDir, 'characters.json'), 'utf-8')) as CharacterData[];\n\n\t\tconst addresses = JSON.parse(readFileSync(join(universeDir, 'addresses.json'), 'utf-8')) as AddressData[];\n\n\t\tconst universeData: UniverseData = {\n\t\t\tid: meta.id,\n\t\t\tname: meta.name,\n\t\t\tgenre: meta.genre,\n\t\t\tdescription: meta.description,\n\t\t\tcharacters,\n\t\t\taddresses,\n\t\t\t...(meta.tmdbId !== undefined && { tmdbId: meta.tmdbId }),\n\t\t\t...(meta.mediaType !== undefined && { mediaType: meta.mediaType }),\n\t\t\t...(meta.rating !== undefined && { rating: meta.rating }),\n\t\t\t...(meta.year !== undefined && { year: meta.year }),\n\t\t\t...(meta.networks !== undefined && { networks: meta.networks }),\n\t\t\t...(meta.posterPath !== undefined && { posterPath: meta.posterPath }),\n\t\t\t...(meta.backdropPath !== undefined && { backdropPath: meta.backdropPath })\n\t\t};\n\n\t\tthis.cache.set(universeId, universeData);\n\n\t\treturn universeData;\n\t}\n\n\tstatic getManifest(): UniverseMeta[] {\n\t\tconst ids = this.listAvailable();\n\n\t\tconst result = ids.map((id) => {\n\t\t\tconst universeDir = join(dataDir, id);\n\n\t\t\treturn JSON.parse(readFileSync(join(universeDir, 'meta.json'), 'utf-8')) as UniverseMeta;\n\t\t});\n\n\t\treturn result;\n\t}\n\n\tstatic getAllInterests(): string[] {\n\t\tconst ids = this.listAvailable();\n\t\tconst interestSet = new Set<string>();\n\n\t\tfor (const id of ids) {\n\t\t\tconst universe = this.load(id);\n\n\t\t\tfor (const character of universe.characters) {\n\t\t\t\tfor (const interest of character.interests) {\n\t\t\t\t\tinterestSet.add(interest);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst result = Array.from(interestSet).sort();\n\n\t\treturn result;\n\t}\n\n\tstatic getAllLocations(): LocationEntry[] {\n\t\tconst ids = this.listAvailable();\n\t\tconst seen = new Map<string, LocationEntry>();\n\n\t\tfor (const id of ids) {\n\t\t\tconst universe = this.load(id);\n\n\t\t\tfor (const address of universe.addresses) {\n\t\t\t\tif (address.city && !seen.has(`city:${address.city}`)) {\n\t\t\t\t\tseen.set(`city:${address.city}`, { name: address.city, type: 'city' });\n\t\t\t\t}\n\n\t\t\t\tif (address.state && !seen.has(`state:${address.state}`)) {\n\t\t\t\t\tseen.set(`state:${address.state}`, { name: address.state, type: 'state' });\n\t\t\t\t}\n\n\t\t\t\tif (address.country && !seen.has(`country:${address.country}`)) {\n\t\t\t\t\tseen.set(`country:${address.country}`, { name: address.country, type: 'country' });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn Array.from(seen.values()).sort((a, b) => a.name.localeCompare(b.name));\n\t}\n\n\tstatic buildCharacterIndex(): CharacterEntry[] {\n\t\tconst ids = this.listAvailable();\n\t\tconst entries: CharacterEntry[] = [];\n\n\t\tfor (const id of ids) {\n\t\t\tconst universe = this.load(id);\n\n\t\t\tfor (const character of universe.characters) {\n\t\t\t\tentries.push({\n\t\t\t\t\tcharacterId: character.id,\n\t\t\t\t\tuniverseId: universe.id,\n\t\t\t\t\tuniverseName: universe.name,\n\t\t\t\t\tfirstName: character.firstName ?? '',\n\t\t\t\t\tlastName: character.lastName ?? '',\n\t\t\t\t\tinterests: character.interests,\n\t\t\t\t\tprofession: character.profession\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn entries;\n\t}\n\n\tstatic listAvailable(): string[] {\n\t\tconst entries = readdirSync(dataDir, { withFileTypes: true });\n\n\t\tconst ids = entries\n\t\t\t.filter((entry) => {\n\t\t\t\tif (!entry.isDirectory()) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\treadFileSync(join(dataDir, entry.name, 'meta.json'), 'utf-8');\n\n\t\t\t\t\treturn true;\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t})\n\t\t\t.map((entry) => entry.name);\n\n\t\treturn ids;\n\t}\n}\n","/**\n * Seeded pseudo-random number generator (mulberry32).\n * Returns a function that produces values in [0, 1).\n */\nexport function createRng(seed?: number): () => number {\n\tif (seed === undefined) {\n\t\treturn Math.random;\n\t}\n\n\tlet s = seed;\n\n\treturn function rng(): number {\n\t\ts += 0x6d2b79f5;\n\t\tlet z = s;\n\t\tz = Math.imul(z ^ (z >>> 15), z | 1);\n\t\tz ^= z + Math.imul(z ^ (z >>> 7), z | 61);\n\n\t\treturn ((z ^ (z >>> 14)) >>> 0) / 4294967296;\n\t};\n}\n\nexport function pickRandom<T>(array: T[], rng: () => number): T {\n\tconst index = Math.floor(rng() * array.length);\n\n\treturn array[index];\n}\n","import { pickRandom } from './random';\n\nexport class EmailGenerator {\n\tstatic generateFromUsername(username: string, emailDomains: string[], rng: () => number): string {\n\t\tconst domain = pickRandom(emailDomains, rng);\n\n\t\treturn `${username}@${domain}`;\n\t}\n}\n","import { createRng, pickRandom, EmailGenerator } from '@/generators';\n\nimport type { Person, UniverseData, CharacterData } from '@/types';\n\nexport class PersonFactory {\n\tstatic build(universe: UniverseData, seed?: number): Person {\n\t\tconst rng = createRng(seed);\n\n\t\tconst character = pickRandom(universe.characters, rng);\n\n\t\treturn this.buildFromCharacter(character, universe, rng);\n\t}\n\n\tstatic buildByCharacterId(characterId: string, universe: UniverseData, seed?: number): Person {\n\t\tconst character = universe.characters.find((c) => c.id === characterId);\n\n\t\tif (!character) {\n\t\t\tthrow new Error(`Character \"${characterId}\" not found in universe \"${universe.id}\"`);\n\t\t}\n\n\t\tconst rng = createRng(seed);\n\n\t\treturn this.buildFromCharacter(character, universe, rng);\n\t}\n\n\tstatic buildCanonical(characterId: string, universe: UniverseData): Person {\n\t\tconst character = universe.characters.find((c) => c.id === characterId);\n\n\t\tif (!character) {\n\t\t\tthrow new Error(`Character \"${characterId}\" not found in universe \"${universe.id}\"`);\n\t\t}\n\n\t\tconst address = character.address ?? universe.addresses[0];\n\t\tconst username = character.usernames[0];\n\t\tconst rng = createRng(0);\n\t\tconst email = EmailGenerator.generateFromUsername(username, character.emailDomains, rng);\n\t\tconst quote = character.quotes[0];\n\n\t\tconst person: Person = {\n\t\t\tid: crypto.randomUUID(),\n\t\t\tcharacterId: character.id,\n\t\t\tfirstName: character.firstName,\n\t\t\tlastName: character.lastName,\n\t\t\tusername,\n\t\t\temail,\n\t\t\taddress: {\n\t\t\t\tstreet: address.street,\n\t\t\t\tcity: address.city,\n\t\t\t\tstate: address.state ?? '',\n\t\t\t\tzip: address.zip ?? '',\n\t\t\t\tcountry: address.country\n\t\t\t},\n\t\t\tprofession: character.profession,\n\t\t\tinterests: character.interests,\n\t\t\tquote,\n\t\t\tuniverse: universe.id,\n\t\t\tuniverseName: universe.name,\n\t\t\t...(character.symbol ? { symbol: character.symbol } : {}),\n\t\t\t...(character.color ? { color: character.color } : {})\n\t\t};\n\n\t\treturn person;\n\t}\n\n\tprivate static buildFromCharacter(character: CharacterData, universe: UniverseData, rng: () => number): Person {\n\t\tconst address = character.address ?? pickRandom(universe.addresses, rng);\n\t\tconst username = pickRandom(character.usernames, rng);\n\t\tconst email = EmailGenerator.generateFromUsername(username, character.emailDomains, rng);\n\t\tconst quote = pickRandom(character.quotes, rng);\n\n\t\tconst person: Person = {\n\t\t\tid: crypto.randomUUID(),\n\t\t\tcharacterId: character.id,\n\t\t\tfirstName: character.firstName,\n\t\t\tlastName: character.lastName,\n\t\t\tusername,\n\t\t\temail,\n\t\t\taddress: {\n\t\t\t\tstreet: address.street,\n\t\t\t\tcity: address.city,\n\t\t\t\tstate: address.state ?? '',\n\t\t\t\tzip: address.zip ?? '',\n\t\t\t\tcountry: address.country\n\t\t\t},\n\t\t\tprofession: character.profession,\n\t\t\tinterests: character.interests,\n\t\t\tquote,\n\t\t\tuniverse: universe.id,\n\t\t\tuniverseName: universe.name,\n\t\t\t...(character.symbol ? { symbol: character.symbol } : {}),\n\t\t\t...(character.color ? { color: character.color } : {})\n\t\t};\n\n\t\treturn person;\n\t}\n}\n","import { UniverseLoader } from '@/universes';\n\nimport { PersonFactory } from './person-factory';\n\nimport type { Person, PersonOptions, GroupOptions, UniverseMeta, UniverseData } from '@/types';\n\nexport class PersonaBuilder {\n\tstatic buildPersonFromData(universe: UniverseData, options: Omit<PersonOptions, 'universe'>): Person {\n\t\treturn PersonFactory.build(universe, options.seed);\n\t}\n\n\tstatic buildPerson(options: PersonOptions): Person {\n\t\tconst universe = UniverseLoader.load(options.universe);\n\n\t\treturn PersonFactory.build(universe, options.seed);\n\t}\n\n\tstatic buildGroup(options: GroupOptions): Person[] {\n\t\tconst persons: Person[] = [];\n\n\t\tfor (let i = 0; i < options.size; i++) {\n\t\t\tconst seed = options.seed !== undefined ? options.seed + i : undefined;\n\n\t\t\tpersons.push(this.buildPerson({ universe: options.universe, seed }));\n\t\t}\n\n\t\treturn persons;\n\t}\n\n\tstatic listUniverses(): UniverseMeta[] {\n\t\tconst ids = UniverseLoader.listAvailable();\n\n\t\tconst result: UniverseMeta[] = ids.map((id) => {\n\t\t\tconst data = UniverseLoader.load(id);\n\n\t\t\tconst meta: UniverseMeta = {\n\t\t\t\tid,\n\t\t\t\tname: data.name,\n\t\t\t\tgenre: data.genre,\n\t\t\t\tdescription: data.description\n\t\t\t};\n\n\t\t\treturn meta;\n\t\t});\n\n\t\treturn result;\n\t}\n}\n","import { createRng } from '@/generators';\n\nimport { PersonFactory } from './person-factory';\n\nimport type { UniverseData, UniverseMeta, Person, CharacterEntry, CharacterQuery } from '@/types';\n\nexport class UniverseStore {\n\tprivate universes: UniverseData[];\n\tprivate characterIndex: CharacterEntry[];\n\n\tconstructor(universes: UniverseData[]) {\n\t\tthis.universes = universes;\n\t\tthis.characterIndex = this.buildIndex(universes);\n\t}\n\n\tget index(): CharacterEntry[] {\n\t\treturn this.characterIndex;\n\t}\n\n\tgetInterests(universeIds?: string[]): string[] {\n\t\tconst entries =\n\t\t\tuniverseIds && universeIds.length > 0\n\t\t\t\t? this.characterIndex.filter((e) => universeIds.includes(e.universeId))\n\t\t\t\t: this.characterIndex;\n\n\t\tconst interestSet = new Set<string>();\n\n\t\tfor (const entry of entries) {\n\t\t\tfor (const interest of entry.interests) {\n\t\t\t\tinterestSet.add(interest);\n\t\t\t}\n\t\t}\n\n\t\tconst result = Array.from(interestSet).sort();\n\n\t\treturn result;\n\t}\n\n\tgetUniverses(): UniverseMeta[] {\n\t\tconst result = this.universes.map((u) => {\n\t\t\tconst meta: UniverseMeta = {\n\t\t\t\tid: u.id,\n\t\t\t\tname: u.name,\n\t\t\t\tgenre: u.genre,\n\t\t\t\tdescription: u.description\n\t\t\t};\n\n\t\t\treturn meta;\n\t\t});\n\n\t\treturn result;\n\t}\n\n\tfindCharacters(query: CharacterQuery): CharacterEntry[] {\n\t\tlet entries = this.characterIndex;\n\n\t\tif (query.universes && query.universes.length > 0) {\n\t\t\tentries = entries.filter((e) => query.universes!.includes(e.universeId));\n\t\t}\n\n\t\tif (query.name && query.name.trim().length > 0) {\n\t\t\tconst needle = query.name.toLowerCase();\n\n\t\t\tentries = entries.filter((e) => {\n\t\t\t\tconst fullName = `${e.firstName} ${e.lastName}`.toLowerCase();\n\n\t\t\t\treturn fullName.includes(needle);\n\t\t\t});\n\t\t}\n\n\t\tif (query.interests && query.interests.length > 0) {\n\t\t\tconst mode = query.interestsMode ?? 'or';\n\n\t\t\tif (mode === 'and') {\n\t\t\t\tentries = entries.filter((e) => query.interests!.every((interest) => e.interests.includes(interest)));\n\t\t\t} else {\n\t\t\t\tentries = entries.filter((e) => query.interests!.some((interest) => e.interests.includes(interest)));\n\t\t\t}\n\t\t}\n\n\t\treturn entries;\n\t}\n\n\tpersonByCharacterId(characterId: string, seed?: number): Person {\n\t\tconst entry = this.characterIndex.find((e) => e.characterId === characterId);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Character \"${characterId}\" not found in store`);\n\t\t}\n\n\t\tconst universe = this.universes.find((u) => u.id === entry.universeId);\n\n\t\tif (!universe) {\n\t\t\tthrow new Error(`Universe \"${entry.universeId}\" not found in store`);\n\t\t}\n\n\t\treturn PersonFactory.buildByCharacterId(characterId, universe, seed);\n\t}\n\n\tgeneratePersonas(query: CharacterQuery, count: number, seed?: number): Person[] {\n\t\tconst matching = this.findCharacters(query);\n\n\t\tif (matching.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst rng = createRng(seed);\n\t\tconst actualCount = Math.min(count, matching.length);\n\n\t\tconst shuffled = [...matching].sort(() => rng() - 0.5);\n\t\tconst selected = shuffled.slice(0, actualCount);\n\t\tconst personas: Person[] = [];\n\n\t\tfor (let i = 0; i < selected.length; i++) {\n\t\t\tconst entry = selected[i];\n\t\t\tconst universe = this.universes.find((u) => u.id === entry.universeId)!;\n\t\t\tconst personSeed = seed !== undefined ? seed + i : undefined;\n\n\t\t\tpersonas.push(PersonFactory.buildByCharacterId(entry.characterId, universe, personSeed));\n\t\t}\n\n\t\treturn personas;\n\t}\n\n\tprivate buildIndex(universes: UniverseData[]): CharacterEntry[] {\n\t\tconst index: CharacterEntry[] = [];\n\n\t\tfor (const universe of universes) {\n\t\t\tfor (const character of universe.characters) {\n\t\t\t\tconst entry: CharacterEntry = {\n\t\t\t\t\tcharacterId: character.id,\n\t\t\t\t\tuniverseId: universe.id,\n\t\t\t\t\tuniverseName: universe.name,\n\t\t\t\t\tfirstName: character.firstName,\n\t\t\t\t\tlastName: character.lastName,\n\t\t\t\t\tinterests: character.interests,\n\t\t\t\t\tprofession: character.profession\n\t\t\t\t};\n\n\t\t\t\tindex.push(entry);\n\t\t\t}\n\t\t}\n\n\t\treturn index;\n\t}\n}\n"],"mappings":"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","names":["require","person","universes"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { U as UniverseData, P as Person, d as UniverseInfo } from './universe-store-DJrm7bP7.cjs';
2
- export { A as Address, a as AddressData, C as CharacterData, b as CharacterEntry, c as CharacterQuery, D as DomainsData, e as UniverseStore } from './universe-store-DJrm7bP7.cjs';
1
+ import { a as UniverseData, U as UniverseMeta, L as LocationEntry, c as CharacterEntry, P as Person } from './universe-store-CWhCn3U6.cjs';
2
+ export { A as Address, b as AddressData, C as CharacterData, d as CharacterQuery, f as LocationType, e as UniverseStore } from './universe-store-CWhCn3U6.cjs';
3
3
 
4
4
  interface PersonOptions {
5
5
  universe: string;
@@ -15,12 +15,23 @@ declare class UniverseLoader {
15
15
  private static cache;
16
16
  static register(data: UniverseData): void;
17
17
  static load(universeId: string): UniverseData;
18
+ static getManifest(): UniverseMeta[];
19
+ static getAllInterests(): string[];
20
+ static getAllLocations(): LocationEntry[];
21
+ static buildCharacterIndex(): CharacterEntry[];
18
22
  static listAvailable(): string[];
19
23
  }
20
24
 
25
+ declare class PersonFactory {
26
+ static build(universe: UniverseData, seed?: number): Person;
27
+ static buildByCharacterId(characterId: string, universe: UniverseData, seed?: number): Person;
28
+ static buildCanonical(characterId: string, universe: UniverseData): Person;
29
+ private static buildFromCharacter;
30
+ }
31
+
21
32
  declare function person(options: PersonOptions): Person;
22
33
  declare function personFromData(universe: UniverseData, seed?: number): Person;
23
34
  declare function group(options: GroupOptions): Person[];
24
- declare function universes(): UniverseInfo[];
35
+ declare function universes(): UniverseMeta[];
25
36
 
26
- export { type GroupOptions, Person, type PersonOptions, UniverseData, UniverseInfo, UniverseLoader, group, person, personFromData, universes };
37
+ export { CharacterEntry, type GroupOptions, LocationEntry, Person, PersonFactory, type PersonOptions, UniverseData, UniverseLoader, UniverseMeta, group, person, personFromData, universes };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { U as UniverseData, P as Person, d as UniverseInfo } from './universe-store-DJrm7bP7.js';
2
- export { A as Address, a as AddressData, C as CharacterData, b as CharacterEntry, c as CharacterQuery, D as DomainsData, e as UniverseStore } from './universe-store-DJrm7bP7.js';
1
+ import { a as UniverseData, U as UniverseMeta, L as LocationEntry, c as CharacterEntry, P as Person } from './universe-store-CWhCn3U6.js';
2
+ export { A as Address, b as AddressData, C as CharacterData, d as CharacterQuery, f as LocationType, e as UniverseStore } from './universe-store-CWhCn3U6.js';
3
3
 
4
4
  interface PersonOptions {
5
5
  universe: string;
@@ -15,12 +15,23 @@ declare class UniverseLoader {
15
15
  private static cache;
16
16
  static register(data: UniverseData): void;
17
17
  static load(universeId: string): UniverseData;
18
+ static getManifest(): UniverseMeta[];
19
+ static getAllInterests(): string[];
20
+ static getAllLocations(): LocationEntry[];
21
+ static buildCharacterIndex(): CharacterEntry[];
18
22
  static listAvailable(): string[];
19
23
  }
20
24
 
25
+ declare class PersonFactory {
26
+ static build(universe: UniverseData, seed?: number): Person;
27
+ static buildByCharacterId(characterId: string, universe: UniverseData, seed?: number): Person;
28
+ static buildCanonical(characterId: string, universe: UniverseData): Person;
29
+ private static buildFromCharacter;
30
+ }
31
+
21
32
  declare function person(options: PersonOptions): Person;
22
33
  declare function personFromData(universe: UniverseData, seed?: number): Person;
23
34
  declare function group(options: GroupOptions): Person[];
24
- declare function universes(): UniverseInfo[];
35
+ declare function universes(): UniverseMeta[];
25
36
 
26
- export { type GroupOptions, Person, type PersonOptions, UniverseData, UniverseInfo, UniverseLoader, group, person, personFromData, universes };
37
+ export { CharacterEntry, type GroupOptions, LocationEntry, Person, PersonFactory, type PersonOptions, UniverseData, UniverseLoader, UniverseMeta, group, person, personFromData, universes };