@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.
Files changed (2) hide show
  1. package/README.md +209 -15
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,24 +1,218 @@
1
- # @uecsio/utils
1
+ # @uecsio/utils-api
2
2
 
3
- Shared TypeScript utility helpers used across UECS services.
3
+ Shared utility helpers for UECS API services built with NestJS and TypeORM.
4
4
 
5
- ## Scripts
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
- - `pnpm run build` compile TypeScript to `dist/`
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
- ## Usage
51
+ **Usage:**
12
52
 
13
- ```ts
14
- import { compactObject } from '@uecsio/utils';
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
- const cleaned = compactObject({
17
- id: 1,
18
- name: 'Example',
19
- optional: undefined,
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
- console.log(cleaned); // { id: 1, name: 'Example' }
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uecsio/utils-api",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Shared utility helpers for UECS API services.",
5
5
  "author": "Dmytro Morozov <morozovdmitry@gmail.com>",
6
6
  "license": "MIT",