Schedule posts to Bluesky with Cloudflare workers.
skyscheduler.work
cf
tool
bsky-tool
cloudflare
bluesky
schedule
bsky
service
social-media
cloudflare-workers
1import * as z from "zod/v4";
2import {
3 BSKY_MAX_APP_PASSWORD_LENGTH,
4 BSKY_MAX_USERNAME_LENGTH,
5 BSKY_MIN_USERNAME_LENGTH,
6 MAX_ALT_TEXT,
7 MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS
8} from "../limits";
9import { appPasswordRegex } from "./regexCases";
10
11export const UsernameSchema = z.object({
12 username: z.string().trim().toLowerCase()
13 .nonempty("username is missing")
14 .min(BSKY_MIN_USERNAME_LENGTH, "username too short")
15 .regex(z.regexes.domain, "username should be in a format like username.bsky.social or a domain")
16 .max(BSKY_MAX_USERNAME_LENGTH, "username too long")
17 .nonoptional()
18});
19
20export const PasswordSchema = z.object({
21 password: z.string().trim()
22 .nonempty("password is missing")
23 .min(MIN_DASHBOARD_PASS, "password too short")
24 .max(MAX_DASHBOARD_PASS, "password too long")
25 .nonoptional(),
26});
27
28export const BSkyAppPasswordSchema = z.object({
29 bskyAppPassword: z.string().trim()
30 .nonempty("missing bsky app password")
31 .max(BSKY_MAX_APP_PASSWORD_LENGTH, "app password too long")
32 .regex(appPasswordRegex, "please go back and recreate your app password from your bsky settings")
33});
34
35export const AltTextSchema = z.object({
36 alt: z.string().trim()
37 .max(MAX_ALT_TEXT, "alt text is too long")
38 .prefault("")
39});