@gherk/reactive-architecture 1.0.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 (78) hide show
  1. package/README.md +151 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +57 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/knowledge/backend-folder-structure.d.ts +10 -0
  7. package/dist/knowledge/backend-folder-structure.d.ts.map +1 -0
  8. package/dist/knowledge/backend-folder-structure.js +730 -0
  9. package/dist/knowledge/backend-folder-structure.js.map +1 -0
  10. package/dist/knowledge/backend-guides.d.ts +13 -0
  11. package/dist/knowledge/backend-guides.d.ts.map +1 -0
  12. package/dist/knowledge/backend-guides.js +914 -0
  13. package/dist/knowledge/backend-guides.js.map +1 -0
  14. package/dist/knowledge/examples.d.ts +6 -0
  15. package/dist/knowledge/examples.d.ts.map +1 -0
  16. package/dist/knowledge/examples.js +829 -0
  17. package/dist/knowledge/examples.js.map +1 -0
  18. package/dist/knowledge/folder-structure.d.ts +10 -0
  19. package/dist/knowledge/folder-structure.d.ts.map +1 -0
  20. package/dist/knowledge/folder-structure.js +686 -0
  21. package/dist/knowledge/folder-structure.js.map +1 -0
  22. package/dist/knowledge/philosophy.d.ts +11 -0
  23. package/dist/knowledge/philosophy.d.ts.map +1 -0
  24. package/dist/knowledge/philosophy.js +427 -0
  25. package/dist/knowledge/philosophy.js.map +1 -0
  26. package/dist/knowledge/stack-guides.d.ts +18 -0
  27. package/dist/knowledge/stack-guides.d.ts.map +1 -0
  28. package/dist/knowledge/stack-guides.js +841 -0
  29. package/dist/knowledge/stack-guides.js.map +1 -0
  30. package/dist/knowledge/style-rules.d.ts +8 -0
  31. package/dist/knowledge/style-rules.d.ts.map +1 -0
  32. package/dist/knowledge/style-rules.js +355 -0
  33. package/dist/knowledge/style-rules.js.map +1 -0
  34. package/dist/prompts/plan-feature.d.ts +3 -0
  35. package/dist/prompts/plan-feature.d.ts.map +1 -0
  36. package/dist/prompts/plan-feature.js +79 -0
  37. package/dist/prompts/plan-feature.js.map +1 -0
  38. package/dist/resources/philosophy-resource.d.ts +3 -0
  39. package/dist/resources/philosophy-resource.d.ts.map +1 -0
  40. package/dist/resources/philosophy-resource.js +25 -0
  41. package/dist/resources/philosophy-resource.js.map +1 -0
  42. package/dist/tools/architecture-guide.d.ts +3 -0
  43. package/dist/tools/architecture-guide.d.ts.map +1 -0
  44. package/dist/tools/architecture-guide.js +38 -0
  45. package/dist/tools/architecture-guide.js.map +1 -0
  46. package/dist/tools/backend-folder-structure.d.ts +3 -0
  47. package/dist/tools/backend-folder-structure.d.ts.map +1 -0
  48. package/dist/tools/backend-folder-structure.js +47 -0
  49. package/dist/tools/backend-folder-structure.js.map +1 -0
  50. package/dist/tools/backend-guide.d.ts +3 -0
  51. package/dist/tools/backend-guide.d.ts.map +1 -0
  52. package/dist/tools/backend-guide.js +41 -0
  53. package/dist/tools/backend-guide.js.map +1 -0
  54. package/dist/tools/detect-and-guide.d.ts +3 -0
  55. package/dist/tools/detect-and-guide.d.ts.map +1 -0
  56. package/dist/tools/detect-and-guide.js +130 -0
  57. package/dist/tools/detect-and-guide.js.map +1 -0
  58. package/dist/tools/examples.d.ts +3 -0
  59. package/dist/tools/examples.d.ts.map +1 -0
  60. package/dist/tools/examples.js +28 -0
  61. package/dist/tools/examples.js.map +1 -0
  62. package/dist/tools/folder-structure.d.ts +3 -0
  63. package/dist/tools/folder-structure.d.ts.map +1 -0
  64. package/dist/tools/folder-structure.js +52 -0
  65. package/dist/tools/folder-structure.js.map +1 -0
  66. package/dist/tools/scaffold.d.ts +3 -0
  67. package/dist/tools/scaffold.d.ts.map +1 -0
  68. package/dist/tools/scaffold.js +562 -0
  69. package/dist/tools/scaffold.js.map +1 -0
  70. package/dist/tools/style-rules.d.ts +3 -0
  71. package/dist/tools/style-rules.d.ts.map +1 -0
  72. package/dist/tools/style-rules.js +43 -0
  73. package/dist/tools/style-rules.js.map +1 -0
  74. package/dist/tools/validate.d.ts +3 -0
  75. package/dist/tools/validate.d.ts.map +1 -0
  76. package/dist/tools/validate.js +195 -0
  77. package/dist/tools/validate.js.map +1 -0
  78. package/package.json +37 -0
