Skip to content

Instantly share code, notes, and snippets.

View joemaffei's full-sized avatar

Joe Maffei joemaffei

View GitHub Profile
@joemaffei
joemaffei / pickStringKeysAndValues.ts
Last active March 21, 2024 15:03
Convert an iterable to an object, keeping only key/value pairs that are both strings. Useful for excluding File values from FormData.
/**
* Converts an iterable to an object, keeping only key/value pairs that are both strings.
*/
function pickStringKeysAndValues<
T extends { entries(): IterableIterator<[unknown, unknown]> },
>(iterable: T): Record<string, string> {
let result: Record<string, string> = {};
for (let [key, value] of iterable.entries()) {
if (typeof key === 'string' && typeof value === 'string') {
result[key] = value;
@joemaffei
joemaffei / dependency-injection-made-simple.ts
Created March 20, 2024 01:51
Stupid simple dependency injection for TypeScript
/**
* Module-level variable where all of the global dependency injection
* overrides are stored.
*/
const provisions = new Map<unknown, unknown>();
/**
* Adds an override to the global dependency injection context.
* TypeScript ensures that the signature of the override is the same
* as that of the dependency being overridden.
@joemaffei
joemaffei / keyMirror.ts
Created March 11, 2024 23:30
Type-safe key mirror
function keyMirror<Obj>(...args: (keyof Obj)[]): Readonly<{ [Key in keyof Obj]: Key }> {
let obj = {};
for (let arg of args) {
Object.defineProperty(obj, arg, {
configurable: false,
enumerable: true,
value: arg,
writable: false,
});
}
@joemaffei
joemaffei / simple-dependency-injection.tsx
Created March 5, 2024 04:57
Simple dependency injection in React
const $dependencyContext = Symbol();
/**
* The provide function would be called at the root of the application,
* or at the "root" of a dynamically imported module.
*/
function provide<T extends Record<symbol, any>>(deps: T) {
(globalThis as any)[$dependencyContext] = {
...(globalThis as any)[$dependencyContext],
...deps,
@joemaffei
joemaffei / window-ipsum.js
Created January 25, 2024 03:42
Window Ipsum: random text from the keys of the window object
function windowIpsum(numberOfWords) {
const keys = Object.keys(window);
return [...Array(numberOfWords)]
.map(() => {
return keys[Math.floor(Math.random() * keys.length)];
})
.join(' ');
}
@joemaffei
joemaffei / sort-obsidian-plugins.js
Created December 30, 2023 15:02
Sort Obsidian plugins by downloads
$('.plugins-container').replaceChildren(...Array.from($('.plugins-container').children).sort((a,b)=>parseInt(b.children[2].textContent.replace(/\D/g,''))-parseInt(a.children[2].textContent.replace(/\D/g,''))))
@joemaffei
joemaffei / mouse-mover.js
Created December 11, 2023 18:32
Mouse mover in Node using RobotJS
const robot = require('robotjs');
const screenSize = robot.getScreenSize();
(async () => {
while (true) {
robot.moveMouseSmooth(
Math.random() * screenSize.width,
Math.random() * screenSize.height,
1
);
await new Promise((resolve) => {
@joemaffei
joemaffei / FileTree.jsx
Created November 10, 2023 20:13
Simple FileTree component
const FileTreeStyles = styled.ul`
button {
font-family: monospace;
background: none;
border: 0;
padding: 0.125em 0;
&:hover {
background: #f002;
}
@joemaffei
joemaffei / array-utility-methods.js
Last active March 21, 2023 20:14
Array utility methods
// Methods I wish existed in the Array prototype
Array.prototype.filterEqual = function filterEqual(item) {
return this.filter(x => x === item);
}
Array.prototype.filterEqualBy = function filterEqualBy(key, item) {
return this.filter(x => x[key] === item);
}
@joemaffei
joemaffei / react-use-proxy.tsx
Created November 8, 2022 06:04
Simple mutable state in React using Proxy
import * as React from 'react';
function useProxy<T>(initialValue: T) {
const [state, setState] = React.useState(initialValue);
const proxy = React.useMemo(() => {
return new Proxy(
{ value: state },
{
set(obj, prop, value) {
if (prop === 'value') {