feat(characters): use local character catalog

This commit is contained in:
2026-07-17 16:03:18 +08:00
parent a210a98d98
commit b3ebd5cf3b
96 changed files with 1023 additions and 522 deletions
@@ -1,42 +0,0 @@
import { describe, expect, it } from "vitest";
import { CharacterSchema } from "@/data/schemas/character";
describe("Character", () => {
it("keeps only the four public character fields", () => {
const character = CharacterSchema.parse({
id: "character_elio",
slug: "elio",
displayName: " Elio Silvestri ",
avatarUrl: "https://cdn.example.com/elio.jpg",
enabled: true,
sortOrder: 1,
});
expect(character).toEqual({
id: "character_elio",
slug: "elio",
displayName: "Elio Silvestri",
avatarUrl: "https://cdn.example.com/elio.jpg",
});
});
it("rejects unsafe slugs and non-HTTPS avatars", () => {
expect(() =>
CharacterSchema.parse({
id: "character_aria",
slug: "Aria Profile",
displayName: "Aria",
avatarUrl: "https://cdn.example.com/aria.jpg",
}),
).toThrow();
expect(() =>
CharacterSchema.parse({
id: "character_aria",
slug: "aria",
displayName: "Aria",
avatarUrl: "http://cdn.example.com/aria.jpg",
}),
).toThrow();
});
});
-17
View File
@@ -1,17 +0,0 @@
import { z } from "zod";
export const CharacterSchema = z
.object({
id: z.string().min(1).max(64),
slug: z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
displayName: z.string().trim().min(1).max(80),
avatarUrl: z.url().refine((url) => url.startsWith("https://"), {
message: "avatarUrl must use HTTPS",
}),
})
.readonly();
export type CharacterInput = z.input<typeof CharacterSchema>;
export type CharacterData = z.output<typeof CharacterSchema>;
export type Character = CharacterData;
@@ -1,17 +0,0 @@
import { z } from "zod";
import { CharacterSchema } from "./character";
export const CharactersResponseSchema = z
.object({
items: z
.array(CharacterSchema)
.default(() => [])
.readonly(),
})
.readonly();
export type CharactersResponseInput = z.input<typeof CharactersResponseSchema>;
export type CharactersResponseData = z.output<typeof CharactersResponseSchema>;
export type CharactersResponse = CharactersResponseData;
-6
View File
@@ -1,6 +0,0 @@
/**
* @file Automatically generated by barrelsby.
*/
export * from "./character";
export * from "./characters_response";