@@ -0,0 +1,829 @@
1
+ // =============================================================================
2
+ // FRAMEWORK-SPECIFIC EXAMPLES
3
+ // =============================================================================
4
+ // Concrete, copy-paste-ready examples implementing the same "Users" feature
5
+ // in different frameworks, all following the Component → Store → Service pattern.
6
+ // =============================================================================
7
+ // ---------------------------------------------------------------------------
8
+ // ANGULAR EXAMPLES (Signals + NgRx SignalStore)
9
+ // ---------------------------------------------------------------------------
10
+ const ANGULAR_MODEL = `
11
+ // models/user.model.ts
12
+ export interface User {
13
+ id: string;
14
+ name: string;
15
+ email: string;
16
+ role: 'admin' | 'user';
17
+ isActive: boolean;
18
+ }
19
+
20
+ export interface CreateUserDto {
21
+ name: string;
22
+ email: string;
23
+ role: 'admin' | 'user';
24
+ }
25
+ `;
26
+ const ANGULAR_SERVICE = `
27
+ // services/user.service.ts
28
+ import { Injectable, inject } from '@angular/core';
29
+ import { HttpClient } from '@angular/common/http';
30
+ import { Observable } from 'rxjs';
31
+ import { User, CreateUserDto } from '../models/user.model';
32
+
33
+ @Injectable({ providedIn: 'root' })
34
+ export class UserService {
35
+ private readonly http = inject(HttpClient);
36
+ private readonly baseUrl = '/api/users';
37
+
38
+ getAll(): Observable<User[]> {
39
+ return this.http.get<User[]>(this.baseUrl);
40
+ }
41
+
42
+ getById(id: string): Observable<User> {
43
+ return this.http.get<User>(\`\${this.baseUrl}/\${id}\`);
44
+ }
45
+
46
+ create(data: CreateUserDto): Observable<User> {
47
+ return this.http.post<User>(this.baseUrl, data);
48
+ }
49
+
50
+ update(id: string, data: Partial<User>): Observable<User> {
51
+ return this.http.put<User>(\`\${this.baseUrl}/\${id}\`, data);
52
+ }
53
+
54
+ delete(id: string): Observable<void> {
55
+ return this.http.delete<void>(\`\${this.baseUrl}/\${id}\`);
56
+ }
57
+ }
58
+ `;
59
+ const ANGULAR_STORE = `
60
+ // store/user.store.ts
61
+ import { computed, inject } from '@angular/core';
62
+ import {
63
+ signalStore,
64
+ withState,
65
+ withComputed,
66
+ withMethods,
67
+ patchState,
68
+ } from '@ngrx/signals';
69
+ import { rxMethod } from '@ngrx/signals/rxjs-interop';
70
+ import { pipe, switchMap, tap } from 'rxjs';
71
+ import { tapResponse } from '@ngrx/operators';
72
+ import { UserService } from '../services/user.service';
73
+ import { User } from '../models/user.model';
74
+
75
+ interface UserState {
76
+ users: User[];
77
+ selectedUser: User | null;
78
+ loading: boolean;
79
+ error: string | null;
80
+ loaded: boolean;
81
+ filter: string;
82
+ }
83
+
84
+ const initialState: UserState = {
85
+ users: [],
86
+ selectedUser: null,
87
+ loading: false,
88
+ error: null,
89
+ loaded: false,
90
+ filter: '',
91
+ };
92
+
93
+ export const UserStore = signalStore(
94
+ { providedIn: 'root' },
95
+ withState(initialState),
96
+ withComputed((state) => ({
97
+ filteredUsers: computed(() => {
98
+ const filter = state.filter().toLowerCase();
99
+ if (!filter) return state.users();
100
+ return state.users().filter(
101
+ (u) =>
102
+ u.name.toLowerCase().includes(filter) ||
103
+ u.email.toLowerCase().includes(filter)
104
+ );
105
+ }),
106
+ activeUsers: computed(() => state.users().filter((u) => u.isActive)),
107
+ userCount: computed(() => state.users().length),
108
+ })),
109
+ withMethods((store, userService = inject(UserService)) => ({
110
+ loadUsers: rxMethod<void>(
111
+ pipe(
112
+ tap(() => patchState(store, { loading: true, error: null })),
113
+ switchMap(() =>
114
+ userService.getAll().pipe(
115
+ tapResponse({
116
+ next: (users) =>
117
+ patchState(store, { users, loading: false, loaded: true }),
118
+ error: (err: Error) =>
119
+ patchState(store, { error: err.message, loading: false }),
120
+ })
121
+ )
122
+ )
123
+ )
124
+ ),
125
+ setFilter(filter: string) {
126
+ patchState(store, { filter });
127
+ },
128
+ clearError() {
129
+ patchState(store, { error: null });
130
+ },
131
+ }))
132
+ );
133
+ `;
134
+ const ANGULAR_LIST_COMPONENT = `
135
+ // components/user-list/user-list.component.ts
136
+ import { Component, inject, OnInit } from '@angular/core';
137
+ import { UserStore } from '../../store/user.store';
138
+
139
+ @Component({
140
+ selector: 'app-user-list',
141
+ standalone: true,
142
+ template: \`
143
+ @if (store.loading()) {
144
+ <div class="loading">Loading users...</div>
145
+ }
146
+
147
+ @if (store.error(); as error) {
148
+ <div class="error">{{ error }}</div>
149
+ }
150
+
151
+ <input
152
+ type="text"
153
+ placeholder="Filter users..."
154
+ (input)="store.setFilter($any($event.target).value)"
155
+ />
156
+
157
+ <ul>
158
+ @for (user of store.filteredUsers(); track user.id) {
159
+ <li>
160
+ <span>{{ user.name }}</span>
161
+ <span>{{ user.email }}</span>
162
+ <span class="badge">{{ user.role }}</span>
163
+ </li>
164
+ }
165
+ </ul>
166
+
167
+ <p>Total: {{ store.userCount() }} users</p>
168
+ \`,
169
+ })
170
+ export class UserListComponent implements OnInit {
171
+ readonly store = inject(UserStore);
172
+
173
+ ngOnInit() {
174
+ this.store.loadUsers();
175
+ }
176
+ }
177
+ `;
178
+ // ---------------------------------------------------------------------------
179
+ // REACT EXAMPLES (Zustand)
180
+ // ---------------------------------------------------------------------------
181
+ const REACT_MODEL = `
182
+ // models/user.model.ts
183
+ export interface User {
184
+ id: string;
185
+ name: string;
186
+ email: string;
187
+ role: 'admin' | 'user';
188
+ isActive: boolean;
189
+ }
190
+
191
+ export interface CreateUserDto {
192
+ name: string;
193
+ email: string;
194
+ role: 'admin' | 'user';
195
+ }
196
+ `;
197
+ const REACT_SERVICE = `
198
+ // services/user.service.ts
199
+ import { User, CreateUserDto } from '../models/user.model';
200
+
201
+ const BASE_URL = '/api/users';
202
+
203
+ export const userService = {
204
+ async getAll(): Promise<User[]> {
205
+ const response = await fetch(BASE_URL);
206
+ if (!response.ok) throw new Error('Failed to fetch users');
207
+ return response.json();
208
+ },
209
+
210
+ async getById(id: string): Promise<User> {
211
+ const response = await fetch(\`\${BASE_URL}/\${id}\`);
212
+ if (!response.ok) throw new Error('Failed to fetch user');
213
+ return response.json();
214
+ },
215
+
216
+ async create(data: CreateUserDto): Promise<User> {
217
+ const response = await fetch(BASE_URL, {
218
+ method: 'POST',
219
+ headers: { 'Content-Type': 'application/json' },
220
+ body: JSON.stringify(data),
221
+ });
222
+ if (!response.ok) throw new Error('Failed to create user');
223
+ return response.json();
224
+ },
225
+
226
+ async update(id: string, data: Partial<User>): Promise<User> {
227
+ const response = await fetch(\`\${BASE_URL}/\${id}\`, {
228
+ method: 'PUT',
229
+ headers: { 'Content-Type': 'application/json' },
230
+ body: JSON.stringify(data),
231
+ });
232
+ if (!response.ok) throw new Error('Failed to update user');
233
+ return response.json();
234
+ },
235
+
236
+ async delete(id: string): Promise<void> {
237
+ const response = await fetch(\`\${BASE_URL}/\${id}\`, { method: 'DELETE' });
238
+ if (!response.ok) throw new Error('Failed to delete user');
239
+ },
240
+ };
241
+ `;
242
+ const REACT_STORE = `
243
+ // store/user.store.ts
244
+ import { create } from 'zustand';
245
+ import { User } from '../models/user.model';
246
+ import { userService } from '../services/user.service';
247
+
248
+ interface UserState {
249
+ users: User[];
250
+ loading: boolean;
251
+ error: string | null;
252
+ loaded: boolean;
253
+ filter: string;
254
+ }
255
+
256
+ interface UserActions {
257
+ loadUsers: () => Promise<void>;
258
+ setFilter: (filter: string) => void;
259
+ clearError: () => void;
260
+ getFilteredUsers: () => User[];
261
+ }
262
+
263
+ export const useUserStore = create<UserState & UserActions>((set, get) => ({
264
+ // State
265
+ users: [],
266
+ loading: false,
267
+ error: null,
268
+ loaded: false,
269
+ filter: '',
270
+
271
+ // Actions
272
+ loadUsers: async () => {
273
+ set({ loading: true, error: null });
274
+ try {
275
+ const users = await userService.getAll();
276
+ set({ users, loading: false, loaded: true });
277
+ } catch (err) {
278
+ set({ error: (err as Error).message, loading: false });
279
+ }
280
+ },
281
+
282
+ setFilter: (filter: string) => set({ filter }),
283
+ clearError: () => set({ error: null }),
284
+
285
+ // Derived (computed)
286
+ getFilteredUsers: () => {
287
+ const { users, filter } = get();
288
+ if (!filter) return users;
289
+ const lower = filter.toLowerCase();
290
+ return users.filter(
291
+ (u) =>
292
+ u.name.toLowerCase().includes(lower) ||
293
+ u.email.toLowerCase().includes(lower)
294
+ );
295
+ },
296
+ }));
297
+ `;
298
+ const REACT_LIST_COMPONENT = `
299
+ // components/UserList.tsx
300
+ import { useEffect } from 'react';
301
+ import { useUserStore } from '../store/user.store';
302
+
303
+ export function UserList() {
304
+ const { loading, error, loadUsers, setFilter, getFilteredUsers } =
305
+ useUserStore();
306
+
307
+ useEffect(() => {
308
+ loadUsers();
309
+ }, [loadUsers]);
310
+
311
+ const filteredUsers = getFilteredUsers();
312
+
313
+ if (loading) return <div className="loading">Loading users...</div>;
314
+ if (error) return <div className="error">{error}</div>;
315
+
316
+ return (
317
+ <div>
318
+ <input
319
+ type="text"
320
+ placeholder="Filter users..."
321
+ onChange={(e) => setFilter(e.target.value)}
322
+ />
323
+
324
+ <ul>
325
+ {filteredUsers.map((user) => (
326
+ <li key={user.id}>
327
+ <span>{user.name}</span>
328
+ <span>{user.email}</span>
329
+ <span className="badge">{user.role}</span>
330
+ </li>
331
+ ))}
332
+ </ul>
333
+
334
+ <p>Total: {filteredUsers.length} users</p>
335
+ </div>
336
+ );
337
+ }
338
+ `;
339
+ // ---------------------------------------------------------------------------
340
+ // VUE EXAMPLES (Pinia)
341
+ // ---------------------------------------------------------------------------
342
+ const VUE_MODEL = `
343
+ // models/user.model.ts
344
+ export interface User {
345
+ id: string;
346
+ name: string;
347
+ email: string;
348
+ role: 'admin' | 'user';
349
+ isActive: boolean;
350
+ }
351
+
352
+ export interface CreateUserDto {
353
+ name: string;
354
+ email: string;
355
+ role: 'admin' | 'user';
356
+ }
357
+ `;
358
+ const VUE_SERVICE = `
359
+ // services/user.service.ts
360
+ import type { User, CreateUserDto } from '../models/user.model';
361
+
362
+ const BASE_URL = '/api/users';
363
+
364
+ export const userService = {
365
+ async getAll(): Promise<User[]> {
366
+ const response = await fetch(BASE_URL);
367
+ if (!response.ok) throw new Error('Failed to fetch users');
368
+ return response.json();
369
+ },
370
+
371
+ async getById(id: string): Promise<User> {
372
+ const response = await fetch(\`\${BASE_URL}/\${id}\`);
373
+ if (!response.ok) throw new Error('Failed to fetch user');
374
+ return response.json();
375
+ },
376
+
377
+ async create(data: CreateUserDto): Promise<User> {
378
+ const response = await fetch(BASE_URL, {
379
+ method: 'POST',
380
+ headers: { 'Content-Type': 'application/json' },
381
+ body: JSON.stringify(data),
382
+ });
383
+ if (!response.ok) throw new Error('Failed to create user');
384
+ return response.json();
385
+ },
386
+
387
+ async update(id: string, data: Partial<User>): Promise<User> {
388
+ const response = await fetch(\`\${BASE_URL}/\${id}\`, {
389
+ method: 'PUT',
390
+ headers: { 'Content-Type': 'application/json' },
391
+ body: JSON.stringify(data),
392
+ });
393
+ if (!response.ok) throw new Error('Failed to update user');
394
+ return response.json();
395
+ },
396
+
397
+ async delete(id: string): Promise<void> {
398
+ const response = await fetch(\`\${BASE_URL}/\${id}\`, { method: 'DELETE' });
399
+ if (!response.ok) throw new Error('Failed to delete user');
400
+ },
401
+ };
402
+ `;
403
+ const VUE_STORE = `
404
+ // store/user.store.ts
405
+ import { defineStore } from 'pinia';
406
+ import { ref, computed } from 'vue';
407
+ import { userService } from '../services/user.service';
408
+ import type { User } from '../models/user.model';
409
+
410
+ export const useUserStore = defineStore('users', () => {
411
+ // State
412
+ const users = ref<User[]>([]);
413
+ const loading = ref(false);
414
+ const error = ref<string | null>(null);
415
+ const loaded = ref(false);
416
+ const filter = ref('');
417
+
418
+ // Getters (computed)
419
+ const filteredUsers = computed(() => {
420
+ if (!filter.value) return users.value;
421
+ const lower = filter.value.toLowerCase();
422
+ return users.value.filter(
423
+ (u) =>
424
+ u.name.toLowerCase().includes(lower) ||
425
+ u.email.toLowerCase().includes(lower)
426
+ );
427
+ });
428
+
429
+ const activeUsers = computed(() =>
430
+ users.value.filter((u) => u.isActive)
431
+ );
432
+
433
+ const userCount = computed(() => users.value.length);
434
+
435
+ // Actions
436
+ async function loadUsers() {
437
+ loading.value = true;
438
+ error.value = null;
439
+ try {
440
+ users.value = await userService.getAll();
441
+ loaded.value = true;
442
+ } catch (err) {
443
+ error.value = (err as Error).message;
444
+ } finally {
445
+ loading.value = false;
446
+ }
447
+ }
448
+
449
+ function setFilter(value: string) {
450
+ filter.value = value;
451
+ }
452
+
453
+ function clearError() {
454
+ error.value = null;
455
+ }
456
+
457
+ return {
458
+ users,
459
+ loading,
460
+ error,
461
+ loaded,
462
+ filter,
463
+ filteredUsers,
464
+ activeUsers,
465
+ userCount,
466
+ loadUsers,
467
+ setFilter,
468
+ clearError,
469
+ };
470
+ });
471
+ `;
472
+ const VUE_LIST_COMPONENT = `
473
+ <!-- components/UserList.vue -->
474
+ <script setup lang="ts">
475
+ import { onMounted } from 'vue';
476
+ import { useUserStore } from '../store/user.store';
477
+
478
+ const store = useUserStore();
479
+
480
+ onMounted(() => {
481
+ store.loadUsers();
482
+ });
483
+ </script>
484
+
485
+ <template>
486
+ <div>
487
+ <div v-if="store.loading" class="loading">Loading users...</div>
488
+ <div v-if="store.error" class="error">{{ store.error }}</div>
489
+
490
+ <input
491
+ type="text"
492
+ placeholder="Filter users..."
493
+ @input="store.setFilter(($event.target as HTMLInputElement).value)"
494
+ />
495
+
496
+ <ul>
497
+ <li v-for="user in store.filteredUsers" :key="user.id">
498
+ <span>{{ user.name }}</span>
499
+ <span>{{ user.email }}</span>
500
+ <span class="badge">{{ user.role }}</span>
501
+ </li>
502
+ </ul>
503
+
504
+ <p>Total: {{ store.userCount }} users</p>
505
+ </div>
506
+ </template>
507
+ `;
508
+ // ---------------------------------------------------------------------------
509
+ // SVELTE EXAMPLES (Svelte Stores)
510
+ // ---------------------------------------------------------------------------
511
+ const SVELTE_MODEL = `
512
+ // models/user.model.ts
513
+ export interface User {
514
+ id: string;
515
+ name: string;
516
+ email: string;
517
+ role: 'admin' | 'user';
518
+ isActive: boolean;
519
+ }
520
+
521
+ export interface CreateUserDto {
522
+ name: string;
523
+ email: string;
524
+ role: 'admin' | 'user';
525
+ }
526
+ `;
527
+ const SVELTE_SERVICE = `
528
+ // services/user.service.ts
529
+ import type { User, CreateUserDto } from '../models/user.model';
530
+
531
+ const BASE_URL = '/api/users';
532
+
533
+ export const userService = {
534
+ async getAll(): Promise<User[]> {
535
+ const response = await fetch(BASE_URL);
536
+ if (!response.ok) throw new Error('Failed to fetch users');
537
+ return response.json();
538
+ },
539
+
540
+ async getById(id: string): Promise<User> {
541
+ const response = await fetch(\`\${BASE_URL}/\${id}\`);
542
+ if (!response.ok) throw new Error('Failed to fetch user');
543
+ return response.json();
544
+ },
545
+
546
+ async create(data: CreateUserDto): Promise<User> {
547
+ const response = await fetch(BASE_URL, {
548
+ method: 'POST',
549
+ headers: { 'Content-Type': 'application/json' },
550
+ body: JSON.stringify(data),
551
+ });
552
+ if (!response.ok) throw new Error('Failed to create user');
553
+ return response.json();
554
+ },
555
+
556
+ async update(id: string, data: Partial<User>): Promise<User> {
557
+ const response = await fetch(\`\${BASE_URL}/\${id}\`, {
558
+ method: 'PUT',
559
+ headers: { 'Content-Type': 'application/json' },
560
+ body: JSON.stringify(data),
561
+ });
562
+ if (!response.ok) throw new Error('Failed to update user');
563
+ return response.json();
564
+ },
565
+
566
+ async delete(id: string): Promise<void> {
567
+ const response = await fetch(\`\${BASE_URL}/\${id}\`, { method: 'DELETE' });
568
+ if (!response.ok) throw new Error('Failed to delete user');
569
+ },
570
+ };
571
+ `;
572
+ const SVELTE_STORE = `
573
+ // store/user.store.ts
574
+ import { writable, derived } from 'svelte/store';
575
+ import { userService } from '../services/user.service';
576
+ import type { User } from '../models/user.model';
577
+
578
+ // State
579
+ const users = writable<User[]>([]);
580
+ const loading = writable(false);
581
+ const error = writable<string | null>(null);
582
+ const loaded = writable(false);
583
+ const filter = writable('');
584
+
585
+ // Derived (computed)
586
+ const filteredUsers = derived([users, filter], ([$users, $filter]) => {
587
+ if (!$filter) return $users;
588
+ const lower = $filter.toLowerCase();
589
+ return $users.filter(
590
+ (u) =>
591
+ u.name.toLowerCase().includes(lower) ||
592
+ u.email.toLowerCase().includes(lower)
593
+ );
594
+ });
595
+
596
+ const activeUsers = derived(users, ($users) =>
597
+ $users.filter((u) => u.isActive)
598
+ );
599
+
600
+ const userCount = derived(users, ($users) => $users.length);
601
+
602
+ // Actions
603
+ async function loadUsers() {
604
+ loading.set(true);
605
+ error.set(null);
606
+ try {
607
+ const data = await userService.getAll();
608
+ users.set(data);
609
+ loaded.set(true);
610
+ } catch (err) {
611
+ error.set((err as Error).message);
612
+ } finally {
613
+ loading.set(false);
614
+ }
615
+ }
616
+
617
+ function setFilter(value: string) {
618
+ filter.set(value);
619
+ }
620
+
621
+ function clearError() {
622
+ error.set(null);
623
+ }
624
+
625
+ export const userStore = {
626
+ users,
627
+ loading,
628
+ error,
629
+ loaded,
630
+ filter,
631
+ filteredUsers,
632
+ activeUsers,
633
+ userCount,
634
+ loadUsers,
635
+ setFilter,
636
+ clearError,
637
+ };
638
+ `;
639
+ const SVELTE_LIST_COMPONENT = `
640
+ <!-- components/UserList.svelte -->
641
+ <script lang="ts">
642
+ import { onMount } from 'svelte';
643
+ import { userStore } from '../store/user.store';
644
+
645
+ const { filteredUsers, loading, error, userCount, loadUsers, setFilter } =
646
+ userStore;
647
+
648
+ onMount(() => {
649
+ loadUsers();
650
+ });
651
+ </script>
652
+
653
+ {#if $loading}
654
+ <div class="loading">Loading users...</div>
655
+ {/if}
656
+
657
+ {#if $error}
658
+ <div class="error">{$error}</div>
659
+ {/if}
660
+
661
+ <input
662
+ type="text"
663
+ placeholder="Filter users..."
664
+ on:input={(e) => setFilter(e.currentTarget.value)}
665
+ />
666
+
667
+ <ul>
668
+ {#each $filteredUsers as user (user.id)}
669
+ <li>
670
+ <span>{user.name}</span>
671
+ <span>{user.email}</span>
672
+ <span class="badge">{user.role}</span>
673
+ </li>
674
+ {/each}
675
+ </ul>
676
+
677
+ <p>Total: {$userCount} users</p>
678
+ `;
679
+ // ---------------------------------------------------------------------------
680
+ // EXAMPLE REGISTRY
681
+ // ---------------------------------------------------------------------------
682
+ const EXAMPLES = {
683
+ angular: {
684
+ list: {
685
+ model: ANGULAR_MODEL,
686
+ service: ANGULAR_SERVICE,
687
+ store: ANGULAR_STORE,
688
+ component: ANGULAR_LIST_COMPONENT,
689
+ },
690
+ detail: {
691
+ model: ANGULAR_MODEL,
692
+ service: ANGULAR_SERVICE,
693
+ store: ANGULAR_STORE,
694
+ component: ANGULAR_LIST_COMPONENT, // Reuse for now
695
+ },
696
+ form: {
697
+ model: ANGULAR_MODEL,
698
+ service: ANGULAR_SERVICE,
699
+ store: ANGULAR_STORE,
700
+ component: ANGULAR_LIST_COMPONENT,
701
+ },
702
+ crud: {
703
+ model: ANGULAR_MODEL,
704
+ service: ANGULAR_SERVICE,
705
+ store: ANGULAR_STORE,
706
+ component: ANGULAR_LIST_COMPONENT,
707
+ },
708
+ },
709
+ react: {
710
+ list: {
711
+ model: REACT_MODEL,
712
+ service: REACT_SERVICE,
713
+ store: REACT_STORE,
714
+ component: REACT_LIST_COMPONENT,
715
+ },
716
+ detail: {
717
+ model: REACT_MODEL,
718
+ service: REACT_SERVICE,
719
+ store: REACT_STORE,
720
+ component: REACT_LIST_COMPONENT,
721
+ },
722
+ form: {
723
+ model: REACT_MODEL,
724
+ service: REACT_SERVICE,
725
+ store: REACT_STORE,
726
+ component: REACT_LIST_COMPONENT,
727
+ },
728
+ crud: {
729
+ model: REACT_MODEL,
730
+ service: REACT_SERVICE,
731
+ store: REACT_STORE,
732
+ component: REACT_LIST_COMPONENT,
733
+ },
734
+ },
735
+ vue: {
736
+ list: {
737
+ model: VUE_MODEL,
738
+ service: VUE_SERVICE,
739
+ store: VUE_STORE,
740
+ component: VUE_LIST_COMPONENT,
741
+ },
742
+ detail: {
743
+ model: VUE_MODEL,
744
+ service: VUE_SERVICE,
745
+ store: VUE_STORE,
746
+ component: VUE_LIST_COMPONENT,
747
+ },
748
+ form: {
749
+ model: VUE_MODEL,
750
+ service: VUE_SERVICE,
751
+ store: VUE_STORE,
752
+ component: VUE_LIST_COMPONENT,
753
+ },
754
+ crud: {
755
+ model: VUE_MODEL,
756
+ service: VUE_SERVICE,
757
+ store: VUE_STORE,
758
+ component: VUE_LIST_COMPONENT,
759
+ },
760
+ },
761
+ svelte: {
762
+ list: {
763
+ model: SVELTE_MODEL,
764
+ service: SVELTE_SERVICE,
765
+ store: SVELTE_STORE,
766
+ component: SVELTE_LIST_COMPONENT,
767
+ },
768
+ detail: {
769
+ model: SVELTE_MODEL,
770
+ service: SVELTE_SERVICE,
771
+ store: SVELTE_STORE,
772
+ component: SVELTE_LIST_COMPONENT,
773
+ },
774
+ form: {
775
+ model: SVELTE_MODEL,
776
+ service: SVELTE_SERVICE,
777
+ store: SVELTE_STORE,
778
+ component: SVELTE_LIST_COMPONENT,
779
+ },
780
+ crud: {
781
+ model: SVELTE_MODEL,
782
+ service: SVELTE_SERVICE,
783
+ store: SVELTE_STORE,
784
+ component: SVELTE_LIST_COMPONENT,
785
+ },
786
+ },
787
+ };
788
+ export function getExample(framework, pattern) {
789
+ const example = EXAMPLES[framework]?.[pattern];
790
+ if (!example)
791
+ return `No example found for ${framework}/${pattern}`;
792
+ return `# ${framework.charAt(0).toUpperCase() + framework.slice(1)} — ${pattern.charAt(0).toUpperCase() + pattern.slice(1)} Pattern
793
+
794
+ Following the **Component → Store → Service** philosophy:
795
+
796
+ ## 1. Model (Define the contract)
797
+ \`\`\`typescript
798
+ ${example.model.trim()}
799
+ \`\`\`
800
+
801
+ ## 2. Service (Data access layer — stateless)
802
+ \`\`\`typescript
803
+ ${example.service.trim()}
804
+ \`\`\`
805
+
806
+ ## 3. Store (State management — single source of truth)
807
+ \`\`\`typescript
808
+ ${example.store.trim()}
809
+ \`\`\`
810
+
811
+ ## 4. Component (UI — reads from store, dispatches to store)
812
+ \`\`\`typescript
813
+ ${example.component.trim()}
814
+ \`\`\`
815
+ `;
816
+ }
817
+ export const AVAILABLE_FRAMEWORKS = [
818
+ 'angular',
819
+ 'react',
820
+ 'vue',
821
+ 'svelte',
822
+ ];
823
+ export const AVAILABLE_PATTERNS = [
824
+ 'list',
825
+ 'detail',
826
+ 'form',
827
+ 'crud',
828
+ ];
829
+ //# sourceMappingURL=examples.js.map