Two Tampermonkey userscripts that make npm package browsing default to npmx.dev, while still allowing you to intentionally open the original npm package page from npmx.
Redirects npm package URLs to the same path on npmx.dev.
Ryan Florence doesn't like me saying that, but it's true.
Why is it true? Well, they look like render props until you scroll down to the return statement and see an arrow function. If you refactor a stateless component into a stateful component (i.e. add a setup scope), the render props subtly become setup props, right under your nose.
Most of the time, using setup props is dangerous and unnecessary, as it leads to problems down the road. At first, all is well, but then you use the component more dynamically and, BOOM, you've got a stale data issue that presents itself in confusing ways. Of course, this problem is most apparent in more complex applications with many moving parts.
| // Track props access and selectively rerun callbacks on rerender. | |
| export function track<Props extends object>( | |
| ...callbacks: ((props: Props) => void)[] | |
| ) { | |
| const tracked = callbacks.map((callback) => new TrackedCallback(callback)) | |
| let oldProps: Props | undefined | |
| return (props: Props) => { | |
| tracked.forEach((callback) => { | |
| if (!oldProps || callback.shouldUpdate(props, oldProps)) { |
| import { Event, events, EventTarget, on } from './framework.ts' | |
| // Extending a built-in class with type-safe events | |
| declare global { | |
| interface Worker { | |
| // Does not exist at runtime. No createEventType wrapper needed. | |
| $rmxEvents: { | |
| message: MessageEvent | |
| } | |
| } |
| import { RoutePattern } from '@remix-run/route-pattern' | |
| import { queryCache } from './query.ts' | |
| const userProfileRoute = new RoutePattern('/users/:id') | |
| type UserProfile = { | |
| name?: string | |
| email?: number | |
| biography?: string | |
| avatar?: string |
| diff --git a/alias.js b/alias.js | |
| index a2e9dddc6b19e5668d23b2b25a0718ee2a201c37..6d21587b4e771ffb406d6193d381076bc5c5f229 100644 | |
| --- a/alias.js | |
| +++ b/alias.js | |
| @@ -98,7 +98,7 @@ function mapColumnsInSQLToAlias(query, alias) { | |
| return mapColumnsInAliasedSQLToAlias(c, alias); | |
| } | |
| return c; | |
| - })); | |
| + })).mapWith(query.decoder); |
| import { sql, Subquery, WithSubquery, type SQL, type SQLWrapper } from 'drizzle-orm' | |
| import type { SelectResultField } from 'drizzle-orm/query-builders/select.types' | |
| type SelectResultFields<TSelectedFields extends Record<string, any>> = { | |
| [K in keyof TSelectedFields]: TSelectedFields[K] extends SQLWrapper | |
| ? SelectResultField<TSelectedFields[K]> | |
| : SQL<TSelectedFields[K]> | |
| } | |
| export function select<TAlias extends string, const TSelectedFields extends Record<string, any>>( |
| // ==UserScript== | |
| // @name YouTube Enhanced Interaction | |
| // @namespace http://tampermonkey.net/ | |
| // @version 0.2 | |
| // @description Enhanced click handling for YouTube recommendations with diagnostics | |
| // @author You | |
| // @match https://www.youtube.com/* | |
| // @grant none | |
| // ==/UserScript== |