@malamute/ai-rules 1.2.0 → 1.3.1

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 (134) hide show
  1. package/README.md +4 -2
  2. package/bin/cli.js +1 -1
  3. package/configs/_shared/rules/conventions/npm.md +80 -0
  4. package/configs/angular/{.claude/settings.json → settings.json} +2 -0
  5. package/configs/dotnet/{.claude/settings.json → settings.json} +2 -0
  6. package/configs/fastapi/{.claude/settings.json → settings.json} +2 -0
  7. package/configs/flask/{.claude/settings.json → settings.json} +2 -0
  8. package/configs/nestjs/{.claude/settings.json → settings.json} +2 -0
  9. package/configs/nextjs/{.claude/settings.json → settings.json} +2 -0
  10. package/package.json +2 -1
  11. package/src/cli.js +5 -7
  12. package/src/config.js +52 -18
  13. package/src/index.js +4 -13
  14. package/src/installer.js +121 -68
  15. package/src/merge.js +8 -15
  16. package/src/tech-config.json +29 -13
  17. package/src/utils.js +7 -15
  18. package/configs/angular/.claude/skills/ngrx-slice/SKILL.md +0 -362
  19. package/configs/angular/.claude/skills/signal-store/SKILL.md +0 -445
  20. /package/configs/_shared/{.claude/rules → rules}/conventions/documentation.md +0 -0
  21. /package/configs/_shared/{.claude/rules → rules}/conventions/git.md +0 -0
  22. /package/configs/_shared/{.claude/rules → rules}/conventions/performance.md +0 -0
  23. /package/configs/_shared/{.claude/rules → rules}/conventions/principles.md +0 -0
  24. /package/configs/_shared/{.claude/rules → rules}/devops/ci-cd.md +0 -0
  25. /package/configs/_shared/{.claude/rules → rules}/devops/docker.md +0 -0
  26. /package/configs/_shared/{.claude/rules → rules}/devops/nx.md +0 -0
  27. /package/configs/_shared/{.claude/rules → rules}/domain/backend/api-design.md +0 -0
  28. /package/configs/_shared/{.claude/rules → rules}/domain/frontend/accessibility.md +0 -0
  29. /package/configs/_shared/{.claude/rules → rules}/lang/csharp/async.md +0 -0
  30. /package/configs/_shared/{.claude/rules → rules}/lang/csharp/csharp.md +0 -0
  31. /package/configs/_shared/{.claude/rules → rules}/lang/csharp/linq.md +0 -0
  32. /package/configs/_shared/{.claude/rules → rules}/lang/python/async.md +0 -0
  33. /package/configs/_shared/{.claude/rules → rules}/lang/python/celery.md +0 -0
  34. /package/configs/_shared/{.claude/rules → rules}/lang/python/config.md +0 -0
  35. /package/configs/_shared/{.claude/rules → rules}/lang/python/database/sqlalchemy.md +0 -0
  36. /package/configs/_shared/{.claude/rules → rules}/lang/python/deployment.md +0 -0
  37. /package/configs/_shared/{.claude/rules → rules}/lang/python/error-handling.md +0 -0
  38. /package/configs/_shared/{.claude/rules → rules}/lang/python/migrations.md +0 -0
  39. /package/configs/_shared/{.claude/rules → rules}/lang/python/python.md +0 -0
  40. /package/configs/_shared/{.claude/rules → rules}/lang/python/repository.md +0 -0
  41. /package/configs/_shared/{.claude/rules → rules}/lang/python/testing.md +0 -0
  42. /package/configs/_shared/{.claude/rules → rules}/lang/typescript/async.md +0 -0
  43. /package/configs/_shared/{.claude/rules → rules}/lang/typescript/generics.md +0 -0
  44. /package/configs/_shared/{.claude/rules → rules}/lang/typescript/typescript.md +0 -0
  45. /package/configs/_shared/{.claude/rules → rules}/quality/error-handling.md +0 -0
  46. /package/configs/_shared/{.claude/rules → rules}/quality/logging.md +0 -0
  47. /package/configs/_shared/{.claude/rules → rules}/quality/observability.md +0 -0
  48. /package/configs/_shared/{.claude/rules → rules}/quality/testing-patterns.md +0 -0
  49. /package/configs/_shared/{.claude/rules → rules}/security/secrets-management.md +0 -0
  50. /package/configs/_shared/{.claude/rules → rules}/security/security.md +0 -0
  51. /package/configs/_shared/{.claude/skills → skills}/analysis/explore/SKILL.md +0 -0
  52. /package/configs/_shared/{.claude/skills → skills}/analysis/security-audit/SKILL.md +0 -0
  53. /package/configs/_shared/{.claude/skills → skills}/dev/api-endpoint/SKILL.md +0 -0
  54. /package/configs/_shared/{.claude/skills → skills}/dev/debug/SKILL.md +0 -0
  55. /package/configs/_shared/{.claude/skills → skills}/dev/generate-tests/SKILL.md +0 -0
  56. /package/configs/_shared/{.claude/skills → skills}/dev/learning/SKILL.md +0 -0
  57. /package/configs/_shared/{.claude/skills → skills}/dev/spec/SKILL.md +0 -0
  58. /package/configs/_shared/{.claude/skills → skills}/git/fix-issue/SKILL.md +0 -0
  59. /package/configs/_shared/{.claude/skills → skills}/git/review/SKILL.md +0 -0
  60. /package/configs/_shared/{.claude/skills → skills}/git/review-pr/SKILL.md +0 -0
  61. /package/configs/_shared/{.claude/skills → skills}/infra/deploy/SKILL.md +0 -0
  62. /package/configs/_shared/{.claude/skills → skills}/infra/docker/SKILL.md +0 -0
  63. /package/configs/_shared/{.claude/skills → skills}/infra/migration/SKILL.md +0 -0
  64. /package/configs/_shared/{.claude/skills → skills}/nx/nx-affected/SKILL.md +0 -0
  65. /package/configs/_shared/{.claude/skills → skills}/nx/nx-lib/SKILL.md +0 -0
  66. /package/configs/angular/{.claude/rules → rules}/core/components.md +0 -0
  67. /package/configs/angular/{.claude/rules → rules}/core/resource.md +0 -0
  68. /package/configs/angular/{.claude/rules → rules}/core/signals.md +0 -0
  69. /package/configs/angular/{.claude/rules → rules}/http.md +0 -0
  70. /package/configs/angular/{.claude/rules → rules}/routing.md +0 -0
  71. /package/configs/angular/{.claude/rules → rules}/ssr.md +0 -0
  72. /package/configs/angular/{.claude/rules → rules}/state/signal-store.md +0 -0
  73. /package/configs/angular/{.claude/rules → rules}/state/state.md +0 -0
  74. /package/configs/angular/{.claude/rules → rules}/testing.md +0 -0
  75. /package/configs/angular/{.claude/rules → rules}/ui/aria.md +0 -0
  76. /package/configs/angular/{.claude/rules → rules}/ui/forms.md +0 -0
  77. /package/configs/angular/{.claude/rules → rules}/ui/pipes-directives.md +0 -0
  78. /package/configs/dotnet/{.claude/rules → rules}/api.md +0 -0
  79. /package/configs/dotnet/{.claude/rules → rules}/architecture.md +0 -0
  80. /package/configs/dotnet/{.claude/rules → rules}/background-services.md +0 -0
  81. /package/configs/dotnet/{.claude/rules → rules}/configuration.md +0 -0
  82. /package/configs/dotnet/{.claude/rules → rules}/database/efcore.md +0 -0
  83. /package/configs/dotnet/{.claude/rules → rules}/ddd.md +0 -0
  84. /package/configs/dotnet/{.claude/rules → rules}/dependency-injection.md +0 -0
  85. /package/configs/dotnet/{.claude/rules → rules}/mediatr.md +0 -0
  86. /package/configs/dotnet/{.claude/rules → rules}/middleware.md +0 -0
  87. /package/configs/dotnet/{.claude/rules → rules}/result-pattern.md +0 -0
  88. /package/configs/dotnet/{.claude/rules → rules}/testing.md +0 -0
  89. /package/configs/dotnet/{.claude/rules → rules}/validation.md +0 -0
  90. /package/configs/fastapi/{.claude/rules → rules}/background-tasks.md +0 -0
  91. /package/configs/fastapi/{.claude/rules → rules}/dependencies.md +0 -0
  92. /package/configs/fastapi/{.claude/rules → rules}/fastapi.md +0 -0
  93. /package/configs/fastapi/{.claude/rules → rules}/lifespan.md +0 -0
  94. /package/configs/fastapi/{.claude/rules → rules}/middleware.md +0 -0
  95. /package/configs/fastapi/{.claude/rules → rules}/pydantic.md +0 -0
  96. /package/configs/fastapi/{.claude/rules → rules}/responses.md +0 -0
  97. /package/configs/fastapi/{.claude/rules → rules}/routers.md +0 -0
  98. /package/configs/fastapi/{.claude/rules → rules}/security.md +0 -0
  99. /package/configs/fastapi/{.claude/rules → rules}/testing.md +0 -0
  100. /package/configs/fastapi/{.claude/rules → rules}/websockets.md +0 -0
  101. /package/configs/flask/{.claude/rules → rules}/blueprints.md +0 -0
  102. /package/configs/flask/{.claude/rules → rules}/cli.md +0 -0
  103. /package/configs/flask/{.claude/rules → rules}/configuration.md +0 -0
  104. /package/configs/flask/{.claude/rules → rules}/context.md +0 -0
  105. /package/configs/flask/{.claude/rules → rules}/error-handlers.md +0 -0
  106. /package/configs/flask/{.claude/rules → rules}/extensions.md +0 -0
  107. /package/configs/flask/{.claude/rules → rules}/flask.md +0 -0
  108. /package/configs/flask/{.claude/rules → rules}/marshmallow.md +0 -0
  109. /package/configs/flask/{.claude/rules → rules}/security.md +0 -0
  110. /package/configs/flask/{.claude/rules → rules}/testing.md +0 -0
  111. /package/configs/nestjs/{.claude/rules → rules}/auth.md +0 -0
  112. /package/configs/nestjs/{.claude/rules → rules}/common-patterns.md +0 -0
  113. /package/configs/nestjs/{.claude/rules → rules}/database/prisma.md +0 -0
  114. /package/configs/nestjs/{.claude/rules → rules}/database/typeorm.md +0 -0
  115. /package/configs/nestjs/{.claude/rules → rules}/filters.md +0 -0
  116. /package/configs/nestjs/{.claude/rules → rules}/interceptors.md +0 -0
  117. /package/configs/nestjs/{.claude/rules → rules}/middleware.md +0 -0
  118. /package/configs/nestjs/{.claude/rules → rules}/modules.md +0 -0
  119. /package/configs/nestjs/{.claude/rules → rules}/pipes.md +0 -0
  120. /package/configs/nestjs/{.claude/rules → rules}/testing.md +0 -0
  121. /package/configs/nestjs/{.claude/rules → rules}/validation.md +0 -0
  122. /package/configs/nestjs/{.claude/rules → rules}/websockets.md +0 -0
  123. /package/configs/nextjs/{.claude/rules → rules}/api-routes.md +0 -0
  124. /package/configs/nextjs/{.claude/rules → rules}/authentication.md +0 -0
  125. /package/configs/nextjs/{.claude/rules → rules}/components.md +0 -0
  126. /package/configs/nextjs/{.claude/rules → rules}/data-fetching.md +0 -0
  127. /package/configs/nextjs/{.claude/rules → rules}/database.md +0 -0
  128. /package/configs/nextjs/{.claude/rules → rules}/middleware.md +0 -0
  129. /package/configs/nextjs/{.claude/rules → rules}/routing.md +0 -0
  130. /package/configs/nextjs/{.claude/rules → rules}/seo.md +0 -0
  131. /package/configs/nextjs/{.claude/rules → rules}/server-actions.md +0 -0
  132. /package/configs/nextjs/{.claude/rules → rules}/state/redux-toolkit.md +0 -0
  133. /package/configs/nextjs/{.claude/rules → rules}/state/zustand.md +0 -0
  134. /package/configs/nextjs/{.claude/rules → rules}/testing.md +0 -0
