mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 00:03:33 +10:00
feat: add guards and subscription ui
This commit is contained in:
72
apps/web/components/billing-plans.tsx
Normal file
72
apps/web/components/billing-plans.tsx
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import { useMemo, useState } from "react";
|
||||||
|
import { classNames } from "@documenso/lib";
|
||||||
|
import { STRIPE_PLANS, fetchCheckoutSession, useSubscription } from "@documenso/lib/stripe";
|
||||||
|
import { Button } from "@documenso/ui";
|
||||||
|
import { Switch } from "@headlessui/react";
|
||||||
|
|
||||||
|
export const BillingPlans = () => {
|
||||||
|
const { subscription, hasSubscription, isLoading } = useSubscription();
|
||||||
|
const [isAnnual, setIsAnnual] = useState(true);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{!subscription &&
|
||||||
|
STRIPE_PLANS.map((plan) => (
|
||||||
|
<div key={plan.name} className="rounded-lg border py-4 px-6">
|
||||||
|
<h3 className="text-center text-lg font-medium leading-6 text-gray-900">{plan.name}</h3>
|
||||||
|
|
||||||
|
<div className="my-4 flex justify-center">
|
||||||
|
<Switch.Group as="div" className="flex items-center">
|
||||||
|
<Switch
|
||||||
|
checked={isAnnual}
|
||||||
|
onChange={setIsAnnual}
|
||||||
|
className={classNames(
|
||||||
|
isAnnual ? "bg-neon-600" : "bg-gray-200",
|
||||||
|
"relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-neon-600 focus:ring-offset-2"
|
||||||
|
)}>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
className={classNames(
|
||||||
|
isAnnual ? "translate-x-5" : "translate-x-0",
|
||||||
|
"pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Switch>
|
||||||
|
<Switch.Label as="span" className="ml-3 text-sm">
|
||||||
|
<span className="font-medium text-gray-900">Annual billing</span>{" "}
|
||||||
|
<span className="text-gray-500">(Save $60)</span>
|
||||||
|
</Switch.Label>
|
||||||
|
</Switch.Group>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="mt-2 text-center text-gray-500">
|
||||||
|
${(isAnnual ? plan.prices.yearly.price : plan.prices.monthly.price).toFixed(2)}{" "}
|
||||||
|
<span className="text-sm text-gray-400">{isAnnual ? "/yr" : "/mo"}</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p className="mt-4 text-center text-sm text-gray-500">
|
||||||
|
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Corrupti voluptates delectus
|
||||||
|
doloremque hic vel!
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="mt-4">
|
||||||
|
<Button
|
||||||
|
className="w-full"
|
||||||
|
disabled={isLoading}
|
||||||
|
onClick={() =>
|
||||||
|
fetchCheckoutSession({
|
||||||
|
priceId: isAnnual ? plan.prices.yearly.priceId : plan.prices.monthly.priceId,
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.success) {
|
||||||
|
window.location.href = res.url;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}>
|
||||||
|
Subscribe
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -4,9 +4,18 @@ import Link from "next/link";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { updateUser } from "@documenso/features";
|
import { updateUser } from "@documenso/features";
|
||||||
import { getUser } from "@documenso/lib/api";
|
import { getUser } from "@documenso/lib/api";
|
||||||
|
import {
|
||||||
|
STRIPE_PLANS,
|
||||||
|
fetchCheckoutSession,
|
||||||
|
fetchPortalSession,
|
||||||
|
isSubscriptionsEnabled,
|
||||||
|
useSubscription,
|
||||||
|
} from "@documenso/lib/stripe";
|
||||||
|
import { SubscriptionStatus } from '@prisma/client'
|
||||||
import { Button } from "@documenso/ui";
|
import { Button } from "@documenso/ui";
|
||||||
import { CreditCardIcon, KeyIcon, UserCircleIcon } from "@heroicons/react/24/outline";
|
import { CreditCardIcon, KeyIcon, UserCircleIcon } from "@heroicons/react/24/outline";
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
|
import { BillingPlans } from "./billing-plans";
|
||||||
|
|
||||||
const subNavigation = [
|
const subNavigation = [
|
||||||
{
|
{
|
||||||
@ -35,6 +44,7 @@ function classNames(...classes: any) {
|
|||||||
|
|
||||||
export default function Setttings() {
|
export default function Setttings() {
|
||||||
const session = useSession();
|
const session = useSession();
|
||||||
|
const { subscription, hasSubscription } = useSubscription();
|
||||||
const [user, setUser] = useState({
|
const [user, setUser] = useState({
|
||||||
email: "",
|
email: "",
|
||||||
name: "",
|
name: "",
|
||||||
@ -179,24 +189,63 @@ export default function Setttings() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
hidden={subNavigation.filter((e) => e.current)[0]?.name !== subNavigation?.[2]?.name}
|
hidden={
|
||||||
|
subNavigation.find((e) => e.current)?.name !== subNavigation?.[2]?.name
|
||||||
|
}
|
||||||
className="min-h-[251px] divide-y divide-gray-200 lg:col-span-9">
|
className="min-h-[251px] divide-y divide-gray-200 lg:col-span-9">
|
||||||
{/* Billing section */}
|
{/* Billing section */}
|
||||||
<div className="py-6 px-4 sm:p-6 lg:pb-8">
|
<div className="py-6 px-4 sm:p-6 lg:pb-8">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-medium leading-6 text-gray-900">Billing</h2>
|
<h2 className="text-lg font-medium leading-6 text-gray-900">Billing</h2>
|
||||||
|
|
||||||
|
{!isSubscriptionsEnabled() && (
|
||||||
|
<p className="mt-2 text-sm text-gray-500">
|
||||||
|
Subscriptions are not enabled on this instance, you have nothing to do here.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isSubscriptionsEnabled() && <>
|
||||||
<p className="mt-1 text-sm text-gray-500">
|
<p className="mt-1 text-sm text-gray-500">
|
||||||
Your subscription is currently <strong>{user?.subscription ? 'Active' : 'Inactive'}</strong>.
|
Your subscription is currently{" "}
|
||||||
|
<strong>{subscription?.status && subscription?.status !== SubscriptionStatus.INACTIVE ? "Active" : "Inactive"}</strong>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
{subscription?.status === SubscriptionStatus.PAST_DUE && (
|
||||||
|
<p className="mt-1 text-sm text-red-500">
|
||||||
|
Your subscription is past due. Please update your payment details to continue
|
||||||
|
using the service without interruption.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
<p className="mt-1 text-sm text-gray-500">
|
<p className="mt-1 text-sm text-gray-500">
|
||||||
We use Stripe to process payments. Your card details are never stored on our
|
Lorem ipsum dolor sit amet consectetur adipisicing elit. Est consectetur magnam
|
||||||
servers.
|
illo aperiam expedita porro eos eum nam sapiente.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="mt-8">
|
<div className="mt-8">
|
||||||
<Button onClick={() => {}}>Manage my subscription</Button>
|
<div className="grid grid-cols-1 lg:grid-cols-2">
|
||||||
|
|
||||||
|
<BillingPlans />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{subscription && (
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
if (isSubscriptionsEnabled() && subscription?.customerId) {
|
||||||
|
fetchPortalSession({
|
||||||
|
id: subscription.customerId,
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.success) {
|
||||||
|
window.location.href = res.url;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
Manage my subscription
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { ReactElement, ReactNode } from "react";
|
import { ReactElement, ReactNode } from "react";
|
||||||
import { NextPage } from "next";
|
import { NextPage } from "next";
|
||||||
import type { AppProps } from "next/app";
|
import type { AppProps } from "next/app";
|
||||||
|
import { SubscriptionProvider } from "@documenso/lib/stripe/providers/subscription-provider";
|
||||||
import "../../../node_modules/placeholder-loading/src/scss/placeholder-loading.scss";
|
import "../../../node_modules/placeholder-loading/src/scss/placeholder-loading.scss";
|
||||||
import "../../../node_modules/react-resizable/css/styles.css";
|
import "../../../node_modules/react-resizable/css/styles.css";
|
||||||
import "../styles/tailwind.css";
|
import "../styles/tailwind.css";
|
||||||
@ -20,13 +21,15 @@ type AppPropsWithLayout = AppProps & {
|
|||||||
|
|
||||||
export default function App({
|
export default function App({
|
||||||
Component,
|
Component,
|
||||||
pageProps: { session, ...pageProps },
|
pageProps: { session, initialSubscription, ...pageProps },
|
||||||
}: AppPropsWithLayout) {
|
}: AppPropsWithLayout) {
|
||||||
const getLayout = Component.getLayout || ((page: any) => page);
|
const getLayout = Component.getLayout || ((page: any) => page);
|
||||||
return (
|
return (
|
||||||
<SessionProvider session={session}>
|
<SessionProvider session={session}>
|
||||||
<Toaster position="top-center"></Toaster>
|
<SubscriptionProvider initialSubscription={initialSubscription}>
|
||||||
|
<Toaster position="top-center" />
|
||||||
{getLayout(<Component {...pageProps} />)}
|
{getLayout(<Component {...pageProps} />)}
|
||||||
|
</SubscriptionProvider>
|
||||||
</SessionProvider>
|
</SessionProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
import { Head, Html, Main, NextScript } from "next/document";
|
import { Head, Html, Main, NextScript } from "next/document";
|
||||||
import Script from "next/script";
|
|
||||||
|
|
||||||
export default function Document(props) {
|
|
||||||
let pageProps = props.__NEXT_DATA__?.props?.pageProps;
|
|
||||||
|
|
||||||
|
export default function Document() {
|
||||||
return (
|
return (
|
||||||
<Html className="h-full scroll-smooth bg-gray-100 font-normal antialiased" lang="en">
|
<Html className="h-full scroll-smooth bg-gray-100 font-normal antialiased" lang="en">
|
||||||
<Head>
|
<Head>
|
||||||
@ -4,6 +4,7 @@ import { defaultHandler, defaultResponder } from "@documenso/lib/server";
|
|||||||
import { getUserFromToken } from "@documenso/lib/server";
|
import { getUserFromToken } from "@documenso/lib/server";
|
||||||
import prisma from "@documenso/prisma";
|
import prisma from "@documenso/prisma";
|
||||||
import formidable from "formidable";
|
import formidable from "formidable";
|
||||||
|
import { isSubscribedServer } from "@documenso/lib/stripe";
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
api: {
|
api: {
|
||||||
@ -15,7 +16,17 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
const form = formidable();
|
const form = formidable();
|
||||||
|
|
||||||
const user = await getUserFromToken(req, res);
|
const user = await getUserFromToken(req, res);
|
||||||
if (!user) return;
|
if (!user) {
|
||||||
|
return res.status(401).end();
|
||||||
|
};
|
||||||
|
|
||||||
|
const isSubscribed = await isSubscribedServer(req);
|
||||||
|
|
||||||
|
if (!isSubscribed) {
|
||||||
|
throw new Error("User is not subscribed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
form.parse(req, async (err, fields, files) => {
|
form.parse(req, async (err, fields, files) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
|
|||||||
@ -20,12 +20,15 @@ import {
|
|||||||
} from "@prisma/client";
|
} from "@prisma/client";
|
||||||
import { truncate } from "fs";
|
import { truncate } from "fs";
|
||||||
import { Tooltip as ReactTooltip } from "react-tooltip";
|
import { Tooltip as ReactTooltip } from "react-tooltip";
|
||||||
|
import { useSubscription } from "@documenso/lib/stripe";
|
||||||
|
|
||||||
type FormValues = {
|
type FormValues = {
|
||||||
document: File;
|
document: File;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DashboardPage: NextPageWithLayout = (props: any) => {
|
const DashboardPage: NextPageWithLayout = (props: any) => {
|
||||||
|
const { hasSubscription } = useSubscription();
|
||||||
|
|
||||||
const stats = [
|
const stats = [
|
||||||
{
|
{
|
||||||
name: "Draft",
|
name: "Draft",
|
||||||
@ -90,9 +93,12 @@ const DashboardPage: NextPageWithLayout = (props: any) => {
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (hasSubscription) {
|
||||||
document?.getElementById("fileUploadHelper")?.click();
|
document?.getElementById("fileUploadHelper")?.click();
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
className="group hover:border-neon-600 duration-200 relative block w-full cursor-pointer rounded-lg border-2 border-dashed border-gray-300 p-12 text-center focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
|
aria-disabled={!hasSubscription}
|
||||||
|
className="group hover:border-neon-600 duration-200 relative block w-full cursor-pointer rounded-lg border-2 border-dashed border-gray-300 p-12 text-center focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 aria-disabled:opacity-50 aria-disabled:pointer-events-none">
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
className="mx-auto h-12 w-12 text-gray-400 group-hover:text-gray-700 duration-200"
|
className="mx-auto h-12 w-12 text-gray-400 group-hover:text-gray-700 duration-200"
|
||||||
|
|||||||
@ -20,9 +20,11 @@ import {
|
|||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import { DocumentStatus } from "@prisma/client";
|
import { DocumentStatus } from "@prisma/client";
|
||||||
import { Tooltip as ReactTooltip } from "react-tooltip";
|
import { Tooltip as ReactTooltip } from "react-tooltip";
|
||||||
|
import { useSubscription } from "@documenso/lib/stripe";
|
||||||
|
|
||||||
const DocumentsPage: NextPageWithLayout = (props: any) => {
|
const DocumentsPage: NextPageWithLayout = (props: any) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { hasSubscription } = useSubscription();
|
||||||
const [documents, setDocuments]: any[] = useState([]);
|
const [documents, setDocuments]: any[] = useState([]);
|
||||||
const [filteredDocuments, setFilteredDocuments] = useState([]);
|
const [filteredDocuments, setFilteredDocuments] = useState([]);
|
||||||
|
|
||||||
@ -135,6 +137,7 @@ const DocumentsPage: NextPageWithLayout = (props: any) => {
|
|||||||
<div className="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
|
<div className="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
|
||||||
<Button
|
<Button
|
||||||
icon={DocumentPlusIcon}
|
icon={DocumentPlusIcon}
|
||||||
|
disabled={!hasSubscription}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
document?.getElementById("fileUploadHelper")?.click();
|
document?.getElementById("fileUploadHelper")?.click();
|
||||||
}}>
|
}}>
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { useRouter } from "next/router";
|
|||||||
import { NEXT_PUBLIC_WEBAPP_URL } from "@documenso/lib";
|
import { NEXT_PUBLIC_WEBAPP_URL } from "@documenso/lib";
|
||||||
import { getDocument } from "@documenso/lib/query";
|
import { getDocument } from "@documenso/lib/query";
|
||||||
import { getUserFromToken } from "@documenso/lib/server";
|
import { getUserFromToken } from "@documenso/lib/server";
|
||||||
|
import { useSubscription } from "@documenso/lib/stripe";
|
||||||
import { Breadcrumb, Button } from "@documenso/ui";
|
import { Breadcrumb, Button } from "@documenso/ui";
|
||||||
import PDFEditor from "../../../components/editor/pdf-editor";
|
import PDFEditor from "../../../components/editor/pdf-editor";
|
||||||
import Layout from "../../../components/layout";
|
import Layout from "../../../components/layout";
|
||||||
@ -14,6 +15,7 @@ import { Document as PrismaDocument } from "@prisma/client";
|
|||||||
|
|
||||||
const DocumentsDetailPage: NextPageWithLayout = (props: any) => {
|
const DocumentsDetailPage: NextPageWithLayout = (props: any) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { hasSubscription } = useSubscription();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import {
|
|||||||
import { DocumentStatus, Document as PrismaDocument, Recipient } from "@prisma/client";
|
import { DocumentStatus, Document as PrismaDocument, Recipient } from "@prisma/client";
|
||||||
import { FormProvider, useFieldArray, useForm, useWatch } from "react-hook-form";
|
import { FormProvider, useFieldArray, useForm, useWatch } from "react-hook-form";
|
||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
|
import { useSubscription } from "@documenso/lib/stripe";
|
||||||
|
|
||||||
export type FormValues = {
|
export type FormValues = {
|
||||||
signers: Array<Pick<Recipient, 'id' | 'email' | 'name' | 'sendStatus' | 'readStatus' | 'signingStatus'>>;
|
signers: Array<Pick<Recipient, 'id' | 'email' | 'name' | 'sendStatus' | 'readStatus' | 'signingStatus'>>;
|
||||||
@ -29,6 +30,7 @@ export type FormValues = {
|
|||||||
type FormSigner = FormValues["signers"][number];
|
type FormSigner = FormValues["signers"][number];
|
||||||
|
|
||||||
const RecipientsPage: NextPageWithLayout = (props: any) => {
|
const RecipientsPage: NextPageWithLayout = (props: any) => {
|
||||||
|
const { hasSubscription } = useSubscription();
|
||||||
const title: string = `"` + props?.document?.title + `"` + "Recipients | Documenso";
|
const title: string = `"` + props?.document?.title + `"` + "Recipients | Documenso";
|
||||||
const breadcrumbItems = [
|
const breadcrumbItems = [
|
||||||
{
|
{
|
||||||
@ -116,6 +118,7 @@ const RecipientsPage: NextPageWithLayout = (props: any) => {
|
|||||||
: setOpen(true);
|
: setOpen(true);
|
||||||
}}
|
}}
|
||||||
disabled={
|
disabled={
|
||||||
|
!hasSubscription ||
|
||||||
(formValues.length || 0) === 0 ||
|
(formValues.length || 0) === 0 ||
|
||||||
!formValues.some(
|
!formValues.some(
|
||||||
(r) => r.email && !hasEmailError(r) && r.sendStatus === "NOT_SENT"
|
(r) => r.email && !hasEmailError(r) && r.sendStatus === "NOT_SENT"
|
||||||
|
|||||||
192
package-lock.json
generated
192
package-lock.json
generated
@ -2023,6 +2023,14 @@
|
|||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/bytes": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/call-bind": {
|
"node_modules/call-bind": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
||||||
@ -2296,6 +2304,14 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/content-type": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cookie": {
|
"node_modules/cookie": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
||||||
@ -2485,6 +2501,14 @@
|
|||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/depd": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/detective": {
|
"node_modules/detective": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz",
|
||||||
@ -3954,6 +3978,21 @@
|
|||||||
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/http-errors": {
|
||||||
|
"version": "1.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
|
||||||
|
"integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
|
||||||
|
"dependencies": {
|
||||||
|
"depd": "~1.1.2",
|
||||||
|
"inherits": "2.0.4",
|
||||||
|
"setprototypeof": "1.1.1",
|
||||||
|
"statuses": ">= 1.5.0 < 2",
|
||||||
|
"toidentifier": "1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/http-signature": {
|
"node_modules/http-signature": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||||
@ -3972,7 +4011,6 @@
|
|||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safer-buffer": ">= 2.1.2 < 3"
|
"safer-buffer": ">= 2.1.2 < 3"
|
||||||
},
|
},
|
||||||
@ -4033,8 +4071,7 @@
|
|||||||
"node_modules/inherits": {
|
"node_modules/inherits": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/inquirer": {
|
"node_modules/inquirer": {
|
||||||
"version": "6.5.2",
|
"version": "6.5.2",
|
||||||
@ -4995,6 +5032,27 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/micro": {
|
||||||
|
"version": "10.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/micro/-/micro-10.0.1.tgz",
|
||||||
|
"integrity": "sha512-9uwZSsUrqf6+4FLLpiPj5TRWQv5w5uJrJwsx1LR/TjqvQmKC1XnGQ9OHrFwR3cbZ46YqPqxO/XJCOpWnqMPw2Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"arg": "4.1.0",
|
||||||
|
"content-type": "1.0.4",
|
||||||
|
"raw-body": "2.4.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"micro": "dist/src/bin/micro.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micro/node_modules/arg": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg=="
|
||||||
|
},
|
||||||
"node_modules/micromatch": {
|
"node_modules/micromatch": {
|
||||||
"version": "4.0.5",
|
"version": "4.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
||||||
@ -6203,6 +6261,20 @@
|
|||||||
"safe-buffer": "^5.1.0"
|
"safe-buffer": "^5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/raw-body": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==",
|
||||||
|
"dependencies": {
|
||||||
|
"bytes": "3.1.0",
|
||||||
|
"http-errors": "1.7.3",
|
||||||
|
"iconv-lite": "0.4.24",
|
||||||
|
"unpipe": "1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react": {
|
"node_modules/react": {
|
||||||
"version": "18.2.0",
|
"version": "18.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
||||||
@ -6713,6 +6785,11 @@
|
|||||||
"randombytes": "^2.1.0"
|
"randombytes": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/setprototypeof": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
|
||||||
|
},
|
||||||
"node_modules/shebang-command": {
|
"node_modules/shebang-command": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
@ -6873,6 +6950,14 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/statuses": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/stop-iteration-iterator": {
|
"node_modules/stop-iteration-iterator": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
|
||||||
@ -7436,6 +7521,14 @@
|
|||||||
"node": ">=8.0"
|
"node": ">=8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/toidentifier": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tough-cookie": {
|
"node_modules/tough-cookie": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||||
@ -7666,6 +7759,14 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/unpipe": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/update-browserslist-db": {
|
"node_modules/update-browserslist-db": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
|
||||||
@ -8039,7 +8140,10 @@
|
|||||||
"name": "@documenso/lib",
|
"name": "@documenso/lib",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@documenso/prisma": "*",
|
||||||
|
"@prisma/client": "^4.8.1",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
|
"micro": "^10.0.1",
|
||||||
"stripe": "^12.4.0"
|
"stripe": "^12.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -8348,7 +8452,10 @@
|
|||||||
"@documenso/lib": {
|
"@documenso/lib": {
|
||||||
"version": "file:packages/lib",
|
"version": "file:packages/lib",
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"@documenso/prisma": "*",
|
||||||
|
"@prisma/client": "^4.8.1",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
|
"micro": "^10.0.1",
|
||||||
"stripe": "^12.4.0"
|
"stripe": "^12.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -9616,6 +9723,11 @@
|
|||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"bytes": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
|
||||||
|
},
|
||||||
"call-bind": {
|
"call-bind": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
||||||
@ -9825,6 +9937,11 @@
|
|||||||
"xdg-basedir": "^3.0.0"
|
"xdg-basedir": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"content-type": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
|
||||||
|
},
|
||||||
"cookie": {
|
"cookie": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
||||||
@ -9967,6 +10084,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
|
||||||
},
|
},
|
||||||
|
"depd": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="
|
||||||
|
},
|
||||||
"detective": {
|
"detective": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz",
|
||||||
@ -11113,6 +11235,18 @@
|
|||||||
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"http-errors": {
|
||||||
|
"version": "1.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
|
||||||
|
"integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
|
||||||
|
"requires": {
|
||||||
|
"depd": "~1.1.2",
|
||||||
|
"inherits": "2.0.4",
|
||||||
|
"setprototypeof": "1.1.1",
|
||||||
|
"statuses": ">= 1.5.0 < 2",
|
||||||
|
"toidentifier": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"http-signature": {
|
"http-signature": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||||
@ -11127,7 +11261,6 @@
|
|||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"safer-buffer": ">= 2.1.2 < 3"
|
"safer-buffer": ">= 2.1.2 < 3"
|
||||||
}
|
}
|
||||||
@ -11173,8 +11306,7 @@
|
|||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"inquirer": {
|
"inquirer": {
|
||||||
"version": "6.5.2",
|
"version": "6.5.2",
|
||||||
@ -11910,6 +12042,23 @@
|
|||||||
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"micro": {
|
||||||
|
"version": "10.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/micro/-/micro-10.0.1.tgz",
|
||||||
|
"integrity": "sha512-9uwZSsUrqf6+4FLLpiPj5TRWQv5w5uJrJwsx1LR/TjqvQmKC1XnGQ9OHrFwR3cbZ46YqPqxO/XJCOpWnqMPw2Q==",
|
||||||
|
"requires": {
|
||||||
|
"arg": "4.1.0",
|
||||||
|
"content-type": "1.0.4",
|
||||||
|
"raw-body": "2.4.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"arg": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"micromatch": {
|
"micromatch": {
|
||||||
"version": "4.0.5",
|
"version": "4.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
||||||
@ -12689,6 +12838,17 @@
|
|||||||
"safe-buffer": "^5.1.0"
|
"safe-buffer": "^5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"raw-body": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==",
|
||||||
|
"requires": {
|
||||||
|
"bytes": "3.1.0",
|
||||||
|
"http-errors": "1.7.3",
|
||||||
|
"iconv-lite": "0.4.24",
|
||||||
|
"unpipe": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react": {
|
"react": {
|
||||||
"version": "18.2.0",
|
"version": "18.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
||||||
@ -13038,6 +13198,11 @@
|
|||||||
"randombytes": "^2.1.0"
|
"randombytes": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"setprototypeof": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
|
||||||
|
},
|
||||||
"shebang-command": {
|
"shebang-command": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
@ -13166,6 +13331,11 @@
|
|||||||
"tweetnacl": "~0.14.0"
|
"tweetnacl": "~0.14.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"statuses": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="
|
||||||
|
},
|
||||||
"stop-iteration-iterator": {
|
"stop-iteration-iterator": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
|
||||||
@ -13582,6 +13752,11 @@
|
|||||||
"is-number": "^7.0.0"
|
"is-number": "^7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"toidentifier": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
|
||||||
|
},
|
||||||
"tough-cookie": {
|
"tough-cookie": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||||
@ -13753,6 +13928,11 @@
|
|||||||
"crypto-random-string": "^1.0.0"
|
"crypto-random-string": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"unpipe": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
|
||||||
|
},
|
||||||
"update-browserslist-db": {
|
"update-browserslist-db": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
"docker:compose": "docker-compose -f ./docker/compose-without-app.yml",
|
"docker:compose": "docker-compose -f ./docker/compose-without-app.yml",
|
||||||
"docker:compose-up": "npm run docker:compose -- up -d",
|
"docker:compose-up": "npm run docker:compose -- up -d",
|
||||||
"docker:compose-down": "npm run docker:compose -- down",
|
"docker:compose-down": "npm run docker:compose -- down",
|
||||||
|
"stripe:listen": "stripe listen --forward-to localhost:3000/api/stripe/webhook",
|
||||||
"dx": "npm install && run-s docker:compose-up db-migrate:dev",
|
"dx": "npm install && run-s docker:compose-up db-migrate:dev",
|
||||||
"d": "npm install && run-s docker:compose-up db-migrate:dev && npm run db-seed && npm run dev"
|
"d": "npm install && run-s docker:compose-up db-migrate:dev && npm run db-seed && npm run dev"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
|
import { ChangeEvent } from "react";
|
||||||
import router from "next/router";
|
import router from "next/router";
|
||||||
import { NEXT_PUBLIC_WEBAPP_URL } from "../lib/constants";
|
import { NEXT_PUBLIC_WEBAPP_URL } from "../lib/constants";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { ChangeEvent } from "react";
|
|
||||||
|
|
||||||
export const uploadDocument = async (event: ChangeEvent) => {
|
export const uploadDocument = async (event: ChangeEvent) => {
|
||||||
if (event.target instanceof HTMLInputElement && event.target?.files && event.target.files[0]) {
|
if (event.target instanceof HTMLInputElement && event.target?.files && event.target.files[0]) {
|
||||||
@ -16,24 +16,28 @@ export const uploadDocument = async (event: ChangeEvent) => {
|
|||||||
|
|
||||||
body.append("document", document || "");
|
body.append("document", document || "");
|
||||||
|
|
||||||
await toast
|
await toast.promise(
|
||||||
.promise(
|
|
||||||
fetch("/api/documents", {
|
fetch("/api/documents", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body,
|
body,
|
||||||
|
}).then((response: Response) => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Could not upload document");
|
||||||
|
}
|
||||||
|
|
||||||
|
response.json().then((createdDocumentIdFromBody) => {
|
||||||
|
router.push(
|
||||||
|
`${NEXT_PUBLIC_WEBAPP_URL}/documents/${createdDocumentIdFromBody}/recipients`
|
||||||
|
);
|
||||||
|
});
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
loading: "Uploading document...",
|
loading: "Uploading document...",
|
||||||
success: `${fileName} uploaded successfully.`,
|
success: `${fileName} uploaded successfully.`,
|
||||||
error: "Could not upload document :/",
|
error: "Could not upload document :/",
|
||||||
}
|
}
|
||||||
)
|
).catch((_err) => {
|
||||||
.then((response: Response) => {
|
// Do nothing
|
||||||
response.json().then((createdDocumentIdFromBody) => {
|
|
||||||
router.push(
|
|
||||||
`${NEXT_PUBLIC_WEBAPP_URL}/documents/${createdDocumentIdFromBody}/recipients`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,14 +1,15 @@
|
|||||||
export const STRIPE_PLANS = [
|
export const STRIPE_PLANS = [
|
||||||
{
|
{
|
||||||
name: "Community Plan (Monthly)",
|
name: "Community Plan",
|
||||||
period: "monthly",
|
prices: {
|
||||||
|
monthly: {
|
||||||
price: 30,
|
price: 30,
|
||||||
priceId: process.env.NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_MONTHLY_PRICE_ID ?? "",
|
priceId: process.env.NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_MONTHLY_PRICE_ID ?? "",
|
||||||
},
|
},
|
||||||
{
|
yearly: {
|
||||||
name: "Community Plan (Yearly)",
|
|
||||||
period: "yearly",
|
|
||||||
price: 300,
|
price: 300,
|
||||||
priceId: process.env.NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_YEARLY_PRICE_ID ?? "",
|
priceId: process.env.NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_YEARLY_PRICE_ID ?? "",
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user