VideoPress: Enable typechecking on the package#49205
Conversation
|
Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.
Interested in more tips and information?
|
|
Thank you for your PR! When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:
This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖 Follow this PR Review Process:
If you have questions about anything, reach out in #jetpack-developers for guidance! |
Code Coverage SummaryCoverage changed in 3 files.
2 files are newly checked for coverage.
|
54d8ba8 to
793bb08
Compare
b0603b7 to
66d9d63
Compare
Replace the placeholder `typecheck` script (`echo "pending implementation"`) with `tsgo --noEmit`, matching the convention used by every other Jetpack package. To get the package to a clean type-check state, fix ~85 pre-existing TypeScript errors across hooks, admin components, block editor, and the classic-editor lib. Notable changes: - Add a public-API type file for `use-videos` (`index.d.ts`) so consumers destructure typed fields instead of `unknown`. - Module-augment `@wordpress/api-fetch`'s `APIFetchOptions` with the `apiNamespace`, `global`, and `formData` properties that the WP runtime middleware accepts but upstream types don't expose. - Remove our `Window.wp` augmentation in favor of a shared `ClassicEditorWp` type in `declarations.d.ts`; multiple workspace packages declare incompatible inline `Window.wp` shapes and merging across them isn't possible. - Mechanical narrowing of strings to literal unions for Button variants, privacy levels, and rating values; remove unsupported `weight`/`size` props from `<Text>` (silently dropped at runtime anyway). - Stringify URL params (`setParam( 'page', String( page ) )`) at the call site, and update the corresponding test expectation. Runtime behavior is preserved everywhere; this is a pure types/test cleanup plus the script flip. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both `select-image-from-media-library.ts` and `use-poster-edit/index.ts` defined the same `wp.media` modal frame shape locally. Move it (and the `Attachment` shape it returns) into `declarations.d.ts` alongside `ClassicEditorWp`, since `wp.media()` is what produces the frame. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Konstantin Obenland <obenland@gmx.de>
`wp` is the global WordPress JS namespace — not classic-editor-specific. Block editor, dashboard, REST API helpers, and i18n all live on it. Rename to reflect what it actually is. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ock destructure
Two follow-ups from PR review:
* `uploadTrackForGuid` is now annotated as returning
`Promise< string | { error: string; message?: string } >` rather than the
inferred `Promise< unknown >`. The error branch in `tracks-control` drops
the `errorResponse` shadow + cast in favor of a `typeof src !== 'string'`
narrowing. Surfaces (and fixes) a latent bug in `use-sync-media`: the
auto-generated-chapter upload path assumed the response was always a
string URL and would have silently stored an error object as a track src
on failure. Now it bails early with a debug log on error.
* Block-registration entry points (`index.ts`, `index.native.ts`) fold the
separate `const { category } = metadata;` line into the existing exported
destructure. `name` and `attributes` are already exported with no external
consumers; the original split bought nothing and added a line.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`@wordpress/element`'s web Platform shim declares `OS`, `select`, and
`isWeb` but omits `isNative` — even though `isNative` exists at runtime
(the shim mirrors React Native's Platform API). Add the missing field
via module augmentation in `api-fetch.d.ts` so the two `Platform.isNative`
call sites can use the idiomatic property instead of `Platform.OS !== 'web'`.
Also cast the `onNoticeRemove={ invalidateResolution }` prop on
PlaceholderWrapper to `() => void` for consistency with the adjacent
Button onClick cast — both are passing a 2-arg function as a 0-arg
callback (pre-existing latent bug, out of scope to fix).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The file augments multiple `@wordpress/*` modules now (api-fetch + element), not just api-fetch. Move it to the package root next to declarations.d.ts since it's cross-cutting type plumbing, and rename to reflect its broader scope. Tsconfig include gets the new path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the unknown[] placeholders in the use-videos .d.ts with the domain types (a new AdminVideo = VideoPressVideo & MetadataVideo alias and LocalVideo), and type the store's filter and setFilter accurately. Those types now flow through useDashboardVideos, so the (VideoPressVideo & MetadataVideo)[] / LocalVideo[] casts at the admin-page call sites are gone. The loading placeholders are typed so the assembled videos list stays strongly typed, the filter handler matches the real setFilter signature, and the now-redundant Boolean(uploading) in the local video list is simplified. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012iifiyxMAG9GGSXpAZ7cuV
The bar chart's comparison-bars module reads process.env.NODE_ENV behind a dev-only guard. Charts resolves `process` from @types/node in its own dependency tree, but packages that consume charts as source via the `jetpack:src` export condition do not — so the file failed to type-check once VideoPress (which imports @automattic/charts) enabled its typecheck. Declare a minimal module-local `process` so the file is self-contained; it harmlessly shadows the global within this module and does not affect charts' own typecheck. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012iifiyxMAG9GGSXpAZ7cuV
66d9d63 to
92d8451
Compare
There was a problem hiding this comment.
Pull request overview
Enables real TypeScript typechecking for the VideoPress package and tightens types across the admin/dashboard + block-editor codepaths so CI catches type regressions (and removes several unsafe casts at call sites).
Changes:
- Replace the placeholder
typecheckscript withtsgo --noEmitand wire in new local.d.ts/augmentations needed for successful package typechecking. - Improve type fidelity for
use-videosconsumers (domain types instead ofunknown[]) and narrow multiple UI props/handlers to match upstream component unions. - Fix/guard a few runtime edge cases surfaced by stricter typing (e.g., track upload error envelope handling, URLSearchParams stringification, omitting undefined POST body fields).
Reviewed changes
Copilot reviewed 38 out of 42 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| projects/packages/videopress/wordpress-augmentations.d.ts | Adds local module augmentations for @wordpress/api-fetch and @wordpress/element to match runtime usage. |
| projects/packages/videopress/tsconfig.json | Includes new ambient declaration files in the package TS program. |
| projects/packages/videopress/src/dashboard/utils/select-image-from-media-library.ts | Switches to shared WpGlobal/media frame types for safer wp.media access. |
| projects/packages/videopress/src/dashboard/hooks/test/use-update-video-poster.test.ts | Cleans up no-longer-needed TS suppression around async mutation completion. |
| projects/packages/videopress/src/dashboard/components/video-details/thumbnail-card.tsx | Uses WpGlobal casting for window.wp.media feature detection. |
| projects/packages/videopress/src/client/lib/video-tracks/index.ts | Types track upload responses and propagates that to callers for correct narrowing. |
| projects/packages/videopress/src/client/lib/token-bridge/test/index.test.ts | Tightens typings around the intentional dynamic require test setup. |
| projects/packages/videopress/src/client/lib/get-media-token/index.ts | Builds POST body to omit undefined values and types wp.apiFetch access via WpGlobal. |
| projects/packages/videopress/src/client/components/timestamp-control/index.tsx | Replaces NodeJS.Timeout with ReturnType<typeof setTimeout> for browser correctness. |
| projects/packages/videopress/src/client/block-editor/hooks/use-sync-media/index.ts | Guards against treating an error envelope as a successful track src. |
| projects/packages/videopress/src/client/block-editor/blocks/video/transforms/index.tsx | Updates transform matching to satisfy updated WP transform typings. |
| projects/packages/videopress/src/client/block-editor/blocks/video/index.ts | Registers block category from metadata and narrows a couple of typed fields. |
| projects/packages/videopress/src/client/block-editor/blocks/video/edit.tsx | Uses browser-safe timer typing and narrows notice/button handler typing. |
| projects/packages/videopress/src/client/block-editor/blocks/video/components/tracks-control/index.tsx | Uses typed TrackUploadResponse to handle error envelopes explicitly. |
| projects/packages/videopress/src/client/block-editor/blocks/video/components/privacy-and-rating-panel/privacy-and-rating-settings.tsx | Adds literal-union narrowing for SelectControl value. |
| projects/packages/videopress/src/client/block-editor/blocks/video/components/poster-panel/index.tsx | Stringifies interpolated numeric values and adds a documented MenuItem typing exception. |
| projects/packages/videopress/src/client/block-editor/blocks/video/components/poster-image-block-control/index.tsx | Documents MenuItem variant typing mismatch via @ts-expect-error. |
| projects/packages/videopress/src/client/block-editor/blocks/video/components/banner/connect-banner.tsx | Makes button text variables explicitly string for stricter inference. |
| projects/packages/videopress/src/client/admin/types/index.ts | Introduces AdminVideo alias (domain video + UI metadata). |
| projects/packages/videopress/src/client/admin/hooks/use-videos/index.d.ts | Adds a typed .d.ts companion for the use-videos hook exports. |
| projects/packages/videopress/src/client/admin/hooks/use-poster-edit/index.ts | Uses shared WpMediaAttachment typing and WpGlobal casting for wp.media. |
| projects/packages/videopress/src/client/admin/hooks/use-plan/test/index.test.ts | Switches test-global typing approach to reuse the existing global augmentation module. |
| projects/packages/videopress/src/client/admin/hooks/use-dashboard-videos/test/index.test.ts | Updates expectations for string URL params and adjusts typing for placeholder IDs. |
| projects/packages/videopress/src/client/admin/hooks/use-dashboard-videos/index.ts | Ensures URL param values are strings and stabilizes/typifies placeholder skeleton items. |
| projects/packages/videopress/src/client/admin/hooks/use-analytics-tracks/index.ts | Narrows blog_id typing to satisfy event property constraints. |
| projects/packages/videopress/src/client/admin/components/video-quick-actions/index.tsx | Adjusts Button icon prop typing to satisfy stricter component unions. |
| projects/packages/videopress/src/client/admin/components/video-list/index.tsx | Fixes local list “has videos” logic by treating uploading as a boolean. |
| projects/packages/videopress/src/client/admin/components/video-filter/index.tsx | Removes unsupported Text props and narrows filter handler/user item typings. |
| projects/packages/videopress/src/client/admin/components/video-card/test/index.test.tsx | Makes the ref-forwarding assertion resilient to async rendering via waitFor. |
| projects/packages/videopress/src/client/admin/components/video-card/index.tsx | Removes unsupported Text props that were becoming invalid DOM attributes. |
| projects/packages/videopress/src/client/admin/components/publish-first-video-popover/types.ts | Derives position typing from Popover props for stronger compatibility. |
| projects/packages/videopress/src/client/admin/components/pricing-section/index.tsx | Adds from=jetpack-videopress attribution and stringifies numeric sprintf inputs. |
| projects/packages/videopress/src/client/admin/components/input/index.tsx | Passes htmlFor to Text via a typed spread workaround. |
| projects/packages/videopress/src/client/admin/components/global-notice/index.tsx | Narrows action variant to the supported union. |
| projects/packages/videopress/src/client/admin/components/edit-video-details/index.tsx | Fixes page comparisons for string route params and narrows SelectControl value typing. |
| projects/packages/videopress/src/client/admin/components/admin-page/libraries.tsx | Ensures sprintf receives string values. |
| projects/packages/videopress/package.json | Enables real typecheck script (tsgo --noEmit). |
| projects/packages/videopress/global.d.ts | Removes local Window.wp augmentation in favor of the shared WpGlobal alias. |
| projects/packages/videopress/declarations.d.ts | Adds shared WpGlobal/media types and a *.css module declaration. |
| projects/packages/videopress/changelog/typecheck-enable | Changelog entry for enabling package typechecking. |
| projects/js-packages/charts/src/charts/bar-chart/private/comparison-bars.tsx | Declares a minimal local process type for source consumption without @types/node. |
| projects/js-packages/charts/changelog/fix-comparison-bars-process-type | Changelog entry for the Charts typecheck fix. |
Replace the manual singular/plural ternary with a single _n() call so the library header count respects each locale's plural rules instead of only modeling one-vs-many. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012iifiyxMAG9GGSXpAZ7cuV
…ntation
The side-effect value import of admin-page/types executed the module (and its
runtime imports) during the test run. Switch to `import type {}` so it's erased
from the emitted JS while still keeping the file a module — which keeps the
local `require` declaration block-scoped instead of leaking into global scope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012iifiyxMAG9GGSXpAZ7cuV
…nit tests Enabling typechecking (#49205) added two new code paths that the coverage check flagged as uncovered: * get-media-token builds the POST body with a loop that omits `undefined` params instead of serializing them as the string "undefined". * use-sync-media guards the auto-generated-chapter upload path, short- circuiting when `uploadTrackForGuid` resolves to a non-string error envelope instead of storing it as a track `src`. Add focused tests for both: get-media-token asserts the request body omits undefined params and stringifies defined ones (including the falsy `0` subscription plan id); use-sync-media drives a save transition into the chapter-upload branch and verifies the guard both blocks the bad write and allows the happy path. Claude-Session: https://claude.ai/code/session_01VdJE5vvnA1vJ4u6wqhFuQz
…casts Address PR review findings on the typecheck-enablement work: * use-sync-media: route the auto-generated chapter upload's error-envelope branch and a new .catch to setError, so failures surface to the consumer instead of being dropped into a dev-only debug log. Tighten the hook's error type from object|null to Error|null and cover both failure paths with tests. * edit.tsx: replace the invalidateResolution double-casts with the existing invalidateCachedEmbedPreview callback, removing the cast and fixing the "Try again" handler that previously ran against a MouseEvent. * edit-video-details: drop the `null as never` cast on VideoPlayer's optional videoRef; video-quick-actions: name the icon cast as JSX.Element. * use-videos/index.d.ts: declare the spread-derived query fields, type useVideosQuery, and note the file must stay in sync with index.js. * Fix stacked // comments and trim verbose docblocks to the load-bearing point. Claude-Session: https://claude.ai/code/session_013fq3GxfSjTQAE4gE9QjTWi
Continues the type-prep workstream from #49204 (React 19 type prep), which has since merged to
trunk.Proposed changes
typecheckscript (echo "pending implementation") withtsgo --noEmit, matching every other Jetpack package. From this PR on, type errors inprojects/packages/videopresswill fail CI like every other typechecked package..d.tscompanion for theuse-videoshook so the ~25 consumers across the admin dashboard and hooks tree destructure typed fields.use-videos.d.tsnow uses the domain types instead ofunknown[]— a newAdminVideo = VideoPressVideo & MetadataVideoalias foritems/uploading/uploadErrors,LocalVideo[]for local videos, and accuratefilter/setFiltertypes. Those types flow throughuseDashboardVideos, so the(VideoPressVideo & MetadataVideo)[]/LocalVideo[]casts at theadmin-pagecall sites are gone. The only remaining cast is a single, commented one on the loading-skeleton placeholders (which deliberately carry just anid).@wordpress/api-fetch'sAPIFetchOptions(inwordpress-augmentations.d.ts) with theapiNamespace,global, andformDataproperties that this codebase passes at runtime via middleware but that upstream types don't expose. Also augments@wordpress/element'sPlatformwithisNative(used byfetch-video-itemanduse-video-data).Window.wpaugmentation in favor of a sharedWpGlobaltype alias indeclarations.d.ts. Multiple workspace packages (@automattic/number-formatters) declare incompatible inlineWindow.wpshapes that TypeScript can't merge across anonymous object types; aliasing avoids the conflict.uploadTrackForGuidas returningPromise< string | { error: string; message?: string } >so its consumers get real narrowing instead ofunknowncasts. Behavior change: this surfaces a latent bug inuse-sync-media's auto-generated-chapter upload path — the success handler treated the response as always-a-string and would have silently stored an error envelope as a tracksrcon failure. The newtypeof src !== 'string'early-return short-circuits with a debug log instead of corrupting the track.variant, videoprivacySetting, videorating, and similar@wordpress/components/@wordpress/dataviewsprop unions.searchParams.setParam( 'page', String( page ) )— at the call site and update the correspondinguseDashboardVideostest expectation. The pre-existingpage: numberarg was a type-system bug; runtime params on a URL are always strings.weight/sizeprops from<Text>; the baseTextcomponent doesn't read them (only theH3/Titlewrappers do), so they were silently emitted as invalid HTML attributes (<div weight="regular">). No visual change.withNotices(...)HOC outputs and theinvalidateResolutionButtononClickvia explicitascasts (a deliberate behavior-preserving choice; theonClickhandler is broken at runtime but the bug is pre-existing and out of scope here).@automattic/*workspace imports where the import resolver can't follow thejetpack:srccondition.tsgodoes follow it; the suppression is a known-workaround pattern this monorepo has used elsewhere.Behavior changes worth noting (surfaced in review)
A few changes here alter runtime behavior; all are intended and the first two are correctness fixes:
hasVideos(video-list):uploadingis aboolean, so the olduploading?.length > 0term was a silent no-op (booleans have no.length) and never contributed. It now contributes (simplified to... || uploading), so the local list reflects an in-progress upload as it was always meant to.block-editor/blocks/video/index.ts):categoryis now destructured fromblock.jsonmetadata and passed toregisterBlockType, which previously omitted it. The block now registers under its declaredmediacategory.pricing-section):from: 'jetpack-videopress'is now passed touseProductCheckoutWorkflow(a required prop that was previouslyundefined, matching the siblinguseConnectioncall). The upgrade/checkout URL now carriesfrom=jetpack-videopress.get-media-token): the POST body is now built soundefinedvalues are omitted, instead ofnew URLSearchParams( fetchData )serializing them as the literal string"undefined".Rebase notes
trunk. Trunk removed the*.native.tsvariants forblock-editor/blocks/videoandlib/get-media-token, so the native-shim type changes this PR originally carried were dropped as obsolete. Trunk also independently migrated these components fromuseBreakpointMatchtouseViewportMatchand applied theSupportedLayoutsfix inroutes/library/stage.tsx; those took precedence during conflict resolution.@automattic/charts'comparison-barsmodule readsprocess.env.NODE_ENVand resolvedprocessonly from its own@types/node. Since VideoPress imports@automattic/chartsas source (jetpack:src), enabling VideoPress's typecheck tripped over it. The module now declares a minimal localprocessso it's self-contained. (Could be split into a separate Charts PR if preferred — it sits in its own commit.)Does this pull request change what data or activity we track or use?
The
from=jetpack-videopresscheckout attribution noted above is added to the upgrade URL. No new analytics or data collection.Testing instructions
cd projects/packages/videopress pnpm run typecheckpnpm test?page=is now set to the string form. Visual behavior identical.Placeholdererror/loading states still render.<track src="[object Object]">in the saved markup).src/clientorsrc/dashboardand runpnpm run typecheck— it should now fail. Revert before committing.