svelte-reflector 2.1.3 → 2.1.5
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/dist/core/generators/queryOverride.d.ts +1 -2
- package/dist/core/generators/queryOverride.js +2 -5
- package/dist/core/method/MethodRequestAnalyzer.js +8 -3
- package/dist/core/module/ModuleClassBuilder.js +5 -2
- package/dist/core/schema/SchemaPropertyClassifier.js +14 -9
- package/dist/helpers/helpers.d.ts +4 -0
- package/dist/helpers/helpers.js +9 -0
- package/dist/props/array.property.js +11 -9
- package/dist/runtime/reflector.svelte.ts +27 -2
- package/package.json +1 -1
|
@@ -2,8 +2,7 @@ import type { AttributeProp } from "../../types/types.js";
|
|
|
2
2
|
/** TS type literal for a single query override entry. Mirrors the
|
|
3
3
|
* shape produced by each Prop's bundle entry:
|
|
4
4
|
* PrimitiveProp / EnumProp → `string | null`
|
|
5
|
-
* ArrayProp (enum)
|
|
6
|
-
* ArrayProp (non-enum, raro) → `string[]`
|
|
5
|
+
* ArrayProp (enum or primitive) → `${type}[]`
|
|
7
6
|
*/
|
|
8
7
|
export declare function queryOverrideEntryType(q: AttributeProp): string;
|
|
9
8
|
/** Inline TS object type literal for the full queryOverride bag,
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
/** TS type literal for a single query override entry. Mirrors the
|
|
2
2
|
* shape produced by each Prop's bundle entry:
|
|
3
3
|
* PrimitiveProp / EnumProp → `string | null`
|
|
4
|
-
* ArrayProp (enum)
|
|
5
|
-
* ArrayProp (non-enum, raro) → `string[]`
|
|
4
|
+
* ArrayProp (enum or primitive) → `${type}[]`
|
|
6
5
|
*/
|
|
7
6
|
export function queryOverrideEntryType(q) {
|
|
8
|
-
if ("isEnum" in q && q.isEnum)
|
|
9
|
-
return `${q.type}[]`;
|
|
10
7
|
if (!("rawType" in q) && !("enumName" in q))
|
|
11
|
-
return
|
|
8
|
+
return `${q.type}[]`;
|
|
12
9
|
return "string | null";
|
|
13
10
|
}
|
|
14
11
|
/** Inline TS object type literal for the full queryOverride bag,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PrimitiveProp as PrimitivePropClass } from "../../props/primitive.property.js";
|
|
2
2
|
import { ArrayProp as ArrayPropClass } from "../../props/array.property.js";
|
|
3
3
|
import { EnumProp as EnumPropClass } from "../../props/enum.property.js";
|
|
4
|
-
import { isReferenceObject } from "../../helpers/helpers.js";
|
|
4
|
+
import { isReferenceObject, isPrimitiveEnumValues } from "../../helpers/helpers.js";
|
|
5
5
|
export class MethodRequestAnalyzer {
|
|
6
6
|
paths = [];
|
|
7
7
|
headers = [];
|
|
@@ -49,8 +49,13 @@ export class MethodRequestAnalyzer {
|
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
if (schema.enum) {
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
if (isPrimitiveEnumValues(schema.enum)) {
|
|
53
|
+
console.warn(`[reflector] Field '${moduleName}.${name}': enum=[${schema.enum.join(",")}] looks like a TS primitive type (string/number/boolean), not a real enum. Ignoring 'enum' and treating as plain primitive. Fix the @ApiProperty/@ApiQuery in the back.`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this.querys.push(new EnumPropClass({ name, required: isRequired, enums: schema.enum, isParam: true, entityName: moduleName, context }));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
54
59
|
}
|
|
55
60
|
this.querys.push(new PrimitivePropClass({ name, required: isRequired, schemaObject: schema, validator: undefined, isParam: true }));
|
|
56
61
|
}
|
|
@@ -45,9 +45,12 @@ export class ModuleClassBuilder {
|
|
|
45
45
|
bundle.push(prop.bundleBuild());
|
|
46
46
|
}
|
|
47
47
|
else {
|
|
48
|
-
// ArrayProp (não-enum)
|
|
48
|
+
// ArrayProp (não-enum): emits EnumQueryBuilder<primitive>; só importa
|
|
49
|
+
// enum quando o array é realmente de enum.
|
|
49
50
|
attributes.push(prop.queryBuild());
|
|
50
|
-
|
|
51
|
+
if ("isEnum" in prop && prop.isEnum) {
|
|
52
|
+
this.imports.addEnumImport(prop.type);
|
|
53
|
+
}
|
|
51
54
|
bundle.push(prop.queryBundleBuild());
|
|
52
55
|
this.imports.addReflectorImport("EnumQueryBuilder");
|
|
53
56
|
}
|
|
@@ -2,7 +2,7 @@ import { ArrayProp } from "../../props/array.property.js";
|
|
|
2
2
|
import { EnumProp } from "../../props/enum.property.js";
|
|
3
3
|
import { ObjectProp } from "../../props/object.property.js";
|
|
4
4
|
import { PrimitiveProp } from "../../props/primitive.property.js";
|
|
5
|
-
import { isReferenceObject } from "../../helpers/helpers.js";
|
|
5
|
+
import { isReferenceObject, isPrimitiveEnumValues } from "../../helpers/helpers.js";
|
|
6
6
|
export class SchemaPropertyClassifier {
|
|
7
7
|
static classify(params) {
|
|
8
8
|
const { key, value, requireds, fieldConfigs, schemaName, context } = params;
|
|
@@ -37,14 +37,19 @@ export class SchemaPropertyClassifier {
|
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
if (value.enum) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
if (isPrimitiveEnumValues(value.enum)) {
|
|
41
|
+
console.warn(`[reflector] Field '${schemaName}.${key}': enum=[${value.enum.join(",")}] looks like a TS primitive type (string/number/boolean), not a real enum. Ignoring 'enum' and treating as plain primitive. Fix the @ApiProperty/@ApiQuery in the back.`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
return new EnumProp({
|
|
45
|
+
enums: value.enum,
|
|
46
|
+
name: key,
|
|
47
|
+
required,
|
|
48
|
+
isParam: undefined,
|
|
49
|
+
entityName: schemaName,
|
|
50
|
+
context,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
48
53
|
}
|
|
49
54
|
const config = fieldConfigs.get(key);
|
|
50
55
|
const validator = config?.validator;
|
|
@@ -15,5 +15,9 @@ export declare function getEndpointAndModuleName(rawEndpoint: string): {
|
|
|
15
15
|
};
|
|
16
16
|
export declare function getEndpoint(rawEndpoint: string): string;
|
|
17
17
|
export declare function getFullEndpoint(rawEndpoint: string): string;
|
|
18
|
+
/** True if every enum value is a TS-reserved primitive type name
|
|
19
|
+
* (`"string"`, `"number"`, `"boolean"`) — a sign of misused
|
|
20
|
+
* `@ApiProperty({ enum: String })` on the back. */
|
|
21
|
+
export declare function isPrimitiveEnumValues(enums: unknown[] | undefined): boolean;
|
|
18
22
|
export declare function isEnumSchema(schema: SchemaObject): boolean;
|
|
19
23
|
export declare function isReferenceObject(obj: unknown): obj is ReferenceObject;
|
package/dist/helpers/helpers.js
CHANGED
|
@@ -88,6 +88,15 @@ export function getFullEndpoint(rawEndpoint) {
|
|
|
88
88
|
})
|
|
89
89
|
.join("/");
|
|
90
90
|
}
|
|
91
|
+
const TS_PRIMITIVE_RESERVED = new Set(["string", "number", "integer", "boolean"]);
|
|
92
|
+
/** True if every enum value is a TS-reserved primitive type name
|
|
93
|
+
* (`"string"`, `"number"`, `"boolean"`) — a sign of misused
|
|
94
|
+
* `@ApiProperty({ enum: String })` on the back. */
|
|
95
|
+
export function isPrimitiveEnumValues(enums) {
|
|
96
|
+
if (!enums || enums.length === 0)
|
|
97
|
+
return false;
|
|
98
|
+
return enums.every((e) => typeof e === "string" && TS_PRIMITIVE_RESERVED.has(e.toLowerCase()));
|
|
99
|
+
}
|
|
91
100
|
export function isEnumSchema(schema) {
|
|
92
101
|
if (schema.enum)
|
|
93
102
|
return true;
|
|
@@ -47,6 +47,11 @@ export class ArrayProp {
|
|
|
47
47
|
return theType;
|
|
48
48
|
}
|
|
49
49
|
this._isPrimitiveType = true;
|
|
50
|
+
const itemType = items.type;
|
|
51
|
+
if (itemType === "integer")
|
|
52
|
+
return "number";
|
|
53
|
+
if (itemType === "number" || itemType === "boolean")
|
|
54
|
+
return itemType;
|
|
50
55
|
return "string";
|
|
51
56
|
}
|
|
52
57
|
constructorBuild() {
|
|
@@ -83,16 +88,13 @@ export class ArrayProp {
|
|
|
83
88
|
return `${this.name}: this.${this.name}?.values`;
|
|
84
89
|
}
|
|
85
90
|
queryBuild() {
|
|
86
|
-
if (this.
|
|
87
|
-
|
|
88
|
-
return `readonly ${this.name} = new EnumQueryBuilder<${this.type}>({ key: '${this.name}' })`;
|
|
89
|
-
}
|
|
90
|
-
const literal = `[${this.defaultValues
|
|
91
|
-
.map((v) => (typeof v === "string" ? `'${v}'` : String(v)))
|
|
92
|
-
.join(", ")}]`;
|
|
93
|
-
return `readonly ${this.name} = new EnumQueryBuilder<${this.type}>({ key: '${this.name}', defaultValues: ${literal} })`;
|
|
91
|
+
if (this.defaultValues.length === 0) {
|
|
92
|
+
return `readonly ${this.name} = new EnumQueryBuilder<${this.type}>({ key: '${this.name}', defaultValues: [] })`;
|
|
94
93
|
}
|
|
95
|
-
|
|
94
|
+
const literal = `[${this.defaultValues
|
|
95
|
+
.map((v) => (typeof v === "string" ? `'${v}'` : String(v)))
|
|
96
|
+
.join(", ")}]`;
|
|
97
|
+
return `readonly ${this.name} = new EnumQueryBuilder<${this.type}>({ key: '${this.name}', defaultValues: ${literal} })`;
|
|
96
98
|
}
|
|
97
99
|
staticBuild() {
|
|
98
100
|
const result = this._isPrimitiveType ? "obj" : `new ${this.type}({ data: obj })`;
|
|
@@ -158,10 +158,18 @@ export function genericArrayBundler<T extends { bundle: () => BundleResult<T> }>
|
|
|
158
158
|
return (data as T[]).map((item) => item.bundle());
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Atualiza um query param na URL.
|
|
163
|
+
* - `""` (string vazia) → remove o param.
|
|
164
|
+
* - qualquer outro valor → `searchParams.set(key, String(event))`.
|
|
165
|
+
*/
|
|
161
166
|
export function changeParam({ event, key }: QueryContract) {
|
|
162
|
-
const newValue = event;
|
|
163
167
|
const url = new SvelteURL(page.url);
|
|
164
|
-
|
|
168
|
+
if (event === "") {
|
|
169
|
+
url.searchParams.delete(key);
|
|
170
|
+
} else {
|
|
171
|
+
url.searchParams.set(key, String(event));
|
|
172
|
+
}
|
|
165
173
|
goto(url, { replaceState: true, keepFocus: true });
|
|
166
174
|
}
|
|
167
175
|
|
|
@@ -190,12 +198,24 @@ export class QueryBuilder {
|
|
|
190
198
|
return fromUrl !== null ? fromUrl : this.defaultValue;
|
|
191
199
|
}
|
|
192
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Aplica o valor recebido ao query param.
|
|
203
|
+
* - `null` / `undefined` → no-op (não chama `goto`).
|
|
204
|
+
* - `""` (string vazia) → delega pra `changeParam`, que remove o param.
|
|
205
|
+
* - número / string não-vazia → `set(key, String(event))`.
|
|
206
|
+
*/
|
|
193
207
|
update(event: string | number | null) {
|
|
194
208
|
if (event === null || event === undefined) return;
|
|
195
209
|
return changeParam({ key: this.key, event: String(event) });
|
|
196
210
|
}
|
|
197
211
|
}
|
|
198
212
|
|
|
213
|
+
/**
|
|
214
|
+
* Atualiza vários query params de uma vez.
|
|
215
|
+
* - array → `delete(key)` seguido de `append` para cada item.
|
|
216
|
+
* - `""` → remove o param.
|
|
217
|
+
* - outros valores → `set(key, String(value))`.
|
|
218
|
+
*/
|
|
199
219
|
export function setQueryGroup(group: QueryWithArrayType[]) {
|
|
200
220
|
if (!browser) return;
|
|
201
221
|
|
|
@@ -210,6 +230,11 @@ export function setQueryGroup(group: QueryWithArrayType[]) {
|
|
|
210
230
|
continue;
|
|
211
231
|
}
|
|
212
232
|
|
|
233
|
+
if (value === "") {
|
|
234
|
+
url.searchParams.delete(key);
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
|
|
213
238
|
url.searchParams.set(key, String(value));
|
|
214
239
|
}
|
|
215
240
|
|