From ecc14c07070584acc2e01777552f3fc6de2cd349 Mon Sep 17 00:00:00 2001 From: kseungyong Date: Mon, 18 May 2026 17:31:39 +0900 Subject: [PATCH] fix: restore production build by re-adding missing exports and updating positional-to-object API call sites Resolves #782. - Add isShortcutKey type guard to actions/keybinding.ts - Add isActionWithOptionalArgs runtime guard to actions/definitions.ts - Migrate IndexedDBAdapter constructor + .set() calls to object args in storage migrations - Migrate DefinitionRegistry.register() call to object args in stickers/providers --- apps/web/src/actions/definitions.ts | 16 ++++++++++ apps/web/src/actions/keybinding.ts | 19 ++++++++++++ .../src/services/storage/migrations/runner.ts | 12 ++++---- .../services/storage/migrations/v1-to-v2.ts | 30 +++++++++---------- apps/web/src/stickers/providers/index.ts | 2 +- 5 files changed, 57 insertions(+), 22 deletions(-) diff --git a/apps/web/src/actions/definitions.ts b/apps/web/src/actions/definitions.ts index 986510ec..f698dd0a 100644 --- a/apps/web/src/actions/definitions.ts +++ b/apps/web/src/actions/definitions.ts @@ -208,3 +208,19 @@ export function getDefaultShortcuts(): Map< return shortcuts; } + +const ACTION_SET: ReadonlySet = new Set(Object.keys(ACTIONS)); +// IMPORTANT: This Set must stay in sync with entries in `TActionArgsMap` (./types.ts) +// whose value type does not include `undefined`. If you add a new required-args action +// to TActionArgsMap, add its ID here too — otherwise `isActionWithOptionalArgs` will +// return true at runtime for an action that actually requires arguments. +const REQUIRED_ARGS_ACTIONS: ReadonlySet = new Set([ + "remove-media-asset", + "remove-media-assets", +]); + +export function isActionWithOptionalArgs( + value: string, +): value is TActionWithOptionalArgs { + return ACTION_SET.has(value) && !REQUIRED_ARGS_ACTIONS.has(value); +} diff --git a/apps/web/src/actions/keybinding.ts b/apps/web/src/actions/keybinding.ts index aeec2fd6..28516e93 100644 --- a/apps/web/src/actions/keybinding.ts +++ b/apps/web/src/actions/keybinding.ts @@ -38,6 +38,25 @@ export type SingleCharacterShortcutKey = `${Key}`; export type ShortcutKey = ModifierBasedShortcutKey | SingleCharacterShortcutKey; +const MODIFIER_SET: ReadonlySet = new Set([ + "ctrl", + "alt", + "shift", + "ctrl+shift", + "alt+shift", + "ctrl+alt", + "ctrl+alt+shift", +]); + +export function isShortcutKey(value: string): value is ShortcutKey { + if (isKey(value)) return true; + const lastPlus = value.lastIndexOf("+"); + if (lastPlus === -1) return false; + return ( + MODIFIER_SET.has(value.slice(0, lastPlus)) && isKey(value.slice(lastPlus + 1)) + ); +} + export type KeybindingConfig = { [key in ShortcutKey]?: TActionWithOptionalArgs; }; diff --git a/apps/web/src/services/storage/migrations/runner.ts b/apps/web/src/services/storage/migrations/runner.ts index eed8071f..162db8ca 100644 --- a/apps/web/src/services/storage/migrations/runner.ts +++ b/apps/web/src/services/storage/migrations/runner.ts @@ -38,11 +38,11 @@ export async function runStorageMigrations({ hasCleanedUpMetaDb = true; } - const projectsAdapter = new IndexedDBAdapter( - "video-editor-projects", - "projects", - 1, - ); + const projectsAdapter = new IndexedDBAdapter({ + dbName: "video-editor-projects", + storeName: "projects", + version: 1, + }); const projects = await projectsAdapter.getAll(); @@ -95,7 +95,7 @@ export async function runStorageMigrations({ break; } - await projectsAdapter.set(projectId, result.project); + await projectsAdapter.set({ key: projectId, value: result.project }); migratedCount++; currentVersion = migration.to; projectRecord = result.project; diff --git a/apps/web/src/services/storage/migrations/v1-to-v2.ts b/apps/web/src/services/storage/migrations/v1-to-v2.ts index a87b4a86..601e4797 100644 --- a/apps/web/src/services/storage/migrations/v1-to-v2.ts +++ b/apps/web/src/services/storage/migrations/v1-to-v2.ts @@ -121,20 +121,20 @@ async function loadLegacyTracksForScene({ const sceneDbName = `video-editor-timelines-${projectId}-${sceneId}`; const projectDbName = `video-editor-timelines-${projectId}`; - const adapter = new IndexedDBAdapter( - sceneDbName, - "timeline", - 1, - ); + const adapter = new IndexedDBAdapter({ + dbName: sceneDbName, + storeName: "timeline", + version: 1, + }); let data = await adapter.get("timeline"); if (!data && isMain) { - const projectAdapter = new IndexedDBAdapter( - projectDbName, - "timeline", - 1, - ); + const projectAdapter = new IndexedDBAdapter({ + dbName: projectDbName, + storeName: "timeline", + version: 1, + }); data = await projectAdapter.get("timeline"); } @@ -157,11 +157,11 @@ async function loadMediaTypesById({ return {}; } - const mediaMetadataAdapter = new IndexedDBAdapter( - `video-editor-media-${projectId}`, - "media-metadata", - 1, - ); + const mediaMetadataAdapter = new IndexedDBAdapter({ + dbName: `video-editor-media-${projectId}`, + storeName: "media-metadata", + version: 1, + }); const mediaEntries = await Promise.all( mediaIds.map(async (mediaId) => { diff --git a/apps/web/src/stickers/providers/index.ts b/apps/web/src/stickers/providers/index.ts index 56b3f6cb..b0ea6efc 100644 --- a/apps/web/src/stickers/providers/index.ts +++ b/apps/web/src/stickers/providers/index.ts @@ -19,6 +19,6 @@ export function registerDefaultStickerProviders({ if (stickersRegistry.has(provider.id)) { continue; } - stickersRegistry.register(provider.id, provider); + stickersRegistry.register({ key: provider.id, definition: provider }); } }