Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

Multiple GitHub accounts (Work vs Personal)

This setup uses some tricks to ensure that the right email/name/ssh-key is used for the right repos without having to think about it ever again.

  • First generate two SSH keys, ~/.ssh/id_ed25519 and ~/.ssh/id_ed25519_work
  • Add one key to your personal account and the other to your work account

.ssh/config

/**
* If you have a volume input (0 to 1), such as a slider, use this to convert
* it to a logarithmic volume that is closer to human perception (0 to 1).
*
* A more robust approach would use a Fletcher-Munson curve, however this is a
* close enough approximation for most use cases.
*
* You can customize the curve to your liking, generally 3-4 is a good value.
*
* The inverse of this function is {@link convertVolumeToInput}.
@jamiebuilds
jamiebuilds / main.js
Created June 16, 2023 19:20
dialog.showSaveDialog force normalized extension
let { app, dialog } = require('electron')
let path = require("path")
let pathCompleteExtname = require("path-complete-extname")
app.whenReady().then(async () => {
for (let defaultPath of ['change-me.txt', 'change-me.tar.gz', 'change-me.jpeg']) {
let defaultExtname = pathCompleteExtname(defaultPath)
let defaultBasename = path.basename(defaultPath, defaultExtname)
let { canceled, filePath: selectedPath } = await dialog.showSaveDialog({
@jamiebuilds
jamiebuilds / main.js
Last active June 14, 2023 17:49
showSaveDialog without filters bug
let { app, dialog } = require('electron')
app.whenReady().then(async () => {
// case 1: without filters (BUG)
{
let { canceled, filePath } = await dialog.showSaveDialog({
defaultPath: "change-me.txt",
})
if (canceled) return
await dialog.showMessageBox({
@jamiebuilds
jamiebuilds / index.html
Last active June 14, 2023 17:10
Save Dialog
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
export type QueryTemplateParam = string | number | undefined;
export type QueryFragmentValue = QueryFragment | QueryTemplateParam;
export type QueryFragment = [
{ fragment: string },
ReadonlyArray<QueryTemplateParam>
];
/**
* You can use tagged template literals to build "fragments" of SQL queries

Bump all npm outdated dependencies

npm install $(npm outdated --json | jq -r 'to_entries | map("\(.key)@^\(.value.latest)") | join(" ")')
npm run typecheck

OpenAPI TypeScript Generator

First we start off with a very generic module for executing OpenAPI operations:

export interface ApiRequest {
  path: string;
  method: string;
  params?: Record<string, string>;
  queryParams?: Record<string, string>;
#!/usr/bin/env node
const fs = require("fs/promises")
const globby = require("globby")
const makeDir = require("make-dir")
const path = require("path")
const svgo = require("svgo")
const REPO_ROOT = path.join(__dirname, "..")
async function main() {