···11-import { betterAuth, Session, User } from "better-auth";
22-import { username } from "better-auth/plugins";
11+import { betterAuth, Session } from "better-auth";
32import { withCloudflare } from "better-auth-cloudflare";
43import { drizzleAdapter } from "better-auth/adapters/drizzle";
44+import { username } from "better-auth/plugins";
55import { drizzle } from "drizzle-orm/d1";
66import { schema } from "../db";
77+import { BSKY_MAX_USERNAME_LENGTH, BSKY_MIN_USERNAME_LENGTH } from "../limits.d";
78import { Bindings } from "../types";
88-import { BSKY_MAX_USERNAME_LENGTH, BSKY_MIN_USERNAME_LENGTH } from "../limits.d";
99import { lookupBskyHandle } from "../utils/bskyApi";
1010import { createDMWithUser } from "../utils/bskyMsg";
1111···149149};
150150151151// Export for runtime usage
152152-export { createAuth, ContextVariables };
152152+export { ContextVariables, createAuth };
+1-1
src/db/app.schema.ts
···11import { sql } from "drizzle-orm";
22-import { users } from "./auth.schema";
32import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
43import { EmbedData, PostLabel } from '../types.d';
44+import { users } from "./auth.schema";
5566export const posts = sqliteTable('posts', {
77 uuid: text('uuid', {mode: 'text'}).primaryKey(),
+13-10
src/endpoints/account.tsx
···11import { Context, Hono } from "hono";
22import { secureHeaders } from "hono/secure-headers";
33+import isEmpty from "just-is-empty";
34import { ContextVariables } from "../auth";
44-import { Bindings, LooseObj } from "../types";
55+import { ViolationNoticeBar } from "../layout/violationsBar";
56import { authMiddleware, pullAuthData } from "../middleware/auth";
67import { corsHelperMiddleware } from "../middleware/corsHelper";
78import { verifyTurnstile } from "../middleware/turnstile";
99+import { Bindings, LooseObj } from "../types";
1010+import { doesHandleExist } from "../utils/bskyApi";
1111+import {
1212+ doesUserExist, getAllMediaOfUser, getUserEmailForHandle,
1313+ getUsernameForUser, updateUserData
1414+} from "../utils/dbQuery";
1515+import { consumeInviteKey, doesInviteKeyHaveValues } from "../utils/inviteKeys";
1616+import { deleteFromR2 } from "../utils/r2Query";
1717+import { AccountDeleteSchema, AccountForgotSchema } from "../validation/accountForgotDeleteSchema";
818import { AccountResetSchema } from "../validation/accountResetSchema";
99-import { SignupSchema } from "../validation/signupSchema";
1010-import { LoginSchema } from "../validation/loginSchema";
1119import { AccountUpdateSchema } from "../validation/accountUpdateSchema";
1212-import { AccountDeleteSchema, AccountForgotSchema } from "../validation/accountForgotDeleteSchema";
1313-import { doesUserExist, getAllMediaOfUser, getUserEmailForHandle, getUsernameForUser, updateUserData } from "../utils/dbQuery";
1414-import { doesInviteKeyHaveValues, consumeInviteKey } from "../utils/inviteKeys";
1515-import { doesHandleExist } from "../utils/bskyApi";
1616-import { deleteFromR2 } from "../utils/r2Query";
1717-import isEmpty from "just-is-empty";
1818-import { ViolationNoticeBar } from "../layout/violationsBar";
2020+import { LoginSchema } from "../validation/loginSchema";
2121+import { SignupSchema } from "../validation/signupSchema";
19222023export const account = new Hono<{ Bindings: Bindings, Variables: ContextVariables }>();
2124
+12-10
src/endpoints/post.tsx
···11import { Context, Hono } from "hono";
22import { secureHeaders } from "hono/secure-headers";
33-import { validate as isValid } from 'uuid';
44-import { Bindings, CreatePostQueryResponse, EmbedDataType, LooseObj, Post } from "../types.d";
33+import isEmpty from "just-is-empty";
44+import { validate as isValid } from 'uuid';
55import { ContextVariables } from "../auth";
66+import { PostEdit } from "../layout/editPost";
77+import { ScheduledPost, ScheduledPostList } from "../layout/postList";
68import { authMiddleware } from "../middleware/auth";
79import { corsHelperMiddleware } from "../middleware/corsHelper";
88-import { FileDeleteSchema } from "../validation/mediaSchema";
99-import { EditSchema } from "../validation/postSchema";
1010+import { Bindings, CreatePostQueryResponse, EmbedDataType, LooseObj, Post } from "../types.d";
1011import { makePost } from "../utils/bskyApi";
1111-import { deleteFromR2, uploadFileR2 } from "../utils/r2Query";
1212-import { createPost, deletePost, getPostById, getUsernameForUser,
1313- setPostNowOffForPost, updatePostForUser } from "../utils/dbQuery";
1414-import { ScheduledPost, ScheduledPostList } from "../layout/postList";
1515-import { PostEdit } from "../layout/editPost";
1616-import isEmpty from "just-is-empty";
1212+import {
1313+ createPost, deletePost, getPostById, getUsernameForUser,
1414+ updatePostForUser
1515+} from "../utils/dbQuery";
1716import { enqueuePost, isQueueEnabled, shouldPostNowQueue } from "../utils/queuePublisher";
1717+import { deleteFromR2, uploadFileR2 } from "../utils/r2Query";
1818+import { FileDeleteSchema } from "../validation/mediaSchema";
1919+import { EditSchema } from "../validation/postSchema";
18201921export const post = new Hono<{ Bindings: Bindings, Variables: ContextVariables }>();
2022
+3-3
src/endpoints/preview.tsx
···11import { Context, Hono } from "hono";
22import { secureHeaders } from "hono/secure-headers";
33-import { Bindings } from "../types.d";
33+import isEmpty from "just-is-empty";
44import { ContextVariables } from "../auth";
55+import { BSKY_IMG_MIME_TYPES } from "../limits.d";
56import { authMiddleware } from "../middleware/auth";
67import { corsHelperMiddleware } from "../middleware/corsHelper";
77-import { BSKY_IMG_MIME_TYPES } from "../limits.d";
88+import { Bindings } from "../types.d";
89import { FileContentSchema } from "../validation/mediaSchema";
99-import isEmpty from "just-is-empty";
10101111export const preview = new Hono<{ Bindings: Bindings, Variables: ContextVariables }>();
1212
+16-16
src/index.tsx
···11import { Env, Hono } from "hono";
22-import { createAuth, ContextVariables } from "./auth";
33-import { Bindings, QueueTaskData, QueueTaskType, ScheduledContext } from "./types.d";
44-import Home from "./pages/homepage";
55-import Signup from "./pages/signup";
22+import { ContextVariables, createAuth } from "./auth";
33+import { account } from "./endpoints/account";
44+import { post } from "./endpoints/post";
55+import { preview } from "./endpoints/preview";
66+import { authAdminOnlyMiddleware } from "./middleware/adminOnly";
77+import { authMiddleware } from "./middleware/auth";
88+import { corsHelperMiddleware } from "./middleware/corsHelper";
99+import { redirectToDashIfLogin } from "./middleware/redirectDash";
610import Dashboard from "./pages/dashboard";
1111+import ForgotPassword from "./pages/forgot";
1212+import Home from "./pages/homepage";
713import Login from "./pages/login";
1414+import PrivacyPolicy from "./pages/privacy";
815import ResetPassword from "./pages/reset";
99-import ForgotPassword from "./pages/forgot";
1616+import Signup from "./pages/signup";
1017import TermsOfService from "./pages/tos";
1111-import PrivacyPolicy from "./pages/privacy";
1212-import { cleanUpPostsTask, handlePostTask, handleRepostTask, schedulePostTask } from "./utils/scheduler";
1818+import { Bindings, QueueTaskData, QueueTaskType, ScheduledContext } from "./types.d";
1919+import { makeConstScript } from "./utils/constScriptGen";
1320import { runMaintenanceUpdates } from "./utils/dbQuery";
1414-import { setupAccounts } from "./utils/setup";
1521import { makeInviteKey } from "./utils/inviteKeys";
1616-import { makeConstScript } from "./utils/constScriptGen";
1717-import { authMiddleware } from "./middleware/auth";
1818-import { authAdminOnlyMiddleware } from "./middleware/adminOnly";
1919-import { corsHelperMiddleware } from "./middleware/corsHelper";
2020-import { redirectToDashIfLogin } from "./middleware/redirectDash";
2121-import { account } from "./endpoints/account";
2222-import { post } from "./endpoints/post";
2323-import { preview } from "./endpoints/preview";
2222+import { cleanUpPostsTask, handlePostTask, handleRepostTask, schedulePostTask } from "./utils/scheduler";
2323+import { setupAccounts } from "./utils/setup";
24242525const app = new Hono<{ Bindings: Bindings, Variables: ContextVariables }>();
2626
+1-1
src/layout/editPost.tsx
···11import { html } from "hono/html";
22-import { MAX_LENGTH } from "../limits.d"
22+import { MAX_LENGTH } from "../limits.d";
33import { EmbedDataType, Post } from "../types.d";
44import { PostContentObject } from "./postList";
55
+2-2
src/layout/main.tsx
···11import { html } from 'hono/html';
22import { Child } from 'hono/jsx';
33-import MetaTags from './metaTags';
44-import { PreloadRules } from '../types.d';
53import { CURRENT_SCRIPT_VERSION } from '../limits.d';
44+import { PreloadRules } from '../types.d';
65import { PreloadDependencyTags } from './depTags';
66+import MetaTags from './metaTags';
7788type BaseLayoutProps = {
99 children: Child;
···11import { html } from "hono/html";
22import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits.d";
33-import { UsernameField } from "./usernameField";
44-import { BSkyAppPasswordField, DashboardPasswordField } from "./passwordFields";
53import { PWAutoCompleteSettings } from "../types.d";
44+import { BSkyAppPasswordField, DashboardPasswordField } from "./passwordFields";
55+import { UsernameField } from "./usernameField";
6677export function Settings() {
88 return (
+1-1
src/layout/usernameField.tsx
···11-import { html, raw } from "hono/html";
11+import { raw } from "hono/html";
22import { BSKY_MIN_USERNAME_LENGTH } from "../limits.d";
3344type UsernameFieldProps = {
+6-4
src/layout/violationsBar.tsx
···11import { Context } from "hono";
22-import { getViolationsForCurrentUser } from "../utils/dbQuery";
33-import { Violation } from "../types.d";
42import isEmpty from "just-is-empty";
33+import { Violation } from "../types.d";
44+import { getViolationsForCurrentUser } from "../utils/dbQuery";
5566export async function ViolationNoticeBar(props: any) {
77 const ctx: Context = props.ctx;
···2121 errorStr = "You currently have media that's too large for Bluesky (like a video), please delete those posts";
2222 }
2323 return (
2424- <div id="violationBar" class="warning-box" hx-trigger="accountViolations from:body" hx-swap="outerHTML" hx-get="/account/violations" hx-target="this">
2424+ <div id="violationBar" class="warning-box" hx-trigger="accountViolations from:body"
2525+ hx-swap="outerHTML" hx-get="/account/violations" hx-target="this">
2526 <span class="warning"><b>WARNING</b>: Account error found! {errorStr}</span>
2627 </div>
2728 );
2829 }
2929- return (<div hx-trigger="accountViolations from:body" hidden id="hiddenViolations" hx-get="/account/violations" hx-swap="outerHTML" hx-target="this"></div>);
3030+ return (<div hx-trigger="accountViolations from:body" hidden id="hiddenViolations"
3131+ hx-get="/account/violations" hx-swap="outerHTML" hx-target="this"></div>);
3032};
···11import { Context } from "hono";
22+import AccountHandler from "../layout/account";
33+import FooterCopyright from "../layout/footer";
24import { BaseLayout } from "../layout/main";
35import NavTags from "../layout/navTags";
44-import AccountHandler from "../layout/account";
55-import { UsernameField } from "../layout/usernameField";
66import { TurnstileCaptcha, TurnstileCaptchaPreloads } from "../layout/turnstile";
77-import FooterCopyright from "../layout/footer";
77+import { UsernameField } from "../layout/usernameField";
8899export default function ForgotPassword(props:any) {
1010 const ctx: Context = props.c;
+1-1
src/pages/homepage.tsx
···11import FooterCopyright from "../layout/footer";
22import { BaseLayout } from "../layout/main";
33import NavTags from "../layout/navTags";
44-import { MAX_REPOST_IN_HOURS, MAX_REPOST_INTERVAL, MAX_REPOST_DAYS, R2_FILE_SIZE_LIMIT_IN_MB } from "../limits.d";
44+import { MAX_REPOST_DAYS, MAX_REPOST_IN_HOURS, MAX_REPOST_INTERVAL, R2_FILE_SIZE_LIMIT_IN_MB } from "../limits.d";
5566export default function Home() {
77 return (
+2-2
src/pages/login.tsx
···11+import AccountHandler from "../layout/account";
12import { BaseLayout } from "../layout/main";
23import NavTags from "../layout/navTags";
33-import AccountHandler from "../layout/account";
44-import { UsernameField } from "../layout/usernameField";
54import { DashboardPasswordField } from "../layout/passwordFields";
55+import { UsernameField } from "../layout/usernameField";
66import { PWAutoCompleteSettings } from "../types.d";
7788export default function Login() {
+1-1
src/pages/reset.tsx
···11import { html } from "hono/html";
22+import AccountHandler from "../layout/account";
23import { BaseLayout } from "../layout/main";
34import NavTags from "../layout/navTags";
45import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits.d";
55-import AccountHandler from "../layout/account";
6677export default function ResetPassword() {
88 const links = [{title: "Forgot Password", url: "/forgot"}];
+6-6
src/pages/signup.tsx
···11import { Context } from "hono";
22-import { BaseLayout } from "../layout/main";
33-import { getInviteThread, isUsingInviteKeys } from "../utils/inviteKeys";
44-import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits.d";
55-import NavTags from "../layout/navTags";
62import AccountHandler from "../layout/account";
77-import { UsernameField } from "../layout/usernameField";
88-import { TurnstileCaptcha, TurnstileCaptchaPreloads } from "../layout/turnstile";
93import FooterCopyright from "../layout/footer";
44+import { BaseLayout } from "../layout/main";
55+import NavTags from "../layout/navTags";
106import { BSkyAppPasswordField, DashboardPasswordField } from "../layout/passwordFields";
77+import { TurnstileCaptcha, TurnstileCaptchaPreloads } from "../layout/turnstile";
88+import { UsernameField } from "../layout/usernameField";
99+import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits.d";
1110import { PWAutoCompleteSettings } from "../types.d";
1111+import { getInviteThread, isUsingInviteKeys } from "../utils/inviteKeys";
12121313export default function Signup(props:any) {
1414 const ctx: Context = props.c;
+15-8
src/utils/bskyApi.ts
···11-import { Context } from 'hono';
21import { type AppBskyFeedPost, AtpAgent, RichText } from '@atproto/api';
33-import { Bindings, Post, Repost, PostLabel, EmbedData, PostResponseObject, LooseObj, PlatformLoginResponse, EmbedDataType, ScheduledContext, BskyEmbedWrapper, BskyRecordWrapper } from '../types.d';
22+import { Context } from 'hono';
33+import { imageDimensionsFromStream } from 'image-dimensions';
44+import has from 'just-has';
55+import isEmpty from "just-is-empty";
66+import truncate from "just-truncate";
47import { MAX_ALT_TEXT, MAX_EMBEDS_PER_POST, MAX_POSTED_LENGTH } from '../limits.d';
55-import { updatePostData, getBskyUserPassForId, createViolationForUser, isPostAlreadyPosted, setPostNowOffForPost } from './dbQuery';
88+import {
99+ Bindings, BskyEmbedWrapper, BskyRecordWrapper, EmbedData, EmbedDataType,
1010+ LooseObj, PlatformLoginResponse, Post, PostLabel,
1111+ PostResponseObject, Repost, ScheduledContext
1212+} from '../types.d';
1313+import { postRecordURI } from '../validation/regexCases';
1414+import {
1515+ createViolationForUser, getBskyUserPassForId,
1616+ isPostAlreadyPosted, setPostNowOffForPost, updatePostData
1717+} from './dbQuery';
618import { deleteEmbedsFromR2 } from './r2Query';
77-import { imageDimensionsFromStream } from 'image-dimensions';
88-import { postRecordURI } from '../validation/regexCases';
99-import truncate from "just-truncate";
1010-import isEmpty from "just-is-empty";
1111-import has from 'just-has';
12191320export const doesHandleExist = async (user: string) => {
1421 try {
+1-1
src/utils/bskyMsg.ts
···11import { AtpAgent, RichText } from '@atproto/api';
22-import { loginToBsky } from './bskyApi';
32import { Bindings, PlatformLoginResponse } from '../types.d';
33+import { loginToBsky } from './bskyApi';
4455export const createDMWithUser = async (env: Bindings, user: string, msg: string) => {
66 const agent = new AtpAgent({
+2-2
src/utils/bskyPrune.ts
···11+import isEmpty from 'just-is-empty';
22+import split from 'just-split';
13import { Bindings } from '../types.d';
24import { getPostRecords } from './bskyApi';
35import { getAllPostedPosts, getAllPostedPostsOfUser } from './dbQuery';
44-import split from 'just-split';
55-import isEmpty from 'just-is-empty';
6677// This looks for a bunch of posts that are posted and determines if the posts
88// are still on the network or not. If they are not, then this prunes the posts from
···11+import { addHours, isAfter } from "date-fns";
22+import {
33+ and, count, desc, eq, getTableColumns, gt, inArray,
44+ isNull, lte, ne, notInArray, sql
55+} from "drizzle-orm";
66+import { BatchItem } from "drizzle-orm/batch";
77+import { drizzle, DrizzleD1Database } from "drizzle-orm/d1";
18import { Context } from "hono";
22-import { DrizzleD1Database, drizzle } from "drizzle-orm/d1";
33-import { sql, and, gt, eq, lte, inArray, desc, count, getTableColumns, notInArray, ne, isNull } from "drizzle-orm";
44-import { BatchItem } from "drizzle-orm/batch";
99+import flatten from "just-flatten-it";
1010+import has from "just-has";
1111+import isEmpty from "just-is-empty";
1212+import truncate from "just-truncate";
1313+import unique from "just-unique";
1414+import { v4 as uuidv4, validate as uuidValid } from 'uuid';
515import { posts, reposts, violations } from "../db/app.schema";
616import { accounts, users } from "../db/auth.schema";
1717+import { MAX_HOLD_DAYS_BEFORE_PURGE, MAX_POSTED_LENGTH } from "../limits.d";
1818+import {
1919+ Bindings, BskyAPILoginCreds, CreatePostQueryResponse,
2020+ GetAllPostedBatch, LooseObj, PlatformLoginResponse,
2121+ Post, PostLabel, Repost, Violation
2222+} from "../types.d";
723import { PostSchema } from "../validation/postSchema";
88-import { Bindings, BskyAPILoginCreds, CreatePostQueryResponse, GetAllPostedBatch, LooseObj,
99- PlatformLoginResponse, Post, PostLabel, Repost, Violation } from "../types.d";
1010-import { MAX_HOLD_DAYS_BEFORE_PURGE, MAX_POSTED_LENGTH } from "../limits.d";
1111-import { createLoginCredsObj, createPostObject, createRepostObject, floorCurrentTime, floorGivenTime } from "./helpers";
2424+import {
2525+ createLoginCredsObj, createPostObject, createRepostObject,
2626+ floorCurrentTime, floorGivenTime
2727+} from "./helpers";
1228import { deleteEmbedsFromR2 } from "./r2Query";
1313-import { isAfter, addHours } from "date-fns";
1414-import { v4 as uuidv4, validate as uuidValid } from 'uuid';
1515-import has from "just-has";
1616-import isEmpty from "just-is-empty";
1717-import flatten from "just-flatten-it";
1818-import truncate from "just-truncate";
1919-import unique from "just-unique";
20292130type BatchQuery = [BatchItem<'sqlite'>, ...BatchItem<'sqlite'>[]];
2231
+1-1
src/utils/helpers.ts
···11+import { startOfHour } from "date-fns";
12import isEmpty from "just-is-empty";
23import { BskyAPILoginCreds, Post, Repost } from "../types.d";
33-import { startOfHour } from "date-fns";
4455export function createPostObject(data: any) {
66 const postData: Post = (new Object() as Post);
+1-1
src/utils/queuePublisher.ts
···11-import { Bindings, Post, QueueTaskData, QueueTaskType, Repost } from "../types.d";
21import isEmpty from 'just-is-empty';
32import random from 'just-random';
43import get from 'just-safe-get';
44+import { Bindings, Post, QueueTaskData, QueueTaskType, Repost } from "../types.d";
5566const queueContentType = 'json';
77
+15-6
src/utils/r2Query.ts
···11-import { Bindings, ScheduledContext, EmbedData, EmbedDataType } from '../types.d';
22-import { CF_IMAGES_MAX_DIMENSION, BSKY_IMG_SIZE_LIMIT, CF_IMAGES_FILE_SIZE_LIMIT_IN_MB,
33- CF_IMAGES_FILE_SIZE_LIMIT, R2_FILE_SIZE_LIMIT,
44- MB_TO_BYTES, BSKY_VIDEO_MIME_TYPES, R2_FILE_SIZE_LIMIT_IN_MB,
55- BSKY_IMG_MIME_TYPES, BSKY_VIDEO_SIZE_LIMIT, BSKY_GIF_MIME_TYPES } from "../limits.d";
66-import { v4 as uuidv4 } from 'uuid';
71import { Context } from 'hono';
82import { imageDimensionsFromStream } from 'image-dimensions';
33+import { v4 as uuidv4 } from 'uuid';
44+import {
55+ BSKY_GIF_MIME_TYPES,
66+ BSKY_IMG_MIME_TYPES,
77+ BSKY_IMG_SIZE_LIMIT,
88+ BSKY_VIDEO_MIME_TYPES,
99+ BSKY_VIDEO_SIZE_LIMIT,
1010+ CF_IMAGES_FILE_SIZE_LIMIT,
1111+ CF_IMAGES_FILE_SIZE_LIMIT_IN_MB,
1212+ CF_IMAGES_MAX_DIMENSION,
1313+ MB_TO_BYTES,
1414+ R2_FILE_SIZE_LIMIT,
1515+ R2_FILE_SIZE_LIMIT_IN_MB
1616+} from "../limits.d";
1717+import { Bindings, EmbedData, EmbedDataType, ScheduledContext } from '../types.d';
9181019type FileMetaData = {
1120 name: string,
+9-4
src/utils/scheduler.ts
···11-import { Bindings, ScheduledContext, Post, Repost } from '../types.d';
11+import isEmpty from 'just-is-empty';
22+import { Bindings, Post, Repost, ScheduledContext } from '../types.d';
23import { makePost, makeRepost } from './bskyApi';
34import { pruneBskyPosts } from './bskyPrune';
44-import { getAllPostsForCurrentTime, deleteAllRepostsBeforeCurrentTime, getAllRepostsForCurrentTime,
55- deletePosts, purgePostedPosts } from './dbQuery';
55+import {
66+ deleteAllRepostsBeforeCurrentTime,
77+ deletePosts,
88+ getAllPostsForCurrentTime,
99+ getAllRepostsForCurrentTime,
1010+ purgePostedPosts
1111+} from './dbQuery';
612import { enqueuePost, enqueueRepost, isQueueEnabled } from './queuePublisher';
77-import isEmpty from 'just-is-empty';
813914export const handlePostTask = async(runtime: ScheduledContext, postData: Post, isQueued: boolean = false) => {
1015 const madePost = await makePost(runtime, postData, isQueued);
+1-1
src/validation/accountResetSchema.ts
···11-import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits.d";
21import * as z from "zod/v4";
22+import { MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits.d";
3344export const AccountResetSchema = z.object({
55 resetToken: z.string().nonempty("reset token is missing!"),
+4-1
src/validation/accountUpdateSchema.ts
···11import * as z from "zod/v4";
22+import {
33+ BSKY_MAX_APP_PASSWORD_LENGTH, BSKY_MIN_USERNAME_LENGTH,
44+ MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS
55+} from "../limits.d";
26import { appPasswordRegex } from "./regexCases";
33-import { BSKY_MAX_APP_PASSWORD_LENGTH, BSKY_MIN_USERNAME_LENGTH, MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS } from "../limits.d";
4758export const AccountUpdateSchema = z.object({
69 username: z.string().trim().toLowerCase()
+3-3
src/validation/embedSchema.ts
···11+import isEmpty from "just-is-empty";
22+import * as z from "zod/v4";
13import { BSKY_VIDEO_LENGTH_LIMIT } from "../limits.d";
24import { EmbedDataType } from "../types.d";
33-import { AltTextSchema } from "./sharedValidations";
45import { FileContentSchema } from "./mediaSchema";
56import { postRecordURI } from "./regexCases";
66-import * as z from "zod/v4";
77-import isEmpty from "just-is-empty";
77+import { AltTextSchema } from "./sharedValidations";
8899export const ImageEmbedSchema = z.object({
1010 ...FileContentSchema.shape,
+1-1
src/validation/loginSchema.ts
···11-import { PasswordSchema, UsernameSchema } from "./sharedValidations";
21import * as z from "zod/v4";
22+import { PasswordSchema, UsernameSchema } from "./sharedValidations";
3344// Schema for login validation
55export const LoginSchema = z.object({
+3-3
src/validation/postSchema.ts
···11-import { MIN_LENGTH, MAX_REPOST_INTERVAL_LIMIT, MAX_REPOST_IN_HOURS, MAX_LENGTH } from "../limits.d";
11+import * as z from "zod/v4";
22+import { MAX_LENGTH, MAX_REPOST_INTERVAL_LIMIT, MAX_REPOST_IN_HOURS, MIN_LENGTH } from "../limits.d";
33+import { EmbedDataType, PostLabel } from "../types.d";
24import { ImageEmbedSchema, LinkEmbedSchema, PostRecordSchema, VideoEmbedSchema } from "./embedSchema";
35import { FileContentSchema } from "./mediaSchema";
44-import { EmbedDataType, PostLabel } from "../types.d";
55-import * as z from "zod/v4";
66import { AltTextSchema } from "./sharedValidations";
7788const TextContent = z.object({
+7-1
src/validation/sharedValidations.ts
···11import * as z from "zod/v4";
22+import {
33+ BSKY_MAX_APP_PASSWORD_LENGTH,
44+ BSKY_MAX_USERNAME_LENGTH,
55+ BSKY_MIN_USERNAME_LENGTH,
66+ MAX_ALT_TEXT,
77+ MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS
88+} from "../limits.d";
29import { appPasswordRegex } from "./regexCases";
33-import { BSKY_MAX_APP_PASSWORD_LENGTH, BSKY_MIN_USERNAME_LENGTH, BSKY_MAX_USERNAME_LENGTH, MAX_DASHBOARD_PASS, MIN_DASHBOARD_PASS, MAX_ALT_TEXT } from "../limits.d";
410511export const UsernameSchema = z.object({
612 username: z.string().trim().toLowerCase()