@nahisaho/musubix-pattern-mcp 3.0.16 → 3.1.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/dist/index.d.ts CHANGED
@@ -10,4 +10,5 @@ export * from './compression/index.js';
10
10
  export * from './library/index.js';
11
11
  export * from './privacy/index.js';
12
12
  export * from './learning/index.js';
13
+ export * from './patterns/concurrency/index.js';
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,YAAY,CAAC;AAG3B,cAAc,sBAAsB,CAAC;AAGrC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,YAAY,CAAC;AAG3B,cAAc,sBAAsB,CAAC;AAGrC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,iCAAiC,CAAC"}
package/dist/index.js CHANGED
@@ -16,4 +16,6 @@ export * from './library/index.js';
16
16
  export * from './privacy/index.js';
17
17
  // Wake-Sleep Learning (TSK-WAKE-002)
18
18
  export * from './learning/index.js';
19
+ // Concurrency Patterns (TSK-PAT-001, REQ-PAT-001)
20
+ export * from './patterns/concurrency/index.js';
19
21
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,QAAQ;AACR,cAAc,YAAY,CAAC;AAE3B,uCAAuC;AACvC,cAAc,sBAAsB,CAAC;AAErC,wCAAwC;AACxC,cAAc,wBAAwB,CAAC;AAEvC,oCAAoC;AACpC,cAAc,oBAAoB,CAAC;AAEnC,uCAAuC;AACvC,cAAc,oBAAoB,CAAC;AAEnC,qCAAqC;AACrC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,QAAQ;AACR,cAAc,YAAY,CAAC;AAE3B,uCAAuC;AACvC,cAAc,sBAAsB,CAAC;AAErC,wCAAwC;AACxC,cAAc,wBAAwB,CAAC;AAEvC,oCAAoC;AACpC,cAAc,oBAAoB,CAAC;AAEnC,uCAAuC;AACvC,cAAc,oBAAoB,CAAC;AAEnC,qCAAqC;AACrC,cAAc,qBAAqB,CAAC;AAEpC,kDAAkD;AAClD,cAAc,iCAAiC,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Concurrency Patterns - Best Practices for Concurrent Operations
3
+ *
4
+ * @packageDocumentation
5
+ * @module patterns/concurrency
6
+ *
7
+ * @see REQ-PAT-001 - 同時実行パターン追加
8
+ * @see TSK-PAT-001 - 同時実行パターンタスク
9
+ */
10
+ /**
11
+ * Concurrency pattern definition
12
+ */
13
+ export interface ConcurrencyPattern {
14
+ /** Pattern ID */
15
+ id: string;
16
+ /** Pattern name */
17
+ name: string;
18
+ /** Short description */
19
+ description: string;
20
+ /** When to use this pattern */
21
+ useCase: string;
22
+ /** When NOT to use this pattern */
23
+ antiPattern?: string;
24
+ /** TypeScript template code */
25
+ template: string;
26
+ /** Usage example */
27
+ example: string;
28
+ /** Related patterns */
29
+ relatedPatterns: string[];
30
+ /** Tags for categorization */
31
+ tags: string[];
32
+ /** Confidence score (0-1) */
33
+ confidence: number;
34
+ }
35
+ /**
36
+ * PAT-CONC-001: Optimistic Locking Pattern
37
+ *
38
+ * Use when: Multiple users may edit the same resource,
39
+ * but conflicts are rare.
40
+ */
41
+ export declare const OPTIMISTIC_LOCKING: ConcurrencyPattern;
42
+ /**
43
+ * PAT-CONC-002: Pessimistic Locking Pattern
44
+ *
45
+ * Use when: Conflicts are frequent and you need to prevent them entirely.
46
+ */
47
+ export declare const PESSIMISTIC_LOCKING: ConcurrencyPattern;
48
+ /**
49
+ * PAT-CONC-003: Hold Pattern
50
+ *
51
+ * Use when: You need to temporarily reserve resources before confirmation.
52
+ */
53
+ export declare const HOLD_PATTERN: ConcurrencyPattern;
54
+ /**
55
+ * PAT-CONC-004: Idempotency Key Pattern
56
+ *
57
+ * Use when: Operations may be retried (network failures, user double-clicks).
58
+ */
59
+ export declare const IDEMPOTENCY_KEY: ConcurrencyPattern;
60
+ /**
61
+ * All concurrency patterns
62
+ */
63
+ export declare const CONCURRENCY_PATTERNS: ConcurrencyPattern[];
64
+ /**
65
+ * Get pattern by ID
66
+ */
67
+ export declare function getConcurrencyPattern(id: string): ConcurrencyPattern | undefined;
68
+ /**
69
+ * Get patterns by tag
70
+ */
71
+ export declare function getConcurrencyPatternsByTag(tag: string): ConcurrencyPattern[];
72
+ /**
73
+ * Get all concurrency pattern IDs
74
+ */
75
+ export declare function getConcurrencyPatternIds(): string[];
76
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/patterns/concurrency/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iBAAiB;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,kBA6EhC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,kBAmFjC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,kBA+F1B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,kBA4G7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,kBAAkB,EAKpD,CAAC;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAEhF;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAE7E;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAEnD"}
@@ -0,0 +1,413 @@
1
+ /**
2
+ * Concurrency Patterns - Best Practices for Concurrent Operations
3
+ *
4
+ * @packageDocumentation
5
+ * @module patterns/concurrency
6
+ *
7
+ * @see REQ-PAT-001 - 同時実行パターン追加
8
+ * @see TSK-PAT-001 - 同時実行パターンタスク
9
+ */
10
+ /**
11
+ * PAT-CONC-001: Optimistic Locking Pattern
12
+ *
13
+ * Use when: Multiple users may edit the same resource,
14
+ * but conflicts are rare.
15
+ */
16
+ export const OPTIMISTIC_LOCKING = {
17
+ id: 'PAT-CONC-001',
18
+ name: 'Optimistic Locking',
19
+ description: 'Allows concurrent reads while detecting conflicts at write time using a version field.',
20
+ useCase: 'Use when conflicts are rare and you want to maximize read concurrency. Good for high-read, low-write scenarios.',
21
+ antiPattern: 'Avoid when conflicts are frequent, as users will face many retry prompts.',
22
+ template: `
23
+ interface WithVersion {
24
+ version: number;
25
+ }
26
+
27
+ interface OptimisticLockError extends Error {
28
+ code: 'OPTIMISTIC_LOCK_ERROR';
29
+ currentVersion: number;
30
+ providedVersion: number;
31
+ }
32
+
33
+ async function updateWithOptimisticLock<T extends WithVersion>(
34
+ id: string,
35
+ updates: Partial<T>,
36
+ expectedVersion: number,
37
+ repository: {
38
+ findById(id: string): Promise<T | null>;
39
+ save(entity: T): Promise<T>;
40
+ }
41
+ ): Promise<Result<T, OptimisticLockError>> {
42
+ const current = await repository.findById(id);
43
+
44
+ if (!current) {
45
+ return err({ code: 'NOT_FOUND' } as any);
46
+ }
47
+
48
+ if (current.version !== expectedVersion) {
49
+ return err({
50
+ code: 'OPTIMISTIC_LOCK_ERROR',
51
+ message: \`Version conflict: expected \${expectedVersion}, found \${current.version}\`,
52
+ currentVersion: current.version,
53
+ providedVersion: expectedVersion,
54
+ } as OptimisticLockError);
55
+ }
56
+
57
+ const updated = {
58
+ ...current,
59
+ ...updates,
60
+ version: current.version + 1,
61
+ };
62
+
63
+ return ok(await repository.save(updated));
64
+ }
65
+ `.trim(),
66
+ example: `
67
+ // Entity with version field
68
+ interface Order extends WithVersion {
69
+ id: string;
70
+ status: OrderStatus;
71
+ version: number;
72
+ }
73
+
74
+ // Update with optimistic lock
75
+ const result = await updateWithOptimisticLock(
76
+ orderId,
77
+ { status: 'completed' },
78
+ order.version,
79
+ orderRepository
80
+ );
81
+
82
+ if (result.isErr() && result.error.code === 'OPTIMISTIC_LOCK_ERROR') {
83
+ // Handle conflict - reload and retry or notify user
84
+ console.log('Order was modified by another user');
85
+ }
86
+ `.trim(),
87
+ relatedPatterns: ['PAT-CONC-002', 'PAT-DESIGN-004'],
88
+ tags: ['concurrency', 'versioning', 'conflict-detection'],
89
+ confidence: 0.95,
90
+ };
91
+ /**
92
+ * PAT-CONC-002: Pessimistic Locking Pattern
93
+ *
94
+ * Use when: Conflicts are frequent and you need to prevent them entirely.
95
+ */
96
+ export const PESSIMISTIC_LOCKING = {
97
+ id: 'PAT-CONC-002',
98
+ name: 'Pessimistic Locking',
99
+ description: 'Acquires exclusive lock before modification, preventing concurrent access.',
100
+ useCase: 'Use when conflicts are frequent or the cost of conflict resolution is high. Good for financial transactions.',
101
+ antiPattern: 'Avoid for high-concurrency read scenarios as it reduces throughput.',
102
+ template: `
103
+ interface Lock {
104
+ resourceId: string;
105
+ ownerId: string;
106
+ acquiredAt: Date;
107
+ expiresAt: Date;
108
+ }
109
+
110
+ interface LockManager {
111
+ acquire(resourceId: string, ownerId: string, ttlMs: number): Promise<Lock | null>;
112
+ release(resourceId: string, ownerId: string): Promise<boolean>;
113
+ isLocked(resourceId: string): Promise<boolean>;
114
+ }
115
+
116
+ async function withPessimisticLock<T>(
117
+ resourceId: string,
118
+ ownerId: string,
119
+ lockManager: LockManager,
120
+ operation: () => Promise<T>,
121
+ options: { ttlMs?: number; retryCount?: number; retryDelayMs?: number } = {}
122
+ ): Promise<Result<T, 'LOCK_FAILED' | 'OPERATION_FAILED'>> {
123
+ const { ttlMs = 30000, retryCount = 3, retryDelayMs = 100 } = options;
124
+
125
+ let lock: Lock | null = null;
126
+ let attempts = 0;
127
+
128
+ while (!lock && attempts < retryCount) {
129
+ lock = await lockManager.acquire(resourceId, ownerId, ttlMs);
130
+ if (!lock) {
131
+ attempts++;
132
+ await sleep(retryDelayMs * attempts);
133
+ }
134
+ }
135
+
136
+ if (!lock) {
137
+ return err('LOCK_FAILED');
138
+ }
139
+
140
+ try {
141
+ const result = await operation();
142
+ return ok(result);
143
+ } finally {
144
+ await lockManager.release(resourceId, ownerId);
145
+ }
146
+ }
147
+
148
+ function sleep(ms: number): Promise<void> {
149
+ return new Promise(resolve => setTimeout(resolve, ms));
150
+ }
151
+ `.trim(),
152
+ example: `
153
+ // Transfer money with pessimistic lock
154
+ const result = await withPessimisticLock(
155
+ \`account:\${fromAccountId}\`,
156
+ transactionId,
157
+ lockManager,
158
+ async () => {
159
+ const from = await accountRepo.findById(fromAccountId);
160
+ const to = await accountRepo.findById(toAccountId);
161
+
162
+ from.balance -= amount;
163
+ to.balance += amount;
164
+
165
+ await accountRepo.save(from);
166
+ await accountRepo.save(to);
167
+
168
+ return { from, to };
169
+ },
170
+ { ttlMs: 5000 }
171
+ );
172
+ `.trim(),
173
+ relatedPatterns: ['PAT-CONC-001', 'PAT-CONC-003'],
174
+ tags: ['concurrency', 'locking', 'exclusive-access'],
175
+ confidence: 0.90,
176
+ };
177
+ /**
178
+ * PAT-CONC-003: Hold Pattern
179
+ *
180
+ * Use when: You need to temporarily reserve resources before confirmation.
181
+ */
182
+ export const HOLD_PATTERN = {
183
+ id: 'PAT-CONC-003',
184
+ name: 'Hold Pattern',
185
+ description: 'Temporarily reserves a resource with automatic expiry, useful for booking/checkout flows.',
186
+ useCase: 'Use for e-commerce checkout, seat reservations, or any scenario where users need time to complete a multi-step process.',
187
+ antiPattern: 'Avoid for instant operations where reservation overhead is unnecessary.',
188
+ template: `
189
+ interface Hold<T> {
190
+ id: string;
191
+ resourceId: string;
192
+ resourceType: string;
193
+ heldBy: string;
194
+ heldData: T;
195
+ createdAt: Date;
196
+ expiresAt: Date;
197
+ status: 'active' | 'confirmed' | 'expired' | 'released';
198
+ }
199
+
200
+ interface HoldManager<T> {
201
+ createHold(resourceId: string, data: T, ttlMs: number): Promise<Hold<T>>;
202
+ confirmHold(holdId: string): Promise<T | null>;
203
+ releaseHold(holdId: string): Promise<boolean>;
204
+ getHold(holdId: string): Promise<Hold<T> | null>;
205
+ cleanupExpired(): Promise<number>;
206
+ }
207
+
208
+ function createHoldManager<T>(
209
+ repository: HoldRepository<T>
210
+ ): HoldManager<T> {
211
+ return {
212
+ async createHold(resourceId, data, ttlMs) {
213
+ const hold: Hold<T> = {
214
+ id: generateId(),
215
+ resourceId,
216
+ resourceType: typeof data,
217
+ heldBy: getCurrentUserId(),
218
+ heldData: data,
219
+ createdAt: new Date(),
220
+ expiresAt: new Date(Date.now() + ttlMs),
221
+ status: 'active',
222
+ };
223
+ return repository.save(hold);
224
+ },
225
+
226
+ async confirmHold(holdId) {
227
+ const hold = await repository.findById(holdId);
228
+ if (!hold || hold.status !== 'active') return null;
229
+ if (hold.expiresAt < new Date()) {
230
+ await repository.updateStatus(holdId, 'expired');
231
+ return null;
232
+ }
233
+ await repository.updateStatus(holdId, 'confirmed');
234
+ return hold.heldData;
235
+ },
236
+
237
+ async releaseHold(holdId) {
238
+ return repository.updateStatus(holdId, 'released');
239
+ },
240
+
241
+ async getHold(holdId) {
242
+ return repository.findById(holdId);
243
+ },
244
+
245
+ async cleanupExpired() {
246
+ return repository.markExpired(new Date());
247
+ },
248
+ };
249
+ }
250
+ `.trim(),
251
+ example: `
252
+ // E-commerce checkout flow
253
+ const holdManager = createHoldManager<CartItem[]>(holdRepository);
254
+
255
+ // Step 1: User adds items to cart - create hold
256
+ const hold = await holdManager.createHold(
257
+ 'cart:' + cartId,
258
+ cartItems,
259
+ 15 * 60 * 1000 // 15 minutes
260
+ );
261
+
262
+ // Step 2: User completes payment
263
+ const confirmedItems = await holdManager.confirmHold(hold.id);
264
+ if (confirmedItems) {
265
+ await createOrder(confirmedItems);
266
+ } else {
267
+ // Hold expired, items may no longer be available
268
+ throw new Error('Checkout session expired');
269
+ }
270
+ `.trim(),
271
+ relatedPatterns: ['PAT-CONC-002', 'PAT-DESIGN-007'],
272
+ tags: ['concurrency', 'reservation', 'expiry', 'checkout'],
273
+ confidence: 0.90,
274
+ };
275
+ /**
276
+ * PAT-CONC-004: Idempotency Key Pattern
277
+ *
278
+ * Use when: Operations may be retried (network failures, user double-clicks).
279
+ */
280
+ export const IDEMPOTENCY_KEY = {
281
+ id: 'PAT-CONC-004',
282
+ name: 'Idempotency Key',
283
+ description: 'Ensures operations are processed exactly once using a client-provided unique key.',
284
+ useCase: 'Use for payment processing, order creation, or any operation that should not be duplicated on retry.',
285
+ antiPattern: 'Not needed for naturally idempotent operations (like GET requests or updates that set absolute values).',
286
+ template: `
287
+ interface IdempotencyRecord<T> {
288
+ key: string;
289
+ requestHash: string;
290
+ status: 'processing' | 'completed' | 'failed';
291
+ result?: T;
292
+ error?: string;
293
+ createdAt: Date;
294
+ expiresAt: Date;
295
+ }
296
+
297
+ interface IdempotencyStore<T> {
298
+ get(key: string): Promise<IdempotencyRecord<T> | null>;
299
+ create(key: string, requestHash: string, ttlMs: number): Promise<boolean>;
300
+ complete(key: string, result: T): Promise<void>;
301
+ fail(key: string, error: string): Promise<void>;
302
+ }
303
+
304
+ async function withIdempotency<T>(
305
+ idempotencyKey: string,
306
+ requestBody: unknown,
307
+ store: IdempotencyStore<T>,
308
+ operation: () => Promise<T>,
309
+ options: { ttlMs?: number } = {}
310
+ ): Promise<Result<T, 'IN_PROGRESS' | 'REQUEST_MISMATCH'>> {
311
+ const { ttlMs = 24 * 60 * 60 * 1000 } = options; // 24 hours default
312
+ const requestHash = hashRequest(requestBody);
313
+
314
+ // Check for existing record
315
+ const existing = await store.get(idempotencyKey);
316
+
317
+ if (existing) {
318
+ // Verify request body matches
319
+ if (existing.requestHash !== requestHash) {
320
+ return err('REQUEST_MISMATCH');
321
+ }
322
+
323
+ // Return cached result if completed
324
+ if (existing.status === 'completed' && existing.result !== undefined) {
325
+ return ok(existing.result);
326
+ }
327
+
328
+ // Still processing
329
+ if (existing.status === 'processing') {
330
+ return err('IN_PROGRESS');
331
+ }
332
+ }
333
+
334
+ // Create new record
335
+ const created = await store.create(idempotencyKey, requestHash, ttlMs);
336
+ if (!created) {
337
+ return err('IN_PROGRESS'); // Race condition - another request got there first
338
+ }
339
+
340
+ try {
341
+ const result = await operation();
342
+ await store.complete(idempotencyKey, result);
343
+ return ok(result);
344
+ } catch (error) {
345
+ await store.fail(idempotencyKey, String(error));
346
+ throw error;
347
+ }
348
+ }
349
+
350
+ function hashRequest(body: unknown): string {
351
+ return JSON.stringify(body); // Simplified - use crypto hash in production
352
+ }
353
+ `.trim(),
354
+ example: `
355
+ // Payment processing with idempotency
356
+ app.post('/payments', async (req, res) => {
357
+ const idempotencyKey = req.headers['idempotency-key'];
358
+
359
+ if (!idempotencyKey) {
360
+ return res.status(400).json({ error: 'Idempotency-Key header required' });
361
+ }
362
+
363
+ const result = await withIdempotency(
364
+ idempotencyKey,
365
+ req.body,
366
+ idempotencyStore,
367
+ async () => {
368
+ return await paymentService.processPayment(req.body);
369
+ }
370
+ );
371
+
372
+ if (result.isErr()) {
373
+ if (result.error === 'IN_PROGRESS') {
374
+ return res.status(409).json({ error: 'Request in progress' });
375
+ }
376
+ return res.status(422).json({ error: 'Request body mismatch' });
377
+ }
378
+
379
+ return res.json(result.value);
380
+ });
381
+ `.trim(),
382
+ relatedPatterns: ['PAT-CONC-001', 'PAT-DESIGN-005'],
383
+ tags: ['concurrency', 'idempotency', 'retry-safety', 'payment'],
384
+ confidence: 0.95,
385
+ };
386
+ /**
387
+ * All concurrency patterns
388
+ */
389
+ export const CONCURRENCY_PATTERNS = [
390
+ OPTIMISTIC_LOCKING,
391
+ PESSIMISTIC_LOCKING,
392
+ HOLD_PATTERN,
393
+ IDEMPOTENCY_KEY,
394
+ ];
395
+ /**
396
+ * Get pattern by ID
397
+ */
398
+ export function getConcurrencyPattern(id) {
399
+ return CONCURRENCY_PATTERNS.find((p) => p.id === id);
400
+ }
401
+ /**
402
+ * Get patterns by tag
403
+ */
404
+ export function getConcurrencyPatternsByTag(tag) {
405
+ return CONCURRENCY_PATTERNS.filter((p) => p.tags.includes(tag));
406
+ }
407
+ /**
408
+ * Get all concurrency pattern IDs
409
+ */
410
+ export function getConcurrencyPatternIds() {
411
+ return CONCURRENCY_PATTERNS.map((p) => p.id);
412
+ }
413
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/patterns/concurrency/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA4BH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAuB;IACpD,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,wFAAwF;IAC1F,OAAO,EACL,iHAAiH;IACnH,WAAW,EACT,2EAA2E;IAC7E,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CX,CAAC,IAAI,EAAE;IACN,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;CAoBV,CAAC,IAAI,EAAE;IACN,eAAe,EAAE,CAAC,cAAc,EAAE,gBAAgB,CAAC;IACnD,IAAI,EAAE,CAAC,aAAa,EAAE,YAAY,EAAE,oBAAoB,CAAC;IACzD,UAAU,EAAE,IAAI;CACjB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAuB;IACrD,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EACT,4EAA4E;IAC9E,OAAO,EACL,8GAA8G;IAChH,WAAW,EACT,qEAAqE;IACvE,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiDX,CAAC,IAAI,EAAE;IACN,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;CAoBV,CAAC,IAAI,EAAE;IACN,eAAe,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC;IACjD,IAAI,EAAE,CAAC,aAAa,EAAE,SAAS,EAAE,kBAAkB,CAAC;IACpD,UAAU,EAAE,IAAI;CACjB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAuB;IAC9C,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,2FAA2F;IAC7F,OAAO,EACL,yHAAyH;IAC3H,WAAW,EACT,yEAAyE;IAC3E,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8DX,CAAC,IAAI,EAAE;IACN,OAAO,EAAE;;;;;;;;;;;;;;;;;;;CAmBV,CAAC,IAAI,EAAE;IACN,eAAe,EAAE,CAAC,cAAc,EAAE,gBAAgB,CAAC;IACnD,IAAI,EAAE,CAAC,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,CAAC;IAC1D,UAAU,EAAE,IAAI;CACjB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAuB;IACjD,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT,mFAAmF;IACrF,OAAO,EACL,sGAAsG;IACxG,WAAW,EACT,yGAAyG;IAC3G,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmEX,CAAC,IAAI,EAAE;IACN,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BV,CAAC,IAAI,EAAE;IACN,eAAe,EAAE,CAAC,cAAc,EAAE,gBAAgB,CAAC;IACnD,IAAI,EAAE,CAAC,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,SAAS,CAAC;IAC/D,UAAU,EAAE,IAAI;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAyB;IACxD,kBAAkB;IAClB,mBAAmB;IACnB,YAAY;IACZ,eAAe;CAChB,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,EAAU;IAC9C,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,2BAA2B,CAAC,GAAW;IACrD,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB;IACtC,OAAO,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Patterns Index
3
+ *
4
+ * Exports all design patterns from submodules.
5
+ *
6
+ * @packageDocumentation
7
+ * @module patterns
8
+ */
9
+ export * from './concurrency/index.js';
10
+ export * from './time/index.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/patterns/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Patterns Index
3
+ *
4
+ * Exports all design patterns from submodules.
5
+ *
6
+ * @packageDocumentation
7
+ * @module patterns
8
+ */
9
+ export * from './concurrency/index.js';
10
+ export * from './time/index.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/patterns/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Time Constraint Patterns
3
+ *
4
+ * Best practice patterns for time-based operations.
5
+ *
6
+ * @packageDocumentation
7
+ * @module patterns/time
8
+ *
9
+ * @see BP-DESIGN-007 - Expiry Time Logic
10
+ * @see TSK-PAT-002 - 時間制約パターン
11
+ */
12
+ import type { DesignPattern, PatternExample } from '../../types.js';
13
+ /**
14
+ * PAT-TIME-001: Expiry Pattern
15
+ *
16
+ * Manages entities with expiration times.
17
+ */
18
+ export declare const EXPIRY_PATTERN: DesignPattern;
19
+ /**
20
+ * PAT-TIME-002: Scheduled Event Pattern
21
+ *
22
+ * Handles events that occur at specific times.
23
+ */
24
+ export declare const SCHEDULED_PATTERN: DesignPattern;
25
+ /**
26
+ * PAT-TIME-003: Interval Pattern
27
+ *
28
+ * Manages recurring events at fixed intervals.
29
+ */
30
+ export declare const INTERVAL_PATTERN: DesignPattern;
31
+ /**
32
+ * PAT-TIME-004: Streak Pattern
33
+ *
34
+ * Tracks consecutive activity streaks.
35
+ */
36
+ export declare const STREAK_PATTERN: DesignPattern;
37
+ /**
38
+ * PAT-TIME-005: Cooldown Pattern
39
+ *
40
+ * Prevents actions from being repeated too quickly.
41
+ */
42
+ export declare const COOLDOWN_PATTERN: DesignPattern;
43
+ /**
44
+ * All time constraint patterns
45
+ */
46
+ export declare const TIME_PATTERNS: DesignPattern[];
47
+ /**
48
+ * Get a time pattern by ID
49
+ */
50
+ export declare function getTimePattern(id: string): DesignPattern | undefined;
51
+ /**
52
+ * Get patterns applicable to a domain
53
+ */
54
+ export declare function getTimePatternsByDomain(domain: string): DesignPattern[];
55
+ /**
56
+ * Pattern examples for time patterns
57
+ */
58
+ export declare const TIME_PATTERN_EXAMPLES: PatternExample[];
59
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/patterns/time/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,aAyC5B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,aA6C/B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,aAiD9B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,aAyE5B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,aA2D9B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,aAAa,EAMxC,CAAC;AAEF;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEpE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,CAIvE;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,cAAc,EA0CjD,CAAC"}
@@ -0,0 +1,362 @@
1
+ /**
2
+ * Time Constraint Patterns
3
+ *
4
+ * Best practice patterns for time-based operations.
5
+ *
6
+ * @packageDocumentation
7
+ * @module patterns/time
8
+ *
9
+ * @see BP-DESIGN-007 - Expiry Time Logic
10
+ * @see TSK-PAT-002 - 時間制約パターン
11
+ */
12
+ /**
13
+ * PAT-TIME-001: Expiry Pattern
14
+ *
15
+ * Manages entities with expiration times.
16
+ */
17
+ export const EXPIRY_PATTERN = {
18
+ id: 'PAT-TIME-001',
19
+ name: 'Expiry Pattern',
20
+ category: 'temporal',
21
+ domain: ['all'],
22
+ description: 'Manages entities with explicit expiration times. Use expiresAt field to track validity.',
23
+ problem: 'Entities need to become invalid after a certain time (e.g., tokens, coupons, sessions).',
24
+ solution: 'Store expiresAt as a Date field. Provide isExpired() method that compares against current time.',
25
+ applicability: [
26
+ 'Tokens and sessions',
27
+ 'Coupons and promotions',
28
+ 'Temporary access',
29
+ 'Cache entries',
30
+ ],
31
+ consequences: {
32
+ positive: [
33
+ 'Clear expiration semantics',
34
+ 'Easy to query expired entities',
35
+ 'Timezone-safe with UTC',
36
+ ],
37
+ negative: [
38
+ 'Requires periodic cleanup jobs',
39
+ 'Clock synchronization needed for distributed systems',
40
+ ],
41
+ },
42
+ implementation: `interface Expirable {
43
+ readonly expiresAt: Date;
44
+ }
45
+
46
+ function isExpired(entity: Expirable, now: Date = new Date()): boolean {
47
+ return entity.expiresAt <= now;
48
+ }
49
+
50
+ function createExpiry(durationMs: number, from: Date = new Date()): Date {
51
+ return new Date(from.getTime() + durationMs);
52
+ }`,
53
+ relatedPatterns: ['PAT-TIME-002', 'PAT-TIME-003'],
54
+ confidence: 0.9,
55
+ };
56
+ /**
57
+ * PAT-TIME-002: Scheduled Event Pattern
58
+ *
59
+ * Handles events that occur at specific times.
60
+ */
61
+ export const SCHEDULED_PATTERN = {
62
+ id: 'PAT-TIME-002',
63
+ name: 'Scheduled Event Pattern',
64
+ category: 'temporal',
65
+ domain: ['all'],
66
+ description: 'Manages events scheduled for future execution at specific times.',
67
+ problem: 'Need to execute actions at predetermined times (e.g., reminders, appointments).',
68
+ solution: 'Store scheduledAt timestamp. Use job queue to trigger actions when time arrives.',
69
+ applicability: [
70
+ 'Appointment systems',
71
+ 'Reminder notifications',
72
+ 'Scheduled publishing',
73
+ 'Delayed tasks',
74
+ ],
75
+ consequences: {
76
+ positive: [
77
+ 'Predictable execution timing',
78
+ 'Supports multiple time zones',
79
+ 'Can reschedule easily',
80
+ ],
81
+ negative: [
82
+ 'Requires reliable scheduler',
83
+ 'Missed events need handling strategy',
84
+ ],
85
+ },
86
+ implementation: `interface Schedulable {
87
+ readonly scheduledAt: Date;
88
+ readonly status: 'pending' | 'executed' | 'cancelled';
89
+ }
90
+
91
+ function isReady(event: Schedulable, now: Date = new Date()): boolean {
92
+ return event.status === 'pending' && event.scheduledAt <= now;
93
+ }
94
+
95
+ function reschedule(event: Schedulable, newTime: Date): Schedulable {
96
+ if (event.status !== 'pending') {
97
+ throw new Error('Cannot reschedule non-pending event');
98
+ }
99
+ return { ...event, scheduledAt: newTime };
100
+ }`,
101
+ relatedPatterns: ['PAT-TIME-001', 'PAT-TIME-003'],
102
+ confidence: 0.85,
103
+ };
104
+ /**
105
+ * PAT-TIME-003: Interval Pattern
106
+ *
107
+ * Manages recurring events at fixed intervals.
108
+ */
109
+ export const INTERVAL_PATTERN = {
110
+ id: 'PAT-TIME-003',
111
+ name: 'Interval Pattern',
112
+ category: 'temporal',
113
+ domain: ['all'],
114
+ description: 'Manages recurring events that happen at fixed intervals.',
115
+ problem: 'Events need to repeat periodically (e.g., subscriptions, polling, cron jobs).',
116
+ solution: 'Store intervalMs and lastRunAt. Calculate nextRunAt from last execution.',
117
+ applicability: [
118
+ 'Subscription billing',
119
+ 'Recurring tasks',
120
+ 'Health checks',
121
+ 'Data synchronization',
122
+ ],
123
+ consequences: {
124
+ positive: [
125
+ 'Consistent timing',
126
+ 'Easy to adjust frequency',
127
+ 'Tracks execution history',
128
+ ],
129
+ negative: [
130
+ 'Drift accumulation if not anchored',
131
+ 'Overlapping executions need handling',
132
+ ],
133
+ },
134
+ implementation: `interface Recurring {
135
+ readonly intervalMs: number;
136
+ readonly lastRunAt: Date | null;
137
+ readonly anchorTime: Date;
138
+ }
139
+
140
+ function getNextRunAt(recurring: Recurring, now: Date = new Date()): Date {
141
+ if (!recurring.lastRunAt) {
142
+ return recurring.anchorTime;
143
+ }
144
+ const elapsed = now.getTime() - recurring.anchorTime.getTime();
145
+ const periods = Math.floor(elapsed / recurring.intervalMs) + 1;
146
+ return new Date(recurring.anchorTime.getTime() + periods * recurring.intervalMs);
147
+ }
148
+
149
+ function isDue(recurring: Recurring, now: Date = new Date()): boolean {
150
+ const next = getNextRunAt(recurring, now);
151
+ return next <= now;
152
+ }`,
153
+ relatedPatterns: ['PAT-TIME-001', 'PAT-TIME-002', 'PAT-TIME-004'],
154
+ confidence: 0.85,
155
+ };
156
+ /**
157
+ * PAT-TIME-004: Streak Pattern
158
+ *
159
+ * Tracks consecutive activity streaks.
160
+ */
161
+ export const STREAK_PATTERN = {
162
+ id: 'PAT-TIME-004',
163
+ name: 'Streak Pattern',
164
+ category: 'temporal',
165
+ domain: ['fitness', 'education', 'gaming'],
166
+ description: 'Tracks consecutive day/activity streaks with grace period support.',
167
+ problem: 'Need to track user engagement through consecutive activity days (e.g., login streaks, workout streaks).',
168
+ solution: 'Store currentStreak, longestStreak, lastActivityAt. Update on each activity with grace period.',
169
+ applicability: [
170
+ 'Gamification features',
171
+ 'Habit tracking',
172
+ 'User engagement metrics',
173
+ 'Loyalty programs',
174
+ ],
175
+ consequences: {
176
+ positive: [
177
+ 'Motivates consistent engagement',
178
+ 'Clear progress tracking',
179
+ 'Supports grace periods',
180
+ ],
181
+ negative: [
182
+ 'Timezone handling complexity',
183
+ 'Grace period edge cases',
184
+ ],
185
+ },
186
+ implementation: `interface Streak {
187
+ currentStreak: number;
188
+ longestStreak: number;
189
+ lastActivityAt: Date | null;
190
+ }
191
+
192
+ const ONE_DAY_MS = 24 * 60 * 60 * 1000;
193
+
194
+ function recordActivity(
195
+ streak: Streak,
196
+ gracePeriodMs: number = ONE_DAY_MS * 1.5,
197
+ now: Date = new Date()
198
+ ): Streak {
199
+ if (!streak.lastActivityAt) {
200
+ return {
201
+ currentStreak: 1,
202
+ longestStreak: Math.max(1, streak.longestStreak),
203
+ lastActivityAt: now,
204
+ };
205
+ }
206
+
207
+ const elapsed = now.getTime() - streak.lastActivityAt.getTime();
208
+
209
+ if (elapsed < ONE_DAY_MS) {
210
+ // Same day, no change
211
+ return streak;
212
+ } else if (elapsed <= gracePeriodMs) {
213
+ // Within grace period, increment streak
214
+ const newCurrent = streak.currentStreak + 1;
215
+ return {
216
+ currentStreak: newCurrent,
217
+ longestStreak: Math.max(newCurrent, streak.longestStreak),
218
+ lastActivityAt: now,
219
+ };
220
+ } else {
221
+ // Streak broken
222
+ return {
223
+ currentStreak: 1,
224
+ longestStreak: streak.longestStreak,
225
+ lastActivityAt: now,
226
+ };
227
+ }
228
+ }`,
229
+ relatedPatterns: ['PAT-TIME-003'],
230
+ confidence: 0.8,
231
+ };
232
+ /**
233
+ * PAT-TIME-005: Cooldown Pattern
234
+ *
235
+ * Prevents actions from being repeated too quickly.
236
+ */
237
+ export const COOLDOWN_PATTERN = {
238
+ id: 'PAT-TIME-005',
239
+ name: 'Cooldown Pattern',
240
+ category: 'temporal',
241
+ domain: ['all'],
242
+ description: 'Prevents actions from being performed too frequently with a cooldown period.',
243
+ problem: 'Need to rate-limit user actions (e.g., password reset, notifications, API calls).',
244
+ solution: 'Track lastActionAt and cooldownMs. Check if enough time has passed before allowing action.',
245
+ applicability: [
246
+ 'Rate limiting',
247
+ 'Spam prevention',
248
+ 'Resource protection',
249
+ 'Gaming abilities',
250
+ ],
251
+ consequences: {
252
+ positive: [
253
+ 'Prevents abuse',
254
+ 'Fair resource distribution',
255
+ 'Simple implementation',
256
+ ],
257
+ negative: [
258
+ 'May frustrate legitimate users',
259
+ 'Clock skew issues in distributed systems',
260
+ ],
261
+ },
262
+ implementation: `interface Cooldownable {
263
+ readonly lastActionAt: Date | null;
264
+ readonly cooldownMs: number;
265
+ }
266
+
267
+ function canPerformAction(
268
+ item: Cooldownable,
269
+ now: Date = new Date()
270
+ ): { allowed: boolean; remainingMs: number } {
271
+ if (!item.lastActionAt) {
272
+ return { allowed: true, remainingMs: 0 };
273
+ }
274
+
275
+ const elapsed = now.getTime() - item.lastActionAt.getTime();
276
+ const remaining = item.cooldownMs - elapsed;
277
+
278
+ return {
279
+ allowed: remaining <= 0,
280
+ remainingMs: Math.max(0, remaining),
281
+ };
282
+ }
283
+
284
+ function performAction(item: Cooldownable, now: Date = new Date()): Cooldownable {
285
+ const check = canPerformAction(item, now);
286
+ if (!check.allowed) {
287
+ throw new Error(\`Action on cooldown. Wait \${check.remainingMs}ms\`);
288
+ }
289
+ return { ...item, lastActionAt: now };
290
+ }`,
291
+ relatedPatterns: ['PAT-TIME-001', 'PAT-CONC-004'],
292
+ confidence: 0.85,
293
+ };
294
+ /**
295
+ * All time constraint patterns
296
+ */
297
+ export const TIME_PATTERNS = [
298
+ EXPIRY_PATTERN,
299
+ SCHEDULED_PATTERN,
300
+ INTERVAL_PATTERN,
301
+ STREAK_PATTERN,
302
+ COOLDOWN_PATTERN,
303
+ ];
304
+ /**
305
+ * Get a time pattern by ID
306
+ */
307
+ export function getTimePattern(id) {
308
+ return TIME_PATTERNS.find((p) => p.id === id);
309
+ }
310
+ /**
311
+ * Get patterns applicable to a domain
312
+ */
313
+ export function getTimePatternsByDomain(domain) {
314
+ return TIME_PATTERNS.filter((p) => p.domain.includes('all') || p.domain.includes(domain));
315
+ }
316
+ /**
317
+ * Pattern examples for time patterns
318
+ */
319
+ export const TIME_PATTERN_EXAMPLES = [
320
+ {
321
+ patternId: 'PAT-TIME-001',
322
+ scenario: 'クーポンの有効期限管理',
323
+ code: `const coupon = {
324
+ code: 'SUMMER2025',
325
+ discount: 20,
326
+ expiresAt: new Date('2025-08-31T23:59:59Z'),
327
+ };
328
+
329
+ if (isExpired(coupon)) {
330
+ throw new Error('このクーポンは有効期限切れです');
331
+ }`,
332
+ domain: 'ecommerce',
333
+ },
334
+ {
335
+ patternId: 'PAT-TIME-002',
336
+ scenario: '予約のスケジュール管理',
337
+ code: `const appointment = {
338
+ id: 'APT-001',
339
+ scheduledAt: new Date('2025-01-20T10:00:00Z'),
340
+ status: 'pending' as const,
341
+ };
342
+
343
+ if (isReady(appointment)) {
344
+ sendReminder(appointment);
345
+ }`,
346
+ domain: 'healthcare',
347
+ },
348
+ {
349
+ patternId: 'PAT-TIME-004',
350
+ scenario: 'フィットネスアプリの連続記録',
351
+ code: `let streak: Streak = {
352
+ currentStreak: 5,
353
+ longestStreak: 10,
354
+ lastActivityAt: new Date('2025-01-18'),
355
+ };
356
+
357
+ streak = recordActivity(streak);
358
+ console.log(\`現在の連続: \${streak.currentStreak}日\`);`,
359
+ domain: 'fitness',
360
+ },
361
+ ];
362
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/patterns/time/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAkB;IAC3C,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,gBAAgB;IACtB,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,CAAC,KAAK,CAAC;IACf,WAAW,EACT,yFAAyF;IAC3F,OAAO,EACL,yFAAyF;IAC3F,QAAQ,EACN,iGAAiG;IACnG,aAAa,EAAE;QACb,qBAAqB;QACrB,wBAAwB;QACxB,kBAAkB;QAClB,eAAe;KAChB;IACD,YAAY,EAAE;QACZ,QAAQ,EAAE;YACR,4BAA4B;YAC5B,gCAAgC;YAChC,wBAAwB;SACzB;QACD,QAAQ,EAAE;YACR,gCAAgC;YAChC,sDAAsD;SACvD;KACF;IACD,cAAc,EAAE;;;;;;;;;;EAUhB;IACA,eAAe,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC;IACjD,UAAU,EAAE,GAAG;CAChB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAkB;IAC9C,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,yBAAyB;IAC/B,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,CAAC,KAAK,CAAC;IACf,WAAW,EACT,kEAAkE;IACpE,OAAO,EACL,iFAAiF;IACnF,QAAQ,EACN,kFAAkF;IACpF,aAAa,EAAE;QACb,qBAAqB;QACrB,wBAAwB;QACxB,sBAAsB;QACtB,eAAe;KAChB;IACD,YAAY,EAAE;QACZ,QAAQ,EAAE;YACR,8BAA8B;YAC9B,8BAA8B;YAC9B,uBAAuB;SACxB;QACD,QAAQ,EAAE;YACR,6BAA6B;YAC7B,sCAAsC;SACvC;KACF;IACD,cAAc,EAAE;;;;;;;;;;;;;;EAchB;IACA,eAAe,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC;IACjD,UAAU,EAAE,IAAI;CACjB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAkB;IAC7C,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,kBAAkB;IACxB,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,CAAC,KAAK,CAAC;IACf,WAAW,EACT,0DAA0D;IAC5D,OAAO,EACL,+EAA+E;IACjF,QAAQ,EACN,0EAA0E;IAC5E,aAAa,EAAE;QACb,sBAAsB;QACtB,iBAAiB;QACjB,eAAe;QACf,sBAAsB;KACvB;IACD,YAAY,EAAE;QACZ,QAAQ,EAAE;YACR,mBAAmB;YACnB,0BAA0B;YAC1B,0BAA0B;SAC3B;QACD,QAAQ,EAAE;YACR,oCAAoC;YACpC,sCAAsC;SACvC;KACF;IACD,cAAc,EAAE;;;;;;;;;;;;;;;;;;EAkBhB;IACA,eAAe,EAAE,CAAC,cAAc,EAAE,cAAc,EAAE,cAAc,CAAC;IACjE,UAAU,EAAE,IAAI;CACjB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAkB;IAC3C,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,gBAAgB;IACtB,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC;IAC1C,WAAW,EACT,oEAAoE;IACtE,OAAO,EACL,yGAAyG;IAC3G,QAAQ,EACN,gGAAgG;IAClG,aAAa,EAAE;QACb,uBAAuB;QACvB,gBAAgB;QAChB,yBAAyB;QACzB,kBAAkB;KACnB;IACD,YAAY,EAAE;QACZ,QAAQ,EAAE;YACR,iCAAiC;YACjC,yBAAyB;YACzB,wBAAwB;SACzB;QACD,QAAQ,EAAE;YACR,8BAA8B;YAC9B,yBAAyB;SAC1B;KACF;IACD,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0ChB;IACA,eAAe,EAAE,CAAC,cAAc,CAAC;IACjC,UAAU,EAAE,GAAG;CAChB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAkB;IAC7C,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,kBAAkB;IACxB,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,CAAC,KAAK,CAAC;IACf,WAAW,EACT,8EAA8E;IAChF,OAAO,EACL,mFAAmF;IACrF,QAAQ,EACN,4FAA4F;IAC9F,aAAa,EAAE;QACb,eAAe;QACf,iBAAiB;QACjB,qBAAqB;QACrB,kBAAkB;KACnB;IACD,YAAY,EAAE;QACZ,QAAQ,EAAE;YACR,gBAAgB;YAChB,4BAA4B;YAC5B,uBAAuB;SACxB;QACD,QAAQ,EAAE;YACR,gCAAgC;YAChC,0CAA0C;SAC3C;KACF;IACD,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BhB;IACA,eAAe,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC;IACjD,UAAU,EAAE,IAAI;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAoB;IAC5C,cAAc;IACd,iBAAiB;IACjB,gBAAgB;IAChB,cAAc;IACd,gBAAgB;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAAU;IACvC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,OAAO,aAAa,CAAC,MAAM,CACzB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAC7D,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAqB;IACrD;QACE,SAAS,EAAE,cAAc;QACzB,QAAQ,EAAE,aAAa;QACvB,IAAI,EAAE;;;;;;;;EAQR;QACE,MAAM,EAAE,WAAW;KACpB;IACD;QACE,SAAS,EAAE,cAAc;QACzB,QAAQ,EAAE,aAAa;QACvB,IAAI,EAAE;;;;;;;;EAQR;QACE,MAAM,EAAE,YAAY;KACrB;IACD;QACE,SAAS,EAAE,cAAc;QACzB,QAAQ,EAAE,gBAAgB;QAC1B,IAAI,EAAE;;;;;;;mDAOyC;QAC/C,MAAM,EAAE,SAAS;KAClB;CACF,CAAC"}
package/dist/types.d.ts CHANGED
@@ -86,4 +86,49 @@ export interface PrivacyFilterResult {
86
86
  reason?: string;
87
87
  sanitizedPattern?: Pattern;
88
88
  }
