@uecsio/utils-api 0.0.1 → 0.0.2
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 +209 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,24 +1,218 @@
|
|
|
1
|
-
# @uecsio/utils
|
|
1
|
+
# @uecsio/utils-api
|
|
2
2
|
|
|
3
|
-
Shared
|
|
3
|
+
Shared utility helpers for UECS API services built with NestJS and TypeORM.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @uecsio/utils-api
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Peer Dependencies
|
|
12
|
+
|
|
13
|
+
This package requires the following peer dependencies:
|
|
14
|
+
|
|
15
|
+
- `@nestjs/common`: ^11.0.0
|
|
16
|
+
- `@nestjs/typeorm`: ^11.0.0
|
|
17
|
+
- `typeorm`: ^0.3.26
|
|
18
|
+
- `class-validator`: ^0.14.0
|
|
19
|
+
- `@dataui/crud-typeorm`: ^5.3.4
|
|
20
|
+
|
|
21
|
+
## Services
|
|
22
|
+
|
|
23
|
+
### BaseTypeOrmCrudService
|
|
24
|
+
|
|
25
|
+
A base class that extends `TypeOrmCrudService` from `@dataui/crud-typeorm` and adds a `getRepository()` method for direct repository access.
|
|
26
|
+
|
|
27
|
+
**Usage:**
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { Injectable } from '@nestjs/common';
|
|
31
|
+
import { InjectRepository } from '@nestjs/typeorm';
|
|
32
|
+
import { Repository } from 'typeorm';
|
|
33
|
+
import { BaseTypeOrmCrudService } from '@uecsio/utils-api';
|
|
34
|
+
import { Page } from './entities/page.entity';
|
|
35
|
+
|
|
36
|
+
@Injectable()
|
|
37
|
+
export class PagesService extends BaseTypeOrmCrudService<Page> {
|
|
38
|
+
constructor(@InjectRepository(Page) repo: Repository<Page>) {
|
|
39
|
+
super(repo);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Now you can access the repository from other services
|
|
44
|
+
const repository = pagesService.getRepository();
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### UrlGeneratorService
|
|
6
48
|
|
|
7
|
-
-
|
|
8
|
-
- `pnpm run lint` – run ESLint on the source
|
|
9
|
-
- `pnpm run test` – execute unit tests with Jest
|
|
49
|
+
Generates unique URL-friendly slugs from strings with automatic collision handling. Supports transliteration for Cyrillic characters and automatically appends numeric suffixes (e.g., `slug-1`, `slug-2`) if duplicates are found.
|
|
10
50
|
|
|
11
|
-
|
|
51
|
+
**Usage:**
|
|
12
52
|
|
|
13
|
-
```
|
|
14
|
-
import {
|
|
53
|
+
```typescript
|
|
54
|
+
import { Injectable } from '@nestjs/common';
|
|
55
|
+
import { InjectRepository } from '@nestjs/typeorm';
|
|
56
|
+
import { Repository } from 'typeorm';
|
|
57
|
+
import { UrlGeneratorService } from '@uecsio/utils-api';
|
|
58
|
+
import { Page } from './entities/page.entity';
|
|
15
59
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
60
|
+
@Injectable()
|
|
61
|
+
export class PageUrlService {
|
|
62
|
+
constructor(
|
|
63
|
+
@InjectRepository(Page) private readonly repository: Repository<Page>,
|
|
64
|
+
private readonly urlGenerator: UrlGeneratorService,
|
|
65
|
+
) {}
|
|
21
66
|
|
|
22
|
-
|
|
67
|
+
async generateSlug(title: string): Promise<string> {
|
|
68
|
+
// Generate a unique URL slug from the title
|
|
69
|
+
return this.urlGenerator.generateUrl(
|
|
70
|
+
'url', // Field name to check for uniqueness
|
|
71
|
+
title, // Base value to convert to slug
|
|
72
|
+
this.repository, // Repository to check for duplicates
|
|
73
|
+
{
|
|
74
|
+
excludeId: 123, // Optional: exclude this ID when updating
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
23
79
|
```
|
|
24
80
|
|
|
81
|
+
**Options:**
|
|
82
|
+
|
|
83
|
+
- `urlField`: Field name to check for uniqueness (default: `'url'`)
|
|
84
|
+
- `baseValue`: String to convert to URL-friendly slug
|
|
85
|
+
- `repository`: TypeORM repository to check for duplicates
|
|
86
|
+
- `options.excludeId`: ID to exclude from uniqueness check (useful when updating)
|
|
87
|
+
- `options.extraCondition`: Additional WHERE conditions for duplicate checking
|
|
88
|
+
- `options.maxAttempts`: Maximum number of attempts before giving up (default: 100)
|
|
89
|
+
|
|
90
|
+
## Validators
|
|
91
|
+
|
|
92
|
+
### @IsUrlPath()
|
|
93
|
+
|
|
94
|
+
Validates that a string is a valid URL path segment (without protocol and domain). Allows alphanumeric characters, hyphens, underscores, forward slashes, and periods.
|
|
95
|
+
|
|
96
|
+
**Usage:**
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { IsString } from 'class-validator';
|
|
100
|
+
import { IsUrlPath } from '@uecsio/utils-api';
|
|
101
|
+
|
|
102
|
+
export class CreatePageDto {
|
|
103
|
+
@IsString()
|
|
104
|
+
@IsUrlPath()
|
|
105
|
+
url: string; // Valid: "/welcome", "about-us", "products/item-1"
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### @IsUniqueValue()
|
|
110
|
+
|
|
111
|
+
Validates that a value is unique in a database table. Automatically excludes the current record's ID when updating.
|
|
112
|
+
|
|
113
|
+
**Usage:**
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { IsString } from 'class-validator';
|
|
117
|
+
import { IsUniqueValue } from '@uecsio/utils-api';
|
|
118
|
+
import { Page } from './entities/page.entity';
|
|
119
|
+
|
|
120
|
+
export class CreatePageDto {
|
|
121
|
+
@IsString()
|
|
122
|
+
@IsUniqueValue(Page, 'url')
|
|
123
|
+
url: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export class UpdatePageDto {
|
|
127
|
+
id: number;
|
|
128
|
+
|
|
129
|
+
@IsString()
|
|
130
|
+
@IsUniqueValue(Page, 'url') // Will exclude this.id from the check
|
|
131
|
+
url: string;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// With custom ID field
|
|
135
|
+
export class UpdateUserDto {
|
|
136
|
+
userId: number;
|
|
137
|
+
|
|
138
|
+
@IsString()
|
|
139
|
+
@IsUniqueValue(User, 'email', 'userId') // Use 'userId' instead of 'id'
|
|
140
|
+
email: string;
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Parameters:**
|
|
145
|
+
|
|
146
|
+
- `entity`: The TypeORM entity class to check against
|
|
147
|
+
- `field`: The field name in the entity to check for uniqueness
|
|
148
|
+
- `idField`: Optional field name for the ID (default: `'id'`)
|
|
149
|
+
- `validationOptions`: Optional `class-validator` validation options
|
|
150
|
+
|
|
151
|
+
**Note:** This validator requires `IsUniqueValueConstraint` to be provided in your NestJS module:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import { Module } from '@nestjs/common';
|
|
155
|
+
import { IsUniqueValueConstraint } from '@uecsio/utils-api';
|
|
156
|
+
|
|
157
|
+
@Module({
|
|
158
|
+
providers: [IsUniqueValueConstraint],
|
|
159
|
+
// ...
|
|
160
|
+
})
|
|
161
|
+
export class MyModule {}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Complete Example
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import { Module } from '@nestjs/common';
|
|
168
|
+
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
169
|
+
import { BaseTypeOrmCrudService, UrlGeneratorService, IsUniqueValueConstraint } from '@uecsio/utils-api';
|
|
170
|
+
import { Page } from './entities/page.entity';
|
|
171
|
+
import { CreatePageDto } from './dto/create-page.dto';
|
|
172
|
+
|
|
173
|
+
// Service extending base CRUD service
|
|
174
|
+
@Injectable()
|
|
175
|
+
export class PagesService extends BaseTypeOrmCrudService<Page> {
|
|
176
|
+
constructor(@InjectRepository(Page) repo: Repository<Page>) {
|
|
177
|
+
super(repo);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// DTO with validators
|
|
182
|
+
export class CreatePageDto {
|
|
183
|
+
@IsString()
|
|
184
|
+
@IsUrlPath()
|
|
185
|
+
@IsUniqueValue(Page, 'url')
|
|
186
|
+
url: string;
|
|
187
|
+
|
|
188
|
+
@IsString()
|
|
189
|
+
title: string;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Module setup
|
|
193
|
+
@Module({
|
|
194
|
+
imports: [TypeOrmModule.forFeature([Page])],
|
|
195
|
+
providers: [
|
|
196
|
+
PagesService,
|
|
197
|
+
UrlGeneratorService,
|
|
198
|
+
IsUniqueValueConstraint, // Required for @IsUniqueValue()
|
|
199
|
+
],
|
|
200
|
+
exports: [PagesService],
|
|
201
|
+
})
|
|
202
|
+
export class PagesModule {}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Scripts
|
|
206
|
+
|
|
207
|
+
- `npm run build` – Compile TypeScript to `dist/`
|
|
208
|
+
- `npm run build:watch` – Watch mode for development
|
|
209
|
+
- `npm run lint` – Run ESLint on the source
|
|
210
|
+
- `npm run lint:fix` – Fix ESLint issues automatically
|
|
211
|
+
- `npm run test` – Execute unit tests with Jest
|
|
212
|
+
- `npm run test:watch` – Watch mode for tests
|
|
213
|
+
- `npm run test:cov` – Run tests with coverage
|
|
214
|
+
- `npm run clean` – Remove the `dist/` directory
|
|
215
|
+
|
|
216
|
+
## License
|
|
217
|
+
|
|
218
|
+
MIT
|