all repos — stealth-developers @ 97afd595b83b32b08a37f992172c79e04b9d3137

feat(api): types
vi did:web:vt3e.cat
Sat, 16 May 2026 04:58:24 +0100
commit

97afd595b83b32b08a37f992172c79e04b9d3137

parent

85dd92402efceceef196ff57fdd9fa3c49e32d52

A pkgs/api/.gitignore

@@ -0,0 +1,34 @@

+# dependencies (bun install) +node_modules + +# output +out +dist +*.tgz + +# code coverage +coverage +*.lcov + +# logs +logs +_.log +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# caches +.eslintcache +.cache +*.tsbuildinfo + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store
A pkgs/api/package.json

@@ -0,0 +1,19 @@

+{ + "name": "@stealth-developers/api", + "type": "module", + "module": "src/index.ts", + "exports": { + ".": "./dist/index.js" + }, + "devDependencies": { + "@types/bun": "latest" + }, + "scripts": { + "build:types": "tsc --emitDeclarationOnly", + "build:js": "bun build ./src/index.ts --outdir ./dist --minify --target bun", + "build": "bun run build:types && bun run build:js" + }, + "peerDependencies": { + "typescript": "^5" + } +}
A pkgs/api/src/index.ts

@@ -0,0 +1,2 @@

+export * from "./types" +export * from "./responses"
A pkgs/api/src/responses.ts

@@ -0,0 +1,30 @@

+import type { Message, Ticket, User } from "./types"; + +export type TicketResponse = { + ticket: Ticket; + messages: Message[]; +}; + +export type TicketsResponse = { + tickets: Ticket[]; + // todo)) type pagination +}; + +export type MeResponse = User; +export type ModeratorsResponse = User[]; + +export type Statistic = { + mean: number; + median: number; + count: number; +}; +export type OverallStatsResponse = { + global: Statistic; + hourly: (Statistic & { hour: number })[]; +}; + +type LeaderboardStat = Statistic & { + user: User; + rank: number; +}; +export type LeaderboardResponse = LeaderboardStat[];
A pkgs/api/src/types.ts

@@ -0,0 +1,56 @@

+export type User = { + id: string; + name: string; + avatarUrl: string; + isModerator: boolean; +}; + +export type Ticket = { + number: string; + status: "open" | "closed" | "archived"; + + closedBy: User | null; + closedAt: Date | null; + + /** the reason the ticket was opened if it was not opened by the subject */ + topic: string | null; + closeReason: string | null; + privateReason: string | null; + + /** the user who opened the ticket, if it was not opened by the subject */ + openedBy: User | null; + /** the user who is the subject of the ticket, i.e. the reporter */ + subject: User; +}; + +export type Message = { + id: number; + messageId: string | null; + + createdAt: Date; + updatedAt: Date | null; + deletedAt: Date | null; + + author: User; + authorType: "user" | "staff" | "system"; + + content: string; + attachments: Attachment[]; + mentions: User[]; +}; + +export type Attachment = { + id: string; + ownerType: "ticket" | "ticket_message" | "bug"; + owner: User | null; + + fileName: string; + contentType: string; + size: number; + + bucket: string; + key: string; + url: string; + + uploadedAt: Date; +};
A pkgs/api/tsconfig.json

@@ -0,0 +1,28 @@

+{ + "include": ["src"], + "compilerOptions": { + // Environment setup & latest features + "lib": ["ESNext"], + "target": "ESNext", + "module": "Preserve", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + "types": ["bun"], + + "outDir": "dist", + "declaration": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false, + }, +}
M pkgs/bot/src/roblox/robloxUser.tspkgs/bot/src/roblox/robloxUser.ts

@@ -31,8 +31,15 @@

await interaction.editReply( `Found user with username ${user.name}, fetching thumbnail...`, ); - const [thumbnailRes] = await roblox.getThumbnail(id, { shape: "SQUARE" }); - const thumbnailUri = thumbnailRes ? thumbnailRes.response?.imageUri : null; + const [thumbnailRes, thumbnailErr] = await roblox.getThumbnail(id, { shape: "SQUARE" }); + const thumbnailUri = thumbnailRes ? thumbnailRes.response?.imageUri : "https://cdn.discordapp.com/icons/895998762630127616/36c6e14d0933eb338826599b632df818.webp?size=80&quality=lossless"; + + logger.debug({ + user, + thumbnailRes, + thumbnailErr, + thumbnailUri, + }); const randomMessages = [ "grok is this true",