@jaypie/mcp 0.3.2 โ†’ 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/createMcpServer.d.ts +7 -1
  2. package/dist/index.js +26 -3135
  3. package/dist/index.js.map +1 -1
  4. package/dist/suite.d.ts +1 -0
  5. package/dist/suite.js +2442 -0
  6. package/dist/suite.js.map +1 -0
  7. package/package.json +8 -3
  8. package/release-notes/constructs/1.2.17.md +11 -0
  9. package/release-notes/fabric/0.1.2.md +11 -0
  10. package/release-notes/fabric/0.1.3.md +25 -0
  11. package/release-notes/fabric/0.1.4.md +42 -0
  12. package/release-notes/mcp/0.3.3.md +12 -0
  13. package/release-notes/mcp/0.3.4.md +36 -0
  14. package/release-notes/mcp/0.4.0.md +27 -0
  15. package/release-notes/testkit/1.2.15.md +23 -0
  16. package/skills/agents.md +25 -0
  17. package/skills/aws.md +107 -0
  18. package/skills/cdk.md +141 -0
  19. package/skills/cicd.md +152 -0
  20. package/skills/datadog.md +129 -0
  21. package/skills/debugging.md +148 -0
  22. package/skills/dns.md +134 -0
  23. package/skills/dynamodb.md +140 -0
  24. package/skills/errors.md +142 -0
  25. package/skills/fabric.md +191 -0
  26. package/skills/index.md +7 -0
  27. package/skills/jaypie.md +100 -0
  28. package/skills/legacy.md +97 -0
  29. package/skills/logs.md +160 -0
  30. package/skills/mocks.md +174 -0
  31. package/skills/models.md +195 -0
  32. package/skills/releasenotes.md +94 -0
  33. package/skills/secrets.md +155 -0
  34. package/skills/services.md +175 -0
  35. package/skills/style.md +190 -0
  36. package/skills/tests.md +209 -0
  37. package/skills/tools.md +127 -0
  38. package/skills/topics.md +116 -0
  39. package/skills/variables.md +146 -0
  40. package/skills/writing.md +153 -0
  41. package/prompts/Branch_Management.md +0 -34
  42. package/prompts/Development_Process.md +0 -89
  43. package/prompts/Jaypie_Agent_Rules.md +0 -110
  44. package/prompts/Jaypie_Auth0_Express_Mongoose.md +0 -736
  45. package/prompts/Jaypie_Browser_and_Frontend_Web_Packages.md +0 -18
  46. package/prompts/Jaypie_CDK_Constructs_and_Patterns.md +0 -430
  47. package/prompts/Jaypie_CICD_with_GitHub_Actions.md +0 -371
  48. package/prompts/Jaypie_Commander_CLI_Package.md +0 -166
  49. package/prompts/Jaypie_Core_Errors_and_Logging.md +0 -39
  50. package/prompts/Jaypie_DynamoDB_Package.md +0 -774
  51. package/prompts/Jaypie_Eslint_NPM_Package.md +0 -78
  52. package/prompts/Jaypie_Express_Package.md +0 -630
  53. package/prompts/Jaypie_Fabric_Commander.md +0 -411
  54. package/prompts/Jaypie_Fabric_LLM.md +0 -312
  55. package/prompts/Jaypie_Fabric_Lambda.md +0 -308
  56. package/prompts/Jaypie_Fabric_MCP.md +0 -316
  57. package/prompts/Jaypie_Fabric_Package.md +0 -513
  58. package/prompts/Jaypie_Fabricator.md +0 -617
  59. package/prompts/Jaypie_Ideal_Project_Structure.md +0 -78
  60. package/prompts/Jaypie_Init_CICD_with_GitHub_Actions.md +0 -1186
  61. package/prompts/Jaypie_Init_Express_on_Lambda.md +0 -115
  62. package/prompts/Jaypie_Init_Jaypie_CDK_Package.md +0 -35
  63. package/prompts/Jaypie_Init_Lambda_Package.md +0 -505
  64. package/prompts/Jaypie_Init_Monorepo_Project.md +0 -44
  65. package/prompts/Jaypie_Init_Project_Subpackage.md +0 -65
  66. package/prompts/Jaypie_Legacy_Patterns.md +0 -15
  67. package/prompts/Jaypie_Llm_Calls.md +0 -449
  68. package/prompts/Jaypie_Llm_Tools.md +0 -155
  69. package/prompts/Jaypie_MCP_Package.md +0 -281
  70. package/prompts/Jaypie_Mocks_and_Testkit.md +0 -137
  71. package/prompts/Jaypie_Repokit.md +0 -103
  72. package/prompts/Jaypie_Scrub.md +0 -177
  73. package/prompts/Jaypie_Streaming.md +0 -467
  74. package/prompts/Templates_CDK_Subpackage.md +0 -115
  75. package/prompts/Templates_Express_Subpackage.md +0 -187
  76. package/prompts/Templates_Project_Monorepo.md +0 -326
  77. package/prompts/Templates_Project_Subpackage.md +0 -93
  78. package/prompts/Write_Efficient_Prompt_Guides.md +0 -48
  79. package/prompts/Write_and_Maintain_Engaging_Readme.md +0 -67
