fix build
This commit is contained in:
@@ -22,11 +22,8 @@ import { isLocalhost } from "~/utils/client";
|
|||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
region: z.string(),
|
region: z.string(),
|
||||||
unsendUrl: z.string().url(),
|
unsendUrl: z.string().url(),
|
||||||
sendRate: z.preprocess((val) => Number(val), z.number()),
|
sendRate: z.coerce.number(),
|
||||||
transactionalQuota: z.preprocess(
|
transactionalQuota: z.coerce.number().min(0).max(100),
|
||||||
(val) => Number(val),
|
|
||||||
z.number().min(0).max(100)
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
type SesSettingsProps = {
|
type SesSettingsProps = {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
export function useInterval(callback: () => void, delay: number | null) {
|
export function useInterval(callback: () => void, delay: number | null) {
|
||||||
const savedCallback = useRef<() => void>();
|
const savedCallback = useRef<(() => void) | null>(null);
|
||||||
|
|
||||||
// Remember the latest callback.
|
// Remember the latest callback.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@@ -125,13 +125,21 @@ export async function syncStripeData(customerId: string) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!subscription.items.data[0]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await db.subscription.upsert({
|
await db.subscription.upsert({
|
||||||
where: { id: subscription.id },
|
where: { id: subscription.id },
|
||||||
update: {
|
update: {
|
||||||
status: subscription.status,
|
status: subscription.status,
|
||||||
priceId: subscription.items.data[0]?.price?.id || "",
|
priceId: subscription.items.data[0]?.price?.id || "",
|
||||||
currentPeriodEnd: new Date(subscription.current_period_end * 1000),
|
currentPeriodEnd: new Date(
|
||||||
currentPeriodStart: new Date(subscription.current_period_start * 1000),
|
subscription.items.data[0]?.current_period_end * 1000
|
||||||
|
),
|
||||||
|
currentPeriodStart: new Date(
|
||||||
|
subscription.items.data[0]?.current_period_start * 1000
|
||||||
|
),
|
||||||
cancelAtPeriodEnd: subscription.cancel_at
|
cancelAtPeriodEnd: subscription.cancel_at
|
||||||
? new Date(subscription.cancel_at * 1000)
|
? new Date(subscription.cancel_at * 1000)
|
||||||
: null,
|
: null,
|
||||||
@@ -142,8 +150,12 @@ export async function syncStripeData(customerId: string) {
|
|||||||
id: subscription.id,
|
id: subscription.id,
|
||||||
status: subscription.status,
|
status: subscription.status,
|
||||||
priceId: subscription.items.data[0]?.price?.id || "",
|
priceId: subscription.items.data[0]?.price?.id || "",
|
||||||
currentPeriodEnd: new Date(subscription.current_period_end * 1000),
|
currentPeriodEnd: new Date(
|
||||||
currentPeriodStart: new Date(subscription.current_period_start * 1000),
|
subscription.items.data[0]?.current_period_end * 1000
|
||||||
|
),
|
||||||
|
currentPeriodStart: new Date(
|
||||||
|
subscription.items.data[0]?.current_period_start * 1000
|
||||||
|
),
|
||||||
cancelAtPeriodEnd: subscription.cancel_at
|
cancelAtPeriodEnd: subscription.cancel_at
|
||||||
? new Date(subscription.cancel_at * 1000)
|
? new Date(subscription.cancel_at * 1000)
|
||||||
: null,
|
: null,
|
||||||
|
@@ -6,7 +6,7 @@ const METER_EVENT_NAME = "unsend_usage";
|
|||||||
|
|
||||||
export async function sendUsageToStripe(customerId: string, usage: number) {
|
export async function sendUsageToStripe(customerId: string, usage: number) {
|
||||||
const stripe = new Stripe(env.STRIPE_SECRET_KEY!, {
|
const stripe = new Stripe(env.STRIPE_SECRET_KEY!, {
|
||||||
apiVersion: "2025-01-27.acacia",
|
apiVersion: "2025-03-31.basil",
|
||||||
});
|
});
|
||||||
|
|
||||||
const meterEvent = await stripe.billing.meterEvents.create({
|
const meterEvent = await stripe.billing.meterEvents.create({
|
||||||
|
@@ -44,7 +44,7 @@ export type SlashCommandItem = {
|
|||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
searchTerms: string[];
|
searchTerms: string[];
|
||||||
icon: JSX.Element;
|
icon: ReactNode;
|
||||||
command: (options: CommandProps) => void;
|
command: (options: CommandProps) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ import { MenuProps } from "../types";
|
|||||||
import { LinkPreviewPanel } from "../components/panels/LinkPreviewPanel";
|
import { LinkPreviewPanel } from "../components/panels/LinkPreviewPanel";
|
||||||
import { LinkEditorPanel } from "../components/panels/LinkEditorPanel";
|
import { LinkEditorPanel } from "../components/panels/LinkEditorPanel";
|
||||||
|
|
||||||
export const LinkMenu = ({ editor, appendTo }: MenuProps): JSX.Element => {
|
export const LinkMenu = ({ editor, appendTo }: MenuProps): React.ReactNode => {
|
||||||
const [showEdit, setShowEdit] = useState(false);
|
const [showEdit, setShowEdit] = useState(false);
|
||||||
|
|
||||||
const shouldShow = useCallback(() => {
|
const shouldShow = useCallback(() => {
|
||||||
|
@@ -10,7 +10,7 @@ import {
|
|||||||
Link,
|
Link,
|
||||||
Heading,
|
Heading,
|
||||||
Hr,
|
Hr,
|
||||||
Button,
|
Butan as Button,
|
||||||
Img,
|
Img,
|
||||||
Preview,
|
Preview,
|
||||||
Row,
|
Row,
|
||||||
@@ -271,17 +271,17 @@ export class EmailRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// `renderMark` will call the method of the corresponding mark type
|
// `renderMark` will call the method of the corresponding mark type
|
||||||
private renderMark(node: JSONContent): JSX.Element {
|
private renderMark(node: JSONContent): React.ReactNode {
|
||||||
// It will wrap the text with the corresponding mark type
|
// It will wrap the text with the corresponding mark type
|
||||||
const text = node.text || <> </>;
|
const text = node.text || <> </>;
|
||||||
const marks = node.marks || [];
|
const marks = node.marks || [];
|
||||||
|
|
||||||
return marks.reduce(
|
return marks.reduce<React.ReactNode>(
|
||||||
(acc, mark) => {
|
(acc, mark) => {
|
||||||
const type = mark.type;
|
const type = mark.type;
|
||||||
if (type in this) {
|
if (type in this) {
|
||||||
// @ts-expect-error - `this` is not assignable to type 'never'
|
// @ts-expect-error - `this` is not assignable to type 'never'
|
||||||
return this[type]?.(mark, acc) as JSX.Element;
|
return this[type]?.(mark, acc) as React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(`Mark type "${type}" is not supported.`);
|
throw new Error(`Mark type "${type}" is not supported.`);
|
||||||
@@ -293,7 +293,7 @@ export class EmailRenderer {
|
|||||||
private getMappedContent(
|
private getMappedContent(
|
||||||
node: JSONContent,
|
node: JSONContent,
|
||||||
options?: NodeOptions
|
options?: NodeOptions
|
||||||
): JSX.Element[] {
|
): React.ReactNode[] {
|
||||||
return node.content
|
return node.content
|
||||||
?.map((childNode) => {
|
?.map((childNode) => {
|
||||||
const component = this.renderNode(childNode, options);
|
const component = this.renderNode(childNode, options);
|
||||||
@@ -303,18 +303,18 @@ export class EmailRenderer {
|
|||||||
|
|
||||||
return <Fragment key={generateKey()}>{component}</Fragment>;
|
return <Fragment key={generateKey()}>{component}</Fragment>;
|
||||||
})
|
})
|
||||||
.filter((n) => n !== null) as JSX.Element[];
|
.filter((n) => n !== null) as React.ReactNode[];
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderNode(
|
private renderNode(
|
||||||
node: JSONContent,
|
node: JSONContent,
|
||||||
options: NodeOptions = {}
|
options: NodeOptions = {}
|
||||||
): JSX.Element | null {
|
): React.ReactNode | null {
|
||||||
const type = node.type || "";
|
const type = node.type || "";
|
||||||
|
|
||||||
if (type in this) {
|
if (type in this) {
|
||||||
// @ts-expect-error - `this` is not assignable to type 'never'
|
// @ts-expect-error - `this` is not assignable to type 'never'
|
||||||
return this[type]?.(node, options) as JSX.Element;
|
return this[type]?.(node, options) as React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(`Node type "${type}" is not supported.`);
|
throw new Error(`Node type "${type}" is not supported.`);
|
||||||
@@ -323,7 +323,7 @@ export class EmailRenderer {
|
|||||||
private unsubscribeFooter(
|
private unsubscribeFooter(
|
||||||
node: JSONContent,
|
node: JSONContent,
|
||||||
options?: NodeOptions
|
options?: NodeOptions
|
||||||
): JSX.Element {
|
): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
style={{
|
style={{
|
||||||
@@ -338,7 +338,7 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private paragraph(node: JSONContent, options?: NodeOptions): JSX.Element {
|
private paragraph(node: JSONContent, options?: NodeOptions): React.ReactNode {
|
||||||
const { attrs } = node;
|
const { attrs } = node;
|
||||||
const alignment = attrs?.textAlign || "left";
|
const alignment = attrs?.textAlign || "left";
|
||||||
|
|
||||||
@@ -362,7 +362,7 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private text(node: JSONContent, _?: NodeOptions): JSX.Element {
|
private text(node: JSONContent, _?: NodeOptions): React.ReactNode {
|
||||||
const text = node.text || " ";
|
const text = node.text || " ";
|
||||||
if (node.marks) {
|
if (node.marks) {
|
||||||
return this.renderMark(node);
|
return this.renderMark(node);
|
||||||
@@ -371,30 +371,30 @@ export class EmailRenderer {
|
|||||||
return <>{text}</>;
|
return <>{text}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bold(_: MarkType, text: JSX.Element): JSX.Element {
|
private bold(_: MarkType, text: React.ReactNode): React.ReactNode {
|
||||||
return <strong>{text}</strong>;
|
return <strong>{text}</strong>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private italic(_: MarkType, text: JSX.Element): JSX.Element {
|
private italic(_: MarkType, text: React.ReactNode): React.ReactNode {
|
||||||
return <em>{text}</em>;
|
return <em>{text}</em>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private underline(_: MarkType, text: JSX.Element): JSX.Element {
|
private underline(_: MarkType, text: React.ReactNode): React.ReactNode {
|
||||||
return <u>{text}</u>;
|
return <u>{text}</u>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private strike(_: MarkType, text: JSX.Element): JSX.Element {
|
private strike(_: MarkType, text: React.ReactNode): React.ReactNode {
|
||||||
return <s style={{ textDecoration: "line-through" }}>{text}</s>;
|
return <s style={{ textDecoration: "line-through" }}>{text}</s>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private textStyle(mark: MarkType, text: JSX.Element): JSX.Element {
|
private textStyle(mark: MarkType, text: React.ReactNode): React.ReactNode {
|
||||||
const { attrs } = mark;
|
const { attrs } = mark;
|
||||||
const { fontSize, fontWeight, color } = attrs || {};
|
const { fontSize, fontWeight, color } = attrs || {};
|
||||||
|
|
||||||
return <span style={{ fontSize, fontWeight, color }}>{text}</span>;
|
return <span style={{ fontSize, fontWeight, color }}>{text}</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private link(mark: MarkType, text: JSX.Element): JSX.Element {
|
private link(mark: MarkType, text: React.ReactNode): React.ReactNode {
|
||||||
const { attrs } = mark;
|
const { attrs } = mark;
|
||||||
let href = attrs?.href || "#";
|
let href = attrs?.href || "#";
|
||||||
const target = attrs?.target || "_blank";
|
const target = attrs?.target || "_blank";
|
||||||
@@ -425,7 +425,7 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private heading(node: JSONContent, options?: NodeOptions): JSX.Element {
|
private heading(node: JSONContent, options?: NodeOptions): React.ReactNode {
|
||||||
const { attrs } = node;
|
const { attrs } = node;
|
||||||
const { next, prev } = options || {};
|
const { next, prev } = options || {};
|
||||||
|
|
||||||
@@ -456,7 +456,7 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private variable(node: JSONContent, _?: NodeOptions): JSX.Element {
|
private variable(node: JSONContent, _?: NodeOptions): React.ReactNode {
|
||||||
const { id: variable, fallback } = node.attrs || {};
|
const { id: variable, fallback } = node.attrs || {};
|
||||||
|
|
||||||
let formattedVariable = this.variableFormatter({
|
let formattedVariable = this.variableFormatter({
|
||||||
@@ -474,7 +474,7 @@ export class EmailRenderer {
|
|||||||
return <>{formattedVariable}</>;
|
return <>{formattedVariable}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private horizontalRule(_: JSONContent, __?: NodeOptions): JSX.Element {
|
private horizontalRule(_: JSONContent, __?: NodeOptions): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
<Hr
|
<Hr
|
||||||
style={{
|
style={{
|
||||||
@@ -486,7 +486,7 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private orderedList(node: JSONContent, _?: NodeOptions): JSX.Element {
|
private orderedList(node: JSONContent, _?: NodeOptions): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
<Container style={{ maxWidth: "100%" }}>
|
<Container style={{ maxWidth: "100%" }}>
|
||||||
<ol
|
<ol
|
||||||
@@ -503,7 +503,7 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bulletList(node: JSONContent, _?: NodeOptions): JSX.Element {
|
private bulletList(node: JSONContent, _?: NodeOptions): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
style={{
|
style={{
|
||||||
@@ -524,7 +524,7 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private listItem(node: JSONContent, options?: NodeOptions): JSX.Element {
|
private listItem(node: JSONContent, options?: NodeOptions): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
style={{
|
style={{
|
||||||
@@ -544,7 +544,7 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private button(node: JSONContent, options?: NodeOptions): JSX.Element {
|
private button(node: JSONContent, options?: NodeOptions): React.ReactNode {
|
||||||
const { attrs } = node;
|
const { attrs } = node;
|
||||||
const {
|
const {
|
||||||
text,
|
text,
|
||||||
@@ -592,7 +592,7 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private spacer(node: JSONContent, _?: NodeOptions): JSX.Element {
|
private spacer(node: JSONContent, _?: NodeOptions): React.ReactNode {
|
||||||
const { attrs } = node;
|
const { attrs } = node;
|
||||||
const { height = "auto" } = attrs || {};
|
const { height = "auto" } = attrs || {};
|
||||||
|
|
||||||
@@ -605,11 +605,11 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private hardBreak(_: JSONContent, __?: NodeOptions): JSX.Element {
|
private hardBreak(_: JSONContent, __?: NodeOptions): React.ReactNode {
|
||||||
return <br />;
|
return <br />;
|
||||||
}
|
}
|
||||||
|
|
||||||
private logo(node: JSONContent, options?: NodeOptions): JSX.Element {
|
private logo(node: JSONContent, options?: NodeOptions): React.ReactNode {
|
||||||
const { attrs } = node;
|
const { attrs } = node;
|
||||||
const {
|
const {
|
||||||
src,
|
src,
|
||||||
@@ -645,7 +645,7 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private image(node: JSONContent, options?: NodeOptions): JSX.Element {
|
private image(node: JSONContent, options?: NodeOptions): React.ReactNode {
|
||||||
const { attrs } = node;
|
const { attrs } = node;
|
||||||
const {
|
const {
|
||||||
src,
|
src,
|
||||||
@@ -711,7 +711,10 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private blockquote(node: JSONContent, options?: NodeOptions): JSX.Element {
|
private blockquote(
|
||||||
|
node: JSONContent,
|
||||||
|
options?: NodeOptions
|
||||||
|
): React.ReactNode {
|
||||||
const { next, prev } = options || {};
|
const { next, prev } = options || {};
|
||||||
const isNextSpacer = next?.type === "spacer";
|
const isNextSpacer = next?.type === "spacer";
|
||||||
const isPrevSpacer = prev?.type === "spacer";
|
const isPrevSpacer = prev?.type === "spacer";
|
||||||
@@ -734,7 +737,7 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private code(_: MarkType, text: JSX.Element): JSX.Element {
|
private code(_: MarkType, text: React.ReactNode): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
<code
|
<code
|
||||||
style={{
|
style={{
|
||||||
@@ -752,7 +755,7 @@ export class EmailRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private codeBlock(node: JSONContent, options?: NodeOptions): JSX.Element {
|
private codeBlock(node: JSONContent, options?: NodeOptions): React.ReactNode {
|
||||||
const { attrs } = node;
|
const { attrs } = node;
|
||||||
const language = attrs?.language;
|
const language = attrs?.language;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user