a homebrewed DnD campaign based in the Honkai: Star Rail universe
hsr honkaistarrail dnd
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

merge packages into monorepo src/lib directory

and other changes...
- breadcrumbs can be defined easily as dynamic paths
- fix check constraint definitions in character_ability table (again)
- augment the `HTMLAttributes<T>` interface with data-loading and data-disabled properties (for later on)
- allow page meta to define nosnippet and maxsnippet rules

+222 -929
+3 -4
app/package.json
··· 35 35 "@fontsource-variable/suse": "catalog:app", 36 36 "@fontsource-variable/suse-mono": "catalog:app", 37 37 "@lucide/svelte": "catalog:svelte", 38 - "@starlight/icons": "link:../packages/icons", 39 - "@starlight/tokenizer": "link:../packages/tokenizer", 40 - "@starlight/types": "link:../packages/types", 38 + "@nc/whatwg-infra": "catalog:app", 41 39 "better-auth": "catalog:app", 42 40 "bits-ui": "catalog:svelte", 43 41 "clsx": "catalog:tailwind", ··· 45 43 "drizzle-zod": "catalog:app", 46 44 "lorem-ipsum": "catalog:app", 47 45 "mode-watcher": "catalog:svelte", 46 + "nanoid": "catalog:app", 48 47 "pg": "catalog:app", 49 48 "resend": "catalog:app", 50 49 "runed": "catalog:svelte", ··· 54 53 "tailwind-variants": "catalog:tailwind", 55 54 "ts-dedent": "catalog:app", 56 55 "tw-animate-css": "catalog:tailwind", 56 + "type-fest": "catalog:app", 57 57 "zod": "catalog:app" 58 58 }, 59 59 "devDependencies": { 60 60 "@playwright/test": "catalog:voidzero", 61 - "@starlight/storybook-utils": "link:../packages/storybook-utils", 62 61 "@sveltejs/adapter-cloudflare": "catalog:svelte", 63 62 "@sveltejs/kit": "catalog:svelte", 64 63 "@sveltejs/vite-plugin-svelte": "catalog:svelte",
+2
app/src/elements.d.ts
··· 3 3 declare module 'svelte/elements' { 4 4 export interface HTMLAttributes<T> { 5 5 'data-slot'?: string 6 + 'data-loading'?: boolean 7 + 'data-disabled'?: boolean 6 8 } 7 9 } 8 10
+3 -3
app/src/lib/server/campaign/db-schema.ts
··· 1 - import { ne, sql } from 'drizzle-orm' 1 + import { ne } from 'drizzle-orm' 2 2 import { 3 3 boolean, 4 4 check, ··· 11 11 } from 'drizzle-orm/pg-core' 12 12 import { publicId } from '$lib/unique-id' 13 13 import { user } from '$server/auth/db-schema' 14 - import { lower } from '$server/db/expressions' 14 + import { emptyString, lower } from '$server/db/expressions' 15 15 import { sourcebook } from '$server/sourcebook/db-schema' 16 16 17 17 export const campaign = pgTable( ··· 29 29 }, 30 30 (table) => [ 31 31 index('campaign_idx_lower_name').on(lower(table.name)), 32 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 32 + check('name_is_not_empty_string', ne(table.name, emptyString())), 33 33 ], 34 34 ) 35 35
+8 -8
app/src/lib/server/character/db-schema.ts
··· 15 15 import { background } from '$server/background/db-schema' 16 16 import { campaign } from '$server/campaign/db-schema' 17 17 import { characterClass } from '$server/class/db-schema' 18 - import { lower } from '$server/db/expressions' 18 + import { emptyString, lower } from '$server/db/expressions' 19 19 import { equipment } from '$server/equipment/db-schema' 20 20 import { language } from '$server/language/db-schema' 21 21 import { condition, damage } from '$server/mechanic/db-schema' ··· 52 52 }, 53 53 (table) => [ 54 54 index('character_idx_lower_name').on(lower(table.name)), 55 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 55 + check('name_is_not_empty_string', ne(table.name, emptyString())), 56 56 check('level_is_valid', sql`${table.level} >= 0 AND ${table.level} <= 20`), 57 57 check( 58 58 'current_hp_is_valid', ··· 117 117 cha: smallint('charisma').notNull(), 118 118 }, 119 119 (table) => [ 120 - check('str_is_nonnegative', sql`${table.str}, 0`), 121 - check('dex_is_nonnegative', sql`${table.dex}, 0`), 122 - check('con_is_nonnegative', sql`${table.con}, 0`), 123 - check('int_is_nonnegative', sql`${table.int}, 0`), 124 - check('wis_is_nonnegative', sql`${table.wis}, 0`), 125 - check('cha_is_nonnegative', sql`${table.cha}, 0`), 120 + check('str_is_nonnegative', sql`${table.str} >= 0`), 121 + check('dex_is_nonnegative', sql`${table.dex} >= 0`), 122 + check('con_is_nonnegative', sql`${table.con} >= 0`), 123 + check('int_is_nonnegative', sql`${table.int} >= 0`), 124 + check('wis_is_nonnegative', sql`${table.wis} >= 0`), 125 + check('cha_is_nonnegative', sql`${table.cha} >= 0`), 126 126 ], 127 127 ) 128 128
+4 -4
app/src/lib/server/class/db-schema.ts
··· 10 10 timestamp, 11 11 } from 'drizzle-orm/pg-core' 12 12 import { publicId } from '$lib/unique-id' 13 - import { lower } from '$server/db/expressions' 13 + import { emptyString, lower } from '$server/db/expressions' 14 14 import { sourcebook } from '$server/sourcebook/db-schema' 15 15 16 16 export const characterClass = pgTable( ··· 27 27 }, 28 28 (table) => [ 29 29 index('character_class_idx_lower_name').on(lower(table.name)), 30 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 30 + check('name_is_not_empty_string', ne(table.name, emptyString())), 31 31 ], 32 32 ) 33 33 ··· 44 44 }, 45 45 (table) => [ 46 46 index('character_class_feature_idx_lower_name').on(lower(table.name)), 47 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 47 + check('name_is_not_empty_string', ne(table.name, emptyString())), 48 48 check('level_is_valid', sql`${table.level} >= 1 AND ${table.level} <= 20`), 49 49 ], 50 50 ) ··· 62 62 }, 63 63 (table) => [ 64 64 index(`character_class_feature_mod_idx_lower_name`).on(table.name), 65 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 65 + check('name_is_not_empty_string', ne(table.name, emptyString())), 66 66 ], 67 67 )
+3 -3
app/src/lib/server/equipment/db-schema.ts
··· 12 12 timestamp, 13 13 } from 'drizzle-orm/pg-core' 14 14 import { publicId } from '$lib/unique-id' 15 - import { lower } from '$server/db/expressions' 15 + import { emptyString, lower } from '$server/db/expressions' 16 16 import { ability } from '$server/mechanic/db-schema' 17 17 import { sourcebook } from '$server/sourcebook/db-schema' 18 18 ··· 38 38 }, 39 39 (table) => [ 40 40 index('equipment_idx_lower_name').on(lower(table.name)), 41 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 41 + check('name_is_not_empty_string', ne(table.name, emptyString())), 42 42 ], 43 43 ) 44 44 ··· 89 89 }, 90 90 (table) => [ 91 91 index('equipment_category_idx_lower_name').on(lower(table.name)), 92 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 92 + check('name_is_not_empty_string', ne(table.name, emptyString())), 93 93 ], 94 94 ) 95 95
+4 -3
app/src/lib/server/faction/db-schema.ts
··· 1 - import { ne, sql } from 'drizzle-orm' 1 + import { ne } from 'drizzle-orm' 2 2 import { 3 3 check, 4 4 foreignKey, ··· 10 10 timestamp, 11 11 } from 'drizzle-orm/pg-core' 12 12 import { publicId } from '$lib/unique-id' 13 + import { emptyString } from '$server/db/expressions' 13 14 import { sourcebook } from '$server/sourcebook/db-schema' 14 15 15 16 export const faction = pgTable( ··· 26 27 }, 27 28 (table) => [ 28 29 index('faction_idx_lower_name').on(table.name), 29 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 30 + check('name_is_not_empty_string', ne(table.name, emptyString())), 30 31 foreignKey({ columns: [table.parentFactionId], foreignColumns: [table.id] }), 31 32 ], 32 33 ) ··· 55 56 (table) => [ 56 57 index().on(table.factionId1, table.factionId2), 57 58 check('factions_are_different', ne(table.factionId1, table.factionId2)), 58 - check('reason_is_not_empty_string', ne(table.reason, sql`''`)), 59 + check('reason_is_not_empty_string', ne(table.reason, emptyString())), 59 60 ], 60 61 )
+3 -3
app/src/lib/server/feat/db-schema.ts
··· 1 - import { ne, sql } from 'drizzle-orm' 1 + import { ne } from 'drizzle-orm' 2 2 import { boolean, check, index, integer, pgTable, text } from 'drizzle-orm/pg-core' 3 3 import { publicId } from '$lib/unique-id' 4 - import { lower } from '$server/db/expressions' 4 + import { emptyString, lower } from '$server/db/expressions' 5 5 6 6 export const feat = pgTable( 7 7 'feat', ··· 14 14 }, 15 15 (table) => [ 16 16 index('feat_idx_lower_name').on(lower(table.name)), 17 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 17 + check('name_is_not_empty_string', ne(table.name, emptyString())), 18 18 ], 19 19 )
+3 -3
app/src/lib/server/language/db-schema.ts
··· 1 - import { ne, sql } from 'drizzle-orm' 1 + import { ne } from 'drizzle-orm' 2 2 import { check, index, integer, pgTable, text } from 'drizzle-orm/pg-core' 3 - import { lower } from '$server/db/expressions' 3 + import { emptyString, lower } from '$server/db/expressions' 4 4 import { sourcebook } from '$server/sourcebook/db-schema' 5 5 6 6 export const language = pgTable( ··· 14 14 }, 15 15 (table) => [ 16 16 index('language_idx_lower_name').on(lower(table.name)), 17 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 17 + check('name_is_not_empty_string', ne(table.name, emptyString())), 18 18 ], 19 19 )
+6 -6
app/src/lib/server/mechanic/db-schema.ts
··· 1 - import { ne, sql } from 'drizzle-orm' 1 + import { ne } from 'drizzle-orm' 2 2 import { boolean, check, index, integer, pgTable, text } from 'drizzle-orm/pg-core' 3 - import { lower } from '$server/db/expressions' 3 + import { emptyString, lower } from '$server/db/expressions' 4 4 import { sourcebook } from '$server/sourcebook/db-schema' 5 5 6 6 export const condition = pgTable( ··· 15 15 }, 16 16 (table) => [ 17 17 index('mechanic_idx_lower_name').on(lower(table.name)), 18 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 18 + check('name_is_not_empty_string', ne(table.name, emptyString())), 19 19 ], 20 20 ) 21 21 ··· 31 31 }, 32 32 (table) => [ 33 33 index('damage_idx_lower_name').on(lower(table.name)), 34 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 34 + check('name_is_not_empty_string', ne(table.name, emptyString())), 35 35 ], 36 36 ) 37 37 ··· 44 44 }, 45 45 (table) => [ 46 46 index('ability_idx_lower_name').on(lower(table.name)), 47 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 47 + check('name_is_not_empty_string', ne(table.name, emptyString())), 48 48 ], 49 49 ) 50 50 ··· 60 60 }, 61 61 (table) => [ 62 62 index('skill_idx_lower_name').on(lower(table.name)), 63 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 63 + check('name_is_not_empty_string', ne(table.name, emptyString())), 64 64 ], 65 65 )
+3 -3
app/src/lib/server/monster/db-schema.ts
··· 11 11 } from 'drizzle-orm/pg-core' 12 12 import { publicId } from '$lib/unique-id' 13 13 import { campaignSession } from '$server/campaign/db-schema' 14 - import { lower } from '$server/db/expressions' 14 + import { emptyString, lower } from '$server/db/expressions' 15 15 import { damage } from '$server/mechanic/db-schema' 16 16 import { sourcebook } from '$server/sourcebook/db-schema' 17 17 ··· 35 35 }, 36 36 (table) => [ 37 37 index('monster_idx_lower_name').on(lower(table.name)), 38 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 38 + check('name_is_not_empty_string', ne(table.name, emptyString())), 39 39 check('walk_speed_is_nonnegative', sql`${table.walkSpeed} >= 0`), 40 40 check('swim_speed_is_nonnegative', sql`${table.swimSpeed} >= 0`), 41 - check('climb_speed_is_nonnegative', sql`${table.climbSpeed} 0`), 41 + check('climb_speed_is_nonnegative', sql`${table.climbSpeed} >= 0`), 42 42 check('fly_speed_is_nonnegative', sql`${table.flySpeed} >= 0`), 43 43 check('burrow_speed_is_nonnegative', sql`${table.burrowSpeed} >= 0`), 44 44 ],
+2 -2
app/src/lib/server/spell/db-schema.ts
··· 12 12 pgEnum, 13 13 } from 'drizzle-orm/pg-core' 14 14 import { publicId } from '$lib/unique-id' 15 - import { lower } from '$server/db/expressions' 15 + import { emptyString, lower } from '$server/db/expressions' 16 16 import { damage } from '$server/mechanic/db-schema' 17 17 import { sourcebook } from '$server/sourcebook/db-schema' 18 18 ··· 54 54 }, 55 55 (table) => [ 56 56 index('spell_idx_lower_name').on(lower(table.name)), 57 - check('name_is_not_empty_string', ne(table.name, sql`''`)), 57 + check('name_is_not_empty_string', ne(table.name, emptyString())), 58 58 check('level_is_valid', sql`${table.level} >= 0 AND ${table.level} <= 9`), 59 59 ], 60 60 )
+1 -1
app/src/lib/server/spell/spell-repo.ts
··· 1 - import type { SpellDuration } from '@starlight/types/dnd' 2 1 import { eq, type InferInsertModel, type InferSelectModel } from 'drizzle-orm' 2 + import type { SpellDuration } from '$lib/engine/dnd/spell-duration' 3 3 import type { 4 4 DatabaseSource, 5 5 InferUpdateModel,
+27
app/src/lib/truncate-text.ts
··· 1 + const segmenter = new Intl.Segmenter('en', { granularity: 'word' }) 2 + 3 + /** 4 + * Locale-aware text truncation. The truncation does not occur 5 + * in the middle of a word, but before the next word that would 6 + * overflow the given max length. 7 + */ 8 + export function truncateText(s: string, maxLength: number) { 9 + if (s.length === 0 || maxLength === 0) { 10 + return '' 11 + } 12 + 13 + const words = segmenter.segment(s) 14 + const joined: string[] = [] 15 + let runningLength = 1 // 1 for the ellipsis 16 + 17 + for (const word of words) { 18 + const newLength = runningLength + word.segment.length 19 + if (newLength <= maxLength) { 20 + runningLength = newLength 21 + joined.push(word.segment) 22 + } 23 + } 24 + 25 + const ellipsis = '\u2026' 26 + return `${joined.join('').trim()}${ellipsis}` 27 + }
+1 -1
app/src/lib/ui/components/button/button.stories.svelte
··· 1 1 <script module> 2 - import { typeAs } from '@starlight/storybook-utils' 2 + import { typeAs } from '$lib/storybook/type-as' 3 3 import { defineMeta } from '@storybook/addon-svelte-csf' 4 4 import Button from './Button.svelte' 5 5
+1 -1
app/src/lib/ui/components/chip/chip.stories.svelte
··· 1 1 <script module> 2 - import { typeAs } from '@starlight/storybook-utils' 2 + import { typeAs } from '$lib/storybook/type-as' 3 3 import { defineMeta } from '@storybook/addon-svelte-csf' 4 4 import Chip from './chip.svelte' 5 5
+1 -1
app/src/lib/ui/components/separator/Separator.stories.svelte
··· 1 1 <script module> 2 - import { baseArgTypes } from '@starlight/storybook-utils' 2 + import { baseArgTypes } from '$lib/storybook/type-as' 3 3 import { defineMeta } from '@storybook/addon-svelte-csf' 4 4 import Separator from './Separator.svelte' 5 5
+2 -2
app/src/lib/ui/components/separator/phrase-separator.stories.svelte
··· 1 1 <script module> 2 - import { baseArgTypes, typeAs } from '@starlight/storybook-utils' 2 + import { baseArgTypes, typeAs } from '$lib/storybook/type-as' 3 3 import { defineMeta } from '@storybook/addon-svelte-csf' 4 - import PhraseSeparator from './PhraseSeparator.svelte' 4 + import PhraseSeparator from './phrase-separator.svelte' 5 5 6 6 const { Story } = defineMeta({ 7 7 component: PhraseSeparator,
+1 -1
app/src/lib/ui/components/text/Text.stories.svelte
··· 1 1 <script module> 2 - import { typeAs } from '@starlight/storybook-utils' 2 + import { typeAs } from '$lib/storybook/type-as' 3 3 import { defineMeta } from '@storybook/addon-svelte-csf' 4 4 import Text from './Text.svelte' 5 5
+1
app/src/lib/ui/icons/element-icon/index.ts
··· 1 + export { default as ElementIcon } from './ElementIcon.svelte'
+1
app/src/lib/ui/icons/mechanic-icon/index.ts
··· 1 + export { default as MechanicIcon } from './MechanicIcon.svelte'
+28 -1
app/src/lib/ui/layout/breadcrumb/index.ts
··· 1 1 export { default as Breadcrumb } from './breadcrumb.svelte' 2 2 3 3 import type { BreadcrumbItemProps } from './types' 4 - export function definePaths<TPath extends string>(paths: Record<TPath, BreadcrumbItemProps[]>) { 4 + 5 + type StaticPath<TPath extends string> = Record<TPath, BreadcrumbItemProps[]> 6 + type DynamicPath<TPath extends string> = Record< 7 + TPath, 8 + (path: string, text: string) => BreadcrumbItemProps[] 9 + > 10 + 11 + export function definePaths<TPath extends string>(paths: StaticPath<TPath>) { 12 + return paths 13 + } 14 + 15 + export function defineDynamicPaths<TPath extends string>(paths: DynamicPath<TPath>) { 5 16 return paths 6 17 } 18 + 19 + export function paths<TStaticPath extends string, TDynamicPath extends string>(paths: { 20 + staticPaths: StaticPath<TStaticPath> 21 + dynamicPaths?: DynamicPath<TDynamicPath> 22 + }) { 23 + // oxlint-disable-next-line no-explicit-any 24 + const newPaths = { staticPaths: paths.staticPaths } as any 25 + if (paths.dynamicPaths === undefined) { 26 + newPaths['dynamicPaths'] = {} 27 + } 28 + 29 + return newPaths as { 30 + staticPaths: StaticPath<TStaticPath> 31 + dynamicPaths: DynamicPath<TDynamicPath> 32 + } 33 + }
+8 -5
app/src/lib/ui/page-meta/page-meta.svelte
··· 11 11 }: PageMetaOptions = $props() 12 12 let htmlTitle = $derived(pageTitle(title)) 13 13 let htmlUrl = $derived(page.url.toString()) 14 - let htmlRobots = $derived.by(() => { 14 + let htmlRules = $derived.by(() => { 15 15 if (robots === undefined) { 16 16 return 'none' 17 17 } 18 18 19 19 const rules = [] 20 - if(robots.noindex) { rules.push('noindex') } 21 - if(robots.nofollow) { rules.push('nofollow') } 22 - if(robots.noimageindex) { rules.push('noimageindex') } 20 + if (robots.noindex) { rules.push('noindex') } 21 + if (robots.nofollow) { rules.push('nofollow') } 22 + if (robots.noimageindex) { rules.push('noimageindex') } 23 + if (robots.nosnippet) { rules.push('nosnippet') } 24 + if (robots.maxsnippet) { rules.push(`max-snippet:${robots.maxsnippet}`) } 23 25 return rules.join(', ') 24 26 }) 25 27 ··· 27 29 28 30 <title>{htmlTitle}</title> 29 31 <meta name="description" content={description} /> 30 - <meta name="robots" content={htmlRobots} /> 32 + <meta name="robots" content={htmlRules} /> 31 33 <meta property="og:title" content={htmlTitle} /> 32 34 <meta property="og:description" content={description} /> 33 35 <meta property="og:type" content="website" /> 34 36 <meta property="og:url" content={htmlUrl} /> 35 37 <meta property="og:site_name" content="The Drifting Starlight" /> 38 + <meta name="format-detection" content="telephone=no">
+2
app/src/lib/ui/page-meta/types.ts
··· 6 6 nofollow?: boolean 7 7 noindex?: boolean 8 8 noimageindex?: boolean 9 + nosnippet?: boolean 10 + maxsnippet?: number 9 11 } 10 12 }
+1 -1
app/src/lib/ui/patterns/ability-card/ability-card.stories.svelte
··· 1 1 <script module> 2 - import { typeAs } from '@starlight/storybook-utils' 2 + import { typeAs } from '$lib/storybook/type-as' 3 3 import { defineMeta } from '@storybook/addon-svelte-csf' 4 4 import { AbilityCard } from '$ui/patterns/ability-card' 5 5
+6 -4
app/src/lib/ui/patterns/ability-card/ability-card.svelte
··· 14 14 </script> 15 15 16 16 <script lang="ts"> 17 - import { ElementIcon } from '@starlight/icons' 18 - import type { DiceRoll, AbilityRoll, SpellComponentAbbr } from '@starlight/types/dnd' 19 - import { getSpellComponentName } from '@starlight/types/dnd' 20 - import type { Element, Mechanic } from '@starlight/types/hsr' 17 + import type { DiceRoll } from '$lib/engine/dnd/dice-roll' 18 + import type { AbilityRoll } from '$lib/engine/dnd/ability' 19 + import { getSpellComponentName, type SpellComponentAbbr } from '$lib/engine/dnd/spell-component' 20 + import type { Element } from '$lib/engine/hsr/element' 21 + import type { Mechanic } from '$lib/engine/hsr/mechanic' 21 22 import { Card } from '$ui/components/card' 22 23 import { DescList } from '$ui/components/desc-list' 23 24 import { Tooltip } from '$ui/components/tooltip' 25 + import { ElementIcon } from '$ui/icons/element-icon' 24 26 import { CombatText } from '$ui/patterns/combat-text' 25 27 import { ElementText } from '$ui/patterns/element' 26 28 import { MechanicChip } from '$ui/patterns/mechanic'
+1 -1
app/src/lib/ui/patterns/combat-text/combat-text.stories.svelte
··· 1 1 <script module> 2 - import { typeAs } from '@starlight/storybook-utils' 2 + import { typeAs } from '$lib/storybook/type-as' 3 3 import { defineMeta } from '@storybook/addon-svelte-csf' 4 4 import { CombatText } from '$ui/patterns/combat-text' 5 5
+1 -1
app/src/lib/ui/patterns/combat-text/combat-text.svelte
··· 1 1 <script lang="ts"> 2 - import { tokenize } from '@starlight/tokenizer' 2 + import { tokenize } from '$lib/engine/tokenizer/tokenize' 3 3 import type { SvelteHTMLElements } from 'svelte/elements' 4 4 import { ElementText } from '$ui/patterns/element' 5 5
+1 -1
app/src/lib/ui/patterns/element/element-chip.stories.svelte
··· 1 1 <script module> 2 2 import { defineMeta } from '@storybook/addon-svelte-csf' 3 - import { typeAs } from '@starlight/storybook-utils' 3 + import { typeAs } from '$lib/storybook/type-as' 4 4 import { ElementChip } from '$ui/patterns/element' 5 5 6 6 const { Story } = defineMeta({
+2 -2
app/src/lib/ui/patterns/element/element-chip.svelte
··· 1 1 <script lang="ts"> 2 - import { type Element, getElementColor } from '@starlight/types/hsr' 2 + import { type Element, getElementColor } from '$lib/engine/hsr/element' 3 3 import { Chip, type ChipProps } from '$ui/components/chip' 4 - import ElementText from './ElementText.svelte' 4 + import ElementText from './element-text.svelte' 5 5 6 6 type Omitted = 'color' | 'withIcon' | 'withDot' 7 7 type ElementChipRootElement = Omit<ChipProps, Omitted>
+1 -1
app/src/lib/ui/patterns/element/element-text.stories.svelte
··· 1 1 <script module> 2 2 import { defineMeta } from '@storybook/addon-svelte-csf' 3 - import { typeAs } from '@starlight/storybook-utils' 3 + import { typeAs } from '$lib/storybook/type-as' 4 4 import { ElementText } from '$ui/patterns/element' 5 5 6 6 const { Story } = defineMeta({
+1 -1
app/src/lib/ui/patterns/element/element-text.svelte
··· 1 1 <script lang="ts"> 2 - import { getElementName, getElementColor, type Element } from '@starlight/types/hsr' 2 + import { getElementName, getElementColor, type Element } from '$lib/engine/hsr/element' 3 3 import type { SvelteHTMLElements } from 'svelte/elements' 4 4 import Text from '$ui/components/text/Text.svelte' 5 5 import type { TextProps } from '$ui/components/text/Text'
+1 -1
app/src/lib/ui/patterns/mechanic/mechanic-chip.stories.svelte
··· 1 1 <script module> 2 - import { typeAs } from '@starlight/storybook-utils' 2 + import { typeAs } from '$lib/storybook/type-as' 3 3 import { defineMeta } from '@storybook/addon-svelte-csf' 4 4 import { MechanicChip } from '$ui/patterns/mechanic' 5 5
+2 -2
app/src/lib/ui/patterns/mechanic/mechanic-chip.svelte
··· 1 1 <script lang="ts"> 2 - import { MechanicIcon } from '@starlight/icons' 3 - import { getMechanicName, type Mechanic } from '@starlight/types/hsr' 2 + import { MechanicIcon } from '$ui/icons/mechanic-icon' 3 + import { getMechanicName, type Mechanic } from '$lib/engine/hsr/mechanic' 4 4 import { Chip, type ChipProps } from '$ui/components/chip' 5 5 6 6 type Style = 'fill' | 'outline'
+1 -1
app/src/lib/ui/patterns/proficiency/Proficiency.svelte
··· 1 1 <script lang="ts"> 2 2 import type { SvelteHTMLElements } from 'svelte/elements' 3 3 import { cn, tv } from 'tailwind-variants' 4 - import type { Proficiency } from '@starlight/types/dnd' 4 + import type { Proficiency } from '$lib/engine/dnd/proficiency' 5 5 6 6 type SkillProficiencyRootElement = SvelteHTMLElements['div'] 7 7 type SkillProficiencyProps = SkillProficiencyRootElement & {
+1 -1
app/src/lib/ui/patterns/skill-scores/types.ts
··· 1 - import type { AbilityAbbr } from '@starlight/types/dnd' 1 + import type { AbilityAbbr } from '$lib/engine/dnd/ability' 2 2 3 3 export type ProficiencyKind = 'untrained' | 'halfProficient' | 'proficient' | 'expertise' 4 4
+1 -1
app/src/lib/unique-id.ts
··· 22 22 * Intended as public-facing and readable IDs in URLs. 23 23 * @see https://planetscale.com/blog/why-we-chose-nanoids-for-planetscales-api 24 24 */ 25 - export function publicId(name: string = 'public_id') { 25 + export function publicId(name = 'public_id') { 26 26 return text(name) 27 27 .$defaultFn(() => nanoid()) 28 28 .unique()
app/src/routes/(app)/classes/[page]/+page.svelte

This is a binary file and will not be displayed.

+1 -1
app/src/routes/(app)/classes/new/page.remote.ts
··· 1 - import { AbilityAbbrArray, getAbilityDesc, getAbilityName } from '@starlight/types/dnd' 2 1 import { prerender, query } from '$app/server' 2 + import { AbilityAbbrArray, getAbilityDesc, getAbilityName } from '$lib/engine/dnd/ability' 3 3 import { definePageMeta } from '$ui/page-meta' 4 4 5 5 export const getPageMeta = prerender(() =>
app/src/routes/(app)/sourcebooks/[page]/+page.svelte

This is a binary file and will not be displayed.

+1 -1
app/src/routes/(app)/species/new/page.remote.ts
··· 1 - import { AbilityAbbrArray, getAbilityDesc, getAbilityName } from '@starlight/types/dnd' 2 1 import { prerender, query } from '$app/server' 2 + import { AbilityAbbrArray, getAbilityDesc, getAbilityName } from '$lib/engine/dnd/ability' 3 3 import { definePageMeta } from '$ui/page-meta' 4 4 5 5 export const getPageMeta = prerender(() =>
+9 -4
app/src/routes/(app)/spells/page.remote.ts
··· 1 1 import { prerender, query } from '$app/server' 2 2 import { db } from '$server/db' 3 3 import { SpellRepository } from '$server/spell/spell-repo' 4 - import { definePaths } from '$ui/layout/breadcrumb' 4 + import { paths } from '$ui/layout/breadcrumb' 5 5 import { definePageMeta } from '$ui/page-meta' 6 6 7 7 export const getPageMeta = prerender(() => ··· 21 21 const root = { path: '/spells', text: 'Spells' } 22 22 const newEntry = { path: '/spells/new', text: 'Create a new spell entry' } 23 23 24 - return definePaths({ 25 - root: [root], 26 - newEntry: [root, newEntry], 24 + return paths({ 25 + staticPaths: { 26 + root: [root], 27 + newEntry: [root, newEntry], 28 + }, 29 + dynamicPaths: { 30 + page: (path, text) => [root, newEntry, { path: `/spells/new/${path}`, text }], 31 + }, 27 32 }) 28 33 })
+1 -1
app/src/routes/(auth)/AuthFooter.svelte
··· 1 1 <script lang="ts"> 2 - import { GoogleIcon } from '@starlight/icons' 3 2 import type { ComponentProps } from 'svelte' 4 3 import type { SvelteHTMLElements } from 'svelte/elements' 5 4 import { Button } from '$ui/components/button' 5 + import GoogleIcon from '$ui/icons/logos/GoogleIcon.svelte' 6 6 7 7 type AuthFooterRootElement = SvelteHTMLElements['button'] 8 8 type AuthFooterProps = AuthFooterRootElement & {
+1 -1
app/src/routes/users/[username]/CharacterPreview.svelte
··· 1 1 <script lang="ts"> 2 - import type { CharacterLevel } from '@starlight/types/dnd' 2 + import type { CharacterLevel } from '$lib/engine/dnd/character-level' 3 3 import type { SvelteHTMLElements } from 'svelte/elements' 4 4 import { Chip } from '$ui/components/chip' 5 5
-1
app/src/styles/app.css
··· 4 4 @import './color.css'; 5 5 @import './utilities.css'; 6 6 @import 'shadcn-svelte/tailwind.css'; 7 - @source './../../node_modules/@starlight/icons'; 8 7 9 8 @custom-variant dark (&:is(.dark *)); 10 9
+1
app/svelte.config.js
··· 24 24 alias: { 25 25 $ui: 'src/lib/ui', 26 26 $server: 'src/lib/server', 27 + $engine: 'src/lib/engine', 27 28 $story: '.storybook/', 28 29 }, 29 30 experimental: {
-24
packages/icons/.gitignore
··· 1 - node_modules 2 - 3 - # Output 4 - .output 5 - .vercel 6 - .netlify 7 - .wrangler 8 - /.svelte-kit 9 - /build 10 - /dist 11 - 12 - # OS 13 - .DS_Store 14 - Thumbs.db 15 - 16 - # Env 17 - .env 18 - .env.* 19 - !.env.example 20 - !.env.test 21 - 22 - # Vite 23 - vite.config.js.timestamp-* 24 - vite.config.ts.timestamp-*
-36
packages/icons/.storybook/main.ts
··· 1 - import type { StorybookConfig } from '@storybook/sveltekit' 2 - import type { UserConfig } from 'vite' 3 - import { dirname } from 'node:path' 4 - import { fileURLToPath } from 'node:url' 5 - 6 - const config: StorybookConfig = { 7 - stories: ['../stories/*.stories.svelte'], 8 - staticDirs: ['../static'], 9 - addons: [ 10 - getAbsolutePath('@storybook/addon-docs'), 11 - getAbsolutePath('@storybook/addon-svelte-csf'), 12 - getAbsolutePath('@storybook/addon-themes'), 13 - getAbsolutePath('@storybook/addon-a11y'), 14 - getAbsolutePath('@storybook/addon-vitest'), 15 - ], 16 - framework: { 17 - name: getAbsolutePath('@storybook/sveltekit'), 18 - options: {}, 19 - }, 20 - async viteFinal(config) { 21 - const { mergeConfig } = await import('vite') 22 - return mergeConfig(config, { 23 - server: { 24 - fs: { 25 - strict: false, 26 - }, 27 - }, 28 - } satisfies UserConfig) 29 - }, 30 - } 31 - 32 - export default config 33 - 34 - function getAbsolutePath(value: string): string { 35 - return dirname(fileURLToPath(import.meta.resolve(`${value}/package.json`))) 36 - }
-27
packages/icons/.storybook/preview.ts
··· 1 - import type { Preview } from '@storybook/sveltekit' 2 - import './tailwind.css' 3 - 4 - const preview: Preview = { 5 - parameters: { 6 - backgrounds: { 7 - options: { 8 - dark: { name: 'Dark', value: '#151512' }, 9 - light: { name: 'Light', value: '#fff' }, 10 - }, 11 - }, 12 - controls: { 13 - matchers: { 14 - color: /(background|color)$/i, 15 - date: /Date$/i, 16 - }, 17 - }, 18 - docs: { 19 - codePanel: true, 20 - }, 21 - a11y: { 22 - test: 'todo', 23 - }, 24 - }, 25 - } 26 - 27 - export default preview
-1
packages/icons/.storybook/tailwind.css
··· 1 - @import 'tailwindcss';
-66
packages/icons/package.json
··· 1 - { 2 - "name": "@starlight/icons", 3 - "version": "0.0.1", 4 - "private": true, 5 - "files": [ 6 - "dist", 7 - "!dist/**/*.spec.*", 8 - "!dist/**/*.test.*" 9 - ], 10 - "type": "module", 11 - "sideEffects": [ 12 - "**/*.css" 13 - ], 14 - "types": "./dist/index.d.ts", 15 - "svelte": "./dist/index.js", 16 - "exports": { 17 - ".": { 18 - "types": "./dist/index.d.ts", 19 - "svelte": "./dist/index.js" 20 - }, 21 - "./hsr/element": { 22 - "types": "./dist/ElementIcon.svelte.d.ts", 23 - "svelte": "./dist/ElementIcon.svelte" 24 - }, 25 - "./hsr/mechanic": { 26 - "types": "./dist/MechanicIcon.svelte.d.ts", 27 - "svelte": "./dist/MechanicIcon.svelte" 28 - }, 29 - "./logos/google": { 30 - "types": "./dist/GoogleIcon.svelte.d.ts", 31 - "svelte": "./dist/GoogleIcon.svelte" 32 - } 33 - }, 34 - "scripts": { 35 - "dev": "vite dev", 36 - "build": "vite build && pnpm run prepack", 37 - "fmt": "oxfmt --config=../../.oxfmtrc.json", 38 - "lint": "oxlint", 39 - "fix": "oxlint --fix", 40 - "preview": "vite preview", 41 - "prepare": "svelte-kit sync || echo ''", 42 - "prepack": "svelte-kit sync && svelte-package", 43 - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 44 - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 45 - "storybook": "storybook dev -p 6006", 46 - "build-storybook": "storybook build" 47 - }, 48 - "dependencies": { 49 - "@starlight/types": "workspace:../types" 50 - }, 51 - "devDependencies": { 52 - "@starlight/storybook-utils": "link:../storybook-utils", 53 - "@sveltejs/adapter-auto": "catalog:svelte", 54 - "@sveltejs/kit": "catalog:svelte", 55 - "@sveltejs/package": "catalog:svelte", 56 - "@sveltejs/vite-plugin-svelte": "catalog:svelte", 57 - "@tailwindcss/vite": "catalog:tailwind", 58 - "svelte-check": "catalog:svelte", 59 - "tailwindcss": "catalog:tailwind", 60 - "typescript": "catalog:dev" 61 - }, 62 - "peerDependencies": { 63 - "@lucide/svelte": "^1.x", 64 - "svelte": "catalog:svelte" 65 - } 66 - }
-12
packages/icons/src/app.html
··· 1 - <!doctype html> 2 - <html lang="en"> 3 - <head> 4 - <meta charset="utf-8" /> 5 - <link rel="icon" href="%sveltekit.assets%/favicon.svg" /> 6 - <meta name="viewport" content="width=device-width, initial-scale=1" /> 7 - %sveltekit.head% 8 - </head> 9 - <body data-sveltekit-preload-data="hover"> 10 - <div style="display: contents">%sveltekit.body%</div> 11 - </body> 12 - </html>
packages/icons/src/lib/UniverseIcon.svelte app/src/lib/ui/icons/UniverseIcon.svelte
packages/icons/src/lib/WhirlIcon.svelte app/src/lib/ui/icons/WhirlIcon.svelte
+1 -1
packages/icons/src/lib/hsr/ElementIcon.svelte app/src/lib/ui/icons/element-icon/ElementIcon.svelte
··· 1 1 <script lang="ts"> 2 2 import type { IconProps } from '@lucide/svelte' 3 - import type { Element } from '@starlight/types/hsr' 4 3 import { cn, tv } from 'tailwind-variants' 4 + import type { Element } from '$lib/engine/hsr/element' 5 5 import { getElementIcon } from './ElementIcon.js' 6 6 7 7 const elementIconTv = tv({
+1 -1
packages/icons/src/lib/hsr/ElementIcon.ts app/src/lib/ui/icons/element-icon/ElementIcon.ts
··· 1 - import type { Element } from '@starlight/types/hsr' 2 1 import type { Component } from 'svelte' 3 2 import FlameIcon from '@lucide/svelte/icons/flame' 4 3 import SnowflakeIcon from '@lucide/svelte/icons/snowflake' 5 4 import SwordsIcon from '@lucide/svelte/icons/swords' 6 5 import WindIcon from '@lucide/svelte/icons/wind' 7 6 import ZapIcon from '@lucide/svelte/icons/zap' 7 + import type { Element } from '$lib/engine/hsr/element' 8 8 import UniverseIcon from '../UniverseIcon.svelte' 9 9 import WhirlIcon from '../WhirlIcon.svelte' 10 10
+1 -1
packages/icons/src/lib/hsr/MechanicIcon.svelte app/src/lib/ui/icons/mechanic-icon/MechanicIcon.svelte
··· 1 1 <script lang="ts"> 2 2 import type { IconProps } from '@lucide/svelte' 3 - import type { Mechanic } from '@starlight/types/hsr' 4 3 import { cn, tv, type VariantProps } from 'tailwind-variants' 4 + import type { Mechanic } from '$lib/engine/hsr/mechanic' 5 5 import { getMechanicIcon } from './MechanicIcon.js' 6 6 7 7 const mechanicIconTv = tv({
+1 -1
packages/icons/src/lib/hsr/MechanicIcon.ts app/src/lib/ui/icons/mechanic-icon/MechanicIcon.ts
··· 1 - import type { Mechanic } from '@starlight/types/hsr' 2 1 import type { Component } from 'svelte' 3 2 import BombIcon from '@lucide/svelte/icons/bomb' 4 3 import ChevronsDownIcon from '@lucide/svelte/icons/chevrons-down' ··· 9 8 import ShieldHalfIcon from '@lucide/svelte/icons/shield-half' 10 9 import SparklesIcon from '@lucide/svelte/icons/sparkles' 11 10 import SplitIcon from '@lucide/svelte/icons/split' 11 + import type { Mechanic } from '$lib/engine/hsr/mechanic' 12 12 13 13 const mechanicMap: Record<Mechanic, Component> = { 14 14 'single-target': CrosshairIcon,
-3
packages/icons/src/lib/index.ts
··· 1 - export { default as ElementIcon } from './hsr/ElementIcon.svelte' 2 - export { default as MechanicIcon } from './hsr/MechanicIcon.svelte' 3 - export { default as GoogleIcon } from './logos/GoogleIcon.svelte'
packages/icons/src/lib/logos/GoogleIcon.svelte app/src/lib/ui/icons/logos/GoogleIcon.svelte
packages/icons/static/.well-known

This is a binary file and will not be displayed.

+2 -2
packages/icons/stories/ElementIcon.stories.svelte app/src/lib/ui/icons/element-icon/ElementIcon.stories.svelte
··· 1 1 <script module> 2 2 import { defineMeta } from '@storybook/addon-svelte-csf' 3 - import { typeAs } from '@starlight/storybook-utils' 4 - import ElementIcon from './../src/lib/hsr/ElementIcon.svelte' 3 + import ElementIcon from './ElementIcon.svelte' 4 + import { typeAs } from '$lib/storybook/type-as' 5 5 6 6 const { Story } = defineMeta({ 7 7 component: ElementIcon,
+1 -1
packages/icons/stories/GoogleIcon.stories.svelte app/src/lib/ui/icons/logos/GoogleIcon.stories.svelte
··· 1 1 <script module> 2 2 import { defineMeta } from '@storybook/addon-svelte-csf' 3 - import GoogleIcon from './../src/lib/branding/GoogleIcon.svelte' 3 + import GoogleIcon from './GoogleIcon.svelte' 4 4 5 5 const { Story } = defineMeta({ 6 6 component: GoogleIcon,
+2 -2
packages/icons/stories/MechanicIcon.stories.svelte app/src/lib/ui/icons/mechanic-icon/MechanicIcon.stories.svelte
··· 1 1 <script module> 2 - import { typeAs } from '@starlight/storybook-utils' 3 2 import { defineMeta } from '@storybook/addon-svelte-csf' 4 - import MechanicIcon from './../src/lib/hsr/MechanicIcon.svelte' 3 + import { typeAs } from '$lib/storybook/type-as' 4 + import MechanicIcon from './MechanicIcon.svelte' 5 5 6 6 const { Story } = defineMeta({ 7 7 component: MechanicIcon,
-22
packages/icons/stories/PathIcon.stories.svelte
··· 1 - <script module> 2 - import { defineMeta } from '@storybook/addon-svelte-csf' 3 - import PathIcon from './../src/lib/hsr/path/PathIcon.svelte' 4 - 5 - const { Story } = defineMeta({ 6 - component: PathIcon, 7 - tags: ['autodocs'], 8 - }) 9 - </script> 10 - 11 - <Story name="Playground" args={{ path: 'destruction' }} /> 12 - <Story name="ElementIcon" asChild parameters={{ controls: { disable: true } }}> 13 - <div class="flex flex-col gap-2 items-start bg-blue-500"> 14 - <PathIcon path="abundance" class="fill-white size-8" /> 15 - <PathIcon path="destruction" /> 16 - <PathIcon path="erudition" /> 17 - <PathIcon path="hunt" /> 18 - <PathIcon path="nihility" /> 19 - <PathIcon path="preservation" /> 20 - <PathIcon path="remembrance" /> 21 - </div> 22 - </Story>
+1 -1
packages/icons/stories/UniverseIcon.stories.svelte app/src/lib/ui/icons/UniverseIcon.stories.svelte
··· 1 1 <script module> 2 2 import { defineMeta } from '@storybook/addon-svelte-csf' 3 - import UniverseIcon from './../src/lib/UniverseIcon.svelte' 3 + import UniverseIcon from './UniverseIcon.svelte' 4 4 5 5 const { Story } = defineMeta({ 6 6 component: UniverseIcon,
+1 -1
packages/icons/stories/WhirlIcon.stories.svelte app/src/lib/ui/icons/WhirlIcon.stories.svelte
··· 1 1 <script module> 2 2 import { defineMeta } from '@storybook/addon-svelte-csf' 3 - import WhirlIcon from './../src/lib/WhirlIcon.svelte' 3 + import WhirlIcon from './WhirlIcon.svelte' 4 4 5 5 const { Story } = defineMeta({ 6 6 component: WhirlIcon,
-10
packages/icons/svelte.config.js
··· 1 - import adapter from '@sveltejs/adapter-auto' 2 - import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' 3 - 4 - /** @type {import('@sveltejs/kit').Config} */ 5 - export default { 6 - preprocess: vitePreprocess(), 7 - kit: { 8 - adapter: adapter(), 9 - }, 10 - }
-16
packages/icons/tsconfig.json
··· 1 - { 2 - "extends": "./.svelte-kit/tsconfig.json", 3 - "compilerOptions": { 4 - "allowImportingTsExtensions": true, 5 - "allowJs": true, 6 - "checkJs": true, 7 - "esModuleInterop": true, 8 - "forceConsistentCasingInFileNames": true, 9 - "resolveJsonModule": true, 10 - "skipLibCheck": true, 11 - "sourceMap": true, 12 - "strict": true, 13 - "module": "NodeNext", 14 - "moduleResolution": "NodeNext" 15 - } 16 - }
-7
packages/icons/vite.config.ts
··· 1 - import { sveltekit } from '@sveltejs/kit/vite' 2 - import tailwindcss from '@tailwindcss/vite' 3 - import { defineProject } from 'vitest/config' 4 - 5 - export default defineProject({ 6 - plugins: [sveltekit(), tailwindcss()], 7 - })
-35
packages/storybook-utils/package.json
··· 1 - { 2 - "name": "@starlight/storybook-utils", 3 - "version": "1.0.0", 4 - "private": true, 5 - "license": "MIT", 6 - "author": "Samantha Nguyen", 7 - "files": [ 8 - "./dist" 9 - ], 10 - "type": "module", 11 - "exports": { 12 - ".": { 13 - "types": "./dist/index.d.mts", 14 - "import": "./dist/index.mjs" 15 - } 16 - }, 17 - "scripts": { 18 - "build": "tsdown", 19 - "dev": "tsdown --watch", 20 - "test": "vitest --coverage", 21 - "test-ui": "vitest --ui --coverage", 22 - "fmt": "oxfmt --config=../../.oxfmtrc.json", 23 - "lint": "oxlint", 24 - "fix": "oxlint --fix" 25 - }, 26 - "dependencies": { 27 - "@starlight/types": "workspace:../types" 28 - }, 29 - "devDependencies": { 30 - "typescript": "catalog:dev" 31 - }, 32 - "peerDependencies": { 33 - "storybook": "10.x" 34 - } 35 - }
+2 -1
packages/storybook-utils/src/index.ts app/src/lib/storybook/type-as.ts
··· 1 1 import type { BaseAnnotations, InputType } from 'storybook/internal/csf' 2 - import { ElementArray, MechanicArray } from '@starlight/types/hsr' 2 + import { ElementArray } from '$lib/engine/hsr/element' 3 + import { MechanicArray } from '$lib/engine/hsr/mechanic' 3 4 4 5 type InputTypeControl = InputType['control'] 5 6 type RefinedInputType<T extends keyof InputType> = Omit<InputType, T>
+3 -2
packages/storybook-utils/tests/index.test.ts app/src/lib/storybook/type-as.test.ts
··· 1 - import { ElementArray, MechanicArray } from '@starlight/types/hsr' 2 1 import { describe, expect, test } from 'vitest' 3 - import { typeAs } from '../src' 2 + import { ElementArray } from '$lib/engine/hsr/element' 3 + import { MechanicArray } from '$lib/engine/hsr/mechanic' 4 + import { typeAs } from './' 4 5 5 6 describe('typeAs', () => { 6 7 test('boolean()', () => {
-7
packages/storybook-utils/tsdown.config.ts
··· 1 - import { defineConfig } from 'tsdown' 2 - 3 - export default defineConfig({ 4 - entry: 'src/index.ts', 5 - minify: true, 6 - dts: true, 7 - })
-12
packages/storybook-utils/vite.config.ts
··· 1 - import { defineProject } from 'vitest/config' 2 - 3 - export default defineProject({ 4 - build: { 5 - lib: { 6 - entry: new URL('src/index.ts', import.meta.url).pathname, 7 - }, 8 - }, 9 - test: { 10 - includeSource: ['src/**/*.{js,ts}'], 11 - }, 12 - })
-8
packages/tokenizer/bench/tokenize.bench.ts
··· 1 - import { bench } from 'vitest' 2 - import { tokenize } from '../src' 3 - 4 - bench('tokenize()', () => { 5 - const text = 6 - "Deals quantum equal to [30,35,40,45,50] of Castorice's Max HP to one designated enemy." 7 - tokenize(text) 8 - })
-35
packages/tokenizer/package.json
··· 1 - { 2 - "name": "@starlight/tokenizer", 3 - "version": "1.0.0", 4 - "private": true, 5 - "license": "MIT", 6 - "author": "Samantha Nguyen", 7 - "files": [ 8 - "./dist" 9 - ], 10 - "type": "module", 11 - "module": "./dist/index.mjs", 12 - "types": "./dist/index.d.mts", 13 - "exports": { 14 - ".": { 15 - "types": "./dist/index.d.mts", 16 - "import": "./dist/index.mjs" 17 - } 18 - }, 19 - "scripts": { 20 - "build": "tsdown", 21 - "test": "vitest", 22 - "test-ci": "vitest --run", 23 - "test-ui": "vitest --ui", 24 - "fmt": "oxfmt --config=../../.oxfmtrc.json", 25 - "lint": "oxlint", 26 - "fix": "oxlint --fix" 27 - }, 28 - "dependencies": { 29 - "@nc/whatwg-infra": "npm:@jsr/nc__whatwg-infra@^1.1.0", 30 - "@starlight/types": "workspace:../types" 31 - }, 32 - "devDependencies": { 33 - "typescript": "catalog:dev" 34 - } 35 - }
-8
packages/tokenizer/src/index.ts
··· 1 - export { tokenize } from './tokenize' 2 - export type { 3 - Token, 4 - TokenDmgArray, 5 - TokenElementLiteral, 6 - TokenKind, 7 - TokenStringLiteral, 8 - } from './types'
packages/tokenizer/src/tokenize.ts app/src/lib/engine/tokenizer/tokenize.ts
+1 -1
packages/tokenizer/src/types.ts app/src/lib/engine/tokenizer/types.ts
··· 1 - import type { Element } from '@starlight/types/hsr' 1 + import type { Element } from '$lib/engine/hsr/element' 2 2 3 3 export type TokenDmgArray = { kind: 'DmgArray'; value: number[] } 4 4 export type TokenElementLiteral = { kind: 'ElementLiteral'; value: Element }
+1 -1
packages/tokenizer/src/utils.ts app/src/lib/engine/tokenizer/utils.ts
··· 1 - import { zElement, type Element } from '@starlight/types/hsr' 1 + import { zElement, type Element } from '$lib/engine/hsr/element' 2 2 import type { TokenStringLiteral } from './types' 3 3 4 4 type PredicateFn = (s: string) => boolean
+1 -1
packages/tokenizer/tests/tokenize.test.ts app/src/lib/engine/tokenizer/tokenize.test.ts
··· 1 1 import { assert, test } from 'vitest' 2 - import { tokenize } from '../src' 2 + import { tokenize } from './tokenize' 3 3 4 4 test('tokenize()', () => { 5 5 const text =
+1 -1
packages/tokenizer/tests/utilts.test.ts app/src/lib/engine/tokenizer/utilts.test.ts
··· 1 1 import { isAsciiDigit, isAsciiWsp } from '@nc/whatwg-infra/codePoints' 2 2 import { assert, describe, test } from 'vitest' 3 - import { splitBy } from '../src/utils' 3 + import { splitBy } from './utils' 4 4 5 5 describe('splitBy()', () => { 6 6 test('ascii whitespace', () => {
-7
packages/tokenizer/tsdown.config.ts
··· 1 - import { defineConfig } from 'tsdown' 2 - 3 - export default defineConfig({ 4 - entry: 'src/index.ts', 5 - minify: true, 6 - dts: true, 7 - })
-12
packages/tokenizer/vite.config.ts
··· 1 - import { defineProject } from 'vitest/config' 2 - 3 - export default defineProject({ 4 - build: { 5 - lib: { 6 - entry: new URL('src/index.ts', import.meta.url).pathname, 7 - }, 8 - }, 9 - test: { 10 - includeSource: ['src/**/*.{js,ts}'], 11 - }, 12 - })
-40
packages/types/package.json
··· 1 - { 2 - "name": "@starlight/types", 3 - "version": "1.0.0", 4 - "private": true, 5 - "license": "MIT", 6 - "author": "Samantha Nguyen", 7 - "files": [ 8 - "./dist" 9 - ], 10 - "type": "module", 11 - "exports": { 12 - "./dnd": { 13 - "types": "./dist/dnd/index.d.ts", 14 - "import": "./dist/dnd/index.js" 15 - }, 16 - "./hsr": { 17 - "types": "./dist/hsr/index.d.ts", 18 - "import": "./dist/hsr/index.js" 19 - }, 20 - "./zod": { 21 - "types": "./dist/zod.d.ts", 22 - "import": "./dist/zod.js" 23 - } 24 - }, 25 - "scripts": { 26 - "build": "tsdown", 27 - "dev": "tsdown --watch", 28 - "test": "vitest --coverage", 29 - "test-ci": "vitest --run --coverage", 30 - "test-ui": "vitest --ui --coverage", 31 - "fmt": "oxfmt --config=../../.oxfmtrc.json" 32 - }, 33 - "dependencies": { 34 - "type-fest": "catalog:dev", 35 - "zod": "catalog:app" 36 - }, 37 - "devDependencies": { 38 - "typescript": "catalog:dev" 39 - } 40 - }
+2
packages/types/src/dnd/ability.ts app/src/lib/engine/dnd/ability.ts
··· 36 36 WIS: { name: 'Wisdom', desc: 'A quality of perceptive attunement.' }, 37 37 CHA: { name: 'Charisma', desc: 'A quality of social appeal and glamour.' }, 38 38 } 39 + 39 40 export function getAbilityName(a: AbilityAbbr) { 40 41 return AbilityMap[a].name 41 42 } 43 + 42 44 export function getAbilityDesc(a: AbilityAbbr) { 43 45 return AbilityMap[a].desc 44 46 }
packages/types/src/dnd/alignment.ts app/src/lib/engine/dnd/alignment.ts
packages/types/src/dnd/character-level.ts app/src/lib/engine/dnd/character-level.ts
packages/types/src/dnd/dice-range.ts app/src/lib/engine/dnd/dice-range.ts
packages/types/src/dnd/dice-roll.ts app/src/lib/engine/dnd/dice-roll.ts
packages/types/src/dnd/feature.ts app/src/lib/engine/dnd/feature.ts
-11
packages/types/src/dnd/index.ts
··· 1 - export * from './ability' 2 - export * from './alignment' 3 - export * from './character-level' 4 - export * from './dice-roll' 5 - export * from './dice-range' 6 - export * from './feature' 7 - export * from './spell-component' 8 - export * from './spell-duration' 9 - export * from './spell-range' 10 - export * from './spell-school' 11 - export * from './proficiency'
packages/types/src/dnd/proficiency.ts app/src/lib/engine/dnd/proficiency.ts
packages/types/src/dnd/spell-component.ts app/src/lib/engine/dnd/spell-component.ts
packages/types/src/dnd/spell-duration.ts app/src/lib/engine/dnd/spell-duration.ts
packages/types/src/dnd/spell-range.ts app/src/lib/engine/dnd/spell-range.ts
packages/types/src/dnd/spell-school.ts app/src/lib/engine/dnd/spell-school.ts
packages/types/src/hsr/element.ts app/src/lib/engine/hsr/element.ts
-3
packages/types/src/hsr/index.ts
··· 1 - export * from './element' 2 - export * from './mechanic' 3 - export * from './path'
packages/types/src/hsr/mechanic.ts app/src/lib/engine/hsr/mechanic.ts
packages/types/src/hsr/path.ts app/src/lib/engine/hsr/path.ts
packages/types/src/obj.ts app/src/lib/engine/obj.ts
packages/types/src/zod.ts app/src/lib/engine/zod.ts
+3 -3
packages/types/tests/dnd/ability.test.ts app/src/lib/engine/dnd/ability.test.ts
··· 1 1 import { describe, expect, test } from 'vitest' 2 2 import { 3 - AbilityAbbr, 4 - AbilityName, 5 3 getAbilityName, 6 4 getAbilityDesc, 7 5 zAbilityAbbr, 8 6 zAbilityName, 9 7 zAbilityRoll, 10 - } from '../../src/dnd/ability' 8 + type AbilityName, 9 + type AbilityAbbr, 10 + } from './ability' 11 11 12 12 describe('zAbilityAbbr', () => { 13 13 describe('safeParse()', () => {
+1 -1
packages/types/tests/dnd/alignment.test.ts app/src/lib/engine/dnd/alignment.test.ts
··· 1 1 import { describe, expect, test } from 'vitest' 2 - import { zAlignment, zAlignmentAbbr } from '../../src/dnd/alignment' 2 + import { zAlignment, zAlignmentAbbr } from './alignment' 3 3 4 4 describe('zAlignmentAbbr', () => { 5 5 describe('safeParse()', () => {
+1 -1
packages/types/tests/dnd/character-level.test.ts app/src/lib/engine/dnd/character-level.test.ts
··· 1 1 import { describe, expect, test } from 'vitest' 2 - import { zCharacterLevel } from '../../src/dnd/character-level' 2 + import { zCharacterLevel } from './character-level' 3 3 4 4 describe('zCharacterLevel', () => { 5 5 describe('safeParse()', () => {
+1 -1
packages/types/tests/dnd/dice-range.test.ts app/src/lib/engine/dnd/dice-range.test.ts
··· 1 1 import { describe, expect, test } from 'vitest' 2 - import { zD10, zD12, zD20, zD4, zD6, zD8 } from '../../src/dnd/dice-range' 2 + import { zD10, zD12, zD20, zD4, zD6, zD8 } from './dice-range' 3 3 4 4 describe('zD4', () => { 5 5 describe('safeParse()', () => {
+1 -1
packages/types/tests/dnd/dice-roll.test.ts app/src/lib/engine/dnd/dice-roll.test.ts
··· 1 1 import { describe, expect, test } from 'vitest' 2 - import { zD4Roll, zDiceRoll } from '../../src/dnd/dice-roll' 2 + import { zD4Roll, zDiceRoll } from './dice-roll' 3 3 4 4 describe('zD4Roll', () => { 5 5 describe('safeParse()', () => {
+3 -3
packages/types/tests/dnd/spell-component.test.ts app/src/lib/engine/dnd/spell-component.test.ts
··· 1 1 import { describe, expect, test } from 'vitest' 2 2 import { 3 + type SpellComponentName, 4 + type SpellComponentAbbr, 3 5 getSpellComponentName, 4 - SpellComponentAbbr, 5 6 zSpellComponentAbbr, 6 - SpellComponentName, 7 - } from '../../src/dnd/spell-component' 7 + } from './spell-component' 8 8 9 9 describe('SpellComponentLetterSchema', () => { 10 10 describe('safeParse()', () => {
+1 -1
packages/types/tests/dnd/spell-duration.test.ts app/src/lib/engine/dnd/spell-duration.test.ts
··· 5 5 zTimeUnit, 6 6 zTimeSpan, 7 7 zSpellDuration, 8 - } from '../../src/dnd/spell-duration' 8 + } from './spell-duration' 9 9 10 10 describe('zConcentration', () => { 11 11 describe('safeParse()', () => {
+1 -6
packages/types/tests/dnd/spell-range.test.ts app/src/lib/engine/dnd/spell-range.test.ts
··· 1 1 import { describe, expect, test } from 'vitest' 2 - import { 3 - zSpellDistanceLiteral, 4 - zSpellRange, 5 - zSpellSelf, 6 - zSpellTouch, 7 - } from '../../src/dnd/spell-range' 2 + import { zSpellDistanceLiteral, zSpellRange, zSpellSelf, zSpellTouch } from './spell-range' 8 3 9 4 describe('SpellTouchSchema', () => { 10 5 describe('safeParse()', () => {
+1 -1
packages/types/tests/dnd/spell-school.test.ts app/src/lib/engine/dnd/spell-school.test.ts
··· 1 1 import { describe, expect, test } from 'vitest' 2 - import { zSpellSchool } from '../../src/dnd/spell-school' 2 + import { zSpellSchool } from './spell-school' 3 3 4 4 describe('zSpellSchool', () => { 5 5 describe('safeParse()', () => {
-57
packages/types/tests/hsr/element.test.ts
··· 1 - import { describe, expect, test } from 'vitest' 2 - import { 3 - Element, 4 - ElementColor, 5 - getElementName, 6 - getElementColor, 7 - zElement, 8 - } from '../../src/hsr/element' 9 - 10 - describe('zElement', () => { 11 - describe('safeParse()', () => { 12 - test.for([ 13 - ['fire'], 14 - ['ice'], 15 - ['imaginary'], 16 - ['lightning'], 17 - ['physical'], 18 - ['quantum'], 19 - ['wind'], 20 - ])("is ok: '%s'", ([a]) => { 21 - expect(zElement.safeParse(a)).toMatchObject({ 22 - data: a, 23 - success: true, 24 - }) 25 - }) 26 - }) 27 - }) 28 - 29 - describe('Lookup functions', () => { 30 - describe('getElementName()', () => { 31 - test.for([ 32 - ['fire', 'Fire'], 33 - ['ice', 'Ice'], 34 - ['imaginary', 'Imaginary'], 35 - ['lightning', 'Lightning'], 36 - ['physical', 'Physical'], 37 - ['quantum', 'Quantum'], 38 - ['wind', 'Wind'], 39 - ] as [Element, string][])("is ok: '%s'", ([element, expectedName]) => { 40 - expect(getElementName(element)).toEqual(expectedName) 41 - }) 42 - }) 43 - 44 - describe('getElementColor()', () => { 45 - test.for([ 46 - ['fire', 'red'], 47 - ['ice', 'cyan'], 48 - ['imaginary', 'yellow'], 49 - ['lightning', 'purple'], 50 - ['physical', 'white'], 51 - ['quantum', 'indigo'], 52 - ['wind', 'green'], 53 - ] as [Element, ElementColor][])("is ok: '%s'", ([element, expectedName]) => { 54 - expect(getElementColor(element)).toEqual(expectedName) 55 - }) 56 - }) 57 - })
-87
packages/types/tests/hsr/mechanic.test.ts
··· 1 - import { describe, expect, test } from 'vitest' 2 - import { 3 - getMechanicName, 4 - Mechanic, 5 - zDefenseMechanic, 6 - zMechanic, 7 - zOffenseMechanic, 8 - } from '../../src/hsr/mechanic' 9 - 10 - describe('zOffenseMechanic', () => { 11 - describe('safeParse', () => { 12 - test.for([['single-target'], ['aoe'], ['bounce'], ['blast'], ['impair']])( 13 - "is ok: '%s'", 14 - ([s]) => { 15 - expect(zOffenseMechanic.safeParse(s)).toMatchObject({ 16 - data: s, 17 - success: true, 18 - }) 19 - }, 20 - ) 21 - 22 - test.for([['support'], ['restore'], ['enhance'], ['defense']])("errors: '%s'", ([s]) => { 23 - expect(zOffenseMechanic.safeParse(s)).toMatchObject({ 24 - success: false, 25 - }) 26 - }) 27 - }) 28 - }) 29 - 30 - describe('DefenseMechanicSchema', () => { 31 - describe('safeParse', () => { 32 - test.for([['support'], ['restore'], ['enhance'], ['defense']])("is ok: '%s'", ([s]) => { 33 - expect(zDefenseMechanic.safeParse(s)).toMatchObject({ 34 - data: s, 35 - success: true, 36 - }) 37 - }) 38 - 39 - test.for([['single-target'], ['aoe'], ['bounce'], ['blast'], ['impair']])( 40 - "errors: '%s'", 41 - ([s]) => { 42 - expect(zDefenseMechanic.safeParse(s)).toMatchObject({ 43 - success: false, 44 - }) 45 - }, 46 - ) 47 - }) 48 - }) 49 - 50 - describe('zMechanic', () => { 51 - describe('safeParse', () => { 52 - test.for([ 53 - ['single-target'], 54 - ['aoe'], 55 - ['bounce'], 56 - ['blast'], 57 - ['impair'], 58 - ['support'], 59 - ['restore'], 60 - ['enhance'], 61 - ['defense'], 62 - ])("is ok: '%s'", ([s]) => { 63 - expect(zMechanic.safeParse(s)).toMatchObject({ 64 - data: s, 65 - success: true, 66 - }) 67 - }) 68 - }) 69 - }) 70 - 71 - describe('Lookup functions', () => { 72 - describe('getMechanicName()', () => { 73 - test.for([ 74 - ['single-target', 'Single Target'], 75 - ['aoe', 'AoE'], 76 - ['bounce', 'Bounce'], 77 - ['blast', 'Blast'], 78 - ['impair', 'Impair'], 79 - ['support', 'Support'], 80 - ['restore', 'Restore'], 81 - ['enhance', 'Enhance'], 82 - ['defense', 'Defense'], 83 - ] as [Mechanic, string][])("is ok: '%s'", ([mechanic, expectedName]) => { 84 - expect(getMechanicName(mechanic)).toEqual(expectedName) 85 - }) 86 - }) 87 - })
-74
packages/types/tests/hsr/path.test.ts
··· 1 - import { describe, expect, test } from 'vitest' 2 - import { zNonPlayablePath, zPath, zPlayablePath } from '../../src/hsr/path' 3 - 4 - describe('zPath', () => { 5 - describe('safeParse()', () => { 6 - test.for([ 7 - ['Abundance'], 8 - ['Beauty'], 9 - ['Destruction'], 10 - ['Elation'], 11 - ['Enigmata'], 12 - ['Equilibrium'], 13 - ['Erudition'], 14 - ['Finality'], 15 - ['Harmony'], 16 - ['Hunt'], 17 - ['Nihility'], 18 - ['Order'], 19 - ['Permanence'], 20 - ['Preservation'], 21 - ['Propagation'], 22 - ['Remembrance'], 23 - ['Trailblaze'], 24 - ['Voracity'], 25 - ])("is ok: '%s'", ([s]) => { 26 - expect(zPath.safeParse(s)).toMatchObject({ 27 - data: s, 28 - success: true, 29 - }) 30 - }) 31 - }) 32 - }) 33 - 34 - describe('zNonPlayablePath', () => { 35 - describe('safeParse()', () => { 36 - test.for([ 37 - ['Beauty'], 38 - ['Elation'], 39 - ['Enigmata'], 40 - ['Equilibrium'], 41 - ['Finality'], 42 - ['Order'], 43 - ['Permanence'], 44 - ['Propagation'], 45 - ['Trailblaze'], 46 - ['Voracity'], 47 - ])("is ok: '%s'", ([s]) => { 48 - expect(zNonPlayablePath.safeParse(s)).toMatchObject({ 49 - data: s, 50 - success: true, 51 - }) 52 - }) 53 - }) 54 - }) 55 - 56 - describe('zPlayablePath', () => { 57 - describe('safeParse()', () => { 58 - test.for([ 59 - ['Abundance'], 60 - ['Destruction'], 61 - ['Erudition'], 62 - ['Harmony'], 63 - ['Hunt'], 64 - ['Nihility'], 65 - ['Preservation'], 66 - ['Remembrance'], 67 - ])("is ok: '%s'", ([s]) => { 68 - expect(zPlayablePath.safeParse(s)).toMatchObject({ 69 - data: s, 70 - success: true, 71 - }) 72 - }) 73 - }) 74 - })
-40
packages/types/tests/obj.test.ts
··· 1 - import { describe, expect, test } from 'vitest' 2 - import { keysOf, valuesOf } from '../src/obj' 3 - 4 - describe('keysOf()', () => { 5 - test('is ok with object', () => { 6 - const input = { 7 - foo: 'Foo', 8 - bar: 'Bar', 9 - } as const 10 - const actual = keysOf(input) 11 - 12 - expect(actual).toEqual(['foo', 'bar']) 13 - }) 14 - 15 - test('is ok with empty object', () => { 16 - const input = {} as const 17 - const actual = keysOf(input) 18 - 19 - expect(actual).toEqual([]) 20 - }) 21 - }) 22 - 23 - describe('valuesOf()', () => { 24 - test('is ok with object', () => { 25 - const input = { 26 - foo: 'Foo', 27 - bar: 'Bar', 28 - } as const 29 - const actual = valuesOf(input) 30 - 31 - expect(actual).toEqual(['Foo', 'Bar']) 32 - }) 33 - 34 - test('is ok with empty object', () => { 35 - const input = {} as const 36 - const actual = valuesOf(input) 37 - 38 - expect(actual).toEqual([]) 39 - }) 40 - })
-9
packages/types/tsdown.config.ts
··· 1 - import { defineConfig } from 'tsdown' 2 - 3 - export default defineConfig({ 4 - entry: ['src/dnd/index.ts', 'src/hsr/index.ts', 'src/zod.ts'], 5 - minify: true, 6 - dts: true, 7 - platform: 'neutral', 8 - publint: true, 9 - })
-7
packages/types/vite.config.ts
··· 1 - import { defineProject } from 'vitest/config' 2 - 3 - export default defineProject({ 4 - test: { 5 - includeSource: ['src/**/*.{js,ts}'], 6 - }, 7 - })
+28 -130
pnpm-lock.yaml
··· 19 19 '@fontsource-variable/suse-mono': 20 20 specifier: ^5.2.1 21 21 version: 5.2.1 22 + '@nc/whatwg-infra': 23 + specifier: jsr:^1.1.0 24 + version: 1.1.0 22 25 '@types/pg': 23 26 specifier: ^8.20.0 24 27 version: 8.20.0 ··· 43 46 lorem-ipsum: 44 47 specifier: ^2.0.8 45 48 version: 2.0.8 49 + nanoid: 50 + specifier: ^5.1.9 51 + version: 5.1.9 46 52 pg: 47 53 specifier: ^8.20.0 48 54 version: 8.20.0 ··· 52 58 ts-dedent: 53 59 specifier: ^2.2.0 54 60 version: 2.2.0 61 + type-fest: 62 + specifier: ^5.6.0 63 + version: 5.6.0 55 64 zod: 56 65 specifier: ^4.3.6 57 66 version: 4.3.6 ··· 71 80 sonda: 72 81 specifier: ^0.11.1 73 82 version: 0.11.1 74 - type-fest: 75 - specifier: ^5.4.4 76 - version: 5.5.0 77 83 typescript: 78 84 specifier: ^5.9.3 79 85 version: 5.9.3 ··· 112 118 '@lucide/svelte': 113 119 specifier: ^1.8.0 114 120 version: 1.8.0 115 - '@sveltejs/adapter-auto': 116 - specifier: ^7.0.1 117 - version: 7.0.1 118 121 '@sveltejs/adapter-cloudflare': 119 122 specifier: ^7.2.8 120 123 version: 7.2.8 121 124 '@sveltejs/kit': 122 125 specifier: ^2.57.1 123 126 version: 2.57.1 124 - '@sveltejs/package': 125 - specifier: ^2.5.7 126 - version: 2.5.7 127 127 '@sveltejs/vite-plugin-svelte': 128 128 specifier: ^7.0.0 129 129 version: 7.0.0 ··· 314 314 '@lucide/svelte': 315 315 specifier: catalog:svelte 316 316 version: 1.8.0(svelte@5.55.4) 317 - '@starlight/icons': 318 - specifier: link:../packages/icons 319 - version: link:../packages/icons 320 - '@starlight/tokenizer': 321 - specifier: link:../packages/tokenizer 322 - version: link:../packages/tokenizer 323 - '@starlight/types': 324 - specifier: link:../packages/types 325 - version: link:../packages/types 317 + '@nc/whatwg-infra': 318 + specifier: catalog:app 319 + version: '@jsr/nc__whatwg-infra@1.1.0' 326 320 better-auth: 327 321 specifier: catalog:app 328 322 version: 1.6.5(@cloudflare/workers-types@4.20260417.1)(@opentelemetry/api@1.9.1)(@sveltejs/kit@2.57.1)(drizzle-kit@0.31.10)(drizzle-orm@0.45.2)(pg@8.20.0)(react-dom@19.2.5)(react@19.2.5)(svelte@5.55.4)(vitest@4.1.4) ··· 344 338 mode-watcher: 345 339 specifier: catalog:svelte 346 340 version: 1.1.0(svelte@5.55.4) 341 + nanoid: 342 + specifier: catalog:app 343 + version: 5.1.9 347 344 pg: 348 345 specifier: catalog:app 349 346 version: 8.20.0 ··· 371 368 tw-animate-css: 372 369 specifier: catalog:tailwind 373 370 version: 1.4.0 371 + type-fest: 372 + specifier: catalog:app 373 + version: 5.6.0 374 374 zod: 375 375 specifier: catalog:app 376 376 version: 4.3.6 ··· 378 378 '@playwright/test': 379 379 specifier: catalog:voidzero 380 380 version: 1.59.1 381 - '@starlight/storybook-utils': 382 - specifier: link:../packages/storybook-utils 383 - version: link:../packages/storybook-utils 384 381 '@sveltejs/adapter-cloudflare': 385 382 specifier: catalog:svelte 386 383 version: 7.2.8(@sveltejs/kit@2.57.1)(wrangler@4.67.0) ··· 436 433 specifier: catalog:svelte 437 434 version: 2.1.1(svelte@5.55.4)(vitest@4.1.4) 438 435 439 - packages/icons: 440 - dependencies: 441 - '@lucide/svelte': 442 - specifier: ^1.x 443 - version: 1.8.0(svelte@5.55.4) 444 - '@starlight/types': 445 - specifier: workspace:../types 446 - version: link:../types 447 - svelte: 448 - specifier: catalog:svelte 449 - version: 5.55.4 450 - devDependencies: 451 - '@starlight/storybook-utils': 452 - specifier: link:../storybook-utils 453 - version: link:../storybook-utils 454 - '@sveltejs/adapter-auto': 455 - specifier: catalog:svelte 456 - version: 7.0.1(@sveltejs/kit@2.57.1) 457 - '@sveltejs/kit': 458 - specifier: catalog:svelte 459 - version: 2.57.1(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.0.0)(svelte@5.55.4)(typescript@5.9.3)(vite@8.0.8) 460 - '@sveltejs/package': 461 - specifier: catalog:svelte 462 - version: 2.5.7(svelte@5.55.4)(typescript@5.9.3) 463 - '@sveltejs/vite-plugin-svelte': 464 - specifier: catalog:svelte 465 - version: 7.0.0(svelte@5.55.4)(vite@8.0.8) 466 - '@tailwindcss/vite': 467 - specifier: catalog:tailwind 468 - version: 4.2.2(vite@8.0.8) 469 - svelte-check: 470 - specifier: catalog:svelte 471 - version: 4.4.6(picomatch@4.0.4)(svelte@5.55.4)(typescript@5.9.3) 472 - tailwindcss: 473 - specifier: catalog:tailwind 474 - version: 4.2.2 475 - typescript: 476 - specifier: catalog:dev 477 - version: 5.9.3 478 - 479 - packages/storybook-utils: 480 - dependencies: 481 - '@starlight/types': 482 - specifier: workspace:../types 483 - version: link:../types 484 - storybook: 485 - specifier: 10.x 486 - version: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5)(react@19.2.5) 487 - devDependencies: 488 - typescript: 489 - specifier: catalog:dev 490 - version: 5.9.3 491 - 492 - packages/tokenizer: 493 - dependencies: 494 - '@nc/whatwg-infra': 495 - specifier: npm:@jsr/nc__whatwg-infra@^1.1.0 496 - version: '@jsr/nc__whatwg-infra@1.1.0' 497 - '@starlight/types': 498 - specifier: workspace:../types 499 - version: link:../types 500 - devDependencies: 501 - typescript: 502 - specifier: catalog:dev 503 - version: 5.9.3 504 - 505 - packages/types: 506 - dependencies: 507 - type-fest: 508 - specifier: catalog:dev 509 - version: 5.5.0 510 - zod: 511 - specifier: catalog:app 512 - version: 4.3.6 513 - devDependencies: 514 - typescript: 515 - specifier: catalog:dev 516 - version: 5.9.3 517 - 518 436 packages: 519 437 520 438 '@adobe/css-tools@4.4.4': ··· 2411 2329 peerDependencies: 2412 2330 acorn: ^8.9.0 2413 2331 2414 - '@sveltejs/adapter-auto@7.0.1': 2415 - resolution: {integrity: sha512-dvuPm1E7M9NI/+canIQ6KKQDU2AkEefEZ2Dp7cY6uKoPq9Z/PhOXABe526UdW2mN986gjVkuSLkOYIBnS/M2LQ==} 2416 - peerDependencies: 2417 - '@sveltejs/kit': ^2.0.0 2418 - 2419 2332 '@sveltejs/adapter-cloudflare@7.2.8': 2420 2333 resolution: {integrity: sha512-bIdhY/Fi4AQmqiBdQVKnafH1h9Gw+xbCvHyUu4EouC8rJOU02zwhi14k/FDhQ0mJF1iblIu3m8UNQ8GpGIvIOQ==} 2421 2334 peerDependencies: ··· 2437 2350 optional: true 2438 2351 typescript: 2439 2352 optional: true 2440 - 2441 - '@sveltejs/package@2.5.7': 2442 - resolution: {integrity: sha512-qqD9xa9H7TDiGFrF6rz7AirOR8k15qDK/9i4MIE8te4vWsv5GEogPks61rrZcLy+yWph+aI6pIj2MdoK3YI8AQ==} 2443 - engines: {node: ^16.14 || >=18} 2444 - hasBin: true 2445 - peerDependencies: 2446 - svelte: ^3.44.0 || ^4.0.0 || ^5.0.0-next.1 2447 2353 2448 2354 '@sveltejs/vite-plugin-svelte@7.0.0': 2449 2355 resolution: {integrity: sha512-ILXmxC7HAsnkK2eslgPetrqqW1BKSL7LktsFgqzNj83MaivMGZzluWq32m25j2mDOjmSKX7GGWahePhuEs7P/g==} ··· 3727 3633 engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 3728 3634 hasBin: true 3729 3635 3636 + nanoid@5.1.9: 3637 + resolution: {integrity: sha512-ZUvP7KeBLe3OZ1ypw6dI/TzYJuvHP77IM4Ry73waSQTLn8/g8rpdjfyVAh7t1/+FjBtG4lCP42MEbDxOsRpBMw==} 3638 + engines: {node: ^18 || >=20} 3639 + hasBin: true 3640 + 3730 3641 nanostores@1.2.0: 3731 3642 resolution: {integrity: sha512-F0wCzbsH80G7XXo0Jd9/AVQC7ouWY6idUCTnMwW5t/Rv9W8qmO6endavDwg7TNp5GbugwSukFMVZqzPSrSMndg==} 3732 3643 engines: {node: ^20.0.0 || >=22.0.0} ··· 4417 4328 resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} 4418 4329 engines: {node: '>=12.20'} 4419 4330 4420 - type-fest@5.5.0: 4421 - resolution: {integrity: sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==} 4331 + type-fest@5.6.0: 4332 + resolution: {integrity: sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==} 4422 4333 engines: {node: '>=20'} 4423 4334 4424 4335 typebox@1.1.26: ··· 6153 6064 dependencies: 6154 6065 acorn: 8.16.0 6155 6066 6156 - '@sveltejs/adapter-auto@7.0.1(@sveltejs/kit@2.57.1)': 6157 - dependencies: 6158 - '@sveltejs/kit': 2.57.1(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.0.0)(svelte@5.55.4)(typescript@5.9.3)(vite@8.0.8) 6159 - 6160 6067 '@sveltejs/adapter-cloudflare@7.2.8(@sveltejs/kit@2.57.1)(wrangler@4.67.0)': 6161 6068 dependencies: 6162 6069 '@cloudflare/workers-types': 4.20260417.1 ··· 6184 6091 optionalDependencies: 6185 6092 '@opentelemetry/api': 1.9.1 6186 6093 typescript: 5.9.3 6187 - 6188 - '@sveltejs/package@2.5.7(svelte@5.55.4)(typescript@5.9.3)': 6189 - dependencies: 6190 - chokidar: 5.0.0 6191 - kleur: 4.1.5 6192 - sade: 1.8.1 6193 - semver: 7.7.4 6194 - svelte: 5.55.4 6195 - svelte2tsx: 0.7.53(svelte@5.55.4)(typescript@5.9.3) 6196 - transitivePeerDependencies: 6197 - - typescript 6198 6094 6199 6095 '@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.4)(vite@8.0.8)': 6200 6096 dependencies: ··· 7421 7317 7422 7318 nanoid@3.3.11: {} 7423 7319 7320 + nanoid@5.1.9: {} 7321 + 7424 7322 nanostores@1.2.0: {} 7425 7323 7426 7324 natural-compare@1.4.0: {} ··· 8211 8109 8212 8110 type-fest@2.19.0: {} 8213 8111 8214 - type-fest@5.5.0: 8112 + type-fest@5.6.0: 8215 8113 dependencies: 8216 8114 tagged-tag: 1.0.0 8217 8115
+7 -5
pnpm-workspace.yaml
··· 1 1 packages: 2 - - packages/** 3 2 - app 4 3 5 4 allowBuilds: ··· 15 14 '@fontsource-variable/fraunces': ^5.2.9 16 15 '@fontsource-variable/suse': ^5.2.9 17 16 '@fontsource-variable/suse-mono': ^5.2.1 17 + '@nc/whatwg-infra': jsr:^1.1.0 18 18 '@types/pg': ^8.20.0 19 19 auth: ^1.5.6 20 20 better-auth: ^1.5.6 ··· 23 23 drizzle-orm: ^0.45.2 24 24 drizzle-zod: ^0.8.3 25 25 lorem-ipsum: ^2.0.8 26 + nanoid: ^5.1.9 26 27 pg: ^8.20.0 27 28 resend: ^6.9.4 28 29 ts-dedent: ^2.2.0 30 + type-fest: ^5.6.0 29 31 zod: ^4.3.6 30 32 dev: 31 33 '@types/node': ^25.6.0 ··· 85 87 vitest: ^4.1.4 86 88 87 89 dedupePeers: true 88 - 89 - linkWorkspacePackages: deep 90 - onlyBuiltDependencies: 91 - - esbuild 92 90 ignoredOptionalDependencies: 93 91 - '@prisma/client' 94 92 - 'arktype' ··· 99 97 - 'yup' 100 98 - 'mysql2' 101 99 - 'prisma' 100 + 101 + linkWorkspacePackages: deep 102 + onlyBuiltDependencies: 103 + - esbuild 102 104 trustPolicy: no-downgrade 103 105 trustPolicyExclude: 104 106 - 'chokidar@4.0.3'