Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a way to intercept and change form action result in handle hook #9676

Open
qurafi opened this issue Apr 16, 2023 · 2 comments
Open

Add a way to intercept and change form action result in handle hook #9676

qurafi opened this issue Apr 16, 2023 · 2 comments
Labels
feature request New feature or request

Comments

@qurafi
Copy link

qurafi commented Apr 16, 2023

Describe the problem

There's no native way to intercept form actions and changing its result before being rendered.

Why I need this
I'm experimenting automatic endpoint/form validation based on the defined schema file. I will load all needed schemas in the hook handle and validate them and return result back to user. Something similar to what's in Fastify framework

For standalone endpoints this works fine. but with form actions, this is challenging as I have to render the page with the error props but sveltekit yet doesn't provide any mechanism to change that.

Describe the proposed solution

We could either have a seperate hook function in hooks.server or provide a callback in resolve function similar to transformPageChunk

Alternatives considered

  1. Manually define the desired behavior in each form action with a shared function. but this is redundant
  2. A hacky way to use transformPageChunk to replace form in kit.start(app, __sveltekit_dev.element, { node_ids: [0, 2], data, form: null, error: null }); with the desired results. but this is a hacky solution and requires more testing and could break pages and introduce security issues.

Importance

would make my life easier

Additional Information

No response

@Rich-Harris
Copy link
Member

Per #9682 (comment), can you describe in concrete terms (i.e. with examples) why you need this?

@qurafi
Copy link
Author

qurafi commented Apr 17, 2023

The implementation didn't take that much but I think the PR was too early. I don't think a separate hook is necessary as all form actions pass through the handle hook. I prefer a central hook to handle everything as it flexible for external lib users to add hook instead of managing adding individual hooks.

as far as I can see this doesn't give you a way to replace form but not to modify/inspect it, which doesn't seem all that flexible. I think it's much more likely that if we were to add a feature like this, we'd have something like a handleAction hook, similar to the proposed handleLoad hook in #9542.

For flexibility we could accept a function that takes the outgoing data actionResult: (data) => ...

Per #9682 (comment), can you describe in concrete terms (i.e. with examples) why you need this?

I put "Why I need this' section in the original issue but if it was not clear. I will try to explain again.

So this is a pseudocode what I'm trying to achieve.

// reference to all routes schemas(every route has its own schema file)
const schemas = {
    "/auth": import("/src/routes/auth/schema.js")
    // ...
}

// the invidual schema file will look like
export const GET = {
    type: "object",
    properties: {
        // 
    }
}

export const login_action = {
    // 
}


// and then we could handle all our validation logic in a single function
export const handle = function hook({ event, resolve }) {
    const schemas_module = schemas[event.route.id] // get route schema based on path
    if (schemas_module) {
        const route_schemas = await schemas_module; // load the schemas module
        if (request_is_standalone) {
            const validate = getValidationFnForSchema(route_schemas[event.request.method])
            const { valid, errors } = validate(requestBody);
            if (!valid) {
                return new Response(errors) // return errors as json
            }
        } else if (request_is_form_submission) {
            const action_name = ... // get action name from url
            const validate = getValidationFnForSchema(routes[`${action_name}_action`])
            const { valid, errors } = validate(formData);
            if (!valid) {
                // Can't return just a response as the page need to be rendered
                // so we will have something like this instead
                return resolve(event, {
                    actionResult: {form_errors: errors}
                })
            }
        }
    }
}

@eltigerchino eltigerchino added the feature request New feature or request label Nov 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants