Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"license": "ISC",
"description": "",
"dependencies": {
"@hono/zod-validator": "^0.7.3",
"@hono/zod-validator": "^0.7.5",
"@interledger/open-payments": "^7.1.3",
"@noble/ed25519": "^3.0.0",
"@paralleldrive/cuid2": "^2.2.2",
Expand All @@ -24,7 +24,7 @@
"hono": "^4.9.8",
"http-message-signatures": "^1.0.4",
"httpbis-digest-headers": "^1.0.0",
"zod": "^3.25.76"
"zod": "^4.1.13"
},
"types": "./src/types.ts",
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion api/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ app.onError((error, c) => {
message: 'Validation failed',
code: 'VALIDATION_ERROR',
details: {
issues: error.errors.map((err) => ({
issues: error.issues.map((err) => ({
path: err.path.join('.'),
message: err.message,
code: err.code
Expand Down
4 changes: 2 additions & 2 deletions api/src/routes/get-config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { zValidator } from '@hono/zod-validator'
import { HTTPException } from 'hono/http-exception'
import { z } from 'zod'
import z from 'zod'
import { ConfigStorageService } from '@shared/config-storage-service'
import { AWS_PREFIX } from '@shared/defines'
import { PRESET_IDS, TOOLS } from '@shared/types'
Expand All @@ -26,7 +26,7 @@ app.get(
zValidator(
'query',
z.object({
wa: z.string().url(),
wa: z.url(),
preset: z.enum(PRESET_IDS)
})
),
Expand Down
4 changes: 2 additions & 2 deletions api/src/routes/probabilistic-revshare.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HTTPException } from 'hono/http-exception'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'
import z from 'zod'
import type { ContentfulStatusCode } from 'hono/utils/http-status'
import type { WalletAddress } from '@interledger/open-payments'
import { decode, pickWeightedRandom } from '@shared/probabilistic-revenue-share'
Expand All @@ -14,7 +14,7 @@ app.get(
zValidator(
'param',
z.object({
payload: z.string().base64url().max(50_000).min(20)
payload: z.base64url().max(50_000).min(20)
})
),
async ({ req, json }) => {
Expand Down
22 changes: 11 additions & 11 deletions api/src/schemas/payment.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as z from 'zod/v4'
import z from 'zod'

export const PaymentQuoteSchema = z.object({
senderWalletAddress: z.string().url('Invalid sender wallet address'),
receiverWalletAddress: z.string().url('Invalid receiver wallet address'),
senderWalletAddress: z.url('Invalid sender wallet address'),
receiverWalletAddress: z.url('Invalid receiver wallet address'),
amount: z.number().positive('Amount must be positive'),
note: z.string().optional()
})
Expand Down Expand Up @@ -35,11 +35,11 @@ export const PaymentFinalizeSchema = z.object({
walletAddress: WalletAddressSchema,
pendingGrant: z.object({
interact: z.object({
redirect: z.string().url(),
redirect: z.url(),
finish: z.string()
}),
continue: z.object({
uri: z.string().url(),
uri: z.url(),
access_token: z.object({
value: z.string()
}),
Expand All @@ -48,18 +48,18 @@ export const PaymentFinalizeSchema = z.object({
}),
quote: z.object({
id: z.string(),
walletAddress: z.string().url('Invalid wallet address'),
receiver: z.string().url(),
walletAddress: z.url('Invalid wallet address'),
receiver: z.url(),
receiveAmount: AmountSchema,
debitAmount: AmountSchema,
method: z.literal('ilp'),
createdAt: z.string().datetime(),
expiresAt: z.string().datetime().optional()
createdAt: z.iso.datetime(),
expiresAt: z.iso.datetime().optional()
}),
incomingPaymentGrant: z.object({
access_token: z.object({
value: z.string(),
manage: z.string().url(),
manage: z.url(),
expires_in: z.number().int(),
access: z.array(
z.object({
Expand All @@ -73,7 +73,7 @@ export const PaymentFinalizeSchema = z.object({
access_token: z.object({
value: z.string()
}),
uri: z.string().url(),
uri: z.url(),
wait: z.number().int().optional()
})
}),
Expand Down
2 changes: 1 addition & 1 deletion api/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type {
PaymentQuoteSchema,
WalletAddressParamSchema
} from './schemas/payment.js'
import type { z } from 'zod/v4'
import type z from 'zod'

export type PaymentStatusSuccess = {
paymentId: string
Expand Down
4 changes: 2 additions & 2 deletions frontend/app/lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { z } from 'zod'
import type z from 'zod'
import type {
createBannerSchema,
createButtonSchema,
Expand Down Expand Up @@ -37,7 +37,7 @@ export type SanitizedFields = Pick<
>

export type JSONError<T extends z.ZodTypeAny> = {
errors: z.typeToFlattenedError<z.infer<T>>
errors: z.ZodFlattenedError<z.infer<T>>
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down
21 changes: 10 additions & 11 deletions frontend/app/utils/validate.client.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import { z } from 'zod'
import z from 'zod'
import {
bannerFieldsSchema,
buttonFieldsSchema,
widgetFieldsSchema
} from './validate.shared'
import type { ElementConfigType } from '@shared/types'

export const elementConfigStorageSchema = z
.object({
versionName: z.string(),
tag: z.string().optional(),
// can be undefined initially
walletAddress: z.string().optional()
})
.merge(buttonFieldsSchema)
.merge(bannerFieldsSchema)
.merge(widgetFieldsSchema)
export const elementConfigStorageSchema = z.object({
versionName: z.string(),
tag: z.string().optional(),
// can be undefined initially
walletAddress: z.string().optional(),
...buttonFieldsSchema.shape,
...bannerFieldsSchema.shape,
...widgetFieldsSchema.shape
})

/**
* Validates configurations from localStorage.
Expand Down
58 changes: 31 additions & 27 deletions frontend/app/utils/validate.server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { z } from 'zod'
import z from 'zod'
import {
checkHrefFormat,
getWalletAddress,
Expand Down Expand Up @@ -29,7 +29,7 @@ export const walletSchema = z.object({
await getWalletAddress(updatedUrl)
} catch (e) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
code: 'custom',
message:
e instanceof WalletAddressFormatError
? e.message
Expand All @@ -48,29 +48,26 @@ export const fullConfigSchema = z.object({
fullconfig: z.string().min(1, { message: 'Unknown error' })
})

export const createButtonSchema = z
.object({
elementType: z.literal('button')
})
.merge(buttonFieldsSchema)
.merge(walletSchema)
.merge(versionSchema)
export const createButtonSchema = z.object({
elementType: z.literal('button'),
...buttonFieldsSchema.shape,
...walletSchema.shape,
...versionSchema.shape
})

export const createBannerSchema = z
.object({
elementType: z.literal('banner')
})
.merge(bannerFieldsSchema)
.merge(walletSchema)
.merge(versionSchema)
export const createBannerSchema = z.object({
elementType: z.literal('banner'),
...bannerFieldsSchema.shape,
...walletSchema.shape,
...versionSchema.shape
})

export const createWidgetSchema = z
.object({
elementType: z.literal('widget')
})
.merge(widgetFieldsSchema)
.merge(walletSchema)
.merge(versionSchema)
export const createWidgetSchema = z.object({
elementType: z.literal('widget'),
...widgetFieldsSchema.shape,
...walletSchema.shape,
...versionSchema.shape
})

export const getElementSchema = (type: string) => {
switch (type) {
Expand All @@ -95,7 +92,10 @@ export const validateForm = async (
if (intent === 'import' || intent === 'delete') {
result = await walletSchema.safeParseAsync(formData)
} else if (intent === 'newversion') {
const newVersionSchema = versionSchema.merge(walletSchema)
const newVersionSchema = z.object({
...versionSchema.shape,
...walletSchema.shape
})
result = await newVersionSchema.safeParseAsync(formData)
} else {
let currentSchema
Expand All @@ -111,9 +111,13 @@ export const validateForm = async (
default:
currentSchema = createBannerSchema
}
result = await currentSchema
.merge(fullConfigSchema)
.safeParseAsync(Object.assign(formData, { ...{ elementType } }))
const mergedSchema = z.object({
...currentSchema.shape,
...fullConfigSchema.shape
})
result = await mergedSchema.safeParseAsync(
Object.assign(formData, { ...{ elementType } })
)
}
/* eslint-disable @typescript-eslint/no-explicit-any */
const payload = result.data as unknown as any
Expand Down
14 changes: 7 additions & 7 deletions frontend/app/utils/validate.shared.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { z } from 'zod'
import z from 'zod'
import {
CORNER_OPTION,
BANNER_POSITION,
Expand All @@ -23,7 +23,7 @@ const widgetFontSizeError = {
export const buttonFieldsSchema = z.object({
buttonFontName: z.string().min(1, { message: 'Choose a font' }),
buttonText: z.string().min(1, { message: 'Button label cannot be empty' }),
buttonBorder: z.nativeEnum(CORNER_OPTION),
buttonBorder: z.enum(CORNER_OPTION),
buttonTextColor: z.string().min(6),
buttonBackgroundColor: z.string().min(6),
buttonDescriptionText: z.string().optional()
Expand All @@ -48,10 +48,10 @@ export const bannerFieldsSchema = z.object({
bannerDescriptionVisible: z.coerce.boolean().optional(),
bannerTextColor: z.string().min(6),
bannerBackgroundColor: z.string().min(6),
bannerSlideAnimation: z.nativeEnum(SLIDE_ANIMATION),
bannerSlideAnimation: z.enum(SLIDE_ANIMATION),
bannerThumbnail: z.string().optional(),
bannerPosition: z.nativeEnum(BANNER_POSITION),
bannerBorder: z.nativeEnum(CORNER_OPTION)
bannerPosition: z.enum(BANNER_POSITION),
bannerBorder: z.enum(CORNER_OPTION)
})

export const widgetFieldsSchema = z.object({
Expand All @@ -71,14 +71,14 @@ export const widgetFieldsSchema = z.object({
})
.optional(),
widgetDescriptionVisible: z.coerce.boolean().optional(),
widgetPosition: z.nativeEnum(WIDGET_POSITION),
widgetPosition: z.enum(WIDGET_POSITION),
widgetDonateAmount: z.coerce
.number()
.min(0, { message: 'Donate amount must be positive' }),
widgetButtonText: z
.string()
.min(1, { message: 'Button text cannot be empty' }),
widgetButtonBorder: z.nativeEnum(CORNER_OPTION),
widgetButtonBorder: z.enum(CORNER_OPTION),
widgetButtonBackgroundColor: z.string().min(1),
widgetButtonTextColor: z.string().min(1),
widgetTextColor: z.string().min(1),
Expand Down
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"sanitize-html": "^2.17.0",
"tailwindcss": "^3.4.18",
"valtio": "^2.1.8",
"zod": "^3.25.76"
"zod": "^4.1.13"
},
"devDependencies": {
"@cloudflare/vite-plugin": "^1.14.1",
Expand Down
26 changes: 13 additions & 13 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.