@barcidev/ngx-autogen 0.1.71 → 0.1.72

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.
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.signalStore = signalStore;
13
13
  const core_1 = require("@angular-devkit/core");
14
+ const ts_morph_1 = require("ts-morph");
14
15
  const schematics_1 = require("@angular-devkit/schematics");
15
16
  const tasks_1 = require("@angular-devkit/schematics/tasks");
16
17
  const dependencies_1 = require("@schematics/angular/utility/dependencies");
@@ -103,33 +104,29 @@ function ensureNgrxSignals(version) {
103
104
  }
104
105
  function updateIndexFile(ctx) {
105
106
  return (tree) => {
106
- const { options, indexPath, nameDash, entityName } = ctx;
107
- const entityHeader = `/* ${entityName.toUpperCase()} */`;
108
- const exportBlock = [
109
- entityHeader,
110
- `export * from './${nameDash}${options.grouped ? "/models" : ""}/${nameDash}.model';`,
111
- `export * from './${nameDash}${options.grouped ? "/services" : ""}/${nameDash}.service';`,
112
- `export * from './${nameDash}/${nameDash}.store';`,
113
- "",
114
- ].join("\n");
107
+ const { options, indexPath, nameDash } = ctx;
115
108
  let content = tree.exists(indexPath)
116
109
  ? tree.read(indexPath).toString()
117
110
  : "";
118
- if (content.includes(entityHeader)) {
119
- // Evitar duplicados línea por línea
120
- const newLines = exportBlock
121
- .split("\n")
122
- .filter((line) => line.trim() !== "" && !content.includes(line));
123
- if (newLines.length > 0)
124
- content += newLines.join("\n") + "\n";
125
- }
126
- else {
127
- content =
128
- content.trim() + (content.length > 0 ? "\n\n" : "") + exportBlock;
111
+ const project = new ts_morph_1.Project({
112
+ manipulationSettings: { quoteKind: ts_morph_1.QuoteKind.Single }
113
+ });
114
+ const sourceFile = project.createSourceFile('index.ts', content);
115
+ const exportsToAdd = [
116
+ `./${nameDash}${options.grouped ? "/models" : ""}/${nameDash}.model`,
117
+ `./${nameDash}${options.grouped ? "/services" : ""}/${nameDash}.service`,
118
+ `./${nameDash}/${nameDash}.store`
119
+ ];
120
+ const currentExports = sourceFile.getExportDeclarations().map(e => e.getModuleSpecifierValue());
121
+ for (const exp of exportsToAdd) {
122
+ if (!currentExports.includes(exp)) {
123
+ sourceFile.addExportDeclaration({ moduleSpecifier: exp });
124
+ }
129
125
  }
126
+ const newContent = sourceFile.getFullText();
130
127
  tree.exists(indexPath)
131
- ? tree.overwrite(indexPath, content)
132
- : tree.create(indexPath, content);
128
+ ? tree.overwrite(indexPath, newContent)
129
+ : tree.create(indexPath, newContent);
133
130
  return tree;
134
131
  };
135
132
  }
package/README.es.md DELETED
@@ -1,352 +0,0 @@
1
- # ngx-autogen
2
-
3
- [![Language: English](https://img.shields.io/badge/lang-en-blue.svg)](README.md)
4
- [![Language: Spanish](https://img.shields.io/badge/lang-es-yellow.svg)](README.es.md)
5
-
6
- **ngx-autogen** es un conjunto de schematics diseñados para optimizar y estandarizar el flujo de trabajo en proyectos Angular. Esta librería proporciona herramientas de generación de código que siguen las mejores prácticas, permitiendo a los desarrolladores ahorrar tiempo en tareas repetitivas y configuración de arquitectura.
7
-
8
- ## 🚀 Características
9
-
10
- El proyecto se lanza inicialmente con un enfoque en la gestión de estado, pero está diseñado para crecer:
11
-
12
- - **Store Schematic**: Nuestro primer schematic disponible. Permite generar automáticamente toda la estructura necesaria para un store basado en signals (NGRX-Signals), facilitando la integración rápida y escalable de la gestión de estado en tus aplicaciones.
13
-
14
- ## 📅 Próximamente
15
-
16
- **ngx-autogen** es un proyecto en evolución continua. Se irán agregando progresivamente nuevas herramientas y schematics para cubrir más aspectos del desarrollo en Angular, como:
17
-
18
- - Generación de servicios y utilidades.
19
- - Scaffolding para componentes avanzados.
20
-
21
- ## 📦 Instalación
22
-
23
- Puedes instalar el paquete en tu proyecto Angular mediante angular cli para que se configure automáticamente el proyecto con las dependencias necesarias:
24
-
25
- ```bash
26
- ng add ngx-autogen
27
- ```
28
-
29
- ## 🛠️ Uso
30
-
31
- ### Generar un Store
32
-
33
- #### Propiedades
34
-
35
- - `name`(obligatorio): nombre del store.
36
- - `pk`(opcional): nombre de la primary key, si no se especifica se usara la especificada en el proceso de instalacion del schematic, de lo contrario se usara `id`.
37
- - `path`(opcional): ruta del store, si no se especifica se usara la especificada en el proceso de instalacion del schematic, de lo contrario se usara `src/app/core`. La carpeta `state` se agregará automáticamente a la ruta.
38
- - `grouped` (opcional): si es verdadero, los archivos se agruparán en subcarpetas `models`, `services` y `store`.
39
-
40
- #### Ejemplo
41
-
42
- ```bash
43
- ng g app-store --name="user" --pk="cod"
44
- ```
45
-
46
- Esto creará los archivos `user.model.ts`, `user.service.ts`, `user.store.ts` dentro de la carpeta `src/app/core/state/user`, y los archivos `entity.model.ts`, `with-entity-pagination.ts`, y `with-entity-status.ts` si no existen dentro de la carpeta `src/app/shared/state`.
47
-
48
- ```bash
49
- src/
50
- └── app/
51
- └── shared/
52
- └── state/
53
- ├── entity.model.ts
54
- ├── with-entity-pagination.ts
55
- └── with-entity-status.ts
56
- └── state/
57
- └── index.ts
58
- └── user/
59
- ├── user.service.ts
60
- ├── user.model.ts
61
- └── user.store.ts
62
- ```
63
-
64
- El archivo `index.ts` exportará todo lo necesario para que el store pueda ser importado y utilizado en cualquier parte de la aplicación.
65
-
66
- ```typescript
67
- /* USER */
68
- export * from './user/user.model';
69
- export * from './user/user.service';
70
- export * from './user/user.store';
71
- ```
72
-
73
- La carpeta `src/app/shared/state` contiene los archivos compartidos para el manejo del estado.
74
-
75
- `entity.model.ts`:
76
-
77
- ```typescript
78
- import { HttpErrorResponse } from '@angular/common/http';
79
- import { FormControl } from '@angular/forms';
80
-
81
- export type FormGroupType<T> = {
82
- [K in keyof T]: FormControl<T[K]>;
83
- };
84
-
85
- export interface RequestConfig<T, U = unknown> {
86
- onError?: (error?: HttpErrorResponse) => void;
87
- onSuccess?: (response?: U) => void;
88
- payload: T;
89
- }
90
- ```
91
-
92
- El archivo `user.model.ts` contiene la interface del modelo de datos.
93
-
94
- ```typescript
95
- import { FormGroupType } from 'src/app/shared/state/entity.model';
96
-
97
- export interface AddUser {
98
- }
99
-
100
- export type AddUserForm = FormGroupType<AddUser>;
101
-
102
- export interface UserDto {
103
- cod: number;
104
- }
105
-
106
- export type UpdateUser = Partial<UserDto> & Pick<UserDto, 'cod'>;
107
-
108
- export interface UserRequest{}
109
- ```
110
-
111
- El archivo `user.service.ts` contiene el servicio que se encarga de la lógica de negocio.
112
-
113
- ```typescript
114
- import { Injectable } from '@angular/core';
115
- import { Observable, of } from 'rxjs';
116
- import {
117
- AddUser,
118
- UserDto,
119
- UpdateUser
120
- } from './user.model';
121
-
122
- @Injectable({
123
- providedIn: 'root'
124
- })
125
- export class UserService {
126
-
127
- addUser$(entity: AddUser): Observable<number> {
128
- return of(0);
129
- }
130
-
131
- removeUser$(cod: number): Observable<boolean> {
132
- return of(true);
133
- }
134
-
135
- getUsers$(): Observable<UserDto[]> {
136
- return of([]);
137
- }
138
-
139
- updateUser$(entity: UpdateUser): Observable<boolean> {
140
- return of(true);
141
- }
142
- }
143
- ```
144
-
145
- El archivo `user.store.ts` contiene el store que se encarga de la gestión de estado.
146
-
147
- ```typescript
148
- import { computed, inject } from '@angular/core';
149
- import { patchState, signalStore, type, withComputed, withHooks, withMethods, withState } from '@ngrx/signals';
150
- import {
151
- addEntity,
152
- entityConfig,
153
- removeEntity,
154
- setAllEntities,
155
- updateEntity,
156
- withEntities
157
- } from '@ngrx/signals/entities';
158
- import { rxMethod } from '@ngrx/signals/rxjs-interop';
159
- import { catchError, of, pipe, switchMap, tap } from 'rxjs';
160
-
161
- import { RequestConfig } from 'src/app/shared/state/entity.model';
162
- import { withPagination } from 'src/app/shared/state/with-entity-pagination';
163
- import { withEntityStatus } from 'src/app/shared/state/with-entity-status';
164
- import {
165
- AddUser,
166
- UserDto,
167
- UpdateUser
168
- } from './user.model';
169
- import { UserService } from './user.service';
170
-
171
- const config = entityConfig({
172
- entity: type<UserDto>(),
173
- selectId: (entity) => entity.cod,
174
- });
175
-
176
- export const UserStore = signalStore(
177
- withEntities(config),
178
- withEntityStatus(),
179
- withPagination(),
180
- withComputed(({ entities, entityMap, status: { idSelected } }) => ({
181
- users: computed(() => entities()),
182
- userSeleccionado: computed(() => {
183
- const cod = idSelected();
184
- return cod ? entityMap()[cod] : null;
185
- })
186
- })),
187
- withMethods((store, userService = inject(UserService)) => ({
188
- addUser: rxMethod<RequestConfig<AddUser, UserDto>>(
189
- pipe(
190
- tap(() => {
191
- patchState(store, (state) => ({ status: { ...state.status, addLoading: true } }));
192
- }),
193
- switchMap(({ onError, onSuccess, payload: { request } }) => {
194
- return userService.addUser$(request).pipe(
195
- tap((cod) => {
196
- const newUser: UserDto = { ...request, cod};
197
- patchState(store, addEntity(newUser, config), (state) => ({
198
- ...state,
199
- status: { ...state.status, addError: null, addLoading: false }
200
- }));
201
- if (onSuccess) {
202
- onSuccess(newUser);
203
- }
204
- }),
205
- catchError(() => {
206
- const error = new Error('');
207
- patchState(store, (state) => ({
208
- status: { ...state.status, addError: error, addLoading: false }
209
- }));
210
- if (onError) {
211
- onError();
212
- }
213
- return EMPTY;
214
- })
215
- );
216
- })
217
- )
218
- ),
219
- loadUsers: rxMethod<void>(
220
- pipe(
221
- tap(() => {
222
- patchState(store, (state) => ({ status: { ...state.status, loading: true } }));
223
- }),
224
- switchMap(() => {
225
- return userService.getUsers$().pipe(
226
- tap((response) => {
227
- patchState(store, setAllEntities(response, config), (state) => ({
228
- status: { ...state.status, error: null, loaded: true, loading: false }
229
- }));
230
- }),
231
- catchError(() => {
232
- patchState(store, (state) => ({
233
- status: { ...state.status, error: new Error('Error al cargar users'), loading: false }
234
- }));
235
- return EMPTY;
236
- })
237
- );
238
- })
239
- )
240
- ),
241
- removeUser: rxMethod<RequestConfig<number, boolean>>(
242
- pipe(
243
- tap(({ payload }) => {
244
- patchState(store, (state) => ({
245
- status: {
246
- ...state.status,
247
- _removeLoading: true,
248
- idsRemoving: [...(state.status.idsRemoving || []), payload]
249
- }
250
- }));
251
- }),
252
- switchMap(({ onError, onSuccess, payload }) => {
253
- return userService.removeUser$(payload).pipe(
254
- tap((response) => {
255
- if (response) {
256
- const idsRemoving = store.status.idsRemoving() || [];
257
- patchState(store, removeEntity(payload), (state) => ({
258
- status: {
259
- ...state.status,
260
- _removeLoading: false,
261
- error: null,
262
- idsRemoving: idsRemoving.filter((idRemoving) => idRemoving !== payload)
263
- }
264
- }));
265
- if (onSuccess) {
266
- onSuccess(response);
267
- }
268
- } else {
269
- throw new Error();
270
- }
271
- }),
272
- catchError(() => {
273
- const idsRemoving = store.status.idsRemoving() || [];
274
- patchState(store, (state) => ({
275
- status: {
276
- ...state.status,
277
- _removeLoading: false,
278
- error: new Error(),
279
- idsRemoving: idsRemoving.filter((idRemoving) => idRemoving !== payload)
280
- }
281
- }));
282
- if (onError) {
283
- onError();
284
- }
285
- return EMPTY;
286
- })
287
- );
288
- })
289
- )
290
- ),
291
- updateUser: rxMethod<RequestConfig<UpdateUser, boolean>>(
292
- pipe(
293
- tap(({ payload }) => {
294
- patchState(store, (state) => ({
295
- status: {
296
- ...state.status,
297
- _updateLoading: true,
298
- idsUpdating: [...(state.status.idsUpdating || []), payload.cod]
299
- }
300
- }));
301
- }),
302
- switchMap(({ onError, onSuccess, payload }) => {
303
- return userService.updateUser$(entity).pipe(
304
- tap((response) => {
305
- if (response) {
306
- const idsUpdating = store.status.idsUpdating() || [];
307
- patchState(store, updateEntity({ changes: payload, id: payload.cod }, config), (state) => ({
308
- status: {
309
- ...state.status,
310
- _updateLoading: false,
311
- error: null,
312
- idsUpdating: idsUpdating.filter((idUpdating) => idUpdating !== payload.cod)
313
- }
314
- }));
315
- if (onSuccess) {
316
- onSuccess(response);
317
- }
318
- } else {
319
- throw new Error('');
320
- }
321
- }),
322
- catchError(() => {
323
- const idsUpdating = store.status.idsUpdating() || [];
324
- patchState(store, (state) => ({
325
- status: {
326
- ...state.status,
327
- _updateLoading: false,
328
- error: new Error('Error al actualizar user'),
329
- idsUpdating: idsUpdating.filter((idUpdating) => idUpdating !== payload.cod)
330
- }
331
- }));
332
- if (onError) {
333
- onError();
334
- }
335
- return EMPTY;
336
- })
337
- );
338
- })
339
- )
340
- ),
341
- })),
342
- withHooks({
343
- onInit: (store) => {
344
- store.loadUsers();
345
- },
346
- })
347
- );
348
- ```
349
-
350
- ## 📄 Licencia
351
-
352
- Este proyecto está bajo la licencia [MIT](LICENSE).
@@ -1,20 +0,0 @@
1
- <div
2
- <% if (i18n === 'Yes') { %>
3
- *typedTransloco="let t; prefix:'<%= camelize(name) %>'"
4
- <% } %>
5
- >
6
- <h1>
7
- <% if (i18n === 'Yes') { %>
8
- {{ t('title') }}
9
- <% }
10
- else { %>
11
- <%= classify(name) %> Works!
12
- <% } %>
13
- </h1>
14
-
15
- <% if (store === 'Yes') { %>
16
-
17
- <pre>{{ data$() | json }}</pre>
18
-
19
- <% } %>
20
- </div>
@@ -1,25 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
- import { <%= classify(name) %>Component } from './<%= dasherize(name) %>.component';
3
- <% if (store === 'Yes') { %>import { <%= classify(storeName) %>Store } from './state';<% } %>
4
-
5
- describe('<%= classify(name) %>Component', () => {
6
- let component: <%= classify(name) %>Component;
7
- let fixture: ComponentFixture<<%= classify(name) %>Component>;
8
-
9
- beforeEach(async () => {
10
- await TestBed.configureTestingModule({
11
- imports: [<%= classify(name) %>Component],
12
- providers: [
13
- <% if (store === 'Yes') { %><%= classify(storeName) %>Store,<% } %>
14
- ]
15
- }).compileComponents();
16
-
17
- fixture = TestBed.createComponent(<%= classify(name) %>Component);
18
- component = fixture.componentInstance;
19
- fixture.detectChanges();
20
- });
21
-
22
- it('should create', () => {
23
- expect(component).toBeTruthy();
24
- });
25
- });
@@ -1,17 +0,0 @@
1
- import { Component, inject } from '@angular/core';
2
- <% if (store === 'Yes') { %>
3
- import { <%= classify(storeName) %>Store<% if (!isProvideInRoot) { %>, provide<%= classify(storeName) %>Store<% } %> } from './state';
4
- import { JsonPipe } from '@angular/common';
5
- <% } %>
6
-
7
- @Component({
8
- imports: [<% if (store === 'Yes') { %>JsonPipe<% } %>],
9
- providers: [<% if (store === 'Yes' && !isProvideInRoot) { %>...provide<%= classify(storeName) %>Store()<% } %>],
10
- selector: 'app-<%= dasherize(name) %>',
11
- styleUrls: ['./<%= dasherize(name) %>.component.css'],
12
- templateUrl: './<%= dasherize(name) %>.component.html',
13
- })
14
- export class <%= classify(name) %>Component {
15
- <% if (store === 'Yes') { %> private _<%= camelize(storeName) %>Store = inject(<%= classify(storeName) %>Store);
16
- data$ = this._<%= camelize(storeName) %>Store.entities();<% } %>
17
- }