@@ -1,29 +1,45 @@
1
1
  {
2
2
  "technologies": {
3
3
  "angular": {
4
- "includeRules": ["lang/typescript", "domain/frontend"]
4
+ "type": "frontend",
5
+ "language": "typescript"
5
6
  },
6
7
  "nextjs": {
7
- "includeRules": ["lang/typescript", "domain/frontend"]
8
+ "type": "frontend",
9
+ "language": "typescript"
8
10
  },
9
11
  "nestjs": {
10
- "includeRules": ["lang/typescript", "domain/backend"]
12
+ "type": "backend",
13
+ "language": "typescript"
11
14
  },
12
15
  "dotnet": {
13
- "includeRules": ["lang/csharp", "domain/backend"]
16
+ "type": "backend",
17
+ "language": "csharp"
14
18
  },
15
19
  "fastapi": {
16
- "includeRules": ["lang/python", "domain/backend"]
20
+ "type": "backend",
21
+ "language": "python"
17
22
  },
18
23
  "flask": {
19
- "includeRules": ["lang/python", "domain/backend"]
24
+ "type": "backend",
25
+ "language": "python"
20
26
  }
21
27
  },
22
- "ruleCategories": {
23
- "lang/typescript": "TypeScript best practices",
24
- "lang/python": "Python best practices",
25
- "lang/csharp": "C# language best practices",
26
- "domain/frontend": "Accessibility, UI patterns",
27
- "domain/backend": "API design, server patterns"
28
- }
28
+ "ruleMapping": {
29
+ "language": {
30
+ "typescript": "lang/typescript",
31
+ "python": "lang/python",
32
+ "csharp": "lang/csharp"
33
+ },
34
+ "type": {
35
+ "frontend": "domain/frontend",
36
+ "backend": "domain/backend"
37
+ }
38
+ },
39
+ "alwaysInclude": [
40
+ "conventions",
41
+ "quality",
42
+ "security",
43
+ "devops"
44
+ ]
29
45
  }
