From 3ec7d65225a72e2204b72a71117609c39910360d Mon Sep 17 00:00:00 2001 From: rsek <5354757+rsek@users.noreply.github.com> Date: Mon, 10 Apr 2023 20:59:23 -0700 Subject: [PATCH 1/2] diverge from standard b/c we use namespaces often --- .eslintrc.cjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index a8779de55..b56a2b5f9 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -22,6 +22,8 @@ module.exports = { }, plugins: ['@typescript-eslint'], rules: { + // LoFD, the target of most of our augmentations, uses namespaces. More generally, namespaces are necessary to augment static class members. + '@typescript-eslint/no-namespace': 'off', '@typescript-eslint/no-unused-vars': [1, { argsIgnorePattern: '^_' }], '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/ban-ts-comment': 'off', From 827f6b165b228fe1049b9dfac1dd03963e186c2b Mon Sep 17 00:00:00 2001 From: rsek <5354757+rsek@users.noreply.github.com> Date: Mon, 10 Apr 2023 21:00:34 -0700 Subject: [PATCH 2/2] initial pass at simple type migration --- src/index.ts | 6 ++--- src/module/chat/cards.ts | 4 ++-- src/module/dataforged/import.ts | 2 +- src/module/features/custommoves.ts | 2 +- src/module/item/item.ts | 24 ++++++++++++++++++- src/module/item/itemtypes.ts | 4 ++-- src/module/rolls/ironsworn-roll-message.ts | 4 ++-- src/module/rolls/preroll-dialog.ts | 4 ++-- .../vue/components/with-rolllisteners.vue | 2 +- system/template.json | 4 ++-- 10 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/index.ts b/src/index.ts index bff0beb80..36c788e57 100644 --- a/src/index.ts +++ b/src/index.ts @@ -133,7 +133,7 @@ Hooks.once('init', async () => { }) Items.registerSheet('ironsworn', SFMoveSheet, { - types: ['sfmove'], + types: ['move'], label: 'IRONSWORN.ITEM.TypeMove' }) @@ -175,7 +175,7 @@ Hooks.once('init', async () => { asset: 'IRONSWORN.ITEM.TypeAsset', progress: 'IRONSWORN.ITEM.TypeProgressTrack', bondset: 'IRONSWORN.ITEM.TypeBondset', - sfmove: 'IRONSWORN.ITEM.TypeMove', + move: 'IRONSWORN.ITEM.TypeMove', 'delve-domain': 'IRONSWORN.ITEM.TypeDelveDomain', 'delve-theme': 'IRONSWORN.ITEM.TypeDelveTheme' }) @@ -183,7 +183,7 @@ Hooks.once('init', async () => { asset: 'fa-solid fa-cards-blank', progress: 'fa-solid fa-asterisk', bondset: 'fa-solid fa-handshake', - sfmove: 'icon isicon-d10-tilt', + move: 'icon isicon-d10-tilt', // FIXME ideally, these would be distinct from assets, but all three card types are abstract enough than an icon is tricky 'delve-domain': 'fa-duotone fa-cards-blank', 'delve-theme': 'fa-duotone fa-cards-blank' diff --git a/src/module/chat/cards.ts b/src/module/chat/cards.ts index 064780623..fd59d6b38 100644 --- a/src/module/chat/cards.ts +++ b/src/module/chat/cards.ts @@ -26,7 +26,7 @@ export class IronswornChatCard { const fPack = game.packs.get(pack) const fItem = fPack?.get(id) as IronswornItem - if (fItem?.type !== 'sfmove') return [] + if (fItem?.type !== 'move') return [] const system = fItem.system as SFMoveDataPropertiesData const oracleIds = system.Oracles ?? [] @@ -98,7 +98,7 @@ export class IronswornChatCard { const { uuid } = ev.currentTarget.dataset const item = (await fromUuid(uuid)) as IronswornItem - if (item?.type !== 'sfmove') { + if (item?.type !== 'move') { console.log('falling through') return // (TextEditor as any)._onClickContentLink(ev) } diff --git a/src/module/dataforged/import.ts b/src/module/dataforged/import.ts index 037683c0b..46249ad61 100644 --- a/src/module/dataforged/import.ts +++ b/src/module/dataforged/import.ts @@ -135,7 +135,7 @@ function movesForCategories( console.log(move.Name, move.$id) movesToCreate.push({ _id: hashLookup(cleanMove.dfid), - type: 'sfmove', + type: 'move', name: move.Name, img: 'icons/dice/d10black.svg', system: cleanMove diff --git a/src/module/features/custommoves.ts b/src/module/features/custommoves.ts index 2147d84f5..f5c067a4f 100644 --- a/src/module/features/custommoves.ts +++ b/src/module/features/custommoves.ts @@ -130,7 +130,7 @@ async function augmentWithFolderContents(categories: MoveCategory[]) { const customMoves = [] as Move[] for (const moveItem of folder.contents) { - if (moveItem.documentName !== 'Item' || moveItem.type !== 'sfmove') continue + if (moveItem.documentName !== 'Item' || moveItem.type !== 'move') continue customMoves.push({ color, displayName: moveItem.name ?? '(move)', diff --git a/src/module/item/item.ts b/src/module/item/item.ts index c24920983..3b2a3a895 100644 --- a/src/module/item/item.ts +++ b/src/module/item/item.ts @@ -12,6 +12,19 @@ import type { SFMoveDataPropertiesData } from './itemtypes' +declare global { + namespace Item { + /** + * Migrate candidate source data for this DataModel which may require initial cleaning or transformations. + * @param source - The candidate source data from which the model will be constructed + * @returns Migrated source data, if necessary + */ + function migrateData( + source: Record + ): Record + } +} + /** * Extend the base Item entity * @extends {Item} @@ -21,6 +34,15 @@ export class IronswornItem extends Item { declare system: typeof this.data.data declare sort: typeof this.data.sort + static override migrateData(source: Record) { + // run tihs first so we don't have to worry about e.g. data => system + source = super.migrateData(source) + + /** Migration 6: rename type since it's the only kind of move we use now */ + if (source.type === 'sfmove') source.type = 'move' + return source + } + protected override _onCreate( data: this['data']['_source'], options: DocumentModificationOptions, @@ -126,7 +148,7 @@ export class IronswornItem extends Item { * Move methods */ isProgressMove(): boolean | undefined { - if (this.type !== 'sfmove') return + if (this.type !== 'move') return const sfMoveSystem = this.system as SFMoveDataPropertiesData return sfMoveSystem.Trigger.Options?.some( diff --git a/src/module/item/itemtypes.ts b/src/module/item/itemtypes.ts index 30295e7db..fd2fbe64d 100644 --- a/src/module/item/itemtypes.ts +++ b/src/module/item/itemtypes.ts @@ -183,11 +183,11 @@ export interface SFMoveDataPropertiesData extends IMove { } export interface SFMoveDataSource { - type: 'sfmove' + type: 'move' data: SFMoveDataPropertiesData } export interface SFMoveDataProperties { - type: 'sfmove' + type: 'move' data: SFMoveDataPropertiesData } diff --git a/src/module/rolls/ironsworn-roll-message.ts b/src/module/rolls/ironsworn-roll-message.ts index 886baf852..dac42e6c0 100644 --- a/src/module/rolls/ironsworn-roll-message.ts +++ b/src/module/rolls/ironsworn-roll-message.ts @@ -260,7 +260,7 @@ export class IronswornRollMessage { this.roll.postRollOptions.replacedOutcome?.source } const move = await this.roll.moveItem - if (move?.type !== 'sfmove') return ret + if (move?.type !== 'move') return ret const key = DfRollOutcome[theOutcome] const moveSystem = move.system as SFMoveDataPropertiesData @@ -319,7 +319,7 @@ export class IronswornRollMessage { private async oraclesData(): Promise { const move = await this.roll.moveItem - if (move?.type !== 'sfmove') return {} + if (move?.type !== 'move') return {} const system = move.system as SFMoveDataPropertiesData const dfids = system.Oracles ?? [] diff --git a/src/module/rolls/preroll-dialog.ts b/src/module/rolls/preroll-dialog.ts index 3a309ffe9..15251587c 100644 --- a/src/module/rolls/preroll-dialog.ts +++ b/src/module/rolls/preroll-dialog.ts @@ -56,7 +56,7 @@ function rollableOptions(trigger: IMoveTrigger) { } export function moveHasRollableOptions(move: IronswornItem) { - if (move.type !== 'sfmove') return false + if (move.type !== 'move') return false const data = move.system as SFMoveDataPropertiesData const options = rollableOptions(data.Trigger) return options.length > 0 @@ -285,7 +285,7 @@ export class IronswornPrerollDialog extends Dialog< } static async showForMove(move: IronswornItem, opts?: showForMoveOpts) { - if (move.type !== 'sfmove') { + if (move.type !== 'move') { throw new Error('this only works with SF moves') } diff --git a/src/module/vue/components/with-rolllisteners.vue b/src/module/vue/components/with-rolllisteners.vue index ace853b52..8e9eba97a 100644 --- a/src/module/vue/components/with-rolllisteners.vue +++ b/src/module/vue/components/with-rolllisteners.vue @@ -39,7 +39,7 @@ async function click(ev: JQuery.ClickEvent) { const { uuid, dfid } = ev.currentTarget.dataset if (uuid) { const gameItem = (await fromUuid(uuid)) as IronswornItem | IronswornActor - if (gameItem?.type === 'sfmove') { + if (gameItem?.type === 'move') { $emit('moveclick', gameItem) return !!$attrs['onMoveclick'] } diff --git a/system/template.json b/system/template.json index 9b1d9deed..8c5700bbd 100644 --- a/system/template.json +++ b/system/template.json @@ -163,7 +163,7 @@ "asset", "progress", "bondset", - "sfmove", + "move", "delve-theme", "delve-domain" ], @@ -234,7 +234,7 @@ ], "conditions": [] }, - "sfmove": { + "move": { "dfid": "", "Category": "", "Progress Move": false,