@jaypie/mcp 0.1.7 → 0.1.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jaypie/mcp",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Jaypie MCP",
5
5
  "repository": {
6
6
  "type": "git",
@@ -45,6 +45,5 @@
45
45
  },
46
46
  "publishConfig": {
47
47
  "access": "public"
48
- },
49
- "gitHead": "14683b303359f95dc63e58998959fddae3c90e97"
48
+ }
50
49
  }
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: coding style resource, helpful when stuck on lint errors
3
3
  globs: packages/fabricator/**
4
+ version: 0.3.0
4
5
  ---
5
6
  # Brief Guide to @jaypie/fabricator
6
7
 
@@ -17,6 +18,8 @@ The `Fabricator` class wraps faker.js and provides:
17
18
  - **Direct faker access**: All faker modules are proxied for convenience
18
19
  - **Enhanced random number generation**: Built-in `random()` function with advanced options
19
20
  - **Custom generators**: Specialized methods like `words()` and `generate.person()`
21
+ - **Unique identifiers**: Each fabricator has an `id` (UUID) and `name` property
22
+ - **Nested fabricators**: Support for hierarchical data generation with child fabricators
20
23
 
21
24
  ```typescript
22
25
  import { fabricator } from "@jaypie/fabricator";
@@ -27,6 +30,20 @@ const fab = fabricator();
27
30
  // Create seeded (deterministic) fabricator
28
31
  const seededFab = fabricator("my-seed");
29
32
  const uuidFab = fabricator("550e8400-e29b-41d4-a716-446655440000");
33
+
34
+ // Access built-in properties
35
+ console.log(fab.id); // UUID
36
+ console.log(fab.name); // Generated name like "Happy Mountain"
37
+ ```
38
+
39
+ **Options**:
40
+ ```typescript
41
+ const fab = fabricator("my-seed", {
42
+ name: "Custom Name", // String or function
43
+ generator: {
44
+ name: ({ fabricator }) => fabricator.faker.person.firstName()
45
+ }
46
+ });
30
47
  ```
31
48
 
32
49
  ### 2. Deterministic Seeding
@@ -43,30 +60,54 @@ fab2.faker.person.firstName(); // "Jordan" (same!)
43
60
 
44
61
  **UUID Seeding**: UUIDs are converted to numeric arrays using `uuidToBytes` for efficient seeding.
45
62
 
63
+ **Environment Variable**: Set `PROJECT_SEED` environment variable to provide a default seed for all unseeded fabricators:
64
+ ```typescript
65
+ process.env.PROJECT_SEED = "my-project-seed";
66
+ const fab = fabricator(); // Uses PROJECT_SEED
67
+ ```
68
+
46
69
  ### 3. Random Number Generation
47
70
 
48
71
  The `random()` function provides advanced randomness with multiple distribution types:
49
72
 
50
73
  **Basic Usage:**
51
74
  ```typescript
52
- fab.random(); // 0-1 float
53
- fab.random({ min: 1, max: 10 }); // 1-10 float
54
- fab.random({ min: 1, max: 10, integer: true }); // 1-10 integer
75
+ fab.random(); // 0-1 float
76
+ fab.random({ min: 1, max: 10 }); // 1-10 float
77
+ fab.random({ min: 1, max: 10, integer: true }); // 1-10 integer
55
78
  ```
56
79
 
57
- **Advanced Options:**
58
- - `min/max`: Bounds (defaults: 0-1)
59
- - `integer`: Return integers (default: false)
60
- - `mean/stddev`: Normal distribution
61
- - `precision`: Decimal places
62
- - `currency`: Shorthand for precision: 2
63
- - `start`: Add offset to result
64
- - `seed`: Override the fabricator's seed for this call only
80
+ **All Options:**
81
+ ```typescript
82
+ fab.random({
83
+ min: 1, // Minimum value (default: 0)
84
+ max: 10, // Maximum value (default: 1)
85
+ integer: true, // Return integer instead of float (default: false)
86
+ mean: 5, // For normal distribution
87
+ stddev: 2, // For normal distribution
88
+ precision: 2, // Decimal places
89
+ currency: true, // Shorthand for precision: 2
90
+ start: 100, // Add offset to result
91
+ seed: "override" // Override fabricator's seed for this call only
92
+ });
93
+ ```
65
94
 
66
95
  **Smart Defaults:**
67
96
  - If only `min` is set, `max` defaults to `min * 2`
68
97
  - Normal distribution with `mean/stddev` can optionally be clamped by `min/max`
69
98
 
99
+ **Common Patterns:**
100
+ ```typescript
101
+ // Currency values
102
+ fab.random({ min: 10, max: 1000, currency: true }); // e.g., 542.73
103
+
104
+ // Percentages
105
+ fab.random({ min: 0, max: 100, integer: true }); // e.g., 42
106
+
107
+ // Weighted random with normal distribution
108
+ fab.random({ mean: 50, stddev: 15, min: 0, max: 100 }); // Clusters around 50
109
+ ```
110
+
70
111
  ### 4. Faker Integration
71
112
 
72
113
  All faker modules are directly accessible through getters:
@@ -81,14 +122,14 @@ fab.company.name();
81
122
 
82
123
  ### 5. Custom Methods
83
124
 
84
- #### `words()`: Two-Word Combinations
125
+ #### `generate.words()`: Two-Word Combinations
85
126
  Generates one of three patterns randomly:
86
127
  - adjective + noun
87
128
  - adjective + verb
88
129
  - noun + verb
89
130
 
90
131
  ```typescript
91
- fab.words(); // "happy dog" or "quick run" or "mountain climb"
132
+ fab.generate.words(); // "happy dog" or "quick run" or "mountain climb"
92
133
  ```
93
134
 
94
135
  #### `generate.person(id?)`: Complex Person Generator
@@ -135,6 +176,47 @@ export const CHANCE = {
135
176
 
136
177
  Use these for consistent probability calculations across your test data.
137
178
 
179
+ ### 7. Nested Fabricators
180
+
181
+ Create hierarchical data structures with `Fabricator.new()` and nested configurations:
182
+
183
+ ```typescript
184
+ import { Fabricator } from "@jaypie/fabricator";
185
+
186
+ // Define a nested structure
187
+ const world = Fabricator.new({
188
+ seed: "my-world",
189
+ name: ({ fabricator }) => fabricator.location.city(),
190
+ fabricators: {
191
+ cities: {
192
+ name: ({ fabricator }) => fabricator.location.city(),
193
+ fabricators: {
194
+ streets: {
195
+ name: ({ fabricator }) => fabricator.location.street()
196
+ }
197
+ }
198
+ },
199
+ exports: {
200
+ name: ({ fabricator }) => fabricator.commerce.product()
201
+ }
202
+ }
203
+ });
204
+
205
+ // Access nested fabricators
206
+ const cities = world.cities(5); // Array of 5 city fabricators
207
+ const cityGen = world.cities(); // Generator for infinite cities
208
+
209
+ // Access nested child fabricators
210
+ const city = cities[0];
211
+ const streets = city.streets(10); // 10 streets for this city
212
+ ```
213
+
214
+ **Deterministic Child Seeding**: Child fabricators are seeded deterministically based on their parent's ID and their index, ensuring reproducible hierarchies.
215
+
216
+ **Generator vs Array**:
217
+ - `world.cities()` - Returns a generator for unlimited fabricators
218
+ - `world.cities(n)` - Returns an array of exactly n fabricators
219
+
138
220
  ## Architecture
139
221
 
140
222
  ### Internal Utilities
@@ -143,6 +225,131 @@ Use these for consistent probability calculations across your test data.
143
225
  - **`uuidToBytes()`**: Converts UUIDs to byte arrays for seeding
144
226
  - **`uuidToNumber()`**: Converts UUIDs to single numbers (fallback)
145
227
  - **`numericSeedArray()`**: Smart converter that detects UUIDs and uses appropriate conversion
228
+ - **`uuidFrom()`**: Generates deterministic UUID v5 from string or number using `JAYPIE_FABRICATOR_UUID` as namespace
229
+ - **`isUuid()`**: Validates if a string is a properly formatted UUID
230
+
231
+ ## Best Practices & Patterns
232
+
233
+ ### Seeding Strategy
234
+
235
+ Always tie seeds to fabricator instance ID for determinism with variety:
236
+
237
+ ```typescript
238
+ // In parent fabricator method
239
+ for (let i = 0; i < count; i++) {
240
+ const seed = `${this.id}-tenant-${i}`;
241
+ tenants.push(new TenantFabricator({ seed, name }));
242
+ }
243
+
244
+ // In child fabricator method
245
+ for (let i = 0; i < count; i++) {
246
+ const seed = `${this.id}-merchant-${i}`;
247
+ merchants.push(new MerchantFabricator({ seed, name }));
248
+ }
249
+ ```
250
+
251
+ **Result:**
252
+ - Same fabricator instance → same data (deterministic)
253
+ - Different fabricator instance → different data (variety)
254
+ - Each entity gets unique seed: `parentId-entityType-index`
255
+
256
+ ### Name Handling Pattern
257
+
258
+ When passing name functions to child fabricators, pass the function itself (don't call it):
259
+
260
+ ```typescript
261
+ // ✅ Correct - parent will invoke function
262
+ const name = config?.name ? () => config.name : undefined;
263
+ new TenantFabricator({ name, seed });
264
+
265
+ // ❌ Wrong - calling function too early
266
+ const name = config?.name ? config.name : generateName({ fabricator: this });
267
+ new TenantFabricator({ name: () => name, seed });
268
+ ```
269
+
270
+ The parent Fabricator class invokes name functions lazily when `get name()` is accessed and caches the result.
271
+
272
+ ### Generator Functions
273
+
274
+ Export generator functions separately for reusability and testability:
275
+
276
+ ```typescript
277
+ // Export the generator function
278
+ export const generateTenantName = ({ fabricator }: FabricatorNameParams) => {
279
+ const city = fabricator.faker.location.city();
280
+ const suffixes = ["Financial", "Payments", "Commerce"];
281
+ const suffixIndex = Math.floor(fabricator.random() * suffixes.length);
282
+ return `${city} ${suffixes[suffixIndex]}`;
283
+ };
284
+
285
+ // Use in fabricator via generator option
286
+ const fab = new Fabricator({
287
+ seed: "my-seed",
288
+ generator: {
289
+ name: generateTenantName
290
+ }
291
+ });
292
+ ```
293
+
294
+ ### Extending Fabricator
295
+
296
+ Create domain-specific fabricators by extending the base class:
297
+
298
+ ```typescript
299
+ import { Fabricator as JaypieFabricator } from "@jaypie/fabricator";
300
+
301
+ export class TenantFabricator extends JaypieFabricator {
302
+ constructor({
303
+ name,
304
+ seed,
305
+ }: {
306
+ name?: string | ((params: FabricatorNameParams) => string);
307
+ seed?: string | number;
308
+ } = {}) {
309
+ super({
310
+ name,
311
+ seed,
312
+ generator: {
313
+ name: generateTenantName,
314
+ },
315
+ });
316
+ }
317
+
318
+ // Add domain-specific methods
319
+ merchants(count: number): MerchantFabricator[] {
320
+ const merchants: MerchantFabricator[] = [];
321
+ for (let i = 0; i < count; i++) {
322
+ merchants.push(new MerchantFabricator({
323
+ seed: `${this.id}-merchant-${i}`
324
+ }));
325
+ }
326
+ return merchants;
327
+ }
328
+ }
329
+ ```
330
+
331
+ ### Common Anti-Patterns
332
+
333
+ **❌ Don't manage name storage yourself**
334
+ ```typescript
335
+ // Wrong - parent already handles this
336
+ private readonly _name: string;
337
+ get name(): string {
338
+ return this._name;
339
+ }
340
+ ```
341
+ **✅ Right:** Use parent's `get name()` accessor via `generator` option.
342
+
343
+ **❌ Don't pass index parameters**
344
+ ```typescript
345
+ // Wrong - couples fabricator to sequence position
346
+ class TenantFabricator {
347
+ constructor({ index, seed }) {
348
+ this._name = this.generateName(index);
349
+ }
350
+ }
351
+ ```
352
+ **✅ Right:** Use constructor config or generator functions.
146
353
 
147
354
  ## Key Design Patterns
148
355
 
@@ -150,15 +357,5 @@ Use these for consistent probability calculations across your test data.
150
357
  2. **Probabilistic Variations**: Use float rolls with CHANCE constants for realistic data variety
151
358
  3. **Proxy Access**: All faker modules exposed through getters for ergonomic API
152
359
  4. **Seed Flexibility**: Accepts strings, numbers, or UUIDs as seeds
153
-
154
- ## Usage in @entpayco/fabricator
155
-
156
- Your wrapper package should:
157
- - Extend or compose `Fabricator` from `@jaypie/fabricator`
158
- - Add domain-specific generators (payments, accounts, transactions, etc.)
159
- - Follow the same patterns: seeding, probabilistic variations, subfaker for complex objects
160
- - Maintain the same function signature standards (single param, config object, or optional config)
161
-
162
- ---
163
-
164
- Ready to build domain-specific test data generators on this foundation!
360
+ 5. **Hierarchical Generation**: Nested fabricators enable deterministic tree structures for complex data models
361
+ 6. **Identity & Naming**: Every fabricator has a unique ID and name for tracking and debugging
package/LICENSE.txt DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Finlayson Studio, LLC
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.