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
|
@@ -1550,7 +1550,6 @@ export class BaseApiClient {
|
|
|
1550
1550
|
retryDelay, retryCondition, validateResponse, skipAuth,
|
|
1551
1551
|
responseSchema, requestId, [...this.middleware, ...middleware],
|
|
1552
1552
|
cacheTags, revalidate, connection, updateTag
|
|
1553
|
-
cacheTags, revalidate, connection, updateTag
|
|
1554
1553
|
)
|
|
1555
1554
|
|
|
1556
1555
|
requestCache.set(dedupeKey, requestPromise)
|
|
@@ -1568,7 +1567,6 @@ export class BaseApiClient {
|
|
|
1568
1567
|
retryDelay, retryCondition, validateResponse, skipAuth,
|
|
1569
1568
|
responseSchema, requestId, [...this.middleware, ...middleware],
|
|
1570
1569
|
cacheTags, revalidate, connection, updateTag
|
|
1571
|
-
cacheTags, revalidate, connection, updateTag
|
|
1572
1570
|
)
|
|
1573
1571
|
}
|
|
1574
1572
|
|
|
@@ -2724,7 +2722,9 @@ var SchemaGenerator = class {
|
|
|
2724
2722
|
].join("\n");
|
|
2725
2723
|
let content = this.removeUnusedCode(contentWithImports);
|
|
2726
2724
|
if (!content.includes('import { z } from "zod"') && !content.includes("import { z } from 'zod'")) {
|
|
2727
|
-
content =
|
|
2725
|
+
content = `import { z } from "zod"
|
|
2726
|
+
|
|
2727
|
+
${content}`;
|
|
2728
2728
|
}
|
|
2729
2729
|
return {
|
|
2730
2730
|
path: "schemas/index.ts",
|
|
@@ -3135,6 +3135,166 @@ var ActionGenerator = class {
|
|
|
3135
3135
|
static {
|
|
3136
3136
|
__name(this, "ActionGenerator");
|
|
3137
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
|
+
}
|
|
3138
3298
|
buildImportPath(relativePath) {
|
|
3139
3299
|
const outputDirectory = this.configuration.outputDir || "generated";
|
|
3140
3300
|
const cleanPath = relativePath.startsWith("/") ? relativePath.slice(1) : relativePath;
|
|
@@ -3199,8 +3359,7 @@ var ActionGenerator = class {
|
|
|
3199
3359
|
] : []
|
|
3200
3360
|
].filter(Boolean).join("\n");
|
|
3201
3361
|
const rateLimitSetup = hasRateLimit ? `
|
|
3202
|
-
// Rate limiting setup
|
|
3203
|
-
const redis = new Redis({
|
|
3362
|
+
${this.commentsEnabled ? "// Rate limiting setup\n" : ""}const redis = new Redis({
|
|
3204
3363
|
url: process.env.UPSTASH_REDIS_REST_URL!,
|
|
3205
3364
|
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
|
|
3206
3365
|
})
|
|
@@ -3210,60 +3369,7 @@ const ratelimit = new Ratelimit({
|
|
|
3210
3369
|
limiter: Ratelimit.slidingWindow(10, '1 m'),
|
|
3211
3370
|
analytics: true,
|
|
3212
3371
|
})` : "";
|
|
3213
|
-
const utilityFunctions =
|
|
3214
|
-
// Utility functions for enhanced server actions
|
|
3215
|
-
async function getClientInfo() {
|
|
3216
|
-
const headersList = await headers()
|
|
3217
|
-
const userAgent = headersList.get('user-agent') || 'unknown'
|
|
3218
|
-
const ip = headersList.get('x-forwarded-for') || headersList.get('x-real-ip') || 'unknown'
|
|
3219
|
-
|
|
3220
|
-
return { userAgent, ip }
|
|
3221
|
-
}
|
|
3222
|
-
|
|
3223
|
-
async function validateAndSanitizeInput<T>(schema: z.ZodSchema<T>, input: unknown): Promise<T> {
|
|
3224
|
-
try {
|
|
3225
|
-
return await schema.parseAsync(input)
|
|
3226
|
-
} catch (error) {
|
|
3227
|
-
if (error instanceof z.ZodError) {
|
|
3228
|
-
const errorMessages = error.issues.map(issue => {
|
|
3229
|
-
const path = issue.path.length > 0 ? \`\${issue.path.join('.')}: \` : ''
|
|
3230
|
-
return \`\${path}\${issue.message}\`
|
|
3231
|
-
}).join(', ')
|
|
3232
|
-
throw new ActionError(\`Input validation failed: \${errorMessages}\`, 'VALIDATION_ERROR')
|
|
3233
|
-
}
|
|
3234
|
-
throw new ActionError('Invalid input format', 'VALIDATION_ERROR')
|
|
3235
|
-
}
|
|
3236
|
-
}
|
|
3237
|
-
|
|
3238
|
-
// Enhanced error handling with context
|
|
3239
|
-
class ActionExecutionError extends ActionError {
|
|
3240
|
-
constructor(
|
|
3241
|
-
message: string,
|
|
3242
|
-
public readonly context: {
|
|
3243
|
-
endpoint: string
|
|
3244
|
-
method: string
|
|
3245
|
-
timestamp: number
|
|
3246
|
-
},
|
|
3247
|
-
public readonly originalError?: unknown
|
|
3248
|
-
) {
|
|
3249
|
-
super(message, 'EXECUTION_ERROR')
|
|
3250
|
-
}
|
|
3251
|
-
}
|
|
3252
|
-
|
|
3253
|
-
// Logging utility for server actions
|
|
3254
|
-
async function logActionExecution(
|
|
3255
|
-
action: string,
|
|
3256
|
-
success: boolean,
|
|
3257
|
-
duration: number,
|
|
3258
|
-
context?: Record<string, any>
|
|
3259
|
-
) {
|
|
3260
|
-
if (process.env.NODE_ENV === 'development') {
|
|
3261
|
-
console.log(\`[ACTION] \${action} - \${success ? 'SUCCESS' : 'FAILED'} (\${duration}ms)\`, context)
|
|
3262
|
-
}
|
|
3263
|
-
|
|
3264
|
-
// In production, send to your logging service
|
|
3265
|
-
// await analytics.track('server_action_executed', { action, success, duration, ...context })
|
|
3266
|
-
}`;
|
|
3372
|
+
const utilityFunctions = this.buildUtilityFunctions();
|
|
3267
3373
|
const content = `${imports}
|
|
3268
3374
|
${rateLimitSetup}
|
|
3269
3375
|
${utilityFunctions}
|
|
@@ -3280,8 +3386,8 @@ ${actions}`;
|
|
|
3280
3386
|
}
|
|
3281
3387
|
});
|
|
3282
3388
|
}
|
|
3283
|
-
const
|
|
3284
|
-
${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")}`;
|
|
3285
3391
|
generatedFiles.push({
|
|
3286
3392
|
path: "actions/index.ts",
|
|
3287
3393
|
content: indexContent,
|
|
@@ -3330,54 +3436,48 @@ ${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier
|
|
|
3330
3436
|
body: ${operationName}RequestSchema,
|
|
3331
3437
|
params: ${operationName}ParamsSchema
|
|
3332
3438
|
})`;
|
|
3333
|
-
parameterProcessing =
|
|
3334
|
-
// Validate and sanitize input
|
|
3335
|
-
const { body, params } = await validateAndSanitizeInput(${schemaName}, parsedInput)
|
|
3336
|
-
const validatedBody = body
|
|
3337
|
-
const validatedParams = params as z.infer<typeof ${operationName}ParamsSchema>`;
|
|
3439
|
+
parameterProcessing = this.buildCombinedValidationSnippet(operationName, schemaName);
|
|
3338
3440
|
requestOptionsParams = this.buildRequestOptions(pathParameters, queryParameters, true, true);
|
|
3339
3441
|
} else if (hasRequestBody) {
|
|
3340
3442
|
schemaName = `${operationName}RequestSchema`;
|
|
3341
|
-
parameterProcessing =
|
|
3342
|
-
// Validate and sanitize request body
|
|
3343
|
-
const validatedBody = await validateAndSanitizeInput(${schemaName}, parsedInput)`;
|
|
3443
|
+
parameterProcessing = this.buildBodyValidationSnippet(schemaName);
|
|
3344
3444
|
requestOptionsParams = `body: validatedBody`;
|
|
3345
3445
|
} else if (hasAnyParams) {
|
|
3346
3446
|
schemaName = `${operationName}ParamsSchema`;
|
|
3347
|
-
parameterProcessing =
|
|
3348
|
-
// Validate and sanitize parameters
|
|
3349
|
-
const validatedParams = await validateAndSanitizeInput(${schemaName}, parsedInput) as z.infer<typeof ${operationName}ParamsSchema>`;
|
|
3447
|
+
parameterProcessing = this.buildParamsValidationSnippet(operationName, schemaName);
|
|
3350
3448
|
requestOptionsParams = this.buildRequestOptions(pathParameters, queryParameters, false, true);
|
|
3351
3449
|
} else {
|
|
3352
3450
|
schemaName = "z.void()";
|
|
3353
3451
|
parameterProcessing = "";
|
|
3354
3452
|
requestOptionsParams = "";
|
|
3355
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} }`;
|
|
3356
3458
|
const clientName = requiresAuth || hasRateLimit ? "authActionClient" : "actionClientWithMeta";
|
|
3357
3459
|
const rateLimitCode = hasRateLimit ? `
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
}` : "";
|
|
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
|
+
}` : "";
|
|
3369
3470
|
const revalidationCode = revalidationTags.length > 0 ? revalidationTags.map(
|
|
3370
|
-
(tag) => ` updateTag('${tag}')
|
|
3371
|
-
console.log('Updated tag: ${tag}')`
|
|
3471
|
+
(tag) => ` updateTag('${tag}')${this.loggingEnabled ? `
|
|
3472
|
+
console.log('Updated tag: ${tag}')` : ""}`
|
|
3372
3473
|
).join("\n") : "";
|
|
3373
3474
|
const kebabActionName = actionName.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
|
|
3374
3475
|
if (isQuery) {
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
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(
|
|
3381
3481
|
${clientName}
|
|
3382
3482
|
.metadata({
|
|
3383
3483
|
name: "${kebabActionName}",
|
|
@@ -3385,7 +3485,7 @@ export const ${actionName} = cache(
|
|
|
3385
3485
|
rateLimit: { requests: ${endpoint.metadata.rateLimit?.requests || 10}, window: "${endpoint.metadata.rateLimit?.window || "1m"}" }` : ""}
|
|
3386
3486
|
})
|
|
3387
3487
|
.schema(${schemaName})
|
|
3388
|
-
.action(async ({ parsedInput, ctx }:
|
|
3488
|
+
.action(async ({ parsedInput, ctx }: ${actionArgsType}) => {
|
|
3389
3489
|
const startTime = Date.now()
|
|
3390
3490
|
|
|
3391
3491
|
try {${rateLimitCode}${parameterProcessing}
|
|
@@ -3400,23 +3500,11 @@ export const ${actionName} = cache(
|
|
|
3400
3500
|
}
|
|
3401
3501
|
})
|
|
3402
3502
|
|
|
3403
|
-
|
|
3404
|
-
const duration = Date.now() - startTime
|
|
3405
|
-
await logActionExecution('${actionName}', true, duration, {
|
|
3406
|
-
method: '${endpoint.method}',
|
|
3407
|
-
path: '${endpoint.path}'
|
|
3408
|
-
})
|
|
3503
|
+
${this.buildSuccessLoggingBlock(actionName, endpoint, 8)}
|
|
3409
3504
|
|
|
3410
3505
|
return response.data
|
|
3411
3506
|
} catch (error) {
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
// Enhanced error logging
|
|
3415
|
-
await logActionExecution('${actionName}', false, duration, {
|
|
3416
|
-
method: '${endpoint.method}',
|
|
3417
|
-
path: '${endpoint.path}',
|
|
3418
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
3419
|
-
})
|
|
3507
|
+
${this.buildErrorLoggingBlock(actionName, endpoint, 8)}
|
|
3420
3508
|
|
|
3421
3509
|
// Throw enhanced error with context
|
|
3422
3510
|
throw new ActionExecutionError(
|
|
@@ -3433,50 +3521,37 @@ export const ${actionName} = cache(
|
|
|
3433
3521
|
)`;
|
|
3434
3522
|
}
|
|
3435
3523
|
const redirectCode = `
|
|
3436
|
-
|
|
3437
|
-
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')) {
|
|
3438
3525
|
const location = response.headers.get('location')!
|
|
3439
3526
|
redirect(location)
|
|
3440
3527
|
}`;
|
|
3441
3528
|
const streamingCode = `
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
// Process streaming response
|
|
3445
|
-
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
|
|
3446
3531
|
}`;
|
|
3447
3532
|
const fileUploadCode = hasFileUpload ? uploadStrategy === "external" && uploadProvider === "vercel-blob" ? `
|
|
3448
|
-
|
|
3449
|
-
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) {
|
|
3450
3534
|
const file = (validatedBody as any).file as File
|
|
3451
3535
|
const blob = await put(file.name, file, { access: 'public' })
|
|
3452
3536
|
Object.assign(validatedBody, { fileUrl: blob.url })
|
|
3453
3537
|
}` : uploadStrategy === "external" && uploadProvider === "uploadthing" ? `
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
const file = (validatedBody as any).file as File
|
|
3465
|
-
// Process file with compression and validation if enabled
|
|
3466
|
-
}` : "";
|
|
3467
|
-
return `/**
|
|
3468
|
-
* ${endpoint.summary || endpoint.description || `${endpoint.method} ${endpoint.path}`}
|
|
3469
|
-
* @generated from ${endpoint.method} ${endpoint.path}
|
|
3470
|
-
* Features: Input validation, revalidation, error handling
|
|
3471
|
-
*/
|
|
3472
|
-
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}
|
|
3473
3548
|
.metadata({
|
|
3474
3549
|
name: "${kebabActionName}",
|
|
3475
3550
|
requiresAuth: ${requiresAuth}${hasRateLimit ? `,
|
|
3476
3551
|
rateLimit: { requests: ${endpoint.metadata.rateLimit?.requests || 10}, window: "${endpoint.metadata.rateLimit?.window || "1m"}" }` : ""}
|
|
3477
3552
|
})
|
|
3478
3553
|
.schema(${schemaName})
|
|
3479
|
-
.action(async ({ parsedInput, ctx }:
|
|
3554
|
+
.action(async ({ parsedInput, ctx }: ${actionArgsType}) => {
|
|
3480
3555
|
const startTime = Date.now()
|
|
3481
3556
|
|
|
3482
3557
|
try {${rateLimitCode}${parameterProcessing}${fileUploadCode}
|
|
@@ -3491,33 +3566,13 @@ export const ${actionName} = ${clientName}
|
|
|
3491
3566
|
}
|
|
3492
3567
|
})${streamingCode}${redirectCode}
|
|
3493
3568
|
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
// Background tasks (Next.js 15 feature)
|
|
3498
|
-
${isStreaming ? `after(async () => {
|
|
3499
|
-
// Perform background tasks after response is sent
|
|
3500
|
-
await logActionExecution('${actionName}', true, Date.now() - startTime, {
|
|
3501
|
-
method: '${endpoint.method}',
|
|
3502
|
-
path: '${endpoint.path}'
|
|
3503
|
-
})
|
|
3504
|
-
})` : `// Log successful execution
|
|
3505
|
-
const duration = Date.now() - startTime
|
|
3506
|
-
await logActionExecution('${actionName}', true, duration, {
|
|
3507
|
-
method: '${endpoint.method}',
|
|
3508
|
-
path: '${endpoint.path}'
|
|
3509
|
-
})`}
|
|
3569
|
+
${revalidationCode ? `${this.commentLine("Revalidate cache after successful mutation", 6)}${revalidationCode}
|
|
3570
|
+
` : ""}
|
|
3571
|
+
${this.buildSuccessLoggingBlock(actionName, endpoint, 6, isStreaming)}
|
|
3510
3572
|
|
|
3511
3573
|
return response.data
|
|
3512
3574
|
} catch (error) {
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
// Enhanced error logging
|
|
3516
|
-
await logActionExecution('${actionName}', false, duration, {
|
|
3517
|
-
method: '${endpoint.method}',
|
|
3518
|
-
path: '${endpoint.path}',
|
|
3519
|
-
error: error instanceof Error ? error.message : 'Unknown error'
|
|
3520
|
-
})
|
|
3575
|
+
${this.buildErrorLoggingBlock(actionName, endpoint, 6)}
|
|
3521
3576
|
|
|
3522
3577
|
// Throw enhanced error with context
|
|
3523
3578
|
throw new ActionExecutionError(
|
|
@@ -3676,7 +3731,6 @@ var HookGenerator = class {
|
|
|
3676
3731
|
if (hasInfiniteQueries) reactQueryImports.push("useInfiniteQuery");
|
|
3677
3732
|
const reactImports = [];
|
|
3678
3733
|
if (hasMutations) reactImports.push("useOptimistic", "useTransition");
|
|
3679
|
-
if (hasQueries) reactImports.push("useCallback");
|
|
3680
3734
|
const imports = [
|
|
3681
3735
|
"'use client'",
|
|
3682
3736
|
"",
|
|
@@ -3788,19 +3842,19 @@ ${Object.keys(endpointsByTag).map((tag) => `export * from './${toValidIdentifier
|
|
|
3788
3842
|
* @returns useQuery result with data of type ${returnType}
|
|
3789
3843
|
*/
|
|
3790
3844
|
export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join(", ")}, ` : ""}options?: ${optionsType}) {
|
|
3791
|
-
const [searchParams
|
|
3845
|
+
const [searchParams] = useQueryStates(searchParamsParser)
|
|
3792
3846
|
const { initialData, ...restOptions } = options ?? {}
|
|
3793
3847
|
|
|
3794
3848
|
return useQuery({
|
|
3795
3849
|
queryKey: [...${queryKey}, searchParams],
|
|
3796
|
-
queryFn:
|
|
3850
|
+
queryFn: async ({ signal }: { signal?: AbortSignal }) => {
|
|
3797
3851
|
try {
|
|
3798
3852
|
const result = await ${actionName}(${actionCallParams.replace(queryParamObject, "{ ...searchParams }")})
|
|
3799
3853
|
return result
|
|
3800
3854
|
} catch (error) {
|
|
3801
3855
|
handleActionError(error)
|
|
3802
3856
|
}
|
|
3803
|
-
},
|
|
3857
|
+
},
|
|
3804
3858
|
staleTime: ${staleTime},
|
|
3805
3859
|
gcTime: ${staleTime * 2}, // React Query v5: gcTime replaces cacheTime
|
|
3806
3860
|
enabled: ${enabledCondition} && (options?.enabled ?? true),
|
|
@@ -3808,7 +3862,6 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3808
3862
|
refetchOnReconnect: true, // Refetch when network reconnects
|
|
3809
3863
|
refetchOnMount: 'always', // Always refetch on mount for fresh data
|
|
3810
3864
|
refetchInterval: options?.refetchInterval, // Optional polling interval
|
|
3811
|
-
initialDataUpdatedAt: initialData ? Date.now() : undefined,
|
|
3812
3865
|
// React Query v5: placeholderData replaces keepPreviousData
|
|
3813
3866
|
placeholderData: (previousData: ${returnType} | undefined) => previousData,
|
|
3814
3867
|
retry: (failureCount: number, error: Error) => {
|
|
@@ -3832,14 +3885,14 @@ export function ${hookName.replace("use", "useInfinite")}(${parameterTypes.lengt
|
|
|
3832
3885
|
|
|
3833
3886
|
return useInfiniteQuery({
|
|
3834
3887
|
queryKey: [...${queryKey}, 'infinite', searchParams],
|
|
3835
|
-
queryFn:
|
|
3888
|
+
queryFn: async ({ pageParam = 1, signal }: { pageParam?: number; signal?: AbortSignal }) => {
|
|
3836
3889
|
try {
|
|
3837
3890
|
const result = await ${actionName}(${actionCallParams.replace(queryParamObject, "{ ...searchParams, page: pageParam, limit: searchParams.limit }")})
|
|
3838
3891
|
return result
|
|
3839
3892
|
} catch (error) {
|
|
3840
3893
|
handleActionError(error)
|
|
3841
3894
|
}
|
|
3842
|
-
},
|
|
3895
|
+
},
|
|
3843
3896
|
getNextPageParam: (lastPage: ${returnType}, allPages: ${returnType}[]) => {
|
|
3844
3897
|
if (lastPage?.hasMore || (Array.isArray(lastPage) && lastPage.length === searchParams.limit)) {
|
|
3845
3898
|
return allPages.length + 1
|
|
@@ -3852,7 +3905,6 @@ export function ${hookName.replace("use", "useInfinite")}(${parameterTypes.lengt
|
|
|
3852
3905
|
refetchOnWindowFocus: true,
|
|
3853
3906
|
refetchOnReconnect: true,
|
|
3854
3907
|
refetchOnMount: 'always',
|
|
3855
|
-
initialDataUpdatedAt: initialData ? Date.now() : undefined,
|
|
3856
3908
|
placeholderData: (previousData: ${returnType} | undefined) => previousData,
|
|
3857
3909
|
retry: 3,
|
|
3858
3910
|
initialData: initialData as ${returnType} | undefined,
|
|
@@ -3869,10 +3921,10 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3869
3921
|
|
|
3870
3922
|
return useSuspenseQuery({
|
|
3871
3923
|
queryKey: ${queryKey},
|
|
3872
|
-
queryFn:
|
|
3924
|
+
queryFn: async () => {
|
|
3873
3925
|
const result = await ${actionName}(${actionCallParams})
|
|
3874
3926
|
return result
|
|
3875
|
-
},
|
|
3927
|
+
},
|
|
3876
3928
|
staleTime: ${staleTime},
|
|
3877
3929
|
initialData: initialData as ${returnType} | undefined,
|
|
3878
3930
|
...restOptions
|
|
@@ -3889,14 +3941,14 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3889
3941
|
|
|
3890
3942
|
return useQuery({
|
|
3891
3943
|
queryKey: ${queryKey},
|
|
3892
|
-
queryFn:
|
|
3944
|
+
queryFn: async ({ signal }: { signal?: AbortSignal }) => {
|
|
3893
3945
|
try {
|
|
3894
3946
|
const result = await ${actionName}(${actionCallParams})
|
|
3895
3947
|
return result
|
|
3896
3948
|
} catch (error) {
|
|
3897
3949
|
handleActionError(error)
|
|
3898
3950
|
}
|
|
3899
|
-
},
|
|
3951
|
+
},
|
|
3900
3952
|
staleTime: ${staleTime},
|
|
3901
3953
|
gcTime: ${staleTime * 2}, // React Query v5: gcTime replaces cacheTime
|
|
3902
3954
|
enabled: ${enabledCondition} && (options?.enabled ?? true),
|
|
@@ -3904,7 +3956,6 @@ export function ${hookName}(${parameterTypes.length > 0 ? `${parameterTypes.join
|
|
|
3904
3956
|
refetchOnReconnect: true, // Refetch when network reconnects
|
|
3905
3957
|
refetchOnMount: 'always', // Always refetch on mount for fresh data
|
|
3906
3958
|
refetchInterval: options?.refetchInterval, // Optional polling interval
|
|
3907
|
-
initialDataUpdatedAt: initialData ? Date.now() : undefined,
|
|
3908
3959
|
// React Query v5: placeholderData replaces keepPreviousData
|
|
3909
3960
|
placeholderData: (previousData: ${returnType} | undefined) => previousData,
|
|
3910
3961
|
retry: (failureCount: number, error: Error) => {
|
|
@@ -3927,10 +3978,10 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3927
3978
|
|
|
3928
3979
|
return useSuspenseQuery({
|
|
3929
3980
|
queryKey: ${queryKey},
|
|
3930
|
-
queryFn:
|
|
3981
|
+
queryFn: async () => {
|
|
3931
3982
|
const result = await ${actionName}(${actionCallParams})
|
|
3932
3983
|
return result
|
|
3933
|
-
},
|
|
3984
|
+
},
|
|
3934
3985
|
staleTime: ${staleTime},
|
|
3935
3986
|
initialData: initialData as ${returnType} | undefined,
|
|
3936
3987
|
...restOptions
|
|
@@ -3963,8 +4014,6 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3963
4014
|
const relatedQueries = this.findRelatedQueries(endpoint, context);
|
|
3964
4015
|
const invalidationCode = this.buildInvalidationCode(endpoint, relatedQueries, invalidationTags);
|
|
3965
4016
|
const cancelQueriesCode = this.buildCancelQueriesCode(endpoint, relatedQueries);
|
|
3966
|
-
const snapshotCode = this.buildSnapshotCode(endpoint, relatedQueries);
|
|
3967
|
-
const rollbackCode = this.buildRollbackCode(endpoint, relatedQueries);
|
|
3968
4017
|
return `/**
|
|
3969
4018
|
* Optimized mutation hook for ${endpoint.method} ${endpoint.path}
|
|
3970
4019
|
* Features: Optimistic updates, smart invalidation, error handling
|
|
@@ -3974,7 +4023,7 @@ export function ${hookName.replace("use", "useSuspense")}(${parameterTypes.lengt
|
|
|
3974
4023
|
export function ${hookName}(options?: {
|
|
3975
4024
|
onSuccess?: (data: ${outputType}, variables: ${inputType}) => void
|
|
3976
4025
|
onError?: (error: Error, variables: ${inputType}) => void
|
|
3977
|
-
optimisticUpdate?: (variables: ${inputType}) =>
|
|
4026
|
+
optimisticUpdate?: (variables: ${inputType}) => unknown
|
|
3978
4027
|
showToast?: boolean
|
|
3979
4028
|
}) {
|
|
3980
4029
|
const queryClient = useQueryClient()
|
|
@@ -3985,7 +4034,7 @@ export function ${hookName}(options?: {
|
|
|
3985
4034
|
mutationFn: async (variables: ${inputType}): Promise<${outputType}> => {
|
|
3986
4035
|
try {
|
|
3987
4036
|
const result = await ${actionName}(${variablesParam === "undefined" ? "" : "variables"})
|
|
3988
|
-
return result
|
|
4037
|
+
return (result ?? ({} as ${outputType}))
|
|
3989
4038
|
} catch (error) {
|
|
3990
4039
|
handleActionError(error)
|
|
3991
4040
|
}
|
|
@@ -3993,16 +4042,14 @@ export function ${hookName}(options?: {
|
|
|
3993
4042
|
|
|
3994
4043
|
onMutate: async (variables: ${inputType}) => {
|
|
3995
4044
|
${cancelQueriesCode}
|
|
3996
|
-
|
|
3997
|
-
${snapshotCode}
|
|
3998
|
-
|
|
4045
|
+
|
|
3999
4046
|
// Optimistic update (if provided)
|
|
4000
4047
|
if (options?.optimisticUpdate) {
|
|
4001
4048
|
const optimisticValue = options.optimisticUpdate(variables)
|
|
4002
4049
|
setOptimisticData(optimisticValue)
|
|
4003
4050
|
}
|
|
4004
4051
|
|
|
4005
|
-
return {
|
|
4052
|
+
return {}
|
|
4006
4053
|
},
|
|
4007
4054
|
|
|
4008
4055
|
onSuccess: (data, variables) => {
|
|
@@ -4011,17 +4058,11 @@ ${snapshotCode}
|
|
|
4011
4058
|
toast.success('${this.getSuccessMessage(endpoint)}')
|
|
4012
4059
|
}
|
|
4013
4060
|
|
|
4014
|
-
// Invalidate and refetch related queries
|
|
4015
|
-
${invalidationCode}
|
|
4016
|
-
|
|
4017
4061
|
// Custom success handler
|
|
4018
4062
|
options?.onSuccess?.(data, variables)
|
|
4019
4063
|
},
|
|
4020
4064
|
|
|
4021
|
-
onError: (error: Error, variables: ${inputType}
|
|
4022
|
-
// Rollback optimistic update
|
|
4023
|
-
${rollbackCode}
|
|
4024
|
-
|
|
4065
|
+
onError: (error: Error, variables: ${inputType}) => {
|
|
4025
4066
|
// Show error toast
|
|
4026
4067
|
if (options?.showToast !== false) {
|
|
4027
4068
|
toast.error(error.message || '${this.getErrorMessage(endpoint)}')
|
|
@@ -4031,7 +4072,7 @@ ${rollbackCode}
|
|
|
4031
4072
|
options?.onError?.(error as Error, variables)
|
|
4032
4073
|
},
|
|
4033
4074
|
|
|
4034
|
-
onSettled: () => {
|
|
4075
|
+
onSettled: async () => {
|
|
4035
4076
|
// Always refetch after error or success
|
|
4036
4077
|
${invalidationCode}
|
|
4037
4078
|
}
|
|
@@ -4057,100 +4098,81 @@ ${invalidationCode}
|
|
|
4057
4098
|
return [];
|
|
4058
4099
|
}
|
|
4059
4100
|
const relatedQueries = [];
|
|
4060
|
-
const
|
|
4101
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4061
4102
|
const mutationTag = endpoint.tags[0];
|
|
4062
|
-
const
|
|
4103
|
+
const mutationSegments = this.getResourceSegments(endpoint.path);
|
|
4104
|
+
const mutationResource = mutationSegments[0];
|
|
4063
4105
|
context.schema.endpoints.forEach((queryEndpoint) => {
|
|
4064
4106
|
if (queryEndpoint.method !== "GET") return;
|
|
4065
|
-
const
|
|
4107
|
+
const queryId = queryEndpoint.operationId || queryEndpoint.id;
|
|
4108
|
+
if (seen.has(queryId)) return;
|
|
4066
4109
|
const queryTag = queryEndpoint.tags[0];
|
|
4067
|
-
|
|
4110
|
+
const querySegments = this.getResourceSegments(queryEndpoint.path);
|
|
4111
|
+
const queryResource = querySegments[0];
|
|
4112
|
+
if (mutationTag && queryTag === mutationTag) {
|
|
4068
4113
|
relatedQueries.push(queryEndpoint);
|
|
4114
|
+
seen.add(queryId);
|
|
4069
4115
|
return;
|
|
4070
4116
|
}
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
if (baseMatch) {
|
|
4075
|
-
relatedQueries.push(queryEndpoint);
|
|
4076
|
-
}
|
|
4117
|
+
if (mutationResource && queryResource && mutationResource === queryResource) {
|
|
4118
|
+
relatedQueries.push(queryEndpoint);
|
|
4119
|
+
seen.add(queryId);
|
|
4077
4120
|
}
|
|
4078
4121
|
});
|
|
4079
4122
|
return relatedQueries;
|
|
4080
4123
|
}
|
|
4124
|
+
getResourceSegments(path3) {
|
|
4125
|
+
return path3.split("/").filter(Boolean).filter((segment) => segment.toLowerCase() !== "api" && !/^v\d+/i.test(segment));
|
|
4126
|
+
}
|
|
4081
4127
|
/**
|
|
4082
4128
|
* Build invalidation code for related queries
|
|
4083
4129
|
*/
|
|
4084
4130
|
buildInvalidationCode(endpoint, relatedQueries, invalidationTags) {
|
|
4085
|
-
const invalidations =
|
|
4131
|
+
const invalidations = /* @__PURE__ */ new Set();
|
|
4086
4132
|
relatedQueries.forEach((queryEndpoint) => {
|
|
4087
|
-
const
|
|
4088
|
-
invalidations.
|
|
4133
|
+
const queryKeyPrefix = toActionName(queryEndpoint.operationId || queryEndpoint.id);
|
|
4134
|
+
invalidations.add(`queryClient.invalidateQueries({ queryKey: ['${queryKeyPrefix}'] })`);
|
|
4089
4135
|
});
|
|
4090
4136
|
invalidationTags.forEach((tag) => {
|
|
4091
|
-
|
|
4092
|
-
invalidations.push(` queryClient.invalidateQueries({ queryKey: ['${tag}'] })`);
|
|
4093
|
-
}
|
|
4137
|
+
invalidations.add(`queryClient.invalidateQueries({ queryKey: ['${tag}'] })`);
|
|
4094
4138
|
});
|
|
4095
|
-
if (invalidations.
|
|
4139
|
+
if (invalidations.size === 0) {
|
|
4096
4140
|
const inferredKey = this.inferQueryKeyFromPath(endpoint);
|
|
4097
4141
|
if (inferredKey) {
|
|
4098
|
-
invalidations.
|
|
4142
|
+
invalidations.add(`queryClient.invalidateQueries({ queryKey: ${inferredKey} })`);
|
|
4099
4143
|
}
|
|
4100
4144
|
}
|
|
4101
|
-
|
|
4145
|
+
if (invalidations.size === 0) {
|
|
4146
|
+
return " // No specific cache invalidation needed";
|
|
4147
|
+
}
|
|
4148
|
+
if (invalidations.size === 1) {
|
|
4149
|
+
const [statement] = Array.from(invalidations);
|
|
4150
|
+
return ` await ${statement}`;
|
|
4151
|
+
}
|
|
4152
|
+
return ` await Promise.all([
|
|
4153
|
+
${Array.from(invalidations).join(",\n ")}
|
|
4154
|
+
])`;
|
|
4102
4155
|
}
|
|
4103
4156
|
/**
|
|
4104
4157
|
* Build cancel queries code
|
|
4105
4158
|
* Uses query key patterns to cancel all related queries regardless of parameters
|
|
4106
4159
|
*/
|
|
4107
4160
|
buildCancelQueriesCode(endpoint, relatedQueries) {
|
|
4108
|
-
const cancels =
|
|
4161
|
+
const cancels = /* @__PURE__ */ new Set();
|
|
4109
4162
|
relatedQueries.forEach((queryEndpoint) => {
|
|
4110
|
-
const queryKeyPrefix =
|
|
4111
|
-
cancels.
|
|
4163
|
+
const queryKeyPrefix = toActionName(queryEndpoint.operationId || queryEndpoint.id);
|
|
4164
|
+
cancels.add(`queryClient.cancelQueries({ queryKey: ['${queryKeyPrefix}'] })`);
|
|
4112
4165
|
});
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
/**
|
|
4116
|
-
* Build snapshot code for rollback
|
|
4117
|
-
* Note: We can't snapshot specific queries with parameters in onMutate scope
|
|
4118
|
-
* Instead, we'll invalidate all related queries on error
|
|
4119
|
-
*/
|
|
4120
|
-
buildSnapshotCode(endpoint, relatedQueries) {
|
|
4121
|
-
if (relatedQueries.length === 0) {
|
|
4122
|
-
return " // No queries to snapshot";
|
|
4166
|
+
if (cancels.size === 0) {
|
|
4167
|
+
return " // No queries to cancel";
|
|
4123
4168
|
}
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
* Build rollback code
|
|
4128
|
-
*/
|
|
4129
|
-
buildRollbackCode(endpoint, relatedQueries) {
|
|
4130
|
-
if (relatedQueries.length === 0) {
|
|
4131
|
-
return " // No queries to rollback";
|
|
4169
|
+
if (cancels.size === 1) {
|
|
4170
|
+
const [statement] = Array.from(cancels);
|
|
4171
|
+
return ` await ${statement}`;
|
|
4132
4172
|
}
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
const varName = `previous${this.toPascalCase(toActionName(queryEndpoint.operationId || queryEndpoint.id))}`;
|
|
4137
|
-
rollbacks.push(` if (context?.${varName}) {
|
|
4138
|
-
queryClient.setQueryData(${queryKey}, context.${varName})
|
|
4139
|
-
}`);
|
|
4140
|
-
});
|
|
4141
|
-
return rollbacks.join("\n");
|
|
4142
|
-
}
|
|
4143
|
-
/**
|
|
4144
|
-
* Get snapshot return names for context
|
|
4145
|
-
*/
|
|
4146
|
-
getSnapshotReturnNames(relatedQueries) {
|
|
4147
|
-
if (relatedQueries.length === 0) {
|
|
4148
|
-
return "previousData: null";
|
|
4149
|
-
}
|
|
4150
|
-
return relatedQueries.map((queryEndpoint) => {
|
|
4151
|
-
const varName = `previous${this.toPascalCase(toActionName(queryEndpoint.operationId || queryEndpoint.id))}`;
|
|
4152
|
-
return `${varName}`;
|
|
4153
|
-
}).join(", ");
|
|
4173
|
+
return ` await Promise.all([
|
|
4174
|
+
${Array.from(cancels).join(",\n ")}
|
|
4175
|
+
])`;
|
|
4154
4176
|
}
|
|
4155
4177
|
/**
|
|
4156
4178
|
* Infer query key from mutation path
|
|
@@ -4244,11 +4266,11 @@ ${invalidationCode}
|
|
|
4244
4266
|
}
|
|
4245
4267
|
getTypeFromZodSchema(schema) {
|
|
4246
4268
|
if (!schema || typeof schema !== "object") {
|
|
4247
|
-
return "
|
|
4269
|
+
return "unknown";
|
|
4248
4270
|
}
|
|
4249
4271
|
const def = schema._def;
|
|
4250
4272
|
if (!def) {
|
|
4251
|
-
return "
|
|
4273
|
+
return "unknown";
|
|
4252
4274
|
}
|
|
4253
4275
|
switch (def.typeName) {
|
|
4254
4276
|
case "ZodString":
|
|
@@ -4262,7 +4284,7 @@ ${invalidationCode}
|
|
|
4262
4284
|
case "ZodOptional":
|
|
4263
4285
|
return this.getTypeFromZodSchema(def.innerType);
|
|
4264
4286
|
default:
|
|
4265
|
-
return "
|
|
4287
|
+
return "unknown";
|
|
4266
4288
|
}
|
|
4267
4289
|
}
|
|
4268
4290
|
groupEndpointsByTag(endpoints) {
|
|
@@ -4324,7 +4346,7 @@ export function useBridgeQuery<TData = unknown, TError = Error>(
|
|
|
4324
4346
|
export function useBridgeInfiniteQuery<TData = unknown, TError = Error>(
|
|
4325
4347
|
queryKey: QueryKey,
|
|
4326
4348
|
queryFn: QueryFunction<TData, QueryKey>,
|
|
4327
|
-
options?: Partial<UseInfiniteQueryOptions<TData, TError,
|
|
4349
|
+
options?: Partial<UseInfiniteQueryOptions<TData, TError, TData, QueryKey>>
|
|
4328
4350
|
) {
|
|
4329
4351
|
return useInfiniteQuery<TData, TError>({
|
|
4330
4352
|
queryKey,
|
|
@@ -9400,7 +9422,8 @@ var bridgeConfigSchema = zod.z.object({
|
|
|
9400
9422
|
logging: zod.z.boolean().default(true),
|
|
9401
9423
|
validation: zod.z.boolean().default(true),
|
|
9402
9424
|
mocking: zod.z.boolean().default(false),
|
|
9403
|
-
watch: zod.z.boolean().default(false)
|
|
9425
|
+
watch: zod.z.boolean().default(false),
|
|
9426
|
+
hotReload: zod.z.boolean().default(false)
|
|
9404
9427
|
}).optional(),
|
|
9405
9428
|
plugins: zod.z.array(
|
|
9406
9429
|
zod.z.object({
|
|
@@ -9413,6 +9436,7 @@ var bridgeConfigSchema = zod.z.object({
|
|
|
9413
9436
|
typescript: zod.z.boolean().default(true),
|
|
9414
9437
|
strict: zod.z.boolean().default(true),
|
|
9415
9438
|
comments: zod.z.boolean().default(true),
|
|
9439
|
+
documentation: zod.z.boolean().default(true),
|
|
9416
9440
|
examples: zod.z.boolean().default(false),
|
|
9417
9441
|
tests: zod.z.boolean().default(false)
|
|
9418
9442
|
}).optional()
|
|
@@ -9518,12 +9542,14 @@ ${errorMessages}`,
|
|
|
9518
9542
|
logging: true,
|
|
9519
9543
|
validation: true,
|
|
9520
9544
|
mocking: false,
|
|
9521
|
-
watch: false
|
|
9545
|
+
watch: false,
|
|
9546
|
+
hotReload: false
|
|
9522
9547
|
},
|
|
9523
9548
|
generation: {
|
|
9524
9549
|
typescript: true,
|
|
9525
9550
|
strict: true,
|
|
9526
9551
|
comments: true,
|
|
9552
|
+
documentation: true,
|
|
9527
9553
|
examples: false,
|
|
9528
9554
|
tests: false
|
|
9529
9555
|
}
|
|
@@ -9590,5 +9616,5 @@ exports.VersionChecker = VersionChecker;
|
|
|
9590
9616
|
exports.__name = __name;
|
|
9591
9617
|
exports.checkAndNotifyUpdates = checkAndNotifyUpdates;
|
|
9592
9618
|
exports.createBridgeVersionChecker = createBridgeVersionChecker;
|
|
9593
|
-
//# sourceMappingURL=chunk-
|
|
9594
|
-
//# sourceMappingURL=chunk-
|
|
9619
|
+
//# sourceMappingURL=chunk-PZXEJ43S.cjs.map
|
|
9620
|
+
//# sourceMappingURL=chunk-PZXEJ43S.cjs.map
|