Closed Maikpwwq closed 1 year ago
Could you please create a minimal reproduction?
@hamatoyogi Sure. I create a new Qwik app
, with react and static adapters
. In header click link
to visit Form route
.
Project Repository Vercel Deployment Vercel Project
When send form
I am getting those issues on my Vercel Deployment
Thanks @Maikpwwq can you outline the steps to reproduce the issue in the repo that you shared (the more info the better, like which files to look at etc)
@shairez just clone the repo, run the app, navigate to the form and try to send it. It is not so difficult.
I am trying to implement a form, in my routes
folder I created a folder called customer-form
with a file Index.tsx
. This fails to store my data when is deployed to Vercel with this in console:
I have tried first with mongo, now with supabase the problem persist. My file Index.tsx
import { component$, $, useTask$ } from "@builder.io/qwik"; // , useSignal
import { isServer } from "@builder.io/qwik/build";
import { createClient } from "@supabase/supabase-js";
import { v4 as uuidv4 } from 'uuid'
import clsx from "clsx";
import {
routeLoader$,
z,
} from "@builder.io/qwik-city";
import type { InitialValues, SubmitHandler } from "@modular-forms/qwik"; //
import {
useForm,
formAction$,
zodForm$,
reset,
} from "@modular-forms/qwik";
import styles from "~/components/modular-forms/modularForm.module.css";
import { MUITypography, MUIPaper } from "~/integrations/react/mui";
import { TextInput } from "~/components/modular-forms/TextInput";
const SUPABASE_URL = `${import.meta.env.VITE_SUPABASE_URL}`;
const SUPABASE_KEY = `${import.meta.env.VITE_SUPABASE_KEY}`;
type LoginForm = {
name: string;
email: string;
phone: string;
issue: string;
message: string;
};
const loginSchema = z.object({
name: z.string().min(1, "Por favor introduzca su nombre."),
email: z
.string()
.min(1, "Por favor introduzca su email.")
.email("The email address is badly formatted."),
phone: z
.string()
.min(1, "Por favor introduzca su teléfono.")
.min(10, "Tu teléfono debe tener 10 caracteres o más."),
issue: z.string().min(1, "Por favor introduzca su asunto."),
message: z
.string()
.min(1, "Por favor introduzca su mensaje.")
.min(8, "Tu mensaje debe tener 8 caracteres o más."),
});
// Also posible infer typos
// type LoginForm = z.infer<typeof loginSchema>;
// can only be declared in `layout.tsx`, `index.tsx` and `plugin.tsx` inside the src/routes directory
export const useFormLoader = routeLoader$<InitialValues<LoginForm>>(() => ({
name: "",
email: "",
phone: "",
issue: "",
message: "",
}));
type ResponseData = {
customerId: string;
};
export const useFormAction = formAction$<LoginForm, ResponseData>(
async (values) => {
// Runs on SERVER
console.log("useFormAction", values);
try {
// Create a single supabase client for interacting with your database
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY);
const { name, email, phone, issue, message } = values;
const recordID : string = uuidv4();
const hexNumber : number = 1; // parseInt(recordID.replace(/-/g, ''), 16);
const { data: customer_form, error } = await supabase
.from("customer_form")
.insert([{ id: hexNumber, created_at: new Date(), name, email, phone, issue, message }])
.select("*");
console.log("supabase contact form", customer_form, error);
if (customer_form) {
console.log("Success supabase contact form", customer_form[0].id);
}
if (error) {
console.log("Error supabase contact form", error);
}
return {
status: "success",
message: `Gracias, su mensaje ha sido recibido. ${recordID}`,
data: { customerId: recordID },
};
} catch (error) {
console.error(error);
return {
status: "error",
message: `No se ha podido enviar su mensaje. ${error}`,
data: { customerId: "" },
};
}
},
zodForm$(loginSchema),
); // valiForm$(LoginSchema)
export default component$(() => {
// const nav = useNavigate();
// , FieldArray
const [loginForm, { Form, Field }] = useForm<LoginForm, ResponseData>({
loader: useFormLoader(),
action: useFormAction(),
validate: zodForm$(loginSchema),
});
const handleSubmit = $<SubmitHandler<LoginForm>>(
async (values: any, event: any) => {
// Runs on CLIENT
console.log("handleSubmit", values, event);
},
);
const successData = $(async () => {
console.log(
"handleSubmitSuccess",
loginForm.submitted,
loginForm.submitting,
loginForm.response,
);
alert(loginForm.response.message);
reset(loginForm); // , useFormLoader
// clearResponse(loginForm);
// const value = getValue(form, name, options);
// await nav("/");
});
const errorData = $(async () => {
console.log(
"handleSubmitError",
loginForm.submitted,
loginForm.submitting,
loginForm.response,
);
alert(loginForm.response.message);
});
useTask$(({ track }) => {
track(() => loginForm.response.status);
if (isServer) {
return; // Server guard
}
if (
loginForm.submitted &&
loginForm.submitting === false &&
loginForm.response.status === "success"
) {
successData();
} else if (
loginForm.submitted &&
loginForm.submitting === false &&
loginForm.response.status === "error"
) {
errorData();
}
});
return (
<div class="container container-center flex justify-center" style={{}}>
<MUIPaper className={styles.cardContactForm} elevation={16}>
<div class={styles.sheetFormStyle}>
<MUITypography
variant="h6"
color={"var(--qwik-dark-blue)"}
align="center"
>
Formulario de contacto
</MUITypography>
<MUITypography variant="body1" className="pt-2 pb-4" align="center">
Solicita información adicional o una presentación de nuestros
servicios.
</MUITypography>
<Form
class={styles.formFlex}
onSubmit$={handleSubmit}
// preventdefault:submit
// reloadDocument={true}
>
<Field
name="name"
>
{(field, props) => (
<TextInput
{...props}
value={field.value}
error={field.error}
type="text"
label="Nombre:"
placeholder="Nombre"
required
/>
)}
</Field>
<Field
name="email"
>
{(field, props) => (
<TextInput
{...props}
value={field.value}
error={field.error}
type="email"
label="Email:"
placeholder="Correo electrónico"
required
/>
)}
</Field>
<Field
name="phone"
>
{(field, props) => (
<TextInput
{...props}
value={field.value}
error={field.error}
type="tel"
label="Teléfono:"
placeholder="+57"
required
/>
)}
</Field>
<Field
name="issue"
>
{(field, props) => (
<TextInput
{...props}
value={field.value}
error={field.error}
type="text"
label="Asunto:"
placeholder="Asunto"
required
/>
)}
</Field>
<Field
name="message"
>
{(field, props) => (
<TextInput
{...props}
value={field.value}
error={field.error}
type="text"
label="Mensaje:"
placeholder="Mensaje"
required
/>
)}
</Field>
<button
type="submit"
class={clsx("mx-3 lg:mx-5", styles.btnStyle)}
>
Enviar
</button>
</Form>
</div>
</MUIPaper>
</div>
);
});
@gioboa I did it
Project Repository Vercel Deployment Vercel Project
Get Code
git clone https://github.com/Maikpwwq/qwik-ssg-modular-forms.git
cd ./qwik-ssg-modular-forms
pnpm i
pnpm run start
Go to Form
route through the Link
, and tried to send Form.
Can you try to deploy you app in a different vendor please? eg. Cloudflare It's test is to verify if it's a specific issue of Vercel.
@gioboa take a look at the capture, the error is related with Qwik generated modules
@gioboa I did it
Project Repository Vercel Deployment Vercel Project
Get Code
git clone https://github.com/Maikpwwq/qwik-ssg-modular-forms.git cd ./qwik-ssg-modular-forms pnpm i pnpm run start
Go to
Form
route through theLink
, and tried to send Form.
Thanks, anyway a simpler example with only the specific issue will be better. Btw in your repo you have .env vars and this can be a security issue for you, you should remove them
@gioboa This is a minimal reproduction, abstracted from my main project. I need to solve this issue then I can delete and restore my keys. How to use forms in Qwik? The documentation talks about @modular-forms/qwik
I follow the configuration but it still fails. Really I have prove almost everything, serverless functions on Vercel, server$ functions on Qwik, now actions$ and I am a bit frustrated with this.
It works in development mode in production deploy continue failing.
I will investigate in this issue. hold on
--- UPDATE ---
You are doing SSG. Did you try SSR with Vercel adapter?
I am really sorry that you are running into issues.
Quick search on DOMException: The operation is insecure
Shows this is an issue with FireFox, CORS and HTTPS.
If that is the case, it has nothing to do with Vercel.
The above is the reason why we always ask you to do a minimal reproduction. We get tens of issues every day, we can't look at them all, especially if the reproduction steps are complex involving creating Vercel deployments, only to later realize that it has nothing to do with Vercel and probably has to do with CORS and HTTPs.
We need a simpler reproduction (and I am going to guess that once you have simpler reproduction, you will realize it has nothing to do with Qwik.)
@gioboa Yes this site use Adapters for SSG. This because Vercel deploy only static content. I first tried with Vercel Edge Functions
and also with Vercel server less functions
, I couldn't get it to work using the correct URL to connect serverless functions in afetch call.
dev http://localhost:8888/.netlify/functions/get_contacts/
prod https://nexasoft.netlify.app/.netlify/functions/get_contacts/
I update minimal repository with changes, those works in preview but in deployed project fails.
I think the issues you are running into are because you are trying to run server actions (server$
or routeAction$
) but don't have an actual server environment that runs JS code.
I don't think this is an issue with Qwik but rather with your setup.
This issue is turning into technical support of your issue rather than a generic issue which would benefit all Qwik users.
Here is what we need from you to help you:
I am going to close this issue; once you have a minimal reproduction that shows a Qwik issue feel free to open a new one.
@mhevery currently I have created a minimal reproduction in a Qwik empty project, using the static adapter. Take a look first:
Github Project Repository Vercel Project
Get Code
git clone https://github.com/Maikpwwq/qwik-ssg-modular-forms.git
cd ./qwik-ssg-modular-forms
pnpm i
pnpm run start
Take into account I am trying to build just a simple Form in Qwik. I just need to sent it, that's because I am using my keys to access Mongo Or Supabase.
@mhevery you close it but have not take a look into the minimal reproduction first. Just is this fuck.. page. Is the reason why I ask you to install the dependecies first.
import { component$, $, useTask$ } from "@builder.io/qwik"; // , useSignal
import { isServer } from "@builder.io/qwik/build";
import { createClient } from "@supabase/supabase-js";
// import { v4 as uuidv4 } from 'uuid'
import clsx from "clsx";
import {
routeLoader$,
z,
} from "@builder.io/qwik-city";
import type { InitialValues, SubmitHandler } from "@modular-forms/qwik"; //
import {
useForm,
formAction$,
zodForm$,
reset,
} from "@modular-forms/qwik";
import styles from "~/components/modular-forms/modularForm.module.css";
import { MUITypography, MUIPaper } from "~/integrations/react/mui";
import { TextInput } from "~/components/modular-forms/TextInput";
const SUPABASE_URL = `${import.meta.env.VITE_SUPABASE_URL}`;
const SUPABASE_KEY = `${import.meta.env.VITE_SUPABASE_KEY}`;
type LoginForm = {
name: string;
email: string;
phone: string;
issue: string;
message: string;
};
const loginSchema = z.object({
name: z.string().min(1, "Por favor introduzca su nombre."),
email: z
.string()
.min(1, "Por favor introduzca su email.")
.email("The email address is badly formatted."),
phone: z
.string()
.min(1, "Por favor introduzca su teléfono.")
.min(10, "Tu teléfono debe tener 10 caracteres o más."),
issue: z.string().min(1, "Por favor introduzca su asunto."),
message: z
.string()
.min(1, "Por favor introduzca su mensaje.")
.min(8, "Tu mensaje debe tener 8 caracteres o más."),
});
// Also posible infer typos
// type LoginForm = z.infer<typeof loginSchema>;
// can only be declared in `layout.tsx`, `index.tsx` and `plugin.tsx` inside the src/routes directory
export const useFormLoader = routeLoader$<InitialValues<LoginForm>>(() => ({
name: "",
email: "",
phone: "",
issue: "",
message: "",
}));
type ResponseData = {
customerId: string;
};
export const useFormAction = formAction$<LoginForm, ResponseData>(
async (values) => {
// Runs on SERVER
console.log("useFormAction", values);
try {
// Create a single supabase client for interacting with your database
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY);
const { name, email, phone, issue, message } = values;
// const recordID : string = uuidv4();
// Genera un número aleatorio entre 1 y 1000
// const hexNumber : number = Math.floor(Math.random() * 1000) + 1; // parseInt(recordID.replace(/-/g, ''), 16);
const { data: customer_form, error } = await supabase
.from("customer_form")
.insert([{ created_at: new Date(), name, email, phone, issue, message }])
.select("*");
console.log("supabase contact form", customer_form, error);
if (error) {
throw new Error(`Supabase contact: ${error}`);
}
if (customer_form) {
console.log("Success supabase contact form", customer_form[0].id);
}
return {
status: "success",
message: `Gracias, su mensaje ha sido recibido. ${customer_form[0].id}`,
data: { customerId: customer_form[0].id.toString() },
};
} catch (error) {
console.error(error);
return {
status: "error",
message: `No se ha podido enviar su mensaje. ${error}`,
data: { customerId: "" },
};
}
},
zodForm$(loginSchema),
); // valiForm$(LoginSchema)
export default component$(() => {
// const nav = useNavigate();
// , FieldArray
const [loginForm, { Form, Field }] = useForm<LoginForm, ResponseData>({
loader: useFormLoader(),
action: useFormAction(),
validate: zodForm$(loginSchema),
});
const handleSubmit = $<SubmitHandler<LoginForm>>(
async (values: any, event: any) => {
// Runs on CLIENT
console.log("handleSubmit", values, event);
},
);
const successData = $(async () => {
console.log(
"handleSubmitSuccess",
loginForm.submitted,
loginForm.submitting,
loginForm.response,
);
alert(loginForm.response.message);
reset(loginForm); // , useFormLoader
// clearResponse(loginForm);
// const value = getValue(form, name, options);
// await nav("/");
});
const errorData = $(async () => {
console.log(
"handleSubmitError",
loginForm.submitted,
loginForm.submitting,
loginForm.response,
);
alert(loginForm.response.message);
});
useTask$(({ track }) => {
track(() => loginForm.response.status);
if (isServer) {
return; // Server guard
}
if (
loginForm.submitted &&
loginForm.submitting === false &&
loginForm.response.status === "success"
) {
successData();
} else if (
loginForm.submitted &&
loginForm.submitting === false &&
loginForm.response.status === "error"
) {
errorData();
}
});
return (
<div class="container container-center flex justify-center" style={{}}>
<MUIPaper className={styles.cardContactForm} elevation={16}>
<div class={styles.sheetFormStyle}>
<MUITypography
variant="h6"
color={"var(--qwik-dark-blue)"}
align="center"
>
Formulario de contacto
</MUITypography>
<MUITypography variant="body1" className="pt-2 pb-4" align="center">
Solicita información adicional o una presentación de nuestros
servicios.
</MUITypography>
<Form
class={styles.formFlex}
onSubmit$={handleSubmit}
// preventdefault:submit
// reloadDocument={true}
>
<Field
name="name"
>
{(field, props) => (
<TextInput
{...props}
value={field.value}
error={field.error}
type="text"
label="Nombre:"
placeholder="Nombre"
required
/>
)}
</Field>
<Field
name="email"
>
{(field, props) => (
<TextInput
{...props}
value={field.value}
error={field.error}
type="email"
label="Email:"
placeholder="Correo electrónico"
required
/>
)}
</Field>
<Field
name="phone"
>
{(field, props) => (
<TextInput
{...props}
value={field.value}
error={field.error}
type="tel"
label="Teléfono:"
placeholder="+57"
required
/>
)}
</Field>
<Field
name="issue"
>
{(field, props) => (
<TextInput
{...props}
value={field.value}
error={field.error}
type="text"
label="Asunto:"
placeholder="Asunto"
required
/>
)}
</Field>
<Field
name="message"
>
{(field, props) => (
<TextInput
{...props}
value={field.value}
error={field.error}
type="text"
label="Mensaje:"
placeholder="Mensaje"
required
/>
)}
</Field>
<button
type="submit"
class={clsx("mx-3 lg:mx-5", styles.btnStyle)}
>
Enviar
</button>
</Form>
</div>
</MUIPaper>
</div>
);
});
@Maikpwwq I am sorry you are having trouble with this. But please understand that we get a lot of requests and need to focus on actually fixing issues with Qwik.
(Here is an example of clear reproduction, few lines, no dependencies, stack blitz link.)
So I am really sorry, but we just don't have the time to debug your application.
@mhevery This in not a full application, just a starter template of Qwik, that tried to implement basically a Contact Form following the official documentation of Qwik and @modular-forms/qwik. then I am uploading credentials so is really easy to recreate just clone and run. Finally I update repository to disable SSG, replacing it with Vercel Edge Adapter
. Again everything works in local but do not in production.
If I go to https://vercel.com/maikpwwq/qwik-app I get 404. Where can I see the app running?
@mhevery try with https://qwik-app-psi-sable.vercel.app/
Everything worked, I saw no errors.
It throws not errors but doesn't complete my server call to supabase, as it does in my local. For that reason return that message:
Gracias, su mensaje ha sido recibido. [object Promise]
with [object Promise] instead value of the transaction id.
I can store data in my local correctly, but when I deploy doesn't works anymore.
I think this may have resolved it. https://github.com/BuilderIO/qwik/pull/5041
Which component is affected?
Qwik Runtime
Describe the bug
Static Qwik app
, I use a function to perform some task in my MongoDBexport const addCustomer = server$(async (data) => {...
this when click in a Btn and everything works fine in development environment.<button onClick$={async () => {const resume = await addCustomer(customerRecord); ...}
So I pushed changes to production in
Vercel host
. Then when I send the information again, it Fails giving me this error in browser console.Uncaught (in promise) DOMException: The operation is insecure.
.HELP!
Reproduction
I create a new Qwik app, with react and static adapters. Then I have in header a click
link
to visitForm
route. Project Repository Vercel Deployment Vercel ProjectSteps to reproduce
Get Code
Go to
Form
route through theLink
, and tried to send Form.System Info
Additional Information
No response