mulink 1.1.8 → 1.2.0
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 +2 -2
- package/dist/.tsbuildinfo +1 -1
- package/dist/lib/{chunk-AHGDKSOY.js → chunk-BMHPB646.js} +495 -252
- package/dist/lib/chunk-BMHPB646.js.map +1 -0
- package/dist/lib/{chunk-SSMOIVFN.cjs → chunk-IAS3P4RF.cjs} +495 -252
- package/dist/lib/chunk-IAS3P4RF.cjs.map +1 -0
- package/dist/lib/cli.cjs +57 -29
- package/dist/lib/cli.cjs.map +1 -1
- package/dist/lib/cli.js +42 -14
- package/dist/lib/cli.js.map +1 -1
- package/dist/lib/client.cjs +20 -20
- package/dist/lib/client.cjs.map +1 -1
- package/dist/lib/client.d.cts +4 -4
- package/dist/lib/client.d.ts +4 -4
- package/dist/lib/client.js +4 -4
- package/dist/lib/client.js.map +1 -1
- package/dist/lib/index.cjs +177 -15
- package/dist/lib/index.cjs.map +1 -1
- package/dist/lib/index.d.cts +211 -3
- package/dist/lib/index.d.ts +211 -3
- package/dist/lib/index.js +153 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/{version-checker-uF6o5ziX.d.cts → version-checker-DU88tpi8.d.cts} +152 -12
- package/dist/lib/{version-checker-uF6o5ziX.d.ts → version-checker-DU88tpi8.d.ts} +152 -12
- package/package.json +2 -2
- package/dist/lib/chunk-AHGDKSOY.js.map +0 -1
- package/dist/lib/chunk-SSMOIVFN.cjs.map +0 -1
|
@@ -7,17 +7,48 @@ var __defProp = Object.defineProperty;
|
|
|
7
7
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
8
|
|
|
9
9
|
// src/core/types.ts
|
|
10
|
-
var BridgeError = class extends Error {
|
|
10
|
+
var BridgeError = class _BridgeError extends Error {
|
|
11
11
|
static {
|
|
12
12
|
__name(this, "BridgeError");
|
|
13
13
|
}
|
|
14
14
|
code;
|
|
15
15
|
details;
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
timestamp;
|
|
17
|
+
cause;
|
|
18
|
+
constructor(message, code, details, cause) {
|
|
19
|
+
super(message, { cause });
|
|
18
20
|
this.name = "BridgeError";
|
|
19
21
|
this.code = code;
|
|
20
22
|
this.details = details;
|
|
23
|
+
this.timestamp = Date.now();
|
|
24
|
+
this.cause = cause;
|
|
25
|
+
if (Error.captureStackTrace) {
|
|
26
|
+
Error.captureStackTrace(this, _BridgeError);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Converts the error to a JSON-serializable object
|
|
31
|
+
*
|
|
32
|
+
* @returns JSON representation of the error
|
|
33
|
+
*/
|
|
34
|
+
toJSON() {
|
|
35
|
+
return {
|
|
36
|
+
name: this.name,
|
|
37
|
+
message: this.message,
|
|
38
|
+
code: this.code,
|
|
39
|
+
details: this.details,
|
|
40
|
+
timestamp: this.timestamp,
|
|
41
|
+
stack: this.stack,
|
|
42
|
+
cause: this.cause?.message
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Checks if this error is retryable
|
|
47
|
+
*
|
|
48
|
+
* @returns True if the operation that caused this error can be retried
|
|
49
|
+
*/
|
|
50
|
+
isRetryable() {
|
|
51
|
+
return false;
|
|
21
52
|
}
|
|
22
53
|
};
|
|
23
54
|
var ValidationError = class extends BridgeError {
|
|
@@ -25,28 +56,42 @@ var ValidationError = class extends BridgeError {
|
|
|
25
56
|
__name(this, "ValidationError");
|
|
26
57
|
}
|
|
27
58
|
errors;
|
|
28
|
-
constructor(message, errors) {
|
|
29
|
-
super(message, "VALIDATION_ERROR", errors);
|
|
59
|
+
constructor(message, errors, cause) {
|
|
60
|
+
super(message, "VALIDATION_ERROR", errors, cause);
|
|
30
61
|
this.errors = errors;
|
|
31
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Gets formatted validation error messages
|
|
65
|
+
*
|
|
66
|
+
* @returns Array of formatted error messages
|
|
67
|
+
*/
|
|
68
|
+
getFormattedErrors() {
|
|
69
|
+
return this.errors.errors.map((err) => {
|
|
70
|
+
const path3 = err.path.join(".");
|
|
71
|
+
return `${path3}: ${err.message}`;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
32
74
|
};
|
|
33
75
|
var SchemaParseError = class extends BridgeError {
|
|
34
76
|
static {
|
|
35
77
|
__name(this, "SchemaParseError");
|
|
36
78
|
}
|
|
37
79
|
schemaUrl;
|
|
38
|
-
constructor(message, schemaUrl) {
|
|
39
|
-
super(message, "SCHEMA_PARSE_ERROR", { schemaUrl });
|
|
80
|
+
constructor(message, schemaUrl, cause) {
|
|
81
|
+
super(message, "SCHEMA_PARSE_ERROR", { schemaUrl }, cause);
|
|
40
82
|
this.schemaUrl = schemaUrl;
|
|
41
83
|
}
|
|
84
|
+
isRetryable() {
|
|
85
|
+
return this.cause instanceof TypeError && this.cause.message.includes("fetch");
|
|
86
|
+
}
|
|
42
87
|
};
|
|
43
88
|
var GenerationError = class extends BridgeError {
|
|
44
89
|
static {
|
|
45
90
|
__name(this, "GenerationError");
|
|
46
91
|
}
|
|
47
92
|
file;
|
|
48
|
-
constructor(message, file) {
|
|
49
|
-
super(message, "GENERATION_ERROR", { file });
|
|
93
|
+
constructor(message, file, cause) {
|
|
94
|
+
super(message, "GENERATION_ERROR", { file }, cause);
|
|
50
95
|
this.file = file;
|
|
51
96
|
}
|
|
52
97
|
};
|
|
@@ -134,8 +179,8 @@ var BridgeLogger = class {
|
|
|
134
179
|
if (!this.options.colors || !process.stdout.isTTY) {
|
|
135
180
|
console.log(message);
|
|
136
181
|
return {
|
|
137
|
-
succeed: /* @__PURE__ */ __name((msg) => console.log(colorize(`\u2713 ${msg
|
|
138
|
-
fail: /* @__PURE__ */ __name((msg) => console.error(colorize(`\u2717 ${msg
|
|
182
|
+
succeed: /* @__PURE__ */ __name((msg) => console.log(colorize(`\u2713 ${msg ?? message}`, "green")), "succeed"),
|
|
183
|
+
fail: /* @__PURE__ */ __name((msg) => console.error(colorize(`\u2717 ${msg ?? message}`, "red")), "fail"),
|
|
139
184
|
stop: /* @__PURE__ */ __name(() => {
|
|
140
185
|
}, "stop")
|
|
141
186
|
};
|
|
@@ -143,17 +188,20 @@ var BridgeLogger = class {
|
|
|
143
188
|
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
144
189
|
let i = 0;
|
|
145
190
|
const interval = setInterval(() => {
|
|
146
|
-
|
|
191
|
+
const frame = frames[i++ % frames.length];
|
|
192
|
+
if (frame) {
|
|
193
|
+
process.stdout.write(`\r${colorize(frame, "cyan")} ${message}`);
|
|
194
|
+
}
|
|
147
195
|
}, 100);
|
|
148
196
|
return {
|
|
149
197
|
succeed: /* @__PURE__ */ __name((msg) => {
|
|
150
198
|
clearInterval(interval);
|
|
151
|
-
process.stdout.write(`\r${colorize("\u2713", "green")} ${msg
|
|
199
|
+
process.stdout.write(`\r${colorize("\u2713", "green")} ${msg ?? message}
|
|
152
200
|
`);
|
|
153
201
|
}, "succeed"),
|
|
154
202
|
fail: /* @__PURE__ */ __name((msg) => {
|
|
155
203
|
clearInterval(interval);
|
|
156
|
-
process.stdout.write(`\r${colorize("\u2717", "red")} ${msg
|
|
204
|
+
process.stdout.write(`\r${colorize("\u2717", "red")} ${msg ?? message}
|
|
157
205
|
`);
|
|
158
206
|
}, "fail"),
|
|
159
207
|
stop: /* @__PURE__ */ __name(() => {
|
|
@@ -176,7 +224,7 @@ var VersionChecker = class {
|
|
|
176
224
|
constructor(packageName, currentVersion, logger) {
|
|
177
225
|
this.packageName = packageName;
|
|
178
226
|
this.currentVersion = currentVersion;
|
|
179
|
-
this.logger = logger
|
|
227
|
+
this.logger = logger ?? new BridgeLogger({ prefix: "\u{1F50D} Version Check" });
|
|
180
228
|
}
|
|
181
229
|
/**
|
|
182
230
|
* Check if a new version is available
|
|
@@ -231,7 +279,7 @@ var VersionChecker = class {
|
|
|
231
279
|
/**
|
|
232
280
|
* Get the appropriate upgrade command for the detected package manager
|
|
233
281
|
*/
|
|
234
|
-
getUpgradeCommand(
|
|
282
|
+
getUpgradeCommand(_versionInfo) {
|
|
235
283
|
const packageManager = this.detectPackageManager();
|
|
236
284
|
switch (packageManager) {
|
|
237
285
|
case "yarn":
|
|
@@ -305,8 +353,8 @@ var VersionChecker = class {
|
|
|
305
353
|
const currentParts = this.parseVersion(current);
|
|
306
354
|
const latestParts = this.parseVersion(latest);
|
|
307
355
|
for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
|
|
308
|
-
const currentPart = currentParts[i]
|
|
309
|
-
const latestPart = latestParts[i]
|
|
356
|
+
const currentPart = currentParts[i] ?? 0;
|
|
357
|
+
const latestPart = latestParts[i] ?? 0;
|
|
310
358
|
if (latestPart > currentPart) {
|
|
311
359
|
return true;
|
|
312
360
|
} else if (latestPart < currentPart) {
|
|
@@ -380,7 +428,7 @@ function createBridgeVersionChecker(logger) {
|
|
|
380
428
|
if (existsSync(pkgPath)) {
|
|
381
429
|
const pkgRaw = readFileSync(pkgPath, { encoding: "utf-8" });
|
|
382
430
|
const pkg = JSON.parse(pkgRaw);
|
|
383
|
-
if (pkg
|
|
431
|
+
if (pkg.version) {
|
|
384
432
|
currentVersion = pkg.version;
|
|
385
433
|
}
|
|
386
434
|
} else {
|
|
@@ -388,13 +436,13 @@ function createBridgeVersionChecker(logger) {
|
|
|
388
436
|
if (existsSync(cwdPkg)) {
|
|
389
437
|
const pkgRaw = readFileSync(cwdPkg, { encoding: "utf-8" });
|
|
390
438
|
const pkg = JSON.parse(pkgRaw);
|
|
391
|
-
if (pkg
|
|
439
|
+
if (pkg.version) {
|
|
392
440
|
currentVersion = pkg.version;
|
|
393
441
|
}
|
|
394
442
|
}
|
|
395
443
|
}
|
|
396
444
|
} catch (err) {
|
|
397
|
-
const l = logger
|
|
445
|
+
const l = logger ?? new BridgeLogger({ prefix: "\u{1F50D} Version Check" });
|
|
398
446
|
l.debug("Failed to read package.json for current version, falling back to default", err);
|
|
399
447
|
}
|
|
400
448
|
return new VersionChecker(packageName, currentVersion, logger);
|
|
@@ -432,7 +480,7 @@ var OpenApiSchemaParser = class {
|
|
|
432
480
|
async fetchSchema(schemaUrl) {
|
|
433
481
|
const versionChecker = createBridgeVersionChecker();
|
|
434
482
|
const currentVersion = versionChecker.getCurrentVersion();
|
|
435
|
-
if (!schemaUrl
|
|
483
|
+
if (!schemaUrl.trim()) {
|
|
436
484
|
throw new SchemaParseError("Schema URL is required and cannot be empty", schemaUrl);
|
|
437
485
|
}
|
|
438
486
|
if (schemaUrl.startsWith("http")) {
|
|
@@ -453,7 +501,7 @@ var OpenApiSchemaParser = class {
|
|
|
453
501
|
schemaUrl
|
|
454
502
|
);
|
|
455
503
|
}
|
|
456
|
-
const contentType = response.headers.get("content-type")
|
|
504
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
457
505
|
if (!contentType.includes("application/json") && !contentType.includes("application/yaml") && !contentType.includes("text/yaml")) {
|
|
458
506
|
throw new SchemaParseError(
|
|
459
507
|
`Unsupported content type: ${contentType}. Expected JSON or YAML.`,
|
|
@@ -483,10 +531,10 @@ var OpenApiSchemaParser = class {
|
|
|
483
531
|
);
|
|
484
532
|
}
|
|
485
533
|
}
|
|
486
|
-
|
|
534
|
+
parseDocument(document) {
|
|
487
535
|
const version = this.detectVersion(document);
|
|
488
536
|
const normalizedDocument = this.normalizeDocument(document, version);
|
|
489
|
-
return {
|
|
537
|
+
return Promise.resolve({
|
|
490
538
|
version,
|
|
491
539
|
document: normalizedDocument,
|
|
492
540
|
openApiSpec: normalizedDocument,
|
|
@@ -495,7 +543,7 @@ var OpenApiSchemaParser = class {
|
|
|
495
543
|
security: this.extractSecurity(normalizedDocument),
|
|
496
544
|
servers: this.extractServers(normalizedDocument, document),
|
|
497
545
|
metadata: this.extractMetadata(normalizedDocument)
|
|
498
|
-
};
|
|
546
|
+
});
|
|
499
547
|
}
|
|
500
548
|
detectVersion(document) {
|
|
501
549
|
if (!document || typeof document !== "object") {
|
|
@@ -530,7 +578,7 @@ var OpenApiSchemaParser = class {
|
|
|
530
578
|
info: v2Doc.info,
|
|
531
579
|
servers: v2Doc.host ? [
|
|
532
580
|
{
|
|
533
|
-
url: `${v2Doc.schemes?.[0]
|
|
581
|
+
url: `${v2Doc.schemes?.[0] ?? "https"}://${v2Doc.host}${v2Doc.basePath ?? ""}`
|
|
534
582
|
}
|
|
535
583
|
] : [],
|
|
536
584
|
paths: {},
|
|
@@ -675,20 +723,20 @@ var OpenApiSchemaParser = class {
|
|
|
675
723
|
flows: {
|
|
676
724
|
implicit: v2Scheme.flow === "implicit" ? {
|
|
677
725
|
authorizationUrl: v2Scheme.authorizationUrl,
|
|
678
|
-
scopes: v2Scheme.scopes
|
|
726
|
+
scopes: v2Scheme.scopes ?? {}
|
|
679
727
|
} : void 0,
|
|
680
728
|
password: v2Scheme.flow === "password" ? {
|
|
681
729
|
tokenUrl: v2Scheme.tokenUrl,
|
|
682
|
-
scopes: v2Scheme.scopes
|
|
730
|
+
scopes: v2Scheme.scopes ?? {}
|
|
683
731
|
} : void 0,
|
|
684
732
|
clientCredentials: v2Scheme.flow === "application" ? {
|
|
685
733
|
tokenUrl: v2Scheme.tokenUrl,
|
|
686
|
-
scopes: v2Scheme.scopes
|
|
734
|
+
scopes: v2Scheme.scopes ?? {}
|
|
687
735
|
} : void 0,
|
|
688
736
|
authorizationCode: v2Scheme.flow === "accessCode" ? {
|
|
689
737
|
authorizationUrl: v2Scheme.authorizationUrl,
|
|
690
738
|
tokenUrl: v2Scheme.tokenUrl,
|
|
691
|
-
scopes: v2Scheme.scopes
|
|
739
|
+
scopes: v2Scheme.scopes ?? {}
|
|
692
740
|
} : void 0
|
|
693
741
|
}
|
|
694
742
|
};
|
|
@@ -714,18 +762,18 @@ var OpenApiSchemaParser = class {
|
|
|
714
762
|
const operation = pathItem[method.toLowerCase()];
|
|
715
763
|
if (!operation) continue;
|
|
716
764
|
const endpoint = {
|
|
717
|
-
id: operation.operationId
|
|
765
|
+
id: operation.operationId ?? `${method.toLowerCase()}_${path3.replace(/[^a-zA-Z0-9]/g, "_")}`,
|
|
718
766
|
path: path3,
|
|
719
767
|
method,
|
|
720
768
|
operationId: operation.operationId,
|
|
721
769
|
summary: operation.summary,
|
|
722
770
|
description: operation.description,
|
|
723
|
-
tags: operation.tags
|
|
771
|
+
tags: operation.tags ?? [],
|
|
724
772
|
parameters: this.extractParameters(operation.parameters, pathItem.parameters, document),
|
|
725
773
|
requestBody: this.extractRequestBody(operation.requestBody, document),
|
|
726
774
|
responses: this.extractResponses(operation.responses, document),
|
|
727
|
-
security: operation.security
|
|
728
|
-
deprecated: operation.deprecated
|
|
775
|
+
security: operation.security ?? [],
|
|
776
|
+
deprecated: operation.deprecated ?? false,
|
|
729
777
|
metadata: this.extractEndpointMetadata(operation)
|
|
730
778
|
};
|
|
731
779
|
endpoints.push(endpoint);
|
|
@@ -735,7 +783,7 @@ var OpenApiSchemaParser = class {
|
|
|
735
783
|
}
|
|
736
784
|
extractParameters(operationParams, pathParams, document) {
|
|
737
785
|
const parameters = [];
|
|
738
|
-
const allParams = [...pathParams
|
|
786
|
+
const allParams = [...pathParams ?? [], ...operationParams ?? []];
|
|
739
787
|
for (const param of allParams) {
|
|
740
788
|
if (!param) continue;
|
|
741
789
|
if ("$ref" in param) {
|
|
@@ -745,11 +793,11 @@ var OpenApiSchemaParser = class {
|
|
|
745
793
|
const parameter = {
|
|
746
794
|
name: param.name,
|
|
747
795
|
in: param.in,
|
|
748
|
-
required: param.required
|
|
796
|
+
required: param.required ?? param.in === "path",
|
|
749
797
|
schema: this.convertSchemaToZod(param.schema, document),
|
|
750
798
|
description: param.description,
|
|
751
799
|
example: param.example,
|
|
752
|
-
deprecated: param.deprecated
|
|
800
|
+
deprecated: param.deprecated ?? false
|
|
753
801
|
};
|
|
754
802
|
parameters.push(parameter);
|
|
755
803
|
}
|
|
@@ -768,7 +816,7 @@ var OpenApiSchemaParser = class {
|
|
|
768
816
|
}
|
|
769
817
|
}
|
|
770
818
|
return {
|
|
771
|
-
required: requestBody.required
|
|
819
|
+
required: requestBody.required ?? false,
|
|
772
820
|
description: requestBody.description,
|
|
773
821
|
content
|
|
774
822
|
};
|
|
@@ -808,7 +856,7 @@ var OpenApiSchemaParser = class {
|
|
|
808
856
|
schema: this.convertSchemaToZod(schema, document),
|
|
809
857
|
description: schema.description,
|
|
810
858
|
example: schema.example,
|
|
811
|
-
deprecated: schema.deprecated
|
|
859
|
+
deprecated: schema.deprecated ?? false
|
|
812
860
|
});
|
|
813
861
|
}
|
|
814
862
|
}
|
|
@@ -842,7 +890,7 @@ var OpenApiSchemaParser = class {
|
|
|
842
890
|
const v2Doc = originalDoc;
|
|
843
891
|
return [
|
|
844
892
|
{
|
|
845
|
-
url: `${v2Doc.schemes?.[0]
|
|
893
|
+
url: `${v2Doc.schemes?.[0] ?? "https"}://${v2Doc.host}${v2Doc.basePath ?? ""}`,
|
|
846
894
|
description: "Converted from Swagger 2.0"
|
|
847
895
|
}
|
|
848
896
|
];
|
|
@@ -862,9 +910,9 @@ var OpenApiSchemaParser = class {
|
|
|
862
910
|
}
|
|
863
911
|
extractEndpointMetadata(operation) {
|
|
864
912
|
return {
|
|
865
|
-
requiresAuth: operation.security
|
|
913
|
+
requiresAuth: (operation.security?.length ?? 0) > 0,
|
|
866
914
|
cacheStrategy: "default",
|
|
867
|
-
revalidationTags: operation.tags
|
|
915
|
+
revalidationTags: operation.tags ?? [],
|
|
868
916
|
streaming: false,
|
|
869
917
|
fileUpload: this.hasFileUpload(operation)
|
|
870
918
|
};
|
|
@@ -872,7 +920,7 @@ var OpenApiSchemaParser = class {
|
|
|
872
920
|
hasFileUpload(operation) {
|
|
873
921
|
if (!operation.requestBody || "$ref" in operation.requestBody) return false;
|
|
874
922
|
const content = operation.requestBody.content;
|
|
875
|
-
return Object.keys(content
|
|
923
|
+
return Object.keys(content ?? {}).some(
|
|
876
924
|
(mediaType) => mediaType.includes("multipart/form-data") || mediaType.includes("application/octet-stream")
|
|
877
925
|
);
|
|
878
926
|
}
|
|
@@ -960,7 +1008,7 @@ var OpenApiSchemaParser = class {
|
|
|
960
1008
|
case "object":
|
|
961
1009
|
if (schema.properties) {
|
|
962
1010
|
const shape = {};
|
|
963
|
-
const required = schema.required
|
|
1011
|
+
const required = schema.required ?? [];
|
|
964
1012
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
965
1013
|
let propZodSchema = this.convertSchemaToZod(propSchema, document);
|
|
966
1014
|
if (!required.includes(propName)) {
|
|
@@ -992,7 +1040,7 @@ var ApiClientGenerator = class {
|
|
|
992
1040
|
* Generate import paths based on configuration
|
|
993
1041
|
*/
|
|
994
1042
|
buildImportPath(relativePath) {
|
|
995
|
-
const outputDirectory = this.configuration.outputDir
|
|
1043
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
996
1044
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
997
1045
|
let importBasePath = outputDirectory;
|
|
998
1046
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -1000,24 +1048,24 @@ var ApiClientGenerator = class {
|
|
|
1000
1048
|
}
|
|
1001
1049
|
return `@/${importBasePath}/${cleanPath}`;
|
|
1002
1050
|
}
|
|
1003
|
-
|
|
1051
|
+
generate(context) {
|
|
1004
1052
|
const { schema } = context;
|
|
1005
1053
|
const generatedFiles = [];
|
|
1006
1054
|
generatedFiles.push(this.generateEnhancedBaseClient());
|
|
1007
1055
|
generatedFiles.push(...this.generateEndpointClients(schema.endpoints));
|
|
1008
1056
|
generatedFiles.push(this.generateMainClient(schema.endpoints));
|
|
1009
1057
|
generatedFiles.push(this.generateClientUtilities());
|
|
1010
|
-
return generatedFiles;
|
|
1058
|
+
return Promise.resolve(generatedFiles);
|
|
1011
1059
|
}
|
|
1012
1060
|
generateEnhancedBaseClient() {
|
|
1013
1061
|
const { api, auth } = this.configuration;
|
|
1014
1062
|
const authUtilsImport = this.buildImportPath("auth/utils");
|
|
1015
|
-
const authPath = auth?.authPath
|
|
1016
|
-
const tokenGetter = auth?.tokenGetter
|
|
1063
|
+
const authPath = auth?.authPath ?? "@/lib/auth";
|
|
1064
|
+
const tokenGetter = auth?.tokenGetter ?? "auth";
|
|
1017
1065
|
const content = `/**
|
|
1018
1066
|
* The HTTP client is automatically created by "mulink"
|
|
1019
1067
|
*
|
|
1020
|
-
* Next.js 16.0.
|
|
1068
|
+
* Next.js 16.0.7 Best Practices:
|
|
1021
1069
|
* - Proper separation of client/server code
|
|
1022
1070
|
* - Dynamic imports for server-only modules
|
|
1023
1071
|
* - Works in both Server Components and Client Components
|
|
@@ -1028,7 +1076,7 @@ import { cache } from 'react'
|
|
|
1028
1076
|
|
|
1029
1077
|
/**
|
|
1030
1078
|
* Server-only modules interface
|
|
1031
|
-
* Next.js 16.0.
|
|
1079
|
+
* Next.js 16.0.7: These modules are only available on the server
|
|
1032
1080
|
* We use dynamic imports to avoid bundling them in the client
|
|
1033
1081
|
*/
|
|
1034
1082
|
type NextHeadersModule = typeof import('next/headers')
|
|
@@ -1052,7 +1100,7 @@ function toMutableHeaders(source: NextReadonlyHeaders) {
|
|
|
1052
1100
|
|
|
1053
1101
|
/**
|
|
1054
1102
|
* Lazy load server-only modules only when needed (server-side)
|
|
1055
|
-
* Next.js 16.0.
|
|
1103
|
+
* Next.js 16.0.7: This ensures server-only code is not bundled in the client
|
|
1056
1104
|
*
|
|
1057
1105
|
* @returns Server-only modules or undefined if on client-side
|
|
1058
1106
|
*/
|
|
@@ -1060,7 +1108,7 @@ async function getServerModules() {
|
|
|
1060
1108
|
if (serverOnlyModules !== null) return serverOnlyModules
|
|
1061
1109
|
|
|
1062
1110
|
// Only attempt to import on server-side
|
|
1063
|
-
// Next.js 16.0.
|
|
1111
|
+
// Next.js 16.0.7: typeof window check ensures we're on the server
|
|
1064
1112
|
if (typeof window === 'undefined') {
|
|
1065
1113
|
try {
|
|
1066
1114
|
const headersModule = await import('next/headers').catch(() => null)
|
|
@@ -1286,11 +1334,11 @@ export class BaseApiClient {
|
|
|
1286
1334
|
private readonly middleware: RequestMiddleware[] = []
|
|
1287
1335
|
|
|
1288
1336
|
constructor() {
|
|
1289
|
-
this.baseUrl = process.env.NEXT_PUBLIC_API_URL || process.env.API_BASE_URL || '${api
|
|
1290
|
-
this.defaultTimeout = ${api
|
|
1291
|
-
this.defaultRetries = ${api
|
|
1292
|
-
this.defaultHeaders = ${JSON.stringify(api
|
|
1293
|
-
this.defaultUserAgent = '${api
|
|
1337
|
+
this.baseUrl = process.env.NEXT_PUBLIC_API_URL || process.env.API_BASE_URL || '${api.baseUrl || "http://localhost:3000/api"}'
|
|
1338
|
+
this.defaultTimeout = ${api.timeout || 3e4}
|
|
1339
|
+
this.defaultRetries = ${api.retries || 3}
|
|
1340
|
+
this.defaultHeaders = ${JSON.stringify(api.headers || {}, null, 6)}
|
|
1341
|
+
this.defaultUserAgent = '${api.userAgent || "Mulink-Client/3.4.5"}'
|
|
1294
1342
|
|
|
1295
1343
|
// Add default middleware
|
|
1296
1344
|
this.addMiddleware({
|
|
@@ -1464,16 +1512,26 @@ export class BaseApiClient {
|
|
|
1464
1512
|
}
|
|
1465
1513
|
|
|
1466
1514
|
// Add query parameters with proper encoding
|
|
1515
|
+
// Filter out undefined, null, empty strings, and empty objects to prevent 422 errors
|
|
1467
1516
|
const searchParams = new URLSearchParams()
|
|
1468
1517
|
for (const [key, value] of Object.entries(queryParameters)) {
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1518
|
+
// Skip undefined, null, and empty strings
|
|
1519
|
+
if (value === undefined || value === null || value === '') {
|
|
1520
|
+
continue
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
// Skip empty objects (like {})
|
|
1524
|
+
if (typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length === 0) {
|
|
1525
|
+
continue
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
if (Array.isArray(value)) {
|
|
1529
|
+
value.forEach(v => searchParams.append(key, String(v)))
|
|
1530
|
+
} else if (typeof value === 'object') {
|
|
1531
|
+
// Only serialize non-empty objects
|
|
1532
|
+
searchParams.append(key, JSON.stringify(value))
|
|
1533
|
+
} else {
|
|
1534
|
+
searchParams.append(key, String(value))
|
|
1477
1535
|
}
|
|
1478
1536
|
}
|
|
1479
1537
|
|
|
@@ -1646,7 +1704,7 @@ export class BaseApiClient {
|
|
|
1646
1704
|
controller.abort()
|
|
1647
1705
|
}, timeout)
|
|
1648
1706
|
|
|
1649
|
-
// Next.js 16.0.
|
|
1707
|
+
// Next.js 16.0.7: Build fetch options with cache tags and connection
|
|
1650
1708
|
// Only include next options if we're on the server (Next.js App Router)
|
|
1651
1709
|
const fetchInit: RequestInit & { next?: { tags?: string[]; revalidate?: number | false; connection?: string } } = {
|
|
1652
1710
|
...requestConfig,
|
|
@@ -1654,7 +1712,7 @@ export class BaseApiClient {
|
|
|
1654
1712
|
}
|
|
1655
1713
|
|
|
1656
1714
|
// Add Next.js-specific options only if we have cache tags, revalidate, or connection
|
|
1657
|
-
// Next.js 16.0.
|
|
1715
|
+
// Next.js 16.0.7: Enhanced cache tag support with updateTag
|
|
1658
1716
|
if (cacheTags && cacheTags.length > 0 || revalidate !== undefined || connection) {
|
|
1659
1717
|
fetchInit.next = {}
|
|
1660
1718
|
|
|
@@ -1666,7 +1724,7 @@ export class BaseApiClient {
|
|
|
1666
1724
|
fetchInit.next.revalidate = revalidate === false ? false : revalidate
|
|
1667
1725
|
}
|
|
1668
1726
|
|
|
1669
|
-
// Next.js 16.0.
|
|
1727
|
+
// Next.js 16.0.7: Connection keep-alive for persistent connections
|
|
1670
1728
|
if (connection) {
|
|
1671
1729
|
fetchInit.next.connection = connection
|
|
1672
1730
|
}
|
|
@@ -1674,7 +1732,7 @@ export class BaseApiClient {
|
|
|
1674
1732
|
|
|
1675
1733
|
const response = await fetch(url, fetchInit)
|
|
1676
1734
|
|
|
1677
|
-
// Next.js 16.0.
|
|
1735
|
+
// Next.js 16.0.7: Update cache tags dynamically using updateTag from next/cache
|
|
1678
1736
|
// This allows for granular cache invalidation
|
|
1679
1737
|
if (cacheTags && cacheTags.length > 0) {
|
|
1680
1738
|
try {
|
|
@@ -1938,7 +1996,7 @@ async get<TData>(
|
|
|
1938
1996
|
}
|
|
1939
1997
|
generateClientUtilities() {
|
|
1940
1998
|
const { api } = this.configuration;
|
|
1941
|
-
const errorHandling = api
|
|
1999
|
+
const errorHandling = api.errorHandling;
|
|
1942
2000
|
const enableAuthErrorHandling = errorHandling?.enableAuthErrorHandling !== false;
|
|
1943
2001
|
const authErrorHandlerPath = errorHandling?.authErrorHandlerPath || "@/lib/auth-error-handler";
|
|
1944
2002
|
const authErrorMiddlewareCode = enableAuthErrorHandling ? `
|
|
@@ -2335,7 +2393,7 @@ ${clientMethods}
|
|
|
2335
2393
|
const requestOptionsString = requestOptions.join("\n");
|
|
2336
2394
|
const methodSignature = parameterTypes.length > 1 ? `options: {
|
|
2337
2395
|
${parameterTypes.join("\n ")}
|
|
2338
|
-
}` : parameterTypes.length === 1 && parameterTypes[0].includes("config?") ? "options?: { config?: RequestConfiguration }" : `options: { ${parameterTypes.join(", ")} }`;
|
|
2396
|
+
}` : parameterTypes.length === 1 && parameterTypes[0] && parameterTypes[0].includes("config?") ? "options?: { config?: RequestConfiguration }" : `options: { ${parameterTypes.join(", ")} }`;
|
|
2339
2397
|
if (isQuery) {
|
|
2340
2398
|
return `${documentation}
|
|
2341
2399
|
${methodName} = cache(async (${methodSignature}) => {
|
|
@@ -2606,7 +2664,7 @@ var SchemaGenerator = class {
|
|
|
2606
2664
|
visiting.add(schemaName);
|
|
2607
2665
|
const schema = schemaMap.get(schemaName);
|
|
2608
2666
|
if (schema) {
|
|
2609
|
-
const dependencies = dependencyGraph.get(schemaName)
|
|
2667
|
+
const dependencies = dependencyGraph.get(schemaName) ?? /* @__PURE__ */ new Set();
|
|
2610
2668
|
for (const dep of dependencies) {
|
|
2611
2669
|
if (schemaMap.has(dep)) {
|
|
2612
2670
|
visit(dep);
|
|
@@ -2639,13 +2697,66 @@ var SchemaGenerator = class {
|
|
|
2639
2697
|
findSchemaDependencies(schema) {
|
|
2640
2698
|
const dependencies = [];
|
|
2641
2699
|
const schemaObj = schema.schema;
|
|
2642
|
-
if (schemaObj
|
|
2700
|
+
if (schemaObj?._def) {
|
|
2643
2701
|
this.extractDependenciesFromZodSchema(schemaObj, dependencies);
|
|
2644
2702
|
}
|
|
2645
2703
|
return dependencies;
|
|
2646
2704
|
}
|
|
2705
|
+
extractDependenciesFromDefinition(definition) {
|
|
2706
|
+
const dependencies = [];
|
|
2707
|
+
const schemaRefRegex = /([A-Z][a-zA-Z0-9]*Schema)\b/g;
|
|
2708
|
+
const matches = definition.matchAll(schemaRefRegex);
|
|
2709
|
+
for (const match of matches) {
|
|
2710
|
+
const schemaName = match[1];
|
|
2711
|
+
if (!schemaName) continue;
|
|
2712
|
+
const baseName = schemaName.replace(/Schema$/, "");
|
|
2713
|
+
if (!dependencies.includes(baseName)) {
|
|
2714
|
+
dependencies.push(baseName);
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
return dependencies;
|
|
2718
|
+
}
|
|
2719
|
+
orderDefinitionsByDependencies(definitions) {
|
|
2720
|
+
const visited = /* @__PURE__ */ new Set();
|
|
2721
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
2722
|
+
const result = [];
|
|
2723
|
+
const definitionMap = /* @__PURE__ */ new Map();
|
|
2724
|
+
for (const def of definitions) {
|
|
2725
|
+
const baseName = def.exportName.replace(/Schema$/, "");
|
|
2726
|
+
definitionMap.set(baseName, def);
|
|
2727
|
+
}
|
|
2728
|
+
const visit = /* @__PURE__ */ __name((exportName) => {
|
|
2729
|
+
const baseName = exportName.replace(/Schema$/, "");
|
|
2730
|
+
if (visiting.has(baseName)) {
|
|
2731
|
+
console.warn(`Circular dependency detected for schema: ${exportName}`);
|
|
2732
|
+
return;
|
|
2733
|
+
}
|
|
2734
|
+
if (visited.has(baseName)) {
|
|
2735
|
+
return;
|
|
2736
|
+
}
|
|
2737
|
+
visiting.add(baseName);
|
|
2738
|
+
const def = definitionMap.get(baseName);
|
|
2739
|
+
if (def) {
|
|
2740
|
+
for (const dep of def.dependencies) {
|
|
2741
|
+
if (definitionMap.has(dep)) {
|
|
2742
|
+
visit(`${dep}Schema`);
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
result.push(def);
|
|
2746
|
+
}
|
|
2747
|
+
visiting.delete(baseName);
|
|
2748
|
+
visited.add(baseName);
|
|
2749
|
+
}, "visit");
|
|
2750
|
+
for (const def of definitions) {
|
|
2751
|
+
const baseName = def.exportName.replace(/Schema$/, "");
|
|
2752
|
+
if (!visited.has(baseName)) {
|
|
2753
|
+
visit(def.exportName);
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
return result;
|
|
2757
|
+
}
|
|
2647
2758
|
extractDependenciesFromZodSchema(zodSchema, dependencies, visited = /* @__PURE__ */ new Set()) {
|
|
2648
|
-
if (!zodSchema
|
|
2759
|
+
if (!zodSchema?._def) return;
|
|
2649
2760
|
const def = zodSchema._def;
|
|
2650
2761
|
if (def._schemaRef) {
|
|
2651
2762
|
const refName = def._schemaRef;
|
|
@@ -2668,7 +2779,7 @@ var SchemaGenerator = class {
|
|
|
2668
2779
|
case "ZodObject":
|
|
2669
2780
|
if (def.shape) {
|
|
2670
2781
|
const shape = def.shape();
|
|
2671
|
-
for (const [
|
|
2782
|
+
for (const [_key, value] of Object.entries(shape)) {
|
|
2672
2783
|
this.extractDependenciesFromZodSchema(value, dependencies, visited);
|
|
2673
2784
|
}
|
|
2674
2785
|
}
|
|
@@ -2700,22 +2811,31 @@ var SchemaGenerator = class {
|
|
|
2700
2811
|
break;
|
|
2701
2812
|
}
|
|
2702
2813
|
}
|
|
2703
|
-
|
|
2814
|
+
generateSchemasFile(context) {
|
|
2704
2815
|
const { schemas, endpoints } = context.schema;
|
|
2705
2816
|
const imports = ['import { z } from "zod"'];
|
|
2706
2817
|
const schemaExports = [];
|
|
2707
|
-
const
|
|
2818
|
+
const allSchemaDefinitions = [];
|
|
2708
2819
|
const orderedSchemas = this.orderSchemasByDependencies(schemas);
|
|
2709
2820
|
for (const schema of orderedSchemas) {
|
|
2710
2821
|
const { definition, exportName } = this.generateSchemaDefinition(schema);
|
|
2711
|
-
|
|
2822
|
+
const dependencies = this.findSchemaDependencies(schema);
|
|
2823
|
+
allSchemaDefinitions.push({ definition, exportName, dependencies });
|
|
2712
2824
|
schemaExports.push(exportName);
|
|
2713
2825
|
}
|
|
2714
2826
|
for (const endpoint of endpoints) {
|
|
2715
2827
|
const endpointSchemas = this.generateEndpointSchemas(endpoint);
|
|
2716
|
-
|
|
2717
|
-
|
|
2828
|
+
for (let i = 0; i < endpointSchemas.definitions.length; i++) {
|
|
2829
|
+
const definition = endpointSchemas.definitions[i];
|
|
2830
|
+
const exportName = endpointSchemas.exports[i];
|
|
2831
|
+
if (!definition || !exportName) continue;
|
|
2832
|
+
const dependencies = this.extractDependenciesFromDefinition(definition);
|
|
2833
|
+
allSchemaDefinitions.push({ definition, exportName, dependencies });
|
|
2834
|
+
schemaExports.push(exportName);
|
|
2835
|
+
}
|
|
2718
2836
|
}
|
|
2837
|
+
const orderedDefinitions = this.orderDefinitionsByDependencies(allSchemaDefinitions);
|
|
2838
|
+
const schemaDefinitions = orderedDefinitions.map((item) => item.definition);
|
|
2719
2839
|
const validationHelpers = this.generateValidationHelpers();
|
|
2720
2840
|
const contentWithImports = [
|
|
2721
2841
|
...imports,
|
|
@@ -2734,7 +2854,7 @@ var SchemaGenerator = class {
|
|
|
2734
2854
|
|
|
2735
2855
|
${content}`;
|
|
2736
2856
|
}
|
|
2737
|
-
return {
|
|
2857
|
+
return Promise.resolve({
|
|
2738
2858
|
path: "schemas/index.ts",
|
|
2739
2859
|
content,
|
|
2740
2860
|
type: "typescript",
|
|
@@ -2743,7 +2863,7 @@ ${content}`;
|
|
|
2743
2863
|
imports: ["zod"],
|
|
2744
2864
|
dependencies: []
|
|
2745
2865
|
}
|
|
2746
|
-
};
|
|
2866
|
+
});
|
|
2747
2867
|
}
|
|
2748
2868
|
generateEndpointSchemas(endpoint) {
|
|
2749
2869
|
const definitions = [];
|
|
@@ -2778,6 +2898,9 @@ ${content}`;
|
|
|
2778
2898
|
}
|
|
2779
2899
|
const exportName = `${operationName}RequestSchema`;
|
|
2780
2900
|
const primaryContent = endpoint.requestBody.content[0];
|
|
2901
|
+
if (!primaryContent) {
|
|
2902
|
+
throw new Error(`No content found for request body in ${endpoint.method} ${endpoint.path}`);
|
|
2903
|
+
}
|
|
2781
2904
|
const zodSchemaString = this.zodSchemaToString(primaryContent.schema);
|
|
2782
2905
|
const definition = [
|
|
2783
2906
|
`/**`,
|
|
@@ -2801,17 +2924,22 @@ ${content}`;
|
|
|
2801
2924
|
);
|
|
2802
2925
|
if (successResponses.length > 0) {
|
|
2803
2926
|
const successResponse = successResponses[0];
|
|
2927
|
+
if (!successResponse) {
|
|
2928
|
+
return { definitions, exports };
|
|
2929
|
+
}
|
|
2804
2930
|
let zodSchemaString = "z.void()";
|
|
2805
2931
|
if (successResponse.content && successResponse.content.length > 0) {
|
|
2806
2932
|
const primaryContent = successResponse.content[0];
|
|
2807
|
-
|
|
2933
|
+
if (primaryContent) {
|
|
2934
|
+
zodSchemaString = this.zodSchemaToString(primaryContent.schema);
|
|
2935
|
+
}
|
|
2808
2936
|
}
|
|
2809
2937
|
const exportName = `${operationName}ResponseSchema`;
|
|
2810
2938
|
const definition = [
|
|
2811
2939
|
`/**`,
|
|
2812
2940
|
` * Success response schema for ${endpoint.method} ${endpoint.path}`,
|
|
2813
2941
|
` * Status: ${successResponse.statusCode}`,
|
|
2814
|
-
` * ${successResponse.description}`,
|
|
2942
|
+
` * ${successResponse.description ?? ""}`,
|
|
2815
2943
|
` */`,
|
|
2816
2944
|
`export const ${exportName} = ${zodSchemaString}`,
|
|
2817
2945
|
"",
|
|
@@ -2822,15 +2950,18 @@ ${content}`;
|
|
|
2822
2950
|
}
|
|
2823
2951
|
if (errorResponses.length > 0) {
|
|
2824
2952
|
const errorResponse = errorResponses[0];
|
|
2825
|
-
if (errorResponse
|
|
2953
|
+
if (errorResponse?.content && errorResponse.content.length > 0) {
|
|
2826
2954
|
const exportName = `${operationName}ErrorSchema`;
|
|
2827
2955
|
const primaryContent = errorResponse.content[0];
|
|
2956
|
+
if (!primaryContent) {
|
|
2957
|
+
return { definitions, exports };
|
|
2958
|
+
}
|
|
2828
2959
|
const zodSchemaString = this.zodSchemaToString(primaryContent.schema);
|
|
2829
2960
|
const definition = [
|
|
2830
2961
|
`/**`,
|
|
2831
2962
|
` * Error response schema for ${endpoint.method} ${endpoint.path}`,
|
|
2832
2963
|
` * Status: ${errorResponse.statusCode}`,
|
|
2833
|
-
` * ${errorResponse.description}`,
|
|
2964
|
+
` * ${errorResponse.description ?? ""}`,
|
|
2834
2965
|
` */`,
|
|
2835
2966
|
`export const ${exportName} = ${zodSchemaString}`,
|
|
2836
2967
|
"",
|
|
@@ -2921,8 +3052,8 @@ ${schemaProperties.join(",\n")}
|
|
|
2921
3052
|
};
|
|
2922
3053
|
}
|
|
2923
3054
|
zodSchemaToString(schema, context) {
|
|
2924
|
-
if (!schema
|
|
2925
|
-
if (schema
|
|
3055
|
+
if (!schema?._def) {
|
|
3056
|
+
if (schema?._schemaRef) {
|
|
2926
3057
|
const refName = schema._schemaRef;
|
|
2927
3058
|
const registeredSchema = this.schemaRegistry.get(refName);
|
|
2928
3059
|
if (registeredSchema) {
|
|
@@ -3090,15 +3221,21 @@ export const errorMessages = {
|
|
|
3090
3221
|
const assignments = line.match(/(\w+)\s*[:=]/g);
|
|
3091
3222
|
if (assignments) {
|
|
3092
3223
|
assignments.forEach((match) => {
|
|
3093
|
-
const
|
|
3094
|
-
|
|
3224
|
+
const parts = match.split(/[:=]/);
|
|
3225
|
+
if (parts[0]) {
|
|
3226
|
+
const identifier = parts[0].trim();
|
|
3227
|
+
usedIdentifiers.add(identifier);
|
|
3228
|
+
}
|
|
3095
3229
|
});
|
|
3096
3230
|
}
|
|
3097
3231
|
const functionCalls = line.match(/(\w+)\s*\(/g);
|
|
3098
3232
|
if (functionCalls) {
|
|
3099
3233
|
functionCalls.forEach((match) => {
|
|
3100
|
-
const
|
|
3101
|
-
|
|
3234
|
+
const parts = match.split("(");
|
|
3235
|
+
if (parts[0]) {
|
|
3236
|
+
const identifier = parts[0].trim();
|
|
3237
|
+
usedIdentifiers.add(identifier);
|
|
3238
|
+
}
|
|
3102
3239
|
});
|
|
3103
3240
|
}
|
|
3104
3241
|
if (line.includes("z.infer")) {
|
|
@@ -3116,10 +3253,10 @@ export const errorMessages = {
|
|
|
3116
3253
|
continue;
|
|
3117
3254
|
}
|
|
3118
3255
|
const importMatch = line.match(/import\s*\{([^}]+)\}/);
|
|
3119
|
-
if (importMatch) {
|
|
3256
|
+
if (importMatch?.[1]) {
|
|
3120
3257
|
const imports = importMatch[1].split(",").map((imp) => imp.trim());
|
|
3121
3258
|
const usedImports = imports.filter((imp) => usedIdentifiers.has(imp));
|
|
3122
|
-
if (usedImports.length > 0) {
|
|
3259
|
+
if (usedImports.length > 0 && importMatch[1]) {
|
|
3123
3260
|
cleanedLines.push(line.replace(importMatch[1], usedImports.join(", ")));
|
|
3124
3261
|
} else {
|
|
3125
3262
|
continue;
|
|
@@ -3166,7 +3303,7 @@ var ActionGenerator = class {
|
|
|
3166
3303
|
if (!this.documentationEnabled) {
|
|
3167
3304
|
return "";
|
|
3168
3305
|
}
|
|
3169
|
-
const summary = endpoint.summary
|
|
3306
|
+
const summary = endpoint.summary ?? endpoint.description ?? `${endpoint.method} ${endpoint.path}`;
|
|
3170
3307
|
return `/**
|
|
3171
3308
|
* ${summary}
|
|
3172
3309
|
* @generated from ${endpoint.method} ${endpoint.path}
|
|
@@ -3308,7 +3445,7 @@ ${" ".repeat(indent + 2)}error: error instanceof Error ? error.message : 'Unknow
|
|
|
3308
3445
|
${" ".repeat(indent)}})`;
|
|
3309
3446
|
}
|
|
3310
3447
|
buildImportPath(relativePath) {
|
|
3311
|
-
const outputDirectory = this.configuration.outputDir
|
|
3448
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
3312
3449
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
3313
3450
|
let importBasePath = outputDirectory;
|
|
3314
3451
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -3316,7 +3453,7 @@ ${" ".repeat(indent)}})`;
|
|
|
3316
3453
|
}
|
|
3317
3454
|
return `@/${importBasePath}/${cleanPath}`;
|
|
3318
3455
|
}
|
|
3319
|
-
|
|
3456
|
+
generate(context) {
|
|
3320
3457
|
const { schema, config } = context;
|
|
3321
3458
|
const generatedFiles = [];
|
|
3322
3459
|
const endpointsByTag = this.groupEndpointsByTag(schema.endpoints);
|
|
@@ -3410,7 +3547,7 @@ ${actions}`;
|
|
|
3410
3547
|
dependencies: Object.keys(endpointsByTag).map((tag) => `./${toValidIdentifier(tag)}`)
|
|
3411
3548
|
}
|
|
3412
3549
|
});
|
|
3413
|
-
return generatedFiles;
|
|
3550
|
+
return Promise.resolve(generatedFiles);
|
|
3414
3551
|
}
|
|
3415
3552
|
getOperationName(endpoint) {
|
|
3416
3553
|
if (endpoint.operationId) {
|
|
@@ -3423,7 +3560,7 @@ ${actions}`;
|
|
|
3423
3560
|
const method = this.toPascalCase(endpoint.method.toLowerCase());
|
|
3424
3561
|
return [...pathParts, method].join("");
|
|
3425
3562
|
}
|
|
3426
|
-
generateOptimizedServerAction(endpoint,
|
|
3563
|
+
generateOptimizedServerAction(endpoint, _config) {
|
|
3427
3564
|
const actionName = toActionName(endpoint.operationId || endpoint.id);
|
|
3428
3565
|
const operationName = this.getOperationName(endpoint);
|
|
3429
3566
|
const hasRequestBody = !!endpoint.requestBody;
|
|
@@ -3705,7 +3842,7 @@ var HookGenerator = class {
|
|
|
3705
3842
|
}
|
|
3706
3843
|
return `@/${importBasePath}/${cleanPath}`;
|
|
3707
3844
|
}
|
|
3708
|
-
|
|
3845
|
+
generate(context) {
|
|
3709
3846
|
const { schema } = context;
|
|
3710
3847
|
const generatedFiles = [];
|
|
3711
3848
|
const endpointsByTag = this.groupEndpointsByTag(schema.endpoints);
|
|
@@ -3838,7 +3975,7 @@ ${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier
|
|
|
3838
3975
|
dependencies: ["./useBridgeQuery", ...Object.keys(endpointsByTag).map((tag) => `./${toValidIdentifier(tag)}`)]
|
|
3839
3976
|
}
|
|
3840
3977
|
});
|
|
3841
|
-
return generatedFiles;
|
|
3978
|
+
return Promise.resolve(generatedFiles);
|
|
3842
3979
|
}
|
|
3843
3980
|
getOperationName(endpoint) {
|
|
3844
3981
|
if (endpoint.operationId) {
|
|
@@ -3855,62 +3992,78 @@ ${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier
|
|
|
3855
3992
|
const hookName = toHookName(endpoint.operationId || endpoint.id, true);
|
|
3856
3993
|
const actionName = toActionName(endpoint.operationId || endpoint.id);
|
|
3857
3994
|
const operationName = this.getOperationName(endpoint);
|
|
3858
|
-
const queryKey = this.generateQueryKey(endpoint);
|
|
3859
3995
|
const staleTime = this.getStaleTime(endpoint);
|
|
3860
3996
|
const pathParameters = endpoint.parameters.filter((parameter) => parameter.in === "path");
|
|
3861
3997
|
const queryParameters = endpoint.parameters.filter((parameter) => parameter.in === "query");
|
|
3862
3998
|
const hasPageParam = queryParameters.some((param) => param.name === "page");
|
|
3863
3999
|
const hasSearchParams = endpoint.path.includes("search") || endpoint.path.includes("list");
|
|
3864
|
-
|
|
3865
|
-
const
|
|
4000
|
+
const pathParamTypes = [];
|
|
4001
|
+
const queryParamTypes = [];
|
|
3866
4002
|
pathParameters.forEach((param) => {
|
|
3867
4003
|
const isRequired = param.required ? "" : "?";
|
|
3868
4004
|
const paramType = this.getTypeFromZodSchema(param.schema);
|
|
3869
|
-
|
|
4005
|
+
pathParamTypes.push(`${param.name}${isRequired}: ${paramType}`);
|
|
3870
4006
|
});
|
|
3871
4007
|
queryParameters.forEach((param) => {
|
|
3872
4008
|
const isRequired = param.required ? "" : "?";
|
|
3873
4009
|
const paramType = this.getTypeFromZodSchema(param.schema);
|
|
3874
|
-
|
|
4010
|
+
queryParamTypes.push(`${param.name}${isRequired}: ${paramType}`);
|
|
3875
4011
|
});
|
|
3876
4012
|
const returnType = `z.infer<typeof ${operationName}ResponseSchema>`;
|
|
3877
4013
|
const optionsType = `{ enabled?: boolean; suspense?: boolean; refetchInterval?: number; initialData?: ${returnType} }`;
|
|
3878
|
-
const
|
|
3879
|
-
|
|
4014
|
+
const paramsTypeParts = [];
|
|
4015
|
+
if (pathParameters.length > 0) {
|
|
4016
|
+
paramsTypeParts.push(`path: { ${pathParamTypes.join("; ")} }`);
|
|
4017
|
+
}
|
|
4018
|
+
if (queryParameters.length > 0) {
|
|
4019
|
+
paramsTypeParts.push(`query?: { ${queryParamTypes.join("; ")} }`);
|
|
4020
|
+
}
|
|
4021
|
+
const paramsType = paramsTypeParts.length > 0 ? `{ ${paramsTypeParts.join("; ")} }` : "{}";
|
|
4022
|
+
const enabledCondition = pathParameters.length > 0 && pathParameters[0] ? `!!params?.path?.${pathParameters[0].name}` : "true";
|
|
4023
|
+
const pathParamsBuild = pathParameters.length > 0 ? `{ ${pathParameters.map((p) => `${p.name}: params.path.${p.name}`).join(", ")} }` : "{}";
|
|
4024
|
+
const queryParamsBuild = queryParameters.length > 0 ? `{ ${queryParameters.map((p) => `${p.name}: params?.query?.${p.name}`).join(", ")} }` : "{}";
|
|
4025
|
+
const queryKeyParts = [`'${toActionName(endpoint.operationId || endpoint.id)}'`];
|
|
4026
|
+
if (pathParameters.length > 0) {
|
|
4027
|
+
queryKeyParts.push("params?.path");
|
|
4028
|
+
} else {
|
|
4029
|
+
queryKeyParts.push("null");
|
|
4030
|
+
}
|
|
4031
|
+
if (queryParameters.length > 0) {
|
|
4032
|
+
queryKeyParts.push("params?.query");
|
|
4033
|
+
}
|
|
4034
|
+
const queryKeyString = `[${queryKeyParts.join(", ")}]`;
|
|
4035
|
+
const hasAnyParams = pathParameters.length > 0 || queryParameters.length > 0;
|
|
4036
|
+
const actionCallString = pathParameters.length > 0 && queryParameters.length > 0 ? `{ path: ${pathParamsBuild}, query: ${queryParamsBuild} }` : pathParameters.length > 0 ? `{ path: ${pathParamsBuild} }` : queryParameters.length > 0 ? `{ query: ${queryParamsBuild} }` : "";
|
|
3880
4037
|
if (hasSearchParams) {
|
|
3881
|
-
const
|
|
3882
|
-
const isRequired = param.required;
|
|
3883
|
-
const paramType = this.getTypeFromZodSchema(param.schema);
|
|
3884
|
-
return `${param.name}${isRequired ? "" : "?"}: ${paramType}`;
|
|
3885
|
-
}).join("; ");
|
|
3886
|
-
const queryParamsBuild = queryParameters.length > 0 ? `// Build query params object with only the parameters the endpoint expects
|
|
3887
|
-
const queryParams: { ${queryParamTypes} } = {
|
|
4038
|
+
const queryParamsWithFallback = queryParameters.length > 0 ? `const queryParams = {
|
|
3888
4039
|
${queryParameters.map((param) => {
|
|
3889
4040
|
if (param.name === "query") {
|
|
3890
|
-
return `${param.name}:
|
|
4041
|
+
return `${param.name}: params?.query?.${param.name} || searchParams.search || ''`;
|
|
3891
4042
|
} else if (param.name === "limit") {
|
|
3892
|
-
return `${param.name}:
|
|
4043
|
+
return `${param.name}: params?.query?.${param.name} !== undefined ? params.query.${param.name} : searchParams.limit`;
|
|
3893
4044
|
} else {
|
|
3894
|
-
return `${param.name}:
|
|
4045
|
+
return `${param.name}: params?.query?.${param.name}`;
|
|
3895
4046
|
}
|
|
3896
4047
|
}).join(",\n ")}
|
|
3897
4048
|
}` : "";
|
|
3898
|
-
const
|
|
4049
|
+
const actionCallForSearchParams = queryParameters.length > 0 ? pathParameters.length > 0 ? `{ path: ${pathParamsBuild}, query: queryParams }` : "{ query: queryParams }" : pathParameters.length > 0 ? `{ path: ${pathParamsBuild} }` : hasAnyParams ? actionCallString : "";
|
|
3899
4050
|
return `/**
|
|
3900
4051
|
* Optimized query hook for ${endpoint.method} ${endpoint.path}
|
|
3901
4052
|
* Features: URL state sync, infinite loading, optimistic updates
|
|
4053
|
+
* @param params - Named parameters object with path and query parameters
|
|
4054
|
+
* @param options - Query options
|
|
3902
4055
|
* @returns useQuery result with data of type ${returnType}
|
|
3903
4056
|
*/
|
|
3904
|
-
export function ${hookName}(${
|
|
4057
|
+
export function ${hookName}(params${pathParameters.length > 0 ? "" : "?"}: ${paramsType}, options?: ${optionsType}) {
|
|
3905
4058
|
const [searchParams] = useQueryStates(searchParamsParser)
|
|
3906
4059
|
const { initialData, ...restOptions } = options ?? {}
|
|
3907
4060
|
|
|
3908
4061
|
return useQuery({
|
|
3909
|
-
queryKey: [
|
|
4062
|
+
queryKey: [${queryKeyString}, searchParams],
|
|
3910
4063
|
queryFn: async ({ signal }: { signal?: AbortSignal }) => {
|
|
3911
4064
|
try {
|
|
3912
|
-
${
|
|
3913
|
-
const result = await resolveActionResult<${returnType}>(${actionName}(${
|
|
4065
|
+
${queryParamsWithFallback}
|
|
4066
|
+
const result = await resolveActionResult<${returnType}>(${actionName}(${actionCallForSearchParams}))
|
|
3914
4067
|
return result
|
|
3915
4068
|
} catch (error) {
|
|
3916
4069
|
handleActionError(error)
|
|
@@ -3938,32 +4091,33 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3938
4091
|
|
|
3939
4092
|
/**
|
|
3940
4093
|
* Infinite query version for paginated ${endpoint.path}
|
|
4094
|
+
* @param params - Named parameters object with path and query parameters
|
|
4095
|
+
* @param options - Query options
|
|
3941
4096
|
* @returns useInfiniteQuery result with data of type ${returnType}
|
|
3942
4097
|
*/
|
|
3943
|
-
export function ${hookName.replace("use", "useInfinite")}(${
|
|
4098
|
+
export function ${hookName.replace("use", "useInfinite")}(params${pathParameters.length > 0 ? "" : "?"}: ${paramsType}, options?: ${optionsType}) {
|
|
3944
4099
|
const [searchParams] = useQueryStates(searchParamsParser)
|
|
3945
4100
|
const { initialData, ...restOptions } = options ?? {}
|
|
3946
4101
|
|
|
3947
4102
|
return useInfiniteQuery({
|
|
3948
|
-
queryKey: [
|
|
4103
|
+
queryKey: [${queryKeyString}, 'infinite', searchParams],
|
|
3949
4104
|
initialPageParam: 1,
|
|
3950
4105
|
queryFn: async ({ pageParam = 1, signal }: { pageParam?: number; signal?: AbortSignal }) => {
|
|
3951
4106
|
try {
|
|
3952
|
-
|
|
3953
|
-
const queryParams: { ${queryParamTypes} } = {
|
|
4107
|
+
const queryParams = {
|
|
3954
4108
|
${queryParameters.map((param) => {
|
|
3955
4109
|
if (param.name === "page" && hasPageParam) {
|
|
3956
4110
|
return `${param.name}: pageParam`;
|
|
3957
4111
|
} else if (param.name === "query") {
|
|
3958
|
-
return `${param.name}:
|
|
4112
|
+
return `${param.name}: params?.query?.${param.name} || searchParams.search || ''`;
|
|
3959
4113
|
} else if (param.name === "limit") {
|
|
3960
|
-
return `${param.name}:
|
|
4114
|
+
return `${param.name}: params?.query?.${param.name} !== undefined ? params.query.${param.name} : searchParams.limit`;
|
|
3961
4115
|
} else {
|
|
3962
|
-
return `${param.name}:
|
|
4116
|
+
return `${param.name}: params?.query?.${param.name}`;
|
|
3963
4117
|
}
|
|
3964
4118
|
}).join(",\n ")}
|
|
3965
4119
|
}
|
|
3966
|
-
const result = await resolveActionResult<${returnType}>(${actionName}(${
|
|
4120
|
+
const result = await resolveActionResult<${returnType}>(${actionName}(${queryParameters.length > 0 ? pathParameters.length > 0 ? `{ path: ${pathParamsBuild}, query: queryParams }` : "{ query: queryParams }" : pathParameters.length > 0 ? `{ path: ${pathParamsBuild} }` : hasAnyParams ? actionCallString : ""}))
|
|
3967
4121
|
return result
|
|
3968
4122
|
} catch (error) {
|
|
3969
4123
|
handleActionError(error)
|
|
@@ -4005,15 +4159,17 @@ export function ${hookName.replace("use", "useInfinite")}(${parameterTypes.lengt
|
|
|
4005
4159
|
|
|
4006
4160
|
/**
|
|
4007
4161
|
* Suspense version for ${endpoint.path} - use in Server Components
|
|
4162
|
+
* @param params - Named parameters object with path and query parameters
|
|
4163
|
+
* @param options - Query options
|
|
4008
4164
|
* @returns useSuspenseQuery result with data of type ${returnType}
|
|
4009
4165
|
*/
|
|
4010
|
-
export function ${hookName.replace("use", "useSuspense")}(${
|
|
4166
|
+
export function ${hookName.replace("use", "useSuspense")}(params${pathParameters.length > 0 ? "" : "?"}: ${paramsType}, options?: ${optionsType}) {
|
|
4011
4167
|
const { initialData, ...restOptions } = options ?? {}
|
|
4012
4168
|
|
|
4013
4169
|
return useSuspenseQuery({
|
|
4014
|
-
queryKey: ${
|
|
4170
|
+
queryKey: ${queryKeyString},
|
|
4015
4171
|
queryFn: async () => {
|
|
4016
|
-
const result = await resolveActionResult<${returnType}>(${actionName}(${
|
|
4172
|
+
const result = await resolveActionResult<${returnType}>(${actionName}(${actionCallString}))
|
|
4017
4173
|
return result
|
|
4018
4174
|
},
|
|
4019
4175
|
staleTime: ${staleTime},
|
|
@@ -4025,16 +4181,18 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
4025
4181
|
return `/**
|
|
4026
4182
|
* Optimized query hook for ${endpoint.method} ${endpoint.path}
|
|
4027
4183
|
* Features: Smart caching, error handling, type safety
|
|
4184
|
+
* @param params - Named parameters object with path and query parameters
|
|
4185
|
+
* @param options - Query options
|
|
4028
4186
|
* @returns useQuery result with data of type ${returnType}
|
|
4029
4187
|
*/
|
|
4030
|
-
export function ${hookName}(${
|
|
4188
|
+
export function ${hookName}(params${pathParameters.length > 0 ? "" : "?"}: ${paramsType}, options?: ${optionsType}) {
|
|
4031
4189
|
const { initialData, ...restOptions } = options ?? {}
|
|
4032
4190
|
|
|
4033
4191
|
return useQuery({
|
|
4034
|
-
queryKey: ${
|
|
4192
|
+
queryKey: ${queryKeyString},
|
|
4035
4193
|
queryFn: async ({ signal }: { signal?: AbortSignal }) => {
|
|
4036
4194
|
try {
|
|
4037
|
-
const result = await resolveActionResult<${returnType}>(${
|
|
4195
|
+
const result = await resolveActionResult<${returnType}>(${actionName}(${hasAnyParams ? actionCallString : ""}))
|
|
4038
4196
|
return result
|
|
4039
4197
|
} catch (error) {
|
|
4040
4198
|
handleActionError(error)
|
|
@@ -4062,15 +4220,17 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
4062
4220
|
|
|
4063
4221
|
/**
|
|
4064
4222
|
* Suspense version for ${endpoint.path}
|
|
4223
|
+
* @param params - Named parameters object with path and query parameters
|
|
4224
|
+
* @param options - Query options
|
|
4065
4225
|
* @returns useSuspenseQuery result with data of type ${returnType}
|
|
4066
4226
|
*/
|
|
4067
|
-
export function ${hookName.replace("use", "useSuspense")}(${
|
|
4227
|
+
export function ${hookName.replace("use", "useSuspense")}(params${pathParameters.length > 0 ? "" : "?"}: ${paramsType}, options?: ${optionsType}) {
|
|
4068
4228
|
const { initialData, ...restOptions } = options ?? {}
|
|
4069
4229
|
|
|
4070
4230
|
return useSuspenseQuery({
|
|
4071
|
-
queryKey: ${
|
|
4231
|
+
queryKey: ${queryKeyString},
|
|
4072
4232
|
queryFn: async () => {
|
|
4073
|
-
const result = await resolveActionResult<${returnType}>(${
|
|
4233
|
+
const result = await resolveActionResult<${returnType}>(${actionName}(${actionCallString}))
|
|
4074
4234
|
return result
|
|
4075
4235
|
},
|
|
4076
4236
|
staleTime: ${staleTime},
|
|
@@ -4185,7 +4345,7 @@ ${invalidationCode}
|
|
|
4185
4345
|
* Find related queries that should be invalidated when this mutation runs
|
|
4186
4346
|
*/
|
|
4187
4347
|
findRelatedQueries(endpoint, context) {
|
|
4188
|
-
if (!context?.schema
|
|
4348
|
+
if (!context?.schema.endpoints) {
|
|
4189
4349
|
return [];
|
|
4190
4350
|
}
|
|
4191
4351
|
const relatedQueries = [];
|
|
@@ -4319,7 +4479,6 @@ ${invalidationCode}
|
|
|
4319
4479
|
buildActionCallParams(endpoint, isMutation) {
|
|
4320
4480
|
const pathParameters = endpoint.parameters.filter((parameter) => parameter.in === "path");
|
|
4321
4481
|
const queryParameters = endpoint.parameters.filter((parameter) => parameter.in === "query");
|
|
4322
|
-
!!endpoint.requestBody;
|
|
4323
4482
|
if (isMutation) {
|
|
4324
4483
|
return "variables";
|
|
4325
4484
|
}
|
|
@@ -4400,13 +4559,13 @@ ${invalidationCode}
|
|
|
4400
4559
|
import { useQuery, useMutation, useInfiniteQuery, useSuspenseQuery, type UseQueryOptions, type UseMutationOptions, type UseInfiniteQueryOptions, type UseSuspenseQueryOptions, type QueryKey, type QueryFunction } from '@tanstack/react-query'
|
|
4401
4560
|
|
|
4402
4561
|
/**
|
|
4403
|
-
* Enhanced React Query wrapper hook with Next.js 16.0.
|
|
4562
|
+
* Enhanced React Query wrapper hook with Next.js 16.0.7 optimizations
|
|
4404
4563
|
* Provides consistent defaults across all queries following best practices
|
|
4405
4564
|
*
|
|
4406
4565
|
* Features:
|
|
4407
4566
|
* - React Query v5: Uses gcTime instead of cacheTime
|
|
4408
4567
|
* - React Query v5: Uses placeholderData instead of keepPreviousData
|
|
4409
|
-
* - Next.js 16.0.
|
|
4568
|
+
* - Next.js 16.0.7: Optimized for App Router and Server Components
|
|
4410
4569
|
*/
|
|
4411
4570
|
export function useBridgeQuery<TData = unknown, TError = Error>(
|
|
4412
4571
|
queryKey: QueryKey,
|
|
@@ -4463,7 +4622,7 @@ export function useBridgeInfiniteQuery<TData = unknown, TError = Error, TPagePar
|
|
|
4463
4622
|
|
|
4464
4623
|
/**
|
|
4465
4624
|
* Enhanced suspense query wrapper
|
|
4466
|
-
* Next.js 16.0.
|
|
4625
|
+
* Next.js 16.0.7: Optimized for Server Components with Suspense
|
|
4467
4626
|
*/
|
|
4468
4627
|
export function useBridgeSuspenseQuery<TData = unknown, TError = Error>(
|
|
4469
4628
|
queryKey: QueryKey,
|
|
@@ -4519,7 +4678,7 @@ var AuthGenerator = class {
|
|
|
4519
4678
|
__name(this, "AuthGenerator");
|
|
4520
4679
|
}
|
|
4521
4680
|
buildImportPath(relativePath) {
|
|
4522
|
-
const outputDirectory = this.configuration.outputDir
|
|
4681
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
4523
4682
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
4524
4683
|
let importBasePath = outputDirectory;
|
|
4525
4684
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -4527,11 +4686,11 @@ var AuthGenerator = class {
|
|
|
4527
4686
|
}
|
|
4528
4687
|
return `@/${importBasePath}/${cleanPath}`;
|
|
4529
4688
|
}
|
|
4530
|
-
|
|
4689
|
+
generate(context) {
|
|
4531
4690
|
const { config, schema } = context;
|
|
4532
4691
|
const authConfig = config.auth;
|
|
4533
4692
|
if (!authConfig?.enabled) {
|
|
4534
|
-
return [];
|
|
4693
|
+
return Promise.resolve([]);
|
|
4535
4694
|
}
|
|
4536
4695
|
const files = [];
|
|
4537
4696
|
const authEndpoints = this.findAuthEndpoints(schema.endpoints);
|
|
@@ -4546,7 +4705,7 @@ var AuthGenerator = class {
|
|
|
4546
4705
|
files.push(...this.generateAuthComponents(authEndpoints));
|
|
4547
4706
|
files.push(this.generateAuthMiddleware());
|
|
4548
4707
|
files.push(this.generateAuthContext());
|
|
4549
|
-
return files;
|
|
4708
|
+
return Promise.resolve(files);
|
|
4550
4709
|
}
|
|
4551
4710
|
findAuthEndpoints(endpoints) {
|
|
4552
4711
|
const authEndpoints = {};
|
|
@@ -4579,12 +4738,12 @@ var AuthGenerator = class {
|
|
|
4579
4738
|
}
|
|
4580
4739
|
return userEndpoints;
|
|
4581
4740
|
}
|
|
4582
|
-
generateAuthSchemas(
|
|
4741
|
+
generateAuthSchemas(_authEndpoints, _schema) {
|
|
4583
4742
|
this.buildImportPath("schemas");
|
|
4584
|
-
const loginRequestSchema =
|
|
4743
|
+
const loginRequestSchema = _authEndpoints.login?.requestBody?.content?.find(
|
|
4585
4744
|
(c) => c.type === "application/json"
|
|
4586
4745
|
)?.schema;
|
|
4587
|
-
const loginResponseSchema =
|
|
4746
|
+
const loginResponseSchema = _authEndpoints.login?.responses?.find(
|
|
4588
4747
|
(r) => r.statusCode === "200"
|
|
4589
4748
|
)?.content?.[0]?.schema;
|
|
4590
4749
|
const content = `import { z } from "zod"
|
|
@@ -4685,7 +4844,7 @@ export type Session = z.infer<typeof sessionSchema>`;
|
|
|
4685
4844
|
}
|
|
4686
4845
|
};
|
|
4687
4846
|
}
|
|
4688
|
-
generateAuthTypes(
|
|
4847
|
+
generateAuthTypes(_authEndpoints, _schema) {
|
|
4689
4848
|
const schemasImport = this.buildImportPath("auth/schemas");
|
|
4690
4849
|
const content = `// Auto-generated authentication types
|
|
4691
4850
|
import type {
|
|
@@ -5231,7 +5390,7 @@ export const useRequireAuth = (redirectTo?: string) => {
|
|
|
5231
5390
|
}
|
|
5232
5391
|
};
|
|
5233
5392
|
}
|
|
5234
|
-
generateAuthActions(
|
|
5393
|
+
generateAuthActions(_authEndpoints, _userEndpoints) {
|
|
5235
5394
|
const safeActionImport = this.buildImportPath("lib/safe-action");
|
|
5236
5395
|
const schemasImport = this.buildImportPath("auth/schemas");
|
|
5237
5396
|
const clientImport = this.buildImportPath("auth/client");
|
|
@@ -5463,7 +5622,7 @@ export const useCredentialsLogin = () => {
|
|
|
5463
5622
|
}
|
|
5464
5623
|
};
|
|
5465
5624
|
}
|
|
5466
|
-
generateAuthComponents(
|
|
5625
|
+
generateAuthComponents(_authEndpoints) {
|
|
5467
5626
|
const loginForm = {
|
|
5468
5627
|
path: "auth/components/login-form.tsx",
|
|
5469
5628
|
content: `"use client"
|
|
@@ -5583,7 +5742,6 @@ export function LoginForm() {
|
|
|
5583
5742
|
return [loginForm];
|
|
5584
5743
|
}
|
|
5585
5744
|
generateAuthMiddleware() {
|
|
5586
|
-
this.buildImportPath("auth/utils");
|
|
5587
5745
|
const content = `import { NextResponse } from "next/server"
|
|
5588
5746
|
import type { NextRequest } from "next/server"
|
|
5589
5747
|
|
|
@@ -5951,9 +6109,10 @@ var SchemaAnalyzer = class {
|
|
|
5951
6109
|
}
|
|
5952
6110
|
if (response.description) {
|
|
5953
6111
|
const errorMatch = response.description.match(/error[_\s]?code[:\s]+(\w+)/i);
|
|
5954
|
-
if (errorMatch) {
|
|
5955
|
-
|
|
5956
|
-
|
|
6112
|
+
if (errorMatch?.[1]) {
|
|
6113
|
+
const errorCode = errorMatch[1];
|
|
6114
|
+
errorCodes.set(errorCode.toLowerCase(), {
|
|
6115
|
+
code: errorCode,
|
|
5957
6116
|
status,
|
|
5958
6117
|
message: response.description
|
|
5959
6118
|
});
|
|
@@ -6039,7 +6198,7 @@ var SchemaAnalyzer = class {
|
|
|
6039
6198
|
const endpoints = {};
|
|
6040
6199
|
for (const endpoint of this.schema.endpoints) {
|
|
6041
6200
|
const path3 = endpoint.path.toLowerCase();
|
|
6042
|
-
const operationId = (endpoint.operationId
|
|
6201
|
+
const operationId = (endpoint.operationId ?? "").toLowerCase();
|
|
6043
6202
|
if ((path3.includes("/auth/login/credentials") || operationId.includes("logincredentials") || operationId.includes("signin")) && endpoint.method === "POST") {
|
|
6044
6203
|
endpoints.loginCredentials = endpoint;
|
|
6045
6204
|
} else if ((path3.includes("/auth/login") || operationId.includes("login")) && endpoint.method === "POST" && !endpoints.loginCredentials) {
|
|
@@ -6087,12 +6246,12 @@ var SchemaAnalyzer = class {
|
|
|
6087
6246
|
extractSessionConfig() {
|
|
6088
6247
|
const config = {};
|
|
6089
6248
|
const sessionEndpoints = this.schema.endpoints.filter(
|
|
6090
|
-
(e) => e.path.toLowerCase().includes("/session") || (e.operationId
|
|
6249
|
+
(e) => e.path.toLowerCase().includes("/session") || (e.operationId ?? "").toLowerCase().includes("session")
|
|
6091
6250
|
);
|
|
6092
6251
|
for (const endpoint of sessionEndpoints) {
|
|
6093
6252
|
for (const response of endpoint.responses) {
|
|
6094
6253
|
if (response.headers) {
|
|
6095
|
-
for (const [headerName,
|
|
6254
|
+
for (const [headerName, _headerDef] of Object.entries(response.headers)) {
|
|
6096
6255
|
if (headerName.toLowerCase().includes("expires") || headerName.toLowerCase().includes("max-age")) ;
|
|
6097
6256
|
}
|
|
6098
6257
|
}
|
|
@@ -6172,7 +6331,7 @@ var SchemaAnalyzer = class {
|
|
|
6172
6331
|
/**
|
|
6173
6332
|
* Check if OAuth provider is supported
|
|
6174
6333
|
*/
|
|
6175
|
-
isOAuthProviderSupported(
|
|
6334
|
+
isOAuthProviderSupported(_provider) {
|
|
6176
6335
|
const extractedEndpoints = this.extractAuthEndpoints();
|
|
6177
6336
|
return !!(extractedEndpoints.oauthAuthorize && extractedEndpoints.oauthCallback);
|
|
6178
6337
|
}
|
|
@@ -6254,7 +6413,7 @@ var SchemaAnalyzer = class {
|
|
|
6254
6413
|
errorCodes.set(code.toLowerCase(), {
|
|
6255
6414
|
code,
|
|
6256
6415
|
status,
|
|
6257
|
-
message: schema.properties?.detail?.default
|
|
6416
|
+
message: schema.properties?.detail?.default ?? schema.properties?.message?.default ?? ""
|
|
6258
6417
|
});
|
|
6259
6418
|
});
|
|
6260
6419
|
}
|
|
@@ -6263,9 +6422,10 @@ var SchemaAnalyzer = class {
|
|
|
6263
6422
|
const detail = schema.properties.detail;
|
|
6264
6423
|
if (typeof detail === "string") {
|
|
6265
6424
|
const codeMatch = detail.match(/(\w+)[_\s]?error/i);
|
|
6266
|
-
if (codeMatch) {
|
|
6267
|
-
|
|
6268
|
-
|
|
6425
|
+
if (codeMatch?.[1]) {
|
|
6426
|
+
const errorCode = codeMatch[1];
|
|
6427
|
+
errorCodes.set(errorCode.toLowerCase(), {
|
|
6428
|
+
code: errorCode,
|
|
6269
6429
|
status,
|
|
6270
6430
|
message: detail
|
|
6271
6431
|
});
|
|
@@ -6277,11 +6437,11 @@ var SchemaAnalyzer = class {
|
|
|
6277
6437
|
if (!schema || typeof schema !== "object") return;
|
|
6278
6438
|
if (schema.properties?.file) {
|
|
6279
6439
|
const fileSchema = schema.properties.file;
|
|
6280
|
-
if (fileSchema.maxSize
|
|
6281
|
-
config.maxSize = fileSchema.maxSize
|
|
6440
|
+
if (fileSchema.maxSize ?? fileSchema["x-max-size"]) {
|
|
6441
|
+
config.maxSize = fileSchema.maxSize ?? fileSchema["x-max-size"];
|
|
6282
6442
|
}
|
|
6283
|
-
if (fileSchema.allowedTypes
|
|
6284
|
-
config.allowedTypes = fileSchema.allowedTypes
|
|
6443
|
+
if (fileSchema.allowedTypes ?? fileSchema["x-allowed-types"]) {
|
|
6444
|
+
config.allowedTypes = fileSchema.allowedTypes ?? fileSchema["x-allowed-types"];
|
|
6285
6445
|
}
|
|
6286
6446
|
}
|
|
6287
6447
|
if (schema["x-file-constraints"]) {
|
|
@@ -6301,7 +6461,7 @@ var NextAuthGenerator = class {
|
|
|
6301
6461
|
analyzer;
|
|
6302
6462
|
accountStatusPatterns;
|
|
6303
6463
|
buildImportPath(relativePath) {
|
|
6304
|
-
const outputDirectory = this.configuration.outputDir
|
|
6464
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
6305
6465
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
6306
6466
|
let importBasePath = outputDirectory;
|
|
6307
6467
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -6309,11 +6469,11 @@ var NextAuthGenerator = class {
|
|
|
6309
6469
|
}
|
|
6310
6470
|
return `@/${importBasePath}/${cleanPath}`;
|
|
6311
6471
|
}
|
|
6312
|
-
|
|
6472
|
+
generate(context) {
|
|
6313
6473
|
const { config, schema } = context;
|
|
6314
6474
|
const authConfig = config.auth;
|
|
6315
6475
|
if (!authConfig?.enabled || authConfig.provider !== "next-auth") {
|
|
6316
|
-
return [];
|
|
6476
|
+
return Promise.resolve([]);
|
|
6317
6477
|
}
|
|
6318
6478
|
this.analyzer = new SchemaAnalyzer(schema);
|
|
6319
6479
|
this.accountStatusPatterns = this.analyzer.extractAccountStatusPatterns();
|
|
@@ -6330,7 +6490,7 @@ var NextAuthGenerator = class {
|
|
|
6330
6490
|
console.warn("These features will be disabled in generated code.\n");
|
|
6331
6491
|
}
|
|
6332
6492
|
const detectedOAuthProviders = this.analyzer.extractOAuthProviders();
|
|
6333
|
-
const configuredOAuthProviders = authConfig.oauth?.providers
|
|
6493
|
+
const configuredOAuthProviders = authConfig.oauth?.providers ?? [];
|
|
6334
6494
|
const validOAuthProviders = configuredOAuthProviders.filter(
|
|
6335
6495
|
(provider) => this.analyzer.isOAuthProviderSupported(provider)
|
|
6336
6496
|
);
|
|
@@ -6341,7 +6501,7 @@ var NextAuthGenerator = class {
|
|
|
6341
6501
|
console.warn(
|
|
6342
6502
|
`\u26A0\uFE0F NextAuth is enabled but login endpoints are not found in OpenAPI schema. Expected endpoints: /auth/login or /auth/login/credentials. NextAuth configuration will not be generated.`
|
|
6343
6503
|
);
|
|
6344
|
-
return files;
|
|
6504
|
+
return Promise.resolve(files);
|
|
6345
6505
|
}
|
|
6346
6506
|
files.push(this.generateNextAuthConfig(
|
|
6347
6507
|
extractedEndpoints,
|
|
@@ -6354,7 +6514,7 @@ var NextAuthGenerator = class {
|
|
|
6354
6514
|
if (hasPasskeys) {
|
|
6355
6515
|
files.push(this.generatePasskeyUtils(extractedEndpoints));
|
|
6356
6516
|
}
|
|
6357
|
-
return files;
|
|
6517
|
+
return Promise.resolve(files);
|
|
6358
6518
|
}
|
|
6359
6519
|
findAuthEndpoints(endpoints) {
|
|
6360
6520
|
const authEndpoints = {};
|
|
@@ -6457,14 +6617,14 @@ var NextAuthGenerator = class {
|
|
|
6457
6617
|
}
|
|
6458
6618
|
generateNextAuthConfig(extractedEndpoints, oauthProviders, hasMFA, hasPasskeys) {
|
|
6459
6619
|
const authConfig = this.configuration.auth;
|
|
6460
|
-
const apiBaseUrl = this.configuration.api
|
|
6620
|
+
const apiBaseUrl = this.configuration.api.baseUrl || "http://localhost:8000";
|
|
6461
6621
|
const apiUrl = `process.env.NEXT_PUBLIC_API_URL || '${apiBaseUrl}'`;
|
|
6462
6622
|
const hasGoogle = oauthProviders.includes("google");
|
|
6463
6623
|
const hasGitHub = oauthProviders.includes("github");
|
|
6464
6624
|
oauthProviders.includes("discord");
|
|
6465
6625
|
oauthProviders.includes("microsoft");
|
|
6466
6626
|
oauthProviders.includes("apple");
|
|
6467
|
-
const { activeStatuses, inactiveStatuses, suspendedStatuses, lockedStatuses } = this.accountStatusPatterns;
|
|
6627
|
+
const { activeStatuses, inactiveStatuses, suspendedStatuses, lockedStatuses: _lockedStatuses } = this.accountStatusPatterns;
|
|
6468
6628
|
this.analyzer.extractErrorCodes();
|
|
6469
6629
|
const sessionStrategy = authConfig.session?.strategy || "jwt";
|
|
6470
6630
|
const sessionMaxAge = authConfig.session?.maxAge || 7 * 24 * 60 * 60;
|
|
@@ -7013,7 +7173,7 @@ export async function authenticateWithPasskey(email?: string) {
|
|
|
7013
7173
|
}
|
|
7014
7174
|
};
|
|
7015
7175
|
}
|
|
7016
|
-
generateAuthTypes(
|
|
7176
|
+
generateAuthTypes(_authEndpoints, _accountStatusPatterns) {
|
|
7017
7177
|
const content = `/**
|
|
7018
7178
|
* Authentication Types
|
|
7019
7179
|
* Auto-generated by Mulink
|
|
@@ -7084,7 +7244,7 @@ export class AccountInactiveError extends AuthError {
|
|
|
7084
7244
|
}
|
|
7085
7245
|
};
|
|
7086
7246
|
}
|
|
7087
|
-
generateAuthUtils(
|
|
7247
|
+
generateAuthUtils(_authEndpoints) {
|
|
7088
7248
|
const content = `/**
|
|
7089
7249
|
* Authentication Utilities
|
|
7090
7250
|
* Auto-generated by Mulink
|
|
@@ -7137,7 +7297,7 @@ export async function requireAuth() {
|
|
|
7137
7297
|
}
|
|
7138
7298
|
};
|
|
7139
7299
|
}
|
|
7140
|
-
generatePasskeyUtils(
|
|
7300
|
+
generatePasskeyUtils(_passkeyEndpoints) {
|
|
7141
7301
|
const content = `/**
|
|
7142
7302
|
* Passkey (WebAuthn) Utilities
|
|
7143
7303
|
* Auto-generated by Mulink
|
|
@@ -7190,7 +7350,7 @@ var MiddlewareGenerator = class {
|
|
|
7190
7350
|
__name(this, "MiddlewareGenerator");
|
|
7191
7351
|
}
|
|
7192
7352
|
buildImportPath(relativePath) {
|
|
7193
|
-
const outputDirectory = this.configuration.outputDir
|
|
7353
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
7194
7354
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
7195
7355
|
let importBasePath = outputDirectory;
|
|
7196
7356
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -7198,7 +7358,7 @@ var MiddlewareGenerator = class {
|
|
|
7198
7358
|
}
|
|
7199
7359
|
return `@/${importBasePath}/${cleanPath}`;
|
|
7200
7360
|
}
|
|
7201
|
-
|
|
7361
|
+
generate(_context) {
|
|
7202
7362
|
const files = [];
|
|
7203
7363
|
files.push(this.generateMainMiddleware());
|
|
7204
7364
|
files.push(this.generateRateLimitMiddleware());
|
|
@@ -7206,7 +7366,7 @@ var MiddlewareGenerator = class {
|
|
|
7206
7366
|
files.push(this.generateSecurityMiddleware());
|
|
7207
7367
|
files.push(this.generateLoggingMiddleware());
|
|
7208
7368
|
files.push(this.generateApiMiddleware());
|
|
7209
|
-
return files;
|
|
7369
|
+
return Promise.resolve(files);
|
|
7210
7370
|
}
|
|
7211
7371
|
generateMainMiddleware() {
|
|
7212
7372
|
const authImport = this.buildImportPath("auth/middleware");
|
|
@@ -7613,7 +7773,7 @@ var UploadGenerator = class {
|
|
|
7613
7773
|
}
|
|
7614
7774
|
analyzer;
|
|
7615
7775
|
buildImportPath(relativePath) {
|
|
7616
|
-
const outputDirectory = this.configuration.outputDir
|
|
7776
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
7617
7777
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
7618
7778
|
let importBasePath = outputDirectory;
|
|
7619
7779
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -7621,19 +7781,19 @@ var UploadGenerator = class {
|
|
|
7621
7781
|
}
|
|
7622
7782
|
return `@/${importBasePath}/${cleanPath}`;
|
|
7623
7783
|
}
|
|
7624
|
-
|
|
7784
|
+
generate(context) {
|
|
7625
7785
|
const { schema } = context;
|
|
7626
7786
|
const generatedFiles = [];
|
|
7627
7787
|
this.analyzer = new SchemaAnalyzer(schema);
|
|
7628
7788
|
const uploadEndpoints = schema.endpoints.filter(
|
|
7629
|
-
(endpoint) => endpoint.requestBody?.content
|
|
7789
|
+
(endpoint) => endpoint.requestBody?.content.some(
|
|
7630
7790
|
(content) => content.type === "multipart/form-data" || content.type === "application/octet-stream"
|
|
7631
7791
|
)
|
|
7632
7792
|
);
|
|
7633
7793
|
if (uploadEndpoints.length === 0 || !this.configuration.uploads?.enabled) {
|
|
7634
|
-
return generatedFiles;
|
|
7794
|
+
return Promise.resolve(generatedFiles);
|
|
7635
7795
|
}
|
|
7636
|
-
const presignedConfig = this.configuration.uploads
|
|
7796
|
+
const presignedConfig = this.configuration.uploads.presignedUploads;
|
|
7637
7797
|
if (presignedConfig?.enabled) {
|
|
7638
7798
|
const isPresignedSupported = this.analyzer.isPresignedUploadsSupported();
|
|
7639
7799
|
if (!isPresignedSupported) {
|
|
@@ -7644,14 +7804,14 @@ var UploadGenerator = class {
|
|
|
7644
7804
|
}
|
|
7645
7805
|
const extractedUploadConfig = this.analyzer.extractUploadConfig();
|
|
7646
7806
|
const presignedEnabled = presignedConfig?.enabled && this.analyzer.isPresignedUploadsSupported();
|
|
7647
|
-
const uploadProvider = this.configuration.uploads
|
|
7648
|
-
const uploadStrategy = presignedEnabled ? "presigned" : this.configuration.uploads
|
|
7807
|
+
const uploadProvider = this.configuration.uploads.provider || (extractedUploadConfig.presignedEndpoint ? "minio" : "standard");
|
|
7808
|
+
const uploadStrategy = presignedEnabled ? "presigned" : this.configuration.uploads.strategy || "standard";
|
|
7649
7809
|
presignedEnabled ? {
|
|
7650
|
-
presignEndpoint: extractedUploadConfig.presignedEndpoint || presignedConfig
|
|
7651
|
-
fallbackToBackend: presignedConfig
|
|
7810
|
+
presignEndpoint: extractedUploadConfig.presignedEndpoint || presignedConfig.presignEndpoint || "/api/v1/files/presign-upload",
|
|
7811
|
+
fallbackToBackend: presignedConfig.fallbackToBackend !== false
|
|
7652
7812
|
} : {
|
|
7653
7813
|
};
|
|
7654
|
-
const progressConfig = this.configuration.uploads
|
|
7814
|
+
const progressConfig = this.configuration.uploads.progressTracking || {
|
|
7655
7815
|
enabled: true,
|
|
7656
7816
|
useXHR: true
|
|
7657
7817
|
};
|
|
@@ -7668,7 +7828,7 @@ var UploadGenerator = class {
|
|
|
7668
7828
|
progressConfig
|
|
7669
7829
|
));
|
|
7670
7830
|
}
|
|
7671
|
-
return generatedFiles;
|
|
7831
|
+
return Promise.resolve(generatedFiles);
|
|
7672
7832
|
}
|
|
7673
7833
|
/**
|
|
7674
7834
|
* Find presigned upload endpoint in schema
|
|
@@ -7681,7 +7841,7 @@ var UploadGenerator = class {
|
|
|
7681
7841
|
return pathLower.includes("presign") || pathLower.includes("presigned") || operationIdLower.includes("presign") || operationIdLower.includes("presigned");
|
|
7682
7842
|
}) || null;
|
|
7683
7843
|
}
|
|
7684
|
-
generateUploadUtilities(
|
|
7844
|
+
generateUploadUtilities(_uploadProvider, _uploadStrategy, _presignedEndpoint) {
|
|
7685
7845
|
const { uploads } = this.configuration;
|
|
7686
7846
|
const extractedConfig = this.analyzer.extractUploadConfig();
|
|
7687
7847
|
const maxSize = uploads?.security?.maxSize || (extractedConfig.maxSize ? `${extractedConfig.maxSize}MB` : "10MB");
|
|
@@ -8032,8 +8192,8 @@ async function uploadViaBackendApi(
|
|
|
8032
8192
|
xhr.responseType = 'json'
|
|
8033
8193
|
// Use base URL from environment or configuration
|
|
8034
8194
|
const baseUrl = typeof window !== 'undefined'
|
|
8035
|
-
? (process.env.NEXT_PUBLIC_API_URL || '${this.configuration.api
|
|
8036
|
-
: '${this.configuration.api
|
|
8195
|
+
? (process.env.NEXT_PUBLIC_API_URL || '${this.configuration.api.baseUrl || "http://localhost:8000"}')
|
|
8196
|
+
: '${this.configuration.api.baseUrl || "http://localhost:8000"}'
|
|
8037
8197
|
xhr.open('POST', \`\${baseUrl}${endpoint.path}\`)
|
|
8038
8198
|
xhr.send(formData)
|
|
8039
8199
|
})
|
|
@@ -8308,8 +8468,8 @@ export function ${hookName}Upload(options?: {
|
|
|
8308
8468
|
}
|
|
8309
8469
|
generateUseUploadFileHook(uploadProvider, uploadStrategy, context) {
|
|
8310
8470
|
const uploadUtilsImport = this.buildImportPath("services/uploadUtils");
|
|
8311
|
-
const uploadEndpoints = context?.schema
|
|
8312
|
-
(e) => e.metadata
|
|
8471
|
+
const uploadEndpoints = context?.schema.endpoints.filter(
|
|
8472
|
+
(e) => e.metadata.fileUpload || e.path.toLowerCase().includes("upload") || e.operationId && e.operationId.toLowerCase().includes("upload")
|
|
8313
8473
|
) || [];
|
|
8314
8474
|
const firstUploadEndpoint = uploadEndpoints[0];
|
|
8315
8475
|
let uploadMethodName = "uploadFile";
|
|
@@ -8449,7 +8609,7 @@ var ErrorHandlerGenerator = class {
|
|
|
8449
8609
|
}
|
|
8450
8610
|
analyzer;
|
|
8451
8611
|
buildImportPath(relativePath) {
|
|
8452
|
-
const outputDirectory = this.configuration.outputDir
|
|
8612
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
8453
8613
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
8454
8614
|
let importBasePath = outputDirectory;
|
|
8455
8615
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -8457,18 +8617,18 @@ var ErrorHandlerGenerator = class {
|
|
|
8457
8617
|
}
|
|
8458
8618
|
return `@/${importBasePath}/${cleanPath}`;
|
|
8459
8619
|
}
|
|
8460
|
-
|
|
8620
|
+
generate(context) {
|
|
8461
8621
|
const files = [];
|
|
8462
|
-
const { schema
|
|
8622
|
+
const { schema } = context;
|
|
8463
8623
|
const { api } = this.configuration;
|
|
8464
|
-
const errorHandling = api
|
|
8624
|
+
const errorHandling = api.errorHandling;
|
|
8465
8625
|
this.analyzer = new SchemaAnalyzer(schema);
|
|
8466
8626
|
const errorCodes = this.analyzer.extractErrorCodes();
|
|
8467
8627
|
const accountStatusPatterns = this.analyzer.extractAccountStatusPatterns();
|
|
8468
8628
|
const extractedAuthEndpoints = this.analyzer.extractAuthEndpoints();
|
|
8469
8629
|
const hasAuthEndpoints = !!(extractedAuthEndpoints.login || extractedAuthEndpoints.loginCredentials);
|
|
8470
8630
|
const hasAuthErrors = errorCodes.size > 0 || (accountStatusPatterns.inactiveStatuses.length > 0 || accountStatusPatterns.suspendedStatuses.length > 0);
|
|
8471
|
-
const shouldGenerate = hasAuthEndpoints && (errorHandling?.generateAuthErrorHandler !== false && errorHandling?.enableAuthErrorHandling !== false || hasAuthErrors && errorHandling
|
|
8631
|
+
const shouldGenerate = hasAuthEndpoints && (errorHandling?.generateAuthErrorHandler !== false && errorHandling?.enableAuthErrorHandling !== false || hasAuthErrors && errorHandling.generateAuthErrorHandler !== false);
|
|
8472
8632
|
if (shouldGenerate) {
|
|
8473
8633
|
files.push(this.generateAuthErrorHandler(errorCodes, accountStatusPatterns));
|
|
8474
8634
|
} else if (errorHandling?.enableAuthErrorHandling === true && !hasAuthEndpoints) {
|
|
@@ -8476,11 +8636,11 @@ var ErrorHandlerGenerator = class {
|
|
|
8476
8636
|
`\u26A0\uFE0F Auth error handling is enabled but auth endpoints are not found in OpenAPI schema. Auth error handler will not be generated.`
|
|
8477
8637
|
);
|
|
8478
8638
|
}
|
|
8479
|
-
return files;
|
|
8639
|
+
return Promise.resolve(files);
|
|
8480
8640
|
}
|
|
8481
8641
|
generateAuthErrorHandler(errorCodes, accountStatusPatterns) {
|
|
8482
8642
|
const authPath = this.configuration.auth?.authPath || "@/lib/auth";
|
|
8483
|
-
const errorHandling = this.configuration.api
|
|
8643
|
+
const errorHandling = this.configuration.api.errorHandling;
|
|
8484
8644
|
const authErrorHandlerPath = errorHandling?.authErrorHandlerPath || "@/lib/auth-error-handler";
|
|
8485
8645
|
let handlerOutputPath = authErrorHandlerPath;
|
|
8486
8646
|
if (handlerOutputPath.startsWith("@/")) {
|
|
@@ -8693,7 +8853,7 @@ var SSEGenerator = class {
|
|
|
8693
8853
|
}
|
|
8694
8854
|
analyzer;
|
|
8695
8855
|
buildImportPath(relativePath) {
|
|
8696
|
-
const outputDirectory = this.configuration.outputDir
|
|
8856
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
8697
8857
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
8698
8858
|
let importBasePath = outputDirectory;
|
|
8699
8859
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -8725,11 +8885,11 @@ var SSEGenerator = class {
|
|
|
8725
8885
|
);
|
|
8726
8886
|
return hasEventStream;
|
|
8727
8887
|
}
|
|
8728
|
-
|
|
8888
|
+
generate(context) {
|
|
8729
8889
|
const { schema } = context;
|
|
8730
8890
|
const generatedFiles = [];
|
|
8731
8891
|
this.analyzer = new SchemaAnalyzer(schema);
|
|
8732
|
-
const streamingConfig = this.configuration.framework
|
|
8892
|
+
const streamingConfig = this.configuration.framework.streaming;
|
|
8733
8893
|
const hasStreamingEndpoints = schema.endpoints.some((endpoint) => this.isSSEEndpoint(endpoint));
|
|
8734
8894
|
if (streamingConfig?.enabled === true && !hasStreamingEndpoints) {
|
|
8735
8895
|
console.warn(
|
|
@@ -8738,11 +8898,11 @@ var SSEGenerator = class {
|
|
|
8738
8898
|
}
|
|
8739
8899
|
const shouldEnableStreaming = streamingConfig?.enabled === true ? hasStreamingEndpoints : streamingConfig?.enabled !== false && hasStreamingEndpoints;
|
|
8740
8900
|
if (!shouldEnableStreaming || streamingConfig?.sse?.enabled === false || !hasStreamingEndpoints) {
|
|
8741
|
-
return generatedFiles;
|
|
8901
|
+
return Promise.resolve(generatedFiles);
|
|
8742
8902
|
}
|
|
8743
8903
|
const sseEndpoints = schema.endpoints.filter((endpoint) => this.isSSEEndpoint(endpoint));
|
|
8744
8904
|
if (sseEndpoints.length === 0) {
|
|
8745
|
-
return generatedFiles;
|
|
8905
|
+
return Promise.resolve(generatedFiles);
|
|
8746
8906
|
}
|
|
8747
8907
|
for (const endpoint of sseEndpoints) {
|
|
8748
8908
|
generatedFiles.push(this.generateSSEClientMethod(endpoint));
|
|
@@ -8751,7 +8911,7 @@ var SSEGenerator = class {
|
|
|
8751
8911
|
for (const [tag, tagEndpoints] of Object.entries(endpointsByTag)) {
|
|
8752
8912
|
generatedFiles.push(this.generateSSEHooks(tag, tagEndpoints));
|
|
8753
8913
|
}
|
|
8754
|
-
return generatedFiles;
|
|
8914
|
+
return Promise.resolve(generatedFiles);
|
|
8755
8915
|
}
|
|
8756
8916
|
generateSSEClientMethod(endpoint) {
|
|
8757
8917
|
const operationId = endpoint.operationId || endpoint.id;
|
|
@@ -8786,8 +8946,8 @@ var SSEGenerator = class {
|
|
|
8786
8946
|
}): EventSource => {
|
|
8787
8947
|
${pathParamNames.length > 0 ? `const { ${pathParamNames.join(", ")}, ...restOptions } = options.params || {}
|
|
8788
8948
|
` : ""}const baseUrl = typeof window !== 'undefined'
|
|
8789
|
-
? (process.env.NEXT_PUBLIC_API_URL || '${this.configuration.api
|
|
8790
|
-
: '${this.configuration.api
|
|
8949
|
+
? (process.env.NEXT_PUBLIC_API_URL || '${this.configuration.api.baseUrl || "http://localhost:8000"}')
|
|
8950
|
+
: '${this.configuration.api.baseUrl || "http://localhost:8000"}'
|
|
8791
8951
|
const sseUrl = \`\${baseUrl}${urlConstruction}\`
|
|
8792
8952
|
|
|
8793
8953
|
// Create EventSource connection
|
|
@@ -8833,7 +8993,7 @@ var SSEGenerator = class {
|
|
|
8833
8993
|
generateSSEHooks(tag, endpoints) {
|
|
8834
8994
|
const tagName = toValidIdentifier(tag);
|
|
8835
8995
|
const clientImport = this.buildImportPath("client");
|
|
8836
|
-
const streamingConfig = this.configuration.framework
|
|
8996
|
+
const streamingConfig = this.configuration.framework.streaming?.sse;
|
|
8837
8997
|
const autoReconnect = streamingConfig?.autoReconnect !== false;
|
|
8838
8998
|
const reconnectDelay = streamingConfig?.reconnectDelay || 3e3;
|
|
8839
8999
|
const maxReconnectAttempts = streamingConfig?.maxReconnectAttempts || 5;
|
|
@@ -9026,7 +9186,7 @@ var NextJsCodeGenerator = class {
|
|
|
9026
9186
|
__name(this, "NextJsCodeGenerator");
|
|
9027
9187
|
}
|
|
9028
9188
|
buildImportPath(relativePath) {
|
|
9029
|
-
const outputDirectory = this.configuration.outputDir
|
|
9189
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
9030
9190
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
9031
9191
|
let importBasePath = outputDirectory;
|
|
9032
9192
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -9040,9 +9200,9 @@ var NextJsCodeGenerator = class {
|
|
|
9040
9200
|
path: file.path,
|
|
9041
9201
|
metadata: {
|
|
9042
9202
|
...file.metadata,
|
|
9043
|
-
exports: file.metadata?.exports
|
|
9044
|
-
imports: file.metadata?.imports
|
|
9045
|
-
dependencies: file.metadata?.dependencies
|
|
9203
|
+
exports: file.metadata?.exports ?? [],
|
|
9204
|
+
imports: file.metadata?.imports ?? [],
|
|
9205
|
+
dependencies: file.metadata?.dependencies.map((dependency) => {
|
|
9046
9206
|
if (dependency.startsWith("@/generated/")) {
|
|
9047
9207
|
return dependency;
|
|
9048
9208
|
}
|
|
@@ -9051,7 +9211,7 @@ var NextJsCodeGenerator = class {
|
|
|
9051
9211
|
return `@/generated/${relativePart}`;
|
|
9052
9212
|
}
|
|
9053
9213
|
return dependency;
|
|
9054
|
-
})
|
|
9214
|
+
}) ?? []
|
|
9055
9215
|
}
|
|
9056
9216
|
}));
|
|
9057
9217
|
}
|
|
@@ -9084,11 +9244,11 @@ var NextJsCodeGenerator = class {
|
|
|
9084
9244
|
const uploadGenerator = new UploadGenerator(this.configuration);
|
|
9085
9245
|
generatedFiles.push(...await uploadGenerator.generate(context));
|
|
9086
9246
|
}
|
|
9087
|
-
if (this.configuration.api
|
|
9247
|
+
if (this.configuration.api.errorHandling?.generateAuthErrorHandler !== false) {
|
|
9088
9248
|
const errorHandlerGenerator = new ErrorHandlerGenerator(this.configuration);
|
|
9089
9249
|
generatedFiles.push(...await errorHandlerGenerator.generate(context));
|
|
9090
9250
|
}
|
|
9091
|
-
if (this.configuration.framework
|
|
9251
|
+
if (this.configuration.framework.streaming?.enabled) {
|
|
9092
9252
|
const sseGenerator = new SSEGenerator(this.configuration);
|
|
9093
9253
|
generatedFiles.push(...await sseGenerator.generate(context));
|
|
9094
9254
|
}
|
|
@@ -9098,14 +9258,14 @@ var NextJsCodeGenerator = class {
|
|
|
9098
9258
|
throw new GenerationError(`Failed to generate Next.js files: ${errorMessage}`);
|
|
9099
9259
|
}
|
|
9100
9260
|
}
|
|
9101
|
-
|
|
9261
|
+
generateSafeActionClient() {
|
|
9102
9262
|
const safeActionContent = `import { DEFAULT_SERVER_ERROR_MESSAGE, createSafeActionClient } from "next-safe-action";
|
|
9103
9263
|
import { headers } from "next/headers";
|
|
9104
9264
|
import { z } from "zod";
|
|
9105
9265
|
|
|
9106
9266
|
/**
|
|
9107
9267
|
* Enhanced Action Error class for better error handling
|
|
9108
|
-
* Follows Next.js 16.0.
|
|
9268
|
+
* Follows Next.js 16.0.7 best practices
|
|
9109
9269
|
*/
|
|
9110
9270
|
export class ActionError extends Error {
|
|
9111
9271
|
constructor(
|
|
@@ -9142,7 +9302,7 @@ export const actionClient = createSafeActionClient({
|
|
|
9142
9302
|
|
|
9143
9303
|
/**
|
|
9144
9304
|
* Enhanced action client with metadata support
|
|
9145
|
-
* Next.js 16.0.
|
|
9305
|
+
* Next.js 16.0.7: Supports metadata for better action tracking and rate limiting
|
|
9146
9306
|
*/
|
|
9147
9307
|
export const actionClientWithMeta = createSafeActionClient({
|
|
9148
9308
|
handleServerError(e) {
|
|
@@ -9163,7 +9323,7 @@ export const actionClientWithMeta = createSafeActionClient({
|
|
|
9163
9323
|
requests: z.number().int().positive().describe('Number of requests allowed'),
|
|
9164
9324
|
window: z.string().describe('Time window (e.g., "10s", "1m", "1h")'),
|
|
9165
9325
|
}).optional().describe('Rate limiting configuration'),
|
|
9166
|
-
cacheTags: z.array(z.string()).optional().describe('Cache tags for invalidation (Next.js 16.0.
|
|
9326
|
+
cacheTags: z.array(z.string()).optional().describe('Cache tags for invalidation (Next.js 16.0.7)'),
|
|
9167
9327
|
});
|
|
9168
9328
|
},
|
|
9169
9329
|
});
|
|
@@ -9254,7 +9414,7 @@ async function getCurrentUser() {
|
|
|
9254
9414
|
// Implement your authentication logic here
|
|
9255
9415
|
return null;
|
|
9256
9416
|
}`;
|
|
9257
|
-
return [
|
|
9417
|
+
return Promise.resolve([
|
|
9258
9418
|
{
|
|
9259
9419
|
path: "lib/safe-action.ts",
|
|
9260
9420
|
content: safeActionContent,
|
|
@@ -9265,7 +9425,7 @@ async function getCurrentUser() {
|
|
|
9265
9425
|
dependencies: []
|
|
9266
9426
|
}
|
|
9267
9427
|
}
|
|
9268
|
-
];
|
|
9428
|
+
]);
|
|
9269
9429
|
}
|
|
9270
9430
|
};
|
|
9271
9431
|
var FileSystemManager = class {
|
|
@@ -9273,7 +9433,7 @@ var FileSystemManager = class {
|
|
|
9273
9433
|
__name(this, "FileSystemManager");
|
|
9274
9434
|
}
|
|
9275
9435
|
async writeFile(filePath, content, options = {}) {
|
|
9276
|
-
if (!filePath
|
|
9436
|
+
if (!filePath.trim()) {
|
|
9277
9437
|
throw new Error("File path is required and cannot be empty");
|
|
9278
9438
|
}
|
|
9279
9439
|
if (typeof content !== "string") {
|
|
@@ -9310,7 +9470,7 @@ var FileSystemManager = class {
|
|
|
9310
9470
|
}
|
|
9311
9471
|
}
|
|
9312
9472
|
async readFile(filePath, encoding = "utf8") {
|
|
9313
|
-
if (!filePath
|
|
9473
|
+
if (!filePath.trim()) {
|
|
9314
9474
|
throw new Error("File path is required and cannot be empty");
|
|
9315
9475
|
}
|
|
9316
9476
|
try {
|
|
@@ -9337,7 +9497,7 @@ var FileSystemManager = class {
|
|
|
9337
9497
|
}
|
|
9338
9498
|
}
|
|
9339
9499
|
async getFileHash(filePath) {
|
|
9340
|
-
if (!filePath
|
|
9500
|
+
if (!filePath.trim()) {
|
|
9341
9501
|
throw new Error("File path is required and cannot be empty");
|
|
9342
9502
|
}
|
|
9343
9503
|
try {
|
|
@@ -9363,7 +9523,7 @@ var FileSystemManager = class {
|
|
|
9363
9523
|
}
|
|
9364
9524
|
}
|
|
9365
9525
|
async findFiles(dir, pattern, recursive = true) {
|
|
9366
|
-
if (!dir
|
|
9526
|
+
if (!dir.trim()) {
|
|
9367
9527
|
throw new Error("Directory path is required and cannot be empty");
|
|
9368
9528
|
}
|
|
9369
9529
|
if (!(pattern instanceof RegExp)) {
|
|
@@ -9406,16 +9566,52 @@ var BridgeCore = class {
|
|
|
9406
9566
|
logger;
|
|
9407
9567
|
schemaParser;
|
|
9408
9568
|
fileManager;
|
|
9569
|
+
/**
|
|
9570
|
+
* Creates a new instance of BridgeCore
|
|
9571
|
+
*
|
|
9572
|
+
* Initializes all required dependencies including logger, schema parser, and file manager.
|
|
9573
|
+
* All dependencies are readonly to ensure immutability and thread safety.
|
|
9574
|
+
*/
|
|
9409
9575
|
constructor() {
|
|
9410
9576
|
this.logger = new BridgeLogger({ prefix: "\u{1F517} Mulink" });
|
|
9411
9577
|
this.schemaParser = new OpenApiSchemaParser();
|
|
9412
9578
|
this.fileManager = new FileSystemManager();
|
|
9413
9579
|
}
|
|
9580
|
+
/**
|
|
9581
|
+
* Generates type-safe API client code from OpenAPI schema
|
|
9582
|
+
*
|
|
9583
|
+
* This is the main entry point for code generation. It validates the configuration,
|
|
9584
|
+
* parses the OpenAPI schema, generates all necessary files, and writes them to disk.
|
|
9585
|
+
*
|
|
9586
|
+
* The generated code follows Next.js 16.0.7 best practices including:
|
|
9587
|
+
* - Server Actions with type safety
|
|
9588
|
+
* - React Query hooks with proper caching
|
|
9589
|
+
* - Middleware support
|
|
9590
|
+
* - Error handling
|
|
9591
|
+
* - Cache tag management
|
|
9592
|
+
*
|
|
9593
|
+
* @param configuration - The bridge configuration containing schema URL, output directory, and framework settings
|
|
9594
|
+
* @returns Promise that resolves when generation is complete
|
|
9595
|
+
* @throws {ValidationError} When configuration is invalid
|
|
9596
|
+
* @throws {SchemaParseError} When OpenAPI schema cannot be parsed
|
|
9597
|
+
* @throws {GenerationError} When code generation fails
|
|
9598
|
+
*
|
|
9599
|
+
* @example
|
|
9600
|
+
* ```typescript
|
|
9601
|
+
* const config: BridgeConfiguration = {
|
|
9602
|
+
* schema: 'https://api.example.com/openapi.json',
|
|
9603
|
+
* outputDir: 'src/generated',
|
|
9604
|
+
* framework: { type: 'nextjs', router: 'app', features: {...} },
|
|
9605
|
+
* api: { baseUrl: 'https://api.example.com', timeout: 30000, retries: 3 }
|
|
9606
|
+
* };
|
|
9607
|
+
* await bridge.generate(config);
|
|
9608
|
+
* ```
|
|
9609
|
+
*/
|
|
9414
9610
|
async generate(configuration) {
|
|
9415
9611
|
const startTime = Date.now();
|
|
9416
9612
|
try {
|
|
9417
9613
|
this.logger.info("Starting code generation...");
|
|
9418
|
-
|
|
9614
|
+
this.validateConfiguration(configuration);
|
|
9419
9615
|
this.logger.info(`Parsing schema: ${configuration.schema}`);
|
|
9420
9616
|
const parsedSchema = await this.schemaParser.parse(configuration.schema);
|
|
9421
9617
|
this.logger.debug(
|
|
@@ -9444,16 +9640,17 @@ var BridgeCore = class {
|
|
|
9444
9640
|
throw error;
|
|
9445
9641
|
}
|
|
9446
9642
|
}
|
|
9447
|
-
|
|
9643
|
+
validateConfiguration(configuration) {
|
|
9448
9644
|
const errors = [];
|
|
9449
|
-
if (!configuration.schema
|
|
9645
|
+
if (!configuration.schema.trim()) {
|
|
9450
9646
|
errors.push("Schema URL is required and cannot be empty");
|
|
9451
9647
|
}
|
|
9452
|
-
if (!configuration.outputDir
|
|
9648
|
+
if (!configuration.outputDir.trim()) {
|
|
9453
9649
|
errors.push("Output directory is required and cannot be empty");
|
|
9454
9650
|
}
|
|
9455
9651
|
if (configuration.framework.type !== "nextjs") {
|
|
9456
|
-
|
|
9652
|
+
const frameworkType = configuration.framework.type;
|
|
9653
|
+
errors.push(`Only Next.js framework is currently supported, got: ${frameworkType}`);
|
|
9457
9654
|
}
|
|
9458
9655
|
if (errors.length > 0) {
|
|
9459
9656
|
throw new ValidationError(
|
|
@@ -9470,8 +9667,10 @@ var BridgeCore = class {
|
|
|
9470
9667
|
case "nextjs":
|
|
9471
9668
|
const nextJsGenerator = new NextJsCodeGenerator(config);
|
|
9472
9669
|
return await nextJsGenerator.generate(context);
|
|
9473
|
-
default:
|
|
9474
|
-
|
|
9670
|
+
default: {
|
|
9671
|
+
const frameworkType = config.framework.type;
|
|
9672
|
+
throw new GenerationError(`Unsupported framework: ${frameworkType}`);
|
|
9673
|
+
}
|
|
9475
9674
|
}
|
|
9476
9675
|
} catch (error) {
|
|
9477
9676
|
if (error instanceof GenerationError) {
|
|
@@ -9505,7 +9704,7 @@ var BridgeCore = class {
|
|
|
9505
9704
|
logGenerationSummary(files) {
|
|
9506
9705
|
const fileTypes = files.reduce(
|
|
9507
9706
|
(acc, file) => {
|
|
9508
|
-
acc[file.type] = (acc[file.type]
|
|
9707
|
+
acc[file.type] = (acc[file.type] ?? 0) + 1;
|
|
9509
9708
|
return acc;
|
|
9510
9709
|
},
|
|
9511
9710
|
{}
|
|
@@ -9524,9 +9723,24 @@ var BridgeCore = class {
|
|
|
9524
9723
|
});
|
|
9525
9724
|
}
|
|
9526
9725
|
}
|
|
9527
|
-
|
|
9726
|
+
/**
|
|
9727
|
+
* Validates an OpenAPI schema without generating code
|
|
9728
|
+
*
|
|
9729
|
+
* Useful for checking schema validity before running full generation.
|
|
9730
|
+
*
|
|
9731
|
+
* @param schemaUrl - URL or file path to the OpenAPI schema
|
|
9732
|
+
* @returns Promise resolving to true if schema is valid, false otherwise
|
|
9733
|
+
*
|
|
9734
|
+
* @example
|
|
9735
|
+
* ```typescript
|
|
9736
|
+
* const isValid = await bridge.validateSchema('https://api.example.com/openapi.json');
|
|
9737
|
+
* if (isValid) {
|
|
9738
|
+
* await bridge.generate(config);
|
|
9739
|
+
* }
|
|
9740
|
+
* ```
|
|
9741
|
+
*/
|
|
9528
9742
|
async validateSchema(schemaUrl) {
|
|
9529
|
-
if (!schemaUrl
|
|
9743
|
+
if (!schemaUrl.trim()) {
|
|
9530
9744
|
this.logger.warn("Schema URL is empty or invalid");
|
|
9531
9745
|
return false;
|
|
9532
9746
|
}
|
|
@@ -9540,8 +9754,25 @@ var BridgeCore = class {
|
|
|
9540
9754
|
return false;
|
|
9541
9755
|
}
|
|
9542
9756
|
}
|
|
9757
|
+
/**
|
|
9758
|
+
* Retrieves metadata from an OpenAPI schema
|
|
9759
|
+
*
|
|
9760
|
+
* Extracts schema metadata including title, version, description, and other
|
|
9761
|
+
* OpenAPI document information without parsing the entire schema.
|
|
9762
|
+
*
|
|
9763
|
+
* @param schemaUrl - URL or file path to the OpenAPI schema
|
|
9764
|
+
* @returns Promise resolving to schema metadata
|
|
9765
|
+
* @throws {BridgeError} When schema URL is invalid
|
|
9766
|
+
* @throws {SchemaParseError} When schema cannot be parsed
|
|
9767
|
+
*
|
|
9768
|
+
* @example
|
|
9769
|
+
* ```typescript
|
|
9770
|
+
* const metadata = await bridge.getSchemaInfo('https://api.example.com/openapi.json');
|
|
9771
|
+
* console.log(`Schema: ${metadata.title} v${metadata.version}`);
|
|
9772
|
+
* ```
|
|
9773
|
+
*/
|
|
9543
9774
|
async getSchemaInfo(schemaUrl) {
|
|
9544
|
-
if (!schemaUrl
|
|
9775
|
+
if (!schemaUrl.trim()) {
|
|
9545
9776
|
throw new BridgeError("Schema URL is required and cannot be empty", "INVALID_SCHEMA_URL");
|
|
9546
9777
|
}
|
|
9547
9778
|
try {
|
|
@@ -9553,6 +9784,18 @@ var BridgeCore = class {
|
|
|
9553
9784
|
throw new SchemaParseError(`Failed to parse schema: ${errorMessage}`, schemaUrl);
|
|
9554
9785
|
}
|
|
9555
9786
|
}
|
|
9787
|
+
/**
|
|
9788
|
+
* Clears the internal schema cache
|
|
9789
|
+
*
|
|
9790
|
+
* Useful when you need to force re-fetching of schemas or during development.
|
|
9791
|
+
* The cache is automatically managed, but this method allows manual invalidation.
|
|
9792
|
+
*
|
|
9793
|
+
* @example
|
|
9794
|
+
* ```typescript
|
|
9795
|
+
* bridge.clearCache();
|
|
9796
|
+
* await bridge.generate(config); // Will fetch fresh schema
|
|
9797
|
+
* ```
|
|
9798
|
+
*/
|
|
9556
9799
|
clearCache() {
|
|
9557
9800
|
try {
|
|
9558
9801
|
this.schemaParser.clearCache();
|
|
@@ -9651,7 +9894,7 @@ var ConfigurationLoader = class {
|
|
|
9651
9894
|
}
|
|
9652
9895
|
async load(configPath) {
|
|
9653
9896
|
if (!configPath?.trim()) {
|
|
9654
|
-
configPath = "
|
|
9897
|
+
configPath = "link.config.json";
|
|
9655
9898
|
}
|
|
9656
9899
|
const resolvedPath = path2.resolve(process.cwd(), configPath);
|
|
9657
9900
|
try {
|
|
@@ -9717,7 +9960,7 @@ ${errorMessages}`,
|
|
|
9717
9960
|
);
|
|
9718
9961
|
}
|
|
9719
9962
|
}
|
|
9720
|
-
|
|
9963
|
+
createDefault(framework = "nextjs") {
|
|
9721
9964
|
const defaultConfig = {
|
|
9722
9965
|
schema: "https://petstore3.swagger.io/api/v3/openapi.json",
|
|
9723
9966
|
outputDir: "src/generated",
|
|
@@ -9762,7 +10005,7 @@ ${errorMessages}`,
|
|
|
9762
10005
|
}
|
|
9763
10006
|
async save(config, configPath) {
|
|
9764
10007
|
if (!configPath?.trim()) {
|
|
9765
|
-
configPath = "
|
|
10008
|
+
configPath = "link.config.json";
|
|
9766
10009
|
}
|
|
9767
10010
|
const resolvedPath = path2.resolve(process.cwd(), configPath);
|
|
9768
10011
|
try {
|
|
@@ -9806,5 +10049,5 @@ ${errorMessages}`,
|
|
|
9806
10049
|
};
|
|
9807
10050
|
|
|
9808
10051
|
export { BridgeCore, BridgeError, BridgeLogger, ConfigurationLoader, FileSystemManager, GenerationError, LogLevel, NextJsCodeGenerator, OpenApiSchemaParser, SchemaParseError, ValidationError, VersionChecker, __name, checkAndNotifyUpdates, createBridgeVersionChecker };
|
|
9809
|
-
//# sourceMappingURL=chunk-
|
|
9810
|
-
//# sourceMappingURL=chunk-
|
|
10052
|
+
//# sourceMappingURL=chunk-BMHPB646.js.map
|
|
10053
|
+
//# sourceMappingURL=chunk-BMHPB646.js.map
|