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
|
@@ -1038,8 +1038,8 @@ import { cache } from 'react'
|
|
|
1038
1038
|
* We use dynamic imports to avoid bundling them in the client
|
|
1039
1039
|
*/
|
|
1040
1040
|
let serverOnlyModules: {
|
|
1041
|
-
cookies?: () => import('next/headers').
|
|
1042
|
-
headers?: () => import('next/headers').
|
|
1041
|
+
cookies?: () => Awaited<ReturnType<typeof import('next/headers').cookies>>
|
|
1042
|
+
headers?: () => Awaited<ReturnType<typeof import('next/headers').headers>>
|
|
1043
1043
|
after?: (fn: () => void | Promise<void>) => void
|
|
1044
1044
|
updateTag?: (tag: string) => void
|
|
1045
1045
|
} | null = null
|
|
@@ -1342,12 +1342,14 @@ export class BaseApiClient {
|
|
|
1342
1342
|
|
|
1343
1343
|
// Try external auth service
|
|
1344
1344
|
${this.configuration.auth?.enabled ? `try {
|
|
1345
|
-
const
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1345
|
+
const authModule = await import('${authPath}').catch(() => null)
|
|
1346
|
+
if (authModule && authModule.${tokenGetter}) {
|
|
1347
|
+
const session = await authModule.${tokenGetter}()
|
|
1348
|
+
|
|
1349
|
+
if (session?.accessToken) {
|
|
1350
|
+
getAuthHeaders.Authorization = \`Bearer \${session.accessToken}\`
|
|
1351
|
+
return getAuthHeaders
|
|
1352
|
+
}
|
|
1351
1353
|
}
|
|
1352
1354
|
} catch (error) {
|
|
1353
1355
|
// Auth not available or error accessing
|
|
@@ -1546,7 +1548,8 @@ export class BaseApiClient {
|
|
|
1546
1548
|
const requestPromise = this.executeRequestInternal<TData>(
|
|
1547
1549
|
method, url, body, headers, fetchOptions, timeout, retries,
|
|
1548
1550
|
retryDelay, retryCondition, validateResponse, skipAuth,
|
|
1549
|
-
responseSchema, requestId, [...this.middleware, ...middleware]
|
|
1551
|
+
responseSchema, requestId, [...this.middleware, ...middleware],
|
|
1552
|
+
cacheTags, revalidate, connection, updateTag
|
|
1550
1553
|
)
|
|
1551
1554
|
|
|
1552
1555
|
requestCache.set(dedupeKey, requestPromise)
|
|
@@ -1562,7 +1565,8 @@ export class BaseApiClient {
|
|
|
1562
1565
|
return this.executeRequestInternal<TData>(
|
|
1563
1566
|
method, url, body, headers, fetchOptions, timeout, retries,
|
|
1564
1567
|
retryDelay, retryCondition, validateResponse, skipAuth,
|
|
1565
|
-
responseSchema, requestId, [...this.middleware, ...middleware]
|
|
1568
|
+
responseSchema, requestId, [...this.middleware, ...middleware],
|
|
1569
|
+
cacheTags, revalidate, connection, updateTag
|
|
1566
1570
|
)
|
|
1567
1571
|
}
|
|
1568
1572
|
|
|
@@ -1581,7 +1585,11 @@ export class BaseApiClient {
|
|
|
1581
1585
|
skipAuth: boolean,
|
|
1582
1586
|
responseSchema?: z.ZodSchema<TData>,
|
|
1583
1587
|
requestId?: string,
|
|
1584
|
-
middleware: RequestMiddleware[] = []
|
|
1588
|
+
middleware: RequestMiddleware[] = [],
|
|
1589
|
+
cacheTags: string[] = [],
|
|
1590
|
+
revalidate?: number | false,
|
|
1591
|
+
connection?: 'keep-alive' | 'close',
|
|
1592
|
+
updateTag?: (tag: string) => void
|
|
1585
1593
|
): Promise<ClientResponse<TData>> {
|
|
1586
1594
|
const startTime = Date.now()
|
|
1587
1595
|
|
|
@@ -1668,7 +1676,7 @@ export class BaseApiClient {
|
|
|
1668
1676
|
|
|
1669
1677
|
if (tagUpdater && typeof window === 'undefined') {
|
|
1670
1678
|
// Update cache tags on server-side only
|
|
1671
|
-
cacheTags.forEach(tag => {
|
|
1679
|
+
cacheTags.forEach((tag: string) => {
|
|
1672
1680
|
try {
|
|
1673
1681
|
tagUpdater(tag)
|
|
1674
1682
|
} catch (error) {
|
|
@@ -2555,13 +2563,23 @@ var SchemaGenerator = class {
|
|
|
2555
2563
|
const result = [];
|
|
2556
2564
|
const schemaMap = /* @__PURE__ */ new Map();
|
|
2557
2565
|
const dependencyGraph = /* @__PURE__ */ new Map();
|
|
2566
|
+
const enumSchemas = [];
|
|
2567
|
+
const otherSchemas = [];
|
|
2558
2568
|
for (const schema of schemas) {
|
|
2569
|
+
const isEnum = this.isEnumSchema(schema);
|
|
2570
|
+
if (isEnum) {
|
|
2571
|
+
enumSchemas.push(schema);
|
|
2572
|
+
} else {
|
|
2573
|
+
otherSchemas.push(schema);
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
for (const schema of [...enumSchemas, ...otherSchemas]) {
|
|
2559
2577
|
if (!schemaMap.has(schema.name)) {
|
|
2560
2578
|
schemaMap.set(schema.name, schema);
|
|
2561
2579
|
dependencyGraph.set(schema.name, /* @__PURE__ */ new Set());
|
|
2562
2580
|
}
|
|
2563
2581
|
}
|
|
2564
|
-
for (const schema of
|
|
2582
|
+
for (const schema of [...enumSchemas, ...otherSchemas]) {
|
|
2565
2583
|
const dependencies = this.findSchemaDependencies(schema);
|
|
2566
2584
|
for (const dep of dependencies) {
|
|
2567
2585
|
if (schemaMap.has(dep)) {
|
|
@@ -2591,13 +2609,25 @@ var SchemaGenerator = class {
|
|
|
2591
2609
|
visiting.delete(schemaName);
|
|
2592
2610
|
visited.add(schemaName);
|
|
2593
2611
|
}, "visit");
|
|
2594
|
-
for (const schema of
|
|
2612
|
+
for (const schema of enumSchemas) {
|
|
2613
|
+
if (!visited.has(schema.name)) {
|
|
2614
|
+
visit(schema.name);
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
for (const schema of otherSchemas) {
|
|
2595
2618
|
if (!visited.has(schema.name)) {
|
|
2596
2619
|
visit(schema.name);
|
|
2597
2620
|
}
|
|
2598
2621
|
}
|
|
2599
2622
|
return result;
|
|
2600
2623
|
}
|
|
2624
|
+
isEnumSchema(schema) {
|
|
2625
|
+
if (!schema.schema || !schema.schema._def) {
|
|
2626
|
+
return false;
|
|
2627
|
+
}
|
|
2628
|
+
const def = schema.schema._def;
|
|
2629
|
+
return def.typeName === "ZodEnum";
|
|
2630
|
+
}
|
|
2601
2631
|
findSchemaDependencies(schema) {
|
|
2602
2632
|
const dependencies = [];
|
|
2603
2633
|
const schemaObj = schema.schema;
|
|
@@ -2679,7 +2709,7 @@ var SchemaGenerator = class {
|
|
|
2679
2709
|
schemaExports.push(...endpointSchemas.exports);
|
|
2680
2710
|
}
|
|
2681
2711
|
const validationHelpers = this.generateValidationHelpers();
|
|
2682
|
-
const
|
|
2712
|
+
const contentWithImports = [
|
|
2683
2713
|
...imports,
|
|
2684
2714
|
"",
|
|
2685
2715
|
"// Generated schemas from OpenAPI specification",
|
|
@@ -2689,7 +2719,13 @@ var SchemaGenerator = class {
|
|
|
2689
2719
|
"",
|
|
2690
2720
|
validationHelpers,
|
|
2691
2721
|
""
|
|
2692
|
-
].join("\n")
|
|
2722
|
+
].join("\n");
|
|
2723
|
+
let content = this.removeUnusedCode(contentWithImports);
|
|
2724
|
+
if (!content.includes('import { z } from "zod"') && !content.includes("import { z } from 'zod'")) {
|
|
2725
|
+
content = `import { z } from "zod"
|
|
2726
|
+
|
|
2727
|
+
${content}`;
|
|
2728
|
+
}
|
|
2693
2729
|
return {
|
|
2694
2730
|
path: "schemas/index.ts",
|
|
2695
2731
|
content,
|
|
@@ -3038,7 +3074,11 @@ export const errorMessages = {
|
|
|
3038
3074
|
const lines = content.split("\n");
|
|
3039
3075
|
const cleanedLines = [];
|
|
3040
3076
|
const usedIdentifiers = /* @__PURE__ */ new Set();
|
|
3077
|
+
usedIdentifiers.add("z");
|
|
3041
3078
|
for (const line of lines) {
|
|
3079
|
+
if (line.includes("z.")) {
|
|
3080
|
+
usedIdentifiers.add("z");
|
|
3081
|
+
}
|
|
3042
3082
|
const assignments = line.match(/(\w+)\s*[:=]/g);
|
|
3043
3083
|
if (assignments) {
|
|
3044
3084
|
assignments.forEach((match) => {
|
|
@@ -3053,6 +3093,9 @@ export const errorMessages = {
|
|
|
3053
3093
|
usedIdentifiers.add(identifier);
|
|
3054
3094
|
});
|
|
3055
3095
|
}
|
|
3096
|
+
if (line.includes("z.infer")) {
|
|
3097
|
+
usedIdentifiers.add("z");
|
|
3098
|
+
}
|
|
3056
3099
|
}
|
|
3057
3100
|
for (const line of lines) {
|
|
3058
3101
|
if (line.trim() === "" || line.trim().startsWith("//")) {
|
|
@@ -3060,6 +3103,10 @@ export const errorMessages = {
|
|
|
3060
3103
|
continue;
|
|
3061
3104
|
}
|
|
3062
3105
|
if (line.includes("import") && line.includes("from")) {
|
|
3106
|
+
if (line.includes('from "zod"') || line.includes("from 'zod'")) {
|
|
3107
|
+
cleanedLines.push(line);
|
|
3108
|
+
continue;
|
|
3109
|
+
}
|
|
3063
3110
|
const importMatch = line.match(/import\s*\{([^}]+)\}/);
|
|
3064
3111
|
if (importMatch) {
|
|
3065
3112
|
const imports = importMatch[1].split(",").map((imp) => imp.trim());
|
|
@@ -3088,6 +3135,166 @@ var ActionGenerator = class {
|
|
|
3088
3135
|
static {
|
|
3089
3136
|
__name(this, "ActionGenerator");
|
|
3090
3137
|
}
|
|
3138
|
+
get loggingEnabled() {
|
|
3139
|
+
return this.configuration.dev?.logging !== false;
|
|
3140
|
+
}
|
|
3141
|
+
get validationEnabled() {
|
|
3142
|
+
return this.configuration.dev?.validation !== false;
|
|
3143
|
+
}
|
|
3144
|
+
get commentsEnabled() {
|
|
3145
|
+
return this.configuration.generation?.comments !== false;
|
|
3146
|
+
}
|
|
3147
|
+
get documentationEnabled() {
|
|
3148
|
+
return this.configuration.generation?.documentation !== false;
|
|
3149
|
+
}
|
|
3150
|
+
commentLine(text, indent = 2) {
|
|
3151
|
+
if (!this.commentsEnabled) {
|
|
3152
|
+
return "";
|
|
3153
|
+
}
|
|
3154
|
+
return `${" ".repeat(indent)}// ${text}
|
|
3155
|
+
`;
|
|
3156
|
+
}
|
|
3157
|
+
buildDocBlock(endpoint, featuresDescription) {
|
|
3158
|
+
if (!this.documentationEnabled) {
|
|
3159
|
+
return "";
|
|
3160
|
+
}
|
|
3161
|
+
const summary = endpoint.summary || endpoint.description || `${endpoint.method} ${endpoint.path}`;
|
|
3162
|
+
return `/**
|
|
3163
|
+
* ${summary}
|
|
3164
|
+
* @generated from ${endpoint.method} ${endpoint.path}
|
|
3165
|
+
* Features: ${featuresDescription}
|
|
3166
|
+
*/
|
|
3167
|
+
`;
|
|
3168
|
+
}
|
|
3169
|
+
buildUtilityFunctions() {
|
|
3170
|
+
const parts = [];
|
|
3171
|
+
if (this.commentsEnabled) {
|
|
3172
|
+
parts.push("// Utility functions for enhanced server actions");
|
|
3173
|
+
}
|
|
3174
|
+
parts.push(`async function getClientInfo() {
|
|
3175
|
+
const headersList = await headers()
|
|
3176
|
+
const userAgent = headersList.get('user-agent') || 'unknown'
|
|
3177
|
+
const ip = headersList.get('x-forwarded-for') || headersList.get('x-real-ip') || 'unknown'
|
|
3178
|
+
|
|
3179
|
+
return { userAgent, ip }
|
|
3180
|
+
}`);
|
|
3181
|
+
if (this.validationEnabled) {
|
|
3182
|
+
parts.push(`async function validateAndSanitizeInput<T>(schema: z.ZodSchema<T>, input: unknown): Promise<T> {
|
|
3183
|
+
try {
|
|
3184
|
+
return await schema.parseAsync(input)
|
|
3185
|
+
} catch (error) {
|
|
3186
|
+
if (error instanceof z.ZodError) {
|
|
3187
|
+
const errorMessages = error.issues.map(issue => {
|
|
3188
|
+
const path = issue.path.length > 0 ? \`\${issue.path.join('.')}: \` : ''
|
|
3189
|
+
return \`\${path}\${issue.message}\`
|
|
3190
|
+
}).join(', ')
|
|
3191
|
+
throw new ActionError(\`Input validation failed: \${errorMessages}\`, 'VALIDATION_ERROR')
|
|
3192
|
+
}
|
|
3193
|
+
throw new ActionError('Invalid input format', 'VALIDATION_ERROR')
|
|
3194
|
+
}
|
|
3195
|
+
}`);
|
|
3196
|
+
}
|
|
3197
|
+
const actionErrorBlock = `${this.commentsEnabled ? "// Enhanced error handling with context\n" : ""}class ActionExecutionError extends ActionError {
|
|
3198
|
+
constructor(
|
|
3199
|
+
message: string,
|
|
3200
|
+
public readonly context: {
|
|
3201
|
+
endpoint: string
|
|
3202
|
+
method: string
|
|
3203
|
+
timestamp: number
|
|
3204
|
+
},
|
|
3205
|
+
public readonly originalError?: unknown
|
|
3206
|
+
) {
|
|
3207
|
+
super(message, 'EXECUTION_ERROR')
|
|
3208
|
+
}
|
|
3209
|
+
}`;
|
|
3210
|
+
parts.push(actionErrorBlock);
|
|
3211
|
+
if (this.loggingEnabled) {
|
|
3212
|
+
const loggingHeader = this.commentsEnabled ? "// Logging utility for server actions\n" : "";
|
|
3213
|
+
parts.push(`${loggingHeader}async function logActionExecution(
|
|
3214
|
+
action: string,
|
|
3215
|
+
success: boolean,
|
|
3216
|
+
duration: number,
|
|
3217
|
+
context?: Record<string, any>
|
|
3218
|
+
) {
|
|
3219
|
+
if (process.env.NODE_ENV === 'development') {
|
|
3220
|
+
console.log(\`[ACTION] \${action} - \${success ? 'SUCCESS' : 'FAILED'} (\${duration}ms)\`, context)
|
|
3221
|
+
}
|
|
3222
|
+
|
|
3223
|
+
${this.commentsEnabled ? " // In production, send to your logging service\n // await analytics.track('server_action_executed', { action, success, duration, ...context })" : ""}
|
|
3224
|
+
}`);
|
|
3225
|
+
}
|
|
3226
|
+
return parts.join("\n\n");
|
|
3227
|
+
}
|
|
3228
|
+
buildCombinedValidationSnippet(operationName, schemaName) {
|
|
3229
|
+
if (this.validationEnabled) {
|
|
3230
|
+
return `
|
|
3231
|
+
${this.commentLine("Validate and sanitize input payload", 6)} const { body, params } = await validateAndSanitizeInput(${schemaName}, parsedInput)
|
|
3232
|
+
const validatedBody = body
|
|
3233
|
+
const validatedParams = params as z.infer<typeof ${operationName}ParamsSchema>`;
|
|
3234
|
+
}
|
|
3235
|
+
return `
|
|
3236
|
+
${this.commentLine("Runtime validation disabled - trusting provided payload", 6)} const { body, params } = parsedInput as {
|
|
3237
|
+
body: z.infer<typeof ${operationName}RequestSchema>
|
|
3238
|
+
params: z.infer<typeof ${operationName}ParamsSchema>
|
|
3239
|
+
}
|
|
3240
|
+
const validatedBody = body
|
|
3241
|
+
const validatedParams = params`;
|
|
3242
|
+
}
|
|
3243
|
+
buildBodyValidationSnippet(schemaName) {
|
|
3244
|
+
if (schemaName === "z.void()") {
|
|
3245
|
+
return "";
|
|
3246
|
+
}
|
|
3247
|
+
if (this.validationEnabled) {
|
|
3248
|
+
return `
|
|
3249
|
+
${this.commentLine("Validate and sanitize request body", 6)} const validatedBody = await validateAndSanitizeInput(${schemaName}, parsedInput)`;
|
|
3250
|
+
}
|
|
3251
|
+
return `
|
|
3252
|
+
${this.commentLine("Runtime validation disabled - trusting request body", 6)} const validatedBody = parsedInput as z.infer<typeof ${schemaName}>`;
|
|
3253
|
+
}
|
|
3254
|
+
buildParamsValidationSnippet(operationName, schemaName) {
|
|
3255
|
+
if (schemaName === "z.void()") {
|
|
3256
|
+
return "";
|
|
3257
|
+
}
|
|
3258
|
+
if (this.validationEnabled) {
|
|
3259
|
+
return `
|
|
3260
|
+
${this.commentLine("Validate and sanitize parameters", 6)} const validatedParams = await validateAndSanitizeInput(${schemaName}, parsedInput) as z.infer<typeof ${operationName}ParamsSchema>`;
|
|
3261
|
+
}
|
|
3262
|
+
return `
|
|
3263
|
+
${this.commentLine("Runtime validation disabled - trusting parameters", 6)} const validatedParams = parsedInput as z.infer<typeof ${operationName}ParamsSchema>`;
|
|
3264
|
+
}
|
|
3265
|
+
buildSuccessLoggingBlock(actionName, endpoint, indent, isStreaming = false) {
|
|
3266
|
+
if (!this.loggingEnabled) {
|
|
3267
|
+
return "";
|
|
3268
|
+
}
|
|
3269
|
+
if (isStreaming) {
|
|
3270
|
+
return `
|
|
3271
|
+
${this.commentLine("Background tasks (Next.js 15 feature)", indent)}${" ".repeat(indent)}after(async () => {
|
|
3272
|
+
${this.commentLine("Perform background tasks after response is sent", indent + 2)}${" ".repeat(indent + 2)}await logActionExecution('${actionName}', true, Date.now() - startTime, {
|
|
3273
|
+
${" ".repeat(indent + 4)}method: '${endpoint.method}',
|
|
3274
|
+
${" ".repeat(indent + 4)}path: '${endpoint.path}'
|
|
3275
|
+
${" ".repeat(indent + 2)}})
|
|
3276
|
+
${" ".repeat(indent)}})`;
|
|
3277
|
+
}
|
|
3278
|
+
return `
|
|
3279
|
+
${this.commentLine("Log successful execution", indent)}${" ".repeat(indent)}const duration = Date.now() - startTime
|
|
3280
|
+
${" ".repeat(indent)}await logActionExecution('${actionName}', true, duration, {
|
|
3281
|
+
${" ".repeat(indent + 2)}method: '${endpoint.method}',
|
|
3282
|
+
${" ".repeat(indent + 2)}path: '${endpoint.path}'
|
|
3283
|
+
${" ".repeat(indent)}})`;
|
|
3284
|
+
}
|
|
3285
|
+
buildErrorLoggingBlock(actionName, endpoint, indent) {
|
|
3286
|
+
if (!this.loggingEnabled) {
|
|
3287
|
+
return "";
|
|
3288
|
+
}
|
|
3289
|
+
return `
|
|
3290
|
+
${" ".repeat(indent)}const duration = Date.now() - startTime
|
|
3291
|
+
|
|
3292
|
+
${this.commentLine("Enhanced error logging", indent)}${" ".repeat(indent)}await logActionExecution('${actionName}', false, duration, {
|
|
3293
|
+
${" ".repeat(indent + 2)}method: '${endpoint.method}',
|
|
3294
|
+
${" ".repeat(indent + 2)}path: '${endpoint.path}',
|
|
3295
|
+
${" ".repeat(indent + 2)}error: error instanceof Error ? error.message : 'Unknown error'
|
|
3296
|
+
${" ".repeat(indent)}})`;
|
|
3297
|
+
}
|
|
3091
3298
|
buildImportPath(relativePath) {
|
|
3092
3299
|
const outputDirectory = this.configuration.outputDir || "generated";
|
|
3093
3300
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
@@ -3140,7 +3347,7 @@ var ActionGenerator = class {
|
|
|
3140
3347
|
...hasStreaming ? ["import { after } from 'next/server'"] : [],
|
|
3141
3348
|
"import { headers } from 'next/headers'",
|
|
3142
3349
|
`import { apiClient } from '${clientImport}'`,
|
|
3143
|
-
`import { ${usesAuth || hasRateLimit ? "authActionClient" : "
|
|
3350
|
+
`import { actionClientWithMeta${usesAuth || hasRateLimit ? ", authActionClient" : ""}, ActionError } from '${safeActionImport}'`,
|
|
3144
3351
|
...schemaImportsString ? [`import {
|
|
3145
3352
|
${schemaImportsString}
|
|
3146
3353
|
} from '${schemasImport}'`] : [],
|
|
@@ -3152,8 +3359,7 @@ var ActionGenerator = class {
|
|
|
3152
3359
|
] : []
|
|
3153
3360
|
].filter(Boolean).join("\n");
|
|
3154
3361
|
const rateLimitSetup = hasRateLimit ? `
|
|
3155
|
-
// Rate limiting setup
|
|
3156
|
-
const redis = new Redis({
|
|
3362
|
+
${this.commentsEnabled ? "// Rate limiting setup\n" : ""}const redis = new Redis({
|
|
3157
3363
|
url: process.env.UPSTASH_REDIS_REST_URL!,
|
|
3158
3364
|
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
|
|
3159
3365
|
})
|
|
@@ -3163,60 +3369,7 @@ const ratelimit = new Ratelimit({
|
|
|
3163
3369
|
limiter: Ratelimit.slidingWindow(10, '1 m'),
|
|
3164
3370
|
analytics: true,
|
|
3165
3371
|
})` : "";
|
|
3166
|
-
const utilityFunctions =
|
|
3167
|
-
// Utility functions for enhanced server actions
|
|
3168
|
-
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
|
-
|
|
3176
|
-
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
|
-
// Enhanced error handling with context
|
|
3192
|
-
class ActionExecutionError extends ActionError {
|
|
3193
|
-
constructor(
|
|
3194
|
-
message: string,
|
|
3195
|
-
public readonly context: {
|
|
3196
|
-
endpoint: string
|
|
3197
|
-
method: string
|
|
3198
|
-
timestamp: number
|
|
3199
|
-
},
|
|
3200
|
-
public readonly originalError?: unknown
|
|
3201
|
-
) {
|
|
3202
|
-
super(message, 'EXECUTION_ERROR')
|
|
3203
|
-
}
|
|
3204
|
-
}
|
|
3205
|
-
|
|
3206
|
-
// Logging utility for server actions
|
|
3207
|
-
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
|
-
// In production, send to your logging service
|
|
3218
|
-
// await analytics.track('server_action_executed', { action, success, duration, ...context })
|
|
3219
|
-
}`;
|
|
3372
|
+
const utilityFunctions = this.buildUtilityFunctions();
|
|
3220
3373
|
const content = `${imports}
|
|
3221
3374
|
${rateLimitSetup}
|
|
3222
3375
|
${utilityFunctions}
|
|
@@ -3233,8 +3386,8 @@ ${actions}`;
|
|
|
3233
3386
|
}
|
|
3234
3387
|
});
|
|
3235
3388
|
}
|
|
3236
|
-
const
|
|
3237
|
-
${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier(tag)}'`).join("\n")}`;
|
|
3389
|
+
const indexHeader = this.commentsEnabled ? "// Auto-generated actions index\n" : "";
|
|
3390
|
+
const indexContent = `${indexHeader}${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier(tag)}'`).join("\n")}`;
|
|
3238
3391
|
generatedFiles.push({
|
|
3239
3392
|
path: "actions/index.ts",
|
|
3240
3393
|
content: indexContent,
|
|
@@ -3283,54 +3436,48 @@ ${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier
|
|
|
3283
3436
|
body: ${operationName}RequestSchema,
|
|
3284
3437
|
params: ${operationName}ParamsSchema
|
|
3285
3438
|
})`;
|
|
3286
|
-
parameterProcessing =
|
|
3287
|
-
// Validate and sanitize input
|
|
3288
|
-
const { body, params } = await validateAndSanitizeInput(${schemaName}, parsedInput)
|
|
3289
|
-
const validatedBody = body
|
|
3290
|
-
const validatedParams = params as any`;
|
|
3439
|
+
parameterProcessing = this.buildCombinedValidationSnippet(operationName, schemaName);
|
|
3291
3440
|
requestOptionsParams = this.buildRequestOptions(pathParameters, queryParameters, true, true);
|
|
3292
3441
|
} else if (hasRequestBody) {
|
|
3293
3442
|
schemaName = `${operationName}RequestSchema`;
|
|
3294
|
-
parameterProcessing =
|
|
3295
|
-
// Validate and sanitize request body
|
|
3296
|
-
const validatedBody = await validateAndSanitizeInput(${schemaName}, parsedInput)`;
|
|
3443
|
+
parameterProcessing = this.buildBodyValidationSnippet(schemaName);
|
|
3297
3444
|
requestOptionsParams = `body: validatedBody`;
|
|
3298
3445
|
} else if (hasAnyParams) {
|
|
3299
3446
|
schemaName = `${operationName}ParamsSchema`;
|
|
3300
|
-
parameterProcessing =
|
|
3301
|
-
// Validate and sanitize parameters
|
|
3302
|
-
const validatedParams = await validateAndSanitizeInput(${schemaName}, parsedInput) as any`;
|
|
3447
|
+
parameterProcessing = this.buildParamsValidationSnippet(operationName, schemaName);
|
|
3303
3448
|
requestOptionsParams = this.buildRequestOptions(pathParameters, queryParameters, false, true);
|
|
3304
3449
|
} else {
|
|
3305
3450
|
schemaName = "z.void()";
|
|
3306
3451
|
parameterProcessing = "";
|
|
3307
3452
|
requestOptionsParams = "";
|
|
3308
3453
|
}
|
|
3454
|
+
const parsedInputType = hasRequestBody || hasAnyParams ? `z.infer<typeof ${schemaName}>` : "void";
|
|
3455
|
+
const ctxType = requiresAuth || hasRateLimit ? "{ user?: any; ratelimit?: { remaining: number } }" : "any";
|
|
3456
|
+
const ctxDeclaration = requiresAuth || hasRateLimit ? `ctx: ${ctxType}` : "ctx?: any";
|
|
3457
|
+
const actionArgsType = `{ parsedInput: ${parsedInputType}; ${ctxDeclaration} }`;
|
|
3309
3458
|
const clientName = requiresAuth || hasRateLimit ? "authActionClient" : "actionClientWithMeta";
|
|
3310
3459
|
const rateLimitCode = hasRateLimit ? `
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
}` : "";
|
|
3460
|
+
${this.commentLine("Rate limiting", 6)} const { userAgent, ip } = await getClientInfo()
|
|
3461
|
+
const identifier = \`\${ip}-\${userAgent}\`
|
|
3462
|
+
const { success, limit, reset, remaining } = await ratelimit.limit(identifier)
|
|
3463
|
+
|
|
3464
|
+
if (!success) {
|
|
3465
|
+
throw new ActionError(
|
|
3466
|
+
\`Rate limit exceeded. Try again in \${Math.round((reset - Date.now()) / 1000)} seconds.\`,
|
|
3467
|
+
'RATE_LIMIT_EXCEEDED'
|
|
3468
|
+
)
|
|
3469
|
+
}` : "";
|
|
3322
3470
|
const revalidationCode = revalidationTags.length > 0 ? revalidationTags.map(
|
|
3323
|
-
(tag) => ` updateTag('${tag}')
|
|
3324
|
-
console.log('Updated tag: ${tag}')`
|
|
3471
|
+
(tag) => ` updateTag('${tag}')${this.loggingEnabled ? `
|
|
3472
|
+
console.log('Updated tag: ${tag}')` : ""}`
|
|
3325
3473
|
).join("\n") : "";
|
|
3326
3474
|
const kebabActionName = actionName.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
|
|
3327
3475
|
if (isQuery) {
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
export const ${actionName} = cache(
|
|
3476
|
+
const docBlock = this.buildDocBlock(
|
|
3477
|
+
endpoint,
|
|
3478
|
+
"React cache, input validation, error handling"
|
|
3479
|
+
);
|
|
3480
|
+
return `${docBlock}export const ${actionName} = cache(
|
|
3334
3481
|
${clientName}
|
|
3335
3482
|
.metadata({
|
|
3336
3483
|
name: "${kebabActionName}",
|
|
@@ -3338,7 +3485,7 @@ export const ${actionName} = cache(
|
|
|
3338
3485
|
rateLimit: { requests: ${endpoint.metadata.rateLimit?.requests || 10}, window: "${endpoint.metadata.rateLimit?.window || "1m"}" }` : ""}
|
|
3339
3486
|
})
|
|
3340
3487
|
.schema(${schemaName})
|
|
3341
|
-
.action(async ({ parsedInput, ctx }) => {
|
|
3488
|
+
.action(async ({ parsedInput, ctx }: ${actionArgsType}) => {
|
|
3342
3489
|
const startTime = Date.now()
|
|
3343
3490
|
|
|
3344
3491
|
try {${rateLimitCode}${parameterProcessing}
|
|
@@ -3353,23 +3500,11 @@ export const ${actionName} = cache(
|
|
|
3353
3500
|
}
|
|
3354
3501
|
})
|
|
3355
3502
|
|
|
3356
|
-
|
|
3357
|
-
const duration = Date.now() - startTime
|
|
3358
|
-
await logActionExecution('${actionName}', true, duration, {
|
|
3359
|
-
method: '${endpoint.method}',
|
|
3360
|
-
path: '${endpoint.path}'
|
|
3361
|
-
})
|
|
3503
|
+
${this.buildSuccessLoggingBlock(actionName, endpoint, 8)}
|
|
3362
3504
|
|
|
3363
3505
|
return response.data
|
|
3364
3506
|
} catch (error) {
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
// Enhanced error logging
|
|
3368
|
-
await logActionExecution('${actionName}', false, duration, {
|
|
3369
|
-
method: '${endpoint.method}',
|
|
3370
|
-
path: '${endpoint.path}',
|
|
3371
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
3372
|
-
})
|
|
3507
|
+
${this.buildErrorLoggingBlock(actionName, endpoint, 8)}
|
|
3373
3508
|
|
|
3374
3509
|
// Throw enhanced error with context
|
|
3375
3510
|
throw new ActionExecutionError(
|
|
@@ -3386,50 +3521,37 @@ export const ${actionName} = cache(
|
|
|
3386
3521
|
)`;
|
|
3387
3522
|
}
|
|
3388
3523
|
const redirectCode = `
|
|
3389
|
-
|
|
3390
|
-
if (response.status === 201 && response.headers.get('location')) {
|
|
3524
|
+
${this.commentLine("Handle potential redirects based on response", 8)} if (response.status === 201 && response.headers.get('location')) {
|
|
3391
3525
|
const location = response.headers.get('location')!
|
|
3392
3526
|
redirect(location)
|
|
3393
3527
|
}`;
|
|
3394
3528
|
const streamingCode = `
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
// Process streaming response
|
|
3398
|
-
return response.data
|
|
3529
|
+
${this.commentLine("Handle streaming responses", 8)} if (response.headers.get('content-type')?.includes('text/stream')) {
|
|
3530
|
+
${this.commentLine("Process streaming response", 10)} return response.data
|
|
3399
3531
|
}`;
|
|
3400
3532
|
const fileUploadCode = hasFileUpload ? uploadStrategy === "external" && uploadProvider === "vercel-blob" ? `
|
|
3401
|
-
|
|
3402
|
-
if (validatedBody && typeof validatedBody === 'object' && 'file' in validatedBody) {
|
|
3533
|
+
${this.commentLine("Handle file uploads with Vercel Blob", 8)} if (validatedBody && typeof validatedBody === 'object' && 'file' in validatedBody) {
|
|
3403
3534
|
const file = (validatedBody as any).file as File
|
|
3404
3535
|
const blob = await put(file.name, file, { access: 'public' })
|
|
3405
3536
|
Object.assign(validatedBody, { fileUrl: blob.url })
|
|
3406
3537
|
}` : uploadStrategy === "external" && uploadProvider === "uploadthing" ? `
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
const file = (validatedBody as any).file as File
|
|
3418
|
-
// Process file with compression and validation if enabled
|
|
3419
|
-
}` : "";
|
|
3420
|
-
return `/**
|
|
3421
|
-
* ${endpoint.summary || endpoint.description || `${endpoint.method} ${endpoint.path}`}
|
|
3422
|
-
* @generated from ${endpoint.method} ${endpoint.path}
|
|
3423
|
-
* Features: Input validation, revalidation, error handling
|
|
3424
|
-
*/
|
|
3425
|
-
export const ${actionName} = ${clientName}
|
|
3538
|
+
${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) {
|
|
3539
|
+
${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)} }` : `
|
|
3540
|
+
${this.commentLine("Handle file uploads with standard FormData", 8)} if (validatedBody && typeof validatedBody === 'object' && 'file' in validatedBody) {
|
|
3541
|
+
${this.commentLine("Standard file upload handling", 10)} const file = (validatedBody as any).file as File
|
|
3542
|
+
${this.commentLine("Process file with compression and validation if enabled", 10)} }` : "";
|
|
3543
|
+
const mutationDocBlock = this.buildDocBlock(
|
|
3544
|
+
endpoint,
|
|
3545
|
+
"Input validation, revalidation, error handling"
|
|
3546
|
+
);
|
|
3547
|
+
return `${mutationDocBlock}export const ${actionName} = ${clientName}
|
|
3426
3548
|
.metadata({
|
|
3427
3549
|
name: "${kebabActionName}",
|
|
3428
3550
|
requiresAuth: ${requiresAuth}${hasRateLimit ? `,
|
|
3429
3551
|
rateLimit: { requests: ${endpoint.metadata.rateLimit?.requests || 10}, window: "${endpoint.metadata.rateLimit?.window || "1m"}" }` : ""}
|
|
3430
3552
|
})
|
|
3431
3553
|
.schema(${schemaName})
|
|
3432
|
-
.action(async ({ parsedInput, ctx }) => {
|
|
3554
|
+
.action(async ({ parsedInput, ctx }: ${actionArgsType}) => {
|
|
3433
3555
|
const startTime = Date.now()
|
|
3434
3556
|
|
|
3435
3557
|
try {${rateLimitCode}${parameterProcessing}${fileUploadCode}
|
|
@@ -3444,33 +3566,13 @@ export const ${actionName} = ${clientName}
|
|
|
3444
3566
|
}
|
|
3445
3567
|
})${streamingCode}${redirectCode}
|
|
3446
3568
|
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
// Background tasks (Next.js 15 feature)
|
|
3451
|
-
${isStreaming ? `after(async () => {
|
|
3452
|
-
// Perform background tasks after response is sent
|
|
3453
|
-
await logActionExecution('${actionName}', true, Date.now() - startTime, {
|
|
3454
|
-
method: '${endpoint.method}',
|
|
3455
|
-
path: '${endpoint.path}'
|
|
3456
|
-
})
|
|
3457
|
-
})` : `// Log successful execution
|
|
3458
|
-
const duration = Date.now() - startTime
|
|
3459
|
-
await logActionExecution('${actionName}', true, duration, {
|
|
3460
|
-
method: '${endpoint.method}',
|
|
3461
|
-
path: '${endpoint.path}'
|
|
3462
|
-
})`}
|
|
3569
|
+
${revalidationCode ? `${this.commentLine("Revalidate cache after successful mutation", 6)}${revalidationCode}
|
|
3570
|
+
` : ""}
|
|
3571
|
+
${this.buildSuccessLoggingBlock(actionName, endpoint, 6, isStreaming)}
|
|
3463
3572
|
|
|
3464
3573
|
return response.data
|
|
3465
3574
|
} catch (error) {
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
// Enhanced error logging
|
|
3469
|
-
await logActionExecution('${actionName}', false, duration, {
|
|
3470
|
-
method: '${endpoint.method}',
|
|
3471
|
-
path: '${endpoint.path}',
|
|
3472
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
3473
|
-
})
|
|
3575
|
+
${this.buildErrorLoggingBlock(actionName, endpoint, 6)}
|
|
3474
3576
|
|
|
3475
3577
|
// Throw enhanced error with context
|
|
3476
3578
|
throw new ActionExecutionError(
|
|
@@ -3629,7 +3731,6 @@ var HookGenerator = class {
|
|
|
3629
3731
|
if (hasInfiniteQueries) reactQueryImports.push("useInfiniteQuery");
|
|
3630
3732
|
const reactImports = [];
|
|
3631
3733
|
if (hasMutations) reactImports.push("useOptimistic", "useTransition");
|
|
3632
|
-
if (hasQueries) reactImports.push("useCallback");
|
|
3633
3734
|
const imports = [
|
|
3634
3735
|
"'use client'",
|
|
3635
3736
|
"",
|
|
@@ -3741,19 +3842,19 @@ ${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier
|
|
|
3741
3842
|
* @returns useQuery result with data of type ${returnType}
|
|
3742
3843
|
*/
|
|
3743
3844
|
export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join(", ")}, ` : ""}options?: ${optionsType}) {
|
|
3744
|
-
const [searchParams
|
|
3845
|
+
const [searchParams] = useQueryStates(searchParamsParser)
|
|
3745
3846
|
const { initialData, ...restOptions } = options ?? {}
|
|
3746
3847
|
|
|
3747
3848
|
return useQuery({
|
|
3748
3849
|
queryKey: [...${queryKey}, searchParams],
|
|
3749
|
-
queryFn:
|
|
3850
|
+
queryFn: async ({ signal }: { signal?: AbortSignal }) => {
|
|
3750
3851
|
try {
|
|
3751
3852
|
const result = await ${actionName}(${actionCallParams.replace(queryParamObject, "{ ...searchParams }")})
|
|
3752
3853
|
return result
|
|
3753
3854
|
} catch (error) {
|
|
3754
3855
|
handleActionError(error)
|
|
3755
3856
|
}
|
|
3756
|
-
},
|
|
3857
|
+
},
|
|
3757
3858
|
staleTime: ${staleTime},
|
|
3758
3859
|
gcTime: ${staleTime * 2}, // React Query v5: gcTime replaces cacheTime
|
|
3759
3860
|
enabled: ${enabledCondition} && (options?.enabled ?? true),
|
|
@@ -3763,14 +3864,14 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3763
3864
|
refetchInterval: options?.refetchInterval, // Optional polling interval
|
|
3764
3865
|
initialDataUpdatedAt: initialData ? Date.now() : undefined,
|
|
3765
3866
|
// React Query v5: placeholderData replaces keepPreviousData
|
|
3766
|
-
placeholderData: (previousData) => previousData,
|
|
3767
|
-
retry: (failureCount, error) => {
|
|
3867
|
+
placeholderData: (previousData: ${returnType} | undefined) => previousData,
|
|
3868
|
+
retry: (failureCount: number, error: Error) => {
|
|
3768
3869
|
// Don't retry on 4xx errors (client errors)
|
|
3769
3870
|
if (error instanceof Error && error.message.includes('4')) return false
|
|
3770
3871
|
// Retry up to 3 times for network/server errors
|
|
3771
3872
|
return failureCount < 3
|
|
3772
3873
|
},
|
|
3773
|
-
initialData: initialData as
|
|
3874
|
+
initialData: initialData as ${returnType} | undefined,
|
|
3774
3875
|
...restOptions
|
|
3775
3876
|
})
|
|
3776
3877
|
}
|
|
@@ -3785,15 +3886,15 @@ export function ${hookName.replace("use", "useInfinite")}(${parameterTypes.lengt
|
|
|
3785
3886
|
|
|
3786
3887
|
return useInfiniteQuery({
|
|
3787
3888
|
queryKey: [...${queryKey}, 'infinite', searchParams],
|
|
3788
|
-
queryFn:
|
|
3889
|
+
queryFn: async ({ pageParam = 1, signal }: { pageParam?: number; signal?: AbortSignal }) => {
|
|
3789
3890
|
try {
|
|
3790
3891
|
const result = await ${actionName}(${actionCallParams.replace(queryParamObject, "{ ...searchParams, page: pageParam, limit: searchParams.limit }")})
|
|
3791
3892
|
return result
|
|
3792
3893
|
} catch (error) {
|
|
3793
3894
|
handleActionError(error)
|
|
3794
3895
|
}
|
|
3795
|
-
},
|
|
3796
|
-
getNextPageParam: (lastPage:
|
|
3896
|
+
},
|
|
3897
|
+
getNextPageParam: (lastPage: ${returnType}, allPages: ${returnType}[]) => {
|
|
3797
3898
|
if (lastPage?.hasMore || (Array.isArray(lastPage) && lastPage.length === searchParams.limit)) {
|
|
3798
3899
|
return allPages.length + 1
|
|
3799
3900
|
}
|
|
@@ -3806,9 +3907,9 @@ export function ${hookName.replace("use", "useInfinite")}(${parameterTypes.lengt
|
|
|
3806
3907
|
refetchOnReconnect: true,
|
|
3807
3908
|
refetchOnMount: 'always',
|
|
3808
3909
|
initialDataUpdatedAt: initialData ? Date.now() : undefined,
|
|
3809
|
-
placeholderData: (previousData) => previousData,
|
|
3910
|
+
placeholderData: (previousData: ${returnType} | undefined) => previousData,
|
|
3810
3911
|
retry: 3,
|
|
3811
|
-
initialData: initialData as
|
|
3912
|
+
initialData: initialData as ${returnType} | undefined,
|
|
3812
3913
|
...restOptions
|
|
3813
3914
|
})
|
|
3814
3915
|
}
|
|
@@ -3822,12 +3923,12 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3822
3923
|
|
|
3823
3924
|
return useSuspenseQuery({
|
|
3824
3925
|
queryKey: ${queryKey},
|
|
3825
|
-
queryFn:
|
|
3926
|
+
queryFn: async () => {
|
|
3826
3927
|
const result = await ${actionName}(${actionCallParams})
|
|
3827
3928
|
return result
|
|
3828
|
-
},
|
|
3929
|
+
},
|
|
3829
3930
|
staleTime: ${staleTime},
|
|
3830
|
-
initialData: initialData as
|
|
3931
|
+
initialData: initialData as ${returnType} | undefined,
|
|
3831
3932
|
...restOptions
|
|
3832
3933
|
})
|
|
3833
3934
|
}`;
|
|
@@ -3842,14 +3943,14 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3842
3943
|
|
|
3843
3944
|
return useQuery({
|
|
3844
3945
|
queryKey: ${queryKey},
|
|
3845
|
-
queryFn:
|
|
3946
|
+
queryFn: async ({ signal }: { signal?: AbortSignal }) => {
|
|
3846
3947
|
try {
|
|
3847
3948
|
const result = await ${actionName}(${actionCallParams})
|
|
3848
3949
|
return result
|
|
3849
3950
|
} catch (error) {
|
|
3850
3951
|
handleActionError(error)
|
|
3851
3952
|
}
|
|
3852
|
-
},
|
|
3953
|
+
},
|
|
3853
3954
|
staleTime: ${staleTime},
|
|
3854
3955
|
gcTime: ${staleTime * 2}, // React Query v5: gcTime replaces cacheTime
|
|
3855
3956
|
enabled: ${enabledCondition} && (options?.enabled ?? true),
|
|
@@ -3859,14 +3960,14 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3859
3960
|
refetchInterval: options?.refetchInterval, // Optional polling interval
|
|
3860
3961
|
initialDataUpdatedAt: initialData ? Date.now() : undefined,
|
|
3861
3962
|
// React Query v5: placeholderData replaces keepPreviousData
|
|
3862
|
-
placeholderData: (previousData) => previousData,
|
|
3863
|
-
retry: (failureCount, error) => {
|
|
3963
|
+
placeholderData: (previousData: ${returnType} | undefined) => previousData,
|
|
3964
|
+
retry: (failureCount: number, error: Error) => {
|
|
3864
3965
|
// Don't retry on 4xx errors (client errors)
|
|
3865
3966
|
if (error instanceof Error && error.message.includes('4')) return false
|
|
3866
3967
|
// Retry up to 3 times for network/server errors
|
|
3867
3968
|
return failureCount < 3
|
|
3868
3969
|
},
|
|
3869
|
-
initialData: initialData as
|
|
3970
|
+
initialData: initialData as ${returnType} | undefined,
|
|
3870
3971
|
...restOptions
|
|
3871
3972
|
})
|
|
3872
3973
|
}
|
|
@@ -3880,12 +3981,12 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3880
3981
|
|
|
3881
3982
|
return useSuspenseQuery({
|
|
3882
3983
|
queryKey: ${queryKey},
|
|
3883
|
-
queryFn:
|
|
3984
|
+
queryFn: async () => {
|
|
3884
3985
|
const result = await ${actionName}(${actionCallParams})
|
|
3885
3986
|
return result
|
|
3886
|
-
},
|
|
3987
|
+
},
|
|
3887
3988
|
staleTime: ${staleTime},
|
|
3888
|
-
initialData: initialData as
|
|
3989
|
+
initialData: initialData as ${returnType} | undefined,
|
|
3889
3990
|
...restOptions
|
|
3890
3991
|
})
|
|
3891
3992
|
}`;
|
|
@@ -3916,8 +4017,6 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3916
4017
|
const relatedQueries = this.findRelatedQueries(endpoint, context);
|
|
3917
4018
|
const invalidationCode = this.buildInvalidationCode(endpoint, relatedQueries, invalidationTags);
|
|
3918
4019
|
const cancelQueriesCode = this.buildCancelQueriesCode(endpoint, relatedQueries);
|
|
3919
|
-
const snapshotCode = this.buildSnapshotCode(endpoint, relatedQueries);
|
|
3920
|
-
const rollbackCode = this.buildRollbackCode(endpoint, relatedQueries);
|
|
3921
4020
|
return `/**
|
|
3922
4021
|
* Optimized mutation hook for ${endpoint.method} ${endpoint.path}
|
|
3923
4022
|
* Features: Optimistic updates, smart invalidation, error handling
|
|
@@ -3938,24 +4037,22 @@ export function ${hookName}(options?: {
|
|
|
3938
4037
|
mutationFn: async (variables: ${inputType}): Promise<${outputType}> => {
|
|
3939
4038
|
try {
|
|
3940
4039
|
const result = await ${actionName}(${variablesParam === "undefined" ? "" : "variables"})
|
|
3941
|
-
return result
|
|
4040
|
+
return (result ?? ({} as ${outputType}))
|
|
3942
4041
|
} catch (error) {
|
|
3943
4042
|
handleActionError(error)
|
|
3944
4043
|
}
|
|
3945
4044
|
},
|
|
3946
4045
|
|
|
3947
|
-
onMutate: async (variables) => {
|
|
4046
|
+
onMutate: async (variables: ${inputType}) => {
|
|
3948
4047
|
${cancelQueriesCode}
|
|
3949
|
-
|
|
3950
|
-
${snapshotCode}
|
|
3951
|
-
|
|
4048
|
+
|
|
3952
4049
|
// Optimistic update (if provided)
|
|
3953
4050
|
if (options?.optimisticUpdate) {
|
|
3954
4051
|
const optimisticValue = options.optimisticUpdate(variables)
|
|
3955
4052
|
setOptimisticData(optimisticValue)
|
|
3956
4053
|
}
|
|
3957
4054
|
|
|
3958
|
-
return {
|
|
4055
|
+
return {}
|
|
3959
4056
|
},
|
|
3960
4057
|
|
|
3961
4058
|
onSuccess: (data, variables) => {
|
|
@@ -3964,17 +4061,11 @@ ${snapshotCode}
|
|
|
3964
4061
|
toast.success('${this.getSuccessMessage(endpoint)}')
|
|
3965
4062
|
}
|
|
3966
4063
|
|
|
3967
|
-
// Invalidate and refetch related queries
|
|
3968
|
-
${invalidationCode}
|
|
3969
|
-
|
|
3970
4064
|
// Custom success handler
|
|
3971
4065
|
options?.onSuccess?.(data, variables)
|
|
3972
4066
|
},
|
|
3973
4067
|
|
|
3974
|
-
onError: (error, variables
|
|
3975
|
-
// Rollback optimistic update
|
|
3976
|
-
${rollbackCode}
|
|
3977
|
-
|
|
4068
|
+
onError: (error: Error, variables: ${inputType}) => {
|
|
3978
4069
|
// Show error toast
|
|
3979
4070
|
if (options?.showToast !== false) {
|
|
3980
4071
|
toast.error(error.message || '${this.getErrorMessage(endpoint)}')
|
|
@@ -3984,7 +4075,7 @@ ${rollbackCode}
|
|
|
3984
4075
|
options?.onError?.(error as Error, variables)
|
|
3985
4076
|
},
|
|
3986
4077
|
|
|
3987
|
-
onSettled: () => {
|
|
4078
|
+
onSettled: async () => {
|
|
3988
4079
|
// Always refetch after error or success
|
|
3989
4080
|
${invalidationCode}
|
|
3990
4081
|
}
|
|
@@ -4010,103 +4101,81 @@ ${invalidationCode}
|
|
|
4010
4101
|
return [];
|
|
4011
4102
|
}
|
|
4012
4103
|
const relatedQueries = [];
|
|
4013
|
-
const
|
|
4104
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4014
4105
|
const mutationTag = endpoint.tags[0];
|
|
4015
|
-
const
|
|
4106
|
+
const mutationSegments = this.getResourceSegments(endpoint.path);
|
|
4107
|
+
const mutationResource = mutationSegments[0];
|
|
4016
4108
|
context.schema.endpoints.forEach((queryEndpoint) => {
|
|
4017
4109
|
if (queryEndpoint.method !== "GET") return;
|
|
4018
|
-
const
|
|
4110
|
+
const queryId = queryEndpoint.operationId || queryEndpoint.id;
|
|
4111
|
+
if (seen.has(queryId)) return;
|
|
4019
4112
|
const queryTag = queryEndpoint.tags[0];
|
|
4020
|
-
|
|
4113
|
+
const querySegments = this.getResourceSegments(queryEndpoint.path);
|
|
4114
|
+
const queryResource = querySegments[0];
|
|
4115
|
+
if (mutationTag && queryTag === mutationTag) {
|
|
4021
4116
|
relatedQueries.push(queryEndpoint);
|
|
4117
|
+
seen.add(queryId);
|
|
4022
4118
|
return;
|
|
4023
4119
|
}
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
if (baseMatch) {
|
|
4028
|
-
relatedQueries.push(queryEndpoint);
|
|
4029
|
-
}
|
|
4120
|
+
if (mutationResource && queryResource && mutationResource === queryResource) {
|
|
4121
|
+
relatedQueries.push(queryEndpoint);
|
|
4122
|
+
seen.add(queryId);
|
|
4030
4123
|
}
|
|
4031
4124
|
});
|
|
4032
4125
|
return relatedQueries;
|
|
4033
4126
|
}
|
|
4127
|
+
getResourceSegments(path3) {
|
|
4128
|
+
return path3.split("/").filter(Boolean).filter((segment) => segment.toLowerCase() !== "api" && !/^v\d+/i.test(segment));
|
|
4129
|
+
}
|
|
4034
4130
|
/**
|
|
4035
4131
|
* Build invalidation code for related queries
|
|
4036
4132
|
*/
|
|
4037
4133
|
buildInvalidationCode(endpoint, relatedQueries, invalidationTags) {
|
|
4038
|
-
const invalidations =
|
|
4134
|
+
const invalidations = /* @__PURE__ */ new Set();
|
|
4039
4135
|
relatedQueries.forEach((queryEndpoint) => {
|
|
4040
|
-
const
|
|
4041
|
-
invalidations.
|
|
4136
|
+
const queryKeyPrefix = toActionName(queryEndpoint.operationId || queryEndpoint.id);
|
|
4137
|
+
invalidations.add(`queryClient.invalidateQueries({ queryKey: ['${queryKeyPrefix}'] })`);
|
|
4042
4138
|
});
|
|
4043
4139
|
invalidationTags.forEach((tag) => {
|
|
4044
|
-
|
|
4045
|
-
invalidations.push(` queryClient.invalidateQueries({ queryKey: ['${tag}'] })`);
|
|
4046
|
-
}
|
|
4140
|
+
invalidations.add(`queryClient.invalidateQueries({ queryKey: ['${tag}'] })`);
|
|
4047
4141
|
});
|
|
4048
|
-
if (invalidations.
|
|
4142
|
+
if (invalidations.size === 0) {
|
|
4049
4143
|
const inferredKey = this.inferQueryKeyFromPath(endpoint);
|
|
4050
4144
|
if (inferredKey) {
|
|
4051
|
-
invalidations.
|
|
4145
|
+
invalidations.add(`queryClient.invalidateQueries({ queryKey: ${inferredKey} })`);
|
|
4052
4146
|
}
|
|
4053
4147
|
}
|
|
4054
|
-
|
|
4148
|
+
if (invalidations.size === 0) {
|
|
4149
|
+
return " // No specific cache invalidation needed";
|
|
4150
|
+
}
|
|
4151
|
+
if (invalidations.size === 1) {
|
|
4152
|
+
const [statement] = Array.from(invalidations);
|
|
4153
|
+
return ` await ${statement}`;
|
|
4154
|
+
}
|
|
4155
|
+
return ` await Promise.all([
|
|
4156
|
+
${Array.from(invalidations).join(",\n ")}
|
|
4157
|
+
])`;
|
|
4055
4158
|
}
|
|
4056
4159
|
/**
|
|
4057
4160
|
* Build cancel queries code
|
|
4161
|
+
* Uses query key patterns to cancel all related queries regardless of parameters
|
|
4058
4162
|
*/
|
|
4059
4163
|
buildCancelQueriesCode(endpoint, relatedQueries) {
|
|
4060
|
-
const cancels =
|
|
4164
|
+
const cancels = /* @__PURE__ */ new Set();
|
|
4061
4165
|
relatedQueries.forEach((queryEndpoint) => {
|
|
4062
|
-
const
|
|
4063
|
-
cancels.
|
|
4064
|
-
});
|
|
4065
|
-
return cancels.length > 0 ? cancels.join("\n") : " // No queries to cancel";
|
|
4066
|
-
}
|
|
4067
|
-
/**
|
|
4068
|
-
* Build snapshot code for rollback
|
|
4069
|
-
*/
|
|
4070
|
-
buildSnapshotCode(endpoint, relatedQueries) {
|
|
4071
|
-
if (relatedQueries.length === 0) {
|
|
4072
|
-
return " // No queries to snapshot";
|
|
4073
|
-
}
|
|
4074
|
-
const snapshots = [];
|
|
4075
|
-
relatedQueries.forEach((queryEndpoint, index) => {
|
|
4076
|
-
const queryKey = this.generateQueryKey(queryEndpoint);
|
|
4077
|
-
const varName = `previous${this.toPascalCase(toActionName(queryEndpoint.operationId || queryEndpoint.id))}`;
|
|
4078
|
-
snapshots.push(` const ${varName} = queryClient.getQueryData(${queryKey})`);
|
|
4166
|
+
const queryKeyPrefix = toActionName(queryEndpoint.operationId || queryEndpoint.id);
|
|
4167
|
+
cancels.add(`queryClient.cancelQueries({ queryKey: ['${queryKeyPrefix}'] })`);
|
|
4079
4168
|
});
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
/**
|
|
4083
|
-
* Build rollback code
|
|
4084
|
-
*/
|
|
4085
|
-
buildRollbackCode(endpoint, relatedQueries) {
|
|
4086
|
-
if (relatedQueries.length === 0) {
|
|
4087
|
-
return " // No queries to rollback";
|
|
4169
|
+
if (cancels.size === 0) {
|
|
4170
|
+
return " // No queries to cancel";
|
|
4088
4171
|
}
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
const varName = `previous${this.toPascalCase(toActionName(queryEndpoint.operationId || queryEndpoint.id))}`;
|
|
4093
|
-
rollbacks.push(` if (context?.${varName}) {
|
|
4094
|
-
queryClient.setQueryData(${queryKey}, context.${varName})
|
|
4095
|
-
}`);
|
|
4096
|
-
});
|
|
4097
|
-
return rollbacks.join("\n");
|
|
4098
|
-
}
|
|
4099
|
-
/**
|
|
4100
|
-
* Get snapshot return names for context
|
|
4101
|
-
*/
|
|
4102
|
-
getSnapshotReturnNames(relatedQueries) {
|
|
4103
|
-
if (relatedQueries.length === 0) {
|
|
4104
|
-
return "previousData: null";
|
|
4172
|
+
if (cancels.size === 1) {
|
|
4173
|
+
const [statement] = Array.from(cancels);
|
|
4174
|
+
return ` await ${statement}`;
|
|
4105
4175
|
}
|
|
4106
|
-
return
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
}).join(", ");
|
|
4176
|
+
return ` await Promise.all([
|
|
4177
|
+
${Array.from(cancels).join(",\n ")}
|
|
4178
|
+
])`;
|
|
4110
4179
|
}
|
|
4111
4180
|
/**
|
|
4112
4181
|
* Infer query key from mutation path
|
|
@@ -4264,8 +4333,8 @@ export function useBridgeQuery<TData = unknown, TError = Error>(
|
|
|
4264
4333
|
refetchOnWindowFocus: true,
|
|
4265
4334
|
refetchOnReconnect: true,
|
|
4266
4335
|
refetchOnMount: 'always',
|
|
4267
|
-
placeholderData: (previousData) => previousData,
|
|
4268
|
-
retry: (failureCount, error) => {
|
|
4336
|
+
placeholderData: (previousData: TData | undefined) => previousData,
|
|
4337
|
+
retry: (failureCount: number, error: Error) => {
|
|
4269
4338
|
if (error instanceof Error && error.message.includes('4')) return false
|
|
4270
4339
|
return failureCount < 3
|
|
4271
4340
|
},
|
|
@@ -4290,13 +4359,13 @@ export function useBridgeInfiniteQuery<TData = unknown, TError = Error>(
|
|
|
4290
4359
|
refetchOnWindowFocus: true,
|
|
4291
4360
|
refetchOnReconnect: true,
|
|
4292
4361
|
refetchOnMount: 'always',
|
|
4293
|
-
placeholderData: (previousData) => previousData,
|
|
4294
|
-
retry: (failureCount, error) => {
|
|
4362
|
+
placeholderData: (previousData: TData | undefined) => previousData,
|
|
4363
|
+
retry: (failureCount: number, error: Error) => {
|
|
4295
4364
|
if (error instanceof Error && error.message.includes('4')) return false
|
|
4296
4365
|
return failureCount < 3
|
|
4297
4366
|
},
|
|
4298
4367
|
...options,
|
|
4299
|
-
}
|
|
4368
|
+
})
|
|
4300
4369
|
}
|
|
4301
4370
|
|
|
4302
4371
|
/**
|
|
@@ -4313,7 +4382,7 @@ export function useBridgeSuspenseQuery<TData = unknown, TError = Error>(
|
|
|
4313
4382
|
queryFn: queryFn as QueryFunction<TData, QueryKey>,
|
|
4314
4383
|
staleTime: 5 * 60 * 1000,
|
|
4315
4384
|
gcTime: 10 * 60 * 1000,
|
|
4316
|
-
retry: (failureCount, error) => {
|
|
4385
|
+
retry: (failureCount: number, error: Error) => {
|
|
4317
4386
|
if (error instanceof Error && error.message.includes('4')) return false
|
|
4318
4387
|
return failureCount < 3
|
|
4319
4388
|
},
|
|
@@ -7528,9 +7597,6 @@ var UploadGenerator = class {
|
|
|
7528
7597
|
const compressionFormats = uploads?.compression?.formats || ["gzip", "webp"];
|
|
7529
7598
|
const content = `'use client'
|
|
7530
7599
|
|
|
7531
|
-
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
|
7532
|
-
import { toast } from 'sonner'
|
|
7533
|
-
|
|
7534
7600
|
/**
|
|
7535
7601
|
* Upload configuration
|
|
7536
7602
|
*/
|
|
@@ -7710,7 +7776,7 @@ export function createUploadFormData(
|
|
|
7710
7776
|
"FileValidationResult",
|
|
7711
7777
|
"UploadProgress"
|
|
7712
7778
|
],
|
|
7713
|
-
imports: [
|
|
7779
|
+
imports: [],
|
|
7714
7780
|
dependencies: []
|
|
7715
7781
|
}
|
|
7716
7782
|
};
|
|
@@ -7816,16 +7882,18 @@ async function uploadToS3(
|
|
|
7816
7882
|
xhr.send(formData)
|
|
7817
7883
|
})
|
|
7818
7884
|
}
|
|
7819
|
-
|
|
7885
|
+
` : "";
|
|
7886
|
+
const needsBackendHelper = progressEnabled && useXHR || presignedEnabled && fallbackEnabled;
|
|
7887
|
+
const backendUploadHelper = needsBackendHelper ? `
|
|
7820
7888
|
/**
|
|
7821
7889
|
* Upload via backend API with progress tracking
|
|
7822
|
-
* Uses
|
|
7890
|
+
* Uses XMLHttpRequest for progress tracking support
|
|
7823
7891
|
*/
|
|
7824
7892
|
async function uploadViaBackendApi(
|
|
7825
7893
|
formData: FormData,
|
|
7826
7894
|
onProgress?: (progress: { loaded: number; total: number; percentage: number }) => void
|
|
7827
7895
|
): Promise<z.infer<typeof ${operationName}ResponseSchema>> {
|
|
7828
|
-
|
|
7896
|
+
return new Promise((resolve, reject) => {
|
|
7829
7897
|
const xhr = new XMLHttpRequest()
|
|
7830
7898
|
|
|
7831
7899
|
if (onProgress) {
|
|
@@ -7874,13 +7942,9 @@ async function uploadViaBackendApi(
|
|
|
7874
7942
|
: '${this.configuration.api?.baseUrl || "http://localhost:8000"}'
|
|
7875
7943
|
xhr.open('POST', \`\${baseUrl}${endpoint.path}\`)
|
|
7876
7944
|
xhr.send(formData)
|
|
7877
|
-
})
|
|
7878
|
-
|
|
7879
|
-
|
|
7880
|
-
const response = await ${actionName}(formData as any)
|
|
7881
|
-
return response
|
|
7882
|
-
`}
|
|
7883
|
-
}` : "";
|
|
7945
|
+
})
|
|
7946
|
+
}
|
|
7947
|
+
` : "";
|
|
7884
7948
|
const uploadLogic = presignedEnabled ? `
|
|
7885
7949
|
let fileKey: string | null = null
|
|
7886
7950
|
let directUploadAttempted = false
|
|
@@ -7995,6 +8059,7 @@ async function uploadViaBackendApi(
|
|
|
7995
8059
|
`;
|
|
7996
8060
|
const content = `${imports}
|
|
7997
8061
|
${presignedHelpers}
|
|
8062
|
+
${backendUploadHelper || ""}
|
|
7998
8063
|
|
|
7999
8064
|
/**
|
|
8000
8065
|
* Upload hook for ${endpoint.method} ${endpoint.path}
|
|
@@ -8031,7 +8096,7 @@ export function ${hookName}Upload(options?: {
|
|
|
8031
8096
|
${uploadLogic}
|
|
8032
8097
|
},
|
|
8033
8098
|
|
|
8034
|
-
onSuccess: (data) => {
|
|
8099
|
+
onSuccess: (data: z.infer<typeof ${operationName}ResponseSchema>) => {
|
|
8035
8100
|
// Don't show toast here, let the page handle it
|
|
8036
8101
|
options?.onSuccess?.(data)
|
|
8037
8102
|
|
|
@@ -8245,7 +8310,9 @@ let toast: {
|
|
|
8245
8310
|
} | null = null
|
|
8246
8311
|
|
|
8247
8312
|
// Lazy load toast to avoid bundling issues
|
|
8248
|
-
async function getToast() {
|
|
8313
|
+
async function getToast(): Promise<{
|
|
8314
|
+
error: (message: string, options?: { duration?: number; description?: string }) => void
|
|
8315
|
+
} | null> {
|
|
8249
8316
|
if (toast !== null) return toast
|
|
8250
8317
|
|
|
8251
8318
|
try {
|
|
@@ -8339,24 +8406,26 @@ export async function handleAuthError(error: unknown, redirectTo?: string): Prom
|
|
|
8339
8406
|
const toastInstance = await getToast()
|
|
8340
8407
|
|
|
8341
8408
|
// Show appropriate error message based on error type
|
|
8342
|
-
if (
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8356
|
-
|
|
8357
|
-
|
|
8358
|
-
|
|
8359
|
-
|
|
8409
|
+
if (toastInstance) {
|
|
8410
|
+
if (isInactive) {
|
|
8411
|
+
toastInstance.error('Your account has been deactivated. Please contact support for assistance.', {
|
|
8412
|
+
duration: 5000,
|
|
8413
|
+
description: 'You will be redirected to the login page.',
|
|
8414
|
+
})
|
|
8415
|
+
} else if (apiError.status === 401) {
|
|
8416
|
+
toastInstance.error('Your session has expired. Please sign in again.', {
|
|
8417
|
+
duration: 4000,
|
|
8418
|
+
})
|
|
8419
|
+
} else if (apiError.status === 403) {
|
|
8420
|
+
toastInstance.error('Access denied. Your account may have been suspended.', {
|
|
8421
|
+
duration: 5000,
|
|
8422
|
+
description: 'You will be redirected to the login page.',
|
|
8423
|
+
})
|
|
8424
|
+
} else {
|
|
8425
|
+
toastInstance.error('Authentication failed. Please sign in again.', {
|
|
8426
|
+
duration: 4000,
|
|
8427
|
+
})
|
|
8428
|
+
}
|
|
8360
8429
|
}
|
|
8361
8430
|
|
|
8362
8431
|
if (typeof window !== 'undefined') {
|
|
@@ -8367,7 +8436,7 @@ export async function handleAuthError(error: unknown, redirectTo?: string): Prom
|
|
|
8367
8436
|
const { signOut } = await import('${authPath}')
|
|
8368
8437
|
signOut({
|
|
8369
8438
|
redirect: false,
|
|
8370
|
-
}).catch((signOutError) => {
|
|
8439
|
+
}).catch((signOutError: unknown) => {
|
|
8371
8440
|
console.error('[Auth Error Handler] Error during sign out (non-blocking):', signOutError)
|
|
8372
8441
|
})
|
|
8373
8442
|
} catch (importError) {
|
|
@@ -9356,7 +9425,8 @@ var bridgeConfigSchema = zod.z.object({
|
|
|
9356
9425
|
logging: zod.z.boolean().default(true),
|
|
9357
9426
|
validation: zod.z.boolean().default(true),
|
|
9358
9427
|
mocking: zod.z.boolean().default(false),
|
|
9359
|
-
watch: zod.z.boolean().default(false)
|
|
9428
|
+
watch: zod.z.boolean().default(false),
|
|
9429
|
+
hotReload: zod.z.boolean().default(false)
|
|
9360
9430
|
}).optional(),
|
|
9361
9431
|
plugins: zod.z.array(
|
|
9362
9432
|
zod.z.object({
|
|
@@ -9369,6 +9439,7 @@ var bridgeConfigSchema = zod.z.object({
|
|
|
9369
9439
|
typescript: zod.z.boolean().default(true),
|
|
9370
9440
|
strict: zod.z.boolean().default(true),
|
|
9371
9441
|
comments: zod.z.boolean().default(true),
|
|
9442
|
+
documentation: zod.z.boolean().default(true),
|
|
9372
9443
|
examples: zod.z.boolean().default(false),
|
|
9373
9444
|
tests: zod.z.boolean().default(false)
|
|
9374
9445
|
}).optional()
|
|
@@ -9474,12 +9545,14 @@ ${errorMessages}`,
|
|
|
9474
9545
|
logging: true,
|
|
9475
9546
|
validation: true,
|
|
9476
9547
|
mocking: false,
|
|
9477
|
-
watch: false
|
|
9548
|
+
watch: false,
|
|
9549
|
+
hotReload: false
|
|
9478
9550
|
},
|
|
9479
9551
|
generation: {
|
|
9480
9552
|
typescript: true,
|
|
9481
9553
|
strict: true,
|
|
9482
9554
|
comments: true,
|
|
9555
|
+
documentation: true,
|
|
9483
9556
|
examples: false,
|
|
9484
9557
|
tests: false
|
|
9485
9558
|
}
|
|
@@ -9546,5 +9619,5 @@ exports.VersionChecker = VersionChecker;
|
|
|
9546
9619
|
exports.__name = __name;
|
|
9547
9620
|
exports.checkAndNotifyUpdates = checkAndNotifyUpdates;
|
|
9548
9621
|
exports.createBridgeVersionChecker = createBridgeVersionChecker;
|
|
9549
|
-
//# sourceMappingURL=chunk-
|
|
9550
|
-
//# sourceMappingURL=chunk-
|
|
9622
|
+
//# sourceMappingURL=chunk-OOY4PCDK.cjs.map
|
|
9623
|
+
//# sourceMappingURL=chunk-OOY4PCDK.cjs.map
|