@zola_do/crud 0.1.19 → 0.1.21
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/README.md
CHANGED
|
@@ -1,185 +1,185 @@
|
|
|
1
|
-
# @zola_do/crud
|
|
2
|
-
|
|
3
|
-
Generic CRUD controllers, services, and repositories for NestJS entities.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
# Install individually
|
|
9
|
-
npm install @zola_do/crud
|
|
10
|
-
|
|
11
|
-
# Or via meta package
|
|
12
|
-
npm install @zola_do/nestjs-shared
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Dependencies
|
|
16
|
-
|
|
17
|
-
This package requires:
|
|
18
|
-
|
|
19
|
-
- `@zola_do/core` — Entities, `DataResponseFormat`, `EntityCrudOptions`
|
|
20
|
-
- `@zola_do/collection-query` — `decodeCollectionQuery`, `QueryConstructor`, `FilterOperators`
|
|
21
|
-
- `@zola_do/authorization` — `JwtGuard`, `PermissionsGuard`
|
|
22
|
-
|
|
23
|
-
## Usage
|
|
24
|
-
|
|
25
|
-
### Entity Setup
|
|
26
|
-
|
|
27
|
-
Extend `CommonEntity` (or `Audit` for tenant-aware entities) and use with the CRUD factories:
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
import { CommonEntity } from '@zola_do/core';
|
|
31
|
-
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
|
|
32
|
-
|
|
33
|
-
@Entity('products')
|
|
34
|
-
export class Product extends CommonEntity {
|
|
35
|
-
@PrimaryGeneratedColumn('uuid')
|
|
36
|
-
id: string;
|
|
37
|
-
|
|
38
|
-
@Column()
|
|
39
|
-
name: string;
|
|
40
|
-
|
|
41
|
-
@Column({ type: 'decimal', precision: 10, scale: 2 })
|
|
42
|
-
price: number;
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Controller and Service
|
|
47
|
-
|
|
48
|
-
Create a CRUD controller and service for your entity:
|
|
49
|
-
|
|
50
|
-
```typescript
|
|
51
|
-
import { Controller } from '@nestjs/common';
|
|
52
|
-
import {
|
|
53
|
-
EntityCrudController,
|
|
54
|
-
EntityCrudService,
|
|
55
|
-
} from '@zola_do/crud';
|
|
56
|
-
import { Product } from './product.entity';
|
|
57
|
-
|
|
58
|
-
@Controller('products')
|
|
59
|
-
export class ProductsController extends EntityCrudController<Product>({
|
|
60
|
-
createPermission: 'product:create',
|
|
61
|
-
viewPermission: 'product:view',
|
|
62
|
-
updatePermission: 'product:update',
|
|
63
|
-
deletePermission: 'product:delete',
|
|
64
|
-
}) {
|
|
65
|
-
constructor(service: EntityCrudService<Product>) {
|
|
66
|
-
super(service);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
import { Module } from '@nestjs/common';
|
|
73
|
-
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
74
|
-
import { EntityCrudService } from '@zola_do/crud';
|
|
75
|
-
import { Product } from './product.entity';
|
|
76
|
-
import { ProductsController } from './products.controller';
|
|
77
|
-
|
|
78
|
-
@Module({
|
|
79
|
-
imports: [TypeOrmModule.forFeature([Product])],
|
|
80
|
-
controllers: [ProductsController],
|
|
81
|
-
providers: [EntityCrudService],
|
|
82
|
-
})
|
|
83
|
-
export class ProductsModule {}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Available Endpoints
|
|
87
|
-
|
|
88
|
-
- `POST /` — Create
|
|
89
|
-
- `GET /` — Find all (supports `?q=` collection query)
|
|
90
|
-
- `GET /:id` — Find one
|
|
91
|
-
- `PUT /:id` — Update
|
|
92
|
-
- `DELETE /:id` — Soft delete
|
|
93
|
-
|
|
94
|
-
### EntityCrudOptions
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
import { EntityCrudOptions } from '@zola_do/core';
|
|
98
|
-
|
|
99
|
-
const options: EntityCrudOptions = {
|
|
100
|
-
createDto: CreateProductDto,
|
|
101
|
-
updateDto: UpdateProductDto,
|
|
102
|
-
createPermission: 'product:create',
|
|
103
|
-
viewPermission: 'product:view',
|
|
104
|
-
updatePermission: 'product:update',
|
|
105
|
-
deletePermission: 'product:delete',
|
|
106
|
-
restorePermission: 'product:restore',
|
|
107
|
-
viewArchivedPermission: 'product:view_archived',
|
|
108
|
-
mapCreateContext: ({ req, itemData }) => ({
|
|
109
|
-
organizationId: req?.session?.org?.id,
|
|
110
|
-
organizationName: req?.session?.org?.name,
|
|
111
|
-
createdBy: req?.session?.user?.id,
|
|
112
|
-
}),
|
|
113
|
-
};
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### Request Context Mapping
|
|
117
|
-
|
|
118
|
-
`@zola_do/crud` supports three create-time mapping levels:
|
|
119
|
-
|
|
120
|
-
1. `mapCreateContext` in `EntityCrudOptions` / `ExtraCrudOptions` (highest priority)
|
|
121
|
-
2. module-level resolver provider (`CRUD_REQUEST_CONTEXT_RESOLVER`)
|
|
122
|
-
3. legacy fallback to `req.user.organization` (for backward compatibility)
|
|
123
|
-
|
|
124
|
-
```typescript
|
|
125
|
-
import { Module } from '@nestjs/common';
|
|
126
|
-
import {
|
|
127
|
-
CRUD_REQUEST_CONTEXT_RESOLVER,
|
|
128
|
-
CrudRequestContextResolver,
|
|
129
|
-
} from '@zola_do/crud';
|
|
130
|
-
|
|
131
|
-
const crudRequestContextResolver: CrudRequestContextResolver = {
|
|
132
|
-
resolveCreateContext: ({ req }) => ({
|
|
133
|
-
organizationId: req?.auth?.orgId,
|
|
134
|
-
organizationName: req?.auth?.orgName,
|
|
135
|
-
createdBy: req?.auth?.userId,
|
|
136
|
-
}),
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
@Module({
|
|
140
|
-
providers: [
|
|
141
|
-
{
|
|
142
|
-
provide: CRUD_REQUEST_CONTEXT_RESOLVER,
|
|
143
|
-
useValue: crudRequestContextResolver,
|
|
144
|
-
},
|
|
145
|
-
],
|
|
146
|
-
})
|
|
147
|
-
export class ProductsModule {}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### Relation CRUD
|
|
151
|
-
|
|
152
|
-
For many-to-many or relation management:
|
|
153
|
-
|
|
154
|
-
```typescript
|
|
155
|
-
import { RelationCrudController, RelationCrudService } from '@zola_do/crud';
|
|
156
|
-
|
|
157
|
-
@Controller('products/:productId/categories')
|
|
158
|
-
export class ProductCategoriesController extends RelationCrudController(
|
|
159
|
-
{
|
|
160
|
-
firstEntityIdName: 'productId',
|
|
161
|
-
firstInclude: 'product',
|
|
162
|
-
secondEntityIdName: 'categoryId',
|
|
163
|
-
secondInclude: 'category',
|
|
164
|
-
viewPermission: 'product:view',
|
|
165
|
-
},
|
|
166
|
-
ProductCategory,
|
|
167
|
-
) {
|
|
168
|
-
constructor(service: RelationCrudService) {
|
|
169
|
-
super(service);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
## Exports
|
|
175
|
-
|
|
176
|
-
- **Controllers:** `EntityCrudController`, `RelationCrudController`, `ExtraCrudController`
|
|
177
|
-
- **Services:** `EntityCrudService`, `RelationCrudService`, `ExtraCrudService`
|
|
178
|
-
- **Repositories:** `EntityCrudRepository`, `RelationCrudRepository`, `ExtraCrudRepository`
|
|
179
|
-
- **Context Mapping:** `CRUD_REQUEST_CONTEXT_RESOLVER`, `CrudRequestContextResolver`
|
|
180
|
-
|
|
181
|
-
## Related Packages
|
|
182
|
-
|
|
183
|
-
- [@zola_do/core](../core) — Entity base classes, `EntityCrudOptions`
|
|
184
|
-
- [@zola_do/collection-query](../collection-query) — Query decoding for list endpoints
|
|
185
|
-
- [@zola_do/authorization](../authorization) — Guards for protected CRUD
|
|
1
|
+
# @zola_do/crud
|
|
2
|
+
|
|
3
|
+
Generic CRUD controllers, services, and repositories for NestJS entities.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install individually
|
|
9
|
+
npm install @zola_do/crud
|
|
10
|
+
|
|
11
|
+
# Or via meta package
|
|
12
|
+
npm install @zola_do/nestjs-shared
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Dependencies
|
|
16
|
+
|
|
17
|
+
This package requires:
|
|
18
|
+
|
|
19
|
+
- `@zola_do/core` — Entities, `DataResponseFormat`, `EntityCrudOptions`
|
|
20
|
+
- `@zola_do/collection-query` — `decodeCollectionQuery`, `QueryConstructor`, `FilterOperators`
|
|
21
|
+
- `@zola_do/authorization` — `JwtGuard`, `PermissionsGuard`
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
### Entity Setup
|
|
26
|
+
|
|
27
|
+
Extend `CommonEntity` (or `Audit` for tenant-aware entities) and use with the CRUD factories:
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { CommonEntity } from '@zola_do/core';
|
|
31
|
+
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
|
|
32
|
+
|
|
33
|
+
@Entity('products')
|
|
34
|
+
export class Product extends CommonEntity {
|
|
35
|
+
@PrimaryGeneratedColumn('uuid')
|
|
36
|
+
id: string;
|
|
37
|
+
|
|
38
|
+
@Column()
|
|
39
|
+
name: string;
|
|
40
|
+
|
|
41
|
+
@Column({ type: 'decimal', precision: 10, scale: 2 })
|
|
42
|
+
price: number;
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Controller and Service
|
|
47
|
+
|
|
48
|
+
Create a CRUD controller and service for your entity:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { Controller } from '@nestjs/common';
|
|
52
|
+
import {
|
|
53
|
+
EntityCrudController,
|
|
54
|
+
EntityCrudService,
|
|
55
|
+
} from '@zola_do/crud';
|
|
56
|
+
import { Product } from './product.entity';
|
|
57
|
+
|
|
58
|
+
@Controller('products')
|
|
59
|
+
export class ProductsController extends EntityCrudController<Product>({
|
|
60
|
+
createPermission: 'product:create',
|
|
61
|
+
viewPermission: 'product:view',
|
|
62
|
+
updatePermission: 'product:update',
|
|
63
|
+
deletePermission: 'product:delete',
|
|
64
|
+
}) {
|
|
65
|
+
constructor(service: EntityCrudService<Product>) {
|
|
66
|
+
super(service);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { Module } from '@nestjs/common';
|
|
73
|
+
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
74
|
+
import { EntityCrudService } from '@zola_do/crud';
|
|
75
|
+
import { Product } from './product.entity';
|
|
76
|
+
import { ProductsController } from './products.controller';
|
|
77
|
+
|
|
78
|
+
@Module({
|
|
79
|
+
imports: [TypeOrmModule.forFeature([Product])],
|
|
80
|
+
controllers: [ProductsController],
|
|
81
|
+
providers: [EntityCrudService],
|
|
82
|
+
})
|
|
83
|
+
export class ProductsModule {}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Available Endpoints
|
|
87
|
+
|
|
88
|
+
- `POST /` — Create
|
|
89
|
+
- `GET /` — Find all (supports `?q=` collection query)
|
|
90
|
+
- `GET /:id` — Find one
|
|
91
|
+
- `PUT /:id` — Update
|
|
92
|
+
- `DELETE /:id` — Soft delete
|
|
93
|
+
|
|
94
|
+
### EntityCrudOptions
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { EntityCrudOptions } from '@zola_do/core';
|
|
98
|
+
|
|
99
|
+
const options: EntityCrudOptions = {
|
|
100
|
+
createDto: CreateProductDto,
|
|
101
|
+
updateDto: UpdateProductDto,
|
|
102
|
+
createPermission: 'product:create',
|
|
103
|
+
viewPermission: 'product:view',
|
|
104
|
+
updatePermission: 'product:update',
|
|
105
|
+
deletePermission: 'product:delete',
|
|
106
|
+
restorePermission: 'product:restore',
|
|
107
|
+
viewArchivedPermission: 'product:view_archived',
|
|
108
|
+
mapCreateContext: ({ req, itemData }) => ({
|
|
109
|
+
organizationId: req?.session?.org?.id,
|
|
110
|
+
organizationName: req?.session?.org?.name,
|
|
111
|
+
createdBy: req?.session?.user?.id,
|
|
112
|
+
}),
|
|
113
|
+
};
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Request Context Mapping
|
|
117
|
+
|
|
118
|
+
`@zola_do/crud` supports three create-time mapping levels:
|
|
119
|
+
|
|
120
|
+
1. `mapCreateContext` in `EntityCrudOptions` / `ExtraCrudOptions` (highest priority)
|
|
121
|
+
2. module-level resolver provider (`CRUD_REQUEST_CONTEXT_RESOLVER`)
|
|
122
|
+
3. legacy fallback to `req.user.organization` (for backward compatibility)
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
import { Module } from '@nestjs/common';
|
|
126
|
+
import {
|
|
127
|
+
CRUD_REQUEST_CONTEXT_RESOLVER,
|
|
128
|
+
CrudRequestContextResolver,
|
|
129
|
+
} from '@zola_do/crud';
|
|
130
|
+
|
|
131
|
+
const crudRequestContextResolver: CrudRequestContextResolver = {
|
|
132
|
+
resolveCreateContext: ({ req }) => ({
|
|
133
|
+
organizationId: req?.auth?.orgId,
|
|
134
|
+
organizationName: req?.auth?.orgName,
|
|
135
|
+
createdBy: req?.auth?.userId,
|
|
136
|
+
}),
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
@Module({
|
|
140
|
+
providers: [
|
|
141
|
+
{
|
|
142
|
+
provide: CRUD_REQUEST_CONTEXT_RESOLVER,
|
|
143
|
+
useValue: crudRequestContextResolver,
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
})
|
|
147
|
+
export class ProductsModule {}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Relation CRUD
|
|
151
|
+
|
|
152
|
+
For many-to-many or relation management:
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
import { RelationCrudController, RelationCrudService } from '@zola_do/crud';
|
|
156
|
+
|
|
157
|
+
@Controller('products/:productId/categories')
|
|
158
|
+
export class ProductCategoriesController extends RelationCrudController(
|
|
159
|
+
{
|
|
160
|
+
firstEntityIdName: 'productId',
|
|
161
|
+
firstInclude: 'product',
|
|
162
|
+
secondEntityIdName: 'categoryId',
|
|
163
|
+
secondInclude: 'category',
|
|
164
|
+
viewPermission: 'product:view',
|
|
165
|
+
},
|
|
166
|
+
ProductCategory,
|
|
167
|
+
) {
|
|
168
|
+
constructor(service: RelationCrudService) {
|
|
169
|
+
super(service);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Exports
|
|
175
|
+
|
|
176
|
+
- **Controllers:** `EntityCrudController`, `RelationCrudController`, `ExtraCrudController`
|
|
177
|
+
- **Services:** `EntityCrudService`, `RelationCrudService`, `ExtraCrudService`
|
|
178
|
+
- **Repositories:** `EntityCrudRepository`, `RelationCrudRepository`, `ExtraCrudRepository`
|
|
179
|
+
- **Context Mapping:** `CRUD_REQUEST_CONTEXT_RESOLVER`, `CrudRequestContextResolver`
|
|
180
|
+
|
|
181
|
+
## Related Packages
|
|
182
|
+
|
|
183
|
+
- [@zola_do/core](../core) — Entity base classes, `EntityCrudOptions`
|
|
184
|
+
- [@zola_do/collection-query](../collection-query) — Query decoding for list endpoints
|
|
185
|
+
- [@zola_do/authorization](../authorization) — Guards for protected CRUD
|
|
@@ -5,8 +5,8 @@ import { RelationCrudRepository } from '../repository';
|
|
|
5
5
|
export declare class RelationCrudService<TEntity extends ObjectLiteral> {
|
|
6
6
|
private readonly repository;
|
|
7
7
|
constructor(repository: RelationCrudRepository<TEntity>);
|
|
8
|
-
bulkSaveFirst(payload: any, relationCrudOptions: RelationCrudOptions): Promise<
|
|
9
|
-
bulkSaveSecond(payload: any, relationCrudOptions: RelationCrudOptions):
|
|
8
|
+
bulkSaveFirst(payload: any, relationCrudOptions: RelationCrudOptions): Promise<TEntity[]>;
|
|
9
|
+
bulkSaveSecond(payload: any, relationCrudOptions: RelationCrudOptions): Promise<TEntity[]>;
|
|
10
10
|
findAllFirst(entityId: string, query: CollectionQuery, relationCrudOptions: RelationCrudOptions): Promise<import("@zola_do/core").DataResponseFormat<TEntity>>;
|
|
11
11
|
findAllSecond(entityId: string, query: CollectionQuery, relationCrudOptions: RelationCrudOptions): Promise<import("@zola_do/core").DataResponseFormat<TEntity>>;
|
|
12
12
|
}
|
|
@@ -17,10 +17,10 @@ let RelationCrudService = class RelationCrudService {
|
|
|
17
17
|
this.repository = repository;
|
|
18
18
|
}
|
|
19
19
|
async bulkSaveFirst(payload, relationCrudOptions) {
|
|
20
|
-
return await this.
|
|
20
|
+
return await this.repository.bulkSaveFirst(payload, relationCrudOptions);
|
|
21
21
|
}
|
|
22
22
|
async bulkSaveSecond(payload, relationCrudOptions) {
|
|
23
|
-
return await this.bulkSaveSecond(payload, relationCrudOptions);
|
|
23
|
+
return await this.repository.bulkSaveSecond(payload, relationCrudOptions);
|
|
24
24
|
}
|
|
25
25
|
async findAllFirst(entityId, query, relationCrudOptions) {
|
|
26
26
|
return await this.repository.findAllFirst(entityId, query, relationCrudOptions);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relation-crud.service.js","sourceRoot":"","sources":["../../../src/crud-operation/service/relation-crud.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,2CAA4C;AAG5C,8CAAuD;AAGhD,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAC9B,YAA6B,UAA2C;QAA3C,eAAU,GAAV,UAAU,CAAiC;IAAG,CAAC;IAE5E,KAAK,CAAC,aAAa,CAAC,OAAY,EAAE,mBAAwC;QACxE,OAAO,MAAM,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"relation-crud.service.js","sourceRoot":"","sources":["../../../src/crud-operation/service/relation-crud.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,2CAA4C;AAG5C,8CAAuD;AAGhD,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAC9B,YAA6B,UAA2C;QAA3C,eAAU,GAAV,UAAU,CAAiC;IAAG,CAAC;IAE5E,KAAK,CAAC,aAAa,CAAC,OAAY,EAAE,mBAAwC;QACxE,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IAC3E,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAAY,EAAE,mBAAwC;QACzE,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,QAAgB,EAChB,KAAsB,EACtB,mBAAwC;QAExC,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,YAAY,CACvC,QAAQ,EACR,KAAK,EACL,mBAAmB,CACpB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,QAAgB,EAChB,KAAsB,EACtB,mBAAwC;QAExC,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CACxC,QAAQ,EACR,KAAK,EACL,mBAAmB,CACpB,CAAC;IACJ,CAAC;CACF,CAAA;AAlCY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;qCAE8B,mCAAsB;GADpD,mBAAmB,CAkC/B"}
|