@@ -1,617 +0,0 @@
1
- ---
2
- description: coding style resource, helpful when stuck on lint errors
3
- globs: packages/fabricator/**
4
- version: 0.3.0
5
- ---
6
- # Brief Guide to @jaypie/fabricator
7
-
8
- ## Overview
9
-
10
- `@jaypie/fabricator` is a test data generation library built on top of `@faker-js/faker` that provides deterministic, seeded data generation with additional utilities for randomness and complex data patterns.
11
-
12
- ## Core Concepts
13
-
14
- ### 1. The Fabricator Class
15
-
16
- The `Fabricator` class wraps faker.js and provides:
17
- - **Deterministic seeding**: Pass a string, number, or UUID to get reproducible test data
18
- - **Direct faker access**: All faker modules are proxied for convenience
19
- - **Enhanced random number generation**: Built-in `random()` function with advanced options
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
23
-
24
- ```typescript
25
- import { fabricator } from "@jaypie/fabricator";
26
-
27
- // Create unseeded (random) fabricator
28
- const fab = fabricator();
29
-
30
- // Create seeded (deterministic) fabricator
31
- const seededFab = fabricator("my-seed");
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
- });
47
- ```
48
-
49
- ### 2. Deterministic Seeding
50
-
51
- Any string or number can be used as a seed. The same seed always produces the same output:
52
-
53
- ```typescript
54
- const fab1 = fabricator("test-seed");
55
- const fab2 = fabricator("test-seed");
56
-
57
- fab1.faker.person.firstName(); // "Jordan"
58
- fab2.faker.person.firstName(); // "Jordan" (same!)
59
- ```
60
-
61
- **UUID Seeding**: UUIDs are converted to numeric arrays using `uuidToBytes` for efficient seeding.
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
-
69
- ### 3. Random Number Generation
70
-
71
- The `random()` function provides advanced randomness with multiple distribution types:
72
-
73
- **Basic Usage:**
74
- ```typescript
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
78
- ```
79
-
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
- ```
94
-
95
- **Smart Defaults:**
96
- - If only `min` is set, `max` defaults to `min * 2`
97
- - Normal distribution with `mean/stddev` can optionally be clamped by `min/max`
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
-
111
- ### 4. Faker Integration
112
-
113
- All faker modules are directly accessible through getters:
114
-
115
- ```typescript
116
- fab.person.firstName();
117
- fab.internet.email();
118
- fab.location.city();
119
- fab.company.name();
120
- // ... all faker modules available
121
- ```
122
-
123
- ### 5. Custom Methods
124
-
125
- #### `generate.words()`: Two-Word Combinations
126
- Generates one of three patterns randomly:
127
- - adjective + noun
128
- - adjective + verb
129
- - noun + verb
130
-
131
- ```typescript
132
- fab.generate.words(); // "happy dog" or "quick run" or "mountain climb"
133
- ```
134
-
135
- #### `generate.person(id?)`: Complex Person Generator
136
- Creates realistic person data with probabilistic variations:
137
-
138
- ```typescript
139
- const person = fab.generate.person();
140
- // {
141
- // id: "uuid",
142
- // firstName: "Jordan",
143
- // middleName: "Alex" | undefined,
144
- // lastName: "Smith" | "Smith-Jones",
145
- // fullName: "Jordan Smith" | "Jordan Alex Smith"
146
- // }
147
- ```
148
-
149
- **Probabilistic Rules** (using `CHANCE` constants):
150
- - **firstName**: 2.1% chance (RARE) to be a lastName instead
151
- - **middleName**:
152
- - 14.6% chance (UNCOMMON) to be missing
153
- - 2.1% chance (RARE) to be a lastName
154
- - 0.307% chance (EPIC) to have two middle names
155
- - **lastName**: 2.1% chance (RARE) to be hyphenated
156
- - **fullName**: 14.6% chance (UNCOMMON) to include middle name
157
-
158
- **Independent Seeding**: Pass an optional UUID to get deterministic person data that's independent of the parent fabricator's seed:
159
-
160
- ```typescript
161
- const person1 = fab1.generate.person("same-uuid");
162
- const person2 = fab2.generate.person("same-uuid");
163
- // person1 === person2, regardless of fab1/fab2 seeds
164
- ```
165
-
166
- ### 6. Probability Constants
167
-
168
- ```typescript
169
- export const CHANCE = {
170
- UNCOMMON: 0.146, // ~14.6%
171
- RARE: 0.021, // ~2.1%
172
- EPIC: 0.00307, // ~0.3%
173
- LEGENDARY: 0.000441 // ~0.04%
174
- };
175
- ```
176
-
177
- Use these for consistent probability calculations across your test data.
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
-
220
- ## Architecture
221
-
222
- ### Internal Utilities
223
-
224
- - **`numericSeed()`**: Converts strings to numeric seeds using cyrb53 hash
225
- - **`uuidToBytes()`**: Converts UUIDs to byte arrays for seeding
226
- - **`uuidToNumber()`**: Converts UUIDs to single numbers (fallback)
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.
353
-
354
- ## Key Design Patterns
355
-
356
- 1. **Subfaker Pattern**: Complex generators create independent seeded faker instances to ensure deterministic output regardless of parent state
357
- 2. **Probabilistic Variations**: Use float rolls with CHANCE constants for realistic data variety
358
- 3. **Proxy Access**: All faker modules exposed through getters for ergonomic API
359
- 4. **Seed Flexibility**: Accepts strings, numbers, or UUIDs as seeds
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
362
-
363
- ## EventFabricator: Temporal Event Generation
364
-
365
- ### Overview
366
-
367
- `EventFabricator` is an abstract base class for generating temporally-distributed events across a year. It builds on `Fabricator` to add:
368
- - Annual event counts with configurable distribution
369
- - Temporal templates for hour, day, week, month, and date weighting
370
- - Timezone-aware hour shifting
371
- - Derived event system for cascading events
372
-
373
- ### Basic Usage
374
-
375
- ```typescript
376
- import {
377
- EventFabricator,
378
- HOURS_BUSINESS,
379
- DAYS_WEEKDAYS_ONLY,
380
- type CreateEventParams,
381
- } from "@jaypie/fabricator";
382
-
383
- interface SimpleEvent {
384
- id: string;
385
- timestamp: Date;
386
- }
387
-
388
- class SimpleEventFabricator extends EventFabricator<SimpleEvent> {
389
- protected createEvent({ seed, timestamp }: CreateEventParams): SimpleEvent {
390
- return { id: seed, timestamp };
391
- }
392
- }
393
-
394
- const fab = new SimpleEventFabricator({
395
- seed: "my-events",
396
- annualCount: 1000,
397
- template: [HOURS_BUSINESS, DAYS_WEEKDAYS_ONLY],
398
- });
399
-
400
- const events = fab.events({ year: 2025 });
401
- // Returns 1000 events during business hours on weekdays
402
- ```
403
-
404
- ### Temporal Templates
405
-
406
- Templates control event distribution. They can be combined:
407
-
408
- **Hour Templates:**
409
- - `HOURS_BUSINESS` - 8am-5pm
410
- - `HOURS_RETAIL` - 10am-8pm
411
- - `HOURS_EVENING` - 6pm-10pm
412
- - `HOURS_24_7` - All hours equal
413
-
414
- **Day Templates:**
415
- - `DAYS_WEEKDAYS_ONLY` - Mon-Fri only
416
- - `DAYS_NO_SUNDAY` - All but Sunday
417
- - `DAYS_NO_MONDAY` - All but Monday
418
-
419
- **Curve Templates (gradual peaks):**
420
- - `CURVE_EVENING_PEAK` - Peaks at 7pm
421
- - `CURVE_ECOMMERCE` - Peaks at 8pm
422
- - `CURVE_MIDDAY_PEAK` - Peaks at 11am
423
-
424
- **Spike Templates (sharp peaks):**
425
- - `SPIKE_MORNING` - 7-8am peak
426
- - `SPIKE_LUNCH` - 12-1pm peak
427
- - `SPIKE_EVENING` - 6-7pm peak
428
-
429
- **Boost/Lull Templates (multipliers):**
430
- - `BOOST_SUMMER`, `LULL_SUMMER`
431
- - `BOOST_WINTER`, `LULL_WINTER`
432
- - `BOOST_WEEKENDS`, `LULL_WEEKENDS`
433
- - `BOOST_HOLIDAY_SEASON` - Nov-Dec 1.5x
434
-
435
- ```typescript
436
- const fab = new MyFabricator({
437
- template: [
438
- HOURS_BUSINESS,
439
- DAYS_WEEKDAYS_ONLY,
440
- BOOST_HOLIDAY_SEASON,
441
- CURVE_MIDDAY_PEAK,
442
- ],
443
- });
444
- ```
445
-
446
- ## Derived Events: Cascading Event Generation
447
-
448
- ### Overview
449
-
450
- The derived event system allows events to spawn follow-up events based on probabilistic rules. This is ideal for modeling:
451
- - Financial transactions with voids, refunds, chargebacks
452
- - Subscription renewals with payment retries
453
- - Any event chains with cause-and-effect relationships
454
-
455
- ### Configuration
456
-
457
- ```typescript
458
- import {
459
- EventFabricator,
460
- CHANCE,
461
- type DerivedConfig,
462
- type TimestampedEvent,
463
- } from "@jaypie/fabricator";
464
-
465
- interface Transaction extends TimestampedEvent {
466
- id: string;
467
- amount: number;
468
- type: "purchase" | "void" | "refund" | "chargeback";
469
- parentId?: string;
470
- timestamp: Date;
471
- }
472
-
473
- const derivedConfig: DerivedConfig<Transaction> = {
474
- rules: [
475
- {
476
- name: "void",
477
- probability: CHANCE.RARE, // 2.1%
478
- condition: (parent) => parent.type === "purchase",
479
- timing: { mode: "same-day" },
480
- createDerived: ({ parent, seed, timestamp }) => ({
481
- id: seed,
482
- type: "void",
483
- amount: -parent.amount,
484
- timestamp,
485
- parentId: parent.id,
486
- }),
487
- },
488
- {
489
- name: "refund",
490
- probability: 0.10, // 10%
491
- timing: {
492
- mode: "range",
493
- delayMin: 1,
494
- delayMax: 14,
495
- unit: "days",
496
- },
497
- createDerived: ({ parent, seed, timestamp }) => ({
498
- id: seed,
499
- type: "refund",
500
- amount: -parent.amount,
501
- timestamp,
502
- parentId: parent.id,
503
- }),
504
- },
505
- ],
506
- boundaryBehavior: "include", // include | exclude | clamp
507
- maxDepth: 4, // Prevent infinite chains
508
- };
509
- ```
510
-
511
- ### Timing Modes
512
-
513
- ```typescript
514
- interface DerivedTiming {
515
- mode: "same-day" | "fixed" | "range" | "recurring";
516
- delayMin?: number;
517
- delayMax?: number;
518
- unit?: "days" | "weeks" | "months" | "hours" | "minutes" | "seconds";
519
- interval?: number; // For recurring
520
- maxRecurrences?: number; // For recurring
521
- until?: Date | "end-of-year";
522
- }
523
- ```
524
-
525
- **Examples:**
526
- - Same day: `{ mode: "same-day" }`
527
- - Fixed delay: `{ mode: "fixed", delayMin: 7, unit: "days" }`
528
- - Range: `{ mode: "range", delayMin: 1, delayMax: 14, unit: "days" }`
529
- - Monthly recurring: `{ mode: "recurring", interval: 1, unit: "months", until: "end-of-year" }`
530
-
531
- ### Nested Derived Events (Chains)
532
-
533
- Derived events can spawn their own derived events:
534
-
535
- ```typescript
536
- {
537
- name: "chargeback",
538
- probability: CHANCE.RARE,
539
- timing: { mode: "range", delayMin: 30, delayMax: 90, unit: "days" },
540
- createDerived: ({ parent, seed, timestamp }) => ({
541
- id: seed,
542
- type: "chargeback",
543
- amount: -parent.amount,
544
- timestamp,
545
- parentId: parent.id,
546
- }),
547
- derived: [ // Nested rules for chargebacks
548
- {
549
- name: "representment",
550
- probability: 0.70, // 70% of chargebacks
551
- timing: { mode: "range", delayMin: 7, delayMax: 21, unit: "days" },
552
- createDerived: ({ parent, seed, timestamp }) => ({
553
- id: seed,
554
- type: "representment",
555
- amount: Math.abs(parent.amount), // Re-charge
556
- timestamp,
557
- parentId: parent.id,
558
- }),
559
- },
560
- ],
561
- }
562
- ```
563
-
564
- ### Using with EventFabricator
565
-
566
- ```typescript
567
- class TransactionFabricator extends EventFabricator<Transaction> {
568
- constructor(options = {}) {
569
- super({
570
- ...options,
571
- derived: derivedConfig,
572
- template: [HOURS_BUSINESS, DAYS_WEEKDAYS_ONLY],
573
- });
574
- }
575
-
576
- protected createEvent({ seed, timestamp }: CreateEventParams): Transaction {
577
- const fab = new Fabricator({ seed });
578
- return {
579
- id: seed,
580
- type: "purchase",
581
- amount: fab.random({ min: 10, max: 500, currency: true }),
582
- timestamp,
583
- };
584
- }
585
- }
586
-
587
- const fab = new TransactionFabricator({
588
- seed: "my-business",
589
- annualCount: 1000,
590
- });
591
-
592
- // Get all events including derived events
593
- const events = fab.events({ year: 2025 });
594
-
595
- // Get events with metadata (parent refs, depth, rule names)
596
- const eventsWithMeta = fab.eventsWithMeta({ year: 2025 });
597
- ```
598
-
599
- ### Event Metadata
600
-
601
- `eventsWithMeta()` returns events with relationship data:
602
-
603
- ```typescript
604
- interface EventWithDerivedMeta<T> {
605
- event: T;
606
- depth: number; // 0 = primary, 1 = first derived, etc.
607
- parentSeed?: string; // Seed of parent event
608
- ruleName?: string; // Rule that created this derived event
609
- }
610
- ```
611
-
612
- ### Key Properties
613
-
614
- 1. **Deterministic**: Same seed produces same derived event cascade
615
- 2. **Chronological**: All events (primary + derived) sorted by timestamp
616
- 3. **Depth-Limited**: `maxDepth` prevents infinite chains
617
- 4. **Boundary Control**: Events outside target year can be included, excluded, or clamped
@@ -1,78 +0,0 @@
1
- ---
2
- description: Specification for an ideal project structure, referenced by monorepo init
3
- ---
4
-
5
- # Ideal Project Structure ๐Ÿ†
6
-
7
- Specification for an ideal project structure
8
-
9
- ## โœˆ๏ธ Overview
10
-
11
- * Jaypie project opinions and tooling
12
- * ESLint 9+ with @jaypie/eslint
13
- * NPM with Workspaces ("monorepo")
14
- * TypeScript
15
- * Vite
16
- * Vitest .spec sibling to implementation
17
-
18
- ## ๐Ÿงน ESLint
19
-
20
- Only use ESLint 9+ with the flat file config.
21
-
22
- ```javascript
23
- // eslint.config.mjs
24
- export { default as default } from "@jaypie/eslint";
25
- ```
26
-
27
- See context/prompts/Jaypie_Eslint_NPM_Package.md for details and troubleshooting.
28
-
29
- ## ๐Ÿ“ฆ NPM
30
-
31
- ### Configuration
32
-
33
- Follow the naming convention of other subpackages in a monorepo.
34
- Use `"version": "0.0.1"`, `"type": "module"`, and `"private": true` for all newly created package.json
35
- Do not include authors, keywords, external links.
36
-
37
- ### Dev Dependencies
38
-
39
- #### Top-Level
40
-
41
- * @jaypie/eslint
42
- * @jaypie/testkit
43
- * eslint
44
- * rimraf
45
- * sort-package-json
46
- * tsx
47
- * vitest
48
-
49
- #### Package-Level
50
-
51
- Anything particular to that package outside aforementioned.
52
-
53
- ### Scripts
54
-
55
- | Script | Top-level | Sub-packages | Root-level |
56
- | ------ | --------- | ------------ | ---------- |
57
- | `build` | `npm run build --workspaces` | `vite build` | N/A |
58
- | `clean` | `npm run clean --workspaces && npm run clean:root` | `rimfaf dist` | `clean:root` |
59
- | `format` | `eslint --fix` | `eslint --fix` | N/A |
60
- | `format:package` | `sort-package-json ./package.json ./packages/*/package.json` | `sort-package-json` | N/A |
61
- | `lint` | `eslint` | `eslint .` | N/A |
62
- | `test` | `vitest run` | `vitest run` | N/A |
63
- | `typecheck` | `npm run typecheck --workspaces` | `tsc --noEmit` | N/A |
64
-
65
- ## ๐Ÿงช Testing
66
-
67
- ### Configure Vitest Workspaces
68
-
69
- `vitest.workspace.js`
70
- ```javascript
71
- import { defineWorkspace } from "vitest/config";
72
-
73
- export default defineWorkspace([
74
- "packages/<package>",
75
- ]);
76
- ```
77
-
78
- See context/prompts/Jaypie_Mocks_and_Testkit.md for details and troubleshooting.