svelte-reflector 1.1.13 → 1.1.15
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 +102 -55
- package/dist/core/method/Method.d.ts +1 -2
- package/dist/core/method/MethodApiTypeAnalyzer.d.ts +1 -2
- package/dist/core/method/generators/MethodGenerator.js +6 -1
- package/dist/core/module/ModuleClassBuilder.js +1 -1
- package/dist/core/module/ModuleImports.js +5 -5
- package/dist/file.d.ts +1 -1
- package/dist/file.js +1 -1
- package/dist/generate-doc.js +4 -5
- package/dist/helpers/generate-doc.helper.d.ts +2 -2
- package/dist/helpers/generate-doc.helper.js +0 -1
- package/dist/helpers/helpers.d.ts +1 -0
- package/dist/helpers/helpers.js +6 -0
- package/dist/helpers/input.js +1 -1
- package/dist/main.d.ts +2 -2
- package/dist/main.js +17 -14
- package/dist/method.d.ts +1 -1
- package/dist/module.js +4 -4
- package/dist/reflector.js +3 -3
- package/dist/types/types.d.ts +1 -0
- package/package.json +9 -2
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Svelte Reflector
|
|
2
2
|
|
|
3
|
-
**Turn your OpenAPI into a first
|
|
3
|
+
**Turn your OpenAPI into a first-class Svelte 5 DX.**
|
|
4
4
|
|
|
5
|
-
Svelte Reflector is a **developer
|
|
5
|
+
Svelte Reflector is a **developer-experience-first code generator** that converts OpenAPI specs into fully typed, reactive Svelte 5 modules — ready for production, forms included.
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/svelte-reflector)
|
|
8
8
|
[](https://www.npmjs.com/package/svelte-reflector)
|
|
@@ -12,17 +12,20 @@ Svelte Reflector is a **developer‑experience–first code generator** that con
|
|
|
12
12
|
|
|
13
13
|
A TypeScript code generator that creates type-safe Svelte 5 modules from OpenAPI specifications. It transforms your backend's OpenAPI/Swagger docs into fully-typed Svelte stores with built-in form handling, validation, and API integration.
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Features
|
|
16
16
|
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
17
|
+
- **Automatic Type Generation** - Generates TypeScript interfaces and classes from OpenAPI schemas
|
|
18
|
+
- **Svelte 5 Runes Integration** - Uses `$state` and `$derived` for reactive state management
|
|
19
|
+
- **Form Handling** - Auto-generates form schemas with validation support
|
|
20
|
+
- **Type-Safe API Calls** - Full TypeScript support for all API operations
|
|
21
|
+
- **Query Parameter Sync** - `QueryBuilder` and `EnumQueryBuilder` keep state synced with URL searchParams
|
|
22
|
+
- **Enum Support** - Auto-generates enum types and array enum query builders
|
|
23
|
+
- **OpenAPI/Swagger Compatible** - Works with any backend that exposes OpenAPI specs
|
|
24
|
+
- **Development Mode** - Smart regeneration based on environment
|
|
25
|
+
- **Validation Ready** - Built-in support for custom field validators
|
|
26
|
+
- **Vite Plugin** - Can be used as a Vite plugin for automatic generation on build
|
|
24
27
|
|
|
25
|
-
##
|
|
28
|
+
## Installation
|
|
26
29
|
|
|
27
30
|
```bash
|
|
28
31
|
npm install svelte-reflector
|
|
@@ -32,7 +35,7 @@ yarn add svelte-reflector
|
|
|
32
35
|
pnpm add svelte-reflector
|
|
33
36
|
```
|
|
34
37
|
|
|
35
|
-
##
|
|
38
|
+
## Quick Start
|
|
36
39
|
|
|
37
40
|
### 1. Configure Environment Variables
|
|
38
41
|
|
|
@@ -77,7 +80,7 @@ export const validators = [
|
|
|
77
80
|
# Manual generation (recommended for DEV environment)
|
|
78
81
|
npx reflect
|
|
79
82
|
|
|
80
|
-
# Or programmatically
|
|
83
|
+
# Or programmatically as a Vite plugin
|
|
81
84
|
import { reflector } from "svelte-reflector";
|
|
82
85
|
await reflector(true); // true = force generation
|
|
83
86
|
```
|
|
@@ -99,8 +102,10 @@ console.log(userModule.list); // $state<User[]>
|
|
|
99
102
|
|
|
100
103
|
// Call API methods
|
|
101
104
|
await userModule.listAll({
|
|
102
|
-
|
|
103
|
-
|
|
105
|
+
behavior: {
|
|
106
|
+
onSuccess: (response) => console.log(response),
|
|
107
|
+
onError: (error) => console.error(error),
|
|
108
|
+
},
|
|
104
109
|
});
|
|
105
110
|
|
|
106
111
|
// Work with forms
|
|
@@ -112,7 +117,7 @@ userForm.email.value = "john@example.com";
|
|
|
112
117
|
await userModule.createUser();
|
|
113
118
|
```
|
|
114
119
|
|
|
115
|
-
##
|
|
120
|
+
## Generated Structure
|
|
116
121
|
|
|
117
122
|
```
|
|
118
123
|
src/reflector/
|
|
@@ -120,12 +125,14 @@ src/reflector/
|
|
|
120
125
|
│ └── user/
|
|
121
126
|
│ └── user.module.svelte.ts # API module with methods
|
|
122
127
|
├── schemas.svelte.ts # Generated schemas & types
|
|
123
|
-
├── reflector.svelte.ts # Core utilities (build, isFormValid)
|
|
128
|
+
├── reflector.svelte.ts # Core utilities (build, isFormValid, QueryBuilder, etc.)
|
|
124
129
|
├── fields.ts # Field name constants
|
|
130
|
+
├── enums.ts # Enum type definitions
|
|
131
|
+
├── mocked-params.svelte.ts # Mocked path parameters ($state)
|
|
125
132
|
└── backup.json # Cached OpenAPI spec
|
|
126
133
|
```
|
|
127
134
|
|
|
128
|
-
##
|
|
135
|
+
## Generated Module API
|
|
129
136
|
|
|
130
137
|
Each generated module provides:
|
|
131
138
|
|
|
@@ -136,44 +143,61 @@ Each generated module provides:
|
|
|
136
143
|
| `loading` | `$state<boolean>` | Request loading state |
|
|
137
144
|
| `list` | `$state<T[]>` | List results (for list endpoints) |
|
|
138
145
|
| `forms` | `$state<Record<string, T>>` | Form instances |
|
|
139
|
-
| `querys` | `
|
|
140
|
-
| `headers` | `
|
|
141
|
-
| `paths` | `
|
|
146
|
+
| `querys` | `Querys` | Query parameter state (QueryBuilder instances) |
|
|
147
|
+
| `headers` | `Headers` | Header state |
|
|
148
|
+
| `paths` | `Paths` | Path parameter state |
|
|
142
149
|
|
|
143
150
|
### Methods
|
|
144
151
|
|
|
145
152
|
```typescript
|
|
146
153
|
// List all items (GET with page parameter)
|
|
147
|
-
async listAll(behavior?: Behavior
|
|
154
|
+
async listAll(params?: { behavior?: Behavior }): Promise<T[]>
|
|
148
155
|
|
|
149
156
|
// Get single entity (GET without page parameter)
|
|
150
|
-
async get(behavior?: Behavior
|
|
157
|
+
async get(params?: { behavior?: Behavior }): Promise<T>
|
|
151
158
|
|
|
152
159
|
// Create/Update (POST/PUT/PATCH)
|
|
153
|
-
async create(behavior?: Behavior
|
|
154
|
-
async update(behavior?: Behavior
|
|
160
|
+
async create(params?: { behavior?: Behavior }): Promise<T>
|
|
161
|
+
async update(params?: { behavior?: Behavior }): Promise<T>
|
|
155
162
|
|
|
156
163
|
// Delete (DELETE)
|
|
157
|
-
async delete(behavior?: Behavior
|
|
158
|
-
|
|
159
|
-
// Form with auto-clear
|
|
160
|
-
async createAndClear(behavior?: Behavior<ResponseType>): Promise<T>
|
|
164
|
+
async delete(params?: { behavior?: Behavior }): Promise<void>
|
|
161
165
|
|
|
162
166
|
// Reset all state
|
|
163
167
|
reset(): void
|
|
168
|
+
|
|
169
|
+
// Clear forms
|
|
170
|
+
clearForms(): void
|
|
164
171
|
```
|
|
165
172
|
|
|
166
|
-
|
|
173
|
+
### QueryBuilder
|
|
174
|
+
|
|
175
|
+
Query parameters are wrapped in `QueryBuilder` instances that sync with URL searchParams:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// Single value query parameter
|
|
179
|
+
const querys = module.querys;
|
|
180
|
+
querys.status.update("active"); // Updates URL searchParam and internal state
|
|
181
|
+
|
|
182
|
+
// Array enum query parameter
|
|
183
|
+
const enumQuery = module.querys.roles; // EnumQueryBuilder<RoleType>
|
|
184
|
+
enumQuery.selected = "admin";
|
|
185
|
+
enumQuery.add(); // Adds to URL searchParams
|
|
186
|
+
enumQuery.remove(0); // Removes from URL searchParams
|
|
187
|
+
enumQuery.values; // $derived from URL - always in sync
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Configuration
|
|
167
191
|
|
|
168
192
|
### Environment Variables
|
|
169
193
|
|
|
170
194
|
| Variable | Required | Description |
|
|
171
195
|
|----------|----------|-------------|
|
|
172
|
-
| `BACKEND_URL` |
|
|
173
|
-
| `PUBLIC_BACKEND` |
|
|
174
|
-
| `ENVIRONMENT` |
|
|
175
|
-
| `VITE_ENVIRONMENT` |
|
|
176
|
-
| `NODE_ENV` |
|
|
196
|
+
| `BACKEND_URL` | Yes | Backend API URL |
|
|
197
|
+
| `PUBLIC_BACKEND` | Yes | Alternative to BACKEND_URL |
|
|
198
|
+
| `ENVIRONMENT` | No | DEV/PROD (defaults to PROD) |
|
|
199
|
+
| `VITE_ENVIRONMENT` | No | Vite-specific env var |
|
|
200
|
+
| `NODE_ENV` | No | Node environment |
|
|
177
201
|
|
|
178
202
|
### Behavior Pattern
|
|
179
203
|
|
|
@@ -181,14 +205,16 @@ All API methods accept a `Behavior` object for callbacks:
|
|
|
181
205
|
|
|
182
206
|
```typescript
|
|
183
207
|
interface Behavior<TSuccess, TError> {
|
|
184
|
-
onSuccess?: (value: TSuccess) => void;
|
|
185
|
-
onError?: (error: TError) => void;
|
|
208
|
+
onSuccess?: (value: TSuccess) => Promise<void> | void;
|
|
209
|
+
onError?: (error: TError) => Promise<void> | void;
|
|
186
210
|
}
|
|
187
211
|
|
|
188
212
|
// Usage
|
|
189
213
|
await userModule.createUser({
|
|
190
|
-
|
|
191
|
-
|
|
214
|
+
behavior: {
|
|
215
|
+
onSuccess: (user) => console.log("Created:", user),
|
|
216
|
+
onError: (err) => console.error("Failed:", err),
|
|
217
|
+
},
|
|
192
218
|
});
|
|
193
219
|
```
|
|
194
220
|
|
|
@@ -197,17 +223,25 @@ await userModule.createUser({
|
|
|
197
223
|
Forms use `BuildedInput` class with validation:
|
|
198
224
|
|
|
199
225
|
```typescript
|
|
200
|
-
|
|
226
|
+
class BuildedInput<T> {
|
|
201
227
|
value: T; // Current value ($state)
|
|
202
228
|
display: T; // Display value ($state)
|
|
203
229
|
required: boolean; // Is field required
|
|
204
230
|
placeholder: T; // Placeholder/example value
|
|
231
|
+
readonly kind: 'builded';
|
|
205
232
|
validator?: (v: T) => string | null; // Validation function
|
|
206
233
|
validate(): string | null; // Run validation
|
|
207
234
|
}
|
|
235
|
+
|
|
236
|
+
// Check if all form fields are valid
|
|
237
|
+
import { isFormValid } from "$reflector/reflector.svelte";
|
|
238
|
+
|
|
239
|
+
if (isFormValid(userModule.forms.createUser)) {
|
|
240
|
+
await userModule.createUser();
|
|
241
|
+
}
|
|
208
242
|
```
|
|
209
243
|
|
|
210
|
-
##
|
|
244
|
+
## TypeScript Configuration
|
|
211
245
|
|
|
212
246
|
Add path aliases to your `tsconfig.json`:
|
|
213
247
|
|
|
@@ -235,7 +269,7 @@ export default defineConfig({
|
|
|
235
269
|
});
|
|
236
270
|
```
|
|
237
271
|
|
|
238
|
-
##
|
|
272
|
+
## Workflow
|
|
239
273
|
|
|
240
274
|
### Development Mode
|
|
241
275
|
|
|
@@ -251,7 +285,7 @@ In `ENVIRONMENT=PROD`:
|
|
|
251
285
|
- Fresh types from latest OpenAPI spec
|
|
252
286
|
- Fallback to `backup.json` if backend is unavailable
|
|
253
287
|
|
|
254
|
-
##
|
|
288
|
+
## Advanced Usage
|
|
255
289
|
|
|
256
290
|
### Custom Validators
|
|
257
291
|
|
|
@@ -300,7 +334,7 @@ export function validateEmail(value: string): string | null {
|
|
|
300
334
|
return emailRegex.test(value) ? null : "Invalid email format";
|
|
301
335
|
}
|
|
302
336
|
|
|
303
|
-
//
|
|
337
|
+
// Phone validation
|
|
304
338
|
export function validatePhone(value: string): string | null {
|
|
305
339
|
if (!value) return null;
|
|
306
340
|
const phoneRegex = /^(\+?55\s?)?(\(?\d{2}\)?\s?)?(\d{4,5}-?\d{4})$/;
|
|
@@ -311,7 +345,7 @@ export function validatePhone(value: string): string | null {
|
|
|
311
345
|
export function validateDocument(value: string): string | null {
|
|
312
346
|
if (!value) return null;
|
|
313
347
|
const cleaned = value.replace(/\D/g, '');
|
|
314
|
-
|
|
348
|
+
|
|
315
349
|
if (cleaned.length === 11) {
|
|
316
350
|
return validateCPF(cleaned) ? null : "Invalid CPF";
|
|
317
351
|
} else if (cleaned.length === 14) {
|
|
@@ -322,13 +356,13 @@ export function validateDocument(value: string): string | null {
|
|
|
322
356
|
|
|
323
357
|
function validateCPF(cpf: string): boolean {
|
|
324
358
|
if (/^(\d)\1{10}$/.test(cpf)) return false;
|
|
325
|
-
|
|
359
|
+
|
|
326
360
|
let sum = 0;
|
|
327
361
|
for (let i = 0; i < 9; i++) sum += parseInt(cpf[i]) * (10 - i);
|
|
328
362
|
let rev = 11 - (sum % 11);
|
|
329
363
|
if (rev === 10 || rev === 11) rev = 0;
|
|
330
364
|
if (rev !== parseInt(cpf[9])) return false;
|
|
331
|
-
|
|
365
|
+
|
|
332
366
|
sum = 0;
|
|
333
367
|
for (let i = 0; i < 10; i++) sum += parseInt(cpf[i]) * (11 - i);
|
|
334
368
|
rev = 11 - (sum % 11);
|
|
@@ -338,15 +372,15 @@ function validateCPF(cpf: string): boolean {
|
|
|
338
372
|
|
|
339
373
|
function validateCNPJ(cnpj: string): boolean {
|
|
340
374
|
if (/^(\d)\1{13}$/.test(cnpj)) return false;
|
|
341
|
-
|
|
375
|
+
|
|
342
376
|
const weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
343
377
|
const weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
344
|
-
|
|
378
|
+
|
|
345
379
|
let sum = 0;
|
|
346
380
|
for (let i = 0; i < 12; i++) sum += parseInt(cnpj[i]) * weights1[i];
|
|
347
381
|
let rev = sum % 11 < 2 ? 0 : 11 - (sum % 11);
|
|
348
382
|
if (rev !== parseInt(cnpj[12])) return false;
|
|
349
|
-
|
|
383
|
+
|
|
350
384
|
sum = 0;
|
|
351
385
|
for (let i = 0; i < 13; i++) sum += parseInt(cnpj[i]) * weights2[i];
|
|
352
386
|
rev = sum % 11 < 2 ? 0 : 11 - (sum % 11);
|
|
@@ -435,7 +469,20 @@ const user = new User({ name: "John", email: "john@example.com" });
|
|
|
435
469
|
const data = user.bundle(); // { name: "John", email: "john@example.com" }
|
|
436
470
|
```
|
|
437
471
|
|
|
438
|
-
|
|
472
|
+
### Batch Query Updates
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
import { setQueryGroup } from "$reflector/reflector.svelte";
|
|
476
|
+
|
|
477
|
+
// Update multiple query params at once
|
|
478
|
+
setQueryGroup([
|
|
479
|
+
{ key: "page", value: 1 },
|
|
480
|
+
{ key: "status", value: "active" },
|
|
481
|
+
{ key: "roles", value: ["admin", "editor"] }, // Array params supported
|
|
482
|
+
]);
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
## Troubleshooting
|
|
439
486
|
|
|
440
487
|
### "BACKEND_URL vazio" Error
|
|
441
488
|
|
|
@@ -451,15 +498,15 @@ In DEV mode, run `npx reflect` manually. Check that your backend's OpenAPI spec
|
|
|
451
498
|
2. Check path aliases in `tsconfig.json`
|
|
452
499
|
3. Ensure `$reflector/*` alias is configured
|
|
453
500
|
|
|
454
|
-
##
|
|
501
|
+
## License
|
|
455
502
|
|
|
456
503
|
MIT License - see [LICENSE](LICENSE) for details.
|
|
457
504
|
|
|
458
|
-
##
|
|
505
|
+
## Contributing
|
|
459
506
|
|
|
460
507
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
461
508
|
|
|
462
|
-
##
|
|
509
|
+
## Links
|
|
463
510
|
|
|
464
511
|
- [npm](https://www.npmjs.com/package/svelte-reflector)
|
|
465
512
|
- [GitHub](https://github.com/aleleppy/reflector)
|
|
@@ -468,4 +515,4 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
468
515
|
|
|
469
516
|
---
|
|
470
517
|
|
|
471
|
-
Built with
|
|
518
|
+
Built with by the Pináculo Digital team.
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import type { ApiType } from "../../types/types.js";
|
|
1
|
+
import type { ApiType, ReflectorRequestType } from "../../types/types.js";
|
|
2
2
|
import type { PrimitiveProp } from "../../props/primitive.property.js";
|
|
3
3
|
import type { ArrayProp } from "../../props/array.property.js";
|
|
4
4
|
import type { EnumProp } from "../../props/enum.property.js";
|
|
5
|
-
import type { ReflectorRequestType } from "../../request.js";
|
|
6
5
|
export type AttributeProp = PrimitiveProp | ArrayProp | EnumProp;
|
|
7
6
|
export interface MethodAnalyzers {
|
|
8
7
|
request: {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { ReflectorOperation, ApiType } from "../../types/types.js";
|
|
2
|
-
import type { ReflectorRequestType } from "../../request.js";
|
|
1
|
+
import type { ReflectorOperation, ApiType, ReflectorRequestType } from "../../types/types.js";
|
|
3
2
|
export declare class MethodApiTypeAnalyzer {
|
|
4
3
|
analyze(operation: ReflectorOperation): {
|
|
5
4
|
apiType: ApiType;
|
|
@@ -33,7 +33,12 @@ export class MethodGenerator {
|
|
|
33
33
|
|
|
34
34
|
return ${methodReturn};
|
|
35
35
|
} catch (e) {
|
|
36
|
-
|
|
36
|
+
let parsedError: ApiErrorResponse;
|
|
37
|
+
try {
|
|
38
|
+
parsedError = JSON.parse((e as Error).message) as ApiErrorResponse;
|
|
39
|
+
} catch {
|
|
40
|
+
parsedError = { error: 'unknown', message: (e as Error).message ?? String(e) };
|
|
41
|
+
}
|
|
37
42
|
return await onError?.(parsedError);
|
|
38
43
|
} finally {
|
|
39
44
|
this.loading = false;
|
|
@@ -6,7 +6,7 @@ export class ModuleImports {
|
|
|
6
6
|
mockedImports;
|
|
7
7
|
constructor() {
|
|
8
8
|
this.imports = new Set([
|
|
9
|
-
"// AUTO
|
|
9
|
+
"// AUTO GENERATED by svelte-reflector. DO NOT EDIT.\n",
|
|
10
10
|
'import api from "$repository/api"',
|
|
11
11
|
`import { PUBLIC_ENVIRONMENT } from '$env/static/public'`,
|
|
12
12
|
]);
|
|
@@ -24,7 +24,7 @@ export class ModuleImports {
|
|
|
24
24
|
this.reflectorImports.add(importStr);
|
|
25
25
|
}
|
|
26
26
|
addSetQueryGroupImport() {
|
|
27
|
-
this.reflectorImports.add("
|
|
27
|
+
this.reflectorImports.add("setQueryGroup");
|
|
28
28
|
}
|
|
29
29
|
addEnumImport(enumName) {
|
|
30
30
|
this.enumImports.add(enumName);
|
|
@@ -52,11 +52,11 @@ export class ModuleImports {
|
|
|
52
52
|
}
|
|
53
53
|
buildReflectorImportsLine() {
|
|
54
54
|
const imports = this.getReflectorImportsArray();
|
|
55
|
-
const regularImports = imports.filter(i => i !== "
|
|
56
|
-
const hasSetQueryGroup = imports.includes("
|
|
55
|
+
const regularImports = imports.filter(i => i !== "setQueryGroup");
|
|
56
|
+
const hasSetQueryGroup = imports.includes("setQueryGroup");
|
|
57
57
|
let result = `import { ${regularImports.join(", ")}, type ApiErrorResponse`;
|
|
58
58
|
if (hasSetQueryGroup) {
|
|
59
|
-
result += `,
|
|
59
|
+
result += `, setQueryGroup`;
|
|
60
60
|
}
|
|
61
61
|
result += ` } from "$reflector/reflector.svelte";`;
|
|
62
62
|
return result;
|
package/dist/file.d.ts
CHANGED
package/dist/file.js
CHANGED
package/dist/generate-doc.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import "dotenv/config"; // carrega .env a partir de process.cwd()
|
|
1
|
+
import "dotenv/config";
|
|
3
2
|
import axios from "axios";
|
|
4
3
|
import * as path from "node:path";
|
|
5
4
|
import * as fs from "node:fs";
|
|
@@ -48,7 +47,7 @@ export async function reflector(manual = false) {
|
|
|
48
47
|
const documentation = await axios.get(DOC_URL, { timeout: 15000 });
|
|
49
48
|
data = documentation.data;
|
|
50
49
|
const backup = new Source({ path: "src/backup.json", data: JSON.stringify(data) });
|
|
51
|
-
backup.save();
|
|
50
|
+
await backup.save();
|
|
52
51
|
}
|
|
53
52
|
catch (e) {
|
|
54
53
|
console.warn(`[reflector] Não foi possível obter a documentação em ${DOC_URL}. Carregando cópia local...`);
|
|
@@ -74,8 +73,8 @@ export async function reflector(manual = false) {
|
|
|
74
73
|
return breakReflector();
|
|
75
74
|
}
|
|
76
75
|
const r = new Reflector({ components, paths, validators });
|
|
77
|
-
r.build();
|
|
78
|
-
r.localSave(data);
|
|
76
|
+
await r.build();
|
|
77
|
+
await r.localSave(data);
|
|
79
78
|
return breakReflector();
|
|
80
79
|
}
|
|
81
80
|
function breakReflector() {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SchemaObject } from "../types/open-api-spec.interface.js";
|
|
2
|
+
export declare function toKebabCase(str: string): string;
|
|
2
3
|
export declare function toCamelCase(str: string): string;
|
|
3
4
|
export declare function sanitizeKey(name: string): string;
|
|
4
5
|
export declare function sanitizeNumber(texto: string): string;
|
package/dist/helpers/helpers.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
const trashWords = new Set(["Get", "Res", "Default", "Dto", "Public", "Response", "Self"]);
|
|
2
|
+
export function toKebabCase(str) {
|
|
3
|
+
return str
|
|
4
|
+
.replaceAll(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
5
|
+
.replaceAll(/([A-Z])([A-Z][a-z])/g, "$1-$2")
|
|
6
|
+
.toLowerCase();
|
|
7
|
+
}
|
|
2
8
|
export function toCamelCase(str) {
|
|
3
9
|
return str
|
|
4
10
|
.split("-")
|
package/dist/helpers/input.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export class ReflectorInput {
|
|
2
2
|
password = `z
|
|
3
3
|
.string()
|
|
4
|
-
.regex(/^(?=.*[A-Z])(?=.*[a-z])(
|
|
4
|
+
.regex(/^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[^A-Za-z0-9]).{8,}$/, {
|
|
5
5
|
message: 'A senha deve conter pelo menos ',
|
|
6
6
|
})
|
|
7
7
|
.min(8, { message: '8 caracteres, ' })
|
package/dist/main.d.ts
CHANGED
package/dist/main.js
CHANGED
|
@@ -6,7 +6,6 @@ import { Schema } from "./schema.js";
|
|
|
6
6
|
import { Module } from "./module.js";
|
|
7
7
|
import { baseDir, generatedDir } from "./vars.global.js";
|
|
8
8
|
import { ReflectorFile } from "./reflector.js";
|
|
9
|
-
// import { Module } from "./module.js";
|
|
10
9
|
export const enumTypes = new Map();
|
|
11
10
|
export const mockedParams = new Set();
|
|
12
11
|
export class Reflector {
|
|
@@ -25,6 +24,9 @@ export class Reflector {
|
|
|
25
24
|
modules;
|
|
26
25
|
constructor(params) {
|
|
27
26
|
const { components, paths, validators } = params;
|
|
27
|
+
// Limpa estado global entre execuções
|
|
28
|
+
enumTypes.clear();
|
|
29
|
+
mockedParams.clear();
|
|
28
30
|
this.clearSrc();
|
|
29
31
|
this.components = components;
|
|
30
32
|
this.paths = paths;
|
|
@@ -94,7 +96,7 @@ export class Reflector {
|
|
|
94
96
|
});
|
|
95
97
|
return modules;
|
|
96
98
|
}
|
|
97
|
-
build() {
|
|
99
|
+
async build() {
|
|
98
100
|
const treatedSchemas = this.schemas.map((s) => {
|
|
99
101
|
return `
|
|
100
102
|
${s.interface};
|
|
@@ -110,29 +112,20 @@ export class Reflector {
|
|
|
110
112
|
"const isEmpty = PUBLIC_ENVIRONMENT !== 'DEV';",
|
|
111
113
|
...treatedSchemas,
|
|
112
114
|
].join("\n"));
|
|
113
|
-
this.schemaFile.save();
|
|
114
115
|
const buildFunctions = new ReflectorFile().fileContent;
|
|
115
116
|
this.typesSrc.changeData(buildFunctions);
|
|
116
|
-
this.typesSrc.save();
|
|
117
117
|
this.fieldsFile.changeData(`
|
|
118
118
|
export const FIELD_NAMES = [
|
|
119
119
|
${Array.from(this.propertiesNames).map((p) => `'${p}'`)}
|
|
120
120
|
] as const;
|
|
121
121
|
export type FieldName = (typeof FIELD_NAMES)[number]
|
|
122
122
|
`);
|
|
123
|
-
this.fieldsFile.save();
|
|
124
|
-
for (const module of this.modules) {
|
|
125
|
-
if (module.methods.length === 0)
|
|
126
|
-
continue;
|
|
127
|
-
module.src.save();
|
|
128
|
-
}
|
|
129
123
|
const enumss = Array.from(enumTypes)
|
|
130
124
|
.map(([types, key]) => {
|
|
131
125
|
return `export const ${key} = [ ${types} ] as const; export type ${key} = typeof ${key}[number] `;
|
|
132
126
|
})
|
|
133
127
|
.join(";");
|
|
134
128
|
this.enumFile.changeData(enumss);
|
|
135
|
-
this.enumFile.save();
|
|
136
129
|
const mockedParamss = Array.from(mockedParams)
|
|
137
130
|
.map((paramName) => {
|
|
138
131
|
return `${paramName} = $state<string | null>(null)`;
|
|
@@ -147,12 +140,22 @@ export class Reflector {
|
|
|
147
140
|
export default mockedParams
|
|
148
141
|
`;
|
|
149
142
|
this.mockedParamsFile.changeData(mockedFile);
|
|
150
|
-
|
|
143
|
+
// Salva todos os arquivos em paralelo, aguardando conclusão
|
|
144
|
+
await Promise.all([
|
|
145
|
+
this.schemaFile.save(),
|
|
146
|
+
this.typesSrc.save(),
|
|
147
|
+
this.fieldsFile.save(),
|
|
148
|
+
this.enumFile.save(),
|
|
149
|
+
this.mockedParamsFile.save(),
|
|
150
|
+
...this.modules
|
|
151
|
+
.filter((m) => m.methods.length > 0)
|
|
152
|
+
.map((m) => m.src.save()),
|
|
153
|
+
]);
|
|
151
154
|
return {};
|
|
152
155
|
}
|
|
153
|
-
localSave(data) {
|
|
156
|
+
async localSave(data) {
|
|
154
157
|
this.localDoc.data = JSON.stringify(data);
|
|
155
|
-
this.localDoc.save();
|
|
158
|
+
await this.localDoc.save();
|
|
156
159
|
}
|
|
157
160
|
clearSrc() {
|
|
158
161
|
fs.rmSync(this.src.path, { recursive: true, force: true });
|
package/dist/method.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export declare class Method {
|
|
|
11
11
|
get request(): {
|
|
12
12
|
bodyType: string | undefined;
|
|
13
13
|
responseType: string | null;
|
|
14
|
-
attributeType: import("./
|
|
14
|
+
attributeType: import("./types/types.js").ReflectorRequestType;
|
|
15
15
|
apiType: import("./types/types.js").ApiType;
|
|
16
16
|
parameters: any[];
|
|
17
17
|
hasEnumResponse: boolean;
|
package/dist/module.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import { Source } from "./file.js";
|
|
4
|
-
import { capitalizeFirstLetter } from "./helpers/helpers.js";
|
|
4
|
+
import { capitalizeFirstLetter, toKebabCase } from "./helpers/helpers.js";
|
|
5
5
|
import { Method } from "./method.js";
|
|
6
6
|
import { generatedDir } from "./vars.global.js";
|
|
7
7
|
import { ModuleImports, ModuleMethodProcessor, ModuleParamProcessor, ModuleClassBuilder, ModuleConstructorBuilder, ModuleFileBuilder, } from "./core/index.js";
|
|
@@ -97,9 +97,9 @@ export class Module {
|
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
99
|
getPath() {
|
|
100
|
-
const
|
|
101
|
-
const inPath = path.join(generatedDir,
|
|
102
|
-
const outPath = path.join(inPath, `${
|
|
100
|
+
const kebabName = toKebabCase(this.name);
|
|
101
|
+
const inPath = path.join(generatedDir, "controllers", kebabName);
|
|
102
|
+
const outPath = path.join(inPath, `${kebabName}.module.svelte.ts`);
|
|
103
103
|
fs.mkdirSync(inPath, { recursive: true });
|
|
104
104
|
return outPath;
|
|
105
105
|
}
|
package/dist/reflector.js
CHANGED
|
@@ -171,19 +171,19 @@ export class ReflectorFile {
|
|
|
171
171
|
return changeParam({ key: this.key, event: this.value });
|
|
172
172
|
}
|
|
173
173
|
}`,
|
|
174
|
-
`export function
|
|
174
|
+
`export function setQueryGroup(group: QuerySeiLa[]) {
|
|
175
175
|
const url = new URL(page.url);
|
|
176
176
|
|
|
177
177
|
for (const p of group) {
|
|
178
178
|
const { key, value } = p;
|
|
179
179
|
|
|
180
|
-
const updatedValue = url.searchParams.get(key) ?? value;
|
|
181
|
-
|
|
182
180
|
if (Array.isArray(value)) {
|
|
181
|
+
url.searchParams.delete(key);
|
|
183
182
|
value.forEach((v) => url.searchParams.append(key, String(v)));
|
|
184
183
|
continue;
|
|
185
184
|
}
|
|
186
185
|
|
|
186
|
+
const updatedValue = url.searchParams.get(key) ?? value;
|
|
187
187
|
url.searchParams.set(key, String(updatedValue));
|
|
188
188
|
}
|
|
189
189
|
|
package/dist/types/types.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { EnumProp } from "../props/enum.property.js";
|
|
|
3
3
|
import type { PrimitiveProp } from "../props/primitive.property.js";
|
|
4
4
|
import type { OperationObject } from "./open-api-spec.interface.js";
|
|
5
5
|
export type ReflectorParamType = "string" | "boolean" | "number" | "array" | "object" | "enum" | "any";
|
|
6
|
+
export type ReflectorRequestType = "entity" | "list" | "pagination" | "form" | "other";
|
|
6
7
|
export type ApiType = "get" | "post" | "delete" | "patch" | "put";
|
|
7
8
|
export type ReflectorOperation = OperationObject & {
|
|
8
9
|
apiMethod: ApiType;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-reflector",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.15",
|
|
4
4
|
"description": "Reflects zod types from openAPI schemas",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -26,7 +26,14 @@
|
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^24.8.1",
|
|
29
|
-
"prettier": "^3.6.2",
|
|
30
29
|
"typescript": "^5.9.3"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"prettier": "^3.0.0"
|
|
33
|
+
},
|
|
34
|
+
"peerDependenciesMeta": {
|
|
35
|
+
"prettier": {
|
|
36
|
+
"optional": false
|
|
37
|
+
}
|
|
31
38
|
}
|
|
32
39
|
}
|