loredata 0.2.0 → 0.4.1
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/README.md +126 -65
- package/data/avengers/addresses.json +27 -0
- package/data/avengers/characters.json +305 -0
- package/data/avengers/meta.json +13 -0
- package/data/better-call-saul/addresses.json +37 -0
- package/data/better-call-saul/characters.json +268 -0
- package/data/better-call-saul/meta.json +13 -0
- package/data/big-bang-theory/addresses.json +31 -0
- package/data/big-bang-theory/characters.json +198 -0
- package/data/big-bang-theory/meta.json +13 -0
- package/data/breaking-bad/characters.json +249 -148
- package/data/breaking-bad/meta.json +8 -1
- package/data/fast-and-furious/addresses.json +1 -2
- package/data/fast-and-furious/characters.json +226 -133
- package/data/fast-and-furious/meta.json +13 -1
- package/data/friends/characters.json +402 -281
- package/data/friends/meta.json +8 -1
- package/data/game-of-thrones/addresses.json +6 -22
- package/data/game-of-thrones/characters.json +507 -299
- package/data/game-of-thrones/meta.json +8 -1
- package/data/guardians-of-the-galaxy/addresses.json +17 -0
- package/data/guardians-of-the-galaxy/characters.json +226 -0
- package/data/guardians-of-the-galaxy/meta.json +13 -0
- package/data/harry-potter/addresses.json +6 -11
- package/data/harry-potter/characters.json +239 -147
- package/data/harry-potter/meta.json +8 -1
- package/data/house-md/characters.json +184 -52
- package/data/house-md/meta.json +8 -1
- package/data/lost/characters.json +420 -299
- package/data/lost/meta.json +8 -1
- package/data/matrix/characters.json +144 -34
- package/data/matrix/meta.json +13 -1
- package/data/peaky-blinders/characters.json +191 -37
- package/data/peaky-blinders/meta.json +8 -1
- package/data/prison-break/addresses.json +24 -0
- package/data/prison-break/characters.json +188 -0
- package/data/prison-break/meta.json +13 -0
- package/data/sherlock/characters.json +369 -263
- package/data/sherlock/meta.json +8 -1
- package/data/simpsons/addresses.json +21 -0
- package/data/simpsons/characters.json +383 -0
- package/data/simpsons/meta.json +13 -0
- package/data/sopranos/addresses.json +37 -0
- package/data/sopranos/characters.json +292 -0
- package/data/sopranos/meta.json +13 -0
- package/data/south-park/addresses.json +31 -0
- package/data/south-park/characters.json +372 -0
- package/data/south-park/meta.json +13 -0
- package/data/spider-man/addresses.json +31 -0
- package/data/spider-man/characters.json +219 -0
- package/data/spider-man/meta.json +13 -0
- package/data/star-wars/addresses.json +19 -0
- package/data/star-wars/characters.json +254 -0
- package/data/star-wars/meta.json +13 -0
- package/data/stranger-things/addresses.json +31 -0
- package/data/stranger-things/characters.json +226 -0
- package/data/stranger-things/meta.json +13 -0
- package/data/supernatural/addresses.json +25 -0
- package/data/supernatural/characters.json +190 -0
- package/data/supernatural/meta.json +13 -0
- package/data/the-crown/addresses.json +27 -0
- package/data/the-crown/characters.json +275 -0
- package/data/the-crown/meta.json +13 -0
- package/data/the-office/characters.json +478 -283
- package/data/the-office/meta.json +8 -1
- package/data/the-walking-dead/addresses.json +25 -0
- package/data/the-walking-dead/characters.json +186 -0
- package/data/the-walking-dead/meta.json +13 -0
- package/data/the-witcher/addresses.json +22 -0
- package/data/the-witcher/characters.json +272 -0
- package/data/the-witcher/meta.json +13 -0
- package/data/vikings/addresses.json +26 -0
- package/data/vikings/characters.json +240 -0
- package/data/vikings/meta.json +13 -0
- package/data/westworld/addresses.json +19 -0
- package/data/westworld/characters.json +161 -0
- package/data/westworld/meta.json +13 -0
- package/data/x-men/addresses.json +24 -0
- package/data/x-men/characters.json +242 -0
- package/data/x-men/meta.json +18 -0
- package/dist/browser.cjs +18 -72
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +3 -3
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +18 -72
- package/dist/browser.js.map +1 -1
- package/dist/cli/cli.cjs +41 -73
- package/dist/cli/cli.cjs.map +1 -1
- package/dist/cli/cli.js +41 -73
- package/dist/cli/cli.js.map +1 -1
- package/dist/index.cjs +41 -72
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +41 -72
- package/dist/index.js.map +1 -1
- package/dist/{universe-store-Del1UHgn.d.cts → universe-store-CWhCn3U6.d.cts} +21 -11
- package/dist/{universe-store-Del1UHgn.d.ts → universe-store-CWhCn3U6.d.ts} +21 -11
- package/package.json +85 -81
- package/data/breaking-bad/domains.json +0 -6
- package/data/fast-and-furious/domains.json +0 -6
- package/data/friends/domains.json +0 -6
- package/data/game-of-thrones/domains.json +0 -6
- package/data/harry-potter/domains.json +0 -6
- package/data/house-md/domains.json +0 -6
- package/data/lost/domains.json +0 -6
- package/data/matrix/domains.json +0 -6
- package/data/peaky-blinders/domains.json +0 -6
- package/data/sherlock/domains.json +0 -6
- package/data/the-office/domains.json +0 -6
package/dist/browser.js
CHANGED
|
@@ -19,55 +19,12 @@ function pickRandom(array, rng) {
|
|
|
19
19
|
|
|
20
20
|
// src/generators/email.ts
|
|
21
21
|
var EmailGenerator = class {
|
|
22
|
-
static
|
|
23
|
-
const domain = pickRandom(
|
|
24
|
-
const first = firstName.toLowerCase();
|
|
25
|
-
const last = lastName.toLowerCase();
|
|
26
|
-
return `${first}.${last}@${domain}`;
|
|
27
|
-
}
|
|
28
|
-
static generateFromUsername(username, domains, rng) {
|
|
29
|
-
const domain = pickRandom(domains.emailDomains, rng);
|
|
22
|
+
static generateFromUsername(username, emailDomains, rng) {
|
|
23
|
+
const domain = pickRandom(emailDomains, rng);
|
|
30
24
|
return `${username}@${domain}`;
|
|
31
25
|
}
|
|
32
26
|
};
|
|
33
27
|
|
|
34
|
-
// src/generators/phone.ts
|
|
35
|
-
var PhoneGenerator = class {
|
|
36
|
-
static generate(domains, rng) {
|
|
37
|
-
if (domains.phoneEasterEggs && domains.phoneEasterEggs.length > 0 && rng() < 0.2) {
|
|
38
|
-
return pickRandom(domains.phoneEasterEggs, rng);
|
|
39
|
-
}
|
|
40
|
-
const prefix = pickRandom(domains.phonePrefixes, rng);
|
|
41
|
-
const suffix = this.randomDigits(7, rng);
|
|
42
|
-
return `${prefix}-${suffix.slice(0, 3)}-${suffix.slice(3)}`;
|
|
43
|
-
}
|
|
44
|
-
static randomDigits(count, rng) {
|
|
45
|
-
let result = "";
|
|
46
|
-
for (let i = 0; i < count; i++) {
|
|
47
|
-
result += Math.floor(rng() * 10).toString();
|
|
48
|
-
}
|
|
49
|
-
return result;
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
// src/generators/password.ts
|
|
54
|
-
var PasswordGenerator = class {
|
|
55
|
-
static generate(domains, rng) {
|
|
56
|
-
if (domains.passwordEasterEggs && domains.passwordEasterEggs.length > 0 && rng() < 0.3) {
|
|
57
|
-
return pickRandom(domains.passwordEasterEggs, rng);
|
|
58
|
-
}
|
|
59
|
-
return this.randomPassword(12, rng);
|
|
60
|
-
}
|
|
61
|
-
static randomPassword(length, rng) {
|
|
62
|
-
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$";
|
|
63
|
-
let result = "";
|
|
64
|
-
for (let i = 0; i < length; i++) {
|
|
65
|
-
result += chars[Math.floor(rng() * chars.length)];
|
|
66
|
-
}
|
|
67
|
-
return result;
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
|
|
71
28
|
// src/engine/person-factory.ts
|
|
72
29
|
var PersonFactory = class {
|
|
73
30
|
static build(universe, seed) {
|
|
@@ -90,11 +47,8 @@ var PersonFactory = class {
|
|
|
90
47
|
}
|
|
91
48
|
const address = character.address ?? universe.addresses[0];
|
|
92
49
|
const username = character.usernames[0];
|
|
93
|
-
const domains = character.emailDomain ? { ...universe.domains, emailDomains: [character.emailDomain] } : universe.domains;
|
|
94
50
|
const rng = createRng(0);
|
|
95
|
-
const email = EmailGenerator.generateFromUsername(username,
|
|
96
|
-
const phone = PhoneGenerator.generate(universe.domains, rng);
|
|
97
|
-
const password = PasswordGenerator.generate(universe.domains, rng);
|
|
51
|
+
const email = EmailGenerator.generateFromUsername(username, character.emailDomains, rng);
|
|
98
52
|
const quote = character.quotes[0];
|
|
99
53
|
const person = {
|
|
100
54
|
id: crypto.randomUUID(),
|
|
@@ -103,8 +57,6 @@ var PersonFactory = class {
|
|
|
103
57
|
lastName: character.lastName,
|
|
104
58
|
username,
|
|
105
59
|
email,
|
|
106
|
-
password,
|
|
107
|
-
phone,
|
|
108
60
|
address: {
|
|
109
61
|
street: address.street,
|
|
110
62
|
city: address.city,
|
|
@@ -125,10 +77,7 @@ var PersonFactory = class {
|
|
|
125
77
|
static buildFromCharacter(character, universe, rng) {
|
|
126
78
|
const address = character.address ?? pickRandom(universe.addresses, rng);
|
|
127
79
|
const username = pickRandom(character.usernames, rng);
|
|
128
|
-
const
|
|
129
|
-
const email = EmailGenerator.generateFromUsername(username, domains, rng);
|
|
130
|
-
const phone = PhoneGenerator.generate(universe.domains, rng);
|
|
131
|
-
const password = PasswordGenerator.generate(universe.domains, rng);
|
|
80
|
+
const email = EmailGenerator.generateFromUsername(username, character.emailDomains, rng);
|
|
132
81
|
const quote = pickRandom(character.quotes, rng);
|
|
133
82
|
const person = {
|
|
134
83
|
id: crypto.randomUUID(),
|
|
@@ -137,8 +86,6 @@ var PersonFactory = class {
|
|
|
137
86
|
lastName: character.lastName,
|
|
138
87
|
username,
|
|
139
88
|
email,
|
|
140
|
-
password,
|
|
141
|
-
phone,
|
|
142
89
|
address: {
|
|
143
90
|
street: address.street,
|
|
144
91
|
city: address.city,
|
|
@@ -267,7 +214,6 @@ var UniverseStore = class {
|
|
|
267
214
|
var metaModules = import.meta.glob("../data/*/meta.json", { eager: false });
|
|
268
215
|
var characterModules = import.meta.glob("../data/*/characters.json", { eager: false });
|
|
269
216
|
var addressModules = import.meta.glob("../data/*/addresses.json", { eager: false });
|
|
270
|
-
var domainModules = import.meta.glob("../data/*/domains.json", { eager: false });
|
|
271
217
|
function extractId(path) {
|
|
272
218
|
const parts = path.split("/");
|
|
273
219
|
return parts[parts.length - 2];
|
|
@@ -300,32 +246,27 @@ async function loadUniverse(id) {
|
|
|
300
246
|
const metaPath = `../data/${id}/meta.json`;
|
|
301
247
|
const charactersPath = `../data/${id}/characters.json`;
|
|
302
248
|
const addressesPath = `../data/${id}/addresses.json`;
|
|
303
|
-
const domainsPath = `../data/${id}/domains.json`;
|
|
304
249
|
const metaLoader = metaModules[metaPath];
|
|
305
250
|
const charactersLoader = characterModules[charactersPath];
|
|
306
251
|
const addressesLoader = addressModules[addressesPath];
|
|
307
|
-
|
|
308
|
-
if (!metaLoader || !charactersLoader || !addressesLoader || !domainsLoader) {
|
|
252
|
+
if (!metaLoader || !charactersLoader || !addressesLoader) {
|
|
309
253
|
throw new Error(`Universe "${id}" not found`);
|
|
310
254
|
}
|
|
311
|
-
const [metaModule, charactersModule, addressesModule
|
|
255
|
+
const [metaModule, charactersModule, addressesModule] = await Promise.all([
|
|
312
256
|
metaLoader(),
|
|
313
257
|
charactersLoader(),
|
|
314
|
-
addressesLoader()
|
|
315
|
-
domainsLoader()
|
|
258
|
+
addressesLoader()
|
|
316
259
|
]);
|
|
317
260
|
const meta = metaModule.default;
|
|
318
261
|
const characters = charactersModule.default;
|
|
319
262
|
const addresses = addressesModule.default;
|
|
320
|
-
const domains = domainsModule.default;
|
|
321
263
|
const universeData = {
|
|
322
264
|
id: meta.id,
|
|
323
265
|
name: meta.name,
|
|
324
266
|
genre: meta.genre,
|
|
325
267
|
description: meta.description,
|
|
326
268
|
characters,
|
|
327
|
-
addresses
|
|
328
|
-
domains
|
|
269
|
+
addresses
|
|
329
270
|
};
|
|
330
271
|
return universeData;
|
|
331
272
|
}
|
|
@@ -352,16 +293,21 @@ async function getAllInterests() {
|
|
|
352
293
|
}
|
|
353
294
|
async function getAllLocations() {
|
|
354
295
|
const universes = await loadAllUniverses();
|
|
355
|
-
const
|
|
296
|
+
const seen = /* @__PURE__ */ new Map();
|
|
356
297
|
for (const universe of universes) {
|
|
357
298
|
for (const address of universe.addresses) {
|
|
358
|
-
if (address.city) {
|
|
359
|
-
|
|
299
|
+
if (address.city && !seen.has(`city:${address.city}`)) {
|
|
300
|
+
seen.set(`city:${address.city}`, { name: address.city, type: "city" });
|
|
301
|
+
}
|
|
302
|
+
if (address.state && !seen.has(`state:${address.state}`)) {
|
|
303
|
+
seen.set(`state:${address.state}`, { name: address.state, type: "state" });
|
|
304
|
+
}
|
|
305
|
+
if (address.country && !seen.has(`country:${address.country}`)) {
|
|
306
|
+
seen.set(`country:${address.country}`, { name: address.country, type: "country" });
|
|
360
307
|
}
|
|
361
308
|
}
|
|
362
309
|
}
|
|
363
|
-
|
|
364
|
-
return result;
|
|
310
|
+
return Array.from(seen.values()).sort((a, b) => a.name.localeCompare(b.name));
|
|
365
311
|
}
|
|
366
312
|
|
|
367
313
|
// src/browser.ts
|
package/dist/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/generators/random.ts","../src/generators/email.ts","../src/generators/phone.ts","../src/generators/password.ts","../src/engine/person-factory.ts","../src/engine/universe-store.ts","../src/universes/browser-loader.ts","../src/browser.ts"],"sourcesContent":["/**\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\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 domains = character.emailDomain ? { ...universe.domains, emailDomains: [character.emailDomain] } : universe.domains;\n\t\tconst rng = createRng(0);\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 = 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\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\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\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\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\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 { 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","import type { UniverseData, UniverseMeta, CharacterData, AddressData, DomainsData } from '@/types';\n\ninterface MetaJson {\n\tid: string;\n\tname: string;\n\tgenre: string[];\n\tdescription: string;\n}\n\nconst metaModules = import.meta.glob('../data/*/meta.json', { eager: false });\nconst characterModules = import.meta.glob('../data/*/characters.json', { eager: false });\nconst addressModules = import.meta.glob('../data/*/addresses.json', { eager: false });\nconst domainModules = import.meta.glob('../data/*/domains.json', { eager: false });\n\nfunction extractId(path: string): string {\n\tconst parts = path.split('/');\n\n\treturn parts[parts.length - 2];\n}\n\nexport function getAvailableIds(): string[] {\n\treturn Object.keys(metaModules).map(extractId);\n}\n\nexport async function loadUniverseMeta(id: string): Promise<UniverseMeta> {\n\tconst metaPath = `../data/${id}/meta.json`;\n\tconst metaLoader = metaModules[metaPath];\n\n\tif (!metaLoader) {\n\t\tthrow new Error(`Universe \"${id}\" not found`);\n\t}\n\n\tconst metaModule = await metaLoader();\n\tconst meta = (metaModule as { default: MetaJson }).default;\n\n\tconst result: UniverseMeta = {\n\t\tid: meta.id,\n\t\tname: meta.name,\n\t\tgenre: meta.genre,\n\t\tdescription: meta.description\n\t};\n\n\treturn result;\n}\n\nexport async function getManifest(): Promise<UniverseMeta[]> {\n\tconst ids = getAvailableIds();\n\tconst result = await Promise.all(ids.map((id) => loadUniverseMeta(id)));\n\n\treturn result;\n}\n\nexport async function loadUniverse(id: string): Promise<UniverseData> {\n\tconst metaPath = `../data/${id}/meta.json`;\n\tconst charactersPath = `../data/${id}/characters.json`;\n\tconst addressesPath = `../data/${id}/addresses.json`;\n\tconst domainsPath = `../data/${id}/domains.json`;\n\n\tconst metaLoader = metaModules[metaPath];\n\tconst charactersLoader = characterModules[charactersPath];\n\tconst addressesLoader = addressModules[addressesPath];\n\tconst domainsLoader = domainModules[domainsPath];\n\n\tif (!metaLoader || !charactersLoader || !addressesLoader || !domainsLoader) {\n\t\tthrow new Error(`Universe \"${id}\" not found`);\n\t}\n\n\tconst [metaModule, charactersModule, addressesModule, domainsModule] = await Promise.all([\n\t\tmetaLoader(),\n\t\tcharactersLoader(),\n\t\taddressesLoader(),\n\t\tdomainsLoader()\n\t]);\n\n\tconst meta = (metaModule as { default: MetaJson }).default;\n\tconst characters = (charactersModule as { default: CharacterData[] }).default;\n\tconst addresses = (addressesModule as { default: AddressData[] }).default;\n\tconst domains = (domainsModule as { default: DomainsData }).default;\n\n\tconst universeData: UniverseData = {\n\t\tid: meta.id,\n\t\tname: meta.name,\n\t\tgenre: meta.genre,\n\t\tdescription: meta.description,\n\t\tcharacters,\n\t\taddresses,\n\t\tdomains\n\t};\n\n\treturn universeData;\n}\n\nexport async function loadUniverses(ids: string[]): Promise<UniverseData[]> {\n\tconst result = await Promise.all(ids.map((id) => loadUniverse(id)));\n\n\treturn result;\n}\n\nexport async function loadAllUniverses(): Promise<UniverseData[]> {\n\tconst ids = getAvailableIds();\n\n\treturn loadUniverses(ids);\n}\n\nexport async function getAllInterests(): Promise<string[]> {\n\tconst universes = await loadAllUniverses();\n\tconst interestSet = new Set<string>();\n\n\tfor (const universe of universes) {\n\t\tfor (const character of universe.characters) {\n\t\t\tfor (const interest of character.interests) {\n\t\t\t\tinterestSet.add(interest);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst result = Array.from(interestSet).sort();\n\n\treturn result;\n}\n\nexport async function getAllLocations(): Promise<string[]> {\n\tconst universes = await loadAllUniverses();\n\tconst citySet = new Set<string>();\n\n\tfor (const universe of universes) {\n\t\tfor (const address of universe.addresses) {\n\t\t\tif (address.city) {\n\t\t\t\tcitySet.add(address.city);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst result = Array.from(citySet).sort();\n\n\treturn result;\n}\n","import { PersonFactory } from '@/engine/person-factory';\nimport { UniverseStore } from '@/engine/universe-store';\n\nimport type { Person, UniverseData } from '@/types';\n\nexport { UniverseStore };\nexport {\n\tloadUniverse,\n\tloadUniverses,\n\tloadAllUniverses,\n\tloadUniverseMeta,\n\tgetManifest,\n\tgetAllInterests,\n\tgetAllLocations,\n\tgetAvailableIds\n} from '@/universes/browser-loader';\n\nexport function personFromData(universe: UniverseData, seed?: number): Person {\n\treturn PersonFactory.build(universe, seed);\n}\n\nexport type { Person, UniverseMeta } from '@/types';\nexport type { Address, UniverseData, CharacterData, AddressData, DomainsData } from '@/types';\nexport type { CharacterEntry, CharacterQuery } from '@/types';\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/generators/random.ts","../src/generators/email.ts","../src/engine/person-factory.ts","../src/engine/universe-store.ts","../src/universes/browser-loader.ts","../src/browser.ts"],"sourcesContent":["/**\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 { 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","import type { UniverseData, UniverseMeta, CharacterData, AddressData, LocationEntry } from '@/types';\n\ninterface MetaJson {\n\tid: string;\n\tname: string;\n\tgenre: string[];\n\tdescription: string;\n}\n\nconst metaModules = import.meta.glob('../data/*/meta.json', { eager: false });\nconst characterModules = import.meta.glob('../data/*/characters.json', { eager: false });\nconst addressModules = import.meta.glob('../data/*/addresses.json', { eager: false });\n\nfunction extractId(path: string): string {\n\tconst parts = path.split('/');\n\n\treturn parts[parts.length - 2];\n}\n\nexport function getAvailableIds(): string[] {\n\treturn Object.keys(metaModules).map(extractId);\n}\n\nexport async function loadUniverseMeta(id: string): Promise<UniverseMeta> {\n\tconst metaPath = `../data/${id}/meta.json`;\n\tconst metaLoader = metaModules[metaPath];\n\n\tif (!metaLoader) {\n\t\tthrow new Error(`Universe \"${id}\" not found`);\n\t}\n\n\tconst metaModule = await metaLoader();\n\tconst meta = (metaModule as { default: MetaJson }).default;\n\n\tconst result: UniverseMeta = {\n\t\tid: meta.id,\n\t\tname: meta.name,\n\t\tgenre: meta.genre,\n\t\tdescription: meta.description\n\t};\n\n\treturn result;\n}\n\nexport async function getManifest(): Promise<UniverseMeta[]> {\n\tconst ids = getAvailableIds();\n\tconst result = await Promise.all(ids.map((id) => loadUniverseMeta(id)));\n\n\treturn result;\n}\n\nexport async function loadUniverse(id: string): Promise<UniverseData> {\n\tconst metaPath = `../data/${id}/meta.json`;\n\tconst charactersPath = `../data/${id}/characters.json`;\n\tconst addressesPath = `../data/${id}/addresses.json`;\n\n\tconst metaLoader = metaModules[metaPath];\n\tconst charactersLoader = characterModules[charactersPath];\n\tconst addressesLoader = addressModules[addressesPath];\n\n\tif (!metaLoader || !charactersLoader || !addressesLoader) {\n\t\tthrow new Error(`Universe \"${id}\" not found`);\n\t}\n\n\tconst [metaModule, charactersModule, addressesModule] = await Promise.all([\n\t\tmetaLoader(),\n\t\tcharactersLoader(),\n\t\taddressesLoader()\n\t]);\n\n\tconst meta = (metaModule as { default: MetaJson }).default;\n\tconst characters = (charactersModule as { default: CharacterData[] }).default;\n\tconst addresses = (addressesModule as { default: AddressData[] }).default;\n\n\tconst universeData: UniverseData = {\n\t\tid: meta.id,\n\t\tname: meta.name,\n\t\tgenre: meta.genre,\n\t\tdescription: meta.description,\n\t\tcharacters,\n\t\taddresses\n\t};\n\n\treturn universeData;\n}\n\nexport async function loadUniverses(ids: string[]): Promise<UniverseData[]> {\n\tconst result = await Promise.all(ids.map((id) => loadUniverse(id)));\n\n\treturn result;\n}\n\nexport async function loadAllUniverses(): Promise<UniverseData[]> {\n\tconst ids = getAvailableIds();\n\n\treturn loadUniverses(ids);\n}\n\nexport async function getAllInterests(): Promise<string[]> {\n\tconst universes = await loadAllUniverses();\n\tconst interestSet = new Set<string>();\n\n\tfor (const universe of universes) {\n\t\tfor (const character of universe.characters) {\n\t\t\tfor (const interest of character.interests) {\n\t\t\t\tinterestSet.add(interest);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst result = Array.from(interestSet).sort();\n\n\treturn result;\n}\n\nexport async function getAllLocations(): Promise<LocationEntry[]> {\n\tconst universes = await loadAllUniverses();\n\tconst seen = new Map<string, LocationEntry>();\n\n\tfor (const universe of universes) {\n\t\tfor (const address of universe.addresses) {\n\t\t\tif (address.city && !seen.has(`city:${address.city}`)) {\n\t\t\t\tseen.set(`city:${address.city}`, { name: address.city, type: 'city' });\n\t\t\t}\n\n\t\t\tif (address.state && !seen.has(`state:${address.state}`)) {\n\t\t\t\tseen.set(`state:${address.state}`, { name: address.state, type: 'state' });\n\t\t\t}\n\n\t\t\tif (address.country && !seen.has(`country:${address.country}`)) {\n\t\t\t\tseen.set(`country:${address.country}`, { name: address.country, type: 'country' });\n\t\t\t}\n\t\t}\n\t}\n\n\treturn Array.from(seen.values()).sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { PersonFactory } from '@/engine/person-factory';\nimport { UniverseStore } from '@/engine/universe-store';\n\nimport type { Person, UniverseData } from '@/types';\n\nexport { UniverseStore };\nexport {\n\tloadUniverse,\n\tloadUniverses,\n\tloadAllUniverses,\n\tloadUniverseMeta,\n\tgetManifest,\n\tgetAllInterests,\n\tgetAllLocations,\n\tgetAvailableIds\n} from '@/universes/browser-loader';\n\nexport function personFromData(universe: UniverseData, seed?: number): Person {\n\treturn PersonFactory.build(universe, seed);\n}\n\nexport type { Person, UniverseMeta } from '@/types';\nexport type { Address, UniverseData, CharacterData, AddressData } from '@/types';\nexport type { CharacterEntry, CharacterQuery } from '@/types';\n"],"mappings":";AAIO,SAAS,UAAU,MAA6B;AACtD,MAAI,SAAS,QAAW;AACvB,WAAO,KAAK;AAAA,EACb;AAEA,MAAI,IAAI;AAER,SAAO,SAAS,MAAc;AAC7B,SAAK;AACL,QAAI,IAAI;AACR,QAAI,KAAK,KAAK,IAAK,MAAM,IAAK,IAAI,CAAC;AACnC,SAAK,IAAI,KAAK,KAAK,IAAK,MAAM,GAAI,IAAI,EAAE;AAExC,aAAS,IAAK,MAAM,QAAS,KAAK;AAAA,EACnC;AACD;AAEO,SAAS,WAAc,OAAY,KAAsB;AAC/D,QAAM,QAAQ,KAAK,MAAM,IAAI,IAAI,MAAM,MAAM;AAE7C,SAAO,MAAM,KAAK;AACnB;;;ACvBO,IAAM,iBAAN,MAAqB;AAAA,EAC3B,OAAO,qBAAqB,UAAkB,cAAwB,KAA2B;AAChG,UAAM,SAAS,WAAW,cAAc,GAAG;AAE3C,WAAO,GAAG,QAAQ,IAAI,MAAM;AAAA,EAC7B;AACD;;;ACJO,IAAM,gBAAN,MAAoB;AAAA,EAC1B,OAAO,MAAM,UAAwB,MAAuB;AAC3D,UAAM,MAAM,UAAU,IAAI;AAE1B,UAAM,YAAY,WAAW,SAAS,YAAY,GAAG;AAErD,WAAO,KAAK,mBAAmB,WAAW,UAAU,GAAG;AAAA,EACxD;AAAA,EAEA,OAAO,mBAAmB,aAAqB,UAAwB,MAAuB;AAC7F,UAAM,YAAY,SAAS,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,WAAW;AAEtE,QAAI,CAAC,WAAW;AACf,YAAM,IAAI,MAAM,cAAc,WAAW,4BAA4B,SAAS,EAAE,GAAG;AAAA,IACpF;AAEA,UAAM,MAAM,UAAU,IAAI;AAE1B,WAAO,KAAK,mBAAmB,WAAW,UAAU,GAAG;AAAA,EACxD;AAAA,EAEA,OAAO,eAAe,aAAqB,UAAgC;AAC1E,UAAM,YAAY,SAAS,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,WAAW;AAEtE,QAAI,CAAC,WAAW;AACf,YAAM,IAAI,MAAM,cAAc,WAAW,4BAA4B,SAAS,EAAE,GAAG;AAAA,IACpF;AAEA,UAAM,UAAU,UAAU,WAAW,SAAS,UAAU,CAAC;AACzD,UAAM,WAAW,UAAU,UAAU,CAAC;AACtC,UAAM,MAAM,UAAU,CAAC;AACvB,UAAM,QAAQ,eAAe,qBAAqB,UAAU,UAAU,cAAc,GAAG;AACvF,UAAM,QAAQ,UAAU,OAAO,CAAC;AAEhC,UAAM,SAAiB;AAAA,MACtB,IAAI,OAAO,WAAW;AAAA,MACtB,aAAa,UAAU;AAAA,MACvB,WAAW,UAAU;AAAA,MACrB,UAAU,UAAU;AAAA,MACpB;AAAA,MACA;AAAA,MACA,SAAS;AAAA,QACR,QAAQ,QAAQ;AAAA,QAChB,MAAM,QAAQ;AAAA,QACd,OAAO,QAAQ,SAAS;AAAA,QACxB,KAAK,QAAQ,OAAO;AAAA,QACpB,SAAS,QAAQ;AAAA,MAClB;AAAA,MACA,YAAY,UAAU;AAAA,MACtB,WAAW,UAAU;AAAA,MACrB;AAAA,MACA,UAAU,SAAS;AAAA,MACnB,cAAc,SAAS;AAAA,MACvB,GAAI,UAAU,SAAS,EAAE,QAAQ,UAAU,OAAO,IAAI,CAAC;AAAA,MACvD,GAAI,UAAU,QAAQ,EAAE,OAAO,UAAU,MAAM,IAAI,CAAC;AAAA,IACrD;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,OAAe,mBAAmB,WAA0B,UAAwB,KAA2B;AAC9G,UAAM,UAAU,UAAU,WAAW,WAAW,SAAS,WAAW,GAAG;AACvE,UAAM,WAAW,WAAW,UAAU,WAAW,GAAG;AACpD,UAAM,QAAQ,eAAe,qBAAqB,UAAU,UAAU,cAAc,GAAG;AACvF,UAAM,QAAQ,WAAW,UAAU,QAAQ,GAAG;AAE9C,UAAM,SAAiB;AAAA,MACtB,IAAI,OAAO,WAAW;AAAA,MACtB,aAAa,UAAU;AAAA,MACvB,WAAW,UAAU;AAAA,MACrB,UAAU,UAAU;AAAA,MACpB;AAAA,MACA;AAAA,MACA,SAAS;AAAA,QACR,QAAQ,QAAQ;AAAA,QAChB,MAAM,QAAQ;AAAA,QACd,OAAO,QAAQ,SAAS;AAAA,QACxB,KAAK,QAAQ,OAAO;AAAA,QACpB,SAAS,QAAQ;AAAA,MAClB;AAAA,MACA,YAAY,UAAU;AAAA,MACtB,WAAW,UAAU;AAAA,MACrB;AAAA,MACA,UAAU,SAAS;AAAA,MACnB,cAAc,SAAS;AAAA,MACvB,GAAI,UAAU,SAAS,EAAE,QAAQ,UAAU,OAAO,IAAI,CAAC;AAAA,MACvD,GAAI,UAAU,QAAQ,EAAE,OAAO,UAAU,MAAM,IAAI,CAAC;AAAA,IACrD;AAEA,WAAO;AAAA,EACR;AACD;;;ACzFO,IAAM,gBAAN,MAAoB;AAAA,EAClB;AAAA,EACA;AAAA,EAER,YAAY,WAA2B;AACtC,SAAK,YAAY;AACjB,SAAK,iBAAiB,KAAK,WAAW,SAAS;AAAA,EAChD;AAAA,EAEA,IAAI,QAA0B;AAC7B,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,aAAa,aAAkC;AAC9C,UAAM,UACL,eAAe,YAAY,SAAS,IACjC,KAAK,eAAe,OAAO,CAAC,MAAM,YAAY,SAAS,EAAE,UAAU,CAAC,IACpE,KAAK;AAET,UAAM,cAAc,oBAAI,IAAY;AAEpC,eAAW,SAAS,SAAS;AAC5B,iBAAW,YAAY,MAAM,WAAW;AACvC,oBAAY,IAAI,QAAQ;AAAA,MACzB;AAAA,IACD;AAEA,UAAM,SAAS,MAAM,KAAK,WAAW,EAAE,KAAK;AAE5C,WAAO;AAAA,EACR;AAAA,EAEA,eAA+B;AAC9B,UAAM,SAAS,KAAK,UAAU,IAAI,CAAC,MAAM;AACxC,YAAM,OAAqB;AAAA,QAC1B,IAAI,EAAE;AAAA,QACN,MAAM,EAAE;AAAA,QACR,OAAO,EAAE;AAAA,QACT,aAAa,EAAE;AAAA,MAChB;AAEA,aAAO;AAAA,IACR,CAAC;AAED,WAAO;AAAA,EACR;AAAA,EAEA,eAAe,OAAyC;AACvD,QAAI,UAAU,KAAK;AAEnB,QAAI,MAAM,aAAa,MAAM,UAAU,SAAS,GAAG;AAClD,gBAAU,QAAQ,OAAO,CAAC,MAAM,MAAM,UAAW,SAAS,EAAE,UAAU,CAAC;AAAA,IACxE;AAEA,QAAI,MAAM,QAAQ,MAAM,KAAK,KAAK,EAAE,SAAS,GAAG;AAC/C,YAAM,SAAS,MAAM,KAAK,YAAY;AAEtC,gBAAU,QAAQ,OAAO,CAAC,MAAM;AAC/B,cAAM,WAAW,GAAG,EAAE,SAAS,IAAI,EAAE,QAAQ,GAAG,YAAY;AAE5D,eAAO,SAAS,SAAS,MAAM;AAAA,MAChC,CAAC;AAAA,IACF;AAEA,QAAI,MAAM,aAAa,MAAM,UAAU,SAAS,GAAG;AAClD,YAAM,OAAO,MAAM,iBAAiB;AAEpC,UAAI,SAAS,OAAO;AACnB,kBAAU,QAAQ,OAAO,CAAC,MAAM,MAAM,UAAW,MAAM,CAAC,aAAa,EAAE,UAAU,SAAS,QAAQ,CAAC,CAAC;AAAA,MACrG,OAAO;AACN,kBAAU,QAAQ,OAAO,CAAC,MAAM,MAAM,UAAW,KAAK,CAAC,aAAa,EAAE,UAAU,SAAS,QAAQ,CAAC,CAAC;AAAA,MACpG;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,oBAAoB,aAAqB,MAAuB;AAC/D,UAAM,QAAQ,KAAK,eAAe,KAAK,CAAC,MAAM,EAAE,gBAAgB,WAAW;AAE3E,QAAI,CAAC,OAAO;AACX,YAAM,IAAI,MAAM,cAAc,WAAW,sBAAsB;AAAA,IAChE;AAEA,UAAM,WAAW,KAAK,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,UAAU;AAErE,QAAI,CAAC,UAAU;AACd,YAAM,IAAI,MAAM,aAAa,MAAM,UAAU,sBAAsB;AAAA,IACpE;AAEA,WAAO,cAAc,mBAAmB,aAAa,UAAU,IAAI;AAAA,EACpE;AAAA,EAEA,iBAAiB,OAAuB,OAAe,MAAyB;AAC/E,UAAM,WAAW,KAAK,eAAe,KAAK;AAE1C,QAAI,SAAS,WAAW,GAAG;AAC1B,aAAO,CAAC;AAAA,IACT;AAEA,UAAM,MAAM,UAAU,IAAI;AAC1B,UAAM,cAAc,KAAK,IAAI,OAAO,SAAS,MAAM;AAEnD,UAAM,WAAW,CAAC,GAAG,QAAQ,EAAE,KAAK,MAAM,IAAI,IAAI,GAAG;AACrD,UAAM,WAAW,SAAS,MAAM,GAAG,WAAW;AAC9C,UAAM,WAAqB,CAAC;AAE5B,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACzC,YAAM,QAAQ,SAAS,CAAC;AACxB,YAAM,WAAW,KAAK,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,UAAU;AACrE,YAAM,aAAa,SAAS,SAAY,OAAO,IAAI;AAEnD,eAAS,KAAK,cAAc,mBAAmB,MAAM,aAAa,UAAU,UAAU,CAAC;AAAA,IACxF;AAEA,WAAO;AAAA,EACR;AAAA,EAEQ,WAAW,WAA6C;AAC/D,UAAM,QAA0B,CAAC;AAEjC,eAAW,YAAY,WAAW;AACjC,iBAAW,aAAa,SAAS,YAAY;AAC5C,cAAM,QAAwB;AAAA,UAC7B,aAAa,UAAU;AAAA,UACvB,YAAY,SAAS;AAAA,UACrB,cAAc,SAAS;AAAA,UACvB,WAAW,UAAU;AAAA,UACrB,UAAU,UAAU;AAAA,UACpB,WAAW,UAAU;AAAA,UACrB,YAAY,UAAU;AAAA,QACvB;AAEA,cAAM,KAAK,KAAK;AAAA,MACjB;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AACD;;;ACxIA,IAAM,cAAc,YAAY,KAAK,uBAAuB,EAAE,OAAO,MAAM,CAAC;AAC5E,IAAM,mBAAmB,YAAY,KAAK,6BAA6B,EAAE,OAAO,MAAM,CAAC;AACvF,IAAM,iBAAiB,YAAY,KAAK,4BAA4B,EAAE,OAAO,MAAM,CAAC;AAEpF,SAAS,UAAU,MAAsB;AACxC,QAAM,QAAQ,KAAK,MAAM,GAAG;AAE5B,SAAO,MAAM,MAAM,SAAS,CAAC;AAC9B;AAEO,SAAS,kBAA4B;AAC3C,SAAO,OAAO,KAAK,WAAW,EAAE,IAAI,SAAS;AAC9C;AAEA,eAAsB,iBAAiB,IAAmC;AACzE,QAAM,WAAW,WAAW,EAAE;AAC9B,QAAM,aAAa,YAAY,QAAQ;AAEvC,MAAI,CAAC,YAAY;AAChB,UAAM,IAAI,MAAM,aAAa,EAAE,aAAa;AAAA,EAC7C;AAEA,QAAM,aAAa,MAAM,WAAW;AACpC,QAAM,OAAQ,WAAqC;AAEnD,QAAM,SAAuB;AAAA,IAC5B,IAAI,KAAK;AAAA,IACT,MAAM,KAAK;AAAA,IACX,OAAO,KAAK;AAAA,IACZ,aAAa,KAAK;AAAA,EACnB;AAEA,SAAO;AACR;AAEA,eAAsB,cAAuC;AAC5D,QAAM,MAAM,gBAAgB;AAC5B,QAAM,SAAS,MAAM,QAAQ,IAAI,IAAI,IAAI,CAAC,OAAO,iBAAiB,EAAE,CAAC,CAAC;AAEtE,SAAO;AACR;AAEA,eAAsB,aAAa,IAAmC;AACrE,QAAM,WAAW,WAAW,EAAE;AAC9B,QAAM,iBAAiB,WAAW,EAAE;AACpC,QAAM,gBAAgB,WAAW,EAAE;AAEnC,QAAM,aAAa,YAAY,QAAQ;AACvC,QAAM,mBAAmB,iBAAiB,cAAc;AACxD,QAAM,kBAAkB,eAAe,aAAa;AAEpD,MAAI,CAAC,cAAc,CAAC,oBAAoB,CAAC,iBAAiB;AACzD,UAAM,IAAI,MAAM,aAAa,EAAE,aAAa;AAAA,EAC7C;AAEA,QAAM,CAAC,YAAY,kBAAkB,eAAe,IAAI,MAAM,QAAQ,IAAI;AAAA,IACzE,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,EACjB,CAAC;AAED,QAAM,OAAQ,WAAqC;AACnD,QAAM,aAAc,iBAAkD;AACtE,QAAM,YAAa,gBAA+C;AAElE,QAAM,eAA6B;AAAA,IAClC,IAAI,KAAK;AAAA,IACT,MAAM,KAAK;AAAA,IACX,OAAO,KAAK;AAAA,IACZ,aAAa,KAAK;AAAA,IAClB;AAAA,IACA;AAAA,EACD;AAEA,SAAO;AACR;AAEA,eAAsB,cAAc,KAAwC;AAC3E,QAAM,SAAS,MAAM,QAAQ,IAAI,IAAI,IAAI,CAAC,OAAO,aAAa,EAAE,CAAC,CAAC;AAElE,SAAO;AACR;AAEA,eAAsB,mBAA4C;AACjE,QAAM,MAAM,gBAAgB;AAE5B,SAAO,cAAc,GAAG;AACzB;AAEA,eAAsB,kBAAqC;AAC1D,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,cAAc,oBAAI,IAAY;AAEpC,aAAW,YAAY,WAAW;AACjC,eAAW,aAAa,SAAS,YAAY;AAC5C,iBAAW,YAAY,UAAU,WAAW;AAC3C,oBAAY,IAAI,QAAQ;AAAA,MACzB;AAAA,IACD;AAAA,EACD;AAEA,QAAM,SAAS,MAAM,KAAK,WAAW,EAAE,KAAK;AAE5C,SAAO;AACR;AAEA,eAAsB,kBAA4C;AACjE,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,OAAO,oBAAI,IAA2B;AAE5C,aAAW,YAAY,WAAW;AACjC,eAAW,WAAW,SAAS,WAAW;AACzC,UAAI,QAAQ,QAAQ,CAAC,KAAK,IAAI,QAAQ,QAAQ,IAAI,EAAE,GAAG;AACtD,aAAK,IAAI,QAAQ,QAAQ,IAAI,IAAI,EAAE,MAAM,QAAQ,MAAM,MAAM,OAAO,CAAC;AAAA,MACtE;AAEA,UAAI,QAAQ,SAAS,CAAC,KAAK,IAAI,SAAS,QAAQ,KAAK,EAAE,GAAG;AACzD,aAAK,IAAI,SAAS,QAAQ,KAAK,IAAI,EAAE,MAAM,QAAQ,OAAO,MAAM,QAAQ,CAAC;AAAA,MAC1E;AAEA,UAAI,QAAQ,WAAW,CAAC,KAAK,IAAI,WAAW,QAAQ,OAAO,EAAE,GAAG;AAC/D,aAAK,IAAI,WAAW,QAAQ,OAAO,IAAI,EAAE,MAAM,QAAQ,SAAS,MAAM,UAAU,CAAC;AAAA,MAClF;AAAA,IACD;AAAA,EACD;AAEA,SAAO,MAAM,KAAK,KAAK,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAC7E;;;ACvHO,SAAS,eAAe,UAAwB,MAAuB;AAC7E,SAAO,cAAc,MAAM,UAAU,IAAI;AAC1C;","names":[]}
|
package/dist/cli/cli.cjs
CHANGED
|
@@ -28,7 +28,6 @@ var UniverseLoader = class {
|
|
|
28
28
|
const meta = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(universeDir, "meta.json"), "utf-8"));
|
|
29
29
|
const characters = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(universeDir, "characters.json"), "utf-8"));
|
|
30
30
|
const addresses = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(universeDir, "addresses.json"), "utf-8"));
|
|
31
|
-
const domains = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(universeDir, "domains.json"), "utf-8"));
|
|
32
31
|
const universeData = {
|
|
33
32
|
id: meta.id,
|
|
34
33
|
name: meta.name,
|
|
@@ -36,7 +35,13 @@ var UniverseLoader = class {
|
|
|
36
35
|
description: meta.description,
|
|
37
36
|
characters,
|
|
38
37
|
addresses,
|
|
39
|
-
|
|
38
|
+
...meta.tmdbId !== void 0 && { tmdbId: meta.tmdbId },
|
|
39
|
+
...meta.mediaType !== void 0 && { mediaType: meta.mediaType },
|
|
40
|
+
...meta.rating !== void 0 && { rating: meta.rating },
|
|
41
|
+
...meta.year !== void 0 && { year: meta.year },
|
|
42
|
+
...meta.networks !== void 0 && { networks: meta.networks },
|
|
43
|
+
...meta.posterPath !== void 0 && { posterPath: meta.posterPath },
|
|
44
|
+
...meta.backdropPath !== void 0 && { backdropPath: meta.backdropPath }
|
|
40
45
|
};
|
|
41
46
|
this.cache.set(universeId, universeData);
|
|
42
47
|
return universeData;
|
|
@@ -45,14 +50,7 @@ var UniverseLoader = class {
|
|
|
45
50
|
const ids = this.listAvailable();
|
|
46
51
|
const result = ids.map((id) => {
|
|
47
52
|
const universeDir = (0, import_path.join)(dataDir, id);
|
|
48
|
-
|
|
49
|
-
const entry = {
|
|
50
|
-
id: meta.id,
|
|
51
|
-
name: meta.name,
|
|
52
|
-
genre: meta.genre,
|
|
53
|
-
description: meta.description
|
|
54
|
-
};
|
|
55
|
-
return entry;
|
|
53
|
+
return JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(universeDir, "meta.json"), "utf-8"));
|
|
56
54
|
});
|
|
57
55
|
return result;
|
|
58
56
|
}
|
|
@@ -72,17 +70,41 @@ var UniverseLoader = class {
|
|
|
72
70
|
}
|
|
73
71
|
static getAllLocations() {
|
|
74
72
|
const ids = this.listAvailable();
|
|
75
|
-
const
|
|
73
|
+
const seen = /* @__PURE__ */ new Map();
|
|
76
74
|
for (const id of ids) {
|
|
77
75
|
const universe = this.load(id);
|
|
78
76
|
for (const address of universe.addresses) {
|
|
79
|
-
if (address.city) {
|
|
80
|
-
|
|
77
|
+
if (address.city && !seen.has(`city:${address.city}`)) {
|
|
78
|
+
seen.set(`city:${address.city}`, { name: address.city, type: "city" });
|
|
79
|
+
}
|
|
80
|
+
if (address.state && !seen.has(`state:${address.state}`)) {
|
|
81
|
+
seen.set(`state:${address.state}`, { name: address.state, type: "state" });
|
|
82
|
+
}
|
|
83
|
+
if (address.country && !seen.has(`country:${address.country}`)) {
|
|
84
|
+
seen.set(`country:${address.country}`, { name: address.country, type: "country" });
|
|
81
85
|
}
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
return Array.from(seen.values()).sort((a, b) => a.name.localeCompare(b.name));
|
|
89
|
+
}
|
|
90
|
+
static buildCharacterIndex() {
|
|
91
|
+
const ids = this.listAvailable();
|
|
92
|
+
const entries = [];
|
|
93
|
+
for (const id of ids) {
|
|
94
|
+
const universe = this.load(id);
|
|
95
|
+
for (const character of universe.characters) {
|
|
96
|
+
entries.push({
|
|
97
|
+
characterId: character.id,
|
|
98
|
+
universeId: universe.id,
|
|
99
|
+
universeName: universe.name,
|
|
100
|
+
firstName: character.firstName ?? "",
|
|
101
|
+
lastName: character.lastName ?? "",
|
|
102
|
+
interests: character.interests,
|
|
103
|
+
profession: character.profession
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return entries;
|
|
86
108
|
}
|
|
87
109
|
static listAvailable() {
|
|
88
110
|
const entries = (0, import_fs.readdirSync)(dataDir, { withFileTypes: true });
|
|
@@ -122,55 +144,12 @@ function pickRandom(array, rng) {
|
|
|
122
144
|
|
|
123
145
|
// src/generators/email.ts
|
|
124
146
|
var EmailGenerator = class {
|
|
125
|
-
static
|
|
126
|
-
const domain = pickRandom(
|
|
127
|
-
const first = firstName.toLowerCase();
|
|
128
|
-
const last = lastName.toLowerCase();
|
|
129
|
-
return `${first}.${last}@${domain}`;
|
|
130
|
-
}
|
|
131
|
-
static generateFromUsername(username, domains, rng) {
|
|
132
|
-
const domain = pickRandom(domains.emailDomains, rng);
|
|
147
|
+
static generateFromUsername(username, emailDomains, rng) {
|
|
148
|
+
const domain = pickRandom(emailDomains, rng);
|
|
133
149
|
return `${username}@${domain}`;
|
|
134
150
|
}
|
|
135
151
|
};
|
|
136
152
|
|
|
137
|
-
// src/generators/phone.ts
|
|
138
|
-
var PhoneGenerator = class {
|
|
139
|
-
static generate(domains, rng) {
|
|
140
|
-
if (domains.phoneEasterEggs && domains.phoneEasterEggs.length > 0 && rng() < 0.2) {
|
|
141
|
-
return pickRandom(domains.phoneEasterEggs, rng);
|
|
142
|
-
}
|
|
143
|
-
const prefix = pickRandom(domains.phonePrefixes, rng);
|
|
144
|
-
const suffix = this.randomDigits(7, rng);
|
|
145
|
-
return `${prefix}-${suffix.slice(0, 3)}-${suffix.slice(3)}`;
|
|
146
|
-
}
|
|
147
|
-
static randomDigits(count, rng) {
|
|
148
|
-
let result = "";
|
|
149
|
-
for (let i = 0; i < count; i++) {
|
|
150
|
-
result += Math.floor(rng() * 10).toString();
|
|
151
|
-
}
|
|
152
|
-
return result;
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
// src/generators/password.ts
|
|
157
|
-
var PasswordGenerator = class {
|
|
158
|
-
static generate(domains, rng) {
|
|
159
|
-
if (domains.passwordEasterEggs && domains.passwordEasterEggs.length > 0 && rng() < 0.3) {
|
|
160
|
-
return pickRandom(domains.passwordEasterEggs, rng);
|
|
161
|
-
}
|
|
162
|
-
return this.randomPassword(12, rng);
|
|
163
|
-
}
|
|
164
|
-
static randomPassword(length, rng) {
|
|
165
|
-
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$";
|
|
166
|
-
let result = "";
|
|
167
|
-
for (let i = 0; i < length; i++) {
|
|
168
|
-
result += chars[Math.floor(rng() * chars.length)];
|
|
169
|
-
}
|
|
170
|
-
return result;
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
|
|
174
153
|
// src/engine/person-factory.ts
|
|
175
154
|
var PersonFactory = class {
|
|
176
155
|
static build(universe, seed) {
|
|
@@ -193,11 +172,8 @@ var PersonFactory = class {
|
|
|
193
172
|
}
|
|
194
173
|
const address = character.address ?? universe.addresses[0];
|
|
195
174
|
const username = character.usernames[0];
|
|
196
|
-
const domains = character.emailDomain ? { ...universe.domains, emailDomains: [character.emailDomain] } : universe.domains;
|
|
197
175
|
const rng = createRng(0);
|
|
198
|
-
const email = EmailGenerator.generateFromUsername(username,
|
|
199
|
-
const phone = PhoneGenerator.generate(universe.domains, rng);
|
|
200
|
-
const password = PasswordGenerator.generate(universe.domains, rng);
|
|
176
|
+
const email = EmailGenerator.generateFromUsername(username, character.emailDomains, rng);
|
|
201
177
|
const quote = character.quotes[0];
|
|
202
178
|
const person = {
|
|
203
179
|
id: crypto.randomUUID(),
|
|
@@ -206,8 +182,6 @@ var PersonFactory = class {
|
|
|
206
182
|
lastName: character.lastName,
|
|
207
183
|
username,
|
|
208
184
|
email,
|
|
209
|
-
password,
|
|
210
|
-
phone,
|
|
211
185
|
address: {
|
|
212
186
|
street: address.street,
|
|
213
187
|
city: address.city,
|
|
@@ -228,10 +202,7 @@ var PersonFactory = class {
|
|
|
228
202
|
static buildFromCharacter(character, universe, rng) {
|
|
229
203
|
const address = character.address ?? pickRandom(universe.addresses, rng);
|
|
230
204
|
const username = pickRandom(character.usernames, rng);
|
|
231
|
-
const
|
|
232
|
-
const email = EmailGenerator.generateFromUsername(username, domains, rng);
|
|
233
|
-
const phone = PhoneGenerator.generate(universe.domains, rng);
|
|
234
|
-
const password = PasswordGenerator.generate(universe.domains, rng);
|
|
205
|
+
const email = EmailGenerator.generateFromUsername(username, character.emailDomains, rng);
|
|
235
206
|
const quote = pickRandom(character.quotes, rng);
|
|
236
207
|
const person = {
|
|
237
208
|
id: crypto.randomUUID(),
|
|
@@ -240,8 +211,6 @@ var PersonFactory = class {
|
|
|
240
211
|
lastName: character.lastName,
|
|
241
212
|
username,
|
|
242
213
|
email,
|
|
243
|
-
password,
|
|
244
|
-
phone,
|
|
245
214
|
address: {
|
|
246
215
|
street: address.street,
|
|
247
216
|
city: address.city,
|
|
@@ -432,7 +401,6 @@ program.command("person").description("Generate a single persona").option("-u, -
|
|
|
432
401
|
`
|
|
433
402
|
Name: ${result.firstName} ${result.lastName} (@${result.username})
|
|
434
403
|
Email: ${result.email}
|
|
435
|
-
Phone: ${result.phone}
|
|
436
404
|
Address: ${[result.address.street, result.address.city, result.address.country].filter(Boolean).join(", ")}
|
|
437
405
|
Profession: ${result.profession}
|
|
438
406
|
Interests: ${result.interests.join(", ")}
|
package/dist/cli/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/cli.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","../../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\n\nimport { universes, UniverseLoader, UniverseStore } from '@/index';\n\nimport type { CharacterQuery } from '@/types';\n\nconst program = new Command();\n\nprogram.name('loredata').description('Pop culture fake data generator').version('0.1.0');\n\nprogram\n\t.command('person')\n\t.description('Generate a single persona')\n\t.option('-u, --universe <id>', 'Universe ID (e.g. breaking-bad). Omit for all universes.')\n\t.option('-s, --seed <n>', 'Seed for deterministic generation')\n\t.option('-f, --format <fmt>', 'Output format: pretty | json', 'pretty')\n\t.option('--interests <list>', 'Comma-separated interests filter (e.g. chemistry,cooking)')\n\t.option('--interests-mode <mode>', 'Match mode: and | or (default: or)', 'or')\n\t.option('--name <query>', 'Search by character name')\n\t.action(\n\t\t(options: { universe?: string; seed?: string; format: string; interests?: string; interestsMode: string; name?: string }) => {\n\t\t\tconst seed = options.seed ? parseInt(options.seed, 10) : undefined;\n\t\t\tconst universeIds = options.universe ? [options.universe] : UniverseLoader.listAvailable();\n\t\t\tconst universesData = universeIds.map((id) => UniverseLoader.load(id));\n\t\t\tconst storeInstance = new UniverseStore(universesData);\n\n\t\t\tconst query: CharacterQuery = {\n\t\t\t\tuniverses: options.universe ? [options.universe] : [],\n\t\t\t\tinterests: options.interests ? options.interests.split(',').map((s) => s.trim()) : [],\n\t\t\t\tinterestsMode: options.interestsMode === 'and' ? 'and' : 'or',\n\t\t\t\tname: options.name\n\t\t\t};\n\n\t\t\tconst result = storeInstance.generatePersonas(query, 1, seed)[0];\n\n\t\t\tif (!result) {\n\t\t\t\tconsole.error('No characters match the given filters.');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tif (options.format === 'json') {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconsole.log(\n\t\t\t\t`\nName: ${result.firstName} ${result.lastName} (@${result.username})\nEmail: ${result.email}\nPhone: ${result.phone}\nAddress: ${[result.address.street, result.address.city, result.address.country].filter(Boolean).join(', ')}\nProfession: ${result.profession}\nInterests: ${result.interests.join(', ')}\nQuote: ${result.quote}\nUniverse: ${result.universe}\n `.trim()\n\t\t\t);\n\t\t}\n\t);\n\nprogram\n\t.command('group')\n\t.description('Generate multiple personas')\n\t.option('-u, --universe <id>', 'Universe ID (e.g. got). Omit for all universes.')\n\t.option('-n, --size <n>', 'Number of personas', '3')\n\t.option('-s, --seed <n>', 'Seed for deterministic generation')\n\t.option('-f, --format <fmt>', 'Output format: pretty | json', 'pretty')\n\t.option('--interests <list>', 'Comma-separated interests filter (e.g. chemistry,cooking)')\n\t.option('--interests-mode <mode>', 'Match mode: and | or (default: or)', 'or')\n\t.option('--name <query>', 'Search by character name')\n\t.action(\n\t\t(options: {\n\t\t\tuniverse?: string;\n\t\t\tsize: string;\n\t\t\tseed?: string;\n\t\t\tformat: string;\n\t\t\tinterests?: string;\n\t\t\tinterestsMode: string;\n\t\t\tname?: string;\n\t\t}) => {\n\t\t\tconst size = parseInt(options.size, 10);\n\t\t\tconst seed = options.seed ? parseInt(options.seed, 10) : undefined;\n\t\t\tconst universeIds = options.universe ? [options.universe] : UniverseLoader.listAvailable();\n\t\t\tconst universesData = universeIds.map((id) => UniverseLoader.load(id));\n\t\t\tconst storeInstance = new UniverseStore(universesData);\n\n\t\t\tconst query: CharacterQuery = {\n\t\t\t\tuniverses: options.universe ? [options.universe] : [],\n\t\t\t\tinterests: options.interests ? options.interests.split(',').map((s) => s.trim()) : [],\n\t\t\t\tinterestsMode: options.interestsMode === 'and' ? 'and' : 'or',\n\t\t\t\tname: options.name\n\t\t\t};\n\n\t\t\tconst result = storeInstance.generatePersonas(query, size, seed);\n\n\t\t\tif (result.length === 0) {\n\t\t\t\tconsole.error('No characters match the given filters.');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tif (options.format === 'json') {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfor (const p of result) {\n\t\t\t\tconsole.log(`${p.firstName} ${p.lastName} <${p.email}> — ${p.profession}`);\n\t\t\t}\n\t\t}\n\t);\n\nprogram\n\t.command('universes')\n\t.description('List available universes')\n\t.option('-f, --format <fmt>', 'Output format: pretty | json', 'pretty')\n\t.action((options: { format: string }) => {\n\t\tconst list = universes();\n\n\t\tif (options.format === 'json') {\n\t\t\tconsole.log(JSON.stringify(list, null, 2));\n\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const u of list) {\n\t\t\tconsole.log(` ${u.id.padEnd(20)} ${u.name}`);\n\t\t}\n\t});\n\nprogram.parse();\n","import { readFileSync, readdirSync } from 'fs';\nimport { createRequire } from 'module';\nimport { dirname, join } from 'path';\n\nimport type { UniverseData, UniverseMeta, CharacterData, AddressData, DomainsData } 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 {\n\t\t\tid: string;\n\t\t\tname: string;\n\t\t\tgenre: string[];\n\t\t\tdescription: 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\tgenre: meta.genre,\n\t\t\tdescription: meta.description,\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 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\t\t\tconst meta = JSON.parse(readFileSync(join(universeDir, 'meta.json'), 'utf-8')) as UniverseMeta;\n\n\t\t\tconst entry: UniverseMeta = {\n\t\t\t\tid: meta.id,\n\t\t\t\tname: meta.name,\n\t\t\t\tgenre: meta.genre,\n\t\t\t\tdescription: meta.description\n\t\t\t};\n\n\t\t\treturn entry;\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(): string[] {\n\t\tconst ids = this.listAvailable();\n\t\tconst citySet = 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 address of universe.addresses) {\n\t\t\t\tif (address.city) {\n\t\t\t\t\tcitySet.add(address.city);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst result = Array.from(citySet).sort();\n\n\t\treturn result;\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\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 domains = character.emailDomain ? { ...universe.domains, emailDomains: [character.emailDomain] } : universe.domains;\n\t\tconst rng = createRng(0);\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 = 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\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\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\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\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\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","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, DomainsData } from '@/types';\nexport type { CharacterEntry, CharacterQuery } from '@/types';\n"],"mappings":"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","names":["require","universes"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/cli.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","../../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\n\nimport { universes, UniverseLoader, UniverseStore } from '@/index';\n\nimport type { CharacterQuery } from '@/types';\n\nconst program = new Command();\n\nprogram.name('loredata').description('Pop culture fake data generator').version('0.1.0');\n\nprogram\n\t.command('person')\n\t.description('Generate a single persona')\n\t.option('-u, --universe <id>', 'Universe ID (e.g. breaking-bad). Omit for all universes.')\n\t.option('-s, --seed <n>', 'Seed for deterministic generation')\n\t.option('-f, --format <fmt>', 'Output format: pretty | json', 'pretty')\n\t.option('--interests <list>', 'Comma-separated interests filter (e.g. chemistry,cooking)')\n\t.option('--interests-mode <mode>', 'Match mode: and | or (default: or)', 'or')\n\t.option('--name <query>', 'Search by character name')\n\t.action(\n\t\t(options: { universe?: string; seed?: string; format: string; interests?: string; interestsMode: string; name?: string }) => {\n\t\t\tconst seed = options.seed ? parseInt(options.seed, 10) : undefined;\n\t\t\tconst universeIds = options.universe ? [options.universe] : UniverseLoader.listAvailable();\n\t\t\tconst universesData = universeIds.map((id) => UniverseLoader.load(id));\n\t\t\tconst storeInstance = new UniverseStore(universesData);\n\n\t\t\tconst query: CharacterQuery = {\n\t\t\t\tuniverses: options.universe ? [options.universe] : [],\n\t\t\t\tinterests: options.interests ? options.interests.split(',').map((s) => s.trim()) : [],\n\t\t\t\tinterestsMode: options.interestsMode === 'and' ? 'and' : 'or',\n\t\t\t\tname: options.name\n\t\t\t};\n\n\t\t\tconst result = storeInstance.generatePersonas(query, 1, seed)[0];\n\n\t\t\tif (!result) {\n\t\t\t\tconsole.error('No characters match the given filters.');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tif (options.format === 'json') {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconsole.log(\n\t\t\t\t`\nName: ${result.firstName} ${result.lastName} (@${result.username})\nEmail: ${result.email}\nAddress: ${[result.address.street, result.address.city, result.address.country].filter(Boolean).join(', ')}\nProfession: ${result.profession}\nInterests: ${result.interests.join(', ')}\nQuote: ${result.quote}\nUniverse: ${result.universe}\n `.trim()\n\t\t\t);\n\t\t}\n\t);\n\nprogram\n\t.command('group')\n\t.description('Generate multiple personas')\n\t.option('-u, --universe <id>', 'Universe ID (e.g. got). Omit for all universes.')\n\t.option('-n, --size <n>', 'Number of personas', '3')\n\t.option('-s, --seed <n>', 'Seed for deterministic generation')\n\t.option('-f, --format <fmt>', 'Output format: pretty | json', 'pretty')\n\t.option('--interests <list>', 'Comma-separated interests filter (e.g. chemistry,cooking)')\n\t.option('--interests-mode <mode>', 'Match mode: and | or (default: or)', 'or')\n\t.option('--name <query>', 'Search by character name')\n\t.action(\n\t\t(options: {\n\t\t\tuniverse?: string;\n\t\t\tsize: string;\n\t\t\tseed?: string;\n\t\t\tformat: string;\n\t\t\tinterests?: string;\n\t\t\tinterestsMode: string;\n\t\t\tname?: string;\n\t\t}) => {\n\t\t\tconst size = parseInt(options.size, 10);\n\t\t\tconst seed = options.seed ? parseInt(options.seed, 10) : undefined;\n\t\t\tconst universeIds = options.universe ? [options.universe] : UniverseLoader.listAvailable();\n\t\t\tconst universesData = universeIds.map((id) => UniverseLoader.load(id));\n\t\t\tconst storeInstance = new UniverseStore(universesData);\n\n\t\t\tconst query: CharacterQuery = {\n\t\t\t\tuniverses: options.universe ? [options.universe] : [],\n\t\t\t\tinterests: options.interests ? options.interests.split(',').map((s) => s.trim()) : [],\n\t\t\t\tinterestsMode: options.interestsMode === 'and' ? 'and' : 'or',\n\t\t\t\tname: options.name\n\t\t\t};\n\n\t\t\tconst result = storeInstance.generatePersonas(query, size, seed);\n\n\t\t\tif (result.length === 0) {\n\t\t\t\tconsole.error('No characters match the given filters.');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tif (options.format === 'json') {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfor (const p of result) {\n\t\t\t\tconsole.log(`${p.firstName} ${p.lastName} <${p.email}> — ${p.profession}`);\n\t\t\t}\n\t\t}\n\t);\n\nprogram\n\t.command('universes')\n\t.description('List available universes')\n\t.option('-f, --format <fmt>', 'Output format: pretty | json', 'pretty')\n\t.action((options: { format: string }) => {\n\t\tconst list = universes();\n\n\t\tif (options.format === 'json') {\n\t\t\tconsole.log(JSON.stringify(list, null, 2));\n\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const u of list) {\n\t\t\tconsole.log(` ${u.id.padEnd(20)} ${u.name}`);\n\t\t}\n\t});\n\nprogram.parse();\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","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"],"mappings":"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","names":["require","universes"]}
|