89
+ /**
90
+ * Design Pattern - Best practice pattern definition
91
+ */
92
+ export interface DesignPattern {
93
+ /** Unique pattern ID (e.g., PAT-CONC-001, PAT-TIME-001) */
94
+ id: string;
95
+ /** Human-readable name */
96
+ name: string;
97
+ /** Pattern category (concurrency, temporal, etc.) */
98
+ category: string;
99
+ /** Applicable domains */
100
+ domain: string[];
101
+ /** Brief description */
102
+ description: string;
103
+ /** Problem this pattern solves */
104
+ problem: string;
105
+ /** Solution approach */
106
+ solution: string;
107
+ /** When to apply this pattern */
108
+ applicability: string[];
109
+ /** Trade-offs */
110
+ consequences: {
111
+ positive: string[];
112
+ negative: string[];
113
+ };
114
+ /** TypeScript implementation example */
115
+ implementation: string;
116
+ /** Related pattern IDs */
117
+ relatedPatterns?: string[];
118
+ /** Confidence score (0-1) */
119
+ confidence: number;
120
+ }
121
+ /**
122
+ * Pattern Example - Concrete usage example
123
+ */
124
+ export interface PatternExample {
125
+ /** Pattern ID this example demonstrates */
126
+ patternId: string;
127
+ /** Scenario description */
128
+ scenario: string;
129
+ /** Example code */
130
+ code: string;
131
+ /** Domain this example applies to */
132
+ domain: string;
133
+ }
89
134
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,QAAQ,CAAC;IACxB,WAAW,EAAE,QAAQ,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,YAAY,CAAC;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nahisaho/musubix-pattern-mcp",
3
- "version": "3.0.16",
3
+ "version": "3.1.0",
4
4
  "description": "MUSUBIX Pattern Library Learning MCP - AST-based pattern extraction and abstraction",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",