mulink 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/lib/{chunk-IVMVPQUK.js → chunk-7Y66DW7M.js} +394 -321
- package/dist/lib/chunk-7Y66DW7M.js.map +1 -0
- package/dist/lib/{chunk-RGLCJDOY.cjs → chunk-OOY4PCDK.cjs} +394 -321
- package/dist/lib/chunk-OOY4PCDK.cjs.map +1 -0
- package/dist/lib/cli.cjs +16 -16
- package/dist/lib/cli.js +1 -1
- package/dist/lib/client.cjs +18 -18
- package/dist/lib/client.d.cts +2 -2
- package/dist/lib/client.d.ts +2 -2
- package/dist/lib/client.js +2 -2
- package/dist/lib/index.cjs +15 -15
- package/dist/lib/index.d.cts +2 -2
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/index.js +1 -1
- package/dist/lib/{version-checker-BWdifiXN.d.cts → version-checker-uF6o5ziX.d.cts} +2 -0
- package/dist/lib/{version-checker-BWdifiXN.d.ts → version-checker-uF6o5ziX.d.ts} +2 -0
- package/package.json +1 -1
- package/dist/lib/chunk-IVMVPQUK.js.map +0 -1
- package/dist/lib/chunk-RGLCJDOY.cjs.map +0 -1
|
@@ -1032,8 +1032,8 @@ import { cache } from 'react'
|
|
|
1032
1032
|
* We use dynamic imports to avoid bundling them in the client
|
|
1033
1033
|
*/
|
|
1034
1034
|
let serverOnlyModules: {
|
|
1035
|
-
cookies?: () => import('next/headers').
|
|
1036
|
-
headers?: () => import('next/headers').
|
|
1035
|
+
cookies?: () => Awaited<ReturnType<typeof import('next/headers').cookies>>
|
|
1036
|
+
headers?: () => Awaited<ReturnType<typeof import('next/headers').headers>>
|
|
1037
1037
|
after?: (fn: () => void | Promise<void>) => void
|
|
1038
1038
|
updateTag?: (tag: string) => void
|
|
1039
1039
|
} | null = null
|
|
@@ -1336,12 +1336,14 @@ export class BaseApiClient {
|
|
|
1336
1336
|
|
|
1337
1337
|
// Try external auth service
|
|
1338
1338
|
${this.configuration.auth?.enabled ? `try {
|
|
1339
|
-
const
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1339
|
+
const authModule = await import('${authPath}').catch(() => null)
|
|
1340
|
+
if (authModule && authModule.${tokenGetter}) {
|
|
1341
|
+
const session = await authModule.${tokenGetter}()
|
|
1342
|
+
|
|
1343
|
+
if (session?.accessToken) {
|
|
1344
|
+
getAuthHeaders.Authorization = \`Bearer \${session.accessToken}\`
|
|
1345
|
+
return getAuthHeaders
|
|
1346
|
+
}
|
|
1345
1347
|
}
|
|
1346
1348
|
} catch (error) {
|
|
1347
1349
|
// Auth not available or error accessing
|
|
@@ -1540,7 +1542,8 @@ export class BaseApiClient {
|
|
|
1540
1542
|
const requestPromise = this.executeRequestInternal<TData>(
|
|
1541
1543
|
method, url, body, headers, fetchOptions, timeout, retries,
|
|
1542
1544
|
retryDelay, retryCondition, validateResponse, skipAuth,
|
|
1543
|
-
responseSchema, requestId, [...this.middleware, ...middleware]
|
|
1545
|
+
responseSchema, requestId, [...this.middleware, ...middleware],
|
|
1546
|
+
cacheTags, revalidate, connection, updateTag
|
|
1544
1547
|
)
|
|
1545
1548
|
|
|
1546
1549
|
requestCache.set(dedupeKey, requestPromise)
|
|
@@ -1556,7 +1559,8 @@ export class BaseApiClient {
|
|
|
1556
1559
|
return this.executeRequestInternal<TData>(
|
|
1557
1560
|
method, url, body, headers, fetchOptions, timeout, retries,
|
|
1558
1561
|
retryDelay, retryCondition, validateResponse, skipAuth,
|
|
1559
|
-
responseSchema, requestId, [...this.middleware, ...middleware]
|
|
1562
|
+
responseSchema, requestId, [...this.middleware, ...middleware],
|
|
1563
|
+
cacheTags, revalidate, connection, updateTag
|
|
1560
1564
|
)
|
|
1561
1565
|
}
|
|
1562
1566
|
|
|
@@ -1575,7 +1579,11 @@ export class BaseApiClient {
|
|
|
1575
1579
|
skipAuth: boolean,
|
|
1576
1580
|
responseSchema?: z.ZodSchema<TData>,
|
|
1577
1581
|
requestId?: string,
|
|
1578
|
-
middleware: RequestMiddleware[] = []
|
|
1582
|
+
middleware: RequestMiddleware[] = [],
|
|
1583
|
+
cacheTags: string[] = [],
|
|
1584
|
+
revalidate?: number | false,
|
|
1585
|
+
connection?: 'keep-alive' | 'close',
|
|
1586
|
+
updateTag?: (tag: string) => void
|
|
1579
1587
|
): Promise<ClientResponse<TData>> {
|
|
1580
1588
|
const startTime = Date.now()
|
|
1581
1589
|
|
|
@@ -1662,7 +1670,7 @@ export class BaseApiClient {
|
|
|
1662
1670
|
|
|
1663
1671
|
if (tagUpdater && typeof window === 'undefined') {
|
|
1664
1672
|
// Update cache tags on server-side only
|
|
1665
|
-
cacheTags.forEach(tag => {
|
|
1673
|
+
cacheTags.forEach((tag: string) => {
|
|
1666
1674
|
try {
|
|
1667
1675
|
tagUpdater(tag)
|
|
1668
1676
|
} catch (error) {
|
|
@@ -2549,13 +2557,23 @@ var SchemaGenerator = class {
|
|
|
2549
2557
|
const result = [];
|
|
2550
2558
|
const schemaMap = /* @__PURE__ */ new Map();
|
|
2551
2559
|
const dependencyGraph = /* @__PURE__ */ new Map();
|
|
2560
|
+
const enumSchemas = [];
|
|
2561
|
+
const otherSchemas = [];
|
|
2552
2562
|
for (const schema of schemas) {
|
|
2563
|
+
const isEnum = this.isEnumSchema(schema);
|
|
2564
|
+
if (isEnum) {
|
|
2565
|
+
enumSchemas.push(schema);
|
|
2566
|
+
} else {
|
|
2567
|
+
otherSchemas.push(schema);
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
for (const schema of [...enumSchemas, ...otherSchemas]) {
|
|
2553
2571
|
if (!schemaMap.has(schema.name)) {
|
|
2554
2572
|
schemaMap.set(schema.name, schema);
|
|
2555
2573
|
dependencyGraph.set(schema.name, /* @__PURE__ */ new Set());
|
|
2556
2574
|
}
|
|
2557
2575
|
}
|
|
2558
|
-
for (const schema of
|
|
2576
|
+
for (const schema of [...enumSchemas, ...otherSchemas]) {
|
|
2559
2577
|
const dependencies = this.findSchemaDependencies(schema);
|
|
2560
2578
|
for (const dep of dependencies) {
|
|
2561
2579
|
if (schemaMap.has(dep)) {
|
|
@@ -2585,13 +2603,25 @@ var SchemaGenerator = class {
|
|
|
2585
2603
|
visiting.delete(schemaName);
|
|
2586
2604
|
visited.add(schemaName);
|
|
2587
2605
|
}, "visit");
|
|
2588
|
-
for (const schema of
|
|
2606
|
+
for (const schema of enumSchemas) {
|
|
2607
|
+
if (!visited.has(schema.name)) {
|
|
2608
|
+
visit(schema.name);
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
for (const schema of otherSchemas) {
|
|
2589
2612
|
if (!visited.has(schema.name)) {
|
|
2590
2613
|
visit(schema.name);
|
|
2591
2614
|
}
|
|
2592
2615
|
}
|
|
2593
2616
|
return result;
|
|
2594
2617
|
}
|
|
2618
|
+
isEnumSchema(schema) {
|
|
2619
|
+
if (!schema.schema || !schema.schema._def) {
|
|
2620
|
+
return false;
|
|
2621
|
+
}
|
|
2622
|
+
const def = schema.schema._def;
|
|
2623
|
+
return def.typeName === "ZodEnum";
|
|
2624
|
+
}
|
|
2595
2625
|
findSchemaDependencies(schema) {
|
|
2596
2626
|
const dependencies = [];
|
|
2597
2627
|
const schemaObj = schema.schema;
|
|
@@ -2673,7 +2703,7 @@ var SchemaGenerator = class {
|
|
|
2673
2703
|
schemaExports.push(...endpointSchemas.exports);
|
|
2674
2704
|
}
|
|
2675
2705
|
const validationHelpers = this.generateValidationHelpers();
|
|
2676
|
-
const
|
|
2706
|
+
const contentWithImports = [
|
|
2677
2707
|
...imports,
|
|
2678
2708
|
"",
|
|
2679
2709
|
"// Generated schemas from OpenAPI specification",
|
|
@@ -2683,7 +2713,13 @@ var SchemaGenerator = class {
|
|
|
2683
2713
|
"",
|
|
2684
2714
|
validationHelpers,
|
|
2685
2715
|
""
|
|
2686
|
-
].join("\n")
|
|
2716
|
+
].join("\n");
|
|
2717
|
+
let content = this.removeUnusedCode(contentWithImports);
|
|
2718
|
+
if (!content.includes('import { z } from "zod"') && !content.includes("import { z } from 'zod'")) {
|
|
2719
|
+
content = `import { z } from "zod"
|
|
2720
|
+
|
|
2721
|
+
${content}`;
|
|
2722
|
+
}
|
|
2687
2723
|
return {
|
|
2688
2724
|
path: "schemas/index.ts",
|
|
2689
2725
|
content,
|
|
@@ -3032,7 +3068,11 @@ export const errorMessages = {
|
|
|
3032
3068
|
const lines = content.split("\n");
|
|
3033
3069
|
const cleanedLines = [];
|
|
3034
3070
|
const usedIdentifiers = /* @__PURE__ */ new Set();
|
|
3071
|
+
usedIdentifiers.add("z");
|
|
3035
3072
|
for (const line of lines) {
|
|
3073
|
+
if (line.includes("z.")) {
|
|
3074
|
+
usedIdentifiers.add("z");
|
|
3075
|
+
}
|
|
3036
3076
|
const assignments = line.match(/(\w+)\s*[:=]/g);
|
|
3037
3077
|
if (assignments) {
|
|
3038
3078
|
assignments.forEach((match) => {
|
|
@@ -3047,6 +3087,9 @@ export const errorMessages = {
|
|
|
3047
3087
|
usedIdentifiers.add(identifier);
|
|
3048
3088
|
});
|
|
3049
3089
|
}
|
|
3090
|
+
if (line.includes("z.infer")) {
|
|
3091
|
+
usedIdentifiers.add("z");
|
|
3092
|
+
}
|
|
3050
3093
|
}
|
|
3051
3094
|
for (const line of lines) {
|
|
3052
3095
|
if (line.trim() === "" || line.trim().startsWith("//")) {
|
|
@@ -3054,6 +3097,10 @@ export const errorMessages = {
|
|
|
3054
3097
|
continue;
|
|
3055
3098
|
}
|
|
3056
3099
|
if (line.includes("import") && line.includes("from")) {
|
|
3100
|
+
if (line.includes('from "zod"') || line.includes("from 'zod'")) {
|
|
3101
|
+
cleanedLines.push(line);
|
|
3102
|
+
continue;
|
|
3103
|
+
}
|
|
3057
3104
|
const importMatch = line.match(/import\s*\{([^}]+)\}/);
|
|
3058
3105
|
if (importMatch) {
|
|
3059
3106
|
const imports = importMatch[1].split(",").map((imp) => imp.trim());
|
|
@@ -3082,6 +3129,166 @@ var ActionGenerator = class {
|
|
|
3082
3129
|
static {
|
|
3083
3130
|
__name(this, "ActionGenerator");
|
|
3084
3131
|
}
|
|
3132
|
+
get loggingEnabled() {
|
|
3133
|
+
return this.configuration.dev?.logging !== false;
|
|
3134
|
+
}
|
|
3135
|
+
get validationEnabled() {
|
|
3136
|
+
return this.configuration.dev?.validation !== false;
|
|
3137
|
+
}
|
|
3138
|
+
get commentsEnabled() {
|
|
3139
|
+
return this.configuration.generation?.comments !== false;
|
|
3140
|
+
}
|
|
3141
|
+
get documentationEnabled() {
|
|
3142
|
+
return this.configuration.generation?.documentation !== false;
|
|
3143
|
+
}
|
|
3144
|
+
commentLine(text, indent = 2) {
|
|
3145
|
+
if (!this.commentsEnabled) {
|
|
3146
|
+
return "";
|
|
3147
|
+
}
|
|
3148
|
+
return `${" ".repeat(indent)}// ${text}
|
|
3149
|
+
`;
|
|
3150
|
+
}
|
|
3151
|
+
buildDocBlock(endpoint, featuresDescription) {
|
|
3152
|
+
if (!this.documentationEnabled) {
|
|
3153
|
+
return "";
|
|
3154
|
+
}
|
|
3155
|
+
const summary = endpoint.summary || endpoint.description || `${endpoint.method} ${endpoint.path}`;
|
|
3156
|
+
return `/**
|
|
3157
|
+
* ${summary}
|
|
3158
|
+
* @generated from ${endpoint.method} ${endpoint.path}
|
|
3159
|
+
* Features: ${featuresDescription}
|
|
3160
|
+
*/
|
|
3161
|
+
`;
|
|
3162
|
+
}
|
|
3163
|
+
buildUtilityFunctions() {
|
|
3164
|
+
const parts = [];
|
|
3165
|
+
if (this.commentsEnabled) {
|
|
3166
|
+
parts.push("// Utility functions for enhanced server actions");
|
|
3167
|
+
}
|
|
3168
|
+
parts.push(`async function getClientInfo() {
|
|
3169
|
+
const headersList = await headers()
|
|
3170
|
+
const userAgent = headersList.get('user-agent') || 'unknown'
|
|
3171
|
+
const ip = headersList.get('x-forwarded-for') || headersList.get('x-real-ip') || 'unknown'
|
|
3172
|
+
|
|
3173
|
+
return { userAgent, ip }
|
|
3174
|
+
}`);
|
|
3175
|
+
if (this.validationEnabled) {
|
|
3176
|
+
parts.push(`async function validateAndSanitizeInput<T>(schema: z.ZodSchema<T>, input: unknown): Promise<T> {
|
|
3177
|
+
try {
|
|
3178
|
+
return await schema.parseAsync(input)
|
|
3179
|
+
} catch (error) {
|
|
3180
|
+
if (error instanceof z.ZodError) {
|
|
3181
|
+
const errorMessages = error.issues.map(issue => {
|
|
3182
|
+
const path = issue.path.length > 0 ? \`\${issue.path.join('.')}: \` : ''
|
|
3183
|
+
return \`\${path}\${issue.message}\`
|
|
3184
|
+
}).join(', ')
|
|
3185
|
+
throw new ActionError(\`Input validation failed: \${errorMessages}\`, 'VALIDATION_ERROR')
|
|
3186
|
+
}
|
|
3187
|
+
throw new ActionError('Invalid input format', 'VALIDATION_ERROR')
|
|
3188
|
+
}
|
|
3189
|
+
}`);
|
|
3190
|
+
}
|
|
3191
|
+
const actionErrorBlock = `${this.commentsEnabled ? "// Enhanced error handling with context\n" : ""}class ActionExecutionError extends ActionError {
|
|
3192
|
+
constructor(
|
|
3193
|
+
message: string,
|
|
3194
|
+
public readonly context: {
|
|
3195
|
+
endpoint: string
|
|
3196
|
+
method: string
|
|
3197
|
+
timestamp: number
|
|
3198
|
+
},
|
|
3199
|
+
public readonly originalError?: unknown
|
|
3200
|
+
) {
|
|
3201
|
+
super(message, 'EXECUTION_ERROR')
|
|
3202
|
+
}
|
|
3203
|
+
}`;
|
|
3204
|
+
parts.push(actionErrorBlock);
|
|
3205
|
+
if (this.loggingEnabled) {
|
|
3206
|
+
const loggingHeader = this.commentsEnabled ? "// Logging utility for server actions\n" : "";
|
|
3207
|
+
parts.push(`${loggingHeader}async function logActionExecution(
|
|
3208
|
+
action: string,
|
|
3209
|
+
success: boolean,
|
|
3210
|
+
duration: number,
|
|
3211
|
+
context?: Record<string, any>
|
|
3212
|
+
) {
|
|
3213
|
+
if (process.env.NODE_ENV === 'development') {
|
|
3214
|
+
console.log(\`[ACTION] \${action} - \${success ? 'SUCCESS' : 'FAILED'} (\${duration}ms)\`, context)
|
|
3215
|
+
}
|
|
3216
|
+
|
|
3217
|
+
${this.commentsEnabled ? " // In production, send to your logging service\n // await analytics.track('server_action_executed', { action, success, duration, ...context })" : ""}
|
|
3218
|
+
}`);
|
|
3219
|
+
}
|
|
3220
|
+
return parts.join("\n\n");
|
|
3221
|
+
}
|
|
3222
|
+
buildCombinedValidationSnippet(operationName, schemaName) {
|
|
3223
|
+
if (this.validationEnabled) {
|
|
3224
|
+
return `
|
|
3225
|
+
${this.commentLine("Validate and sanitize input payload", 6)} const { body, params } = await validateAndSanitizeInput(${schemaName}, parsedInput)
|
|
3226
|
+
const validatedBody = body
|
|
3227
|
+
const validatedParams = params as z.infer<typeof ${operationName}ParamsSchema>`;
|
|
3228
|
+
}
|
|
3229
|
+
return `
|
|
3230
|
+
${this.commentLine("Runtime validation disabled - trusting provided payload", 6)} const { body, params } = parsedInput as {
|
|
3231
|
+
body: z.infer<typeof ${operationName}RequestSchema>
|
|
3232
|
+
params: z.infer<typeof ${operationName}ParamsSchema>
|
|
3233
|
+
}
|
|
3234
|
+
const validatedBody = body
|
|
3235
|
+
const validatedParams = params`;
|
|
3236
|
+
}
|
|
3237
|
+
buildBodyValidationSnippet(schemaName) {
|
|
3238
|
+
if (schemaName === "z.void()") {
|
|
3239
|
+
return "";
|
|
3240
|
+
}
|
|
3241
|
+
if (this.validationEnabled) {
|
|
3242
|
+
return `
|
|
3243
|
+
${this.commentLine("Validate and sanitize request body", 6)} const validatedBody = await validateAndSanitizeInput(${schemaName}, parsedInput)`;
|
|
3244
|
+
}
|
|
3245
|
+
return `
|
|
3246
|
+
${this.commentLine("Runtime validation disabled - trusting request body", 6)} const validatedBody = parsedInput as z.infer<typeof ${schemaName}>`;
|
|
3247
|
+
}
|
|
3248
|
+
buildParamsValidationSnippet(operationName, schemaName) {
|
|
3249
|
+
if (schemaName === "z.void()") {
|
|
3250
|
+
return "";
|
|
3251
|
+
}
|
|
3252
|
+
if (this.validationEnabled) {
|
|
3253
|
+
return `
|
|
3254
|
+
${this.commentLine("Validate and sanitize parameters", 6)} const validatedParams = await validateAndSanitizeInput(${schemaName}, parsedInput) as z.infer<typeof ${operationName}ParamsSchema>`;
|
|
3255
|
+
}
|
|
3256
|
+
return `
|
|
3257
|
+
${this.commentLine("Runtime validation disabled - trusting parameters", 6)} const validatedParams = parsedInput as z.infer<typeof ${operationName}ParamsSchema>`;
|
|
3258
|
+
}
|
|
3259
|
+
buildSuccessLoggingBlock(actionName, endpoint, indent, isStreaming = false) {
|
|
3260
|
+
if (!this.loggingEnabled) {
|
|
3261
|
+
return "";
|
|
3262
|
+
}
|
|
3263
|
+
if (isStreaming) {
|
|
3264
|
+
return `
|
|
3265
|
+
${this.commentLine("Background tasks (Next.js 15 feature)", indent)}${" ".repeat(indent)}after(async () => {
|
|
3266
|
+
${this.commentLine("Perform background tasks after response is sent", indent + 2)}${" ".repeat(indent + 2)}await logActionExecution('${actionName}', true, Date.now() - startTime, {
|
|
3267
|
+
${" ".repeat(indent + 4)}method: '${endpoint.method}',
|
|
3268
|
+
${" ".repeat(indent + 4)}path: '${endpoint.path}'
|
|
3269
|
+
${" ".repeat(indent + 2)}})
|
|
3270
|
+
${" ".repeat(indent)}})`;
|
|
3271
|
+
}
|
|
3272
|
+
return `
|
|
3273
|
+
${this.commentLine("Log successful execution", indent)}${" ".repeat(indent)}const duration = Date.now() - startTime
|
|
3274
|
+
${" ".repeat(indent)}await logActionExecution('${actionName}', true, duration, {
|
|
3275
|
+
${" ".repeat(indent + 2)}method: '${endpoint.method}',
|
|
3276
|
+
${" ".repeat(indent + 2)}path: '${endpoint.path}'
|
|
3277
|
+
${" ".repeat(indent)}})`;
|
|
3278
|
+
}
|
|
3279
|
+
buildErrorLoggingBlock(actionName, endpoint, indent) {
|
|
3280
|
+
if (!this.loggingEnabled) {
|
|
3281
|
+
return "";
|
|
3282
|
+
}
|
|
3283
|
+
return `
|
|
3284
|
+
${" ".repeat(indent)}const duration = Date.now() - startTime
|
|
3285
|
+
|
|
3286
|
+
${this.commentLine("Enhanced error logging", indent)}${" ".repeat(indent)}await logActionExecution('${actionName}', false, duration, {
|
|
3287
|
+
${" ".repeat(indent + 2)}method: '${endpoint.method}',
|
|
3288
|
+
${" ".repeat(indent + 2)}path: '${endpoint.path}',
|
|
3289
|
+
${" ".repeat(indent + 2)}error: error instanceof Error ? error.message : 'Unknown error'
|
|
3290
|
+
${" ".repeat(indent)}})`;
|
|
3291
|
+
}
|
|
3085
3292
|
buildImportPath(relativePath) {
|
|
3086
3293
|
const outputDirectory = this.configuration.outputDir || "generated";
|
|
3087
3294
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
@@ -3134,7 +3341,7 @@ var ActionGenerator = class {
|
|
|
3134
3341
|
...hasStreaming ? ["import { after } from 'next/server'"] : [],
|
|
3135
3342
|
"import { headers } from 'next/headers'",
|
|
3136
3343
|
`import { apiClient } from '${clientImport}'`,
|
|
3137
|
-
`import { ${usesAuth || hasRateLimit ? "authActionClient" : "
|
|
3344
|
+
`import { actionClientWithMeta${usesAuth || hasRateLimit ? ", authActionClient" : ""}, ActionError } from '${safeActionImport}'`,
|
|
3138
3345
|
...schemaImportsString ? [`import {
|
|
3139
3346
|
${schemaImportsString}
|
|
3140
3347
|
} from '${schemasImport}'`] : [],
|
|
@@ -3146,8 +3353,7 @@ var ActionGenerator = class {
|
|
|
3146
3353
|
] : []
|
|
3147
3354
|
].filter(Boolean).join("\n");
|
|
3148
3355
|
const rateLimitSetup = hasRateLimit ? `
|
|
3149
|
-
// Rate limiting setup
|
|
3150
|
-
const redis = new Redis({
|
|
3356
|
+
${this.commentsEnabled ? "// Rate limiting setup\n" : ""}const redis = new Redis({
|
|
3151
3357
|
url: process.env.UPSTASH_REDIS_REST_URL!,
|
|
3152
3358
|
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
|
|
3153
3359
|
})
|
|
@@ -3157,60 +3363,7 @@ const ratelimit = new Ratelimit({
|
|
|
3157
3363
|
limiter: Ratelimit.slidingWindow(10, '1 m'),
|
|
3158
3364
|
analytics: true,
|
|
3159
3365
|
})` : "";
|
|
3160
|
-
const utilityFunctions =
|
|
3161
|
-
// Utility functions for enhanced server actions
|
|
3162
|
-
async function getClientInfo() {
|
|
3163
|
-
const headersList = await headers()
|
|
3164
|
-
const userAgent = headersList.get('user-agent') || 'unknown'
|
|
3165
|
-
const ip = headersList.get('x-forwarded-for') || headersList.get('x-real-ip') || 'unknown'
|
|
3166
|
-
|
|
3167
|
-
return { userAgent, ip }
|
|
3168
|
-
}
|
|
3169
|
-
|
|
3170
|
-
async function validateAndSanitizeInput<T>(schema: z.ZodSchema<T>, input: unknown): Promise<T> {
|
|
3171
|
-
try {
|
|
3172
|
-
return await schema.parseAsync(input)
|
|
3173
|
-
} catch (error) {
|
|
3174
|
-
if (error instanceof z.ZodError) {
|
|
3175
|
-
const errorMessages = error.issues.map(issue => {
|
|
3176
|
-
const path = issue.path.length > 0 ? \`\${issue.path.join('.')}: \` : ''
|
|
3177
|
-
return \`\${path}\${issue.message}\`
|
|
3178
|
-
}).join(', ')
|
|
3179
|
-
throw new ActionError(\`Input validation failed: \${errorMessages}\`, 'VALIDATION_ERROR')
|
|
3180
|
-
}
|
|
3181
|
-
throw new ActionError('Invalid input format', 'VALIDATION_ERROR')
|
|
3182
|
-
}
|
|
3183
|
-
}
|
|
3184
|
-
|
|
3185
|
-
// Enhanced error handling with context
|
|
3186
|
-
class ActionExecutionError extends ActionError {
|
|
3187
|
-
constructor(
|
|
3188
|
-
message: string,
|
|
3189
|
-
public readonly context: {
|
|
3190
|
-
endpoint: string
|
|
3191
|
-
method: string
|
|
3192
|
-
timestamp: number
|
|
3193
|
-
},
|
|
3194
|
-
public readonly originalError?: unknown
|
|
3195
|
-
) {
|
|
3196
|
-
super(message, 'EXECUTION_ERROR')
|
|
3197
|
-
}
|
|
3198
|
-
}
|
|
3199
|
-
|
|
3200
|
-
// Logging utility for server actions
|
|
3201
|
-
async function logActionExecution(
|
|
3202
|
-
action: string,
|
|
3203
|
-
success: boolean,
|
|
3204
|
-
duration: number,
|
|
3205
|
-
context?: Record<string, any>
|
|
3206
|
-
) {
|
|
3207
|
-
if (process.env.NODE_ENV === 'development') {
|
|
3208
|
-
console.log(\`[ACTION] \${action} - \${success ? 'SUCCESS' : 'FAILED'} (\${duration}ms)\`, context)
|
|
3209
|
-
}
|
|
3210
|
-
|
|
3211
|
-
// In production, send to your logging service
|
|
3212
|
-
// await analytics.track('server_action_executed', { action, success, duration, ...context })
|
|
3213
|
-
}`;
|
|
3366
|
+
const utilityFunctions = this.buildUtilityFunctions();
|
|
3214
3367
|
const content = `${imports}
|
|
3215
3368
|
${rateLimitSetup}
|
|
3216
3369
|
${utilityFunctions}
|
|
@@ -3227,8 +3380,8 @@ ${actions}`;
|
|
|
3227
3380
|
}
|
|
3228
3381
|
});
|
|
3229
3382
|
}
|
|
3230
|
-
const
|
|
3231
|
-
${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier(tag)}'`).join("\n")}`;
|
|
3383
|
+
const indexHeader = this.commentsEnabled ? "// Auto-generated actions index\n" : "";
|
|
3384
|
+
const indexContent = `${indexHeader}${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier(tag)}'`).join("\n")}`;
|
|
3232
3385
|
generatedFiles.push({
|
|
3233
3386
|
path: "actions/index.ts",
|
|
3234
3387
|
content: indexContent,
|
|
@@ -3277,54 +3430,48 @@ ${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier
|
|
|
3277
3430
|
body: ${operationName}RequestSchema,
|
|
3278
3431
|
params: ${operationName}ParamsSchema
|
|
3279
3432
|
})`;
|
|
3280
|
-
parameterProcessing =
|
|
3281
|
-
// Validate and sanitize input
|
|
3282
|
-
const { body, params } = await validateAndSanitizeInput(${schemaName}, parsedInput)
|
|
3283
|
-
const validatedBody = body
|
|
3284
|
-
const validatedParams = params as any`;
|
|
3433
|
+
parameterProcessing = this.buildCombinedValidationSnippet(operationName, schemaName);
|
|
3285
3434
|
requestOptionsParams = this.buildRequestOptions(pathParameters, queryParameters, true, true);
|
|
3286
3435
|
} else if (hasRequestBody) {
|
|
3287
3436
|
schemaName = `${operationName}RequestSchema`;
|
|
3288
|
-
parameterProcessing =
|
|
3289
|
-
// Validate and sanitize request body
|
|
3290
|
-
const validatedBody = await validateAndSanitizeInput(${schemaName}, parsedInput)`;
|
|
3437
|
+
parameterProcessing = this.buildBodyValidationSnippet(schemaName);
|
|
3291
3438
|
requestOptionsParams = `body: validatedBody`;
|
|
3292
3439
|
} else if (hasAnyParams) {
|
|
3293
3440
|
schemaName = `${operationName}ParamsSchema`;
|
|
3294
|
-
parameterProcessing =
|
|
3295
|
-
// Validate and sanitize parameters
|
|
3296
|
-
const validatedParams = await validateAndSanitizeInput(${schemaName}, parsedInput) as any`;
|
|
3441
|
+
parameterProcessing = this.buildParamsValidationSnippet(operationName, schemaName);
|
|
3297
3442
|
requestOptionsParams = this.buildRequestOptions(pathParameters, queryParameters, false, true);
|
|
3298
3443
|
} else {
|
|
3299
3444
|
schemaName = "z.void()";
|
|
3300
3445
|
parameterProcessing = "";
|
|
3301
3446
|
requestOptionsParams = "";
|
|
3302
3447
|
}
|
|
3448
|
+
const parsedInputType = hasRequestBody || hasAnyParams ? `z.infer<typeof ${schemaName}>` : "void";
|
|
3449
|
+
const ctxType = requiresAuth || hasRateLimit ? "{ user?: any; ratelimit?: { remaining: number } }" : "any";
|
|
3450
|
+
const ctxDeclaration = requiresAuth || hasRateLimit ? `ctx: ${ctxType}` : "ctx?: any";
|
|
3451
|
+
const actionArgsType = `{ parsedInput: ${parsedInputType}; ${ctxDeclaration} }`;
|
|
3303
3452
|
const clientName = requiresAuth || hasRateLimit ? "authActionClient" : "actionClientWithMeta";
|
|
3304
3453
|
const rateLimitCode = hasRateLimit ? `
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
}` : "";
|
|
3454
|
+
${this.commentLine("Rate limiting", 6)} const { userAgent, ip } = await getClientInfo()
|
|
3455
|
+
const identifier = \`\${ip}-\${userAgent}\`
|
|
3456
|
+
const { success, limit, reset, remaining } = await ratelimit.limit(identifier)
|
|
3457
|
+
|
|
3458
|
+
if (!success) {
|
|
3459
|
+
throw new ActionError(
|
|
3460
|
+
\`Rate limit exceeded. Try again in \${Math.round((reset - Date.now()) / 1000)} seconds.\`,
|
|
3461
|
+
'RATE_LIMIT_EXCEEDED'
|
|
3462
|
+
)
|
|
3463
|
+
}` : "";
|
|
3316
3464
|
const revalidationCode = revalidationTags.length > 0 ? revalidationTags.map(
|
|
3317
|
-
(tag) => ` updateTag('${tag}')
|
|
3318
|
-
console.log('Updated tag: ${tag}')`
|
|
3465
|
+
(tag) => ` updateTag('${tag}')${this.loggingEnabled ? `
|
|
3466
|
+
console.log('Updated tag: ${tag}')` : ""}`
|
|
3319
3467
|
).join("\n") : "";
|
|
3320
3468
|
const kebabActionName = actionName.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
|
|
3321
3469
|
if (isQuery) {
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
export const ${actionName} = cache(
|
|
3470
|
+
const docBlock = this.buildDocBlock(
|
|
3471
|
+
endpoint,
|
|
3472
|
+
"React cache, input validation, error handling"
|
|
3473
|
+
);
|
|
3474
|
+
return `${docBlock}export const ${actionName} = cache(
|
|
3328
3475
|
${clientName}
|
|
3329
3476
|
.metadata({
|
|
3330
3477
|
name: "${kebabActionName}",
|
|
@@ -3332,7 +3479,7 @@ export const ${actionName} = cache(
|
|
|
3332
3479
|
rateLimit: { requests: ${endpoint.metadata.rateLimit?.requests || 10}, window: "${endpoint.metadata.rateLimit?.window || "1m"}" }` : ""}
|
|
3333
3480
|
})
|
|
3334
3481
|
.schema(${schemaName})
|
|
3335
|
-
.action(async ({ parsedInput, ctx }) => {
|
|
3482
|
+
.action(async ({ parsedInput, ctx }: ${actionArgsType}) => {
|
|
3336
3483
|
const startTime = Date.now()
|
|
3337
3484
|
|
|
3338
3485
|
try {${rateLimitCode}${parameterProcessing}
|
|
@@ -3347,23 +3494,11 @@ export const ${actionName} = cache(
|
|
|
3347
3494
|
}
|
|
3348
3495
|
})
|
|
3349
3496
|
|
|
3350
|
-
|
|
3351
|
-
const duration = Date.now() - startTime
|
|
3352
|
-
await logActionExecution('${actionName}', true, duration, {
|
|
3353
|
-
method: '${endpoint.method}',
|
|
3354
|
-
path: '${endpoint.path}'
|
|
3355
|
-
})
|
|
3497
|
+
${this.buildSuccessLoggingBlock(actionName, endpoint, 8)}
|
|
3356
3498
|
|
|
3357
3499
|
return response.data
|
|
3358
3500
|
} catch (error) {
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
// Enhanced error logging
|
|
3362
|
-
await logActionExecution('${actionName}', false, duration, {
|
|
3363
|
-
method: '${endpoint.method}',
|
|
3364
|
-
path: '${endpoint.path}',
|
|
3365
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
3366
|
-
})
|
|
3501
|
+
${this.buildErrorLoggingBlock(actionName, endpoint, 8)}
|
|
3367
3502
|
|
|
3368
3503
|
// Throw enhanced error with context
|
|
3369
3504
|
throw new ActionExecutionError(
|
|
@@ -3380,50 +3515,37 @@ export const ${actionName} = cache(
|
|
|
3380
3515
|
)`;
|
|
3381
3516
|
}
|
|
3382
3517
|
const redirectCode = `
|
|
3383
|
-
|
|
3384
|
-
if (response.status === 201 && response.headers.get('location')) {
|
|
3518
|
+
${this.commentLine("Handle potential redirects based on response", 8)} if (response.status === 201 && response.headers.get('location')) {
|
|
3385
3519
|
const location = response.headers.get('location')!
|
|
3386
3520
|
redirect(location)
|
|
3387
3521
|
}`;
|
|
3388
3522
|
const streamingCode = `
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
// Process streaming response
|
|
3392
|
-
return response.data
|
|
3523
|
+
${this.commentLine("Handle streaming responses", 8)} if (response.headers.get('content-type')?.includes('text/stream')) {
|
|
3524
|
+
${this.commentLine("Process streaming response", 10)} return response.data
|
|
3393
3525
|
}`;
|
|
3394
3526
|
const fileUploadCode = hasFileUpload ? uploadStrategy === "external" && uploadProvider === "vercel-blob" ? `
|
|
3395
|
-
|
|
3396
|
-
if (validatedBody && typeof validatedBody === 'object' && 'file' in validatedBody) {
|
|
3527
|
+
${this.commentLine("Handle file uploads with Vercel Blob", 8)} if (validatedBody && typeof validatedBody === 'object' && 'file' in validatedBody) {
|
|
3397
3528
|
const file = (validatedBody as any).file as File
|
|
3398
3529
|
const blob = await put(file.name, file, { access: 'public' })
|
|
3399
3530
|
Object.assign(validatedBody, { fileUrl: blob.url })
|
|
3400
3531
|
}` : uploadStrategy === "external" && uploadProvider === "uploadthing" ? `
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
const file = (validatedBody as any).file as File
|
|
3412
|
-
// Process file with compression and validation if enabled
|
|
3413
|
-
}` : "";
|
|
3414
|
-
return `/**
|
|
3415
|
-
* ${endpoint.summary || endpoint.description || `${endpoint.method} ${endpoint.path}`}
|
|
3416
|
-
* @generated from ${endpoint.method} ${endpoint.path}
|
|
3417
|
-
* Features: Input validation, revalidation, error handling
|
|
3418
|
-
*/
|
|
3419
|
-
export const ${actionName} = ${clientName}
|
|
3532
|
+
${this.commentLine("Handle file uploads with UploadThing", 8)}${this.commentLine("UploadThing requires a separate route handler setup", 8)}${this.commentLine("See: https://docs.uploadthing.com/getting-started/appdir", 8)} if (validatedBody && typeof validatedBody === 'object' && 'file' in validatedBody) {
|
|
3533
|
+
${this.commentLine("UploadThing file handling should be done via their route handler", 10)}${this.commentLine("This is a placeholder - implement according to UploadThing docs", 10)} }` : `
|
|
3534
|
+
${this.commentLine("Handle file uploads with standard FormData", 8)} if (validatedBody && typeof validatedBody === 'object' && 'file' in validatedBody) {
|
|
3535
|
+
${this.commentLine("Standard file upload handling", 10)} const file = (validatedBody as any).file as File
|
|
3536
|
+
${this.commentLine("Process file with compression and validation if enabled", 10)} }` : "";
|
|
3537
|
+
const mutationDocBlock = this.buildDocBlock(
|
|
3538
|
+
endpoint,
|
|
3539
|
+
"Input validation, revalidation, error handling"
|
|
3540
|
+
);
|
|
3541
|
+
return `${mutationDocBlock}export const ${actionName} = ${clientName}
|
|
3420
3542
|
.metadata({
|
|
3421
3543
|
name: "${kebabActionName}",
|
|
3422
3544
|
requiresAuth: ${requiresAuth}${hasRateLimit ? `,
|
|
3423
3545
|
rateLimit: { requests: ${endpoint.metadata.rateLimit?.requests || 10}, window: "${endpoint.metadata.rateLimit?.window || "1m"}" }` : ""}
|
|
3424
3546
|
})
|
|
3425
3547
|
.schema(${schemaName})
|
|
3426
|
-
.action(async ({ parsedInput, ctx }) => {
|
|
3548
|
+
.action(async ({ parsedInput, ctx }: ${actionArgsType}) => {
|
|
3427
3549
|
const startTime = Date.now()
|
|
3428
3550
|
|
|
3429
3551
|
try {${rateLimitCode}${parameterProcessing}${fileUploadCode}
|
|
@@ -3438,33 +3560,13 @@ export const ${actionName} = ${clientName}
|
|
|
3438
3560
|
}
|
|
3439
3561
|
})${streamingCode}${redirectCode}
|
|
3440
3562
|
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
// Background tasks (Next.js 15 feature)
|
|
3445
|
-
${isStreaming ? `after(async () => {
|
|
3446
|
-
// Perform background tasks after response is sent
|
|
3447
|
-
await logActionExecution('${actionName}', true, Date.now() - startTime, {
|
|
3448
|
-
method: '${endpoint.method}',
|
|
3449
|
-
path: '${endpoint.path}'
|
|
3450
|
-
})
|
|
3451
|
-
})` : `// Log successful execution
|
|
3452
|
-
const duration = Date.now() - startTime
|
|
3453
|
-
await logActionExecution('${actionName}', true, duration, {
|
|
3454
|
-
method: '${endpoint.method}',
|
|
3455
|
-
path: '${endpoint.path}'
|
|
3456
|
-
})`}
|
|
3563
|
+
${revalidationCode ? `${this.commentLine("Revalidate cache after successful mutation", 6)}${revalidationCode}
|
|
3564
|
+
` : ""}
|
|
3565
|
+
${this.buildSuccessLoggingBlock(actionName, endpoint, 6, isStreaming)}
|
|
3457
3566
|
|
|
3458
3567
|
return response.data
|
|
3459
3568
|
} catch (error) {
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
// Enhanced error logging
|
|
3463
|
-
await logActionExecution('${actionName}', false, duration, {
|
|
3464
|
-
method: '${endpoint.method}',
|
|
3465
|
-
path: '${endpoint.path}',
|
|
3466
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
3467
|
-
})
|
|
3569
|
+
${this.buildErrorLoggingBlock(actionName, endpoint, 6)}
|
|
3468
3570
|
|
|
3469
3571
|
// Throw enhanced error with context
|
|
3470
3572
|
throw new ActionExecutionError(
|
|
@@ -3623,7 +3725,6 @@ var HookGenerator = class {
|
|
|
3623
3725
|
if (hasInfiniteQueries) reactQueryImports.push("useInfiniteQuery");
|
|
3624
3726
|
const reactImports = [];
|
|
3625
3727
|
if (hasMutations) reactImports.push("useOptimistic", "useTransition");
|
|
3626
|
-
if (hasQueries) reactImports.push("useCallback");
|
|
3627
3728
|
const imports = [
|
|
3628
3729
|
"'use client'",
|
|
3629
3730
|
"",
|
|
@@ -3735,19 +3836,19 @@ ${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier
|
|
|
3735
3836
|
* @returns useQuery result with data of type ${returnType}
|
|
3736
3837
|
*/
|
|
3737
3838
|
export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join(", ")}, ` : ""}options?: ${optionsType}) {
|
|
3738
|
-
const [searchParams
|
|
3839
|
+
const [searchParams] = useQueryStates(searchParamsParser)
|
|
3739
3840
|
const { initialData, ...restOptions } = options ?? {}
|
|
3740
3841
|
|
|
3741
3842
|
return useQuery({
|
|
3742
3843
|
queryKey: [...${queryKey}, searchParams],
|
|
3743
|
-
queryFn:
|
|
3844
|
+
queryFn: async ({ signal }: { signal?: AbortSignal }) => {
|
|
3744
3845
|
try {
|
|
3745
3846
|
const result = await ${actionName}(${actionCallParams.replace(queryParamObject, "{ ...searchParams }")})
|
|
3746
3847
|
return result
|
|
3747
3848
|
} catch (error) {
|
|
3748
3849
|
handleActionError(error)
|
|
3749
3850
|
}
|
|
3750
|
-
},
|
|
3851
|
+
},
|
|
3751
3852
|
staleTime: ${staleTime},
|
|
3752
3853
|
gcTime: ${staleTime * 2}, // React Query v5: gcTime replaces cacheTime
|
|
3753
3854
|
enabled: ${enabledCondition} && (options?.enabled ?? true),
|
|
@@ -3757,14 +3858,14 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3757
3858
|
refetchInterval: options?.refetchInterval, // Optional polling interval
|
|
3758
3859
|
initialDataUpdatedAt: initialData ? Date.now() : undefined,
|
|
3759
3860
|
// React Query v5: placeholderData replaces keepPreviousData
|
|
3760
|
-
placeholderData: (previousData) => previousData,
|
|
3761
|
-
retry: (failureCount, error) => {
|
|
3861
|
+
placeholderData: (previousData: ${returnType} | undefined) => previousData,
|
|
3862
|
+
retry: (failureCount: number, error: Error) => {
|
|
3762
3863
|
// Don't retry on 4xx errors (client errors)
|
|
3763
3864
|
if (error instanceof Error && error.message.includes('4')) return false
|
|
3764
3865
|
// Retry up to 3 times for network/server errors
|
|
3765
3866
|
return failureCount < 3
|
|
3766
3867
|
},
|
|
3767
|
-
initialData: initialData as
|
|
3868
|
+
initialData: initialData as ${returnType} | undefined,
|
|
3768
3869
|
...restOptions
|
|
3769
3870
|
})
|
|
3770
3871
|
}
|
|
@@ -3779,15 +3880,15 @@ export function ${hookName.replace("use", "useInfinite")}(${parameterTypes.lengt
|
|
|
3779
3880
|
|
|
3780
3881
|
return useInfiniteQuery({
|
|
3781
3882
|
queryKey: [...${queryKey}, 'infinite', searchParams],
|
|
3782
|
-
queryFn:
|
|
3883
|
+
queryFn: async ({ pageParam = 1, signal }: { pageParam?: number; signal?: AbortSignal }) => {
|
|
3783
3884
|
try {
|
|
3784
3885
|
const result = await ${actionName}(${actionCallParams.replace(queryParamObject, "{ ...searchParams, page: pageParam, limit: searchParams.limit }")})
|
|
3785
3886
|
return result
|
|
3786
3887
|
} catch (error) {
|
|
3787
3888
|
handleActionError(error)
|
|
3788
3889
|
}
|
|
3789
|
-
},
|
|
3790
|
-
getNextPageParam: (lastPage:
|
|
3890
|
+
},
|
|
3891
|
+
getNextPageParam: (lastPage: ${returnType}, allPages: ${returnType}[]) => {
|
|
3791
3892
|
if (lastPage?.hasMore || (Array.isArray(lastPage) && lastPage.length === searchParams.limit)) {
|
|
3792
3893
|
return allPages.length + 1
|
|
3793
3894
|
}
|
|
@@ -3800,9 +3901,9 @@ export function ${hookName.replace("use", "useInfinite")}(${parameterTypes.lengt
|
|
|
3800
3901
|
refetchOnReconnect: true,
|
|
3801
3902
|
refetchOnMount: 'always',
|
|
3802
3903
|
initialDataUpdatedAt: initialData ? Date.now() : undefined,
|
|
3803
|
-
placeholderData: (previousData) => previousData,
|
|
3904
|
+
placeholderData: (previousData: ${returnType} | undefined) => previousData,
|
|
3804
3905
|
retry: 3,
|
|
3805
|
-
initialData: initialData as
|
|
3906
|
+
initialData: initialData as ${returnType} | undefined,
|
|
3806
3907
|
...restOptions
|
|
3807
3908
|
})
|
|
3808
3909
|
}
|
|
@@ -3816,12 +3917,12 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3816
3917
|
|
|
3817
3918
|
return useSuspenseQuery({
|
|
3818
3919
|
queryKey: ${queryKey},
|
|
3819
|
-
queryFn:
|
|
3920
|
+
queryFn: async () => {
|
|
3820
3921
|
const result = await ${actionName}(${actionCallParams})
|
|
3821
3922
|
return result
|
|
3822
|
-
},
|
|
3923
|
+
},
|
|
3823
3924
|
staleTime: ${staleTime},
|
|
3824
|
-
initialData: initialData as
|
|
3925
|
+
initialData: initialData as ${returnType} | undefined,
|
|
3825
3926
|
...restOptions
|
|
3826
3927
|
})
|
|
3827
3928
|
}`;
|
|
@@ -3836,14 +3937,14 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3836
3937
|
|
|
3837
3938
|
return useQuery({
|
|
3838
3939
|
queryKey: ${queryKey},
|
|
3839
|
-
queryFn:
|
|
3940
|
+
queryFn: async ({ signal }: { signal?: AbortSignal }) => {
|
|
3840
3941
|
try {
|
|
3841
3942
|
const result = await ${actionName}(${actionCallParams})
|
|
3842
3943
|
return result
|
|
3843
3944
|
} catch (error) {
|
|
3844
3945
|
handleActionError(error)
|
|
3845
3946
|
}
|
|
3846
|
-
},
|
|
3947
|
+
},
|
|
3847
3948
|
staleTime: ${staleTime},
|
|
3848
3949
|
gcTime: ${staleTime * 2}, // React Query v5: gcTime replaces cacheTime
|
|
3849
3950
|
enabled: ${enabledCondition} && (options?.enabled ?? true),
|
|
@@ -3853,14 +3954,14 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3853
3954
|
refetchInterval: options?.refetchInterval, // Optional polling interval
|
|
3854
3955
|
initialDataUpdatedAt: initialData ? Date.now() : undefined,
|
|
3855
3956
|
// React Query v5: placeholderData replaces keepPreviousData
|
|
3856
|
-
placeholderData: (previousData) => previousData,
|
|
3857
|
-
retry: (failureCount, error) => {
|
|
3957
|
+
placeholderData: (previousData: ${returnType} | undefined) => previousData,
|
|
3958
|
+
retry: (failureCount: number, error: Error) => {
|
|
3858
3959
|
// Don't retry on 4xx errors (client errors)
|
|
3859
3960
|
if (error instanceof Error && error.message.includes('4')) return false
|
|
3860
3961
|
// Retry up to 3 times for network/server errors
|
|
3861
3962
|
return failureCount < 3
|
|
3862
3963
|
},
|
|
3863
|
-
initialData: initialData as
|
|
3964
|
+
initialData: initialData as ${returnType} | undefined,
|
|
3864
3965
|
...restOptions
|
|
3865
3966
|
})
|
|
3866
3967
|
}
|
|
@@ -3874,12 +3975,12 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3874
3975
|
|
|
3875
3976
|
return useSuspenseQuery({
|
|
3876
3977
|
queryKey: ${queryKey},
|
|
3877
|
-
queryFn:
|
|
3978
|
+
queryFn: async () => {
|
|
3878
3979
|
const result = await ${actionName}(${actionCallParams})
|
|
3879
3980
|
return result
|
|
3880
|
-
},
|
|
3981
|
+
},
|
|
3881
3982
|
staleTime: ${staleTime},
|
|
3882
|
-
initialData: initialData as
|
|
3983
|
+
initialData: initialData as ${returnType} | undefined,
|
|
3883
3984
|
...restOptions
|
|
3884
3985
|
})
|
|
3885
3986
|
}`;
|
|
@@ -3910,8 +4011,6 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3910
4011
|
const relatedQueries = this.findRelatedQueries(endpoint, context);
|
|
3911
4012
|
const invalidationCode = this.buildInvalidationCode(endpoint, relatedQueries, invalidationTags);
|
|
3912
4013
|
const cancelQueriesCode = this.buildCancelQueriesCode(endpoint, relatedQueries);
|
|
3913
|
-
const snapshotCode = this.buildSnapshotCode(endpoint, relatedQueries);
|
|
3914
|
-
const rollbackCode = this.buildRollbackCode(endpoint, relatedQueries);
|
|
3915
4014
|
return `/**
|
|
3916
4015
|
* Optimized mutation hook for ${endpoint.method} ${endpoint.path}
|
|
3917
4016
|
* Features: Optimistic updates, smart invalidation, error handling
|
|
@@ -3932,24 +4031,22 @@ export function ${hookName}(options?: {
|
|
|
3932
4031
|
mutationFn: async (variables: ${inputType}): Promise<${outputType}> => {
|
|
3933
4032
|
try {
|
|
3934
4033
|
const result = await ${actionName}(${variablesParam === "undefined" ? "" : "variables"})
|
|
3935
|
-
return result
|
|
4034
|
+
return (result ?? ({} as ${outputType}))
|
|
3936
4035
|
} catch (error) {
|
|
3937
4036
|
handleActionError(error)
|
|
3938
4037
|
}
|
|
3939
4038
|
},
|
|
3940
4039
|
|
|
3941
|
-
onMutate: async (variables) => {
|
|
4040
|
+
onMutate: async (variables: ${inputType}) => {
|
|
3942
4041
|
${cancelQueriesCode}
|
|
3943
|
-
|
|
3944
|
-
${snapshotCode}
|
|
3945
|
-
|
|
4042
|
+
|
|
3946
4043
|
// Optimistic update (if provided)
|
|
3947
4044
|
if (options?.optimisticUpdate) {
|
|
3948
4045
|
const optimisticValue = options.optimisticUpdate(variables)
|
|
3949
4046
|
setOptimisticData(optimisticValue)
|
|
3950
4047
|
}
|
|
3951
4048
|
|
|
3952
|
-
return {
|
|
4049
|
+
return {}
|
|
3953
4050
|
},
|
|
3954
4051
|
|
|
3955
4052
|
onSuccess: (data, variables) => {
|
|
@@ -3958,17 +4055,11 @@ ${snapshotCode}
|
|
|
3958
4055
|
toast.success('${this.getSuccessMessage(endpoint)}')
|
|
3959
4056
|
}
|
|
3960
4057
|
|
|
3961
|
-
// Invalidate and refetch related queries
|
|
3962
|
-
${invalidationCode}
|
|
3963
|
-
|
|
3964
4058
|
// Custom success handler
|
|
3965
4059
|
options?.onSuccess?.(data, variables)
|
|
3966
4060
|
},
|
|
3967
4061
|
|
|
3968
|
-
onError: (error, variables
|
|
3969
|
-
// Rollback optimistic update
|
|
3970
|
-
${rollbackCode}
|
|
3971
|
-
|
|
4062
|
+
onError: (error: Error, variables: ${inputType}) => {
|
|
3972
4063
|
// Show error toast
|
|
3973
4064
|
if (options?.showToast !== false) {
|
|
3974
4065
|
toast.error(error.message || '${this.getErrorMessage(endpoint)}')
|
|
@@ -3978,7 +4069,7 @@ ${rollbackCode}
|
|
|
3978
4069
|
options?.onError?.(error as Error, variables)
|
|
3979
4070
|
},
|
|
3980
4071
|
|
|
3981
|
-
onSettled: () => {
|
|
4072
|
+
onSettled: async () => {
|
|
3982
4073
|
// Always refetch after error or success
|
|
3983
4074
|
${invalidationCode}
|
|
3984
4075
|
}
|
|
@@ -4004,103 +4095,81 @@ ${invalidationCode}
|
|
|
4004
4095
|
return [];
|
|
4005
4096
|
}
|
|
4006
4097
|
const relatedQueries = [];
|
|
4007
|
-
const
|
|
4098
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4008
4099
|
const mutationTag = endpoint.tags[0];
|
|
4009
|
-
const
|
|
4100
|
+
const mutationSegments = this.getResourceSegments(endpoint.path);
|
|
4101
|
+
const mutationResource = mutationSegments[0];
|
|
4010
4102
|
context.schema.endpoints.forEach((queryEndpoint) => {
|
|
4011
4103
|
if (queryEndpoint.method !== "GET") return;
|
|
4012
|
-
const
|
|
4104
|
+
const queryId = queryEndpoint.operationId || queryEndpoint.id;
|
|
4105
|
+
if (seen.has(queryId)) return;
|
|
4013
4106
|
const queryTag = queryEndpoint.tags[0];
|
|
4014
|
-
|
|
4107
|
+
const querySegments = this.getResourceSegments(queryEndpoint.path);
|
|
4108
|
+
const queryResource = querySegments[0];
|
|
4109
|
+
if (mutationTag && queryTag === mutationTag) {
|
|
4015
4110
|
relatedQueries.push(queryEndpoint);
|
|
4111
|
+
seen.add(queryId);
|
|
4016
4112
|
return;
|
|
4017
4113
|
}
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
if (baseMatch) {
|
|
4022
|
-
relatedQueries.push(queryEndpoint);
|
|
4023
|
-
}
|
|
4114
|
+
if (mutationResource && queryResource && mutationResource === queryResource) {
|
|
4115
|
+
relatedQueries.push(queryEndpoint);
|
|
4116
|
+
seen.add(queryId);
|
|
4024
4117
|
}
|
|
4025
4118
|
});
|
|
4026
4119
|
return relatedQueries;
|
|
4027
4120
|
}
|
|
4121
|
+
getResourceSegments(path3) {
|
|
4122
|
+
return path3.split("/").filter(Boolean).filter((segment) => segment.toLowerCase() !== "api" && !/^v\d+/i.test(segment));
|
|
4123
|
+
}
|
|
4028
4124
|
/**
|
|
4029
4125
|
* Build invalidation code for related queries
|
|
4030
4126
|
*/
|
|
4031
4127
|
buildInvalidationCode(endpoint, relatedQueries, invalidationTags) {
|
|
4032
|
-
const invalidations =
|
|
4128
|
+
const invalidations = /* @__PURE__ */ new Set();
|
|
4033
4129
|
relatedQueries.forEach((queryEndpoint) => {
|
|
4034
|
-
const
|
|
4035
|
-
invalidations.
|
|
4130
|
+
const queryKeyPrefix = toActionName(queryEndpoint.operationId || queryEndpoint.id);
|
|
4131
|
+
invalidations.add(`queryClient.invalidateQueries({ queryKey: ['${queryKeyPrefix}'] })`);
|
|
4036
4132
|
});
|
|
4037
4133
|
invalidationTags.forEach((tag) => {
|
|
4038
|
-
|
|
4039
|
-
invalidations.push(` queryClient.invalidateQueries({ queryKey: ['${tag}'] })`);
|
|
4040
|
-
}
|
|
4134
|
+
invalidations.add(`queryClient.invalidateQueries({ queryKey: ['${tag}'] })`);
|
|
4041
4135
|
});
|
|
4042
|
-
if (invalidations.
|
|
4136
|
+
if (invalidations.size === 0) {
|
|
4043
4137
|
const inferredKey = this.inferQueryKeyFromPath(endpoint);
|
|
4044
4138
|
if (inferredKey) {
|
|
4045
|
-
invalidations.
|
|
4139
|
+
invalidations.add(`queryClient.invalidateQueries({ queryKey: ${inferredKey} })`);
|
|
4046
4140
|
}
|
|
4047
4141
|
}
|
|
4048
|
-
|
|
4142
|
+
if (invalidations.size === 0) {
|
|
4143
|
+
return " // No specific cache invalidation needed";
|
|
4144
|
+
}
|
|
4145
|
+
if (invalidations.size === 1) {
|
|
4146
|
+
const [statement] = Array.from(invalidations);
|
|
4147
|
+
return ` await ${statement}`;
|
|
4148
|
+
}
|
|
4149
|
+
return ` await Promise.all([
|
|
4150
|
+
${Array.from(invalidations).join(",\n ")}
|
|
4151
|
+
])`;
|
|
4049
4152
|
}
|
|
4050
4153
|
/**
|
|
4051
4154
|
* Build cancel queries code
|
|
4155
|
+
* Uses query key patterns to cancel all related queries regardless of parameters
|
|
4052
4156
|
*/
|
|
4053
4157
|
buildCancelQueriesCode(endpoint, relatedQueries) {
|
|
4054
|
-
const cancels =
|
|
4158
|
+
const cancels = /* @__PURE__ */ new Set();
|
|
4055
4159
|
relatedQueries.forEach((queryEndpoint) => {
|
|
4056
|
-
const
|
|
4057
|
-
cancels.
|
|
4058
|
-
});
|
|
4059
|
-
return cancels.length > 0 ? cancels.join("\n") : " // No queries to cancel";
|
|
4060
|
-
}
|
|
4061
|
-
/**
|
|
4062
|
-
* Build snapshot code for rollback
|
|
4063
|
-
*/
|
|
4064
|
-
buildSnapshotCode(endpoint, relatedQueries) {
|
|
4065
|
-
if (relatedQueries.length === 0) {
|
|
4066
|
-
return " // No queries to snapshot";
|
|
4067
|
-
}
|
|
4068
|
-
const snapshots = [];
|
|
4069
|
-
relatedQueries.forEach((queryEndpoint, index) => {
|
|
4070
|
-
const queryKey = this.generateQueryKey(queryEndpoint);
|
|
4071
|
-
const varName = `previous${this.toPascalCase(toActionName(queryEndpoint.operationId || queryEndpoint.id))}`;
|
|
4072
|
-
snapshots.push(` const ${varName} = queryClient.getQueryData(${queryKey})`);
|
|
4160
|
+
const queryKeyPrefix = toActionName(queryEndpoint.operationId || queryEndpoint.id);
|
|
4161
|
+
cancels.add(`queryClient.cancelQueries({ queryKey: ['${queryKeyPrefix}'] })`);
|
|
4073
4162
|
});
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
/**
|
|
4077
|
-
* Build rollback code
|
|
4078
|
-
*/
|
|
4079
|
-
buildRollbackCode(endpoint, relatedQueries) {
|
|
4080
|
-
if (relatedQueries.length === 0) {
|
|
4081
|
-
return " // No queries to rollback";
|
|
4163
|
+
if (cancels.size === 0) {
|
|
4164
|
+
return " // No queries to cancel";
|
|
4082
4165
|
}
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
const varName = `previous${this.toPascalCase(toActionName(queryEndpoint.operationId || queryEndpoint.id))}`;
|
|
4087
|
-
rollbacks.push(` if (context?.${varName}) {
|
|
4088
|
-
queryClient.setQueryData(${queryKey}, context.${varName})
|
|
4089
|
-
}`);
|
|
4090
|
-
});
|
|
4091
|
-
return rollbacks.join("\n");
|
|
4092
|
-
}
|
|
4093
|
-
/**
|
|
4094
|
-
* Get snapshot return names for context
|
|
4095
|
-
*/
|
|
4096
|
-
getSnapshotReturnNames(relatedQueries) {
|
|
4097
|
-
if (relatedQueries.length === 0) {
|
|
4098
|
-
return "previousData: null";
|
|
4166
|
+
if (cancels.size === 1) {
|
|
4167
|
+
const [statement] = Array.from(cancels);
|
|
4168
|
+
return ` await ${statement}`;
|
|
4099
4169
|
}
|
|
4100
|
-
return
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
}).join(", ");
|
|
4170
|
+
return ` await Promise.all([
|
|
4171
|
+
${Array.from(cancels).join(",\n ")}
|
|
4172
|
+
])`;
|
|
4104
4173
|
}
|
|
4105
4174
|
/**
|
|
4106
4175
|
* Infer query key from mutation path
|
|
@@ -4258,8 +4327,8 @@ export function useBridgeQuery<TData = unknown, TError = Error>(
|
|
|
4258
4327
|
refetchOnWindowFocus: true,
|
|
4259
4328
|
refetchOnReconnect: true,
|
|
4260
4329
|
refetchOnMount: 'always',
|
|
4261
|
-
placeholderData: (previousData) => previousData,
|
|
4262
|
-
retry: (failureCount, error) => {
|
|
4330
|
+
placeholderData: (previousData: TData | undefined) => previousData,
|
|
4331
|
+
retry: (failureCount: number, error: Error) => {
|
|
4263
4332
|
if (error instanceof Error && error.message.includes('4')) return false
|
|
4264
4333
|
return failureCount < 3
|
|
4265
4334
|
},
|
|
@@ -4284,13 +4353,13 @@ export function useBridgeInfiniteQuery<TData = unknown, TError = Error>(
|
|
|
4284
4353
|
refetchOnWindowFocus: true,
|
|
4285
4354
|
refetchOnReconnect: true,
|
|
4286
4355
|
refetchOnMount: 'always',
|
|
4287
|
-
placeholderData: (previousData) => previousData,
|
|
4288
|
-
retry: (failureCount, error) => {
|
|
4356
|
+
placeholderData: (previousData: TData | undefined) => previousData,
|
|
4357
|
+
retry: (failureCount: number, error: Error) => {
|
|
4289
4358
|
if (error instanceof Error && error.message.includes('4')) return false
|
|
4290
4359
|
return failureCount < 3
|
|
4291
4360
|
},
|
|
4292
4361
|
...options,
|
|
4293
|
-
}
|
|
4362
|
+
})
|
|
4294
4363
|
}
|
|
4295
4364
|
|
|
4296
4365
|
/**
|
|
@@ -4307,7 +4376,7 @@ export function useBridgeSuspenseQuery<TData = unknown, TError = Error>(
|
|
|
4307
4376
|
queryFn: queryFn as QueryFunction<TData, QueryKey>,
|
|
4308
4377
|
staleTime: 5 * 60 * 1000,
|
|
4309
4378
|
gcTime: 10 * 60 * 1000,
|
|
4310
|
-
retry: (failureCount, error) => {
|
|
4379
|
+
retry: (failureCount: number, error: Error) => {
|
|
4311
4380
|
if (error instanceof Error && error.message.includes('4')) return false
|
|
4312
4381
|
return failureCount < 3
|
|
4313
4382
|
},
|
|
@@ -7522,9 +7591,6 @@ var UploadGenerator = class {
|
|
|
7522
7591
|
const compressionFormats = uploads?.compression?.formats || ["gzip", "webp"];
|
|
7523
7592
|
const content = `'use client'
|
|
7524
7593
|
|
|
7525
|
-
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
|
7526
|
-
import { toast } from 'sonner'
|
|
7527
|
-
|
|
7528
7594
|
/**
|
|
7529
7595
|
* Upload configuration
|
|
7530
7596
|
*/
|
|
@@ -7704,7 +7770,7 @@ export function createUploadFormData(
|
|
|
7704
7770
|
"FileValidationResult",
|
|
7705
7771
|
"UploadProgress"
|
|
7706
7772
|
],
|
|
7707
|
-
imports: [
|
|
7773
|
+
imports: [],
|
|
7708
7774
|
dependencies: []
|
|
7709
7775
|
}
|
|
7710
7776
|
};
|
|
@@ -7810,16 +7876,18 @@ async function uploadToS3(
|
|
|
7810
7876
|
xhr.send(formData)
|
|
7811
7877
|
})
|
|
7812
7878
|
}
|
|
7813
|
-
|
|
7879
|
+
` : "";
|
|
7880
|
+
const needsBackendHelper = progressEnabled && useXHR || presignedEnabled && fallbackEnabled;
|
|
7881
|
+
const backendUploadHelper = needsBackendHelper ? `
|
|
7814
7882
|
/**
|
|
7815
7883
|
* Upload via backend API with progress tracking
|
|
7816
|
-
* Uses
|
|
7884
|
+
* Uses XMLHttpRequest for progress tracking support
|
|
7817
7885
|
*/
|
|
7818
7886
|
async function uploadViaBackendApi(
|
|
7819
7887
|
formData: FormData,
|
|
7820
7888
|
onProgress?: (progress: { loaded: number; total: number; percentage: number }) => void
|
|
7821
7889
|
): Promise<z.infer<typeof ${operationName}ResponseSchema>> {
|
|
7822
|
-
|
|
7890
|
+
return new Promise((resolve, reject) => {
|
|
7823
7891
|
const xhr = new XMLHttpRequest()
|
|
7824
7892
|
|
|
7825
7893
|
if (onProgress) {
|
|
@@ -7868,13 +7936,9 @@ async function uploadViaBackendApi(
|
|
|
7868
7936
|
: '${this.configuration.api?.baseUrl || "http://localhost:8000"}'
|
|
7869
7937
|
xhr.open('POST', \`\${baseUrl}${endpoint.path}\`)
|
|
7870
7938
|
xhr.send(formData)
|
|
7871
|
-
})
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
const response = await ${actionName}(formData as any)
|
|
7875
|
-
return response
|
|
7876
|
-
`}
|
|
7877
|
-
}` : "";
|
|
7939
|
+
})
|
|
7940
|
+
}
|
|
7941
|
+
` : "";
|
|
7878
7942
|
const uploadLogic = presignedEnabled ? `
|
|
7879
7943
|
let fileKey: string | null = null
|
|
7880
7944
|
let directUploadAttempted = false
|
|
@@ -7989,6 +8053,7 @@ async function uploadViaBackendApi(
|
|
|
7989
8053
|
`;
|
|
7990
8054
|
const content = `${imports}
|
|
7991
8055
|
${presignedHelpers}
|
|
8056
|
+
${backendUploadHelper || ""}
|
|
7992
8057
|
|
|
7993
8058
|
/**
|
|
7994
8059
|
* Upload hook for ${endpoint.method} ${endpoint.path}
|
|
@@ -8025,7 +8090,7 @@ export function ${hookName}Upload(options?: {
|
|
|
8025
8090
|
${uploadLogic}
|
|
8026
8091
|
},
|
|
8027
8092
|
|
|
8028
|
-
onSuccess: (data) => {
|
|
8093
|
+
onSuccess: (data: z.infer<typeof ${operationName}ResponseSchema>) => {
|
|
8029
8094
|
// Don't show toast here, let the page handle it
|
|
8030
8095
|
options?.onSuccess?.(data)
|
|
8031
8096
|
|
|
@@ -8239,7 +8304,9 @@ let toast: {
|
|
|
8239
8304
|
} | null = null
|
|
8240
8305
|
|
|
8241
8306
|
// Lazy load toast to avoid bundling issues
|
|
8242
|
-
async function getToast() {
|
|
8307
|
+
async function getToast(): Promise<{
|
|
8308
|
+
error: (message: string, options?: { duration?: number; description?: string }) => void
|
|
8309
|
+
} | null> {
|
|
8243
8310
|
if (toast !== null) return toast
|
|
8244
8311
|
|
|
8245
8312
|
try {
|
|
@@ -8333,24 +8400,26 @@ export async function handleAuthError(error: unknown, redirectTo?: string): Prom
|
|
|
8333
8400
|
const toastInstance = await getToast()
|
|
8334
8401
|
|
|
8335
8402
|
// Show appropriate error message based on error type
|
|
8336
|
-
if (
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
8403
|
+
if (toastInstance) {
|
|
8404
|
+
if (isInactive) {
|
|
8405
|
+
toastInstance.error('Your account has been deactivated. Please contact support for assistance.', {
|
|
8406
|
+
duration: 5000,
|
|
8407
|
+
description: 'You will be redirected to the login page.',
|
|
8408
|
+
})
|
|
8409
|
+
} else if (apiError.status === 401) {
|
|
8410
|
+
toastInstance.error('Your session has expired. Please sign in again.', {
|
|
8411
|
+
duration: 4000,
|
|
8412
|
+
})
|
|
8413
|
+
} else if (apiError.status === 403) {
|
|
8414
|
+
toastInstance.error('Access denied. Your account may have been suspended.', {
|
|
8415
|
+
duration: 5000,
|
|
8416
|
+
description: 'You will be redirected to the login page.',
|
|
8417
|
+
})
|
|
8418
|
+
} else {
|
|
8419
|
+
toastInstance.error('Authentication failed. Please sign in again.', {
|
|
8420
|
+
duration: 4000,
|
|
8421
|
+
})
|
|
8422
|
+
}
|
|
8354
8423
|
}
|
|
8355
8424
|
|
|
8356
8425
|
if (typeof window !== 'undefined') {
|
|
@@ -8361,7 +8430,7 @@ export async function handleAuthError(error: unknown, redirectTo?: string): Prom
|
|
|
8361
8430
|
const { signOut } = await import('${authPath}')
|
|
8362
8431
|
signOut({
|
|
8363
8432
|
redirect: false,
|
|
8364
|
-
}).catch((signOutError) => {
|
|
8433
|
+
}).catch((signOutError: unknown) => {
|
|
8365
8434
|
console.error('[Auth Error Handler] Error during sign out (non-blocking):', signOutError)
|
|
8366
8435
|
})
|
|
8367
8436
|
} catch (importError) {
|
|
@@ -9350,7 +9419,8 @@ var bridgeConfigSchema = z.object({
|
|
|
9350
9419
|
logging: z.boolean().default(true),
|
|
9351
9420
|
validation: z.boolean().default(true),
|
|
9352
9421
|
mocking: z.boolean().default(false),
|
|
9353
|
-
watch: z.boolean().default(false)
|
|
9422
|
+
watch: z.boolean().default(false),
|
|
9423
|
+
hotReload: z.boolean().default(false)
|
|
9354
9424
|
}).optional(),
|
|
9355
9425
|
plugins: z.array(
|
|
9356
9426
|
z.object({
|
|
@@ -9363,6 +9433,7 @@ var bridgeConfigSchema = z.object({
|
|
|
9363
9433
|
typescript: z.boolean().default(true),
|
|
9364
9434
|
strict: z.boolean().default(true),
|
|
9365
9435
|
comments: z.boolean().default(true),
|
|
9436
|
+
documentation: z.boolean().default(true),
|
|
9366
9437
|
examples: z.boolean().default(false),
|
|
9367
9438
|
tests: z.boolean().default(false)
|
|
9368
9439
|
}).optional()
|
|
@@ -9468,12 +9539,14 @@ ${errorMessages}`,
|
|
|
9468
9539
|
logging: true,
|
|
9469
9540
|
validation: true,
|
|
9470
9541
|
mocking: false,
|
|
9471
|
-
watch: false
|
|
9542
|
+
watch: false,
|
|
9543
|
+
hotReload: false
|
|
9472
9544
|
},
|
|
9473
9545
|
generation: {
|
|
9474
9546
|
typescript: true,
|
|
9475
9547
|
strict: true,
|
|
9476
9548
|
comments: true,
|
|
9549
|
+
documentation: true,
|
|
9477
9550
|
examples: false,
|
|
9478
9551
|
tests: false
|
|
9479
9552
|
}
|
|
@@ -9526,5 +9599,5 @@ ${errorMessages}`,
|
|
|
9526
9599
|
};
|
|
9527
9600
|
|
|
9528
9601
|
export { BridgeCore, BridgeError, BridgeLogger, ConfigurationLoader, FileSystemManager, GenerationError, LogLevel, NextJsCodeGenerator, OpenApiSchemaParser, SchemaParseError, ValidationError, VersionChecker, __name, checkAndNotifyUpdates, createBridgeVersionChecker };
|
|
9529
|
-
//# sourceMappingURL=chunk-
|
|
9530
|
-
//# sourceMappingURL=chunk-
|
|
9602
|
+
//# sourceMappingURL=chunk-7Y66DW7M.js.map
|
|
9603
|
+
//# sourceMappingURL=chunk-7Y66DW7M.js.map
|