mulink 1.0.4 → 1.0.6
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-KCNMWAI2.js → chunk-GHDF3TJA.js} +284 -258
- package/dist/lib/chunk-GHDF3TJA.js.map +1 -0
- package/dist/lib/{chunk-GKRRC2YD.cjs → chunk-PZXEJ43S.cjs} +284 -258
- package/dist/lib/chunk-PZXEJ43S.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-GKRRC2YD.cjs.map +0 -1
- package/dist/lib/chunk-KCNMWAI2.js.map +0 -1
|
@@ -1544,7 +1544,6 @@ export class BaseApiClient {
|
|
|
1544
1544
|
retryDelay, retryCondition, validateResponse, skipAuth,
|
|
1545
1545
|
responseSchema, requestId, [...this.middleware, ...middleware],
|
|
1546
1546
|
cacheTags, revalidate, connection, updateTag
|
|
1547
|
-
cacheTags, revalidate, connection, updateTag
|
|
1548
1547
|
)
|
|
1549
1548
|
|
|
1550
1549
|
requestCache.set(dedupeKey, requestPromise)
|
|
@@ -1562,7 +1561,6 @@ export class BaseApiClient {
|
|
|
1562
1561
|
retryDelay, retryCondition, validateResponse, skipAuth,
|
|
1563
1562
|
responseSchema, requestId, [...this.middleware, ...middleware],
|
|
1564
1563
|
cacheTags, revalidate, connection, updateTag
|
|
1565
|
-
cacheTags, revalidate, connection, updateTag
|
|
1566
1564
|
)
|
|
1567
1565
|
}
|
|
1568
1566
|
|
|
@@ -2718,7 +2716,9 @@ var SchemaGenerator = class {
|
|
|
2718
2716
|
].join("\n");
|
|
2719
2717
|
let content = this.removeUnusedCode(contentWithImports);
|
|
2720
2718
|
if (!content.includes('import { z } from "zod"') && !content.includes("import { z } from 'zod'")) {
|
|
2721
|
-
content =
|
|
2719
|
+
content = `import { z } from "zod"
|
|
2720
|
+
|
|
2721
|
+
${content}`;
|
|
2722
2722
|
}
|
|
2723
2723
|
return {
|
|
2724
2724
|
path: "schemas/index.ts",
|
|
@@ -3129,6 +3129,166 @@ var ActionGenerator = class {
|
|
|
3129
3129
|
static {
|
|
3130
3130
|
__name(this, "ActionGenerator");
|
|
3131
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
|
+
}
|
|
3132
3292
|
buildImportPath(relativePath) {
|
|
3133
3293
|
const outputDirectory = this.configuration.outputDir || "generated";
|
|
3134
3294
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
@@ -3193,8 +3353,7 @@ var ActionGenerator = class {
|
|
|
3193
3353
|
] : []
|
|
3194
3354
|
].filter(Boolean).join("\n");
|
|
3195
3355
|
const rateLimitSetup = hasRateLimit ? `
|
|
3196
|
-
// Rate limiting setup
|
|
3197
|
-
const redis = new Redis({
|
|
3356
|
+
${this.commentsEnabled ? "// Rate limiting setup\n" : ""}const redis = new Redis({
|
|
3198
3357
|
url: process.env.UPSTASH_REDIS_REST_URL!,
|
|
3199
3358
|
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
|
|
3200
3359
|
})
|
|
@@ -3204,60 +3363,7 @@ const ratelimit = new Ratelimit({
|
|
|
3204
3363
|
limiter: Ratelimit.slidingWindow(10, '1 m'),
|
|
3205
3364
|
analytics: true,
|
|
3206
3365
|
})` : "";
|
|
3207
|
-
const utilityFunctions =
|
|
3208
|
-
// Utility functions for enhanced server actions
|
|
3209
|
-
async function getClientInfo() {
|
|
3210
|
-
const headersList = await headers()
|
|
3211
|
-
const userAgent = headersList.get('user-agent') || 'unknown'
|
|
3212
|
-
const ip = headersList.get('x-forwarded-for') || headersList.get('x-real-ip') || 'unknown'
|
|
3213
|
-
|
|
3214
|
-
return { userAgent, ip }
|
|
3215
|
-
}
|
|
3216
|
-
|
|
3217
|
-
async function validateAndSanitizeInput<T>(schema: z.ZodSchema<T>, input: unknown): Promise<T> {
|
|
3218
|
-
try {
|
|
3219
|
-
return await schema.parseAsync(input)
|
|
3220
|
-
} catch (error) {
|
|
3221
|
-
if (error instanceof z.ZodError) {
|
|
3222
|
-
const errorMessages = error.issues.map(issue => {
|
|
3223
|
-
const path = issue.path.length > 0 ? \`\${issue.path.join('.')}: \` : ''
|
|
3224
|
-
return \`\${path}\${issue.message}\`
|
|
3225
|
-
}).join(', ')
|
|
3226
|
-
throw new ActionError(\`Input validation failed: \${errorMessages}\`, 'VALIDATION_ERROR')
|
|
3227
|
-
}
|
|
3228
|
-
throw new ActionError('Invalid input format', 'VALIDATION_ERROR')
|
|
3229
|
-
}
|
|
3230
|
-
}
|
|
3231
|
-
|
|
3232
|
-
// Enhanced error handling with context
|
|
3233
|
-
class ActionExecutionError extends ActionError {
|
|
3234
|
-
constructor(
|
|
3235
|
-
message: string,
|
|
3236
|
-
public readonly context: {
|
|
3237
|
-
endpoint: string
|
|
3238
|
-
method: string
|
|
3239
|
-
timestamp: number
|
|
3240
|
-
},
|
|
3241
|
-
public readonly originalError?: unknown
|
|
3242
|
-
) {
|
|
3243
|
-
super(message, 'EXECUTION_ERROR')
|
|
3244
|
-
}
|
|
3245
|
-
}
|
|
3246
|
-
|
|
3247
|
-
// Logging utility for server actions
|
|
3248
|
-
async function logActionExecution(
|
|
3249
|
-
action: string,
|
|
3250
|
-
success: boolean,
|
|
3251
|
-
duration: number,
|
|
3252
|
-
context?: Record<string, any>
|
|
3253
|
-
) {
|
|
3254
|
-
if (process.env.NODE_ENV === 'development') {
|
|
3255
|
-
console.log(\`[ACTION] \${action} - \${success ? 'SUCCESS' : 'FAILED'} (\${duration}ms)\`, context)
|
|
3256
|
-
}
|
|
3257
|
-
|
|
3258
|
-
// In production, send to your logging service
|
|
3259
|
-
// await analytics.track('server_action_executed', { action, success, duration, ...context })
|
|
3260
|
-
}`;
|
|
3366
|
+
const utilityFunctions = this.buildUtilityFunctions();
|
|
3261
3367
|
const content = `${imports}
|
|
3262
3368
|
${rateLimitSetup}
|
|
3263
3369
|
${utilityFunctions}
|
|
@@ -3274,8 +3380,8 @@ ${actions}`;
|
|
|
3274
3380
|
}
|
|
3275
3381
|
});
|
|
3276
3382
|
}
|
|
3277
|
-
const
|
|
3278
|
-
${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")}`;
|
|
3279
3385
|
generatedFiles.push({
|
|
3280
3386
|
path: "actions/index.ts",
|
|
3281
3387
|
content: indexContent,
|
|
@@ -3324,54 +3430,48 @@ ${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier
|
|
|
3324
3430
|
body: ${operationName}RequestSchema,
|
|
3325
3431
|
params: ${operationName}ParamsSchema
|
|
3326
3432
|
})`;
|
|
3327
|
-
parameterProcessing =
|
|
3328
|
-
// Validate and sanitize input
|
|
3329
|
-
const { body, params } = await validateAndSanitizeInput(${schemaName}, parsedInput)
|
|
3330
|
-
const validatedBody = body
|
|
3331
|
-
const validatedParams = params as z.infer<typeof ${operationName}ParamsSchema>`;
|
|
3433
|
+
parameterProcessing = this.buildCombinedValidationSnippet(operationName, schemaName);
|
|
3332
3434
|
requestOptionsParams = this.buildRequestOptions(pathParameters, queryParameters, true, true);
|
|
3333
3435
|
} else if (hasRequestBody) {
|
|
3334
3436
|
schemaName = `${operationName}RequestSchema`;
|
|
3335
|
-
parameterProcessing =
|
|
3336
|
-
// Validate and sanitize request body
|
|
3337
|
-
const validatedBody = await validateAndSanitizeInput(${schemaName}, parsedInput)`;
|
|
3437
|
+
parameterProcessing = this.buildBodyValidationSnippet(schemaName);
|
|
3338
3438
|
requestOptionsParams = `body: validatedBody`;
|
|
3339
3439
|
} else if (hasAnyParams) {
|
|
3340
3440
|
schemaName = `${operationName}ParamsSchema`;
|
|
3341
|
-
parameterProcessing =
|
|
3342
|
-
// Validate and sanitize parameters
|
|
3343
|
-
const validatedParams = await validateAndSanitizeInput(${schemaName}, parsedInput) as z.infer<typeof ${operationName}ParamsSchema>`;
|
|
3441
|
+
parameterProcessing = this.buildParamsValidationSnippet(operationName, schemaName);
|
|
3344
3442
|
requestOptionsParams = this.buildRequestOptions(pathParameters, queryParameters, false, true);
|
|
3345
3443
|
} else {
|
|
3346
3444
|
schemaName = "z.void()";
|
|
3347
3445
|
parameterProcessing = "";
|
|
3348
3446
|
requestOptionsParams = "";
|
|
3349
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} }`;
|
|
3350
3452
|
const clientName = requiresAuth || hasRateLimit ? "authActionClient" : "actionClientWithMeta";
|
|
3351
3453
|
const rateLimitCode = hasRateLimit ? `
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
}` : "";
|
|
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
|
+
}` : "";
|
|
3363
3464
|
const revalidationCode = revalidationTags.length > 0 ? revalidationTags.map(
|
|
3364
|
-
(tag) => ` updateTag('${tag}')
|
|
3365
|
-
console.log('Updated tag: ${tag}')`
|
|
3465
|
+
(tag) => ` updateTag('${tag}')${this.loggingEnabled ? `
|
|
3466
|
+
console.log('Updated tag: ${tag}')` : ""}`
|
|
3366
3467
|
).join("\n") : "";
|
|
3367
3468
|
const kebabActionName = actionName.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
|
|
3368
3469
|
if (isQuery) {
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
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(
|
|
3375
3475
|
${clientName}
|
|
3376
3476
|
.metadata({
|
|
3377
3477
|
name: "${kebabActionName}",
|
|
@@ -3379,7 +3479,7 @@ export const ${actionName} = cache(
|
|
|
3379
3479
|
rateLimit: { requests: ${endpoint.metadata.rateLimit?.requests || 10}, window: "${endpoint.metadata.rateLimit?.window || "1m"}" }` : ""}
|
|
3380
3480
|
})
|
|
3381
3481
|
.schema(${schemaName})
|
|
3382
|
-
.action(async ({ parsedInput, ctx }:
|
|
3482
|
+
.action(async ({ parsedInput, ctx }: ${actionArgsType}) => {
|
|
3383
3483
|
const startTime = Date.now()
|
|
3384
3484
|
|
|
3385
3485
|
try {${rateLimitCode}${parameterProcessing}
|
|
@@ -3394,23 +3494,11 @@ export const ${actionName} = cache(
|
|
|
3394
3494
|
}
|
|
3395
3495
|
})
|
|
3396
3496
|
|
|
3397
|
-
|
|
3398
|
-
const duration = Date.now() - startTime
|
|
3399
|
-
await logActionExecution('${actionName}', true, duration, {
|
|
3400
|
-
method: '${endpoint.method}',
|
|
3401
|
-
path: '${endpoint.path}'
|
|
3402
|
-
})
|
|
3497
|
+
${this.buildSuccessLoggingBlock(actionName, endpoint, 8)}
|
|
3403
3498
|
|
|
3404
3499
|
return response.data
|
|
3405
3500
|
} catch (error) {
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
// Enhanced error logging
|
|
3409
|
-
await logActionExecution('${actionName}', false, duration, {
|
|
3410
|
-
method: '${endpoint.method}',
|
|
3411
|
-
path: '${endpoint.path}',
|
|
3412
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
3413
|
-
})
|
|
3501
|
+
${this.buildErrorLoggingBlock(actionName, endpoint, 8)}
|
|
3414
3502
|
|
|
3415
3503
|
// Throw enhanced error with context
|
|
3416
3504
|
throw new ActionExecutionError(
|
|
@@ -3427,50 +3515,37 @@ export const ${actionName} = cache(
|
|
|
3427
3515
|
)`;
|
|
3428
3516
|
}
|
|
3429
3517
|
const redirectCode = `
|
|
3430
|
-
|
|
3431
|
-
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')) {
|
|
3432
3519
|
const location = response.headers.get('location')!
|
|
3433
3520
|
redirect(location)
|
|
3434
3521
|
}`;
|
|
3435
3522
|
const streamingCode = `
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
// Process streaming response
|
|
3439
|
-
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
|
|
3440
3525
|
}`;
|
|
3441
3526
|
const fileUploadCode = hasFileUpload ? uploadStrategy === "external" && uploadProvider === "vercel-blob" ? `
|
|
3442
|
-
|
|
3443
|
-
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) {
|
|
3444
3528
|
const file = (validatedBody as any).file as File
|
|
3445
3529
|
const blob = await put(file.name, file, { access: 'public' })
|
|
3446
3530
|
Object.assign(validatedBody, { fileUrl: blob.url })
|
|
3447
3531
|
}` : uploadStrategy === "external" && uploadProvider === "uploadthing" ? `
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
const file = (validatedBody as any).file as File
|
|
3459
|
-
// Process file with compression and validation if enabled
|
|
3460
|
-
}` : "";
|
|
3461
|
-
return `/**
|
|
3462
|
-
* ${endpoint.summary || endpoint.description || `${endpoint.method} ${endpoint.path}`}
|
|
3463
|
-
* @generated from ${endpoint.method} ${endpoint.path}
|
|
3464
|
-
* Features: Input validation, revalidation, error handling
|
|
3465
|
-
*/
|
|
3466
|
-
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}
|
|
3467
3542
|
.metadata({
|
|
3468
3543
|
name: "${kebabActionName}",
|
|
3469
3544
|
requiresAuth: ${requiresAuth}${hasRateLimit ? `,
|
|
3470
3545
|
rateLimit: { requests: ${endpoint.metadata.rateLimit?.requests || 10}, window: "${endpoint.metadata.rateLimit?.window || "1m"}" }` : ""}
|
|
3471
3546
|
})
|
|
3472
3547
|
.schema(${schemaName})
|
|
3473
|
-
.action(async ({ parsedInput, ctx }:
|
|
3548
|
+
.action(async ({ parsedInput, ctx }: ${actionArgsType}) => {
|
|
3474
3549
|
const startTime = Date.now()
|
|
3475
3550
|
|
|
3476
3551
|
try {${rateLimitCode}${parameterProcessing}${fileUploadCode}
|
|
@@ -3485,33 +3560,13 @@ export const ${actionName} = ${clientName}
|
|
|
3485
3560
|
}
|
|
3486
3561
|
})${streamingCode}${redirectCode}
|
|
3487
3562
|
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
// Background tasks (Next.js 15 feature)
|
|
3492
|
-
${isStreaming ? `after(async () => {
|
|
3493
|
-
// Perform background tasks after response is sent
|
|
3494
|
-
await logActionExecution('${actionName}', true, Date.now() - startTime, {
|
|
3495
|
-
method: '${endpoint.method}',
|
|
3496
|
-
path: '${endpoint.path}'
|
|
3497
|
-
})
|
|
3498
|
-
})` : `// Log successful execution
|
|
3499
|
-
const duration = Date.now() - startTime
|
|
3500
|
-
await logActionExecution('${actionName}', true, duration, {
|
|
3501
|
-
method: '${endpoint.method}',
|
|
3502
|
-
path: '${endpoint.path}'
|
|
3503
|
-
})`}
|
|
3563
|
+
${revalidationCode ? `${this.commentLine("Revalidate cache after successful mutation", 6)}${revalidationCode}
|
|
3564
|
+
` : ""}
|
|
3565
|
+
${this.buildSuccessLoggingBlock(actionName, endpoint, 6, isStreaming)}
|
|
3504
3566
|
|
|
3505
3567
|
return response.data
|
|
3506
3568
|
} catch (error) {
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
// Enhanced error logging
|
|
3510
|
-
await logActionExecution('${actionName}', false, duration, {
|
|
3511
|
-
method: '${endpoint.method}',
|
|
3512
|
-
path: '${endpoint.path}',
|
|
3513
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
3514
|
-
})
|
|
3569
|
+
${this.buildErrorLoggingBlock(actionName, endpoint, 6)}
|
|
3515
3570
|
|
|
3516
3571
|
// Throw enhanced error with context
|
|
3517
3572
|
throw new ActionExecutionError(
|
|
@@ -3670,7 +3725,6 @@ var HookGenerator = class {
|
|
|
3670
3725
|
if (hasInfiniteQueries) reactQueryImports.push("useInfiniteQuery");
|
|
3671
3726
|
const reactImports = [];
|
|
3672
3727
|
if (hasMutations) reactImports.push("useOptimistic", "useTransition");
|
|
3673
|
-
if (hasQueries) reactImports.push("useCallback");
|
|
3674
3728
|
const imports = [
|
|
3675
3729
|
"'use client'",
|
|
3676
3730
|
"",
|
|
@@ -3782,19 +3836,19 @@ ${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier
|
|
|
3782
3836
|
* @returns useQuery result with data of type ${returnType}
|
|
3783
3837
|
*/
|
|
3784
3838
|
export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join(", ")}, ` : ""}options?: ${optionsType}) {
|
|
3785
|
-
const [searchParams
|
|
3839
|
+
const [searchParams] = useQueryStates(searchParamsParser)
|
|
3786
3840
|
const { initialData, ...restOptions } = options ?? {}
|
|
3787
3841
|
|
|
3788
3842
|
return useQuery({
|
|
3789
3843
|
queryKey: [...${queryKey}, searchParams],
|
|
3790
|
-
queryFn:
|
|
3844
|
+
queryFn: async ({ signal }: { signal?: AbortSignal }) => {
|
|
3791
3845
|
try {
|
|
3792
3846
|
const result = await ${actionName}(${actionCallParams.replace(queryParamObject, "{ ...searchParams }")})
|
|
3793
3847
|
return result
|
|
3794
3848
|
} catch (error) {
|
|
3795
3849
|
handleActionError(error)
|
|
3796
3850
|
}
|
|
3797
|
-
},
|
|
3851
|
+
},
|
|
3798
3852
|
staleTime: ${staleTime},
|
|
3799
3853
|
gcTime: ${staleTime * 2}, // React Query v5: gcTime replaces cacheTime
|
|
3800
3854
|
enabled: ${enabledCondition} && (options?.enabled ?? true),
|
|
@@ -3802,7 +3856,6 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3802
3856
|
refetchOnReconnect: true, // Refetch when network reconnects
|
|
3803
3857
|
refetchOnMount: 'always', // Always refetch on mount for fresh data
|
|
3804
3858
|
refetchInterval: options?.refetchInterval, // Optional polling interval
|
|
3805
|
-
initialDataUpdatedAt: initialData ? Date.now() : undefined,
|
|
3806
3859
|
// React Query v5: placeholderData replaces keepPreviousData
|
|
3807
3860
|
placeholderData: (previousData: ${returnType} | undefined) => previousData,
|
|
3808
3861
|
retry: (failureCount: number, error: Error) => {
|
|
@@ -3826,14 +3879,14 @@ export function ${hookName.replace("use", "useInfinite")}(${parameterTypes.lengt
|
|
|
3826
3879
|
|
|
3827
3880
|
return useInfiniteQuery({
|
|
3828
3881
|
queryKey: [...${queryKey}, 'infinite', searchParams],
|
|
3829
|
-
queryFn:
|
|
3882
|
+
queryFn: async ({ pageParam = 1, signal }: { pageParam?: number; signal?: AbortSignal }) => {
|
|
3830
3883
|
try {
|
|
3831
3884
|
const result = await ${actionName}(${actionCallParams.replace(queryParamObject, "{ ...searchParams, page: pageParam, limit: searchParams.limit }")})
|
|
3832
3885
|
return result
|
|
3833
3886
|
} catch (error) {
|
|
3834
3887
|
handleActionError(error)
|
|
3835
3888
|
}
|
|
3836
|
-
},
|
|
3889
|
+
},
|
|
3837
3890
|
getNextPageParam: (lastPage: ${returnType}, allPages: ${returnType}[]) => {
|
|
3838
3891
|
if (lastPage?.hasMore || (Array.isArray(lastPage) && lastPage.length === searchParams.limit)) {
|
|
3839
3892
|
return allPages.length + 1
|
|
@@ -3846,7 +3899,6 @@ export function ${hookName.replace("use", "useInfinite")}(${parameterTypes.lengt
|
|
|
3846
3899
|
refetchOnWindowFocus: true,
|
|
3847
3900
|
refetchOnReconnect: true,
|
|
3848
3901
|
refetchOnMount: 'always',
|
|
3849
|
-
initialDataUpdatedAt: initialData ? Date.now() : undefined,
|
|
3850
3902
|
placeholderData: (previousData: ${returnType} | undefined) => previousData,
|
|
3851
3903
|
retry: 3,
|
|
3852
3904
|
initialData: initialData as ${returnType} | undefined,
|
|
@@ -3863,10 +3915,10 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3863
3915
|
|
|
3864
3916
|
return useSuspenseQuery({
|
|
3865
3917
|
queryKey: ${queryKey},
|
|
3866
|
-
queryFn:
|
|
3918
|
+
queryFn: async () => {
|
|
3867
3919
|
const result = await ${actionName}(${actionCallParams})
|
|
3868
3920
|
return result
|
|
3869
|
-
},
|
|
3921
|
+
},
|
|
3870
3922
|
staleTime: ${staleTime},
|
|
3871
3923
|
initialData: initialData as ${returnType} | undefined,
|
|
3872
3924
|
...restOptions
|
|
@@ -3883,14 +3935,14 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3883
3935
|
|
|
3884
3936
|
return useQuery({
|
|
3885
3937
|
queryKey: ${queryKey},
|
|
3886
|
-
queryFn:
|
|
3938
|
+
queryFn: async ({ signal }: { signal?: AbortSignal }) => {
|
|
3887
3939
|
try {
|
|
3888
3940
|
const result = await ${actionName}(${actionCallParams})
|
|
3889
3941
|
return result
|
|
3890
3942
|
} catch (error) {
|
|
3891
3943
|
handleActionError(error)
|
|
3892
3944
|
}
|
|
3893
|
-
},
|
|
3945
|
+
},
|
|
3894
3946
|
staleTime: ${staleTime},
|
|
3895
3947
|
gcTime: ${staleTime * 2}, // React Query v5: gcTime replaces cacheTime
|
|
3896
3948
|
enabled: ${enabledCondition} && (options?.enabled ?? true),
|
|
@@ -3898,7 +3950,6 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3898
3950
|
refetchOnReconnect: true, // Refetch when network reconnects
|
|
3899
3951
|
refetchOnMount: 'always', // Always refetch on mount for fresh data
|
|
3900
3952
|
refetchInterval: options?.refetchInterval, // Optional polling interval
|
|
3901
|
-
initialDataUpdatedAt: initialData ? Date.now() : undefined,
|
|
3902
3953
|
// React Query v5: placeholderData replaces keepPreviousData
|
|
3903
3954
|
placeholderData: (previousData: ${returnType} | undefined) => previousData,
|
|
3904
3955
|
retry: (failureCount: number, error: Error) => {
|
|
@@ -3921,10 +3972,10 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3921
3972
|
|
|
3922
3973
|
return useSuspenseQuery({
|
|
3923
3974
|
queryKey: ${queryKey},
|
|
3924
|
-
queryFn:
|
|
3975
|
+
queryFn: async () => {
|
|
3925
3976
|
const result = await ${actionName}(${actionCallParams})
|
|
3926
3977
|
return result
|
|
3927
|
-
},
|
|
3978
|
+
},
|
|
3928
3979
|
staleTime: ${staleTime},
|
|
3929
3980
|
initialData: initialData as ${returnType} | undefined,
|
|
3930
3981
|
...restOptions
|
|
@@ -3957,8 +4008,6 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3957
4008
|
const relatedQueries = this.findRelatedQueries(endpoint, context);
|
|
3958
4009
|
const invalidationCode = this.buildInvalidationCode(endpoint, relatedQueries, invalidationTags);
|
|
3959
4010
|
const cancelQueriesCode = this.buildCancelQueriesCode(endpoint, relatedQueries);
|
|
3960
|
-
const snapshotCode = this.buildSnapshotCode(endpoint, relatedQueries);
|
|
3961
|
-
const rollbackCode = this.buildRollbackCode(endpoint, relatedQueries);
|
|
3962
4011
|
return `/**
|
|
3963
4012
|
* Optimized mutation hook for ${endpoint.method} ${endpoint.path}
|
|
3964
4013
|
* Features: Optimistic updates, smart invalidation, error handling
|
|
@@ -3968,7 +4017,7 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3968
4017
|
export function ${hookName}(options?: {
|
|
3969
4018
|
onSuccess?: (data: ${outputType}, variables: ${inputType}) => void
|
|
3970
4019
|
onError?: (error: Error, variables: ${inputType}) => void
|
|
3971
|
-
optimisticUpdate?: (variables: ${inputType}) =>
|
|
4020
|
+
optimisticUpdate?: (variables: ${inputType}) => unknown
|
|
3972
4021
|
showToast?: boolean
|
|
3973
4022
|
}) {
|
|
3974
4023
|
const queryClient = useQueryClient()
|
|
@@ -3979,7 +4028,7 @@ export function ${hookName}(options?: {
|
|
|
3979
4028
|
mutationFn: async (variables: ${inputType}): Promise<${outputType}> => {
|
|
3980
4029
|
try {
|
|
3981
4030
|
const result = await ${actionName}(${variablesParam === "undefined" ? "" : "variables"})
|
|
3982
|
-
return result
|
|
4031
|
+
return (result ?? ({} as ${outputType}))
|
|
3983
4032
|
} catch (error) {
|
|
3984
4033
|
handleActionError(error)
|
|
3985
4034
|
}
|
|
@@ -3987,16 +4036,14 @@ export function ${hookName}(options?: {
|
|
|
3987
4036
|
|
|
3988
4037
|
onMutate: async (variables: ${inputType}) => {
|
|
3989
4038
|
${cancelQueriesCode}
|
|
3990
|
-
|
|
3991
|
-
${snapshotCode}
|
|
3992
|
-
|
|
4039
|
+
|
|
3993
4040
|
// Optimistic update (if provided)
|
|
3994
4041
|
if (options?.optimisticUpdate) {
|
|
3995
4042
|
const optimisticValue = options.optimisticUpdate(variables)
|
|
3996
4043
|
setOptimisticData(optimisticValue)
|
|
3997
4044
|
}
|
|
3998
4045
|
|
|
3999
|
-
return {
|
|
4046
|
+
return {}
|
|
4000
4047
|
},
|
|
4001
4048
|
|
|
4002
4049
|
onSuccess: (data, variables) => {
|
|
@@ -4005,17 +4052,11 @@ ${snapshotCode}
|
|
|
4005
4052
|
toast.success('${this.getSuccessMessage(endpoint)}')
|
|
4006
4053
|
}
|
|
4007
4054
|
|
|
4008
|
-
// Invalidate and refetch related queries
|
|
4009
|
-
${invalidationCode}
|
|
4010
|
-
|
|
4011
4055
|
// Custom success handler
|
|
4012
4056
|
options?.onSuccess?.(data, variables)
|
|
4013
4057
|
},
|
|
4014
4058
|
|
|
4015
|
-
onError: (error: Error, variables: ${inputType}
|
|
4016
|
-
// Rollback optimistic update
|
|
4017
|
-
${rollbackCode}
|
|
4018
|
-
|
|
4059
|
+
onError: (error: Error, variables: ${inputType}) => {
|
|
4019
4060
|
// Show error toast
|
|
4020
4061
|
if (options?.showToast !== false) {
|
|
4021
4062
|
toast.error(error.message || '${this.getErrorMessage(endpoint)}')
|
|
@@ -4025,7 +4066,7 @@ ${rollbackCode}
|
|
|
4025
4066
|
options?.onError?.(error as Error, variables)
|
|
4026
4067
|
},
|
|
4027
4068
|
|
|
4028
|
-
onSettled: () => {
|
|
4069
|
+
onSettled: async () => {
|
|
4029
4070
|
// Always refetch after error or success
|
|
4030
4071
|
${invalidationCode}
|
|
4031
4072
|
}
|
|
@@ -4051,100 +4092,81 @@ ${invalidationCode}
|
|
|
4051
4092
|
return [];
|
|
4052
4093
|
}
|
|
4053
4094
|
const relatedQueries = [];
|
|
4054
|
-
const
|
|
4095
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4055
4096
|
const mutationTag = endpoint.tags[0];
|
|
4056
|
-
const
|
|
4097
|
+
const mutationSegments = this.getResourceSegments(endpoint.path);
|
|
4098
|
+
const mutationResource = mutationSegments[0];
|
|
4057
4099
|
context.schema.endpoints.forEach((queryEndpoint) => {
|
|
4058
4100
|
if (queryEndpoint.method !== "GET") return;
|
|
4059
|
-
const
|
|
4101
|
+
const queryId = queryEndpoint.operationId || queryEndpoint.id;
|
|
4102
|
+
if (seen.has(queryId)) return;
|
|
4060
4103
|
const queryTag = queryEndpoint.tags[0];
|
|
4061
|
-
|
|
4104
|
+
const querySegments = this.getResourceSegments(queryEndpoint.path);
|
|
4105
|
+
const queryResource = querySegments[0];
|
|
4106
|
+
if (mutationTag && queryTag === mutationTag) {
|
|
4062
4107
|
relatedQueries.push(queryEndpoint);
|
|
4108
|
+
seen.add(queryId);
|
|
4063
4109
|
return;
|
|
4064
4110
|
}
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
if (baseMatch) {
|
|
4069
|
-
relatedQueries.push(queryEndpoint);
|
|
4070
|
-
}
|
|
4111
|
+
if (mutationResource && queryResource && mutationResource === queryResource) {
|
|
4112
|
+
relatedQueries.push(queryEndpoint);
|
|
4113
|
+
seen.add(queryId);
|
|
4071
4114
|
}
|
|
4072
4115
|
});
|
|
4073
4116
|
return relatedQueries;
|
|
4074
4117
|
}
|
|
4118
|
+
getResourceSegments(path3) {
|
|
4119
|
+
return path3.split("/").filter(Boolean).filter((segment) => segment.toLowerCase() !== "api" && !/^v\d+/i.test(segment));
|
|
4120
|
+
}
|
|
4075
4121
|
/**
|
|
4076
4122
|
* Build invalidation code for related queries
|
|
4077
4123
|
*/
|
|
4078
4124
|
buildInvalidationCode(endpoint, relatedQueries, invalidationTags) {
|
|
4079
|
-
const invalidations =
|
|
4125
|
+
const invalidations = /* @__PURE__ */ new Set();
|
|
4080
4126
|
relatedQueries.forEach((queryEndpoint) => {
|
|
4081
|
-
const
|
|
4082
|
-
invalidations.
|
|
4127
|
+
const queryKeyPrefix = toActionName(queryEndpoint.operationId || queryEndpoint.id);
|
|
4128
|
+
invalidations.add(`queryClient.invalidateQueries({ queryKey: ['${queryKeyPrefix}'] })`);
|
|
4083
4129
|
});
|
|
4084
4130
|
invalidationTags.forEach((tag) => {
|
|
4085
|
-
|
|
4086
|
-
invalidations.push(` queryClient.invalidateQueries({ queryKey: ['${tag}'] })`);
|
|
4087
|
-
}
|
|
4131
|
+
invalidations.add(`queryClient.invalidateQueries({ queryKey: ['${tag}'] })`);
|
|
4088
4132
|
});
|
|
4089
|
-
if (invalidations.
|
|
4133
|
+
if (invalidations.size === 0) {
|
|
4090
4134
|
const inferredKey = this.inferQueryKeyFromPath(endpoint);
|
|
4091
4135
|
if (inferredKey) {
|
|
4092
|
-
invalidations.
|
|
4136
|
+
invalidations.add(`queryClient.invalidateQueries({ queryKey: ${inferredKey} })`);
|
|
4093
4137
|
}
|
|
4094
4138
|
}
|
|
4095
|
-
|
|
4139
|
+
if (invalidations.size === 0) {
|
|
4140
|
+
return " // No specific cache invalidation needed";
|
|
4141
|
+
}
|
|
4142
|
+
if (invalidations.size === 1) {
|
|
4143
|
+
const [statement] = Array.from(invalidations);
|
|
4144
|
+
return ` await ${statement}`;
|
|
4145
|
+
}
|
|
4146
|
+
return ` await Promise.all([
|
|
4147
|
+
${Array.from(invalidations).join(",\n ")}
|
|
4148
|
+
])`;
|
|
4096
4149
|
}
|
|
4097
4150
|
/**
|
|
4098
4151
|
* Build cancel queries code
|
|
4099
4152
|
* Uses query key patterns to cancel all related queries regardless of parameters
|
|
4100
4153
|
*/
|
|
4101
4154
|
buildCancelQueriesCode(endpoint, relatedQueries) {
|
|
4102
|
-
const cancels =
|
|
4155
|
+
const cancels = /* @__PURE__ */ new Set();
|
|
4103
4156
|
relatedQueries.forEach((queryEndpoint) => {
|
|
4104
|
-
const queryKeyPrefix =
|
|
4105
|
-
cancels.
|
|
4157
|
+
const queryKeyPrefix = toActionName(queryEndpoint.operationId || queryEndpoint.id);
|
|
4158
|
+
cancels.add(`queryClient.cancelQueries({ queryKey: ['${queryKeyPrefix}'] })`);
|
|
4106
4159
|
});
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
/**
|
|
4110
|
-
* Build snapshot code for rollback
|
|
4111
|
-
* Note: We can't snapshot specific queries with parameters in onMutate scope
|
|
4112
|
-
* Instead, we'll invalidate all related queries on error
|
|
4113
|
-
*/
|
|
4114
|
-
buildSnapshotCode(endpoint, relatedQueries) {
|
|
4115
|
-
if (relatedQueries.length === 0) {
|
|
4116
|
-
return " // No queries to snapshot";
|
|
4160
|
+
if (cancels.size === 0) {
|
|
4161
|
+
return " // No queries to cancel";
|
|
4117
4162
|
}
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
* Build rollback code
|
|
4122
|
-
*/
|
|
4123
|
-
buildRollbackCode(endpoint, relatedQueries) {
|
|
4124
|
-
if (relatedQueries.length === 0) {
|
|
4125
|
-
return " // No queries to rollback";
|
|
4163
|
+
if (cancels.size === 1) {
|
|
4164
|
+
const [statement] = Array.from(cancels);
|
|
4165
|
+
return ` await ${statement}`;
|
|
4126
4166
|
}
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
const varName = `previous${this.toPascalCase(toActionName(queryEndpoint.operationId || queryEndpoint.id))}`;
|
|
4131
|
-
rollbacks.push(` if (context?.${varName}) {
|
|
4132
|
-
queryClient.setQueryData(${queryKey}, context.${varName})
|
|
4133
|
-
}`);
|
|
4134
|
-
});
|
|
4135
|
-
return rollbacks.join("\n");
|
|
4136
|
-
}
|
|
4137
|
-
/**
|
|
4138
|
-
* Get snapshot return names for context
|
|
4139
|
-
*/
|
|
4140
|
-
getSnapshotReturnNames(relatedQueries) {
|
|
4141
|
-
if (relatedQueries.length === 0) {
|
|
4142
|
-
return "previousData: null";
|
|
4143
|
-
}
|
|
4144
|
-
return relatedQueries.map((queryEndpoint) => {
|
|
4145
|
-
const varName = `previous${this.toPascalCase(toActionName(queryEndpoint.operationId || queryEndpoint.id))}`;
|
|
4146
|
-
return `${varName}`;
|
|
4147
|
-
}).join(", ");
|
|
4167
|
+
return ` await Promise.all([
|
|
4168
|
+
${Array.from(cancels).join(",\n ")}
|
|
4169
|
+
])`;
|
|
4148
4170
|
}
|
|
4149
4171
|
/**
|
|
4150
4172
|
* Infer query key from mutation path
|
|
@@ -4238,11 +4260,11 @@ ${invalidationCode}
|
|
|
4238
4260
|
}
|
|
4239
4261
|
getTypeFromZodSchema(schema) {
|
|
4240
4262
|
if (!schema || typeof schema !== "object") {
|
|
4241
|
-
return "
|
|
4263
|
+
return "unknown";
|
|
4242
4264
|
}
|
|
4243
4265
|
const def = schema._def;
|
|
4244
4266
|
if (!def) {
|
|
4245
|
-
return "
|
|
4267
|
+
return "unknown";
|
|
4246
4268
|
}
|
|
4247
4269
|
switch (def.typeName) {
|
|
4248
4270
|
case "ZodString":
|
|
@@ -4256,7 +4278,7 @@ ${invalidationCode}
|
|
|
4256
4278
|
case "ZodOptional":
|
|
4257
4279
|
return this.getTypeFromZodSchema(def.innerType);
|
|
4258
4280
|
default:
|
|
4259
|
-
return "
|
|
4281
|
+
return "unknown";
|
|
4260
4282
|
}
|
|
4261
4283
|
}
|
|
4262
4284
|
groupEndpointsByTag(endpoints) {
|
|
@@ -4318,7 +4340,7 @@ export function useBridgeQuery<TData = unknown, TError = Error>(
|
|
|
4318
4340
|
export function useBridgeInfiniteQuery<TData = unknown, TError = Error>(
|
|
4319
4341
|
queryKey: QueryKey,
|
|
4320
4342
|
queryFn: QueryFunction<TData, QueryKey>,
|
|
4321
|
-
options?: Partial<UseInfiniteQueryOptions<TData, TError,
|
|
4343
|
+
options?: Partial<UseInfiniteQueryOptions<TData, TError, TData, QueryKey>>
|
|
4322
4344
|
) {
|
|
4323
4345
|
return useInfiniteQuery<TData, TError>({
|
|
4324
4346
|
queryKey,
|
|
@@ -9394,7 +9416,8 @@ var bridgeConfigSchema = z.object({
|
|
|
9394
9416
|
logging: z.boolean().default(true),
|
|
9395
9417
|
validation: z.boolean().default(true),
|
|
9396
9418
|
mocking: z.boolean().default(false),
|
|
9397
|
-
watch: z.boolean().default(false)
|
|
9419
|
+
watch: z.boolean().default(false),
|
|
9420
|
+
hotReload: z.boolean().default(false)
|
|
9398
9421
|
}).optional(),
|
|
9399
9422
|
plugins: z.array(
|
|
9400
9423
|
z.object({
|
|
@@ -9407,6 +9430,7 @@ var bridgeConfigSchema = z.object({
|
|
|
9407
9430
|
typescript: z.boolean().default(true),
|
|
9408
9431
|
strict: z.boolean().default(true),
|
|
9409
9432
|
comments: z.boolean().default(true),
|
|
9433
|
+
documentation: z.boolean().default(true),
|
|
9410
9434
|
examples: z.boolean().default(false),
|
|
9411
9435
|
tests: z.boolean().default(false)
|
|
9412
9436
|
}).optional()
|
|
@@ -9512,12 +9536,14 @@ ${errorMessages}`,
|
|
|
9512
9536
|
logging: true,
|
|
9513
9537
|
validation: true,
|
|
9514
9538
|
mocking: false,
|
|
9515
|
-
watch: false
|
|
9539
|
+
watch: false,
|
|
9540
|
+
hotReload: false
|
|
9516
9541
|
},
|
|
9517
9542
|
generation: {
|
|
9518
9543
|
typescript: true,
|
|
9519
9544
|
strict: true,
|
|
9520
9545
|
comments: true,
|
|
9546
|
+
documentation: true,
|
|
9521
9547
|
examples: false,
|
|
9522
9548
|
tests: false
|
|
9523
9549
|
}
|
|
@@ -9570,5 +9596,5 @@ ${errorMessages}`,
|
|
|
9570
9596
|
};
|
|
9571
9597
|
|
|
9572
9598
|
export { BridgeCore, BridgeError, BridgeLogger, ConfigurationLoader, FileSystemManager, GenerationError, LogLevel, NextJsCodeGenerator, OpenApiSchemaParser, SchemaParseError, ValidationError, VersionChecker, __name, checkAndNotifyUpdates, createBridgeVersionChecker };
|
|
9573
|
-
//# sourceMappingURL=chunk-
|
|
9574
|
-
//# sourceMappingURL=chunk-
|
|
9599
|
+
//# sourceMappingURL=chunk-GHDF3TJA.js.map
|
|
9600
|
+
//# sourceMappingURL=chunk-GHDF3TJA.js.map
|