Skip to content

Commit 60b40af

Browse files
authored
Feat Refactor Models (#8)
* debug schema * extract demo data * refactor models
1 parent ba04cbe commit 60b40af

69 files changed

Lines changed: 4602 additions & 652 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/forge-schema/scripts/generate-json-schema.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
import path from "node:path";
22
import { z } from "zod/v4";
3-
import { campaign } from "../src/models/campaign/index.js";
4-
import { character } from "../src/models/character/index.js";
5-
import { registry } from "../src/models/registry/index.js";
3+
import { jsonCollection } from "../src/json-collection.js";
4+
import { characterDocument } from "../src/models/doc-character.js";
5+
import { campaignRuleset } from "../src/models/ruleset-campaign.js";
6+
import { coreRuleset } from "../src/models/ruleset-core.js";
67

7-
const characterSchema = z.toJSONSchema(character, { reused: "ref" });
8-
const registryCampaignSchema = z.toJSONSchema(campaign, { reused: "ref" });
9-
const registryCoreSchema = z.toJSONSchema(registry, { reused: "ref" });
8+
const characterSchema = z.toJSONSchema(characterDocument, { reused: "ref" });
9+
const registryCampaignSchema = z.toJSONSchema(campaignRuleset, {
10+
reused: "ref",
11+
});
12+
const registryCoreSchema = z.toJSONSchema(coreRuleset, { reused: "ref" });
1013

11-
z.globalRegistry.add(character, { id: "Character" });
12-
z.globalRegistry.add(campaign, { id: "Campaign" });
13-
z.globalRegistry.add(registry, { id: "Registry" });
14-
15-
const combinedSchema = z.toJSONSchema(z.globalRegistry, { reused: "ref" });
14+
const testingSchema = z.toJSONSchema(jsonCollection, {
15+
target: "draft-2020-12",
16+
unrepresentable: "throw",
17+
cycles: "throw",
18+
reused: "ref",
19+
});
1620

1721
/**
1822
* Returns the version value from the package.json
@@ -61,7 +65,7 @@ const generateSchemas = async (): Promise<void> => {
6165
{ data: characterSchema, filename: "character.json" },
6266
{ data: registryCampaignSchema, filename: "campaign.json" },
6367
{ data: registryCoreSchema, filename: "core.json" },
64-
{ data: combinedSchema, filename: "schema.json" },
68+
{ data: testingSchema, filename: "schema.json" },
6569
];
6670

6771
// Dynamically import fs/promises for ESM compatibility
@@ -71,7 +75,7 @@ const generateSchemas = async (): Promise<void> => {
7175
await Promise.all(
7276
schemas.map(async ({ data, filename }) => {
7377
const dest = path.join(directory, filename);
74-
return writeFile(dest, JSON.stringify(data), "utf-8");
78+
return writeFile(dest, JSON.stringify(data, null, 3), "utf-8");
7579
}),
7680
);
7781
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { z } from "zod/v4";
2+
3+
type CollectionMetadata = {
4+
id: string;
5+
description: string;
6+
examples: z.$output[];
7+
};
8+
9+
export const jsonCollection = z.registry<CollectionMetadata>();
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { z } from "zod/v4";
2+
import { jsonCollection } from "../../json-collection.js";
3+
import { createReference } from "../../utility/create-reference.js";
4+
5+
export const ancestry = z
6+
.object({
7+
_type: z.literal("ancestry"),
8+
name: z.string(),
9+
description: z.string().optional(),
10+
primaryFeature: z.object({ name: z.string(), description: z.string() }),
11+
secondaryFeature: z.object({ name: z.string(), description: z.string() }),
12+
})
13+
.register(jsonCollection, {
14+
id: "Ancestry",
15+
description: "The ancestry of a character",
16+
examples: [
17+
{
18+
_type: "ancestry",
19+
name: "Ribbet",
20+
description:
21+
"Ribbets resemble anthropomorphic frogs with protruding eyes, and webbed hands and feet.",
22+
primaryFeature: {
23+
name: "Amphibious",
24+
description: "You can breathe and move naturally under water.",
25+
},
26+
secondaryFeature: {
27+
name: "Long Tounge",
28+
description:
29+
"You can use your long tounge to grab onto things within close range. Mark a stress to use your tounge as a finesse close weapon that deals d12 physical damage using your proficiency.",
30+
},
31+
},
32+
],
33+
});
34+
35+
export const ancestryReference = createReference("heritage/ancestry").register(
36+
jsonCollection,
37+
{
38+
id: "AncestryReference",
39+
description: "A reference to an ancestry",
40+
examples: [
41+
{
42+
_type: "reference",
43+
_key: "heritage/ancestry",
44+
value: "ribbet",
45+
},
46+
],
47+
},
48+
);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { z } from "zod/v4";
2+
import { jsonCollection } from "../../json-collection.js";
3+
import { createReference } from "../../utility/create-reference.js";
4+
5+
export const community = z
6+
.object({
7+
_type: z.literal("community"),
8+
name: z.string(),
9+
description: z.string().optional(),
10+
feature: z.object({
11+
name: z.string(),
12+
description: z.string(),
13+
}),
14+
})
15+
.register(jsonCollection, {
16+
id: "Community",
17+
description: "A community that shaped a characters backstory",
18+
examples: [
19+
{
20+
_type: "community",
21+
name: "Highborn",
22+
description:
23+
"Being part of a highborn community means you're accustomed to a life of elegance, opulence, and prestige within the upper echelons of society.",
24+
feature: {
25+
name: "Privilege",
26+
description:
27+
"You have advantage on rolls to consort with nobles, negotiate prices, or leverage your reputation to get what you want.",
28+
},
29+
},
30+
],
31+
});
32+
33+
export const communityReference = createReference(
34+
"heritage/community",
35+
).register(jsonCollection, {
36+
id: "CommunityReference",
37+
description: "A reference to a community",
38+
examples: [
39+
{
40+
_type: "reference",
41+
_key: "heritage/community",
42+
value: "highborn",
43+
},
44+
],
45+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { z } from "zod/v4";
2+
import { jsonCollection } from "../../json-collection.js";
3+
import { createReference } from "../../utility/create-reference.js";
4+
5+
export const domain = z
6+
.object({
7+
_type: z.literal("domain"),
8+
name: z.string(),
9+
description: z.string().nullable(),
10+
})
11+
.register(jsonCollection, {
12+
id: "Domain",
13+
description: "A domain of a character class",
14+
examples: [
15+
{
16+
_type: "domain",
17+
name: "Arcana",
18+
description:
19+
"Arcana is the domain of innate and instinctual magic. Those who choose this path tap into the raw, enigmatic forces of the realms to manipulate both their own energy and the elements. Arcana offers wielders a volatile power, but it is incredibly potent when correctly channeled. The Arcana domain can be accessed by the Druid and Sorcerer classes.",
20+
},
21+
],
22+
});
23+
24+
export const domainReference = createReference("role/domain").register(
25+
jsonCollection,
26+
{
27+
id: "DomainReference",
28+
description: "A reference to a domain",
29+
examples: [
30+
{
31+
_type: "reference",
32+
_key: "role/domain",
33+
value: "arcana",
34+
},
35+
],
36+
},
37+
);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export { ancestry, ancestryReference } from "./ancestry.js";
2+
export { community, communityReference } from "./community.js";
3+
export { domain, domainReference } from "./domain.js";
4+
export { inventoryArmor, inventoryArmorReference } from "./inventory-armor.js";
5+
export { inventoryThing, inventoryThingReference } from "./inventory-thing.js";
6+
export {
7+
inventoryWeapon,
8+
inventoryWeaponReference,
9+
} from "./inventory-weapon.js";
10+
export { roleClass, roleClassReference } from "./role-class.js";
11+
export { roleSubclass, roleSubclassReference } from "./role-subclass.js";
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { z } from "zod/v4";
2+
import { jsonCollection } from "../../json-collection.js";
3+
import { createReference } from "../../utility/create-reference.js";
4+
import { damageThresholds } from "../common/damage-threshold.js";
5+
6+
export const inventoryArmor = z
7+
.object({
8+
_type: z.literal("inventoryArmor").default("inventoryArmor"),
9+
name: z.string(),
10+
description: z.string().nullable(),
11+
baseThresholds: damageThresholds,
12+
baseScore: z.number().int().min(0),
13+
features: z.array(z.string()).nullable(),
14+
})
15+
.register(jsonCollection, {
16+
id: "ItemArmor",
17+
description: "A set of armor that can be equipped by a character",
18+
examples: [
19+
{
20+
_type: "inventoryArmor",
21+
name: "Full Plate Armor",
22+
description: null,
23+
baseThresholds: {
24+
_type: "damageThresholds",
25+
major: 8,
26+
severe: 17,
27+
},
28+
baseScore: 4,
29+
features: ["Very Heavy: -2 to Evasion"],
30+
},
31+
],
32+
});
33+
34+
export const inventoryArmorReference = createReference("item/armor").register(
35+
jsonCollection,
36+
{
37+
id: "ItemArmorReference",
38+
description: "A reference to an armor",
39+
examples: [
40+
{
41+
_type: "reference",
42+
_key: "item/armor",
43+
value: "full-plate-armor",
44+
},
45+
],
46+
},
47+
);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { z } from "zod/v4";
2+
import { jsonCollection } from "../../json-collection.js";
3+
import { createReference } from "../../utility/create-reference.js";
4+
5+
export const inventoryThing = z
6+
.object({
7+
_type: z.literal("inventoryThing").default("inventoryThing"),
8+
name: z.string(),
9+
description: z.string().nullable(),
10+
})
11+
.register(jsonCollection, {
12+
id: "Thing",
13+
description: "A thing that can be added to a character's inventory",
14+
examples: [
15+
{
16+
_type: "inventoryThing",
17+
name: "Suspicious looking potion",
18+
description: "The label is written in a language you don't recognize.",
19+
},
20+
],
21+
});
22+
23+
export const inventoryThingReference = createReference("item/special").register(
24+
jsonCollection,
25+
{
26+
id: "ItemSpecialReference",
27+
description: "A reference to a special item",
28+
examples: [
29+
{
30+
_type: "reference",
31+
_key: "item/special",
32+
value: "suspicious-looking-potion",
33+
},
34+
],
35+
},
36+
);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { z } from "zod/v4";
2+
import { jsonCollection } from "../../json-collection.js";
3+
import { createReference } from "../../utility/create-reference.js";
4+
import { damageType } from "../common/damage-type.js";
5+
import { diceType } from "../common/dice-type.js";
6+
import { range } from "../common/range.js";
7+
import { traitName } from "../common/trait.js";
8+
9+
export const inventoryWeapon = z
10+
.object({
11+
_type: z.literal("inventoryWeapon").default("inventoryWeapon"),
12+
name: z.string(),
13+
trait: traitName,
14+
range: range,
15+
damageDice: diceType,
16+
damageType: damageType,
17+
features: z.array(z.string()).nullable(),
18+
burden: z.union([z.literal("One-Handed"), z.literal("Two-Handed")]),
19+
})
20+
.register(jsonCollection, {
21+
id: "Weapon",
22+
description: "A weapon that can be equipped by a character",
23+
examples: [
24+
{
25+
_type: "inventoryWeapon",
26+
name: "Warhammer",
27+
trait: "Strength",
28+
range: "Melee",
29+
damageDice: "d8",
30+
damageType: "Physical",
31+
features: ["Versatile"],
32+
burden: "One-Handed",
33+
},
34+
],
35+
});
36+
37+
export const inventoryWeaponReference = createReference("item/weapon").register(
38+
jsonCollection,
39+
{
40+
id: "ItemWeaponReference",
41+
description: "A reference to a weapon",
42+
examples: [
43+
{
44+
_type: "reference",
45+
_key: "item/weapon",
46+
value: "warhammer",
47+
},
48+
],
49+
},
50+
);

0 commit comments

Comments
 (0)