Skip to content

Instantly share code, notes, and snippets.

View tjunghans's full-sized avatar
💭
Open for business

Thomas Junghans tjunghans

💭
Open for business
View GitHub Profile
@tjunghans
tjunghans / git-releases-per-year.sh
Created February 8, 2024 13:31
Count / collect tagged git commits for a year
On xyz master branch run the following to get the count for the year 2024.
git log --format="%h %an %Cgreen%as%Creset %d" --first-parent --tags --no-walk | grep -c -e '2024'
Omit “-c” to list the entries for 2024:
git log --format="%h %an %Cgreen%as%Creset %d" --first-parent --tags --no-walk | grep -e '2024'
@tjunghans
tjunghans / react-query.js
Created January 29, 2024 20:39
react-query Jest Mock
// Place this file inside <projectRoot>/__mocks__/react-query.js
export const useQuery = jest
.fn()
.mockReturnValue({ data: {}, isLoading: false, error: {} });
export class QueryClient {}
@tjunghans
tjunghans / component-mock.tsx
Created January 9, 2024 12:53
React Component Mock
import React, { type DetailedHTMLProps, type HTMLAttributes } from "react";
export const createComponentMock = <
T extends DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
>(
componentName: string
) => {
const fakeComponent = (props: T) => (
<div data-testid={componentName} {...props} />
);
@tjunghans
tjunghans / react-component-with-use-effect.tsx
Last active April 1, 2023 13:44
Example of a functional React component with useEffect and the AbortController to cancel an async operation
// See https://gist.github.com/tjunghans/0129439ad12b37b98c72477156cddbce for the definition of `doSomethingAsync`.
function MyComponent({ someprop }) {
const [value, setValue] = React.useState("");
React.useEffect(() => {
// Create an instance of the AbortController that will
// be used to abort in the useEffect return.
const controller = new AbortController();
@tjunghans
tjunghans / asynchronous-fn-with-abort.ts
Last active April 1, 2023 13:44
Example of an asynchronous function that returns a promise which can be cancelled using the AbortController
// The implementation below is inspired by the [example](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal#examples)
// that shows how a fetch operation can be aborted using the signal option.
// See https://gist.github.com/tjunghans/da50cc29f3f965d587db99c2f44813f1 for an example on how `doSomethingAsync` is used.
function doSomethingAsync(
// payload can be anything. It's just an example
payload,
{ signal }: { signal?: AbortSignal } = {}
): Promise<any> {
// Abort immediately if `abort` was already called.
@tjunghans
tjunghans / .editorconfig
Created March 17, 2023 22:22
.editorconfig
# EditorConfig is awesome: https://editorconfig.org/
root = true
[*]
charset = utf-8
indent_style = space
end_of_line = lf
indent_size = 2
insert_final_newline = true
#!/usr/bin/env node
const { readdir, writeFile } = require("fs");
const { promisify } = require("util");
function createDirEntry(dir) {
return { name: dir, path: `packages/node_modules/${dir}` };
}
function createProjectCodeWorkspaceContents(dirs) {
@tjunghans
tjunghans / esm-default-exports.md
Created November 23, 2021 10:52
ESM Default exports

This is something a think about a lot. I a while ago I browsed the Pure ESM package gist by Sindresorhus and there's one point When should I use a default export or named exports?.

He suggests:

My general rule is that if something exports a single main thing, it should be a default export.

There's also this:

Why use default exports at all? Simplify usage: Having a default export simplifies import when the person importing the module just wants the obvious thing from there. There’s simply less syntax and typing to do.

@tjunghans
tjunghans / Summary-Notes-On-Secure-User-Auth.md
Last active September 6, 2021 19:57
Summary Notes on "Implementing Secure User Authentication in PHP Applications with Long-Term Persistence"

Summary Notes on "Implementing Secure User Authentication in PHP Applications with Long-Term Persistence"

Source

  • Secure Authentication is hard

Secure Password Storage in 2015

Passwords: Hashes, Salts, and Policies

(function () {
"use strict";
const table = document.querySelector("table");
if (table) {
const thead = table.querySelector("thead");
const tbody = table.querySelector("tbody");
// create "Path" header column