@veloxts/web 0.6.31 → 0.6.51
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/CHANGELOG.md +224 -0
- package/dist/actions/action.d.ts +53 -1
- package/dist/actions/action.js +43 -7
- package/dist/actions/auth-bridge.d.ts +219 -0
- package/dist/actions/auth-bridge.js +282 -0
- package/dist/actions/bridge.d.ts +6 -1
- package/dist/actions/bridge.js +17 -1
- package/dist/actions/handler.js +3 -3
- package/dist/actions/index.d.ts +4 -0
- package/dist/actions/index.js +2 -0
- package/dist/actions/types.d.ts +67 -41
- package/dist/actions/validated.d.ts +226 -0
- package/dist/actions/validated.js +628 -0
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js +1 -1
- package/dist/app/create-app.js +61 -1
- package/dist/app/index.d.ts +21 -0
- package/dist/app/index.js +21 -0
- package/dist/client/index.d.ts +14 -3
- package/dist/client/index.js +14 -3
- package/dist/client/use-action.d.ts +1 -1
- package/dist/client/use-form-action.d.ts +1 -1
- package/dist/index.d.ts +37 -12
- package/dist/index.js +48 -31
- package/dist/server/browser-error.d.ts +91 -0
- package/dist/server/browser-error.js +244 -0
- package/dist/server/index.d.ts +48 -0
- package/dist/server/index.js +47 -0
- package/dist/types/actions.d.ts +39 -0
- package/dist/types/actions.js +9 -0
- package/dist/types/index.d.ts +20 -0
- package/dist/types/index.js +19 -0
- package/dist/types/routing.d.ts +192 -0
- package/dist/types/routing.js +9 -0
- package/package.json +43 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,229 @@
|
|
|
1
1
|
# @veloxts/web
|
|
2
2
|
|
|
3
|
+
## 0.6.51
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fix(web): configure @vinxi/server-functions for RSC server actions
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @veloxts/auth@0.6.51
|
|
10
|
+
- @veloxts/client@0.6.51
|
|
11
|
+
- @veloxts/core@0.6.51
|
|
12
|
+
- @veloxts/router@0.6.51
|
|
13
|
+
|
|
14
|
+
## 0.6.50
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- lint fixed
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
- @veloxts/auth@0.6.50
|
|
21
|
+
- @veloxts/client@0.6.50
|
|
22
|
+
- @veloxts/core@0.6.50
|
|
23
|
+
- @veloxts/router@0.6.50
|
|
24
|
+
|
|
25
|
+
## 0.6.49
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- feat(create): add client import lint script for RSC templates
|
|
30
|
+
- Updated dependencies
|
|
31
|
+
- @veloxts/auth@0.6.49
|
|
32
|
+
- @veloxts/client@0.6.49
|
|
33
|
+
- @veloxts/core@0.6.49
|
|
34
|
+
- @veloxts/router@0.6.49
|
|
35
|
+
|
|
36
|
+
## 0.6.48
|
|
37
|
+
|
|
38
|
+
### Patch Changes
|
|
39
|
+
|
|
40
|
+
- fix(web): remove server-only guards incompatible with Vite SS
|
|
41
|
+
- Updated dependencies
|
|
42
|
+
- @veloxts/auth@0.6.48
|
|
43
|
+
- @veloxts/client@0.6.48
|
|
44
|
+
- @veloxts/core@0.6.48
|
|
45
|
+
- @veloxts/router@0.6.48
|
|
46
|
+
|
|
47
|
+
## 0.6.47
|
|
48
|
+
|
|
49
|
+
### Patch Changes
|
|
50
|
+
|
|
51
|
+
- fix(web): use /adapters for createH3ApiHandler to avoid server-only
|
|
52
|
+
- Updated dependencies
|
|
53
|
+
- @veloxts/auth@0.6.47
|
|
54
|
+
- @veloxts/client@0.6.47
|
|
55
|
+
- @veloxts/core@0.6.47
|
|
56
|
+
- @veloxts/router@0.6.47
|
|
57
|
+
|
|
58
|
+
## 0.6.46
|
|
59
|
+
|
|
60
|
+
### Patch Changes
|
|
61
|
+
|
|
62
|
+
- fix(web): remove transitive server-only import from main entry
|
|
63
|
+
- Updated dependencies
|
|
64
|
+
- @veloxts/auth@0.6.46
|
|
65
|
+
- @veloxts/client@0.6.46
|
|
66
|
+
- @veloxts/core@0.6.46
|
|
67
|
+
- @veloxts/router@0.6.46
|
|
68
|
+
|
|
69
|
+
## 0.6.45
|
|
70
|
+
|
|
71
|
+
### Patch Changes
|
|
72
|
+
|
|
73
|
+
- fix(web): remove server-only guard from main entry for Vinxi compat
|
|
74
|
+
- Updated dependencies
|
|
75
|
+
- @veloxts/auth@0.6.45
|
|
76
|
+
- @veloxts/client@0.6.45
|
|
77
|
+
- @veloxts/core@0.6.45
|
|
78
|
+
- @veloxts/router@0.6.45
|
|
79
|
+
|
|
80
|
+
## 0.6.44
|
|
81
|
+
|
|
82
|
+
### Patch Changes
|
|
83
|
+
|
|
84
|
+
- refactor(web): implement proper RSC server/client separation
|
|
85
|
+
- fix(web): remove server-only guard from main entry to allow Vinxi config loading
|
|
86
|
+
- Main entry (`@veloxts/web`) now allows build-time Node.js usage (e.g., `defineVeloxApp` in `app.config.ts`)
|
|
87
|
+
- RSC runtime protection still enforced via `@veloxts/web/server` and `@veloxts/web/actions` guards
|
|
88
|
+
- Fixes "This module cannot be imported from a Client Component" error during `vinxi dev`
|
|
89
|
+
- Updated dependencies
|
|
90
|
+
- @veloxts/auth@0.6.44
|
|
91
|
+
- @veloxts/client@0.6.44
|
|
92
|
+
- @veloxts/core@0.6.44
|
|
93
|
+
- @veloxts/router@0.6.44
|
|
94
|
+
|
|
95
|
+
## 0.6.43
|
|
96
|
+
|
|
97
|
+
### Patch Changes
|
|
98
|
+
|
|
99
|
+
- fix(web): exclude native modules from Vite dependency optimization
|
|
100
|
+
- Updated dependencies
|
|
101
|
+
- @veloxts/auth@0.6.43
|
|
102
|
+
- @veloxts/client@0.6.43
|
|
103
|
+
- @veloxts/core@0.6.43
|
|
104
|
+
- @veloxts/router@0.6.43
|
|
105
|
+
|
|
106
|
+
## 0.6.42
|
|
107
|
+
|
|
108
|
+
### Patch Changes
|
|
109
|
+
|
|
110
|
+
- fix(web): enable tsconfig path aliases for Vite/Vinxi + docs(web): add @public/@internal JSDoc annotations to server actions
|
|
111
|
+
- Updated dependencies
|
|
112
|
+
- @veloxts/auth@0.6.42
|
|
113
|
+
- @veloxts/client@0.6.42
|
|
114
|
+
- @veloxts/core@0.6.42
|
|
115
|
+
- @veloxts/router@0.6.42
|
|
116
|
+
|
|
117
|
+
## 0.6.41
|
|
118
|
+
|
|
119
|
+
### Patch Changes
|
|
120
|
+
|
|
121
|
+
- feat(web): add authAction helper for procedure bridge authentication
|
|
122
|
+
- Updated dependencies
|
|
123
|
+
- @veloxts/auth@0.6.41
|
|
124
|
+
- @veloxts/client@0.6.41
|
|
125
|
+
- @veloxts/core@0.6.41
|
|
126
|
+
- @veloxts/router@0.6.41
|
|
127
|
+
|
|
128
|
+
## 0.6.40
|
|
129
|
+
|
|
130
|
+
### Patch Changes
|
|
131
|
+
|
|
132
|
+
- feat(create): consolidate template styles with unified dark mode design
|
|
133
|
+
- Updated dependencies
|
|
134
|
+
- @veloxts/auth@0.6.40
|
|
135
|
+
- @veloxts/client@0.6.40
|
|
136
|
+
- @veloxts/core@0.6.40
|
|
137
|
+
- @veloxts/router@0.6.40
|
|
138
|
+
|
|
139
|
+
## 0.6.39
|
|
140
|
+
|
|
141
|
+
### Patch Changes
|
|
142
|
+
|
|
143
|
+
- fix RSC client hydration with split layout architecture
|
|
144
|
+
- Updated dependencies
|
|
145
|
+
- @veloxts/auth@0.6.39
|
|
146
|
+
- @veloxts/client@0.6.39
|
|
147
|
+
- @veloxts/core@0.6.39
|
|
148
|
+
- @veloxts/router@0.6.39
|
|
149
|
+
|
|
150
|
+
## 0.6.38
|
|
151
|
+
|
|
152
|
+
### Patch Changes
|
|
153
|
+
|
|
154
|
+
- fix client hydration for RSC templates
|
|
155
|
+
- Updated dependencies
|
|
156
|
+
- @veloxts/auth@0.6.38
|
|
157
|
+
- @veloxts/client@0.6.38
|
|
158
|
+
- @veloxts/core@0.6.38
|
|
159
|
+
- @veloxts/router@0.6.38
|
|
160
|
+
|
|
161
|
+
## 0.6.37
|
|
162
|
+
|
|
163
|
+
### Patch Changes
|
|
164
|
+
|
|
165
|
+
- feat(web): add validated() helper for secure server actions & add rsc-auth template with validated()
|
|
166
|
+
- Updated dependencies
|
|
167
|
+
- @veloxts/auth@0.6.37
|
|
168
|
+
- @veloxts/client@0.6.37
|
|
169
|
+
- @veloxts/core@0.6.37
|
|
170
|
+
- @veloxts/router@0.6.37
|
|
171
|
+
|
|
172
|
+
## 0.6.36
|
|
173
|
+
|
|
174
|
+
### Patch Changes
|
|
175
|
+
|
|
176
|
+
- Gap Remediation Plan
|
|
177
|
+
- Updated dependencies
|
|
178
|
+
- @veloxts/auth@0.6.36
|
|
179
|
+
- @veloxts/client@0.6.36
|
|
180
|
+
- @veloxts/core@0.6.36
|
|
181
|
+
- @veloxts/router@0.6.36
|
|
182
|
+
|
|
183
|
+
## 0.6.35
|
|
184
|
+
|
|
185
|
+
### Patch Changes
|
|
186
|
+
|
|
187
|
+
- proper auth template testing in verify-publis
|
|
188
|
+
- Updated dependencies
|
|
189
|
+
- @veloxts/auth@0.6.35
|
|
190
|
+
- @veloxts/client@0.6.35
|
|
191
|
+
- @veloxts/core@0.6.35
|
|
192
|
+
- @veloxts/router@0.6.35
|
|
193
|
+
|
|
194
|
+
## 0.6.34
|
|
195
|
+
|
|
196
|
+
### Patch Changes
|
|
197
|
+
|
|
198
|
+
- update PostgreSQL adapter for Prisma 7 API
|
|
199
|
+
- Updated dependencies
|
|
200
|
+
- @veloxts/auth@0.6.34
|
|
201
|
+
- @veloxts/client@0.6.34
|
|
202
|
+
- @veloxts/core@0.6.34
|
|
203
|
+
- @veloxts/router@0.6.34
|
|
204
|
+
|
|
205
|
+
## 0.6.33
|
|
206
|
+
|
|
207
|
+
### Patch Changes
|
|
208
|
+
|
|
209
|
+
- changed claude.md instruction, added prisma config
|
|
210
|
+
- Updated dependencies
|
|
211
|
+
- @veloxts/auth@0.6.33
|
|
212
|
+
- @veloxts/client@0.6.33
|
|
213
|
+
- @veloxts/core@0.6.33
|
|
214
|
+
- @veloxts/router@0.6.33
|
|
215
|
+
|
|
216
|
+
## 0.6.32
|
|
217
|
+
|
|
218
|
+
### Patch Changes
|
|
219
|
+
|
|
220
|
+
- Introducing new Ecosystem Expansion packages: cache, queue, mail, storage, scheduler, events. Do not use yet
|
|
221
|
+
- Updated dependencies
|
|
222
|
+
- @veloxts/auth@0.6.32
|
|
223
|
+
- @veloxts/client@0.6.32
|
|
224
|
+
- @veloxts/core@0.6.32
|
|
225
|
+
- @veloxts/router@0.6.32
|
|
226
|
+
|
|
3
227
|
## 0.6.31
|
|
4
228
|
|
|
5
229
|
### Patch Changes
|
package/dist/actions/action.d.ts
CHANGED
|
@@ -35,12 +35,14 @@
|
|
|
35
35
|
*/
|
|
36
36
|
import type { BaseContext } from '@veloxts/core';
|
|
37
37
|
import type { CompiledProcedure } from '@veloxts/router';
|
|
38
|
-
import type
|
|
38
|
+
import { type infer as ZodInfer, type ZodSchema, type ZodType, type ZodTypeDef } from 'zod';
|
|
39
|
+
import { type H3ActionContext } from '../adapters/h3-adapter.js';
|
|
39
40
|
import { type ExecuteProcedureOptions } from './procedure-bridge.js';
|
|
40
41
|
import type { ActionContext, ActionError, ActionErrorCode, ActionResult, ActionSuccess, AuthenticatedActionContext } from './types.js';
|
|
41
42
|
/**
|
|
42
43
|
* Handler function that receives validated input and returns output.
|
|
43
44
|
* The context type varies based on whether the action is protected.
|
|
45
|
+
* @public
|
|
44
46
|
*/
|
|
45
47
|
type ActionHandlerFn<TInput, TOutput, TContext extends ActionContext = ActionContext> = (input: TInput, ctx: TContext) => Promise<TOutput>;
|
|
46
48
|
/**
|
|
@@ -49,11 +51,13 @@ type ActionHandlerFn<TInput, TOutput, TContext extends ActionContext = ActionCon
|
|
|
49
51
|
*
|
|
50
52
|
* Note: Named `ValidatedAction` to distinguish from the simpler `ServerAction`
|
|
51
53
|
* type in types.ts which does not wrap the output in ActionResult.
|
|
54
|
+
* @public
|
|
52
55
|
*/
|
|
53
56
|
type ValidatedAction<TInput, TOutput> = (input: TInput) => Promise<ActionResult<TOutput>>;
|
|
54
57
|
/**
|
|
55
58
|
* Configuration options for action creation.
|
|
56
59
|
* These are set via the fluent builder methods.
|
|
60
|
+
* @public
|
|
57
61
|
*/
|
|
58
62
|
interface ActionConfig<TInput, TOutput, TContext extends ActionContext> {
|
|
59
63
|
inputSchema?: ZodSchema<TInput>;
|
|
@@ -63,10 +67,12 @@ interface ActionConfig<TInput, TOutput, TContext extends ActionContext> {
|
|
|
63
67
|
}
|
|
64
68
|
/**
|
|
65
69
|
* Custom error handler type.
|
|
70
|
+
* @public
|
|
66
71
|
*/
|
|
67
72
|
type ErrorHandler<TContext extends ActionContext = ActionContext> = (error: unknown, ctx: TContext) => ActionError | Promise<ActionError>;
|
|
68
73
|
/**
|
|
69
74
|
* Options for creating an action from a procedure.
|
|
75
|
+
* @public
|
|
70
76
|
*/
|
|
71
77
|
interface FromProcedureOptions extends ExecuteProcedureOptions {
|
|
72
78
|
/**
|
|
@@ -75,10 +81,53 @@ interface FromProcedureOptions extends ExecuteProcedureOptions {
|
|
|
75
81
|
* @default false
|
|
76
82
|
*/
|
|
77
83
|
parseFormData?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Called after successful procedure execution.
|
|
86
|
+
* Use for side effects like setting cookies, logging, etc.
|
|
87
|
+
*
|
|
88
|
+
* @param result - The procedure's output
|
|
89
|
+
* @param ctx - H3 action context with cookie methods
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* action.fromProcedure(authProcedures.login, {
|
|
94
|
+
* onSuccess: async (tokens, ctx) => {
|
|
95
|
+
* ctx.setCookie('accessToken', tokens.accessToken, { httpOnly: true });
|
|
96
|
+
* }
|
|
97
|
+
* });
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
onSuccess?: (result: unknown, ctx: H3ActionContext) => void | Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Called before procedure execution.
|
|
103
|
+
* Use for extracting data from cookies, setting up context.
|
|
104
|
+
*
|
|
105
|
+
* @param ctx - H3 action context with cookie methods
|
|
106
|
+
*/
|
|
107
|
+
beforeExecute?: (ctx: H3ActionContext) => void | Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Transform the result before returning to the client.
|
|
110
|
+
* Useful for stripping sensitive data (like tokens) from responses.
|
|
111
|
+
*
|
|
112
|
+
* @param result - The procedure's raw output
|
|
113
|
+
* @returns The transformed result
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* action.fromProcedure(authProcedures.login, {
|
|
118
|
+
* transformResult: (tokens) => ({
|
|
119
|
+
* success: true,
|
|
120
|
+
* expiresIn: tokens.expiresIn,
|
|
121
|
+
* })
|
|
122
|
+
* });
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
transformResult?: <T>(result: T) => unknown;
|
|
78
126
|
}
|
|
79
127
|
/**
|
|
80
128
|
* Builder for creating actions with fluent method chaining.
|
|
81
129
|
* Each method returns a new builder with updated type parameters.
|
|
130
|
+
* @public
|
|
82
131
|
*/
|
|
83
132
|
interface ActionBuilder<TInput = unknown, TOutput = unknown, TContext extends ActionContext = ActionContext> {
|
|
84
133
|
/**
|
|
@@ -155,6 +204,7 @@ interface ActionBuilder<TInput = unknown, TOutput = unknown, TContext extends Ac
|
|
|
155
204
|
}
|
|
156
205
|
/**
|
|
157
206
|
* Action helper type - combines function signature with builder methods.
|
|
207
|
+
* @public
|
|
158
208
|
*/
|
|
159
209
|
interface Action {
|
|
160
210
|
/**
|
|
@@ -361,6 +411,8 @@ interface Action {
|
|
|
361
411
|
* ```typescript
|
|
362
412
|
* { success: false, error: { code: 'UNAUTHORIZED', message: 'Authentication required' } }
|
|
363
413
|
* ```
|
|
414
|
+
*
|
|
415
|
+
* @public
|
|
364
416
|
*/
|
|
365
417
|
declare const action: Action;
|
|
366
418
|
export { action };
|
package/dist/actions/action.js
CHANGED
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
* });
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
|
+
import { ZodError, } from 'zod';
|
|
37
|
+
import { createH3Context, isH3Context } from '../adapters/h3-adapter.js';
|
|
36
38
|
import { toActionError } from './error-classifier.js';
|
|
37
39
|
import { formDataToObject } from './form-parser.js';
|
|
38
40
|
import { executeProcedureDirectly } from './procedure-bridge.js';
|
|
@@ -41,12 +43,14 @@ import { executeProcedureDirectly } from './procedure-bridge.js';
|
|
|
41
43
|
// ============================================================================
|
|
42
44
|
/**
|
|
43
45
|
* Creates a successful action result.
|
|
46
|
+
* @internal
|
|
44
47
|
*/
|
|
45
48
|
function ok(data) {
|
|
46
49
|
return { success: true, data };
|
|
47
50
|
}
|
|
48
51
|
/**
|
|
49
52
|
* Creates an error action result.
|
|
53
|
+
* @internal
|
|
50
54
|
*/
|
|
51
55
|
function fail(code, message, details) {
|
|
52
56
|
return {
|
|
@@ -59,12 +63,12 @@ function fail(code, message, details) {
|
|
|
59
63
|
// ============================================================================
|
|
60
64
|
/**
|
|
61
65
|
* Formats a Zod error into an ActionError.
|
|
66
|
+
* @internal
|
|
62
67
|
*/
|
|
63
68
|
function formatZodError(err) {
|
|
64
|
-
if (err
|
|
65
|
-
const zodError = err;
|
|
69
|
+
if (err instanceof ZodError) {
|
|
66
70
|
return fail('VALIDATION_ERROR', 'Validation failed', {
|
|
67
|
-
errors:
|
|
71
|
+
errors: err.errors.map((e) => ({
|
|
68
72
|
path: e.path.join('.'),
|
|
69
73
|
message: e.message,
|
|
70
74
|
})),
|
|
@@ -81,6 +85,7 @@ function formatZodError(err) {
|
|
|
81
85
|
* when the schema has async refinements.
|
|
82
86
|
*
|
|
83
87
|
* @see https://zod.dev/?id=parseasync - Zod async parsing docs
|
|
88
|
+
* @internal
|
|
84
89
|
*/
|
|
85
90
|
async function validateWithSchema(schema, data) {
|
|
86
91
|
try {
|
|
@@ -114,6 +119,7 @@ async function validateWithSchema(schema, data) {
|
|
|
114
119
|
*
|
|
115
120
|
* Note: In production with Vinxi integration, this will be replaced
|
|
116
121
|
* with real request context from the server.
|
|
122
|
+
* @internal
|
|
117
123
|
*/
|
|
118
124
|
function createContext() {
|
|
119
125
|
const headers = new Headers();
|
|
@@ -126,6 +132,7 @@ function createContext() {
|
|
|
126
132
|
}
|
|
127
133
|
/**
|
|
128
134
|
* Type guard to check if context has an authenticated user.
|
|
135
|
+
* @internal
|
|
129
136
|
*/
|
|
130
137
|
function hasAuthenticatedUser(ctx) {
|
|
131
138
|
return 'user' in ctx && ctx.user !== undefined && ctx.user !== null;
|
|
@@ -140,6 +147,7 @@ function hasAuthenticatedUser(ctx) {
|
|
|
140
147
|
* for consistent error handling across all action types.
|
|
141
148
|
*
|
|
142
149
|
* @see toActionError - The underlying classification function
|
|
150
|
+
* @internal
|
|
143
151
|
*/
|
|
144
152
|
function handleError(err) {
|
|
145
153
|
return toActionError(err);
|
|
@@ -149,6 +157,7 @@ function handleError(err) {
|
|
|
149
157
|
// ============================================================================
|
|
150
158
|
/**
|
|
151
159
|
* Creates a new builder instance with the given configuration.
|
|
160
|
+
* @internal
|
|
152
161
|
*/
|
|
153
162
|
function createBuilder(config) {
|
|
154
163
|
return {
|
|
@@ -183,6 +192,7 @@ function createBuilder(config) {
|
|
|
183
192
|
}
|
|
184
193
|
/**
|
|
185
194
|
* Creates the final validated action function from config and handler.
|
|
195
|
+
* @internal
|
|
186
196
|
*/
|
|
187
197
|
function createValidatedAction(config, handler) {
|
|
188
198
|
const { inputSchema, outputSchema, requireAuth, onError } = config;
|
|
@@ -329,6 +339,8 @@ function createValidatedAction(config, handler) {
|
|
|
329
339
|
* ```typescript
|
|
330
340
|
* { success: false, error: { code: 'UNAUTHORIZED', message: 'Authentication required' } }
|
|
331
341
|
* ```
|
|
342
|
+
*
|
|
343
|
+
* @public
|
|
332
344
|
*/
|
|
333
345
|
const action = Object.assign(
|
|
334
346
|
// Primary function signature: action(schema, handler)
|
|
@@ -359,18 +371,42 @@ function actionFn(schema, handler) {
|
|
|
359
371
|
});
|
|
360
372
|
},
|
|
361
373
|
fromProcedure(procedure, options) {
|
|
362
|
-
const { parseFormData = false, ...executionOptions } = options ?? {};
|
|
374
|
+
const { parseFormData = false, onSuccess, beforeExecute, transformResult, ...executionOptions } = options ?? {};
|
|
363
375
|
return async (rawInput) => {
|
|
364
376
|
try {
|
|
365
|
-
//
|
|
366
|
-
|
|
377
|
+
// Try to create real H3 context when running in Vinxi
|
|
378
|
+
// Falls back to mock context in non-Vinxi environments
|
|
379
|
+
let ctx;
|
|
380
|
+
try {
|
|
381
|
+
ctx = await createH3Context();
|
|
382
|
+
}
|
|
383
|
+
catch {
|
|
384
|
+
ctx = createContext();
|
|
385
|
+
}
|
|
386
|
+
// Call beforeExecute hook if provided (only for H3 context)
|
|
387
|
+
if (beforeExecute && isH3Context(ctx)) {
|
|
388
|
+
await beforeExecute(ctx);
|
|
389
|
+
}
|
|
367
390
|
// Handle FormData if enabled
|
|
368
391
|
let input = rawInput;
|
|
369
392
|
if (parseFormData && rawInput instanceof FormData) {
|
|
370
393
|
input = formDataToObject(rawInput);
|
|
371
394
|
}
|
|
372
395
|
// Execute the procedure directly
|
|
373
|
-
|
|
396
|
+
const result = await executeProcedureDirectly(procedure, input, ctx, executionOptions);
|
|
397
|
+
// Call onSuccess hook if execution succeeded (only for H3 context)
|
|
398
|
+
if (result.success && onSuccess && isH3Context(ctx)) {
|
|
399
|
+
await onSuccess(result.data, ctx);
|
|
400
|
+
}
|
|
401
|
+
// Transform result if transformer provided
|
|
402
|
+
// Note: When transformResult is used, the caller is responsible for
|
|
403
|
+
// providing the correct return type (via type assertion on the function)
|
|
404
|
+
if (result.success && transformResult) {
|
|
405
|
+
const transformedData = transformResult(result.data);
|
|
406
|
+
// Return with transformed data - caller handles type via external cast
|
|
407
|
+
return { success: true, data: transformedData };
|
|
408
|
+
}
|
|
409
|
+
return result;
|
|
374
410
|
}
|
|
375
411
|
catch (err) {
|
|
376
412
|
return handleError(err);
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Bridge for Server Actions
|
|
3
|
+
*
|
|
4
|
+
* Specialized helpers for authentication procedures that need to
|
|
5
|
+
* set httpOnly cookies for token storage. These helpers wrap
|
|
6
|
+
* `action.fromProcedure()` with auth-specific callbacks.
|
|
7
|
+
*
|
|
8
|
+
* @module @veloxts/web/actions/auth-bridge
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* 'use server';
|
|
13
|
+
*
|
|
14
|
+
* import { authAction } from '@veloxts/web';
|
|
15
|
+
* import { authProcedures } from '@/api/procedures/auth';
|
|
16
|
+
* import { db } from '@/api/database';
|
|
17
|
+
*
|
|
18
|
+
* // Login sets tokens in httpOnly cookies
|
|
19
|
+
* export const login = authAction.fromTokenProcedure(
|
|
20
|
+
* authProcedures.procedures.createSession,
|
|
21
|
+
* { parseFormData: true, contextExtensions: { db } }
|
|
22
|
+
* );
|
|
23
|
+
*
|
|
24
|
+
* // Logout clears auth cookies
|
|
25
|
+
* export const logout = authAction.fromLogoutProcedure(
|
|
26
|
+
* authProcedures.procedures.deleteSession,
|
|
27
|
+
* { contextExtensions: { db } }
|
|
28
|
+
* );
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
import type { BaseContext } from '@veloxts/core';
|
|
32
|
+
import type { CompiledProcedure } from '@veloxts/router';
|
|
33
|
+
import type { H3ActionContext, H3CookieOptions } from '../adapters/h3-adapter.js';
|
|
34
|
+
import type { ExecuteProcedureOptions } from './procedure-bridge.js';
|
|
35
|
+
import type { ActionResult } from './types.js';
|
|
36
|
+
/**
|
|
37
|
+
* Configuration for auth cookies.
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export interface AuthCookieConfig {
|
|
41
|
+
/**
|
|
42
|
+
* Name of the access token cookie.
|
|
43
|
+
* @default 'accessToken'
|
|
44
|
+
*/
|
|
45
|
+
accessTokenName?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Name of the refresh token cookie.
|
|
48
|
+
* @default 'refreshToken'
|
|
49
|
+
*/
|
|
50
|
+
refreshTokenName?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Cookie options applied to auth cookies.
|
|
53
|
+
* Merged with secure defaults.
|
|
54
|
+
*/
|
|
55
|
+
cookieOptions?: H3CookieOptions;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Options for creating an auth action from a procedure.
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
61
|
+
export interface AuthActionOptions extends ExecuteProcedureOptions {
|
|
62
|
+
/**
|
|
63
|
+
* Whether to parse FormData input.
|
|
64
|
+
* @default false
|
|
65
|
+
*/
|
|
66
|
+
parseFormData?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Cookie configuration.
|
|
69
|
+
*/
|
|
70
|
+
cookies?: AuthCookieConfig;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Standard token response from auth procedures.
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
export interface TokenResponse {
|
|
77
|
+
accessToken: string;
|
|
78
|
+
refreshToken: string;
|
|
79
|
+
expiresIn: number;
|
|
80
|
+
tokenType: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Sanitized login response returned to client.
|
|
84
|
+
* Raw tokens are stripped for security (stored in httpOnly cookies).
|
|
85
|
+
* @public
|
|
86
|
+
*/
|
|
87
|
+
export interface LoginResponse {
|
|
88
|
+
success: boolean;
|
|
89
|
+
expiresIn: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Extended H3 context with refresh token available.
|
|
93
|
+
* Used internally by beforeExecute hook in fromRefreshProcedure.
|
|
94
|
+
* @internal
|
|
95
|
+
*/
|
|
96
|
+
export interface H3ActionContextWithRefreshToken extends H3ActionContext {
|
|
97
|
+
refreshToken?: string;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Runtime type guard for TokenResponse.
|
|
101
|
+
* Validates that the procedure result has the expected token shape.
|
|
102
|
+
*
|
|
103
|
+
* @param result - The value to check
|
|
104
|
+
* @returns True if result is a valid TokenResponse
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* if (isTokenResponse(result)) {
|
|
109
|
+
* // result is now typed as TokenResponse
|
|
110
|
+
* console.log(result.accessToken);
|
|
111
|
+
* }
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* @public
|
|
115
|
+
*/
|
|
116
|
+
export declare function isTokenResponse(result: unknown): result is TokenResponse;
|
|
117
|
+
/**
|
|
118
|
+
* Auth-specific action helpers for token-based authentication.
|
|
119
|
+
*
|
|
120
|
+
* These helpers wrap `action.fromProcedure()` with authentication-specific
|
|
121
|
+
* callbacks that handle token storage in httpOnly cookies.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```typescript
|
|
125
|
+
* // In your server actions file
|
|
126
|
+
* 'use server';
|
|
127
|
+
*
|
|
128
|
+
* import { authAction } from '@veloxts/web';
|
|
129
|
+
* import { authProcedures } from '@/api/procedures/auth';
|
|
130
|
+
*
|
|
131
|
+
* export const login = authAction.fromTokenProcedure(
|
|
132
|
+
* authProcedures.procedures.createSession,
|
|
133
|
+
* { parseFormData: true, contextExtensions: { db } }
|
|
134
|
+
* );
|
|
135
|
+
*
|
|
136
|
+
* export const register = authAction.fromTokenProcedure(
|
|
137
|
+
* authProcedures.procedures.createAccount,
|
|
138
|
+
* { parseFormData: true, contextExtensions: { db } }
|
|
139
|
+
* );
|
|
140
|
+
*
|
|
141
|
+
* export const logout = authAction.fromLogoutProcedure(
|
|
142
|
+
* authProcedures.procedures.deleteSession,
|
|
143
|
+
* { contextExtensions: { db } }
|
|
144
|
+
* );
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* @public
|
|
148
|
+
*/
|
|
149
|
+
export declare const authAction: {
|
|
150
|
+
/**
|
|
151
|
+
* Creates a server action from an auth procedure that returns tokens.
|
|
152
|
+
*
|
|
153
|
+
* This helper:
|
|
154
|
+
* 1. Executes the procedure via the procedure bridge
|
|
155
|
+
* 2. On success, stores tokens in httpOnly cookies
|
|
156
|
+
* 3. Returns a sanitized response (tokens stripped for security)
|
|
157
|
+
*
|
|
158
|
+
* @param procedure - The auth procedure that returns TokenResponse
|
|
159
|
+
* @param options - Configuration options
|
|
160
|
+
* @returns Server action that returns LoginResponse
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```typescript
|
|
164
|
+
* export const login = authAction.fromTokenProcedure(
|
|
165
|
+
* authProcedures.procedures.createSession,
|
|
166
|
+
* {
|
|
167
|
+
* parseFormData: true,
|
|
168
|
+
* contextExtensions: { db: prisma },
|
|
169
|
+
* cookies: {
|
|
170
|
+
* accessTokenName: 'session',
|
|
171
|
+
* cookieOptions: { sameSite: 'strict' },
|
|
172
|
+
* },
|
|
173
|
+
* }
|
|
174
|
+
* );
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
fromTokenProcedure<TInput, TContext extends BaseContext = BaseContext>(procedure: CompiledProcedure<TInput, TokenResponse, TContext>, options?: AuthActionOptions): (input: TInput) => Promise<ActionResult<LoginResponse>>;
|
|
178
|
+
/**
|
|
179
|
+
* Creates a server action from a logout procedure.
|
|
180
|
+
*
|
|
181
|
+
* This helper:
|
|
182
|
+
* 1. Executes the procedure via the procedure bridge
|
|
183
|
+
* 2. On success, clears auth cookies
|
|
184
|
+
*
|
|
185
|
+
* @param procedure - The logout procedure
|
|
186
|
+
* @param options - Configuration options
|
|
187
|
+
* @returns Server action that returns the procedure output
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```typescript
|
|
191
|
+
* export const logout = authAction.fromLogoutProcedure(
|
|
192
|
+
* authProcedures.procedures.deleteSession,
|
|
193
|
+
* { contextExtensions: { db: prisma } }
|
|
194
|
+
* );
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
fromLogoutProcedure<TInput, TOutput, TContext extends BaseContext = BaseContext>(procedure: CompiledProcedure<TInput, TOutput, TContext>, options?: Omit<AuthActionOptions, "parseFormData">): (input: TInput) => Promise<ActionResult<TOutput>>;
|
|
198
|
+
/**
|
|
199
|
+
* Creates a server action from a token refresh procedure.
|
|
200
|
+
*
|
|
201
|
+
* This helper:
|
|
202
|
+
* 1. Reads the refresh token from cookies
|
|
203
|
+
* 2. Executes the refresh procedure
|
|
204
|
+
* 3. On success, updates the access token cookie
|
|
205
|
+
*
|
|
206
|
+
* @param procedure - The refresh procedure that returns new tokens
|
|
207
|
+
* @param options - Configuration options
|
|
208
|
+
* @returns Server action that returns LoginResponse
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* ```typescript
|
|
212
|
+
* export const refreshToken = authAction.fromRefreshProcedure(
|
|
213
|
+
* authProcedures.procedures.refreshSession,
|
|
214
|
+
* { contextExtensions: { db: prisma } }
|
|
215
|
+
* );
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
fromRefreshProcedure<TInput, TContext extends BaseContext = BaseContext>(procedure: CompiledProcedure<TInput, TokenResponse, TContext>, options?: AuthActionOptions): (input: TInput) => Promise<ActionResult<LoginResponse>>;
|
|
219
|
+
};
|