{"id":35319272,"url":"https://github.com/barcidev/ngx-autogen","last_synced_at":"2025-12-31T11:01:32.233Z","repository":{"id":330153831,"uuid":"1121776968","full_name":"barcidev/ngx-autogen","owner":"barcidev","description":null,"archived":false,"fork":false,"pushed_at":"2025-12-23T19:11:51.000Z","size":30,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-25T04:33:43.811Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/barcidev.png","metadata":{"files":{"readme":"README.es.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-23T14:36:01.000Z","updated_at":"2025-12-23T19:11:55.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/barcidev/ngx-autogen","commit_stats":null,"previous_names":["jpalacio09/ngx-autogen"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/barcidev/ngx-autogen","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barcidev%2Fngx-autogen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barcidev%2Fngx-autogen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barcidev%2Fngx-autogen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barcidev%2Fngx-autogen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/barcidev","download_url":"https://codeload.github.com/barcidev/ngx-autogen/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barcidev%2Fngx-autogen/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28142763,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-31T02:00:06.200Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-30T21:00:34.251Z","updated_at":"2025-12-31T11:01:32.228Z","avatar_url":"https://github.com/barcidev.png","language":"TypeScript","funding_links":[],"categories":["Development Utilities"],"sub_categories":["Generators and Scaffolding"],"readme":"# ngx-autogen\n\n[![Language: English](https://img.shields.io/badge/lang-en-blue.svg)](README.md)\n[![Language: Spanish](https://img.shields.io/badge/lang-es-yellow.svg)](README.es.md)\n\n**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.\n\n## 🚀 Características\n\nEl proyecto se lanza inicialmente con un enfoque en la gestión de estado, pero está diseñado para crecer:\n\n- **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.\n\n## 📅 Próximamente\n\n**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:\n\n- Generación de servicios y utilidades.\n- Scaffolding para componentes avanzados.\n\n## 📦 Instalación\n\nPuedes instalar el paquete en tu proyecto Angular mediante angular cli para que se configure automáticamente el proyecto con las dependencias necesarias:\n\n```bash\nng add ngx-autogen\n```\n\n## 🛠️ Uso\n\n### Generar un Store\n\n#### Propiedades\n\n- `name`(obligatorio): nombre del store.\n- `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`.\n- `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`.\n\n#### Ejemplo\n\n```bash\nng g app-store --name=\"user\" --pk=\"cod\"\n```\n\nEsto creará los archivos `user.model.ts`, `user.service.ts`, `user.store.ts` dentro de la carpeta `src/app/core/user`, el archivo `entity.model.ts` si no existe, dentro de la carpeta `src/app/core/common/entity` y el archivo `index.ts` dentro de la carpeta `src/app/core`.\n\n```bash\ncommon/\n└── entity/\n    └── entity.model.ts\nuser/\n├── user.service.ts\n├── user.model.ts\n└── user.store.ts\nindex.ts\n```\n\nEl archivo `index.ts` exportará todo lo necesario para que el store pueda ser importado y utilizado en cualquier parte de la aplicación.\n\n```bash\n/* USER */\nexport * from './user/user.model';\nexport * from './user/user.service';\nexport * from './user/user.store';\n```\n\nEl archivo `entity.model.ts` contiene las interfaces y tipos necesarios para el manejo de estados y formularios.\n\n```bash\nimport { FormControl } from '@angular/forms';\n\nexport interface EntityStatus {\n  addError?: Error | null;\n  addLoading?: boolean;\n  removeError?: Error | null;\n  removeLoading?: boolean;\n  error: Error | null;\n  idsRemoving?: (number | string)[];\n  idSelected?: null | number | string;\n  idsUpdating?: (number | string)[];\n  loaded: boolean;\n  loading: boolean;\n  selectedError?: Error | null;\n  selectedLoading?: boolean;\n  updateError?: Error | null;\n  updateLoading?: boolean;\n}\n\nexport type FormGroupType\u003cT\u003e = {\n  [K in keyof T]: FormControl\u003cT[K]\u003e;\n};\n```\n\nEl archivo `user.model.ts` contiene la interface del modelo de datos.\n\n```bash\nimport { FormGroupType } from '../common/form/form.model';\n\nexport interface AddUser {\n}\n\nexport type AddUserForm = FormGroupType\u003cAddUser\u003e;\n\nexport interface UserDto {\n  cod: number;\n}\n\nexport type UpdateUser = Partial\u003cUserDto\u003e \u0026 Pick\u003cUserDto, 'cod'\u003e;\n\nexport interface UserRequest{}\n```\n\nEl archivo `user.service.ts` contiene el servicio que se encarga de la lógica de negocio.\n\n```bash\nimport { Injectable } from '@angular/core';\nimport { Observable, of } from 'rxjs';\nimport {\n  AddUser,\n  UserDto,\n  UpdateUser\n} from './user.model';\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class UserService {\n\n  addUser$(entity: AddUser): Observable\u003cnumber\u003e {\n    return of(0);\n  }\n\n  removeUser$(cod: number): Observable\u003cboolean\u003e {\n    return of(true);\n  }\n\n  getUsers$(): Observable\u003cUserDto[]\u003e {\n    return of([]);\n  }\n\n  updateUser$(entity: UpdateUser): Observable\u003cboolean\u003e {\n    return of(true);\n  }\n}\n```\n\nEl archivo `user.store.ts` contiene el store que se encarga de la gestión de estado.\n\n```bash\nimport { computed, inject } from '@angular/core';\nimport { patchState, signalStore, type, withComputed, withHooks, withMethods, withState } from '@ngrx/signals';\nimport {\n  addEntity,\n  entityConfig,\n  removeEntity,\n  setAllEntities,\n  updateEntity,\n  withEntities\n} from '@ngrx/signals/entities';\nimport { rxMethod } from '@ngrx/signals/rxjs-interop';\nimport { catchError, of, pipe, switchMap, tap } from 'rxjs';\n\nimport { EntityStatus } from '../common/entity/entity.model';\nimport {\n  UserDto,\n  AddUser,\n  UpdateUser\n} from './user.model';\nimport { UserService } from './user.service';\n\nconst initialStatus: EntityStatus = {\n  error: null,\n  loaded: false,\n  loading: false,\n};\n\nconst config = entityConfig({\n  entity: type\u003cUserDto\u003e(),\n  selectId: (entity) =\u003e entity.cod,\n});\n\nexport const UserStore = signalStore(\n  withEntities(config),\n  withState({\n    _status: initialStatus,\n  }),\n  withComputed(({ entityMap, _status }) =\u003e ({\n    users: computed(() =\u003e Object.values(entityMap())),\n    userSeleccionado: computed(() =\u003e {\n      const cod = _status().idSelected;\n      return cod ? entityMap()[cod] : null;\n    }),\n    error: computed(() =\u003e _status().error),\n    loaded: computed(() =\u003e _status().loaded),\n    loading: computed(() =\u003e _status().loading),\n    loadingRemove: computed(\n      () =\u003e (cod?: number) =\u003e\n        (cod ? _status().idsRemoving?.includes(cod) : _status().removeLoading) || false\n    ),\n    loadingUpdate: computed(\n      () =\u003e (cod?: number) =\u003e\n        (cod ? _status().idsUpdating?.includes(cod) : _status().updateLoading) || false\n    ),\n  })),\n  withMethods((store, userService = inject(UserService)) =\u003e ({\n    addUser: rxMethod\u003cAddUser\u003e(\n      pipe(\n        tap(() =\u003e {\n          patchState(store, { _status: { ...store._status(), addLoading: true } });\n        }),\n        switchMap((entity) =\u003e {\n          return userService.addUser$(entity).pipe(\n            tap((cod) =\u003e {\n              patchState(store, addEntity({ ...entity, cod }, config), {\n                _status: {\n                  ...store._status(),\n                  addLoading: false,\n                  error: null,\n                },\n              });\n            }),\n            catchError(() =\u003e {\n              patchState(store, {\n                _status: {\n                  ...store._status(),\n                  addLoading: false,\n                  error: new Error('Error al agregar user'),\n                },\n              });\n              return of(entity);\n            })\n          );\n        })\n      )\n    ),\n    loadUsers: rxMethod\u003cvoid\u003e(\n      pipe(\n        tap(() =\u003e {\n          patchState(store, { _status: { ...store._status(), loading: true } });\n        }),\n        switchMap(() =\u003e {\n          return userService.getUsers$().pipe(\n            tap((response) =\u003e {\n              patchState(store, setAllEntities(response, config), {\n                _status: {\n                  ...store._status(),\n                  error: null,\n                  loaded: true,\n                  loading: false,\n                },\n              });\n            }),\n            catchError(() =\u003e {\n              patchState(store, {\n                _status: {\n                  ...store._status(),\n                  error: new Error('Error al cargar users'),\n                  loading: false,\n                },\n              });\n              return of([]);\n            })\n          );\n        })\n      )\n    ),\n    removeUser: rxMethod\u003cnumber\u003e(\n      pipe(\n        tap((cod) =\u003e {\n          patchState(store, {\n            _status: {\n              ...store._status(),\n              removeLoading: true,\n              idsRemoving: [...(store._status().idsRemoving || []), cod],\n            },\n          });\n        }),\n        switchMap((cod) =\u003e {\n          return userService.removeUser$(cod).pipe(\n            tap((success) =\u003e {\n              if (success) {\n                const idsRemoving = store._status().idsRemoving || [];\n                patchState(store, removeEntity(cod), {\n                  _status: {\n                    ...store._status(),\n                    removeLoading: false,\n                    error: null,\n                    idsRemoving: idsRemoving.filter((idRemoving) =\u003e idRemoving !== cod),\n                  },\n                });\n              } else {\n                throw new Error('Error al eliminar user');\n              }\n            }),\n            catchError(() =\u003e {\n              const idsRemoving = store._status().idsRemoving || [];\n              patchState(store, {\n                _status: {\n                  ...store._status(),\n                  removeLoading: false,\n                  error: new Error('Error al eliminar user'),\n                  idsRemoving: idsRemoving.filter((idRemoving) =\u003e idRemoving !== cod),\n                },\n              });\n              return of(false);\n            })\n          );\n        })\n      )\n    ),\n    updateUser: rxMethod\u003cUpdateUser\u003e(\n      pipe(\n        tap((entity) =\u003e {\n          patchState(store, {\n            _status: {\n              ...store._status(),\n              idsUpdating: [...(store._status().idsUpdating || []), entity.cod],\n              updateLoading: true,\n            },\n          });\n        }),\n        switchMap((entity) =\u003e {\n          return userService.updateUser$(entity).pipe(\n            tap((success) =\u003e {\n              if (success) {\n                const idsUpdating = store._status().idsUpdating || [];\n                patchState(store, updateEntity({ changes: entity, id: entity.cod }, config), {\n                  _status: {\n                    ...store._status(),\n                    error: null,\n                    idsUpdating: idsUpdating.filter((idUpdating) =\u003e idUpdating !== entity.cod),\n                    updateLoading: false,\n                  },\n                });\n              } else {\n                throw new Error('Error al actualizar user');\n              }\n            }),\n            catchError(() =\u003e {\n              const idsUpdating = store._status().idsUpdating || [];\n              patchState(store, {\n                _status: {\n                  ...store._status(),\n                  error: new Error('Error al actualizar user'),\n                  idsUpdating: idsUpdating.filter((idUpdating) =\u003e idUpdating !== entity.cod),\n                  updateLoading: false,\n                },\n              });\n              return of(false);\n            })\n          );\n        })\n      )\n    ),\n  })),\n  withHooks({\n    onInit: (store) =\u003e {\n      store.loadUsers();\n    },\n  })\n);\n```\n\n## 📄 Licencia\n\nEste proyecto está bajo la licencia [MIT](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbarcidev%2Fngx-autogen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbarcidev%2Fngx-autogen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbarcidev%2Fngx-autogen/lists"}