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>;
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.
~/.ssh/id_ed25519
and ~/.ssh/id_ed25519_work
Personally I've never liked how tools like Remix or NextJS have mapped a nested file system to routes. Simple things like "I want to put this component in its own file" become annoying tasks.
I've always been a fan of "flatter" file systems, my files often look like this:
/App/
async function validatePassword(password: string): string[] { | |
let errors = [] | |
// 1. Don't regex for things you can trivially express in code | |
// ----------------------------------------------------------- | |
// For example, we could have written this as `/^.{0,7}$/` but that's not | |
// nearly as clear as checking the length of the string. | |
if (password.length < 8) { | |
errors.push("Password must be at least 8 characters long") |
/** | |
* 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}. |
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({ |
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({ |
<!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 lint from './task-lint'; | |
export test from './task-test'; | |
export build from './task-build'; | |
export dev from './task-dev'; | |
export default dev; |
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 |