package/src/utils.js CHANGED
@@ -1,7 +1,7 @@
1
- const fs = require('fs');
2
- const path = require('path');
1
+ import fs from 'fs';
2
+ import path from 'path';
3
3
 
4
- const colors = {
4
+ export const colors = {
5
5
  red: (text) => `\x1b[31m${text}\x1b[0m`,
6
6
  green: (text) => `\x1b[32m${text}\x1b[0m`,
7
7
  blue: (text) => `\x1b[34m${text}\x1b[0m`,
@@ -11,7 +11,7 @@ const colors = {
11
11
  bold: (text) => `\x1b[1m${text}\x1b[0m`,
12
12
  };
13
13
 
14
- const log = {
14
+ export const log = {
15
15
  info: (msg) => console.log(`${colors.blue('ℹ')} ${msg}`),
16
16
  success: (msg) => console.log(`${colors.green('✓')} ${msg}`),
17
17
  warning: (msg) => console.log(`${colors.yellow('⚠')} ${msg}`),
@@ -19,7 +19,7 @@ const log = {
19
19
  dry: (msg) => console.log(`${colors.cyan('○')} ${msg}`),
20
20
  };
21
21
 
22
- function getFilesRecursive(dir, baseDir = dir) {
22
+ export function getFilesRecursive(dir, baseDir = dir) {
23
23
  const files = [];
24
24
  if (!fs.existsSync(dir)) return files;
25
25
 
@@ -35,7 +35,7 @@ function getFilesRecursive(dir, baseDir = dir) {
35
35
  return files;
36
36
  }
37
37
 
38
- function copyDirRecursive(src, dest, options = {}) {
38
+ export function copyDirRecursive(src, dest, options = {}) {
39
39
  const { dryRun = false, backup = false, targetDir = dest } = options;
40
40
  const operations = [];
41
41
 
@@ -75,7 +75,7 @@ function copyDirRecursive(src, dest, options = {}) {
75
75
  return operations;
76
76
  }
77
77
 
78
- function backupFile(filePath, targetDir) {
78
+ export function backupFile(filePath, targetDir) {
79
79
  const backupDir = path.join(targetDir, '.claude', 'backups');
80
80
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
81
81
  const relativePath = path.relative(targetDir, filePath);
@@ -86,11 +86,3 @@ function backupFile(filePath, targetDir) {
86
86
 
87
87
  return backupPath;
88
88
  }
89
-
90
- module.exports = {
91
- colors,
92
- log,
93
- getFilesRecursive,
94
- copyDirRecursive,
95
- backupFile,
96
- };
@@ -1,362 +0,0 @@
1
- ---
2
- name: ngrx-slice
3
- description: Generate a complete NgRx store slice with actions, reducer, effects, selectors, and Entity Adapter
4
- argument-hint: <domain> [--entity <EntityName>]
5
- ---
6
-
7
- # Generate NgRx Store Slice
8
-
9
- Generate a complete NgRx store slice following best practices with Entity Adapter.
10
-
11
- ## Syntax
12
-
13
- ```
14
- /ngrx-slice <domain> [--entity <EntityName>]
15
- ```
16
-
17
- ## Examples
18
-
19
- ```bash
20
- /ngrx-slice users
21
- /ngrx-slice products --entity Product
22
- /ngrx-slice orders --entity Order
23
- ```
24
-
25
- ## Generated Structure
26
-
27
- ```
28
- libs/<domain>/data-access/src/lib/+state/
29
- ├── <domain>.actions.ts # Action groups with createActionGroup
30
- ├── <domain>.reducer.ts # Reducer with Entity Adapter
31
- ├── <domain>.effects.ts # Functional effects
32
- ├── <domain>.selectors.ts # Memoized selectors
33
- ├── <domain>.state.ts # State interface
34
- └── <domain>.adapter.ts # Entity Adapter config
35
- ```
36
-
37
- ## File Templates
38
-
39
- ### 1. State Interface (`<domain>.state.ts`)
40
-
41
- ```typescript
42
- import { EntityState } from '@ngrx/entity';
43
-
44
- export interface <Entity> {
45
- id: string;
46
- // Add entity properties
47
- }
48
-
49
- export interface <Entity>State extends EntityState<<Entity>> {
50
- selectedId: string | null;
51
- loading: boolean;
52
- error: string | null;
53
- }
54
- ```
55
-
56
- ### 2. Entity Adapter (`<domain>.adapter.ts`)
57
-
58
- ```typescript
59
- import { createEntityAdapter, EntityAdapter } from '@ngrx/entity';
60
- import { <Entity>, <Entity>State } from './<domain>.state';
61
-
62
- export const <entity>Adapter: EntityAdapter<<Entity>> = createEntityAdapter<<Entity>>({
63
- selectId: (<entity>) => <entity>.id,
64
- sortComparer: (a, b) => a.name.localeCompare(b.name),
65
- });
66
-
67
- export const initial<Entity>State: <Entity>State = <entity>Adapter.getInitialState({
68
- selectedId: null,
69
- loading: false,
70
- error: null,
71
- });
72
- ```
73
-
74
- ### 3. Actions (`<domain>.actions.ts`)
75
-
76
- ```typescript
77
- import { createActionGroup, emptyProps, props } from '@ngrx/store';
78
- import { Update } from '@ngrx/entity';
79
- import { <Entity> } from './<domain>.state';
80
-
81
- export const <Entity>Actions = createActionGroup({
82
- source: '<Entities>',
83
- events: {
84
- // Load
85
- 'Load <Entities>': emptyProps(),
86
- 'Load <Entities> Success': props<{ <entities>: <Entity>[] }>(),
87
- 'Load <Entities> Failure': props<{ error: string }>(),
88
-
89
- // Load Single
90
- 'Load <Entity>': props<{ id: string }>(),
91
- 'Load <Entity> Success': props<{ <entity>: <Entity> }>(),
92
- 'Load <Entity> Failure': props<{ error: string }>(),
93
-
94
- // Create
95
- 'Create <Entity>': props<{ <entity>: Omit<<Entity>, 'id'> }>(),
96
- 'Create <Entity> Success': props<{ <entity>: <Entity> }>(),
97
- 'Create <Entity> Failure': props<{ error: string }>(),
98
-
99
- // Update
100
- 'Update <Entity>': props<{ update: Update<<Entity>> }>(),
101
- 'Update <Entity> Success': props<{ <entity>: <Entity> }>(),
102
- 'Update <Entity> Failure': props<{ error: string }>(),
103
-
104
- // Delete
105
- 'Delete <Entity>': props<{ id: string }>(),
106
- 'Delete <Entity> Success': props<{ id: string }>(),
107
- 'Delete <Entity> Failure': props<{ error: string }>(),
108
-
109
- // Selection
110
- 'Select <Entity>': props<{ id: string }>(),
111
- 'Clear Selection': emptyProps(),
112
- },
113
- });
114
- ```
115
-
116
- ### 4. Reducer (`<domain>.reducer.ts`)
117
-
118
- ```typescript
119
- import { createReducer, on } from '@ngrx/store';
120
- import { <Entity>Actions } from './<domain>.actions';
121
- import { <entity>Adapter, initial<Entity>State } from './<domain>.adapter';
122
-
123
- export const <entity>Reducer = createReducer(
124
- initial<Entity>State,
125
-
126
- // Load All
127
- on(<Entity>Actions.load<Entities>, (state) => ({
128
- ...state,
129
- loading: true,
130
- error: null,
131
- })),
132
- on(<Entity>Actions.load<Entities>Success, (state, { <entities> }) =>
133
- <entity>Adapter.setAll(<entities>, { ...state, loading: false })
134
- ),
135
- on(<Entity>Actions.load<Entities>Failure, (state, { error }) => ({
136
- ...state,
137
- loading: false,
138
- error,
139
- })),
140
-
141
- // Load Single
142
- on(<Entity>Actions.load<Entity>Success, (state, { <entity> }) =>
143
- <entity>Adapter.upsertOne(<entity>, state)
144
- ),
145
-
146
- // Create
147
- on(<Entity>Actions.create<Entity>Success, (state, { <entity> }) =>
148
- <entity>Adapter.addOne(<entity>, state)
149
- ),
150
-
151
- // Update
152
- on(<Entity>Actions.update<Entity>Success, (state, { <entity> }) =>
153
- <entity>Adapter.updateOne({ id: <entity>.id, changes: <entity> }, state)
154
- ),
155
-
156
- // Delete
157
- on(<Entity>Actions.delete<Entity>Success, (state, { id }) =>
158
- <entity>Adapter.removeOne(id, state)
159
- ),
160
-
161
- // Selection
162
- on(<Entity>Actions.select<Entity>, (state, { id }) => ({
163
- ...state,
164
- selectedId: id,
165
- })),
166
- on(<Entity>Actions.clearSelection, (state) => ({
167
- ...state,
168
- selectedId: null,
169
- })),
170
- );
171
- ```
172
-
173
- ### 5. Selectors (`<domain>.selectors.ts`)
174
-
175
- ```typescript
176
- import { createFeatureSelector, createSelector } from '@ngrx/store';
177
- import { <Entity>State } from './<domain>.state';
178
- import { <entity>Adapter } from './<domain>.adapter';
179
-
180
- export const select<Entity>State = createFeatureSelector<<Entity>State>('<entities>');
181
-
182
- const { selectAll, selectEntities, selectIds, selectTotal } =
183
- <entity>Adapter.getSelectors();
184
-
185
- export const selectAll<Entities> = createSelector(select<Entity>State, selectAll);
186
-
187
- export const select<Entity>Entities = createSelector(select<Entity>State, selectEntities);
188
-
189
- export const select<Entity>Ids = createSelector(select<Entity>State, selectIds);
190
-
191
- export const select<Entity>Total = createSelector(select<Entity>State, selectTotal);
192
-
193
- export const select<Entities>Loading = createSelector(
194
- select<Entity>State,
195
- (state) => state.loading
196
- );
197
-
198
- export const select<Entities>Error = createSelector(
199
- select<Entity>State,
200
- (state) => state.error
201
- );
202
-
203
- export const selectSelected<Entity>Id = createSelector(
204
- select<Entity>State,
205
- (state) => state.selectedId
206
- );
207
-
208
- export const selectSelected<Entity> = createSelector(
209
- select<Entity>Entities,
210
- selectSelected<Entity>Id,
211
- (entities, selectedId) => (selectedId ? entities[selectedId] : null)
212
- );
213
- ```
214
-
215
- ### 6. Effects (`<domain>.effects.ts`)
216
-
217
- ```typescript
218
- import { inject } from '@angular/core';
219
- import { Actions, createEffect, ofType } from '@ngrx/effects';
220
- import { catchError, exhaustMap, map, of } from 'rxjs';
221
- import { <Entity>Actions } from './<domain>.actions';
222
- import { <Entity>Service } from '../services/<domain>.service';
223
-
224
- export const load<Entities>$ = createEffect(
225
- (
226
- actions$ = inject(Actions),
227
- <entity>Service = inject(<Entity>Service)
228
- ) =>
229
- actions$.pipe(
230
- ofType(<Entity>Actions.load<Entities>),
231
- exhaustMap(() =>
232
- <entity>Service.getAll().pipe(
233
- map((<entities>) => <Entity>Actions.load<Entities>Success({ <entities> })),
234
- catchError((error) =>
235
- of(<Entity>Actions.load<Entities>Failure({ error: error.message }))
236
- )
237
- )
238
- )
239
- ),
240
- { functional: true }
241
- );
242
-
243
- export const load<Entity>$ = createEffect(
244
- (
245
- actions$ = inject(Actions),
246
- <entity>Service = inject(<Entity>Service)
247
- ) =>
248
- actions$.pipe(
249
- ofType(<Entity>Actions.load<Entity>),
250
- exhaustMap(({ id }) =>
251
- <entity>Service.getById(id).pipe(
252
- map((<entity>) => <Entity>Actions.load<Entity>Success({ <entity> })),
253
- catchError((error) =>
254
- of(<Entity>Actions.load<Entity>Failure({ error: error.message }))
255
- )
256
- )
257
- )
258
- ),
259
- { functional: true }
260
- );
261
-
262
- export const create<Entity>$ = createEffect(
263
- (
264
- actions$ = inject(Actions),
265
- <entity>Service = inject(<Entity>Service)
266
- ) =>
267
- actions$.pipe(
268
- ofType(<Entity>Actions.create<Entity>),
269
- exhaustMap(({ <entity> }) =>
270
- <entity>Service.create(<entity>).pipe(
271
- map((<entity>) => <Entity>Actions.create<Entity>Success({ <entity> })),
272
- catchError((error) =>
273
- of(<Entity>Actions.create<Entity>Failure({ error: error.message }))
274
- )
275
- )
276
- )
277
- ),
278
- { functional: true }
279
- );
280
-
281
- export const update<Entity>$ = createEffect(
282
- (
283
- actions$ = inject(Actions),
284
- <entity>Service = inject(<Entity>Service)
285
- ) =>
286
- actions$.pipe(
287
- ofType(<Entity>Actions.update<Entity>),
288
- exhaustMap(({ update }) =>
289
- <entity>Service.update(update.id as string, update.changes).pipe(
290
- map((<entity>) => <Entity>Actions.update<Entity>Success({ <entity> })),
291
- catchError((error) =>
292
- of(<Entity>Actions.update<Entity>Failure({ error: error.message }))
293
- )
294
- )
295
- )
296
- ),
297
- { functional: true }
298
- );
299
-
300
- export const delete<Entity>$ = createEffect(
301
- (
302
- actions$ = inject(Actions),
303
- <entity>Service = inject(<Entity>Service)
304
- ) =>
305
- actions$.pipe(
306
- ofType(<Entity>Actions.delete<Entity>),
307
- exhaustMap(({ id }) =>
308
- <entity>Service.delete(id).pipe(
309
- map(() => <Entity>Actions.delete<Entity>Success({ id })),
310
- catchError((error) =>
311
- of(<Entity>Actions.delete<Entity>Failure({ error: error.message }))
312
- )
313
- )
314
- )
315
- ),
316
- { functional: true }
317
- );
318
- ```
319
-
320
- ## Execution Steps
321
-
322
- 1. **Parse Arguments**
323
- - Extract domain name (e.g., "users")
324
- - Extract entity name (e.g., "User") or derive from domain
325
-
326
- 2. **Create Files**
327
- - Generate all 6 files with proper naming
328
- - Replace placeholders with actual names
329
-
330
- 3. **Update Public API**
331
- - Export all from `index.ts`
332
-
333
- 4. **Provide Registration**
334
- - Show how to register in `app.config.ts`
335
-
336
- ## Output
337
-
338
- ```typescript
339
- // app.config.ts
340
- import { provideState } from '@ngrx/store';
341
- import { provideEffects } from '@ngrx/effects';
342
- import { <entity>Reducer } from '@app/<domain>/data-access';
343
- import * as <entity>Effects from '@app/<domain>/data-access';
344
-
345
- export const appConfig: ApplicationConfig = {
346
- providers: [
347
- provideStore(),
348
- provideState('<entities>', <entity>Reducer),
349
- provideEffects(<entity>Effects),
350
- ],
351
- };
352
- ```
353
-
354
- ## Placeholders
355
-
356
- | Placeholder | Example (users) |
357
- |-------------|-----------------|
358
- | `<domain>` | users |
359
- | `<entity>` | user |
360
- | `<Entity>` | User |
361
- | `<entities>` | users |
362
- | `<Entities>` | Users |