Skip to content

Instantly share code, notes, and snippets.

View LironHazan's full-sized avatar
🎸
666 -> 🦀

LironH LironHazan

🎸
666 -> 🦀
View GitHub Profile
console.log("My awesome snippet");
console.warn("Avoid running untrusted snippets!");
@LironHazan
LironHazan / LazyLoadChildren.tsx
Created March 26, 2022 14:59
A react utility component for Lazy-loading of content as a page is scrolled
import React, { useState, useRef, useEffect } from 'react';
import RectContentLoader from './RectContentLoader';
export interface VirtRenderingProps {
placeholderHeight?: number; // the height of the rendered item
root?: HTMLElement | null; // If the root is null, then the bounds of the actual document viewport are used.
children: React.ReactNode;
}
/**
@LironHazan
LironHazan / RectContentLoader.tsx
Created March 26, 2022 14:56
Minimal react svg rect content holder
export interface RectContentLoaderProps {
placeholderHeight: number;
}
const RectContentLoader = ({ placeholderHeight }: RectContentLoaderProps) => {
return (
<svg height={placeholderHeight}>
<rect
x="0"
y="0"
@LironHazan
LironHazan / parse_pizza.ts
Created June 18, 2021 08:24
consume dummy parser (for blog post)
let textWithSpaces = `foo == "hey there" && foo == "eatPizza"`;
let output = parseDummyQL(textWithSpaces);
console.log(output);
// [
// [ 'foo', '==', 'hey there 🍕' ],
// [ '&&', [ 'foo', '==', 'eatPizza 🍕' ] ]
// ]
@LironHazan
LironHazan / dummy-ql.ts
Created June 18, 2021 08:14
DummyQL for my blog post
import Parsimmon from 'parsimmon';
const P = Parsimmon;
let MyFooQueryLang = P.createLanguage({
// `r` eq rules.
dummy_query: (r) => r.expression.many(),
expression: (r) => P.alt(r.base, r.sub),
base: (r) => P.seq(r.field, r.operator, r.value),
@LironHazan
LironHazan / is-err.ts
Created May 22, 2021 05:39
for my blog post
/**
* Since we don't have a type based pattern matching we're using "tags" runtime check
* @param result
*/
export function isError<T, E extends ErrorClassification>(result: Result<E, T>): result is E {
return typeof result === 'object' && 'message' in result && 'type' in result;
}
@LironHazan
LironHazan / result-util.ts
Created May 22, 2021 05:37
snippet for a blog post
export class ResultT<E, T> {
private result: Result<ErrorClassification, T>;
constructor(result: Result<ErrorClassification, T>) {
this.result = result;
}
ok(onSuccessFn: (lifted: T) => ResultT<E, T>): ResultT<E, T> {
return isError(this.result) ? this : onSuccessFn(this.result as T);
}
async function fetchTables<E>(auth: any): Promise<Either<void, Promise<void>>> {
const sheets = google.sheets({ version: 'v4', auth });
const authorised: Task<string> = async () => readFromFile('src/private/table_meta.json', 'utf-8');
const authErr = () => console.log('error reading private/table_meta.json');
const fetchTables = async (data: string) => {
const { tables, id } = JSON.parse(data);
const ft: (t: string) => Task<Promise<Either<Error, unknown>>> = (t: string) => task.of(fetchTable(sheets, t, id));
const tasks: Task<string>[] = tables.map(ft);
const readCreds: Task<string> = async () => readFromFile('src/private/credentials.json', 'utf-8');
const fail = <T>(reason: T) => new Error(`${reason}`);
const auth = (creds: string) => authorize(JSON.parse(creds), fetchTables);
export async function exportTables<E>(): Promise<Either<Error, Promise<Either<void, void>>>> {
const result: TaskEither<Error, string> = tryCatch(readCreds, fail);
return await pipe(result, map(auth))();
}
@LironHazan
LironHazan / fetchTable.ts
Created January 29, 2021 11:41
fetchTable.ts
function fetchTable<T>(sheets: Sheets, range: any, spreadsheetId: any): Promise<Either<Error, unknown>> {
return new Promise((resolve, reject) => {
sheets.spreadsheets.values.get({ spreadsheetId, range }, (err, res) => {
if (err || !res.data) {
console.log('The API returned an error: ' + err);
return reject(err);
}
return resolve(tableAsJson(res.data.values, range));
});
});