loredata 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -5
- package/data/breaking-bad/characters.json +36 -7
- package/data/breaking-bad/meta.json +3 -1
- package/data/fast-and-furious/characters.json +26 -7
- package/data/fast-and-furious/meta.json +3 -1
- package/data/friends/characters.json +128 -22
- package/data/friends/meta.json +6 -1
- package/data/game-of-thrones/characters.json +45 -15
- package/data/game-of-thrones/meta.json +3 -1
- package/data/harry-potter/characters.json +30 -7
- package/data/harry-potter/meta.json +3 -1
- package/data/house-md/characters.json +58 -15
- package/data/house-md/meta.json +6 -1
- package/data/lost/characters.json +120 -24
- package/data/lost/meta.json +6 -1
- package/data/matrix/characters.json +112 -24
- package/data/matrix/meta.json +6 -1
- package/data/peaky-blinders/characters.json +33 -11
- package/data/peaky-blinders/meta.json +6 -1
- package/data/sherlock/characters.json +99 -19
- package/data/sherlock/meta.json +6 -1
- package/data/the-office/characters.json +55 -15
- package/data/the-office/meta.json +3 -1
- package/dist/browser.cjs +107 -8
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +7 -3
- package/dist/browser.d.ts +7 -3
- package/dist/browser.js +103 -8
- package/dist/browser.js.map +1 -1
- package/dist/cli/cli.cjs +109 -16
- package/dist/cli/cli.cjs.map +1 -1
- package/dist/cli/cli.js +110 -17
- package/dist/cli/cli.js.map +1 -1
- package/dist/index.cjs +110 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -4
- package/dist/index.d.ts +14 -4
- package/dist/index.js +110 -16
- package/dist/index.js.map +1 -1
- package/dist/{universe-store-DJrm7bP7.d.cts → universe-store-Del1UHgn.d.cts} +11 -9
- package/dist/{universe-store-DJrm7bP7.d.ts → universe-store-Del1UHgn.d.ts} +11 -9
- package/package.json +9 -4
package/dist/browser.cjs
CHANGED
|
@@ -21,9 +21,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var browser_exports = {};
|
|
22
22
|
__export(browser_exports, {
|
|
23
23
|
UniverseStore: () => UniverseStore,
|
|
24
|
+
getAllInterests: () => getAllInterests,
|
|
25
|
+
getAllLocations: () => getAllLocations,
|
|
24
26
|
getAvailableIds: () => getAvailableIds,
|
|
27
|
+
getManifest: () => getManifest,
|
|
25
28
|
loadAllUniverses: () => loadAllUniverses,
|
|
26
29
|
loadUniverse: () => loadUniverse,
|
|
30
|
+
loadUniverseMeta: () => loadUniverseMeta,
|
|
27
31
|
loadUniverses: () => loadUniverses,
|
|
28
32
|
personFromData: () => personFromData
|
|
29
33
|
});
|
|
@@ -114,6 +118,45 @@ var PersonFactory = class {
|
|
|
114
118
|
const rng = createRng(seed);
|
|
115
119
|
return this.buildFromCharacter(character, universe, rng);
|
|
116
120
|
}
|
|
121
|
+
static buildCanonical(characterId, universe) {
|
|
122
|
+
const character = universe.characters.find((c) => c.id === characterId);
|
|
123
|
+
if (!character) {
|
|
124
|
+
throw new Error(`Character "${characterId}" not found in universe "${universe.id}"`);
|
|
125
|
+
}
|
|
126
|
+
const address = character.address ?? universe.addresses[0];
|
|
127
|
+
const username = character.usernames[0];
|
|
128
|
+
const domains = character.emailDomain ? { ...universe.domains, emailDomains: [character.emailDomain] } : universe.domains;
|
|
129
|
+
const rng = createRng(0);
|
|
130
|
+
const email = EmailGenerator.generateFromUsername(username, domains, rng);
|
|
131
|
+
const phone = PhoneGenerator.generate(universe.domains, rng);
|
|
132
|
+
const password = PasswordGenerator.generate(universe.domains, rng);
|
|
133
|
+
const quote = character.quotes[0];
|
|
134
|
+
const person = {
|
|
135
|
+
id: crypto.randomUUID(),
|
|
136
|
+
characterId: character.id,
|
|
137
|
+
firstName: character.firstName,
|
|
138
|
+
lastName: character.lastName,
|
|
139
|
+
username,
|
|
140
|
+
email,
|
|
141
|
+
password,
|
|
142
|
+
phone,
|
|
143
|
+
address: {
|
|
144
|
+
street: address.street,
|
|
145
|
+
city: address.city,
|
|
146
|
+
state: address.state ?? "",
|
|
147
|
+
zip: address.zip ?? "",
|
|
148
|
+
country: address.country
|
|
149
|
+
},
|
|
150
|
+
profession: character.profession,
|
|
151
|
+
interests: character.interests,
|
|
152
|
+
quote,
|
|
153
|
+
universe: universe.id,
|
|
154
|
+
universeName: universe.name,
|
|
155
|
+
...character.symbol ? { symbol: character.symbol } : {},
|
|
156
|
+
...character.color ? { color: character.color } : {}
|
|
157
|
+
};
|
|
158
|
+
return person;
|
|
159
|
+
}
|
|
117
160
|
static buildFromCharacter(character, universe, rng) {
|
|
118
161
|
const address = character.address ?? pickRandom(universe.addresses, rng);
|
|
119
162
|
const username = pickRandom(character.usernames, rng);
|
|
@@ -122,8 +165,6 @@ var PersonFactory = class {
|
|
|
122
165
|
const phone = PhoneGenerator.generate(universe.domains, rng);
|
|
123
166
|
const password = PasswordGenerator.generate(universe.domains, rng);
|
|
124
167
|
const quote = pickRandom(character.quotes, rng);
|
|
125
|
-
const avatarName = encodeURIComponent(`${character.firstName} ${character.lastName}`);
|
|
126
|
-
const avatar = `https://ui-avatars.com/api/?name=${avatarName}&background=random`;
|
|
127
168
|
const person = {
|
|
128
169
|
id: crypto.randomUUID(),
|
|
129
170
|
characterId: character.id,
|
|
@@ -145,7 +186,8 @@ var PersonFactory = class {
|
|
|
145
186
|
quote,
|
|
146
187
|
universe: universe.id,
|
|
147
188
|
universeName: universe.name,
|
|
148
|
-
|
|
189
|
+
...character.symbol ? { symbol: character.symbol } : {},
|
|
190
|
+
...character.color ? { color: character.color } : {}
|
|
149
191
|
};
|
|
150
192
|
return person;
|
|
151
193
|
}
|
|
@@ -174,11 +216,15 @@ var UniverseStore = class {
|
|
|
174
216
|
return result;
|
|
175
217
|
}
|
|
176
218
|
getUniverses() {
|
|
177
|
-
const result = this.universes.map((u) =>
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
219
|
+
const result = this.universes.map((u) => {
|
|
220
|
+
const meta = {
|
|
221
|
+
id: u.id,
|
|
222
|
+
name: u.name,
|
|
223
|
+
genre: u.genre,
|
|
224
|
+
description: u.description
|
|
225
|
+
};
|
|
226
|
+
return meta;
|
|
227
|
+
});
|
|
182
228
|
return result;
|
|
183
229
|
}
|
|
184
230
|
findCharacters(query) {
|
|
@@ -265,6 +311,27 @@ function extractId(path) {
|
|
|
265
311
|
function getAvailableIds() {
|
|
266
312
|
return Object.keys(metaModules).map(extractId);
|
|
267
313
|
}
|
|
314
|
+
async function loadUniverseMeta(id) {
|
|
315
|
+
const metaPath = `../data/${id}/meta.json`;
|
|
316
|
+
const metaLoader = metaModules[metaPath];
|
|
317
|
+
if (!metaLoader) {
|
|
318
|
+
throw new Error(`Universe "${id}" not found`);
|
|
319
|
+
}
|
|
320
|
+
const metaModule = await metaLoader();
|
|
321
|
+
const meta = metaModule.default;
|
|
322
|
+
const result = {
|
|
323
|
+
id: meta.id,
|
|
324
|
+
name: meta.name,
|
|
325
|
+
genre: meta.genre,
|
|
326
|
+
description: meta.description
|
|
327
|
+
};
|
|
328
|
+
return result;
|
|
329
|
+
}
|
|
330
|
+
async function getManifest() {
|
|
331
|
+
const ids = getAvailableIds();
|
|
332
|
+
const result = await Promise.all(ids.map((id) => loadUniverseMeta(id)));
|
|
333
|
+
return result;
|
|
334
|
+
}
|
|
268
335
|
async function loadUniverse(id) {
|
|
269
336
|
const metaPath = `../data/${id}/meta.json`;
|
|
270
337
|
const charactersPath = `../data/${id}/characters.json`;
|
|
@@ -290,6 +357,8 @@ async function loadUniverse(id) {
|
|
|
290
357
|
const universeData = {
|
|
291
358
|
id: meta.id,
|
|
292
359
|
name: meta.name,
|
|
360
|
+
genre: meta.genre,
|
|
361
|
+
description: meta.description,
|
|
293
362
|
characters,
|
|
294
363
|
addresses,
|
|
295
364
|
domains
|
|
@@ -304,6 +373,32 @@ async function loadAllUniverses() {
|
|
|
304
373
|
const ids = getAvailableIds();
|
|
305
374
|
return loadUniverses(ids);
|
|
306
375
|
}
|
|
376
|
+
async function getAllInterests() {
|
|
377
|
+
const universes = await loadAllUniverses();
|
|
378
|
+
const interestSet = /* @__PURE__ */ new Set();
|
|
379
|
+
for (const universe of universes) {
|
|
380
|
+
for (const character of universe.characters) {
|
|
381
|
+
for (const interest of character.interests) {
|
|
382
|
+
interestSet.add(interest);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
const result = Array.from(interestSet).sort();
|
|
387
|
+
return result;
|
|
388
|
+
}
|
|
389
|
+
async function getAllLocations() {
|
|
390
|
+
const universes = await loadAllUniverses();
|
|
391
|
+
const citySet = /* @__PURE__ */ new Set();
|
|
392
|
+
for (const universe of universes) {
|
|
393
|
+
for (const address of universe.addresses) {
|
|
394
|
+
if (address.city) {
|
|
395
|
+
citySet.add(address.city);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
const result = Array.from(citySet).sort();
|
|
400
|
+
return result;
|
|
401
|
+
}
|
|
307
402
|
|
|
308
403
|
// src/browser.ts
|
|
309
404
|
function personFromData(universe, seed) {
|
|
@@ -312,9 +407,13 @@ function personFromData(universe, seed) {
|
|
|
312
407
|
// Annotate the CommonJS export names for ESM import in node:
|
|
313
408
|
0 && (module.exports = {
|
|
314
409
|
UniverseStore,
|
|
410
|
+
getAllInterests,
|
|
411
|
+
getAllLocations,
|
|
315
412
|
getAvailableIds,
|
|
413
|
+
getManifest,
|
|
316
414
|
loadAllUniverses,
|
|
317
415
|
loadUniverse,
|
|
416
|
+
loadUniverseMeta,
|
|
318
417
|
loadUniverses,
|
|
319
418
|
personFromData
|
|
320
419
|
});
|
package/dist/browser.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/browser.ts","../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"],"sourcesContent":["import { PersonFactory } from '@/engine/person-factory';\nimport { UniverseStore } from '@/engine/universe-store';\n\nimport type { Person, UniverseData } from '@/types';\n\nexport { UniverseStore };\nexport { loadUniverse, loadUniverses, loadAllUniverses, getAvailableIds } from '@/universes/browser-loader';\n\nexport function personFromData(universe: UniverseData, seed?: number): Person {\n\treturn PersonFactory.build(universe, seed);\n}\n\nexport type { Person, UniverseInfo } from '@/types';\nexport type { Address, UniverseData, CharacterData, AddressData, DomainsData } from '@/types';\nexport type { CharacterEntry, CharacterQuery } from '@/types';\n","/**\n * Seeded pseudo-random number generator (mulberry32).\n * Returns a function that produces values in [0, 1).\n */\nexport function createRng(seed?: number): () => number {\n\tif (seed === undefined) {\n\t\treturn Math.random;\n\t}\n\n\tlet s = seed;\n\n\treturn function rng(): number {\n\t\ts += 0x6d2b79f5;\n\t\tlet z = s;\n\t\tz = Math.imul(z ^ (z >>> 15), z | 1);\n\t\tz ^= z + Math.imul(z ^ (z >>> 7), z | 61);\n\n\t\treturn ((z ^ (z >>> 14)) >>> 0) / 4294967296;\n\t};\n}\n\nexport function pickRandom<T>(array: T[], rng: () => number): T {\n\tconst index = Math.floor(rng() * array.length);\n\n\treturn array[index];\n}\n","import { pickRandom } from './random';\n\nimport type { DomainsData } from '@/types';\n\nexport class EmailGenerator {\n\tstatic generate(firstName: string, lastName: string, domains: DomainsData, rng: () => number): string {\n\t\tconst domain = pickRandom(domains.emailDomains, rng);\n\t\tconst first = firstName.toLowerCase();\n\t\tconst last = lastName.toLowerCase();\n\n\t\treturn `${first}.${last}@${domain}`;\n\t}\n\n\tstatic generateFromUsername(username: string, domains: DomainsData, rng: () => number): string {\n\t\tconst domain = pickRandom(domains.emailDomains, rng);\n\n\t\treturn `${username}@${domain}`;\n\t}\n}\n","import { pickRandom } from './random';\n\nimport type { DomainsData } from '@/types';\n\nexport class PhoneGenerator {\n\tstatic generate(domains: DomainsData, rng: () => number): string {\n\t\tif (domains.phoneEasterEggs && domains.phoneEasterEggs.length > 0 && rng() < 0.2) {\n\t\t\treturn pickRandom(domains.phoneEasterEggs, rng);\n\t\t}\n\n\t\tconst prefix = pickRandom(domains.phonePrefixes, rng);\n\t\tconst suffix = this.randomDigits(7, rng);\n\n\t\treturn `${prefix}-${suffix.slice(0, 3)}-${suffix.slice(3)}`;\n\t}\n\n\tprivate static randomDigits(count: number, rng: () => number): string {\n\t\tlet result = '';\n\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tresult += Math.floor(rng() * 10).toString();\n\t\t}\n\n\t\treturn result;\n\t}\n}\n","import { pickRandom } from './random';\n\nimport type { DomainsData } from '@/types';\n\nexport class PasswordGenerator {\n\tstatic generate(domains: DomainsData, rng: () => number): string {\n\t\tif (domains.passwordEasterEggs && domains.passwordEasterEggs.length > 0 && rng() < 0.3) {\n\t\t\treturn pickRandom(domains.passwordEasterEggs, rng);\n\t\t}\n\n\t\treturn this.randomPassword(12, rng);\n\t}\n\n\tprivate static randomPassword(length: number, rng: () => number): string {\n\t\tconst chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$';\n\t\tlet result = '';\n\n\t\tfor (let i = 0; i < length; i++) {\n\t\t\tresult += chars[Math.floor(rng() * chars.length)];\n\t\t}\n\n\t\treturn result;\n\t}\n}\n","import { createRng, pickRandom, EmailGenerator, PhoneGenerator, PasswordGenerator } from '@/generators';\n\nimport type { Person, UniverseData, CharacterData } from '@/types';\n\nexport class PersonFactory {\n\tstatic build(universe: UniverseData, seed?: number): Person {\n\t\tconst rng = createRng(seed);\n\n\t\tconst character = pickRandom(universe.characters, rng);\n\n\t\treturn this.buildFromCharacter(character, universe, rng);\n\t}\n\n\tstatic buildByCharacterId(characterId: string, universe: UniverseData, seed?: number): Person {\n\t\tconst character = universe.characters.find((c) => c.id === characterId);\n\n\t\tif (!character) {\n\t\t\tthrow new Error(`Character \"${characterId}\" not found in universe \"${universe.id}\"`);\n\t\t}\n\n\t\tconst rng = createRng(seed);\n\n\t\treturn this.buildFromCharacter(character, universe, rng);\n\t}\n\n\tprivate static buildFromCharacter(character: CharacterData, universe: UniverseData, rng: () => number): Person {\n\t\tconst address = character.address ?? pickRandom(universe.addresses, rng);\n\n\t\tconst username = pickRandom(character.usernames, rng);\n\n\t\tconst domains = character.emailDomain ? { ...universe.domains, emailDomains: [character.emailDomain] } : universe.domains;\n\n\t\tconst email = EmailGenerator.generateFromUsername(username, domains, rng);\n\t\tconst phone = PhoneGenerator.generate(universe.domains, rng);\n\t\tconst password = PasswordGenerator.generate(universe.domains, rng);\n\t\tconst quote = pickRandom(character.quotes, rng);\n\t\tconst avatarName = encodeURIComponent(`${character.firstName} ${character.lastName}`);\n\t\tconst avatar = `https://ui-avatars.com/api/?name=${avatarName}&background=random`;\n\n\t\tconst person: Person = {\n\t\t\tid: crypto.randomUUID(),\n\t\t\tcharacterId: character.id,\n\t\t\tfirstName: character.firstName,\n\t\t\tlastName: character.lastName,\n\t\t\tusername,\n\t\t\temail,\n\t\t\tpassword,\n\t\t\tphone,\n\t\t\taddress: {\n\t\t\t\tstreet: address.street,\n\t\t\t\tcity: address.city,\n\t\t\t\tstate: address.state ?? '',\n\t\t\t\tzip: address.zip ?? '',\n\t\t\t\tcountry: address.country\n\t\t\t},\n\t\t\tprofession: character.profession,\n\t\t\tinterests: character.interests,\n\t\t\tquote,\n\t\t\tuniverse: universe.id,\n\t\t\tuniverseName: universe.name,\n\t\t\tavatar\n\t\t};\n\n\t\treturn person;\n\t}\n}\n","import { createRng } from '@/generators';\n\nimport { PersonFactory } from './person-factory';\n\nimport type { UniverseData, Person, CharacterEntry, CharacterQuery } from '@/types';\n\nexport class UniverseStore {\n\tprivate universes: UniverseData[];\n\tprivate characterIndex: CharacterEntry[];\n\n\tconstructor(universes: UniverseData[]) {\n\t\tthis.universes = universes;\n\t\tthis.characterIndex = this.buildIndex(universes);\n\t}\n\n\tget index(): CharacterEntry[] {\n\t\treturn this.characterIndex;\n\t}\n\n\tgetInterests(universeIds?: string[]): string[] {\n\t\tconst entries =\n\t\t\tuniverseIds && universeIds.length > 0\n\t\t\t\t? this.characterIndex.filter((e) => universeIds.includes(e.universeId))\n\t\t\t\t: this.characterIndex;\n\n\t\tconst interestSet = new Set<string>();\n\n\t\tfor (const entry of entries) {\n\t\t\tfor (const interest of entry.interests) {\n\t\t\t\tinterestSet.add(interest);\n\t\t\t}\n\t\t}\n\n\t\tconst result = Array.from(interestSet).sort();\n\n\t\treturn result;\n\t}\n\n\tgetUniverses(): { id: string; name: string; characterCount: number }[] {\n\t\tconst result = this.universes.map((u) => ({\n\t\t\tid: u.id,\n\t\t\tname: u.name,\n\t\t\tcharacterCount: u.characters.length\n\t\t}));\n\n\t\treturn result;\n\t}\n\n\tfindCharacters(query: CharacterQuery): CharacterEntry[] {\n\t\tlet entries = this.characterIndex;\n\n\t\tif (query.universes && query.universes.length > 0) {\n\t\t\tentries = entries.filter((e) => query.universes!.includes(e.universeId));\n\t\t}\n\n\t\tif (query.name && query.name.trim().length > 0) {\n\t\t\tconst needle = query.name.toLowerCase();\n\n\t\t\tentries = entries.filter((e) => {\n\t\t\t\tconst fullName = `${e.firstName} ${e.lastName}`.toLowerCase();\n\n\t\t\t\treturn fullName.includes(needle);\n\t\t\t});\n\t\t}\n\n\t\tif (query.interests && query.interests.length > 0) {\n\t\t\tconst mode = query.interestsMode ?? 'or';\n\n\t\t\tif (mode === 'and') {\n\t\t\t\tentries = entries.filter((e) => query.interests!.every((interest) => e.interests.includes(interest)));\n\t\t\t} else {\n\t\t\t\tentries = entries.filter((e) => query.interests!.some((interest) => e.interests.includes(interest)));\n\t\t\t}\n\t\t}\n\n\t\treturn entries;\n\t}\n\n\tpersonByCharacterId(characterId: string, seed?: number): Person {\n\t\tconst entry = this.characterIndex.find((e) => e.characterId === characterId);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Character \"${characterId}\" not found in store`);\n\t\t}\n\n\t\tconst universe = this.universes.find((u) => u.id === entry.universeId);\n\n\t\tif (!universe) {\n\t\t\tthrow new Error(`Universe \"${entry.universeId}\" not found in store`);\n\t\t}\n\n\t\treturn PersonFactory.buildByCharacterId(characterId, universe, seed);\n\t}\n\n\tgeneratePersonas(query: CharacterQuery, count: number, seed?: number): Person[] {\n\t\tconst matching = this.findCharacters(query);\n\n\t\tif (matching.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst rng = createRng(seed);\n\t\tconst actualCount = Math.min(count, matching.length);\n\n\t\tconst shuffled = [...matching].sort(() => rng() - 0.5);\n\t\tconst selected = shuffled.slice(0, actualCount);\n\t\tconst personas: Person[] = [];\n\n\t\tfor (let i = 0; i < selected.length; i++) {\n\t\t\tconst entry = selected[i];\n\t\t\tconst universe = this.universes.find((u) => u.id === entry.universeId)!;\n\t\t\tconst personSeed = seed !== undefined ? seed + i : undefined;\n\n\t\t\tpersonas.push(PersonFactory.buildByCharacterId(entry.characterId, universe, personSeed));\n\t\t}\n\n\t\treturn personas;\n\t}\n\n\tprivate buildIndex(universes: UniverseData[]): CharacterEntry[] {\n\t\tconst index: CharacterEntry[] = [];\n\n\t\tfor (const universe of universes) {\n\t\t\tfor (const character of universe.characters) {\n\t\t\t\tconst entry: CharacterEntry = {\n\t\t\t\t\tcharacterId: character.id,\n\t\t\t\t\tuniverseId: universe.id,\n\t\t\t\t\tuniverseName: universe.name,\n\t\t\t\t\tfirstName: character.firstName,\n\t\t\t\t\tlastName: character.lastName,\n\t\t\t\t\tinterests: character.interests,\n\t\t\t\t\tprofession: character.profession\n\t\t\t\t};\n\n\t\t\t\tindex.push(entry);\n\t\t\t}\n\t\t}\n\n\t\treturn index;\n\t}\n}\n","import type { UniverseData, CharacterData, AddressData, DomainsData } from '@/types';\n\ninterface MetaJson {\n\tid: string;\n\tname: 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 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\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"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/browser.ts","../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"],"sourcesContent":["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","/**\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"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACIO,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;;;ACrBO,IAAM,iBAAN,MAAqB;AAAA,EAC3B,OAAO,SAAS,WAAmB,UAAkB,SAAsB,KAA2B;AACrG,UAAM,SAAS,WAAW,QAAQ,cAAc,GAAG;AACnD,UAAM,QAAQ,UAAU,YAAY;AACpC,UAAM,OAAO,SAAS,YAAY;AAElC,WAAO,GAAG,KAAK,IAAI,IAAI,IAAI,MAAM;AAAA,EAClC;AAAA,EAEA,OAAO,qBAAqB,UAAkB,SAAsB,KAA2B;AAC9F,UAAM,SAAS,WAAW,QAAQ,cAAc,GAAG;AAEnD,WAAO,GAAG,QAAQ,IAAI,MAAM;AAAA,EAC7B;AACD;;;ACdO,IAAM,iBAAN,MAAqB;AAAA,EAC3B,OAAO,SAAS,SAAsB,KAA2B;AAChE,QAAI,QAAQ,mBAAmB,QAAQ,gBAAgB,SAAS,KAAK,IAAI,IAAI,KAAK;AACjF,aAAO,WAAW,QAAQ,iBAAiB,GAAG;AAAA,IAC/C;AAEA,UAAM,SAAS,WAAW,QAAQ,eAAe,GAAG;AACpD,UAAM,SAAS,KAAK,aAAa,GAAG,GAAG;AAEvC,WAAO,GAAG,MAAM,IAAI,OAAO,MAAM,GAAG,CAAC,CAAC,IAAI,OAAO,MAAM,CAAC,CAAC;AAAA,EAC1D;AAAA,EAEA,OAAe,aAAa,OAAe,KAA2B;AACrE,QAAI,SAAS;AAEb,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC/B,gBAAU,KAAK,MAAM,IAAI,IAAI,EAAE,EAAE,SAAS;AAAA,IAC3C;AAEA,WAAO;AAAA,EACR;AACD;;;ACrBO,IAAM,oBAAN,MAAwB;AAAA,EAC9B,OAAO,SAAS,SAAsB,KAA2B;AAChE,QAAI,QAAQ,sBAAsB,QAAQ,mBAAmB,SAAS,KAAK,IAAI,IAAI,KAAK;AACvF,aAAO,WAAW,QAAQ,oBAAoB,GAAG;AAAA,IAClD;AAEA,WAAO,KAAK,eAAe,IAAI,GAAG;AAAA,EACnC;AAAA,EAEA,OAAe,eAAe,QAAgB,KAA2B;AACxE,UAAM,QAAQ;AACd,QAAI,SAAS;AAEb,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAChC,gBAAU,MAAM,KAAK,MAAM,IAAI,IAAI,MAAM,MAAM,CAAC;AAAA,IACjD;AAEA,WAAO;AAAA,EACR;AACD;;;ACnBO,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,UAAU,UAAU,cAAc,EAAE,GAAG,SAAS,SAAS,cAAc,CAAC,UAAU,WAAW,EAAE,IAAI,SAAS;AAClH,UAAM,MAAM,UAAU,CAAC;AACvB,UAAM,QAAQ,eAAe,qBAAqB,UAAU,SAAS,GAAG;AACxE,UAAM,QAAQ,eAAe,SAAS,SAAS,SAAS,GAAG;AAC3D,UAAM,WAAW,kBAAkB,SAAS,SAAS,SAAS,GAAG;AACjE,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;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;AAEvE,UAAM,WAAW,WAAW,UAAU,WAAW,GAAG;AAEpD,UAAM,UAAU,UAAU,cAAc,EAAE,GAAG,SAAS,SAAS,cAAc,CAAC,UAAU,WAAW,EAAE,IAAI,SAAS;AAElH,UAAM,QAAQ,eAAe,qBAAqB,UAAU,SAAS,GAAG;AACxE,UAAM,QAAQ,eAAe,SAAS,SAAS,SAAS,GAAG;AAC3D,UAAM,WAAW,kBAAkB,SAAS,SAAS,SAAS,GAAG;AACjE,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;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;;;ACtGO,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;;;ACjJA;AASA,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;AACpF,IAAM,gBAAgB,YAAY,KAAK,0BAA0B,EAAE,OAAO,MAAM,CAAC;AAEjF,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;AACnC,QAAM,cAAc,WAAW,EAAE;AAEjC,QAAM,aAAa,YAAY,QAAQ;AACvC,QAAM,mBAAmB,iBAAiB,cAAc;AACxD,QAAM,kBAAkB,eAAe,aAAa;AACpD,QAAM,gBAAgB,cAAc,WAAW;AAE/C,MAAI,CAAC,cAAc,CAAC,oBAAoB,CAAC,mBAAmB,CAAC,eAAe;AAC3E,UAAM,IAAI,MAAM,aAAa,EAAE,aAAa;AAAA,EAC7C;AAEA,QAAM,CAAC,YAAY,kBAAkB,iBAAiB,aAAa,IAAI,MAAM,QAAQ,IAAI;AAAA,IACxF,WAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,cAAc;AAAA,EACf,CAAC;AAED,QAAM,OAAQ,WAAqC;AACnD,QAAM,aAAc,iBAAkD;AACtE,QAAM,YAAa,gBAA+C;AAClE,QAAM,UAAW,cAA2C;AAE5D,QAAM,eAA6B;AAAA,IAClC,IAAI,KAAK;AAAA,IACT,MAAM,KAAK;AAAA,IACX,OAAO,KAAK;AAAA,IACZ,aAAa,KAAK;AAAA,IAClB;AAAA,IACA;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,kBAAqC;AAC1D,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,UAAU,oBAAI,IAAY;AAEhC,aAAW,YAAY,WAAW;AACjC,eAAW,WAAW,SAAS,WAAW;AACzC,UAAI,QAAQ,MAAM;AACjB,gBAAQ,IAAI,QAAQ,IAAI;AAAA,MACzB;AAAA,IACD;AAAA,EACD;AAEA,QAAM,SAAS,MAAM,KAAK,OAAO,EAAE,KAAK;AAExC,SAAO;AACR;;;APvHO,SAAS,eAAe,UAAwB,MAAuB;AAC7E,SAAO,cAAc,MAAM,UAAU,IAAI;AAC1C;","names":[]}
|
package/dist/browser.d.cts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { U as UniverseData, P as Person } from './universe-store-
|
|
2
|
-
export { A as Address,
|
|
1
|
+
import { U as UniverseMeta, a as UniverseData, P as Person } from './universe-store-Del1UHgn.cjs';
|
|
2
|
+
export { A as Address, b as AddressData, C as CharacterData, c as CharacterEntry, d as CharacterQuery, D as DomainsData, e as UniverseStore } from './universe-store-Del1UHgn.cjs';
|
|
3
3
|
|
|
4
4
|
declare function getAvailableIds(): string[];
|
|
5
|
+
declare function loadUniverseMeta(id: string): Promise<UniverseMeta>;
|
|
6
|
+
declare function getManifest(): Promise<UniverseMeta[]>;
|
|
5
7
|
declare function loadUniverse(id: string): Promise<UniverseData>;
|
|
6
8
|
declare function loadUniverses(ids: string[]): Promise<UniverseData[]>;
|
|
7
9
|
declare function loadAllUniverses(): Promise<UniverseData[]>;
|
|
10
|
+
declare function getAllInterests(): Promise<string[]>;
|
|
11
|
+
declare function getAllLocations(): Promise<string[]>;
|
|
8
12
|
|
|
9
13
|
declare function personFromData(universe: UniverseData, seed?: number): Person;
|
|
10
14
|
|
|
11
|
-
export { Person, UniverseData, getAvailableIds, loadAllUniverses, loadUniverse, loadUniverses, personFromData };
|
|
15
|
+
export { Person, UniverseData, UniverseMeta, getAllInterests, getAllLocations, getAvailableIds, getManifest, loadAllUniverses, loadUniverse, loadUniverseMeta, loadUniverses, personFromData };
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { U as UniverseData, P as Person } from './universe-store-
|
|
2
|
-
export { A as Address,
|
|
1
|
+
import { U as UniverseMeta, a as UniverseData, P as Person } from './universe-store-Del1UHgn.js';
|
|
2
|
+
export { A as Address, b as AddressData, C as CharacterData, c as CharacterEntry, d as CharacterQuery, D as DomainsData, e as UniverseStore } from './universe-store-Del1UHgn.js';
|
|
3
3
|
|
|
4
4
|
declare function getAvailableIds(): string[];
|
|
5
|
+
declare function loadUniverseMeta(id: string): Promise<UniverseMeta>;
|
|
6
|
+
declare function getManifest(): Promise<UniverseMeta[]>;
|
|
5
7
|
declare function loadUniverse(id: string): Promise<UniverseData>;
|
|
6
8
|
declare function loadUniverses(ids: string[]): Promise<UniverseData[]>;
|
|
7
9
|
declare function loadAllUniverses(): Promise<UniverseData[]>;
|
|
10
|
+
declare function getAllInterests(): Promise<string[]>;
|
|
11
|
+
declare function getAllLocations(): Promise<string[]>;
|
|
8
12
|
|
|
9
13
|
declare function personFromData(universe: UniverseData, seed?: number): Person;
|
|
10
14
|
|
|
11
|
-
export { Person, UniverseData, getAvailableIds, loadAllUniverses, loadUniverse, loadUniverses, personFromData };
|
|
15
|
+
export { Person, UniverseData, UniverseMeta, getAllInterests, getAllLocations, getAvailableIds, getManifest, loadAllUniverses, loadUniverse, loadUniverseMeta, loadUniverses, personFromData };
|
package/dist/browser.js
CHANGED
|
@@ -83,6 +83,45 @@ var PersonFactory = class {
|
|
|
83
83
|
const rng = createRng(seed);
|
|
84
84
|
return this.buildFromCharacter(character, universe, rng);
|
|
85
85
|
}
|
|
86
|
+
static buildCanonical(characterId, universe) {
|
|
87
|
+
const character = universe.characters.find((c) => c.id === characterId);
|
|
88
|
+
if (!character) {
|
|
89
|
+
throw new Error(`Character "${characterId}" not found in universe "${universe.id}"`);
|
|
90
|
+
}
|
|
91
|
+
const address = character.address ?? universe.addresses[0];
|
|
92
|
+
const username = character.usernames[0];
|
|
93
|
+
const domains = character.emailDomain ? { ...universe.domains, emailDomains: [character.emailDomain] } : universe.domains;
|
|
94
|
+
const rng = createRng(0);
|
|
95
|
+
const email = EmailGenerator.generateFromUsername(username, domains, rng);
|
|
96
|
+
const phone = PhoneGenerator.generate(universe.domains, rng);
|
|
97
|
+
const password = PasswordGenerator.generate(universe.domains, rng);
|
|
98
|
+
const quote = character.quotes[0];
|
|
99
|
+
const person = {
|
|
100
|
+
id: crypto.randomUUID(),
|
|
101
|
+
characterId: character.id,
|
|
102
|
+
firstName: character.firstName,
|
|
103
|
+
lastName: character.lastName,
|
|
104
|
+
username,
|
|
105
|
+
email,
|
|
106
|
+
password,
|
|
107
|
+
phone,
|
|
108
|
+
address: {
|
|
109
|
+
street: address.street,
|
|
110
|
+
city: address.city,
|
|
111
|
+
state: address.state ?? "",
|
|
112
|
+
zip: address.zip ?? "",
|
|
113
|
+
country: address.country
|
|
114
|
+
},
|
|
115
|
+
profession: character.profession,
|
|
116
|
+
interests: character.interests,
|
|
117
|
+
quote,
|
|
118
|
+
universe: universe.id,
|
|
119
|
+
universeName: universe.name,
|
|
120
|
+
...character.symbol ? { symbol: character.symbol } : {},
|
|
121
|
+
...character.color ? { color: character.color } : {}
|
|
122
|
+
};
|
|
123
|
+
return person;
|
|
124
|
+
}
|
|
86
125
|
static buildFromCharacter(character, universe, rng) {
|
|
87
126
|
const address = character.address ?? pickRandom(universe.addresses, rng);
|
|
88
127
|
const username = pickRandom(character.usernames, rng);
|
|
@@ -91,8 +130,6 @@ var PersonFactory = class {
|
|
|
91
130
|
const phone = PhoneGenerator.generate(universe.domains, rng);
|
|
92
131
|
const password = PasswordGenerator.generate(universe.domains, rng);
|
|
93
132
|
const quote = pickRandom(character.quotes, rng);
|
|
94
|
-
const avatarName = encodeURIComponent(`${character.firstName} ${character.lastName}`);
|
|
95
|
-
const avatar = `https://ui-avatars.com/api/?name=${avatarName}&background=random`;
|
|
96
133
|
const person = {
|
|
97
134
|
id: crypto.randomUUID(),
|
|
98
135
|
characterId: character.id,
|
|
@@ -114,7 +151,8 @@ var PersonFactory = class {
|
|
|
114
151
|
quote,
|
|
115
152
|
universe: universe.id,
|
|
116
153
|
universeName: universe.name,
|
|
117
|
-
|
|
154
|
+
...character.symbol ? { symbol: character.symbol } : {},
|
|
155
|
+
...character.color ? { color: character.color } : {}
|
|
118
156
|
};
|
|
119
157
|
return person;
|
|
120
158
|
}
|
|
@@ -143,11 +181,15 @@ var UniverseStore = class {
|
|
|
143
181
|
return result;
|
|
144
182
|
}
|
|
145
183
|
getUniverses() {
|
|
146
|
-
const result = this.universes.map((u) =>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
184
|
+
const result = this.universes.map((u) => {
|
|
185
|
+
const meta = {
|
|
186
|
+
id: u.id,
|
|
187
|
+
name: u.name,
|
|
188
|
+
genre: u.genre,
|
|
189
|
+
description: u.description
|
|
190
|
+
};
|
|
191
|
+
return meta;
|
|
192
|
+
});
|
|
151
193
|
return result;
|
|
152
194
|
}
|
|
153
195
|
findCharacters(query) {
|
|
@@ -233,6 +275,27 @@ function extractId(path) {
|
|
|
233
275
|
function getAvailableIds() {
|
|
234
276
|
return Object.keys(metaModules).map(extractId);
|
|
235
277
|
}
|
|
278
|
+
async function loadUniverseMeta(id) {
|
|
279
|
+
const metaPath = `../data/${id}/meta.json`;
|
|
280
|
+
const metaLoader = metaModules[metaPath];
|
|
281
|
+
if (!metaLoader) {
|
|
282
|
+
throw new Error(`Universe "${id}" not found`);
|
|
283
|
+
}
|
|
284
|
+
const metaModule = await metaLoader();
|
|
285
|
+
const meta = metaModule.default;
|
|
286
|
+
const result = {
|
|
287
|
+
id: meta.id,
|
|
288
|
+
name: meta.name,
|
|
289
|
+
genre: meta.genre,
|
|
290
|
+
description: meta.description
|
|
291
|
+
};
|
|
292
|
+
return result;
|
|
293
|
+
}
|
|
294
|
+
async function getManifest() {
|
|
295
|
+
const ids = getAvailableIds();
|
|
296
|
+
const result = await Promise.all(ids.map((id) => loadUniverseMeta(id)));
|
|
297
|
+
return result;
|
|
298
|
+
}
|
|
236
299
|
async function loadUniverse(id) {
|
|
237
300
|
const metaPath = `../data/${id}/meta.json`;
|
|
238
301
|
const charactersPath = `../data/${id}/characters.json`;
|
|
@@ -258,6 +321,8 @@ async function loadUniverse(id) {
|
|
|
258
321
|
const universeData = {
|
|
259
322
|
id: meta.id,
|
|
260
323
|
name: meta.name,
|
|
324
|
+
genre: meta.genre,
|
|
325
|
+
description: meta.description,
|
|
261
326
|
characters,
|
|
262
327
|
addresses,
|
|
263
328
|
domains
|
|
@@ -272,6 +337,32 @@ async function loadAllUniverses() {
|
|
|
272
337
|
const ids = getAvailableIds();
|
|
273
338
|
return loadUniverses(ids);
|
|
274
339
|
}
|
|
340
|
+
async function getAllInterests() {
|
|
341
|
+
const universes = await loadAllUniverses();
|
|
342
|
+
const interestSet = /* @__PURE__ */ new Set();
|
|
343
|
+
for (const universe of universes) {
|
|
344
|
+
for (const character of universe.characters) {
|
|
345
|
+
for (const interest of character.interests) {
|
|
346
|
+
interestSet.add(interest);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
const result = Array.from(interestSet).sort();
|
|
351
|
+
return result;
|
|
352
|
+
}
|
|
353
|
+
async function getAllLocations() {
|
|
354
|
+
const universes = await loadAllUniverses();
|
|
355
|
+
const citySet = /* @__PURE__ */ new Set();
|
|
356
|
+
for (const universe of universes) {
|
|
357
|
+
for (const address of universe.addresses) {
|
|
358
|
+
if (address.city) {
|
|
359
|
+
citySet.add(address.city);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
const result = Array.from(citySet).sort();
|
|
364
|
+
return result;
|
|
365
|
+
}
|
|
275
366
|
|
|
276
367
|
// src/browser.ts
|
|
277
368
|
function personFromData(universe, seed) {
|
|
@@ -279,9 +370,13 @@ function personFromData(universe, seed) {
|
|
|
279
370
|
}
|
|
280
371
|
export {
|
|
281
372
|
UniverseStore,
|
|
373
|
+
getAllInterests,
|
|
374
|
+
getAllLocations,
|
|
282
375
|
getAvailableIds,
|
|
376
|
+
getManifest,
|
|
283
377
|
loadAllUniverses,
|
|
284
378
|
loadUniverse,
|
|
379
|
+
loadUniverseMeta,
|
|
285
380
|
loadUniverses,
|
|
286
381
|
personFromData
|
|
287
382
|
};
|
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\tprivate static buildFromCharacter(character: CharacterData, universe: UniverseData, rng: () => number): Person {\n\t\tconst address = character.address ?? pickRandom(universe.addresses, rng);\n\n\t\tconst username = pickRandom(character.usernames, rng);\n\n\t\tconst domains = character.emailDomain ? { ...universe.domains, emailDomains: [character.emailDomain] } : universe.domains;\n\n\t\tconst email = EmailGenerator.generateFromUsername(username, domains, rng);\n\t\tconst phone = PhoneGenerator.generate(universe.domains, rng);\n\t\tconst password = PasswordGenerator.generate(universe.domains, rng);\n\t\tconst quote = pickRandom(character.quotes, rng);\n\t\tconst avatarName = encodeURIComponent(`${character.firstName} ${character.lastName}`);\n\t\tconst avatar = `https://ui-avatars.com/api/?name=${avatarName}&background=random`;\n\n\t\tconst person: Person = {\n\t\t\tid: crypto.randomUUID(),\n\t\t\tcharacterId: character.id,\n\t\t\tfirstName: character.firstName,\n\t\t\tlastName: character.lastName,\n\t\t\tusername,\n\t\t\temail,\n\t\t\tpassword,\n\t\t\tphone,\n\t\t\taddress: {\n\t\t\t\tstreet: address.street,\n\t\t\t\tcity: address.city,\n\t\t\t\tstate: address.state ?? '',\n\t\t\t\tzip: address.zip ?? '',\n\t\t\t\tcountry: address.country\n\t\t\t},\n\t\t\tprofession: character.profession,\n\t\t\tinterests: character.interests,\n\t\t\tquote,\n\t\t\tuniverse: universe.id,\n\t\t\tuniverseName: universe.name,\n\t\t\tavatar\n\t\t};\n\n\t\treturn person;\n\t}\n}\n","import { createRng } from '@/generators';\n\nimport { PersonFactory } from './person-factory';\n\nimport type { UniverseData, Person, CharacterEntry, CharacterQuery } from '@/types';\n\nexport class UniverseStore {\n\tprivate universes: UniverseData[];\n\tprivate characterIndex: CharacterEntry[];\n\n\tconstructor(universes: UniverseData[]) {\n\t\tthis.universes = universes;\n\t\tthis.characterIndex = this.buildIndex(universes);\n\t}\n\n\tget index(): CharacterEntry[] {\n\t\treturn this.characterIndex;\n\t}\n\n\tgetInterests(universeIds?: string[]): string[] {\n\t\tconst entries =\n\t\t\tuniverseIds && universeIds.length > 0\n\t\t\t\t? this.characterIndex.filter((e) => universeIds.includes(e.universeId))\n\t\t\t\t: this.characterIndex;\n\n\t\tconst interestSet = new Set<string>();\n\n\t\tfor (const entry of entries) {\n\t\t\tfor (const interest of entry.interests) {\n\t\t\t\tinterestSet.add(interest);\n\t\t\t}\n\t\t}\n\n\t\tconst result = Array.from(interestSet).sort();\n\n\t\treturn result;\n\t}\n\n\tgetUniverses(): { id: string; name: string; characterCount: number }[] {\n\t\tconst result = this.universes.map((u) => ({\n\t\t\tid: u.id,\n\t\t\tname: u.name,\n\t\t\tcharacterCount: u.characters.length\n\t\t}));\n\n\t\treturn result;\n\t}\n\n\tfindCharacters(query: CharacterQuery): CharacterEntry[] {\n\t\tlet entries = this.characterIndex;\n\n\t\tif (query.universes && query.universes.length > 0) {\n\t\t\tentries = entries.filter((e) => query.universes!.includes(e.universeId));\n\t\t}\n\n\t\tif (query.name && query.name.trim().length > 0) {\n\t\t\tconst needle = query.name.toLowerCase();\n\n\t\t\tentries = entries.filter((e) => {\n\t\t\t\tconst fullName = `${e.firstName} ${e.lastName}`.toLowerCase();\n\n\t\t\t\treturn fullName.includes(needle);\n\t\t\t});\n\t\t}\n\n\t\tif (query.interests && query.interests.length > 0) {\n\t\t\tconst mode = query.interestsMode ?? 'or';\n\n\t\t\tif (mode === 'and') {\n\t\t\t\tentries = entries.filter((e) => query.interests!.every((interest) => e.interests.includes(interest)));\n\t\t\t} else {\n\t\t\t\tentries = entries.filter((e) => query.interests!.some((interest) => e.interests.includes(interest)));\n\t\t\t}\n\t\t}\n\n\t\treturn entries;\n\t}\n\n\tpersonByCharacterId(characterId: string, seed?: number): Person {\n\t\tconst entry = this.characterIndex.find((e) => e.characterId === characterId);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Character \"${characterId}\" not found in store`);\n\t\t}\n\n\t\tconst universe = this.universes.find((u) => u.id === entry.universeId);\n\n\t\tif (!universe) {\n\t\t\tthrow new Error(`Universe \"${entry.universeId}\" not found in store`);\n\t\t}\n\n\t\treturn PersonFactory.buildByCharacterId(characterId, universe, seed);\n\t}\n\n\tgeneratePersonas(query: CharacterQuery, count: number, seed?: number): Person[] {\n\t\tconst matching = this.findCharacters(query);\n\n\t\tif (matching.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst rng = createRng(seed);\n\t\tconst actualCount = Math.min(count, matching.length);\n\n\t\tconst shuffled = [...matching].sort(() => rng() - 0.5);\n\t\tconst selected = shuffled.slice(0, actualCount);\n\t\tconst personas: Person[] = [];\n\n\t\tfor (let i = 0; i < selected.length; i++) {\n\t\t\tconst entry = selected[i];\n\t\t\tconst universe = this.universes.find((u) => u.id === entry.universeId)!;\n\t\t\tconst personSeed = seed !== undefined ? seed + i : undefined;\n\n\t\t\tpersonas.push(PersonFactory.buildByCharacterId(entry.characterId, universe, personSeed));\n\t\t}\n\n\t\treturn personas;\n\t}\n\n\tprivate buildIndex(universes: UniverseData[]): CharacterEntry[] {\n\t\tconst index: CharacterEntry[] = [];\n\n\t\tfor (const universe of universes) {\n\t\t\tfor (const character of universe.characters) {\n\t\t\t\tconst entry: CharacterEntry = {\n\t\t\t\t\tcharacterId: character.id,\n\t\t\t\t\tuniverseId: universe.id,\n\t\t\t\t\tuniverseName: universe.name,\n\t\t\t\t\tfirstName: character.firstName,\n\t\t\t\t\tlastName: character.lastName,\n\t\t\t\t\tinterests: character.interests,\n\t\t\t\t\tprofession: character.profession\n\t\t\t\t};\n\n\t\t\t\tindex.push(entry);\n\t\t\t}\n\t\t}\n\n\t\treturn index;\n\t}\n}\n","import type { UniverseData, CharacterData, AddressData, DomainsData } from '@/types';\n\ninterface MetaJson {\n\tid: string;\n\tname: 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 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\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","import { PersonFactory } from '@/engine/person-factory';\nimport { UniverseStore } from '@/engine/universe-store';\n\nimport type { Person, UniverseData } from '@/types';\n\nexport { UniverseStore };\nexport { loadUniverse, loadUniverses, loadAllUniverses, getAvailableIds } from '@/universes/browser-loader';\n\nexport function personFromData(universe: UniverseData, seed?: number): Person {\n\treturn PersonFactory.build(universe, seed);\n}\n\nexport type { Person, UniverseInfo } 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/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":[]}
|