vite-plugin-server-actions 1.0.0 → 1.0.1
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/package.json +6 -9
- package/src/build-utils.js +8 -8
- package/src/index.js +38 -38
- package/src/openapi.js +17 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-server-actions",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Server actions for Vite - call backend functions directly from your frontend with automatic API generation, TypeScript support, and zero configuration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vite",
|
|
@@ -60,17 +60,16 @@
|
|
|
60
60
|
"example:vue:dev": "npm run dev --prefix examples/vue-todo-app",
|
|
61
61
|
"example:react:build": "npm run build --prefix examples/react-todo-app",
|
|
62
62
|
"example:react:dev": "npm run dev --prefix examples/react-todo-app",
|
|
63
|
-
"format": "npx prettier --write
|
|
64
|
-
"lint": "eslint src/",
|
|
65
|
-
"lint:fix": "eslint src/ --fix",
|
|
63
|
+
"format": "npx prettier --write .",
|
|
66
64
|
"sort": "npx sort-package-json",
|
|
67
65
|
"test": "vitest",
|
|
68
66
|
"test:run": "vitest run",
|
|
69
67
|
"test:e2e": "playwright test",
|
|
70
68
|
"test:e2e:ui": "playwright test --ui",
|
|
71
69
|
"typecheck": "tsc --noEmit",
|
|
72
|
-
"check": "npm run test:run && npm run
|
|
73
|
-
"prepublishOnly": "npm run check"
|
|
70
|
+
"check": "npm run test:run && npm run typecheck",
|
|
71
|
+
"prepublishOnly": "npm run check",
|
|
72
|
+
"deploy:docs": "cd docs && vc --prod"
|
|
74
73
|
},
|
|
75
74
|
"dependencies": {
|
|
76
75
|
"@asteasolutions/zod-to-openapi": "^7.3.4",
|
|
@@ -82,7 +81,6 @@
|
|
|
82
81
|
},
|
|
83
82
|
"devDependencies": {
|
|
84
83
|
"@apidevtools/swagger-parser": "^12.0.0",
|
|
85
|
-
"@eslint/js": "^9.29.0",
|
|
86
84
|
"@playwright/test": "^1.53.1",
|
|
87
85
|
"@stoplight/spectral-core": "^1.20.0",
|
|
88
86
|
"@stoplight/spectral-rulesets": "^1.22.0",
|
|
@@ -90,7 +88,6 @@
|
|
|
90
88
|
"@types/node": "^24.0.3",
|
|
91
89
|
"@types/swagger-ui-express": "^4.1.6",
|
|
92
90
|
"@vitest/runner": "^3.2.4",
|
|
93
|
-
"eslint": "^9.29.0",
|
|
94
91
|
"playwright": "^1.53.1",
|
|
95
92
|
"prettier": "^3.6.0",
|
|
96
93
|
"typescript": "^5.8.3",
|
|
@@ -98,7 +95,7 @@
|
|
|
98
95
|
"vitest": "^3.2.4"
|
|
99
96
|
},
|
|
100
97
|
"peerDependencies": {
|
|
101
|
-
"vite": "^
|
|
98
|
+
"vite": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
|
|
102
99
|
},
|
|
103
100
|
"readme": "README.md"
|
|
104
101
|
}
|
package/src/build-utils.js
CHANGED
|
@@ -66,17 +66,17 @@ const validationMiddleware = createValidationMiddleware({ schemaDiscovery });
|
|
|
66
66
|
|
|
67
67
|
// Register schemas from server actions
|
|
68
68
|
${Array.from(serverFunctions.entries())
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
.map(([moduleName, { functions }]) => {
|
|
70
|
+
return functions
|
|
71
|
+
.map(
|
|
72
|
+
(fn) => `
|
|
73
73
|
if (serverActions.${moduleName}.${fn}.schema) {
|
|
74
74
|
schemaDiscovery.registerSchema('${moduleName}', '${fn}', serverActions.${moduleName}.${fn}.schema);
|
|
75
75
|
}`,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
)
|
|
77
|
+
.join("\n");
|
|
78
|
+
})
|
|
79
|
+
.join("\n")}
|
|
80
80
|
`;
|
|
81
81
|
|
|
82
82
|
// Generate middleware factory
|
package/src/index.js
CHANGED
|
@@ -463,14 +463,14 @@ export default function serverActions(userOptions = {}) {
|
|
|
463
463
|
// Server functions
|
|
464
464
|
// --------------------------------------------------
|
|
465
465
|
${Array.from(serverFunctions.entries())
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
466
|
+
.flatMap(([moduleName, { functions, filePath }]) =>
|
|
467
|
+
functions
|
|
468
|
+
.map((functionName) => {
|
|
469
|
+
const routePath = options.routeTransform(filePath, functionName);
|
|
470
|
+
const middlewareCall = options.validation?.enabled
|
|
471
|
+
? `createContextualValidationMiddleware('${moduleName}', '${functionName}'), `
|
|
472
|
+
: "";
|
|
473
|
+
return `
|
|
474
474
|
app.post('${options.apiPrefix}/${routePath}', ${middlewareCall}async (req, res) => {
|
|
475
475
|
try {
|
|
476
476
|
const result = await serverActions.${moduleName}.${functionName}(...req.body);
|
|
@@ -481,16 +481,16 @@ export default function serverActions(userOptions = {}) {
|
|
|
481
481
|
}
|
|
482
482
|
});
|
|
483
483
|
`;
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
484
|
+
})
|
|
485
|
+
.join("\n")
|
|
486
|
+
.trim(),
|
|
487
|
+
)
|
|
488
|
+
.join("\n")
|
|
489
|
+
.trim()}
|
|
490
490
|
|
|
491
491
|
${
|
|
492
|
-
|
|
493
|
-
|
|
492
|
+
options.openAPI.enabled
|
|
493
|
+
? `
|
|
494
494
|
// OpenAPI endpoints
|
|
495
495
|
// --------------------------------------------------
|
|
496
496
|
app.get('${options.openAPI.specPath}', (req, res) => {
|
|
@@ -498,16 +498,16 @@ export default function serverActions(userOptions = {}) {
|
|
|
498
498
|
});
|
|
499
499
|
|
|
500
500
|
${
|
|
501
|
-
|
|
502
|
-
|
|
501
|
+
options.openAPI.swaggerUI
|
|
502
|
+
? `
|
|
503
503
|
// Swagger UI
|
|
504
504
|
app.use('${options.openAPI.docsPath}', swaggerUi.serve, swaggerUi.setup(openAPISpec));
|
|
505
505
|
`
|
|
506
|
-
|
|
507
|
-
}
|
|
506
|
+
: ""
|
|
507
|
+
}
|
|
508
508
|
`
|
|
509
|
-
|
|
510
|
-
}
|
|
509
|
+
: ""
|
|
510
|
+
}
|
|
511
511
|
|
|
512
512
|
// Start server
|
|
513
513
|
// --------------------------------------------------
|
|
@@ -515,13 +515,13 @@ export default function serverActions(userOptions = {}) {
|
|
|
515
515
|
app.listen(port, () => {
|
|
516
516
|
console.log(\`🚀 Server listening: http://localhost:\${port}\`);
|
|
517
517
|
${
|
|
518
|
-
|
|
519
|
-
|
|
518
|
+
options.openAPI.enabled
|
|
519
|
+
? `
|
|
520
520
|
console.log(\`📖 API Documentation: http://localhost:\${port}${options.openAPI.docsPath}\`);
|
|
521
521
|
console.log(\`📄 OpenAPI Spec: http://localhost:\${port}${options.openAPI.specPath}\`);
|
|
522
522
|
`
|
|
523
|
-
|
|
524
|
-
}
|
|
523
|
+
: ""
|
|
524
|
+
}
|
|
525
525
|
});
|
|
526
526
|
|
|
527
527
|
// List all server functions
|
|
@@ -573,8 +573,8 @@ if (typeof window !== 'undefined') {
|
|
|
573
573
|
console.log("[Vite Server Actions] 🚀 - Executing ${functionName}");
|
|
574
574
|
|
|
575
575
|
${
|
|
576
|
-
|
|
577
|
-
|
|
576
|
+
isDev
|
|
577
|
+
? `
|
|
578
578
|
// Development-only: Mark that we're in a valid proxy context
|
|
579
579
|
if (typeof window !== 'undefined') {
|
|
580
580
|
window.__VITE_SERVER_ACTIONS_PROXY__ = true;
|
|
@@ -588,8 +588,8 @@ if (typeof window !== 'undefined') {
|
|
|
588
588
|
);
|
|
589
589
|
}
|
|
590
590
|
`
|
|
591
|
-
|
|
592
|
-
}
|
|
591
|
+
: ""
|
|
592
|
+
}
|
|
593
593
|
|
|
594
594
|
try {
|
|
595
595
|
const response = await fetch('${options.apiPrefix}/${routePath}', {
|
|
@@ -618,15 +618,15 @@ if (typeof window !== 'undefined') {
|
|
|
618
618
|
const result = await response.json();
|
|
619
619
|
|
|
620
620
|
${
|
|
621
|
-
|
|
622
|
-
|
|
621
|
+
isDev
|
|
622
|
+
? `
|
|
623
623
|
// Development-only: Clear the proxy context
|
|
624
624
|
if (typeof window !== 'undefined') {
|
|
625
625
|
window.__VITE_SERVER_ACTIONS_PROXY__ = false;
|
|
626
626
|
}
|
|
627
627
|
`
|
|
628
|
-
|
|
629
|
-
}
|
|
628
|
+
: ""
|
|
629
|
+
}
|
|
630
630
|
|
|
631
631
|
return result;
|
|
632
632
|
|
|
@@ -634,15 +634,15 @@ if (typeof window !== 'undefined') {
|
|
|
634
634
|
console.error("[Vite Server Actions] ❗ - Network or execution error in ${functionName}:", error.message);
|
|
635
635
|
|
|
636
636
|
${
|
|
637
|
-
|
|
638
|
-
|
|
637
|
+
isDev
|
|
638
|
+
? `
|
|
639
639
|
// Development-only: Clear the proxy context on error
|
|
640
640
|
if (typeof window !== 'undefined') {
|
|
641
641
|
window.__VITE_SERVER_ACTIONS_PROXY__ = false;
|
|
642
642
|
}
|
|
643
643
|
`
|
|
644
|
-
|
|
645
|
-
}
|
|
644
|
+
: ""
|
|
645
|
+
}
|
|
646
646
|
|
|
647
647
|
// Re-throw with more context if it's not already our custom error
|
|
648
648
|
if (!error.details) {
|
package/src/openapi.js
CHANGED
|
@@ -347,23 +347,23 @@ export class EnhancedOpenAPIGenerator extends OpenAPIGenerator {
|
|
|
347
347
|
const { type, description } = param;
|
|
348
348
|
|
|
349
349
|
switch (type.toLowerCase()) {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
350
|
+
case "string":
|
|
351
|
+
return { type: "string", description };
|
|
352
|
+
case "number":
|
|
353
|
+
return { type: "number", description };
|
|
354
|
+
case "boolean":
|
|
355
|
+
return { type: "boolean", description };
|
|
356
|
+
case "object":
|
|
357
|
+
return { type: "object", description };
|
|
358
|
+
case "array":
|
|
359
|
+
return { type: "array", items: { type: "object" }, description };
|
|
360
|
+
default:
|
|
361
|
+
// Handle union types like 'low'|'medium'|'high'
|
|
362
|
+
if (type.includes("|")) {
|
|
363
|
+
const enumValues = type.split("|").map((v) => v.replace(/['"]/g, "").trim());
|
|
364
|
+
return { type: "string", enum: enumValues, description };
|
|
365
|
+
}
|
|
366
|
+
return { type: "object", description };
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
369
|
}
|