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
|
@@ -13,17 +13,48 @@ var __defProp = Object.defineProperty;
|
|
|
13
13
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
14
14
|
|
|
15
15
|
// src/core/types.ts
|
|
16
|
-
var BridgeError = class extends Error {
|
|
16
|
+
var BridgeError = class _BridgeError extends Error {
|
|
17
17
|
static {
|
|
18
18
|
__name(this, "BridgeError");
|
|
19
19
|
}
|
|
20
20
|
code;
|
|
21
21
|
details;
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
timestamp;
|
|
23
|
+
cause;
|
|
24
|
+
constructor(message, code, details, cause) {
|
|
25
|
+
super(message, { cause });
|
|
24
26
|
this.name = "BridgeError";
|
|
25
27
|
this.code = code;
|
|
26
28
|
this.details = details;
|
|
29
|
+
this.timestamp = Date.now();
|
|
30
|
+
this.cause = cause;
|
|
31
|
+
if (Error.captureStackTrace) {
|
|
32
|
+
Error.captureStackTrace(this, _BridgeError);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Converts the error to a JSON-serializable object
|
|
37
|
+
*
|
|
38
|
+
* @returns JSON representation of the error
|
|
39
|
+
*/
|
|
40
|
+
toJSON() {
|
|
41
|
+
return {
|
|
42
|
+
name: this.name,
|
|
43
|
+
message: this.message,
|
|
44
|
+
code: this.code,
|
|
45
|
+
details: this.details,
|
|
46
|
+
timestamp: this.timestamp,
|
|
47
|
+
stack: this.stack,
|
|
48
|
+
cause: this.cause?.message
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Checks if this error is retryable
|
|
53
|
+
*
|
|
54
|
+
* @returns True if the operation that caused this error can be retried
|
|
55
|
+
*/
|
|
56
|
+
isRetryable() {
|
|
57
|
+
return false;
|
|
27
58
|
}
|
|
28
59
|
};
|
|
29
60
|
var ValidationError = class extends BridgeError {
|
|
@@ -31,28 +62,42 @@ var ValidationError = class extends BridgeError {
|
|
|
31
62
|
__name(this, "ValidationError");
|
|
32
63
|
}
|
|
33
64
|
errors;
|
|
34
|
-
constructor(message, errors) {
|
|
35
|
-
super(message, "VALIDATION_ERROR", errors);
|
|
65
|
+
constructor(message, errors, cause) {
|
|
66
|
+
super(message, "VALIDATION_ERROR", errors, cause);
|
|
36
67
|
this.errors = errors;
|
|
37
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Gets formatted validation error messages
|
|
71
|
+
*
|
|
72
|
+
* @returns Array of formatted error messages
|
|
73
|
+
*/
|
|
74
|
+
getFormattedErrors() {
|
|
75
|
+
return this.errors.errors.map((err) => {
|
|
76
|
+
const path3 = err.path.join(".");
|
|
77
|
+
return `${path3}: ${err.message}`;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
38
80
|
};
|
|
39
81
|
var SchemaParseError = class extends BridgeError {
|
|
40
82
|
static {
|
|
41
83
|
__name(this, "SchemaParseError");
|
|
42
84
|
}
|
|
43
85
|
schemaUrl;
|
|
44
|
-
constructor(message, schemaUrl) {
|
|
45
|
-
super(message, "SCHEMA_PARSE_ERROR", { schemaUrl });
|
|
86
|
+
constructor(message, schemaUrl, cause) {
|
|
87
|
+
super(message, "SCHEMA_PARSE_ERROR", { schemaUrl }, cause);
|
|
46
88
|
this.schemaUrl = schemaUrl;
|
|
47
89
|
}
|
|
90
|
+
isRetryable() {
|
|
91
|
+
return this.cause instanceof TypeError && this.cause.message.includes("fetch");
|
|
92
|
+
}
|
|
48
93
|
};
|
|
49
94
|
var GenerationError = class extends BridgeError {
|
|
50
95
|
static {
|
|
51
96
|
__name(this, "GenerationError");
|
|
52
97
|
}
|
|
53
98
|
file;
|
|
54
|
-
constructor(message, file) {
|
|
55
|
-
super(message, "GENERATION_ERROR", { file });
|
|
99
|
+
constructor(message, file, cause) {
|
|
100
|
+
super(message, "GENERATION_ERROR", { file }, cause);
|
|
56
101
|
this.file = file;
|
|
57
102
|
}
|
|
58
103
|
};
|
|
@@ -140,8 +185,8 @@ var BridgeLogger = class {
|
|
|
140
185
|
if (!this.options.colors || !process.stdout.isTTY) {
|
|
141
186
|
console.log(message);
|
|
142
187
|
return {
|
|
143
|
-
succeed: /* @__PURE__ */ __name((msg) => console.log(colorize(`\u2713 ${msg
|
|
144
|
-
fail: /* @__PURE__ */ __name((msg) => console.error(colorize(`\u2717 ${msg
|
|
188
|
+
succeed: /* @__PURE__ */ __name((msg) => console.log(colorize(`\u2713 ${msg ?? message}`, "green")), "succeed"),
|
|
189
|
+
fail: /* @__PURE__ */ __name((msg) => console.error(colorize(`\u2717 ${msg ?? message}`, "red")), "fail"),
|
|
145
190
|
stop: /* @__PURE__ */ __name(() => {
|
|
146
191
|
}, "stop")
|
|
147
192
|
};
|
|
@@ -149,17 +194,20 @@ var BridgeLogger = class {
|
|
|
149
194
|
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
150
195
|
let i = 0;
|
|
151
196
|
const interval = setInterval(() => {
|
|
152
|
-
|
|
197
|
+
const frame = frames[i++ % frames.length];
|
|
198
|
+
if (frame) {
|
|
199
|
+
process.stdout.write(`\r${colorize(frame, "cyan")} ${message}`);
|
|
200
|
+
}
|
|
153
201
|
}, 100);
|
|
154
202
|
return {
|
|
155
203
|
succeed: /* @__PURE__ */ __name((msg) => {
|
|
156
204
|
clearInterval(interval);
|
|
157
|
-
process.stdout.write(`\r${colorize("\u2713", "green")} ${msg
|
|
205
|
+
process.stdout.write(`\r${colorize("\u2713", "green")} ${msg ?? message}
|
|
158
206
|
`);
|
|
159
207
|
}, "succeed"),
|
|
160
208
|
fail: /* @__PURE__ */ __name((msg) => {
|
|
161
209
|
clearInterval(interval);
|
|
162
|
-
process.stdout.write(`\r${colorize("\u2717", "red")} ${msg
|
|
210
|
+
process.stdout.write(`\r${colorize("\u2717", "red")} ${msg ?? message}
|
|
163
211
|
`);
|
|
164
212
|
}, "fail"),
|
|
165
213
|
stop: /* @__PURE__ */ __name(() => {
|
|
@@ -182,7 +230,7 @@ var VersionChecker = class {
|
|
|
182
230
|
constructor(packageName, currentVersion, logger) {
|
|
183
231
|
this.packageName = packageName;
|
|
184
232
|
this.currentVersion = currentVersion;
|
|
185
|
-
this.logger = logger
|
|
233
|
+
this.logger = logger ?? new BridgeLogger({ prefix: "\u{1F50D} Version Check" });
|
|
186
234
|
}
|
|
187
235
|
/**
|
|
188
236
|
* Check if a new version is available
|
|
@@ -237,7 +285,7 @@ var VersionChecker = class {
|
|
|
237
285
|
/**
|
|
238
286
|
* Get the appropriate upgrade command for the detected package manager
|
|
239
287
|
*/
|
|
240
|
-
getUpgradeCommand(
|
|
288
|
+
getUpgradeCommand(_versionInfo) {
|
|
241
289
|
const packageManager = this.detectPackageManager();
|
|
242
290
|
switch (packageManager) {
|
|
243
291
|
case "yarn":
|
|
@@ -311,8 +359,8 @@ var VersionChecker = class {
|
|
|
311
359
|
const currentParts = this.parseVersion(current);
|
|
312
360
|
const latestParts = this.parseVersion(latest);
|
|
313
361
|
for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
|
|
314
|
-
const currentPart = currentParts[i]
|
|
315
|
-
const latestPart = latestParts[i]
|
|
362
|
+
const currentPart = currentParts[i] ?? 0;
|
|
363
|
+
const latestPart = latestParts[i] ?? 0;
|
|
316
364
|
if (latestPart > currentPart) {
|
|
317
365
|
return true;
|
|
318
366
|
} else if (latestPart < currentPart) {
|
|
@@ -386,7 +434,7 @@ function createBridgeVersionChecker(logger) {
|
|
|
386
434
|
if (fs.existsSync(pkgPath)) {
|
|
387
435
|
const pkgRaw = fs.readFileSync(pkgPath, { encoding: "utf-8" });
|
|
388
436
|
const pkg = JSON.parse(pkgRaw);
|
|
389
|
-
if (pkg
|
|
437
|
+
if (pkg.version) {
|
|
390
438
|
currentVersion = pkg.version;
|
|
391
439
|
}
|
|
392
440
|
} else {
|
|
@@ -394,13 +442,13 @@ function createBridgeVersionChecker(logger) {
|
|
|
394
442
|
if (fs.existsSync(cwdPkg)) {
|
|
395
443
|
const pkgRaw = fs.readFileSync(cwdPkg, { encoding: "utf-8" });
|
|
396
444
|
const pkg = JSON.parse(pkgRaw);
|
|
397
|
-
if (pkg
|
|
445
|
+
if (pkg.version) {
|
|
398
446
|
currentVersion = pkg.version;
|
|
399
447
|
}
|
|
400
448
|
}
|
|
401
449
|
}
|
|
402
450
|
} catch (err) {
|
|
403
|
-
const l = logger
|
|
451
|
+
const l = logger ?? new BridgeLogger({ prefix: "\u{1F50D} Version Check" });
|
|
404
452
|
l.debug("Failed to read package.json for current version, falling back to default", err);
|
|
405
453
|
}
|
|
406
454
|
return new VersionChecker(packageName, currentVersion, logger);
|
|
@@ -438,7 +486,7 @@ var OpenApiSchemaParser = class {
|
|
|
438
486
|
async fetchSchema(schemaUrl) {
|
|
439
487
|
const versionChecker = createBridgeVersionChecker();
|
|
440
488
|
const currentVersion = versionChecker.getCurrentVersion();
|
|
441
|
-
if (!schemaUrl
|
|
489
|
+
if (!schemaUrl.trim()) {
|
|
442
490
|
throw new SchemaParseError("Schema URL is required and cannot be empty", schemaUrl);
|
|
443
491
|
}
|
|
444
492
|
if (schemaUrl.startsWith("http")) {
|
|
@@ -459,7 +507,7 @@ var OpenApiSchemaParser = class {
|
|
|
459
507
|
schemaUrl
|
|
460
508
|
);
|
|
461
509
|
}
|
|
462
|
-
const contentType = response.headers.get("content-type")
|
|
510
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
463
511
|
if (!contentType.includes("application/json") && !contentType.includes("application/yaml") && !contentType.includes("text/yaml")) {
|
|
464
512
|
throw new SchemaParseError(
|
|
465
513
|
`Unsupported content type: ${contentType}. Expected JSON or YAML.`,
|
|
@@ -489,10 +537,10 @@ var OpenApiSchemaParser = class {
|
|
|
489
537
|
);
|
|
490
538
|
}
|
|
491
539
|
}
|
|
492
|
-
|
|
540
|
+
parseDocument(document) {
|
|
493
541
|
const version = this.detectVersion(document);
|
|
494
542
|
const normalizedDocument = this.normalizeDocument(document, version);
|
|
495
|
-
return {
|
|
543
|
+
return Promise.resolve({
|
|
496
544
|
version,
|
|
497
545
|
document: normalizedDocument,
|
|
498
546
|
openApiSpec: normalizedDocument,
|
|
@@ -501,7 +549,7 @@ var OpenApiSchemaParser = class {
|
|
|
501
549
|
security: this.extractSecurity(normalizedDocument),
|
|
502
550
|
servers: this.extractServers(normalizedDocument, document),
|
|
503
551
|
metadata: this.extractMetadata(normalizedDocument)
|
|
504
|
-
};
|
|
552
|
+
});
|
|
505
553
|
}
|
|
506
554
|
detectVersion(document) {
|
|
507
555
|
if (!document || typeof document !== "object") {
|
|
@@ -536,7 +584,7 @@ var OpenApiSchemaParser = class {
|
|
|
536
584
|
info: v2Doc.info,
|
|
537
585
|
servers: v2Doc.host ? [
|
|
538
586
|
{
|
|
539
|
-
url: `${v2Doc.schemes?.[0]
|
|
587
|
+
url: `${v2Doc.schemes?.[0] ?? "https"}://${v2Doc.host}${v2Doc.basePath ?? ""}`
|
|
540
588
|
}
|
|
541
589
|
] : [],
|
|
542
590
|
paths: {},
|
|
@@ -681,20 +729,20 @@ var OpenApiSchemaParser = class {
|
|
|
681
729
|
flows: {
|
|
682
730
|
implicit: v2Scheme.flow === "implicit" ? {
|
|
683
731
|
authorizationUrl: v2Scheme.authorizationUrl,
|
|
684
|
-
scopes: v2Scheme.scopes
|
|
732
|
+
scopes: v2Scheme.scopes ?? {}
|
|
685
733
|
} : void 0,
|
|
686
734
|
password: v2Scheme.flow === "password" ? {
|
|
687
735
|
tokenUrl: v2Scheme.tokenUrl,
|
|
688
|
-
scopes: v2Scheme.scopes
|
|
736
|
+
scopes: v2Scheme.scopes ?? {}
|
|
689
737
|
} : void 0,
|
|
690
738
|
clientCredentials: v2Scheme.flow === "application" ? {
|
|
691
739
|
tokenUrl: v2Scheme.tokenUrl,
|
|
692
|
-
scopes: v2Scheme.scopes
|
|
740
|
+
scopes: v2Scheme.scopes ?? {}
|
|
693
741
|
} : void 0,
|
|
694
742
|
authorizationCode: v2Scheme.flow === "accessCode" ? {
|
|
695
743
|
authorizationUrl: v2Scheme.authorizationUrl,
|
|
696
744
|
tokenUrl: v2Scheme.tokenUrl,
|
|
697
|
-
scopes: v2Scheme.scopes
|
|
745
|
+
scopes: v2Scheme.scopes ?? {}
|
|
698
746
|
} : void 0
|
|
699
747
|
}
|
|
700
748
|
};
|
|
@@ -720,18 +768,18 @@ var OpenApiSchemaParser = class {
|
|
|
720
768
|
const operation = pathItem[method.toLowerCase()];
|
|
721
769
|
if (!operation) continue;
|
|
722
770
|
const endpoint = {
|
|
723
|
-
id: operation.operationId
|
|
771
|
+
id: operation.operationId ?? `${method.toLowerCase()}_${path3.replace(/[^a-zA-Z0-9]/g, "_")}`,
|
|
724
772
|
path: path3,
|
|
725
773
|
method,
|
|
726
774
|
operationId: operation.operationId,
|
|
727
775
|
summary: operation.summary,
|
|
728
776
|
description: operation.description,
|
|
729
|
-
tags: operation.tags
|
|
777
|
+
tags: operation.tags ?? [],
|
|
730
778
|
parameters: this.extractParameters(operation.parameters, pathItem.parameters, document),
|
|
731
779
|
requestBody: this.extractRequestBody(operation.requestBody, document),
|
|
732
780
|
responses: this.extractResponses(operation.responses, document),
|
|
733
|
-
security: operation.security
|
|
734
|
-
deprecated: operation.deprecated
|
|
781
|
+
security: operation.security ?? [],
|
|
782
|
+
deprecated: operation.deprecated ?? false,
|
|
735
783
|
metadata: this.extractEndpointMetadata(operation)
|
|
736
784
|
};
|
|
737
785
|
endpoints.push(endpoint);
|
|
@@ -741,7 +789,7 @@ var OpenApiSchemaParser = class {
|
|
|
741
789
|
}
|
|
742
790
|
extractParameters(operationParams, pathParams, document) {
|
|
743
791
|
const parameters = [];
|
|
744
|
-
const allParams = [...pathParams
|
|
792
|
+
const allParams = [...pathParams ?? [], ...operationParams ?? []];
|
|
745
793
|
for (const param of allParams) {
|
|
746
794
|
if (!param) continue;
|
|
747
795
|
if ("$ref" in param) {
|
|
@@ -751,11 +799,11 @@ var OpenApiSchemaParser = class {
|
|
|
751
799
|
const parameter = {
|
|
752
800
|
name: param.name,
|
|
753
801
|
in: param.in,
|
|
754
|
-
required: param.required
|
|
802
|
+
required: param.required ?? param.in === "path",
|
|
755
803
|
schema: this.convertSchemaToZod(param.schema, document),
|
|
756
804
|
description: param.description,
|
|
757
805
|
example: param.example,
|
|
758
|
-
deprecated: param.deprecated
|
|
806
|
+
deprecated: param.deprecated ?? false
|
|
759
807
|
};
|
|
760
808
|
parameters.push(parameter);
|
|
761
809
|
}
|
|
@@ -774,7 +822,7 @@ var OpenApiSchemaParser = class {
|
|
|
774
822
|
}
|
|
775
823
|
}
|
|
776
824
|
return {
|
|
777
|
-
required: requestBody.required
|
|
825
|
+
required: requestBody.required ?? false,
|
|
778
826
|
description: requestBody.description,
|
|
779
827
|
content
|
|
780
828
|
};
|
|
@@ -814,7 +862,7 @@ var OpenApiSchemaParser = class {
|
|
|
814
862
|
schema: this.convertSchemaToZod(schema, document),
|
|
815
863
|
description: schema.description,
|
|
816
864
|
example: schema.example,
|
|
817
|
-
deprecated: schema.deprecated
|
|
865
|
+
deprecated: schema.deprecated ?? false
|
|
818
866
|
});
|
|
819
867
|
}
|
|
820
868
|
}
|
|
@@ -848,7 +896,7 @@ var OpenApiSchemaParser = class {
|
|
|
848
896
|
const v2Doc = originalDoc;
|
|
849
897
|
return [
|
|
850
898
|
{
|
|
851
|
-
url: `${v2Doc.schemes?.[0]
|
|
899
|
+
url: `${v2Doc.schemes?.[0] ?? "https"}://${v2Doc.host}${v2Doc.basePath ?? ""}`,
|
|
852
900
|
description: "Converted from Swagger 2.0"
|
|
853
901
|
}
|
|
854
902
|
];
|
|
@@ -868,9 +916,9 @@ var OpenApiSchemaParser = class {
|
|
|
868
916
|
}
|
|
869
917
|
extractEndpointMetadata(operation) {
|
|
870
918
|
return {
|
|
871
|
-
requiresAuth: operation.security
|
|
919
|
+
requiresAuth: (operation.security?.length ?? 0) > 0,
|
|
872
920
|
cacheStrategy: "default",
|
|
873
|
-
revalidationTags: operation.tags
|
|
921
|
+
revalidationTags: operation.tags ?? [],
|
|
874
922
|
streaming: false,
|
|
875
923
|
fileUpload: this.hasFileUpload(operation)
|
|
876
924
|
};
|
|
@@ -878,7 +926,7 @@ var OpenApiSchemaParser = class {
|
|
|
878
926
|
hasFileUpload(operation) {
|
|
879
927
|
if (!operation.requestBody || "$ref" in operation.requestBody) return false;
|
|
880
928
|
const content = operation.requestBody.content;
|
|
881
|
-
return Object.keys(content
|
|
929
|
+
return Object.keys(content ?? {}).some(
|
|
882
930
|
(mediaType) => mediaType.includes("multipart/form-data") || mediaType.includes("application/octet-stream")
|
|
883
931
|
);
|
|
884
932
|
}
|
|
@@ -966,7 +1014,7 @@ var OpenApiSchemaParser = class {
|
|
|
966
1014
|
case "object":
|
|
967
1015
|
if (schema.properties) {
|
|
968
1016
|
const shape = {};
|
|
969
|
-
const required = schema.required
|
|
1017
|
+
const required = schema.required ?? [];
|
|
970
1018
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
971
1019
|
let propZodSchema = this.convertSchemaToZod(propSchema, document);
|
|
972
1020
|
if (!required.includes(propName)) {
|
|
@@ -998,7 +1046,7 @@ var ApiClientGenerator = class {
|
|
|
998
1046
|
* Generate import paths based on configuration
|
|
999
1047
|
*/
|
|
1000
1048
|
buildImportPath(relativePath) {
|
|
1001
|
-
const outputDirectory = this.configuration.outputDir
|
|
1049
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
1002
1050
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
1003
1051
|
let importBasePath = outputDirectory;
|
|
1004
1052
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -1006,24 +1054,24 @@ var ApiClientGenerator = class {
|
|
|
1006
1054
|
}
|
|
1007
1055
|
return `@/${importBasePath}/${cleanPath}`;
|
|
1008
1056
|
}
|
|
1009
|
-
|
|
1057
|
+
generate(context) {
|
|
1010
1058
|
const { schema } = context;
|
|
1011
1059
|
const generatedFiles = [];
|
|
1012
1060
|
generatedFiles.push(this.generateEnhancedBaseClient());
|
|
1013
1061
|
generatedFiles.push(...this.generateEndpointClients(schema.endpoints));
|
|
1014
1062
|
generatedFiles.push(this.generateMainClient(schema.endpoints));
|
|
1015
1063
|
generatedFiles.push(this.generateClientUtilities());
|
|
1016
|
-
return generatedFiles;
|
|
1064
|
+
return Promise.resolve(generatedFiles);
|
|
1017
1065
|
}
|
|
1018
1066
|
generateEnhancedBaseClient() {
|
|
1019
1067
|
const { api, auth } = this.configuration;
|
|
1020
1068
|
const authUtilsImport = this.buildImportPath("auth/utils");
|
|
1021
|
-
const authPath = auth?.authPath
|
|
1022
|
-
const tokenGetter = auth?.tokenGetter
|
|
1069
|
+
const authPath = auth?.authPath ?? "@/lib/auth";
|
|
1070
|
+
const tokenGetter = auth?.tokenGetter ?? "auth";
|
|
1023
1071
|
const content = `/**
|
|
1024
1072
|
* The HTTP client is automatically created by "mulink"
|
|
1025
1073
|
*
|
|
1026
|
-
* Next.js 16.0.
|
|
1074
|
+
* Next.js 16.0.7 Best Practices:
|
|
1027
1075
|
* - Proper separation of client/server code
|
|
1028
1076
|
* - Dynamic imports for server-only modules
|
|
1029
1077
|
* - Works in both Server Components and Client Components
|
|
@@ -1034,7 +1082,7 @@ import { cache } from 'react'
|
|
|
1034
1082
|
|
|
1035
1083
|
/**
|
|
1036
1084
|
* Server-only modules interface
|
|
1037
|
-
* Next.js 16.0.
|
|
1085
|
+
* Next.js 16.0.7: These modules are only available on the server
|
|
1038
1086
|
* We use dynamic imports to avoid bundling them in the client
|
|
1039
1087
|
*/
|
|
1040
1088
|
type NextHeadersModule = typeof import('next/headers')
|
|
@@ -1058,7 +1106,7 @@ function toMutableHeaders(source: NextReadonlyHeaders) {
|
|
|
1058
1106
|
|
|
1059
1107
|
/**
|
|
1060
1108
|
* Lazy load server-only modules only when needed (server-side)
|
|
1061
|
-
* Next.js 16.0.
|
|
1109
|
+
* Next.js 16.0.7: This ensures server-only code is not bundled in the client
|
|
1062
1110
|
*
|
|
1063
1111
|
* @returns Server-only modules or undefined if on client-side
|
|
1064
1112
|
*/
|
|
@@ -1066,7 +1114,7 @@ async function getServerModules() {
|
|
|
1066
1114
|
if (serverOnlyModules !== null) return serverOnlyModules
|
|
1067
1115
|
|
|
1068
1116
|
// Only attempt to import on server-side
|
|
1069
|
-
// Next.js 16.0.
|
|
1117
|
+
// Next.js 16.0.7: typeof window check ensures we're on the server
|
|
1070
1118
|
if (typeof window === 'undefined') {
|
|
1071
1119
|
try {
|
|
1072
1120
|
const headersModule = await import('next/headers').catch(() => null)
|
|
@@ -1292,11 +1340,11 @@ export class BaseApiClient {
|
|
|
1292
1340
|
private readonly middleware: RequestMiddleware[] = []
|
|
1293
1341
|
|
|
1294
1342
|
constructor() {
|
|
1295
|
-
this.baseUrl = process.env.NEXT_PUBLIC_API_URL || process.env.API_BASE_URL || '${api
|
|
1296
|
-
this.defaultTimeout = ${api
|
|
1297
|
-
this.defaultRetries = ${api
|
|
1298
|
-
this.defaultHeaders = ${JSON.stringify(api
|
|
1299
|
-
this.defaultUserAgent = '${api
|
|
1343
|
+
this.baseUrl = process.env.NEXT_PUBLIC_API_URL || process.env.API_BASE_URL || '${api.baseUrl || "http://localhost:3000/api"}'
|
|
1344
|
+
this.defaultTimeout = ${api.timeout || 3e4}
|
|
1345
|
+
this.defaultRetries = ${api.retries || 3}
|
|
1346
|
+
this.defaultHeaders = ${JSON.stringify(api.headers || {}, null, 6)}
|
|
1347
|
+
this.defaultUserAgent = '${api.userAgent || "Mulink-Client/3.4.5"}'
|
|
1300
1348
|
|
|
1301
1349
|
// Add default middleware
|
|
1302
1350
|
this.addMiddleware({
|
|
@@ -1470,16 +1518,26 @@ export class BaseApiClient {
|
|
|
1470
1518
|
}
|
|
1471
1519
|
|
|
1472
1520
|
// Add query parameters with proper encoding
|
|
1521
|
+
// Filter out undefined, null, empty strings, and empty objects to prevent 422 errors
|
|
1473
1522
|
const searchParams = new URLSearchParams()
|
|
1474
1523
|
for (const [key, value] of Object.entries(queryParameters)) {
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1524
|
+
// Skip undefined, null, and empty strings
|
|
1525
|
+
if (value === undefined || value === null || value === '') {
|
|
1526
|
+
continue
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
// Skip empty objects (like {})
|
|
1530
|
+
if (typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length === 0) {
|
|
1531
|
+
continue
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
if (Array.isArray(value)) {
|
|
1535
|
+
value.forEach(v => searchParams.append(key, String(v)))
|
|
1536
|
+
} else if (typeof value === 'object') {
|
|
1537
|
+
// Only serialize non-empty objects
|
|
1538
|
+
searchParams.append(key, JSON.stringify(value))
|
|
1539
|
+
} else {
|
|
1540
|
+
searchParams.append(key, String(value))
|
|
1483
1541
|
}
|
|
1484
1542
|
}
|
|
1485
1543
|
|
|
@@ -1652,7 +1710,7 @@ export class BaseApiClient {
|
|
|
1652
1710
|
controller.abort()
|
|
1653
1711
|
}, timeout)
|
|
1654
1712
|
|
|
1655
|
-
// Next.js 16.0.
|
|
1713
|
+
// Next.js 16.0.7: Build fetch options with cache tags and connection
|
|
1656
1714
|
// Only include next options if we're on the server (Next.js App Router)
|
|
1657
1715
|
const fetchInit: RequestInit & { next?: { tags?: string[]; revalidate?: number | false; connection?: string } } = {
|
|
1658
1716
|
...requestConfig,
|
|
@@ -1660,7 +1718,7 @@ export class BaseApiClient {
|
|
|
1660
1718
|
}
|
|
1661
1719
|
|
|
1662
1720
|
// Add Next.js-specific options only if we have cache tags, revalidate, or connection
|
|
1663
|
-
// Next.js 16.0.
|
|
1721
|
+
// Next.js 16.0.7: Enhanced cache tag support with updateTag
|
|
1664
1722
|
if (cacheTags && cacheTags.length > 0 || revalidate !== undefined || connection) {
|
|
1665
1723
|
fetchInit.next = {}
|
|
1666
1724
|
|
|
@@ -1672,7 +1730,7 @@ export class BaseApiClient {
|
|
|
1672
1730
|
fetchInit.next.revalidate = revalidate === false ? false : revalidate
|
|
1673
1731
|
}
|
|
1674
1732
|
|
|
1675
|
-
// Next.js 16.0.
|
|
1733
|
+
// Next.js 16.0.7: Connection keep-alive for persistent connections
|
|
1676
1734
|
if (connection) {
|
|
1677
1735
|
fetchInit.next.connection = connection
|
|
1678
1736
|
}
|
|
@@ -1680,7 +1738,7 @@ export class BaseApiClient {
|
|
|
1680
1738
|
|
|
1681
1739
|
const response = await fetch(url, fetchInit)
|
|
1682
1740
|
|
|
1683
|
-
// Next.js 16.0.
|
|
1741
|
+
// Next.js 16.0.7: Update cache tags dynamically using updateTag from next/cache
|
|
1684
1742
|
// This allows for granular cache invalidation
|
|
1685
1743
|
if (cacheTags && cacheTags.length > 0) {
|
|
1686
1744
|
try {
|
|
@@ -1944,7 +2002,7 @@ async get<TData>(
|
|
|
1944
2002
|
}
|
|
1945
2003
|
generateClientUtilities() {
|
|
1946
2004
|
const { api } = this.configuration;
|
|
1947
|
-
const errorHandling = api
|
|
2005
|
+
const errorHandling = api.errorHandling;
|
|
1948
2006
|
const enableAuthErrorHandling = errorHandling?.enableAuthErrorHandling !== false;
|
|
1949
2007
|
const authErrorHandlerPath = errorHandling?.authErrorHandlerPath || "@/lib/auth-error-handler";
|
|
1950
2008
|
const authErrorMiddlewareCode = enableAuthErrorHandling ? `
|
|
@@ -2341,7 +2399,7 @@ ${clientMethods}
|
|
|
2341
2399
|
const requestOptionsString = requestOptions.join("\n");
|
|
2342
2400
|
const methodSignature = parameterTypes.length > 1 ? `options: {
|
|
2343
2401
|
${parameterTypes.join("\n ")}
|
|
2344
|
-
}` : parameterTypes.length === 1 && parameterTypes[0].includes("config?") ? "options?: { config?: RequestConfiguration }" : `options: { ${parameterTypes.join(", ")} }`;
|
|
2402
|
+
}` : parameterTypes.length === 1 && parameterTypes[0] && parameterTypes[0].includes("config?") ? "options?: { config?: RequestConfiguration }" : `options: { ${parameterTypes.join(", ")} }`;
|
|
2345
2403
|
if (isQuery) {
|
|
2346
2404
|
return `${documentation}
|
|
2347
2405
|
${methodName} = cache(async (${methodSignature}) => {
|
|
@@ -2612,7 +2670,7 @@ var SchemaGenerator = class {
|
|
|
2612
2670
|
visiting.add(schemaName);
|
|
2613
2671
|
const schema = schemaMap.get(schemaName);
|
|
2614
2672
|
if (schema) {
|
|
2615
|
-
const dependencies = dependencyGraph.get(schemaName)
|
|
2673
|
+
const dependencies = dependencyGraph.get(schemaName) ?? /* @__PURE__ */ new Set();
|
|
2616
2674
|
for (const dep of dependencies) {
|
|
2617
2675
|
if (schemaMap.has(dep)) {
|
|
2618
2676
|
visit(dep);
|
|
@@ -2645,13 +2703,66 @@ var SchemaGenerator = class {
|
|
|
2645
2703
|
findSchemaDependencies(schema) {
|
|
2646
2704
|
const dependencies = [];
|
|
2647
2705
|
const schemaObj = schema.schema;
|
|
2648
|
-
if (schemaObj
|
|
2706
|
+
if (schemaObj?._def) {
|
|
2649
2707
|
this.extractDependenciesFromZodSchema(schemaObj, dependencies);
|
|
2650
2708
|
}
|
|
2651
2709
|
return dependencies;
|
|
2652
2710
|
}
|
|
2711
|
+
extractDependenciesFromDefinition(definition) {
|
|
2712
|
+
const dependencies = [];
|
|
2713
|
+
const schemaRefRegex = /([A-Z][a-zA-Z0-9]*Schema)\b/g;
|
|
2714
|
+
const matches = definition.matchAll(schemaRefRegex);
|
|
2715
|
+
for (const match of matches) {
|
|
2716
|
+
const schemaName = match[1];
|
|
2717
|
+
if (!schemaName) continue;
|
|
2718
|
+
const baseName = schemaName.replace(/Schema$/, "");
|
|
2719
|
+
if (!dependencies.includes(baseName)) {
|
|
2720
|
+
dependencies.push(baseName);
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
return dependencies;
|
|
2724
|
+
}
|
|
2725
|
+
orderDefinitionsByDependencies(definitions) {
|
|
2726
|
+
const visited = /* @__PURE__ */ new Set();
|
|
2727
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
2728
|
+
const result = [];
|
|
2729
|
+
const definitionMap = /* @__PURE__ */ new Map();
|
|
2730
|
+
for (const def of definitions) {
|
|
2731
|
+
const baseName = def.exportName.replace(/Schema$/, "");
|
|
2732
|
+
definitionMap.set(baseName, def);
|
|
2733
|
+
}
|
|
2734
|
+
const visit = /* @__PURE__ */ __name((exportName) => {
|
|
2735
|
+
const baseName = exportName.replace(/Schema$/, "");
|
|
2736
|
+
if (visiting.has(baseName)) {
|
|
2737
|
+
console.warn(`Circular dependency detected for schema: ${exportName}`);
|
|
2738
|
+
return;
|
|
2739
|
+
}
|
|
2740
|
+
if (visited.has(baseName)) {
|
|
2741
|
+
return;
|
|
2742
|
+
}
|
|
2743
|
+
visiting.add(baseName);
|
|
2744
|
+
const def = definitionMap.get(baseName);
|
|
2745
|
+
if (def) {
|
|
2746
|
+
for (const dep of def.dependencies) {
|
|
2747
|
+
if (definitionMap.has(dep)) {
|
|
2748
|
+
visit(`${dep}Schema`);
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
result.push(def);
|
|
2752
|
+
}
|
|
2753
|
+
visiting.delete(baseName);
|
|
2754
|
+
visited.add(baseName);
|
|
2755
|
+
}, "visit");
|
|
2756
|
+
for (const def of definitions) {
|
|
2757
|
+
const baseName = def.exportName.replace(/Schema$/, "");
|
|
2758
|
+
if (!visited.has(baseName)) {
|
|
2759
|
+
visit(def.exportName);
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
return result;
|
|
2763
|
+
}
|
|
2653
2764
|
extractDependenciesFromZodSchema(zodSchema, dependencies, visited = /* @__PURE__ */ new Set()) {
|
|
2654
|
-
if (!zodSchema
|
|
2765
|
+
if (!zodSchema?._def) return;
|
|
2655
2766
|
const def = zodSchema._def;
|
|
2656
2767
|
if (def._schemaRef) {
|
|
2657
2768
|
const refName = def._schemaRef;
|
|
@@ -2674,7 +2785,7 @@ var SchemaGenerator = class {
|
|
|
2674
2785
|
case "ZodObject":
|
|
2675
2786
|
if (def.shape) {
|
|
2676
2787
|
const shape = def.shape();
|
|
2677
|
-
for (const [
|
|
2788
|
+
for (const [_key, value] of Object.entries(shape)) {
|
|
2678
2789
|
this.extractDependenciesFromZodSchema(value, dependencies, visited);
|
|
2679
2790
|
}
|
|
2680
2791
|
}
|
|
@@ -2706,22 +2817,31 @@ var SchemaGenerator = class {
|
|
|
2706
2817
|
break;
|
|
2707
2818
|
}
|
|
2708
2819
|
}
|
|
2709
|
-
|
|
2820
|
+
generateSchemasFile(context) {
|
|
2710
2821
|
const { schemas, endpoints } = context.schema;
|
|
2711
2822
|
const imports = ['import { z } from "zod"'];
|
|
2712
2823
|
const schemaExports = [];
|
|
2713
|
-
const
|
|
2824
|
+
const allSchemaDefinitions = [];
|
|
2714
2825
|
const orderedSchemas = this.orderSchemasByDependencies(schemas);
|
|
2715
2826
|
for (const schema of orderedSchemas) {
|
|
2716
2827
|
const { definition, exportName } = this.generateSchemaDefinition(schema);
|
|
2717
|
-
|
|
2828
|
+
const dependencies = this.findSchemaDependencies(schema);
|
|
2829
|
+
allSchemaDefinitions.push({ definition, exportName, dependencies });
|
|
2718
2830
|
schemaExports.push(exportName);
|
|
2719
2831
|
}
|
|
2720
2832
|
for (const endpoint of endpoints) {
|
|
2721
2833
|
const endpointSchemas = this.generateEndpointSchemas(endpoint);
|
|
2722
|
-
|
|
2723
|
-
|
|
2834
|
+
for (let i = 0; i < endpointSchemas.definitions.length; i++) {
|
|
2835
|
+
const definition = endpointSchemas.definitions[i];
|
|
2836
|
+
const exportName = endpointSchemas.exports[i];
|
|
2837
|
+
if (!definition || !exportName) continue;
|
|
2838
|
+
const dependencies = this.extractDependenciesFromDefinition(definition);
|
|
2839
|
+
allSchemaDefinitions.push({ definition, exportName, dependencies });
|
|
2840
|
+
schemaExports.push(exportName);
|
|
2841
|
+
}
|
|
2724
2842
|
}
|
|
2843
|
+
const orderedDefinitions = this.orderDefinitionsByDependencies(allSchemaDefinitions);
|
|
2844
|
+
const schemaDefinitions = orderedDefinitions.map((item) => item.definition);
|
|
2725
2845
|
const validationHelpers = this.generateValidationHelpers();
|
|
2726
2846
|
const contentWithImports = [
|
|
2727
2847
|
...imports,
|
|
@@ -2740,7 +2860,7 @@ var SchemaGenerator = class {
|
|
|
2740
2860
|
|
|
2741
2861
|
${content}`;
|
|
2742
2862
|
}
|
|
2743
|
-
return {
|
|
2863
|
+
return Promise.resolve({
|
|
2744
2864
|
path: "schemas/index.ts",
|
|
2745
2865
|
content,
|
|
2746
2866
|
type: "typescript",
|
|
@@ -2749,7 +2869,7 @@ ${content}`;
|
|
|
2749
2869
|
imports: ["zod"],
|
|
2750
2870
|
dependencies: []
|
|
2751
2871
|
}
|
|
2752
|
-
};
|
|
2872
|
+
});
|
|
2753
2873
|
}
|
|
2754
2874
|
generateEndpointSchemas(endpoint) {
|
|
2755
2875
|
const definitions = [];
|
|
@@ -2784,6 +2904,9 @@ ${content}`;
|
|
|
2784
2904
|
}
|
|
2785
2905
|
const exportName = `${operationName}RequestSchema`;
|
|
2786
2906
|
const primaryContent = endpoint.requestBody.content[0];
|
|
2907
|
+
if (!primaryContent) {
|
|
2908
|
+
throw new Error(`No content found for request body in ${endpoint.method} ${endpoint.path}`);
|
|
2909
|
+
}
|
|
2787
2910
|
const zodSchemaString = this.zodSchemaToString(primaryContent.schema);
|
|
2788
2911
|
const definition = [
|
|
2789
2912
|
`/**`,
|
|
@@ -2807,17 +2930,22 @@ ${content}`;
|
|
|
2807
2930
|
);
|
|
2808
2931
|
if (successResponses.length > 0) {
|
|
2809
2932
|
const successResponse = successResponses[0];
|
|
2933
|
+
if (!successResponse) {
|
|
2934
|
+
return { definitions, exports };
|
|
2935
|
+
}
|
|
2810
2936
|
let zodSchemaString = "z.void()";
|
|
2811
2937
|
if (successResponse.content && successResponse.content.length > 0) {
|
|
2812
2938
|
const primaryContent = successResponse.content[0];
|
|
2813
|
-
|
|
2939
|
+
if (primaryContent) {
|
|
2940
|
+
zodSchemaString = this.zodSchemaToString(primaryContent.schema);
|
|
2941
|
+
}
|
|
2814
2942
|
}
|
|
2815
2943
|
const exportName = `${operationName}ResponseSchema`;
|
|
2816
2944
|
const definition = [
|
|
2817
2945
|
`/**`,
|
|
2818
2946
|
` * Success response schema for ${endpoint.method} ${endpoint.path}`,
|
|
2819
2947
|
` * Status: ${successResponse.statusCode}`,
|
|
2820
|
-
` * ${successResponse.description}`,
|
|
2948
|
+
` * ${successResponse.description ?? ""}`,
|
|
2821
2949
|
` */`,
|
|
2822
2950
|
`export const ${exportName} = ${zodSchemaString}`,
|
|
2823
2951
|
"",
|
|
@@ -2828,15 +2956,18 @@ ${content}`;
|
|
|
2828
2956
|
}
|
|
2829
2957
|
if (errorResponses.length > 0) {
|
|
2830
2958
|
const errorResponse = errorResponses[0];
|
|
2831
|
-
if (errorResponse
|
|
2959
|
+
if (errorResponse?.content && errorResponse.content.length > 0) {
|
|
2832
2960
|
const exportName = `${operationName}ErrorSchema`;
|
|
2833
2961
|
const primaryContent = errorResponse.content[0];
|
|
2962
|
+
if (!primaryContent) {
|
|
2963
|
+
return { definitions, exports };
|
|
2964
|
+
}
|
|
2834
2965
|
const zodSchemaString = this.zodSchemaToString(primaryContent.schema);
|
|
2835
2966
|
const definition = [
|
|
2836
2967
|
`/**`,
|
|
2837
2968
|
` * Error response schema for ${endpoint.method} ${endpoint.path}`,
|
|
2838
2969
|
` * Status: ${errorResponse.statusCode}`,
|
|
2839
|
-
` * ${errorResponse.description}`,
|
|
2970
|
+
` * ${errorResponse.description ?? ""}`,
|
|
2840
2971
|
` */`,
|
|
2841
2972
|
`export const ${exportName} = ${zodSchemaString}`,
|
|
2842
2973
|
"",
|
|
@@ -2927,8 +3058,8 @@ ${schemaProperties.join(",\n")}
|
|
|
2927
3058
|
};
|
|
2928
3059
|
}
|
|
2929
3060
|
zodSchemaToString(schema, context) {
|
|
2930
|
-
if (!schema
|
|
2931
|
-
if (schema
|
|
3061
|
+
if (!schema?._def) {
|
|
3062
|
+
if (schema?._schemaRef) {
|
|
2932
3063
|
const refName = schema._schemaRef;
|
|
2933
3064
|
const registeredSchema = this.schemaRegistry.get(refName);
|
|
2934
3065
|
if (registeredSchema) {
|
|
@@ -3096,15 +3227,21 @@ export const errorMessages = {
|
|
|
3096
3227
|
const assignments = line.match(/(\w+)\s*[:=]/g);
|
|
3097
3228
|
if (assignments) {
|
|
3098
3229
|
assignments.forEach((match) => {
|
|
3099
|
-
const
|
|
3100
|
-
|
|
3230
|
+
const parts = match.split(/[:=]/);
|
|
3231
|
+
if (parts[0]) {
|
|
3232
|
+
const identifier = parts[0].trim();
|
|
3233
|
+
usedIdentifiers.add(identifier);
|
|
3234
|
+
}
|
|
3101
3235
|
});
|
|
3102
3236
|
}
|
|
3103
3237
|
const functionCalls = line.match(/(\w+)\s*\(/g);
|
|
3104
3238
|
if (functionCalls) {
|
|
3105
3239
|
functionCalls.forEach((match) => {
|
|
3106
|
-
const
|
|
3107
|
-
|
|
3240
|
+
const parts = match.split("(");
|
|
3241
|
+
if (parts[0]) {
|
|
3242
|
+
const identifier = parts[0].trim();
|
|
3243
|
+
usedIdentifiers.add(identifier);
|
|
3244
|
+
}
|
|
3108
3245
|
});
|
|
3109
3246
|
}
|
|
3110
3247
|
if (line.includes("z.infer")) {
|
|
@@ -3122,10 +3259,10 @@ export const errorMessages = {
|
|
|
3122
3259
|
continue;
|
|
3123
3260
|
}
|
|
3124
3261
|
const importMatch = line.match(/import\s*\{([^}]+)\}/);
|
|
3125
|
-
if (importMatch) {
|
|
3262
|
+
if (importMatch?.[1]) {
|
|
3126
3263
|
const imports = importMatch[1].split(",").map((imp) => imp.trim());
|
|
3127
3264
|
const usedImports = imports.filter((imp) => usedIdentifiers.has(imp));
|
|
3128
|
-
if (usedImports.length > 0) {
|
|
3265
|
+
if (usedImports.length > 0 && importMatch[1]) {
|
|
3129
3266
|
cleanedLines.push(line.replace(importMatch[1], usedImports.join(", ")));
|
|
3130
3267
|
} else {
|
|
3131
3268
|
continue;
|
|
@@ -3172,7 +3309,7 @@ var ActionGenerator = class {
|
|
|
3172
3309
|
if (!this.documentationEnabled) {
|
|
3173
3310
|
return "";
|
|
3174
3311
|
}
|
|
3175
|
-
const summary = endpoint.summary
|
|
3312
|
+
const summary = endpoint.summary ?? endpoint.description ?? `${endpoint.method} ${endpoint.path}`;
|
|
3176
3313
|
return `/**
|
|
3177
3314
|
* ${summary}
|
|
3178
3315
|
* @generated from ${endpoint.method} ${endpoint.path}
|
|
@@ -3314,7 +3451,7 @@ ${" ".repeat(indent + 2)}error: error instanceof Error ? error.message : 'Unknow
|
|
|
3314
3451
|
${" ".repeat(indent)}})`;
|
|
3315
3452
|
}
|
|
3316
3453
|
buildImportPath(relativePath) {
|
|
3317
|
-
const outputDirectory = this.configuration.outputDir
|
|
3454
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
3318
3455
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
3319
3456
|
let importBasePath = outputDirectory;
|
|
3320
3457
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -3322,7 +3459,7 @@ ${" ".repeat(indent)}})`;
|
|
|
3322
3459
|
}
|
|
3323
3460
|
return `@/${importBasePath}/${cleanPath}`;
|
|
3324
3461
|
}
|
|
3325
|
-
|
|
3462
|
+
generate(context) {
|
|
3326
3463
|
const { schema, config } = context;
|
|
3327
3464
|
const generatedFiles = [];
|
|
3328
3465
|
const endpointsByTag = this.groupEndpointsByTag(schema.endpoints);
|
|
@@ -3416,7 +3553,7 @@ ${actions}`;
|
|
|
3416
3553
|
dependencies: Object.keys(endpointsByTag).map((tag) => `./${toValidIdentifier(tag)}`)
|
|
3417
3554
|
}
|
|
3418
3555
|
});
|
|
3419
|
-
return generatedFiles;
|
|
3556
|
+
return Promise.resolve(generatedFiles);
|
|
3420
3557
|
}
|
|
3421
3558
|
getOperationName(endpoint) {
|
|
3422
3559
|
if (endpoint.operationId) {
|
|
@@ -3429,7 +3566,7 @@ ${actions}`;
|
|
|
3429
3566
|
const method = this.toPascalCase(endpoint.method.toLowerCase());
|
|
3430
3567
|
return [...pathParts, method].join("");
|
|
3431
3568
|
}
|
|
3432
|
-
generateOptimizedServerAction(endpoint,
|
|
3569
|
+
generateOptimizedServerAction(endpoint, _config) {
|
|
3433
3570
|
const actionName = toActionName(endpoint.operationId || endpoint.id);
|
|
3434
3571
|
const operationName = this.getOperationName(endpoint);
|
|
3435
3572
|
const hasRequestBody = !!endpoint.requestBody;
|
|
@@ -3711,7 +3848,7 @@ var HookGenerator = class {
|
|
|
3711
3848
|
}
|
|
3712
3849
|
return `@/${importBasePath}/${cleanPath}`;
|
|
3713
3850
|
}
|
|
3714
|
-
|
|
3851
|
+
generate(context) {
|
|
3715
3852
|
const { schema } = context;
|
|
3716
3853
|
const generatedFiles = [];
|
|
3717
3854
|
const endpointsByTag = this.groupEndpointsByTag(schema.endpoints);
|
|
@@ -3844,7 +3981,7 @@ ${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier
|
|
|
3844
3981
|
dependencies: ["./useBridgeQuery", ...Object.keys(endpointsByTag).map((tag) => `./${toValidIdentifier(tag)}`)]
|
|
3845
3982
|
}
|
|
3846
3983
|
});
|
|
3847
|
-
return generatedFiles;
|
|
3984
|
+
return Promise.resolve(generatedFiles);
|
|
3848
3985
|
}
|
|
3849
3986
|
getOperationName(endpoint) {
|
|
3850
3987
|
if (endpoint.operationId) {
|
|
@@ -3861,62 +3998,78 @@ ${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier
|
|
|
3861
3998
|
const hookName = toHookName(endpoint.operationId || endpoint.id, true);
|
|
3862
3999
|
const actionName = toActionName(endpoint.operationId || endpoint.id);
|
|
3863
4000
|
const operationName = this.getOperationName(endpoint);
|
|
3864
|
-
const queryKey = this.generateQueryKey(endpoint);
|
|
3865
4001
|
const staleTime = this.getStaleTime(endpoint);
|
|
3866
4002
|
const pathParameters = endpoint.parameters.filter((parameter) => parameter.in === "path");
|
|
3867
4003
|
const queryParameters = endpoint.parameters.filter((parameter) => parameter.in === "query");
|
|
3868
4004
|
const hasPageParam = queryParameters.some((param) => param.name === "page");
|
|
3869
4005
|
const hasSearchParams = endpoint.path.includes("search") || endpoint.path.includes("list");
|
|
3870
|
-
|
|
3871
|
-
const
|
|
4006
|
+
const pathParamTypes = [];
|
|
4007
|
+
const queryParamTypes = [];
|
|
3872
4008
|
pathParameters.forEach((param) => {
|
|
3873
4009
|
const isRequired = param.required ? "" : "?";
|
|
3874
4010
|
const paramType = this.getTypeFromZodSchema(param.schema);
|
|
3875
|
-
|
|
4011
|
+
pathParamTypes.push(`${param.name}${isRequired}: ${paramType}`);
|
|
3876
4012
|
});
|
|
3877
4013
|
queryParameters.forEach((param) => {
|
|
3878
4014
|
const isRequired = param.required ? "" : "?";
|
|
3879
4015
|
const paramType = this.getTypeFromZodSchema(param.schema);
|
|
3880
|
-
|
|
4016
|
+
queryParamTypes.push(`${param.name}${isRequired}: ${paramType}`);
|
|
3881
4017
|
});
|
|
3882
4018
|
const returnType = `z.infer<typeof ${operationName}ResponseSchema>`;
|
|
3883
4019
|
const optionsType = `{ enabled?: boolean; suspense?: boolean; refetchInterval?: number; initialData?: ${returnType} }`;
|
|
3884
|
-
const
|
|
3885
|
-
|
|
4020
|
+
const paramsTypeParts = [];
|
|
4021
|
+
if (pathParameters.length > 0) {
|
|
4022
|
+
paramsTypeParts.push(`path: { ${pathParamTypes.join("; ")} }`);
|
|
4023
|
+
}
|
|
4024
|
+
if (queryParameters.length > 0) {
|
|
4025
|
+
paramsTypeParts.push(`query?: { ${queryParamTypes.join("; ")} }`);
|
|
4026
|
+
}
|
|
4027
|
+
const paramsType = paramsTypeParts.length > 0 ? `{ ${paramsTypeParts.join("; ")} }` : "{}";
|
|
4028
|
+
const enabledCondition = pathParameters.length > 0 && pathParameters[0] ? `!!params?.path?.${pathParameters[0].name}` : "true";
|
|
4029
|
+
const pathParamsBuild = pathParameters.length > 0 ? `{ ${pathParameters.map((p) => `${p.name}: params.path.${p.name}`).join(", ")} }` : "{}";
|
|
4030
|
+
const queryParamsBuild = queryParameters.length > 0 ? `{ ${queryParameters.map((p) => `${p.name}: params?.query?.${p.name}`).join(", ")} }` : "{}";
|
|
4031
|
+
const queryKeyParts = [`'${toActionName(endpoint.operationId || endpoint.id)}'`];
|
|
4032
|
+
if (pathParameters.length > 0) {
|
|
4033
|
+
queryKeyParts.push("params?.path");
|
|
4034
|
+
} else {
|
|
4035
|
+
queryKeyParts.push("null");
|
|
4036
|
+
}
|
|
4037
|
+
if (queryParameters.length > 0) {
|
|
4038
|
+
queryKeyParts.push("params?.query");
|
|
4039
|
+
}
|
|
4040
|
+
const queryKeyString = `[${queryKeyParts.join(", ")}]`;
|
|
4041
|
+
const hasAnyParams = pathParameters.length > 0 || queryParameters.length > 0;
|
|
4042
|
+
const actionCallString = pathParameters.length > 0 && queryParameters.length > 0 ? `{ path: ${pathParamsBuild}, query: ${queryParamsBuild} }` : pathParameters.length > 0 ? `{ path: ${pathParamsBuild} }` : queryParameters.length > 0 ? `{ query: ${queryParamsBuild} }` : "";
|
|
3886
4043
|
if (hasSearchParams) {
|
|
3887
|
-
const
|
|
3888
|
-
const isRequired = param.required;
|
|
3889
|
-
const paramType = this.getTypeFromZodSchema(param.schema);
|
|
3890
|
-
return `${param.name}${isRequired ? "" : "?"}: ${paramType}`;
|
|
3891
|
-
}).join("; ");
|
|
3892
|
-
const queryParamsBuild = queryParameters.length > 0 ? `// Build query params object with only the parameters the endpoint expects
|
|
3893
|
-
const queryParams: { ${queryParamTypes} } = {
|
|
4044
|
+
const queryParamsWithFallback = queryParameters.length > 0 ? `const queryParams = {
|
|
3894
4045
|
${queryParameters.map((param) => {
|
|
3895
4046
|
if (param.name === "query") {
|
|
3896
|
-
return `${param.name}:
|
|
4047
|
+
return `${param.name}: params?.query?.${param.name} || searchParams.search || ''`;
|
|
3897
4048
|
} else if (param.name === "limit") {
|
|
3898
|
-
return `${param.name}:
|
|
4049
|
+
return `${param.name}: params?.query?.${param.name} !== undefined ? params.query.${param.name} : searchParams.limit`;
|
|
3899
4050
|
} else {
|
|
3900
|
-
return `${param.name}:
|
|
4051
|
+
return `${param.name}: params?.query?.${param.name}`;
|
|
3901
4052
|
}
|
|
3902
4053
|
}).join(",\n ")}
|
|
3903
4054
|
}` : "";
|
|
3904
|
-
const
|
|
4055
|
+
const actionCallForSearchParams = queryParameters.length > 0 ? pathParameters.length > 0 ? `{ path: ${pathParamsBuild}, query: queryParams }` : "{ query: queryParams }" : pathParameters.length > 0 ? `{ path: ${pathParamsBuild} }` : hasAnyParams ? actionCallString : "";
|
|
3905
4056
|
return `/**
|
|
3906
4057
|
* Optimized query hook for ${endpoint.method} ${endpoint.path}
|
|
3907
4058
|
* Features: URL state sync, infinite loading, optimistic updates
|
|
4059
|
+
* @param params - Named parameters object with path and query parameters
|
|
4060
|
+
* @param options - Query options
|
|
3908
4061
|
* @returns useQuery result with data of type ${returnType}
|
|
3909
4062
|
*/
|
|
3910
|
-
export function ${hookName}(${
|
|
4063
|
+
export function ${hookName}(params${pathParameters.length > 0 ? "" : "?"}: ${paramsType}, options?: ${optionsType}) {
|
|
3911
4064
|
const [searchParams] = useQueryStates(searchParamsParser)
|
|
3912
4065
|
const { initialData, ...restOptions } = options ?? {}
|
|
3913
4066
|
|
|
3914
4067
|
return useQuery({
|
|
3915
|
-
queryKey: [
|
|
4068
|
+
queryKey: [${queryKeyString}, searchParams],
|
|
3916
4069
|
queryFn: async ({ signal }: { signal?: AbortSignal }) => {
|
|
3917
4070
|
try {
|
|
3918
|
-
${
|
|
3919
|
-
const result = await resolveActionResult<${returnType}>(${actionName}(${
|
|
4071
|
+
${queryParamsWithFallback}
|
|
4072
|
+
const result = await resolveActionResult<${returnType}>(${actionName}(${actionCallForSearchParams}))
|
|
3920
4073
|
return result
|
|
3921
4074
|
} catch (error) {
|
|
3922
4075
|
handleActionError(error)
|
|
@@ -3944,32 +4097,33 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3944
4097
|
|
|
3945
4098
|
/**
|
|
3946
4099
|
* Infinite query version for paginated ${endpoint.path}
|
|
4100
|
+
* @param params - Named parameters object with path and query parameters
|
|
4101
|
+
* @param options - Query options
|
|
3947
4102
|
* @returns useInfiniteQuery result with data of type ${returnType}
|
|
3948
4103
|
*/
|
|
3949
|
-
export function ${hookName.replace("use", "useInfinite")}(${
|
|
4104
|
+
export function ${hookName.replace("use", "useInfinite")}(params${pathParameters.length > 0 ? "" : "?"}: ${paramsType}, options?: ${optionsType}) {
|
|
3950
4105
|
const [searchParams] = useQueryStates(searchParamsParser)
|
|
3951
4106
|
const { initialData, ...restOptions } = options ?? {}
|
|
3952
4107
|
|
|
3953
4108
|
return useInfiniteQuery({
|
|
3954
|
-
queryKey: [
|
|
4109
|
+
queryKey: [${queryKeyString}, 'infinite', searchParams],
|
|
3955
4110
|
initialPageParam: 1,
|
|
3956
4111
|
queryFn: async ({ pageParam = 1, signal }: { pageParam?: number; signal?: AbortSignal }) => {
|
|
3957
4112
|
try {
|
|
3958
|
-
|
|
3959
|
-
const queryParams: { ${queryParamTypes} } = {
|
|
4113
|
+
const queryParams = {
|
|
3960
4114
|
${queryParameters.map((param) => {
|
|
3961
4115
|
if (param.name === "page" && hasPageParam) {
|
|
3962
4116
|
return `${param.name}: pageParam`;
|
|
3963
4117
|
} else if (param.name === "query") {
|
|
3964
|
-
return `${param.name}:
|
|
4118
|
+
return `${param.name}: params?.query?.${param.name} || searchParams.search || ''`;
|
|
3965
4119
|
} else if (param.name === "limit") {
|
|
3966
|
-
return `${param.name}:
|
|
4120
|
+
return `${param.name}: params?.query?.${param.name} !== undefined ? params.query.${param.name} : searchParams.limit`;
|
|
3967
4121
|
} else {
|
|
3968
|
-
return `${param.name}:
|
|
4122
|
+
return `${param.name}: params?.query?.${param.name}`;
|
|
3969
4123
|
}
|
|
3970
4124
|
}).join(",\n ")}
|
|
3971
4125
|
}
|
|
3972
|
-
const result = await resolveActionResult<${returnType}>(${actionName}(${
|
|
4126
|
+
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 : ""}))
|
|
3973
4127
|
return result
|
|
3974
4128
|
} catch (error) {
|
|
3975
4129
|
handleActionError(error)
|
|
@@ -4011,15 +4165,17 @@ export function ${hookName.replace("use", "useInfinite")}(${parameterTypes.lengt
|
|
|
4011
4165
|
|
|
4012
4166
|
/**
|
|
4013
4167
|
* Suspense version for ${endpoint.path} - use in Server Components
|
|
4168
|
+
* @param params - Named parameters object with path and query parameters
|
|
4169
|
+
* @param options - Query options
|
|
4014
4170
|
* @returns useSuspenseQuery result with data of type ${returnType}
|
|
4015
4171
|
*/
|
|
4016
|
-
export function ${hookName.replace("use", "useSuspense")}(${
|
|
4172
|
+
export function ${hookName.replace("use", "useSuspense")}(params${pathParameters.length > 0 ? "" : "?"}: ${paramsType}, options?: ${optionsType}) {
|
|
4017
4173
|
const { initialData, ...restOptions } = options ?? {}
|
|
4018
4174
|
|
|
4019
4175
|
return useSuspenseQuery({
|
|
4020
|
-
queryKey: ${
|
|
4176
|
+
queryKey: ${queryKeyString},
|
|
4021
4177
|
queryFn: async () => {
|
|
4022
|
-
const result = await resolveActionResult<${returnType}>(${actionName}(${
|
|
4178
|
+
const result = await resolveActionResult<${returnType}>(${actionName}(${actionCallString}))
|
|
4023
4179
|
return result
|
|
4024
4180
|
},
|
|
4025
4181
|
staleTime: ${staleTime},
|
|
@@ -4031,16 +4187,18 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
4031
4187
|
return `/**
|
|
4032
4188
|
* Optimized query hook for ${endpoint.method} ${endpoint.path}
|
|
4033
4189
|
* Features: Smart caching, error handling, type safety
|
|
4190
|
+
* @param params - Named parameters object with path and query parameters
|
|
4191
|
+
* @param options - Query options
|
|
4034
4192
|
* @returns useQuery result with data of type ${returnType}
|
|
4035
4193
|
*/
|
|
4036
|
-
export function ${hookName}(${
|
|
4194
|
+
export function ${hookName}(params${pathParameters.length > 0 ? "" : "?"}: ${paramsType}, options?: ${optionsType}) {
|
|
4037
4195
|
const { initialData, ...restOptions } = options ?? {}
|
|
4038
4196
|
|
|
4039
4197
|
return useQuery({
|
|
4040
|
-
queryKey: ${
|
|
4198
|
+
queryKey: ${queryKeyString},
|
|
4041
4199
|
queryFn: async ({ signal }: { signal?: AbortSignal }) => {
|
|
4042
4200
|
try {
|
|
4043
|
-
const result = await resolveActionResult<${returnType}>(${
|
|
4201
|
+
const result = await resolveActionResult<${returnType}>(${actionName}(${hasAnyParams ? actionCallString : ""}))
|
|
4044
4202
|
return result
|
|
4045
4203
|
} catch (error) {
|
|
4046
4204
|
handleActionError(error)
|
|
@@ -4068,15 +4226,17 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
4068
4226
|
|
|
4069
4227
|
/**
|
|
4070
4228
|
* Suspense version for ${endpoint.path}
|
|
4229
|
+
* @param params - Named parameters object with path and query parameters
|
|
4230
|
+
* @param options - Query options
|
|
4071
4231
|
* @returns useSuspenseQuery result with data of type ${returnType}
|
|
4072
4232
|
*/
|
|
4073
|
-
export function ${hookName.replace("use", "useSuspense")}(${
|
|
4233
|
+
export function ${hookName.replace("use", "useSuspense")}(params${pathParameters.length > 0 ? "" : "?"}: ${paramsType}, options?: ${optionsType}) {
|
|
4074
4234
|
const { initialData, ...restOptions } = options ?? {}
|
|
4075
4235
|
|
|
4076
4236
|
return useSuspenseQuery({
|
|
4077
|
-
queryKey: ${
|
|
4237
|
+
queryKey: ${queryKeyString},
|
|
4078
4238
|
queryFn: async () => {
|
|
4079
|
-
const result = await resolveActionResult<${returnType}>(${
|
|
4239
|
+
const result = await resolveActionResult<${returnType}>(${actionName}(${actionCallString}))
|
|
4080
4240
|
return result
|
|
4081
4241
|
},
|
|
4082
4242
|
staleTime: ${staleTime},
|
|
@@ -4191,7 +4351,7 @@ ${invalidationCode}
|
|
|
4191
4351
|
* Find related queries that should be invalidated when this mutation runs
|
|
4192
4352
|
*/
|
|
4193
4353
|
findRelatedQueries(endpoint, context) {
|
|
4194
|
-
if (!context?.schema
|
|
4354
|
+
if (!context?.schema.endpoints) {
|
|
4195
4355
|
return [];
|
|
4196
4356
|
}
|
|
4197
4357
|
const relatedQueries = [];
|
|
@@ -4325,7 +4485,6 @@ ${invalidationCode}
|
|
|
4325
4485
|
buildActionCallParams(endpoint, isMutation) {
|
|
4326
4486
|
const pathParameters = endpoint.parameters.filter((parameter) => parameter.in === "path");
|
|
4327
4487
|
const queryParameters = endpoint.parameters.filter((parameter) => parameter.in === "query");
|
|
4328
|
-
!!endpoint.requestBody;
|
|
4329
4488
|
if (isMutation) {
|
|
4330
4489
|
return "variables";
|
|
4331
4490
|
}
|
|
@@ -4406,13 +4565,13 @@ ${invalidationCode}
|
|
|
4406
4565
|
import { useQuery, useMutation, useInfiniteQuery, useSuspenseQuery, type UseQueryOptions, type UseMutationOptions, type UseInfiniteQueryOptions, type UseSuspenseQueryOptions, type QueryKey, type QueryFunction } from '@tanstack/react-query'
|
|
4407
4566
|
|
|
4408
4567
|
/**
|
|
4409
|
-
* Enhanced React Query wrapper hook with Next.js 16.0.
|
|
4568
|
+
* Enhanced React Query wrapper hook with Next.js 16.0.7 optimizations
|
|
4410
4569
|
* Provides consistent defaults across all queries following best practices
|
|
4411
4570
|
*
|
|
4412
4571
|
* Features:
|
|
4413
4572
|
* - React Query v5: Uses gcTime instead of cacheTime
|
|
4414
4573
|
* - React Query v5: Uses placeholderData instead of keepPreviousData
|
|
4415
|
-
* - Next.js 16.0.
|
|
4574
|
+
* - Next.js 16.0.7: Optimized for App Router and Server Components
|
|
4416
4575
|
*/
|
|
4417
4576
|
export function useBridgeQuery<TData = unknown, TError = Error>(
|
|
4418
4577
|
queryKey: QueryKey,
|
|
@@ -4469,7 +4628,7 @@ export function useBridgeInfiniteQuery<TData = unknown, TError = Error, TPagePar
|
|
|
4469
4628
|
|
|
4470
4629
|
/**
|
|
4471
4630
|
* Enhanced suspense query wrapper
|
|
4472
|
-
* Next.js 16.0.
|
|
4631
|
+
* Next.js 16.0.7: Optimized for Server Components with Suspense
|
|
4473
4632
|
*/
|
|
4474
4633
|
export function useBridgeSuspenseQuery<TData = unknown, TError = Error>(
|
|
4475
4634
|
queryKey: QueryKey,
|
|
@@ -4525,7 +4684,7 @@ var AuthGenerator = class {
|
|
|
4525
4684
|
__name(this, "AuthGenerator");
|
|
4526
4685
|
}
|
|
4527
4686
|
buildImportPath(relativePath) {
|
|
4528
|
-
const outputDirectory = this.configuration.outputDir
|
|
4687
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
4529
4688
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
4530
4689
|
let importBasePath = outputDirectory;
|
|
4531
4690
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -4533,11 +4692,11 @@ var AuthGenerator = class {
|
|
|
4533
4692
|
}
|
|
4534
4693
|
return `@/${importBasePath}/${cleanPath}`;
|
|
4535
4694
|
}
|
|
4536
|
-
|
|
4695
|
+
generate(context) {
|
|
4537
4696
|
const { config, schema } = context;
|
|
4538
4697
|
const authConfig = config.auth;
|
|
4539
4698
|
if (!authConfig?.enabled) {
|
|
4540
|
-
return [];
|
|
4699
|
+
return Promise.resolve([]);
|
|
4541
4700
|
}
|
|
4542
4701
|
const files = [];
|
|
4543
4702
|
const authEndpoints = this.findAuthEndpoints(schema.endpoints);
|
|
@@ -4552,7 +4711,7 @@ var AuthGenerator = class {
|
|
|
4552
4711
|
files.push(...this.generateAuthComponents(authEndpoints));
|
|
4553
4712
|
files.push(this.generateAuthMiddleware());
|
|
4554
4713
|
files.push(this.generateAuthContext());
|
|
4555
|
-
return files;
|
|
4714
|
+
return Promise.resolve(files);
|
|
4556
4715
|
}
|
|
4557
4716
|
findAuthEndpoints(endpoints) {
|
|
4558
4717
|
const authEndpoints = {};
|
|
@@ -4585,12 +4744,12 @@ var AuthGenerator = class {
|
|
|
4585
4744
|
}
|
|
4586
4745
|
return userEndpoints;
|
|
4587
4746
|
}
|
|
4588
|
-
generateAuthSchemas(
|
|
4747
|
+
generateAuthSchemas(_authEndpoints, _schema) {
|
|
4589
4748
|
this.buildImportPath("schemas");
|
|
4590
|
-
const loginRequestSchema =
|
|
4749
|
+
const loginRequestSchema = _authEndpoints.login?.requestBody?.content?.find(
|
|
4591
4750
|
(c) => c.type === "application/json"
|
|
4592
4751
|
)?.schema;
|
|
4593
|
-
const loginResponseSchema =
|
|
4752
|
+
const loginResponseSchema = _authEndpoints.login?.responses?.find(
|
|
4594
4753
|
(r) => r.statusCode === "200"
|
|
4595
4754
|
)?.content?.[0]?.schema;
|
|
4596
4755
|
const content = `import { z } from "zod"
|
|
@@ -4691,7 +4850,7 @@ export type Session = z.infer<typeof sessionSchema>`;
|
|
|
4691
4850
|
}
|
|
4692
4851
|
};
|
|
4693
4852
|
}
|
|
4694
|
-
generateAuthTypes(
|
|
4853
|
+
generateAuthTypes(_authEndpoints, _schema) {
|
|
4695
4854
|
const schemasImport = this.buildImportPath("auth/schemas");
|
|
4696
4855
|
const content = `// Auto-generated authentication types
|
|
4697
4856
|
import type {
|
|
@@ -5237,7 +5396,7 @@ export const useRequireAuth = (redirectTo?: string) => {
|
|
|
5237
5396
|
}
|
|
5238
5397
|
};
|
|
5239
5398
|
}
|
|
5240
|
-
generateAuthActions(
|
|
5399
|
+
generateAuthActions(_authEndpoints, _userEndpoints) {
|
|
5241
5400
|
const safeActionImport = this.buildImportPath("lib/safe-action");
|
|
5242
5401
|
const schemasImport = this.buildImportPath("auth/schemas");
|
|
5243
5402
|
const clientImport = this.buildImportPath("auth/client");
|
|
@@ -5469,7 +5628,7 @@ export const useCredentialsLogin = () => {
|
|
|
5469
5628
|
}
|
|
5470
5629
|
};
|
|
5471
5630
|
}
|
|
5472
|
-
generateAuthComponents(
|
|
5631
|
+
generateAuthComponents(_authEndpoints) {
|
|
5473
5632
|
const loginForm = {
|
|
5474
5633
|
path: "auth/components/login-form.tsx",
|
|
5475
5634
|
content: `"use client"
|
|
@@ -5589,7 +5748,6 @@ export function LoginForm() {
|
|
|
5589
5748
|
return [loginForm];
|
|
5590
5749
|
}
|
|
5591
5750
|
generateAuthMiddleware() {
|
|
5592
|
-
this.buildImportPath("auth/utils");
|
|
5593
5751
|
const content = `import { NextResponse } from "next/server"
|
|
5594
5752
|
import type { NextRequest } from "next/server"
|
|
5595
5753
|
|
|
@@ -5957,9 +6115,10 @@ var SchemaAnalyzer = class {
|
|
|
5957
6115
|
}
|
|
5958
6116
|
if (response.description) {
|
|
5959
6117
|
const errorMatch = response.description.match(/error[_\s]?code[:\s]+(\w+)/i);
|
|
5960
|
-
if (errorMatch) {
|
|
5961
|
-
|
|
5962
|
-
|
|
6118
|
+
if (errorMatch?.[1]) {
|
|
6119
|
+
const errorCode = errorMatch[1];
|
|
6120
|
+
errorCodes.set(errorCode.toLowerCase(), {
|
|
6121
|
+
code: errorCode,
|
|
5963
6122
|
status,
|
|
5964
6123
|
message: response.description
|
|
5965
6124
|
});
|
|
@@ -6045,7 +6204,7 @@ var SchemaAnalyzer = class {
|
|
|
6045
6204
|
const endpoints = {};
|
|
6046
6205
|
for (const endpoint of this.schema.endpoints) {
|
|
6047
6206
|
const path3 = endpoint.path.toLowerCase();
|
|
6048
|
-
const operationId = (endpoint.operationId
|
|
6207
|
+
const operationId = (endpoint.operationId ?? "").toLowerCase();
|
|
6049
6208
|
if ((path3.includes("/auth/login/credentials") || operationId.includes("logincredentials") || operationId.includes("signin")) && endpoint.method === "POST") {
|
|
6050
6209
|
endpoints.loginCredentials = endpoint;
|
|
6051
6210
|
} else if ((path3.includes("/auth/login") || operationId.includes("login")) && endpoint.method === "POST" && !endpoints.loginCredentials) {
|
|
@@ -6093,12 +6252,12 @@ var SchemaAnalyzer = class {
|
|
|
6093
6252
|
extractSessionConfig() {
|
|
6094
6253
|
const config = {};
|
|
6095
6254
|
const sessionEndpoints = this.schema.endpoints.filter(
|
|
6096
|
-
(e) => e.path.toLowerCase().includes("/session") || (e.operationId
|
|
6255
|
+
(e) => e.path.toLowerCase().includes("/session") || (e.operationId ?? "").toLowerCase().includes("session")
|
|
6097
6256
|
);
|
|
6098
6257
|
for (const endpoint of sessionEndpoints) {
|
|
6099
6258
|
for (const response of endpoint.responses) {
|
|
6100
6259
|
if (response.headers) {
|
|
6101
|
-
for (const [headerName,
|
|
6260
|
+
for (const [headerName, _headerDef] of Object.entries(response.headers)) {
|
|
6102
6261
|
if (headerName.toLowerCase().includes("expires") || headerName.toLowerCase().includes("max-age")) ;
|
|
6103
6262
|
}
|
|
6104
6263
|
}
|
|
@@ -6178,7 +6337,7 @@ var SchemaAnalyzer = class {
|
|
|
6178
6337
|
/**
|
|
6179
6338
|
* Check if OAuth provider is supported
|
|
6180
6339
|
*/
|
|
6181
|
-
isOAuthProviderSupported(
|
|
6340
|
+
isOAuthProviderSupported(_provider) {
|
|
6182
6341
|
const extractedEndpoints = this.extractAuthEndpoints();
|
|
6183
6342
|
return !!(extractedEndpoints.oauthAuthorize && extractedEndpoints.oauthCallback);
|
|
6184
6343
|
}
|
|
@@ -6260,7 +6419,7 @@ var SchemaAnalyzer = class {
|
|
|
6260
6419
|
errorCodes.set(code.toLowerCase(), {
|
|
6261
6420
|
code,
|
|
6262
6421
|
status,
|
|
6263
|
-
message: schema.properties?.detail?.default
|
|
6422
|
+
message: schema.properties?.detail?.default ?? schema.properties?.message?.default ?? ""
|
|
6264
6423
|
});
|
|
6265
6424
|
});
|
|
6266
6425
|
}
|
|
@@ -6269,9 +6428,10 @@ var SchemaAnalyzer = class {
|
|
|
6269
6428
|
const detail = schema.properties.detail;
|
|
6270
6429
|
if (typeof detail === "string") {
|
|
6271
6430
|
const codeMatch = detail.match(/(\w+)[_\s]?error/i);
|
|
6272
|
-
if (codeMatch) {
|
|
6273
|
-
|
|
6274
|
-
|
|
6431
|
+
if (codeMatch?.[1]) {
|
|
6432
|
+
const errorCode = codeMatch[1];
|
|
6433
|
+
errorCodes.set(errorCode.toLowerCase(), {
|
|
6434
|
+
code: errorCode,
|
|
6275
6435
|
status,
|
|
6276
6436
|
message: detail
|
|
6277
6437
|
});
|
|
@@ -6283,11 +6443,11 @@ var SchemaAnalyzer = class {
|
|
|
6283
6443
|
if (!schema || typeof schema !== "object") return;
|
|
6284
6444
|
if (schema.properties?.file) {
|
|
6285
6445
|
const fileSchema = schema.properties.file;
|
|
6286
|
-
if (fileSchema.maxSize
|
|
6287
|
-
config.maxSize = fileSchema.maxSize
|
|
6446
|
+
if (fileSchema.maxSize ?? fileSchema["x-max-size"]) {
|
|
6447
|
+
config.maxSize = fileSchema.maxSize ?? fileSchema["x-max-size"];
|
|
6288
6448
|
}
|
|
6289
|
-
if (fileSchema.allowedTypes
|
|
6290
|
-
config.allowedTypes = fileSchema.allowedTypes
|
|
6449
|
+
if (fileSchema.allowedTypes ?? fileSchema["x-allowed-types"]) {
|
|
6450
|
+
config.allowedTypes = fileSchema.allowedTypes ?? fileSchema["x-allowed-types"];
|
|
6291
6451
|
}
|
|
6292
6452
|
}
|
|
6293
6453
|
if (schema["x-file-constraints"]) {
|
|
@@ -6307,7 +6467,7 @@ var NextAuthGenerator = class {
|
|
|
6307
6467
|
analyzer;
|
|
6308
6468
|
accountStatusPatterns;
|
|
6309
6469
|
buildImportPath(relativePath) {
|
|
6310
|
-
const outputDirectory = this.configuration.outputDir
|
|
6470
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
6311
6471
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
6312
6472
|
let importBasePath = outputDirectory;
|
|
6313
6473
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -6315,11 +6475,11 @@ var NextAuthGenerator = class {
|
|
|
6315
6475
|
}
|
|
6316
6476
|
return `@/${importBasePath}/${cleanPath}`;
|
|
6317
6477
|
}
|
|
6318
|
-
|
|
6478
|
+
generate(context) {
|
|
6319
6479
|
const { config, schema } = context;
|
|
6320
6480
|
const authConfig = config.auth;
|
|
6321
6481
|
if (!authConfig?.enabled || authConfig.provider !== "next-auth") {
|
|
6322
|
-
return [];
|
|
6482
|
+
return Promise.resolve([]);
|
|
6323
6483
|
}
|
|
6324
6484
|
this.analyzer = new SchemaAnalyzer(schema);
|
|
6325
6485
|
this.accountStatusPatterns = this.analyzer.extractAccountStatusPatterns();
|
|
@@ -6336,7 +6496,7 @@ var NextAuthGenerator = class {
|
|
|
6336
6496
|
console.warn("These features will be disabled in generated code.\n");
|
|
6337
6497
|
}
|
|
6338
6498
|
const detectedOAuthProviders = this.analyzer.extractOAuthProviders();
|
|
6339
|
-
const configuredOAuthProviders = authConfig.oauth?.providers
|
|
6499
|
+
const configuredOAuthProviders = authConfig.oauth?.providers ?? [];
|
|
6340
6500
|
const validOAuthProviders = configuredOAuthProviders.filter(
|
|
6341
6501
|
(provider) => this.analyzer.isOAuthProviderSupported(provider)
|
|
6342
6502
|
);
|
|
@@ -6347,7 +6507,7 @@ var NextAuthGenerator = class {
|
|
|
6347
6507
|
console.warn(
|
|
6348
6508
|
`\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.`
|
|
6349
6509
|
);
|
|
6350
|
-
return files;
|
|
6510
|
+
return Promise.resolve(files);
|
|
6351
6511
|
}
|
|
6352
6512
|
files.push(this.generateNextAuthConfig(
|
|
6353
6513
|
extractedEndpoints,
|
|
@@ -6360,7 +6520,7 @@ var NextAuthGenerator = class {
|
|
|
6360
6520
|
if (hasPasskeys) {
|
|
6361
6521
|
files.push(this.generatePasskeyUtils(extractedEndpoints));
|
|
6362
6522
|
}
|
|
6363
|
-
return files;
|
|
6523
|
+
return Promise.resolve(files);
|
|
6364
6524
|
}
|
|
6365
6525
|
findAuthEndpoints(endpoints) {
|
|
6366
6526
|
const authEndpoints = {};
|
|
@@ -6463,14 +6623,14 @@ var NextAuthGenerator = class {
|
|
|
6463
6623
|
}
|
|
6464
6624
|
generateNextAuthConfig(extractedEndpoints, oauthProviders, hasMFA, hasPasskeys) {
|
|
6465
6625
|
const authConfig = this.configuration.auth;
|
|
6466
|
-
const apiBaseUrl = this.configuration.api
|
|
6626
|
+
const apiBaseUrl = this.configuration.api.baseUrl || "http://localhost:8000";
|
|
6467
6627
|
const apiUrl = `process.env.NEXT_PUBLIC_API_URL || '${apiBaseUrl}'`;
|
|
6468
6628
|
const hasGoogle = oauthProviders.includes("google");
|
|
6469
6629
|
const hasGitHub = oauthProviders.includes("github");
|
|
6470
6630
|
oauthProviders.includes("discord");
|
|
6471
6631
|
oauthProviders.includes("microsoft");
|
|
6472
6632
|
oauthProviders.includes("apple");
|
|
6473
|
-
const { activeStatuses, inactiveStatuses, suspendedStatuses, lockedStatuses } = this.accountStatusPatterns;
|
|
6633
|
+
const { activeStatuses, inactiveStatuses, suspendedStatuses, lockedStatuses: _lockedStatuses } = this.accountStatusPatterns;
|
|
6474
6634
|
this.analyzer.extractErrorCodes();
|
|
6475
6635
|
const sessionStrategy = authConfig.session?.strategy || "jwt";
|
|
6476
6636
|
const sessionMaxAge = authConfig.session?.maxAge || 7 * 24 * 60 * 60;
|
|
@@ -7019,7 +7179,7 @@ export async function authenticateWithPasskey(email?: string) {
|
|
|
7019
7179
|
}
|
|
7020
7180
|
};
|
|
7021
7181
|
}
|
|
7022
|
-
generateAuthTypes(
|
|
7182
|
+
generateAuthTypes(_authEndpoints, _accountStatusPatterns) {
|
|
7023
7183
|
const content = `/**
|
|
7024
7184
|
* Authentication Types
|
|
7025
7185
|
* Auto-generated by Mulink
|
|
@@ -7090,7 +7250,7 @@ export class AccountInactiveError extends AuthError {
|
|
|
7090
7250
|
}
|
|
7091
7251
|
};
|
|
7092
7252
|
}
|
|
7093
|
-
generateAuthUtils(
|
|
7253
|
+
generateAuthUtils(_authEndpoints) {
|
|
7094
7254
|
const content = `/**
|
|
7095
7255
|
* Authentication Utilities
|
|
7096
7256
|
* Auto-generated by Mulink
|
|
@@ -7143,7 +7303,7 @@ export async function requireAuth() {
|
|
|
7143
7303
|
}
|
|
7144
7304
|
};
|
|
7145
7305
|
}
|
|
7146
|
-
generatePasskeyUtils(
|
|
7306
|
+
generatePasskeyUtils(_passkeyEndpoints) {
|
|
7147
7307
|
const content = `/**
|
|
7148
7308
|
* Passkey (WebAuthn) Utilities
|
|
7149
7309
|
* Auto-generated by Mulink
|
|
@@ -7196,7 +7356,7 @@ var MiddlewareGenerator = class {
|
|
|
7196
7356
|
__name(this, "MiddlewareGenerator");
|
|
7197
7357
|
}
|
|
7198
7358
|
buildImportPath(relativePath) {
|
|
7199
|
-
const outputDirectory = this.configuration.outputDir
|
|
7359
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
7200
7360
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
7201
7361
|
let importBasePath = outputDirectory;
|
|
7202
7362
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -7204,7 +7364,7 @@ var MiddlewareGenerator = class {
|
|
|
7204
7364
|
}
|
|
7205
7365
|
return `@/${importBasePath}/${cleanPath}`;
|
|
7206
7366
|
}
|
|
7207
|
-
|
|
7367
|
+
generate(_context) {
|
|
7208
7368
|
const files = [];
|
|
7209
7369
|
files.push(this.generateMainMiddleware());
|
|
7210
7370
|
files.push(this.generateRateLimitMiddleware());
|
|
@@ -7212,7 +7372,7 @@ var MiddlewareGenerator = class {
|
|
|
7212
7372
|
files.push(this.generateSecurityMiddleware());
|
|
7213
7373
|
files.push(this.generateLoggingMiddleware());
|
|
7214
7374
|
files.push(this.generateApiMiddleware());
|
|
7215
|
-
return files;
|
|
7375
|
+
return Promise.resolve(files);
|
|
7216
7376
|
}
|
|
7217
7377
|
generateMainMiddleware() {
|
|
7218
7378
|
const authImport = this.buildImportPath("auth/middleware");
|
|
@@ -7619,7 +7779,7 @@ var UploadGenerator = class {
|
|
|
7619
7779
|
}
|
|
7620
7780
|
analyzer;
|
|
7621
7781
|
buildImportPath(relativePath) {
|
|
7622
|
-
const outputDirectory = this.configuration.outputDir
|
|
7782
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
7623
7783
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
7624
7784
|
let importBasePath = outputDirectory;
|
|
7625
7785
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -7627,19 +7787,19 @@ var UploadGenerator = class {
|
|
|
7627
7787
|
}
|
|
7628
7788
|
return `@/${importBasePath}/${cleanPath}`;
|
|
7629
7789
|
}
|
|
7630
|
-
|
|
7790
|
+
generate(context) {
|
|
7631
7791
|
const { schema } = context;
|
|
7632
7792
|
const generatedFiles = [];
|
|
7633
7793
|
this.analyzer = new SchemaAnalyzer(schema);
|
|
7634
7794
|
const uploadEndpoints = schema.endpoints.filter(
|
|
7635
|
-
(endpoint) => endpoint.requestBody?.content
|
|
7795
|
+
(endpoint) => endpoint.requestBody?.content.some(
|
|
7636
7796
|
(content) => content.type === "multipart/form-data" || content.type === "application/octet-stream"
|
|
7637
7797
|
)
|
|
7638
7798
|
);
|
|
7639
7799
|
if (uploadEndpoints.length === 0 || !this.configuration.uploads?.enabled) {
|
|
7640
|
-
return generatedFiles;
|
|
7800
|
+
return Promise.resolve(generatedFiles);
|
|
7641
7801
|
}
|
|
7642
|
-
const presignedConfig = this.configuration.uploads
|
|
7802
|
+
const presignedConfig = this.configuration.uploads.presignedUploads;
|
|
7643
7803
|
if (presignedConfig?.enabled) {
|
|
7644
7804
|
const isPresignedSupported = this.analyzer.isPresignedUploadsSupported();
|
|
7645
7805
|
if (!isPresignedSupported) {
|
|
@@ -7650,14 +7810,14 @@ var UploadGenerator = class {
|
|
|
7650
7810
|
}
|
|
7651
7811
|
const extractedUploadConfig = this.analyzer.extractUploadConfig();
|
|
7652
7812
|
const presignedEnabled = presignedConfig?.enabled && this.analyzer.isPresignedUploadsSupported();
|
|
7653
|
-
const uploadProvider = this.configuration.uploads
|
|
7654
|
-
const uploadStrategy = presignedEnabled ? "presigned" : this.configuration.uploads
|
|
7813
|
+
const uploadProvider = this.configuration.uploads.provider || (extractedUploadConfig.presignedEndpoint ? "minio" : "standard");
|
|
7814
|
+
const uploadStrategy = presignedEnabled ? "presigned" : this.configuration.uploads.strategy || "standard";
|
|
7655
7815
|
presignedEnabled ? {
|
|
7656
|
-
presignEndpoint: extractedUploadConfig.presignedEndpoint || presignedConfig
|
|
7657
|
-
fallbackToBackend: presignedConfig
|
|
7816
|
+
presignEndpoint: extractedUploadConfig.presignedEndpoint || presignedConfig.presignEndpoint || "/api/v1/files/presign-upload",
|
|
7817
|
+
fallbackToBackend: presignedConfig.fallbackToBackend !== false
|
|
7658
7818
|
} : {
|
|
7659
7819
|
};
|
|
7660
|
-
const progressConfig = this.configuration.uploads
|
|
7820
|
+
const progressConfig = this.configuration.uploads.progressTracking || {
|
|
7661
7821
|
enabled: true,
|
|
7662
7822
|
useXHR: true
|
|
7663
7823
|
};
|
|
@@ -7674,7 +7834,7 @@ var UploadGenerator = class {
|
|
|
7674
7834
|
progressConfig
|
|
7675
7835
|
));
|
|
7676
7836
|
}
|
|
7677
|
-
return generatedFiles;
|
|
7837
|
+
return Promise.resolve(generatedFiles);
|
|
7678
7838
|
}
|
|
7679
7839
|
/**
|
|
7680
7840
|
* Find presigned upload endpoint in schema
|
|
@@ -7687,7 +7847,7 @@ var UploadGenerator = class {
|
|
|
7687
7847
|
return pathLower.includes("presign") || pathLower.includes("presigned") || operationIdLower.includes("presign") || operationIdLower.includes("presigned");
|
|
7688
7848
|
}) || null;
|
|
7689
7849
|
}
|
|
7690
|
-
generateUploadUtilities(
|
|
7850
|
+
generateUploadUtilities(_uploadProvider, _uploadStrategy, _presignedEndpoint) {
|
|
7691
7851
|
const { uploads } = this.configuration;
|
|
7692
7852
|
const extractedConfig = this.analyzer.extractUploadConfig();
|
|
7693
7853
|
const maxSize = uploads?.security?.maxSize || (extractedConfig.maxSize ? `${extractedConfig.maxSize}MB` : "10MB");
|
|
@@ -8038,8 +8198,8 @@ async function uploadViaBackendApi(
|
|
|
8038
8198
|
xhr.responseType = 'json'
|
|
8039
8199
|
// Use base URL from environment or configuration
|
|
8040
8200
|
const baseUrl = typeof window !== 'undefined'
|
|
8041
|
-
? (process.env.NEXT_PUBLIC_API_URL || '${this.configuration.api
|
|
8042
|
-
: '${this.configuration.api
|
|
8201
|
+
? (process.env.NEXT_PUBLIC_API_URL || '${this.configuration.api.baseUrl || "http://localhost:8000"}')
|
|
8202
|
+
: '${this.configuration.api.baseUrl || "http://localhost:8000"}'
|
|
8043
8203
|
xhr.open('POST', \`\${baseUrl}${endpoint.path}\`)
|
|
8044
8204
|
xhr.send(formData)
|
|
8045
8205
|
})
|
|
@@ -8314,8 +8474,8 @@ export function ${hookName}Upload(options?: {
|
|
|
8314
8474
|
}
|
|
8315
8475
|
generateUseUploadFileHook(uploadProvider, uploadStrategy, context) {
|
|
8316
8476
|
const uploadUtilsImport = this.buildImportPath("services/uploadUtils");
|
|
8317
|
-
const uploadEndpoints = context?.schema
|
|
8318
|
-
(e) => e.metadata
|
|
8477
|
+
const uploadEndpoints = context?.schema.endpoints.filter(
|
|
8478
|
+
(e) => e.metadata.fileUpload || e.path.toLowerCase().includes("upload") || e.operationId && e.operationId.toLowerCase().includes("upload")
|
|
8319
8479
|
) || [];
|
|
8320
8480
|
const firstUploadEndpoint = uploadEndpoints[0];
|
|
8321
8481
|
let uploadMethodName = "uploadFile";
|
|
@@ -8455,7 +8615,7 @@ var ErrorHandlerGenerator = class {
|
|
|
8455
8615
|
}
|
|
8456
8616
|
analyzer;
|
|
8457
8617
|
buildImportPath(relativePath) {
|
|
8458
|
-
const outputDirectory = this.configuration.outputDir
|
|
8618
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
8459
8619
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
8460
8620
|
let importBasePath = outputDirectory;
|
|
8461
8621
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -8463,18 +8623,18 @@ var ErrorHandlerGenerator = class {
|
|
|
8463
8623
|
}
|
|
8464
8624
|
return `@/${importBasePath}/${cleanPath}`;
|
|
8465
8625
|
}
|
|
8466
|
-
|
|
8626
|
+
generate(context) {
|
|
8467
8627
|
const files = [];
|
|
8468
|
-
const { schema
|
|
8628
|
+
const { schema } = context;
|
|
8469
8629
|
const { api } = this.configuration;
|
|
8470
|
-
const errorHandling = api
|
|
8630
|
+
const errorHandling = api.errorHandling;
|
|
8471
8631
|
this.analyzer = new SchemaAnalyzer(schema);
|
|
8472
8632
|
const errorCodes = this.analyzer.extractErrorCodes();
|
|
8473
8633
|
const accountStatusPatterns = this.analyzer.extractAccountStatusPatterns();
|
|
8474
8634
|
const extractedAuthEndpoints = this.analyzer.extractAuthEndpoints();
|
|
8475
8635
|
const hasAuthEndpoints = !!(extractedAuthEndpoints.login || extractedAuthEndpoints.loginCredentials);
|
|
8476
8636
|
const hasAuthErrors = errorCodes.size > 0 || (accountStatusPatterns.inactiveStatuses.length > 0 || accountStatusPatterns.suspendedStatuses.length > 0);
|
|
8477
|
-
const shouldGenerate = hasAuthEndpoints && (errorHandling?.generateAuthErrorHandler !== false && errorHandling?.enableAuthErrorHandling !== false || hasAuthErrors && errorHandling
|
|
8637
|
+
const shouldGenerate = hasAuthEndpoints && (errorHandling?.generateAuthErrorHandler !== false && errorHandling?.enableAuthErrorHandling !== false || hasAuthErrors && errorHandling.generateAuthErrorHandler !== false);
|
|
8478
8638
|
if (shouldGenerate) {
|
|
8479
8639
|
files.push(this.generateAuthErrorHandler(errorCodes, accountStatusPatterns));
|
|
8480
8640
|
} else if (errorHandling?.enableAuthErrorHandling === true && !hasAuthEndpoints) {
|
|
@@ -8482,11 +8642,11 @@ var ErrorHandlerGenerator = class {
|
|
|
8482
8642
|
`\u26A0\uFE0F Auth error handling is enabled but auth endpoints are not found in OpenAPI schema. Auth error handler will not be generated.`
|
|
8483
8643
|
);
|
|
8484
8644
|
}
|
|
8485
|
-
return files;
|
|
8645
|
+
return Promise.resolve(files);
|
|
8486
8646
|
}
|
|
8487
8647
|
generateAuthErrorHandler(errorCodes, accountStatusPatterns) {
|
|
8488
8648
|
const authPath = this.configuration.auth?.authPath || "@/lib/auth";
|
|
8489
|
-
const errorHandling = this.configuration.api
|
|
8649
|
+
const errorHandling = this.configuration.api.errorHandling;
|
|
8490
8650
|
const authErrorHandlerPath = errorHandling?.authErrorHandlerPath || "@/lib/auth-error-handler";
|
|
8491
8651
|
let handlerOutputPath = authErrorHandlerPath;
|
|
8492
8652
|
if (handlerOutputPath.startsWith("@/")) {
|
|
@@ -8699,7 +8859,7 @@ var SSEGenerator = class {
|
|
|
8699
8859
|
}
|
|
8700
8860
|
analyzer;
|
|
8701
8861
|
buildImportPath(relativePath) {
|
|
8702
|
-
const outputDirectory = this.configuration.outputDir
|
|
8862
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
8703
8863
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
8704
8864
|
let importBasePath = outputDirectory;
|
|
8705
8865
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -8731,11 +8891,11 @@ var SSEGenerator = class {
|
|
|
8731
8891
|
);
|
|
8732
8892
|
return hasEventStream;
|
|
8733
8893
|
}
|
|
8734
|
-
|
|
8894
|
+
generate(context) {
|
|
8735
8895
|
const { schema } = context;
|
|
8736
8896
|
const generatedFiles = [];
|
|
8737
8897
|
this.analyzer = new SchemaAnalyzer(schema);
|
|
8738
|
-
const streamingConfig = this.configuration.framework
|
|
8898
|
+
const streamingConfig = this.configuration.framework.streaming;
|
|
8739
8899
|
const hasStreamingEndpoints = schema.endpoints.some((endpoint) => this.isSSEEndpoint(endpoint));
|
|
8740
8900
|
if (streamingConfig?.enabled === true && !hasStreamingEndpoints) {
|
|
8741
8901
|
console.warn(
|
|
@@ -8744,11 +8904,11 @@ var SSEGenerator = class {
|
|
|
8744
8904
|
}
|
|
8745
8905
|
const shouldEnableStreaming = streamingConfig?.enabled === true ? hasStreamingEndpoints : streamingConfig?.enabled !== false && hasStreamingEndpoints;
|
|
8746
8906
|
if (!shouldEnableStreaming || streamingConfig?.sse?.enabled === false || !hasStreamingEndpoints) {
|
|
8747
|
-
return generatedFiles;
|
|
8907
|
+
return Promise.resolve(generatedFiles);
|
|
8748
8908
|
}
|
|
8749
8909
|
const sseEndpoints = schema.endpoints.filter((endpoint) => this.isSSEEndpoint(endpoint));
|
|
8750
8910
|
if (sseEndpoints.length === 0) {
|
|
8751
|
-
return generatedFiles;
|
|
8911
|
+
return Promise.resolve(generatedFiles);
|
|
8752
8912
|
}
|
|
8753
8913
|
for (const endpoint of sseEndpoints) {
|
|
8754
8914
|
generatedFiles.push(this.generateSSEClientMethod(endpoint));
|
|
@@ -8757,7 +8917,7 @@ var SSEGenerator = class {
|
|
|
8757
8917
|
for (const [tag, tagEndpoints] of Object.entries(endpointsByTag)) {
|
|
8758
8918
|
generatedFiles.push(this.generateSSEHooks(tag, tagEndpoints));
|
|
8759
8919
|
}
|
|
8760
|
-
return generatedFiles;
|
|
8920
|
+
return Promise.resolve(generatedFiles);
|
|
8761
8921
|
}
|
|
8762
8922
|
generateSSEClientMethod(endpoint) {
|
|
8763
8923
|
const operationId = endpoint.operationId || endpoint.id;
|
|
@@ -8792,8 +8952,8 @@ var SSEGenerator = class {
|
|
|
8792
8952
|
}): EventSource => {
|
|
8793
8953
|
${pathParamNames.length > 0 ? `const { ${pathParamNames.join(", ")}, ...restOptions } = options.params || {}
|
|
8794
8954
|
` : ""}const baseUrl = typeof window !== 'undefined'
|
|
8795
|
-
? (process.env.NEXT_PUBLIC_API_URL || '${this.configuration.api
|
|
8796
|
-
: '${this.configuration.api
|
|
8955
|
+
? (process.env.NEXT_PUBLIC_API_URL || '${this.configuration.api.baseUrl || "http://localhost:8000"}')
|
|
8956
|
+
: '${this.configuration.api.baseUrl || "http://localhost:8000"}'
|
|
8797
8957
|
const sseUrl = \`\${baseUrl}${urlConstruction}\`
|
|
8798
8958
|
|
|
8799
8959
|
// Create EventSource connection
|
|
@@ -8839,7 +8999,7 @@ var SSEGenerator = class {
|
|
|
8839
8999
|
generateSSEHooks(tag, endpoints) {
|
|
8840
9000
|
const tagName = toValidIdentifier(tag);
|
|
8841
9001
|
const clientImport = this.buildImportPath("client");
|
|
8842
|
-
const streamingConfig = this.configuration.framework
|
|
9002
|
+
const streamingConfig = this.configuration.framework.streaming?.sse;
|
|
8843
9003
|
const autoReconnect = streamingConfig?.autoReconnect !== false;
|
|
8844
9004
|
const reconnectDelay = streamingConfig?.reconnectDelay || 3e3;
|
|
8845
9005
|
const maxReconnectAttempts = streamingConfig?.maxReconnectAttempts || 5;
|
|
@@ -9032,7 +9192,7 @@ var NextJsCodeGenerator = class {
|
|
|
9032
9192
|
__name(this, "NextJsCodeGenerator");
|
|
9033
9193
|
}
|
|
9034
9194
|
buildImportPath(relativePath) {
|
|
9035
|
-
const outputDirectory = this.configuration.outputDir
|
|
9195
|
+
const outputDirectory = this.configuration.outputDir ?? "generated";
|
|
9036
9196
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
9037
9197
|
let importBasePath = outputDirectory;
|
|
9038
9198
|
if (importBasePath.startsWith("src/")) {
|
|
@@ -9046,9 +9206,9 @@ var NextJsCodeGenerator = class {
|
|
|
9046
9206
|
path: file.path,
|
|
9047
9207
|
metadata: {
|
|
9048
9208
|
...file.metadata,
|
|
9049
|
-
exports: file.metadata?.exports
|
|
9050
|
-
imports: file.metadata?.imports
|
|
9051
|
-
dependencies: file.metadata?.dependencies
|
|
9209
|
+
exports: file.metadata?.exports ?? [],
|
|
9210
|
+
imports: file.metadata?.imports ?? [],
|
|
9211
|
+
dependencies: file.metadata?.dependencies.map((dependency) => {
|
|
9052
9212
|
if (dependency.startsWith("@/generated/")) {
|
|
9053
9213
|
return dependency;
|
|
9054
9214
|
}
|
|
@@ -9057,7 +9217,7 @@ var NextJsCodeGenerator = class {
|
|
|
9057
9217
|
return `@/generated/${relativePart}`;
|
|
9058
9218
|
}
|
|
9059
9219
|
return dependency;
|
|
9060
|
-
})
|
|
9220
|
+
}) ?? []
|
|
9061
9221
|
}
|
|
9062
9222
|
}));
|
|
9063
9223
|
}
|
|
@@ -9090,11 +9250,11 @@ var NextJsCodeGenerator = class {
|
|
|
9090
9250
|
const uploadGenerator = new UploadGenerator(this.configuration);
|
|
9091
9251
|
generatedFiles.push(...await uploadGenerator.generate(context));
|
|
9092
9252
|
}
|
|
9093
|
-
if (this.configuration.api
|
|
9253
|
+
if (this.configuration.api.errorHandling?.generateAuthErrorHandler !== false) {
|
|
9094
9254
|
const errorHandlerGenerator = new ErrorHandlerGenerator(this.configuration);
|
|
9095
9255
|
generatedFiles.push(...await errorHandlerGenerator.generate(context));
|
|
9096
9256
|
}
|
|
9097
|
-
if (this.configuration.framework
|
|
9257
|
+
if (this.configuration.framework.streaming?.enabled) {
|
|
9098
9258
|
const sseGenerator = new SSEGenerator(this.configuration);
|
|
9099
9259
|
generatedFiles.push(...await sseGenerator.generate(context));
|
|
9100
9260
|
}
|
|
@@ -9104,14 +9264,14 @@ var NextJsCodeGenerator = class {
|
|
|
9104
9264
|
throw new GenerationError(`Failed to generate Next.js files: ${errorMessage}`);
|
|
9105
9265
|
}
|
|
9106
9266
|
}
|
|
9107
|
-
|
|
9267
|
+
generateSafeActionClient() {
|
|
9108
9268
|
const safeActionContent = `import { DEFAULT_SERVER_ERROR_MESSAGE, createSafeActionClient } from "next-safe-action";
|
|
9109
9269
|
import { headers } from "next/headers";
|
|
9110
9270
|
import { z } from "zod";
|
|
9111
9271
|
|
|
9112
9272
|
/**
|
|
9113
9273
|
* Enhanced Action Error class for better error handling
|
|
9114
|
-
* Follows Next.js 16.0.
|
|
9274
|
+
* Follows Next.js 16.0.7 best practices
|
|
9115
9275
|
*/
|
|
9116
9276
|
export class ActionError extends Error {
|
|
9117
9277
|
constructor(
|
|
@@ -9148,7 +9308,7 @@ export const actionClient = createSafeActionClient({
|
|
|
9148
9308
|
|
|
9149
9309
|
/**
|
|
9150
9310
|
* Enhanced action client with metadata support
|
|
9151
|
-
* Next.js 16.0.
|
|
9311
|
+
* Next.js 16.0.7: Supports metadata for better action tracking and rate limiting
|
|
9152
9312
|
*/
|
|
9153
9313
|
export const actionClientWithMeta = createSafeActionClient({
|
|
9154
9314
|
handleServerError(e) {
|
|
@@ -9169,7 +9329,7 @@ export const actionClientWithMeta = createSafeActionClient({
|
|
|
9169
9329
|
requests: z.number().int().positive().describe('Number of requests allowed'),
|
|
9170
9330
|
window: z.string().describe('Time window (e.g., "10s", "1m", "1h")'),
|
|
9171
9331
|
}).optional().describe('Rate limiting configuration'),
|
|
9172
|
-
cacheTags: z.array(z.string()).optional().describe('Cache tags for invalidation (Next.js 16.0.
|
|
9332
|
+
cacheTags: z.array(z.string()).optional().describe('Cache tags for invalidation (Next.js 16.0.7)'),
|
|
9173
9333
|
});
|
|
9174
9334
|
},
|
|
9175
9335
|
});
|
|
@@ -9260,7 +9420,7 @@ async function getCurrentUser() {
|
|
|
9260
9420
|
// Implement your authentication logic here
|
|
9261
9421
|
return null;
|
|
9262
9422
|
}`;
|
|
9263
|
-
return [
|
|
9423
|
+
return Promise.resolve([
|
|
9264
9424
|
{
|
|
9265
9425
|
path: "lib/safe-action.ts",
|
|
9266
9426
|
content: safeActionContent,
|
|
@@ -9271,7 +9431,7 @@ async function getCurrentUser() {
|
|
|
9271
9431
|
dependencies: []
|
|
9272
9432
|
}
|
|
9273
9433
|
}
|
|
9274
|
-
];
|
|
9434
|
+
]);
|
|
9275
9435
|
}
|
|
9276
9436
|
};
|
|
9277
9437
|
var FileSystemManager = class {
|
|
@@ -9279,7 +9439,7 @@ var FileSystemManager = class {
|
|
|
9279
9439
|
__name(this, "FileSystemManager");
|
|
9280
9440
|
}
|
|
9281
9441
|
async writeFile(filePath, content, options = {}) {
|
|
9282
|
-
if (!filePath
|
|
9442
|
+
if (!filePath.trim()) {
|
|
9283
9443
|
throw new Error("File path is required and cannot be empty");
|
|
9284
9444
|
}
|
|
9285
9445
|
if (typeof content !== "string") {
|
|
@@ -9316,7 +9476,7 @@ var FileSystemManager = class {
|
|
|
9316
9476
|
}
|
|
9317
9477
|
}
|
|
9318
9478
|
async readFile(filePath, encoding = "utf8") {
|
|
9319
|
-
if (!filePath
|
|
9479
|
+
if (!filePath.trim()) {
|
|
9320
9480
|
throw new Error("File path is required and cannot be empty");
|
|
9321
9481
|
}
|
|
9322
9482
|
try {
|
|
@@ -9343,7 +9503,7 @@ var FileSystemManager = class {
|
|
|
9343
9503
|
}
|
|
9344
9504
|
}
|
|
9345
9505
|
async getFileHash(filePath) {
|
|
9346
|
-
if (!filePath
|
|
9506
|
+
if (!filePath.trim()) {
|
|
9347
9507
|
throw new Error("File path is required and cannot be empty");
|
|
9348
9508
|
}
|
|
9349
9509
|
try {
|
|
@@ -9369,7 +9529,7 @@ var FileSystemManager = class {
|
|
|
9369
9529
|
}
|
|
9370
9530
|
}
|
|
9371
9531
|
async findFiles(dir, pattern, recursive = true) {
|
|
9372
|
-
if (!dir
|
|
9532
|
+
if (!dir.trim()) {
|
|
9373
9533
|
throw new Error("Directory path is required and cannot be empty");
|
|
9374
9534
|
}
|
|
9375
9535
|
if (!(pattern instanceof RegExp)) {
|
|
@@ -9412,16 +9572,52 @@ var BridgeCore = class {
|
|
|
9412
9572
|
logger;
|
|
9413
9573
|
schemaParser;
|
|
9414
9574
|
fileManager;
|
|
9575
|
+
/**
|
|
9576
|
+
* Creates a new instance of BridgeCore
|
|
9577
|
+
*
|
|
9578
|
+
* Initializes all required dependencies including logger, schema parser, and file manager.
|
|
9579
|
+
* All dependencies are readonly to ensure immutability and thread safety.
|
|
9580
|
+
*/
|
|
9415
9581
|
constructor() {
|
|
9416
9582
|
this.logger = new BridgeLogger({ prefix: "\u{1F517} Mulink" });
|
|
9417
9583
|
this.schemaParser = new OpenApiSchemaParser();
|
|
9418
9584
|
this.fileManager = new FileSystemManager();
|
|
9419
9585
|
}
|
|
9586
|
+
/**
|
|
9587
|
+
* Generates type-safe API client code from OpenAPI schema
|
|
9588
|
+
*
|
|
9589
|
+
* This is the main entry point for code generation. It validates the configuration,
|
|
9590
|
+
* parses the OpenAPI schema, generates all necessary files, and writes them to disk.
|
|
9591
|
+
*
|
|
9592
|
+
* The generated code follows Next.js 16.0.7 best practices including:
|
|
9593
|
+
* - Server Actions with type safety
|
|
9594
|
+
* - React Query hooks with proper caching
|
|
9595
|
+
* - Middleware support
|
|
9596
|
+
* - Error handling
|
|
9597
|
+
* - Cache tag management
|
|
9598
|
+
*
|
|
9599
|
+
* @param configuration - The bridge configuration containing schema URL, output directory, and framework settings
|
|
9600
|
+
* @returns Promise that resolves when generation is complete
|
|
9601
|
+
* @throws {ValidationError} When configuration is invalid
|
|
9602
|
+
* @throws {SchemaParseError} When OpenAPI schema cannot be parsed
|
|
9603
|
+
* @throws {GenerationError} When code generation fails
|
|
9604
|
+
*
|
|
9605
|
+
* @example
|
|
9606
|
+
* ```typescript
|
|
9607
|
+
* const config: BridgeConfiguration = {
|
|
9608
|
+
* schema: 'https://api.example.com/openapi.json',
|
|
9609
|
+
* outputDir: 'src/generated',
|
|
9610
|
+
* framework: { type: 'nextjs', router: 'app', features: {...} },
|
|
9611
|
+
* api: { baseUrl: 'https://api.example.com', timeout: 30000, retries: 3 }
|
|
9612
|
+
* };
|
|
9613
|
+
* await bridge.generate(config);
|
|
9614
|
+
* ```
|
|
9615
|
+
*/
|
|
9420
9616
|
async generate(configuration) {
|
|
9421
9617
|
const startTime = Date.now();
|
|
9422
9618
|
try {
|
|
9423
9619
|
this.logger.info("Starting code generation...");
|
|
9424
|
-
|
|
9620
|
+
this.validateConfiguration(configuration);
|
|
9425
9621
|
this.logger.info(`Parsing schema: ${configuration.schema}`);
|
|
9426
9622
|
const parsedSchema = await this.schemaParser.parse(configuration.schema);
|
|
9427
9623
|
this.logger.debug(
|
|
@@ -9450,16 +9646,17 @@ var BridgeCore = class {
|
|
|
9450
9646
|
throw error;
|
|
9451
9647
|
}
|
|
9452
9648
|
}
|
|
9453
|
-
|
|
9649
|
+
validateConfiguration(configuration) {
|
|
9454
9650
|
const errors = [];
|
|
9455
|
-
if (!configuration.schema
|
|
9651
|
+
if (!configuration.schema.trim()) {
|
|
9456
9652
|
errors.push("Schema URL is required and cannot be empty");
|
|
9457
9653
|
}
|
|
9458
|
-
if (!configuration.outputDir
|
|
9654
|
+
if (!configuration.outputDir.trim()) {
|
|
9459
9655
|
errors.push("Output directory is required and cannot be empty");
|
|
9460
9656
|
}
|
|
9461
9657
|
if (configuration.framework.type !== "nextjs") {
|
|
9462
|
-
|
|
9658
|
+
const frameworkType = configuration.framework.type;
|
|
9659
|
+
errors.push(`Only Next.js framework is currently supported, got: ${frameworkType}`);
|
|
9463
9660
|
}
|
|
9464
9661
|
if (errors.length > 0) {
|
|
9465
9662
|
throw new ValidationError(
|
|
@@ -9476,8 +9673,10 @@ var BridgeCore = class {
|
|
|
9476
9673
|
case "nextjs":
|
|
9477
9674
|
const nextJsGenerator = new NextJsCodeGenerator(config);
|
|
9478
9675
|
return await nextJsGenerator.generate(context);
|
|
9479
|
-
default:
|
|
9480
|
-
|
|
9676
|
+
default: {
|
|
9677
|
+
const frameworkType = config.framework.type;
|
|
9678
|
+
throw new GenerationError(`Unsupported framework: ${frameworkType}`);
|
|
9679
|
+
}
|
|
9481
9680
|
}
|
|
9482
9681
|
} catch (error) {
|
|
9483
9682
|
if (error instanceof GenerationError) {
|
|
@@ -9511,7 +9710,7 @@ var BridgeCore = class {
|
|
|
9511
9710
|
logGenerationSummary(files) {
|
|
9512
9711
|
const fileTypes = files.reduce(
|
|
9513
9712
|
(acc, file) => {
|
|
9514
|
-
acc[file.type] = (acc[file.type]
|
|
9713
|
+
acc[file.type] = (acc[file.type] ?? 0) + 1;
|
|
9515
9714
|
return acc;
|
|
9516
9715
|
},
|
|
9517
9716
|
{}
|
|
@@ -9530,9 +9729,24 @@ var BridgeCore = class {
|
|
|
9530
9729
|
});
|
|
9531
9730
|
}
|
|
9532
9731
|
}
|
|
9533
|
-
|
|
9732
|
+
/**
|
|
9733
|
+
* Validates an OpenAPI schema without generating code
|
|
9734
|
+
*
|
|
9735
|
+
* Useful for checking schema validity before running full generation.
|
|
9736
|
+
*
|
|
9737
|
+
* @param schemaUrl - URL or file path to the OpenAPI schema
|
|
9738
|
+
* @returns Promise resolving to true if schema is valid, false otherwise
|
|
9739
|
+
*
|
|
9740
|
+
* @example
|
|
9741
|
+
* ```typescript
|
|
9742
|
+
* const isValid = await bridge.validateSchema('https://api.example.com/openapi.json');
|
|
9743
|
+
* if (isValid) {
|
|
9744
|
+
* await bridge.generate(config);
|
|
9745
|
+
* }
|
|
9746
|
+
* ```
|
|
9747
|
+
*/
|
|
9534
9748
|
async validateSchema(schemaUrl) {
|
|
9535
|
-
if (!schemaUrl
|
|
9749
|
+
if (!schemaUrl.trim()) {
|
|
9536
9750
|
this.logger.warn("Schema URL is empty or invalid");
|
|
9537
9751
|
return false;
|
|
9538
9752
|
}
|
|
@@ -9546,8 +9760,25 @@ var BridgeCore = class {
|
|
|
9546
9760
|
return false;
|
|
9547
9761
|
}
|
|
9548
9762
|
}
|
|
9763
|
+
/**
|
|
9764
|
+
* Retrieves metadata from an OpenAPI schema
|
|
9765
|
+
*
|
|
9766
|
+
* Extracts schema metadata including title, version, description, and other
|
|
9767
|
+
* OpenAPI document information without parsing the entire schema.
|
|
9768
|
+
*
|
|
9769
|
+
* @param schemaUrl - URL or file path to the OpenAPI schema
|
|
9770
|
+
* @returns Promise resolving to schema metadata
|
|
9771
|
+
* @throws {BridgeError} When schema URL is invalid
|
|
9772
|
+
* @throws {SchemaParseError} When schema cannot be parsed
|
|
9773
|
+
*
|
|
9774
|
+
* @example
|
|
9775
|
+
* ```typescript
|
|
9776
|
+
* const metadata = await bridge.getSchemaInfo('https://api.example.com/openapi.json');
|
|
9777
|
+
* console.log(`Schema: ${metadata.title} v${metadata.version}`);
|
|
9778
|
+
* ```
|
|
9779
|
+
*/
|
|
9549
9780
|
async getSchemaInfo(schemaUrl) {
|
|
9550
|
-
if (!schemaUrl
|
|
9781
|
+
if (!schemaUrl.trim()) {
|
|
9551
9782
|
throw new BridgeError("Schema URL is required and cannot be empty", "INVALID_SCHEMA_URL");
|
|
9552
9783
|
}
|
|
9553
9784
|
try {
|
|
@@ -9559,6 +9790,18 @@ var BridgeCore = class {
|
|
|
9559
9790
|
throw new SchemaParseError(`Failed to parse schema: ${errorMessage}`, schemaUrl);
|
|
9560
9791
|
}
|
|
9561
9792
|
}
|
|
9793
|
+
/**
|
|
9794
|
+
* Clears the internal schema cache
|
|
9795
|
+
*
|
|
9796
|
+
* Useful when you need to force re-fetching of schemas or during development.
|
|
9797
|
+
* The cache is automatically managed, but this method allows manual invalidation.
|
|
9798
|
+
*
|
|
9799
|
+
* @example
|
|
9800
|
+
* ```typescript
|
|
9801
|
+
* bridge.clearCache();
|
|
9802
|
+
* await bridge.generate(config); // Will fetch fresh schema
|
|
9803
|
+
* ```
|
|
9804
|
+
*/
|
|
9562
9805
|
clearCache() {
|
|
9563
9806
|
try {
|
|
9564
9807
|
this.schemaParser.clearCache();
|
|
@@ -9657,7 +9900,7 @@ var ConfigurationLoader = class {
|
|
|
9657
9900
|
}
|
|
9658
9901
|
async load(configPath) {
|
|
9659
9902
|
if (!configPath?.trim()) {
|
|
9660
|
-
configPath = "
|
|
9903
|
+
configPath = "link.config.json";
|
|
9661
9904
|
}
|
|
9662
9905
|
const resolvedPath = path2__default.default.resolve(process.cwd(), configPath);
|
|
9663
9906
|
try {
|
|
@@ -9723,7 +9966,7 @@ ${errorMessages}`,
|
|
|
9723
9966
|
);
|
|
9724
9967
|
}
|
|
9725
9968
|
}
|
|
9726
|
-
|
|
9969
|
+
createDefault(framework = "nextjs") {
|
|
9727
9970
|
const defaultConfig = {
|
|
9728
9971
|
schema: "https://petstore3.swagger.io/api/v3/openapi.json",
|
|
9729
9972
|
outputDir: "src/generated",
|
|
@@ -9768,7 +10011,7 @@ ${errorMessages}`,
|
|
|
9768
10011
|
}
|
|
9769
10012
|
async save(config, configPath) {
|
|
9770
10013
|
if (!configPath?.trim()) {
|
|
9771
|
-
configPath = "
|
|
10014
|
+
configPath = "link.config.json";
|
|
9772
10015
|
}
|
|
9773
10016
|
const resolvedPath = path2__default.default.resolve(process.cwd(), configPath);
|
|
9774
10017
|
try {
|
|
@@ -9826,5 +10069,5 @@ exports.VersionChecker = VersionChecker;
|
|
|
9826
10069
|
exports.__name = __name;
|
|
9827
10070
|
exports.checkAndNotifyUpdates = checkAndNotifyUpdates;
|
|
9828
10071
|
exports.createBridgeVersionChecker = createBridgeVersionChecker;
|
|
9829
|
-
//# sourceMappingURL=chunk-
|
|
9830
|
-
//# sourceMappingURL=chunk-
|
|
10072
|
+
//# sourceMappingURL=chunk-IAS3P4RF.cjs.map
|
|
10073
|
+
//# sourceMappingURL=chunk-IAS3P4RF.cjs.map
|