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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # Svelte Reflector
2
2
 
3
- **Turn your OpenAPI into a firstclass Svelte 5 DX.**
3
+ **Turn your OpenAPI into a first-class Svelte 5 DX.**
4
4
 
5
- Svelte Reflector is a **developerexperiencefirst code generator** that converts OpenAPI specs into fully typed, reactive Svelte 5 modules — ready for production, forms included.
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
  [![npm version](https://img.shields.io/npm/v/svelte-reflector.svg)](https://www.npmjs.com/package/svelte-reflector)
8
8
  [![npm downloads](https://img.shields.io/npm/dm/svelte-reflector.svg)](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
- ## 🚀 Features
15
+ ## Features
16
16
 
17
- - **🔮 Automatic Type Generation** - Generates TypeScript interfaces and classes from OpenAPI schemas
18
- - **⚡ Svelte 5 Runes Integration** - Uses `$state` 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
- - **🔌 OpenAPI/Swagger Compatible** - Works with any backend that exposes OpenAPI specs
22
- - **🧪 Development Mode** - Smart regeneration based on environment
23
- - **✅ Validation Ready** - Built-in support for custom field validators
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
- ## 📦 Installation
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
- ## 🏁 Quick Start
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
- onSuccess: (response) => console.log(response),
103
- onError: (error) => console.error(error),
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
- ## 📁 Generated Structure
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
- ## 🧩 Generated Module API
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` | `QueryParams` | Query parameter state |
140
- | `headers` | `HeaderParams` | Header state |
141
- | `paths` | `PathParams` | Path parameter state |
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<ResponseType>): Promise<T[]>
154
+ async listAll(params?: { behavior?: Behavior }): Promise<T[]>
148
155
 
149
156
  // Get single entity (GET without page parameter)
150
- async get(behavior?: Behavior<ResponseType>): Promise<T>
157
+ async get(params?: { behavior?: Behavior }): Promise<T>
151
158
 
152
159
  // Create/Update (POST/PUT/PATCH)
153
- async create(behavior?: Behavior<ResponseType>): Promise<T>
154
- async update(behavior?: Behavior<ResponseType>): Promise<T>
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<ResponseType>): Promise<void>
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
- ## ⚙️ Configuration
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` | | Backend API URL |
173
- | `PUBLIC_BACKEND` | | Alternative to BACKEND_URL |
174
- | `ENVIRONMENT` | | DEV/PROD (defaults to PROD) |
175
- | `VITE_ENVIRONMENT` | | Vite-specific env var |
176
- | `NODE_ENV` | | Node environment |
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
- onSuccess: (user) => console.log("Created:", user),
191
- onError: (err) => console.error("Failed:", err),
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
- interface BuildedInput<T> {
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
- ## 🔧 TypeScript Configuration
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
- ## 🔄 Workflow
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
- ## 🛠️ Advanced Usage
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
- // Brazilian phone validation
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
- ## 🐛 Troubleshooting
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
- ## 📄 License
501
+ ## License
455
502
 
456
503
  MIT License - see [LICENSE](LICENSE) for details.
457
504
 
458
- ## 🤝 Contributing
505
+ ## Contributing
459
506
 
460
507
  Contributions are welcome! Please feel free to submit a Pull Request.
461
508
 
462
- ## 🔗 Links
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 🦍 by the Pináculo Digital team.
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
- const parsedError = JSON.parse((e as Error).message) as ApiErrorResponse;
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;
@@ -60,7 +60,7 @@ export class ModuleClassBuilder {
60
60
  });
61
61
  const constructorBuild = `
62
62
  constructor() {
63
- setQueryGroupAndReturnQueryBuilders([
63
+ setQueryGroup([
64
64
  ${queryGroupValues.join(",\n ")}
65
65
  ]);
66
66
  }
@@ -6,7 +6,7 @@ export class ModuleImports {
6
6
  mockedImports;
7
7
  constructor() {
8
8
  this.imports = new Set([
9
- "// AUTO GERADO. QUEM ALTERAR GOSTA DE RAPAZES!\n",
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("setQueryGroupAndReturnQueryBuilders");
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 !== "setQueryGroupAndReturnQueryBuilders");
56
- const hasSetQueryGroup = imports.includes("setQueryGroupAndReturnQueryBuilders");
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 += `, setQueryGroupAndReturnQueryBuilders`;
59
+ result += `, setQueryGroup`;
60
60
  }
61
61
  result += ` } from "$reflector/reflector.svelte";`;
62
62
  return result;
package/dist/file.d.ts CHANGED
@@ -7,6 +7,6 @@ export declare class Source {
7
7
  });
8
8
  save(): Promise<void>;
9
9
  safeSave(): Promise<void>;
10
- changeData(data: string): Promise<void>;
10
+ changeData(data: string): void;
11
11
  buildPath(endpoint: string[]): string | undefined;
12
12
  }
package/dist/file.js CHANGED
@@ -16,7 +16,7 @@ export class Source {
16
16
  async safeSave() {
17
17
  writeFileSync(this.path, this.data, "utf8");
18
18
  }
19
- async changeData(data) {
19
+ changeData(data) {
20
20
  this.data = data;
21
21
  }
22
22
  buildPath(endpoint) {
@@ -1,5 +1,4 @@
1
- // src/generate-doc.ts
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,6 +1,6 @@
1
- type LooseValidatorField = {
1
+ interface LooseValidatorField {
2
2
  fields: string[];
3
3
  validator: string;
4
- };
4
+ }
5
5
  export declare function parseValidatorFieldsFromConfig(code: string): LooseValidatorField[];
6
6
  export {};
@@ -72,7 +72,6 @@ export function parseValidatorFieldsFromConfig(code) {
72
72
  if (sm[1])
73
73
  fields.push(sm[1]);
74
74
  }
75
- // ✅ mantém o caminho inteiro (ex: validateInputs.email)
76
75
  results.push({ fields, validator: validatorRaw });
77
76
  }
78
77
  return results;
@@ -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;
@@ -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("-")
@@ -1,7 +1,7 @@
1
1
  export class ReflectorInput {
2
2
  password = `z
3
3
  .string()
4
- .regex(/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,}$/, {
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
@@ -26,7 +26,7 @@ export declare class Reflector {
26
26
  });
27
27
  private getSchemas;
28
28
  private getModules;
29
- build(): {};
30
- localSave(data: OpenAPIObject): void;
29
+ build(): Promise<{}>;
30
+ localSave(data: OpenAPIObject): Promise<void>;
31
31
  private clearSrc;
32
32
  }
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
- this.mockedParamsFile.save();
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("./request.js").ReflectorRequestType;
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 fileName = this.path.split("/").slice(-2).join("-");
101
- const inPath = path.join(generatedDir, this.path);
102
- const outPath = path.join(inPath, `${fileName.toLowerCase()}.module.svelte.ts`);
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 setQueryGroupAndReturnQueryBuilders(group: QuerySeiLa[]) {
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
 
@@ -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.13",
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
  }