Skip to content

Instantly share code, notes, and snippets.

@Tombarr
Tombarr / deploy-elixir-ec2.yml
Created November 14, 2025 20:54
GitHub Action to build and deploy an Elixir/ Phoenix web app on AWS EC2 running Amazon Linux 2023
name: Build & Deploy Phoenix (linux/x86) to EC2
on:
push:
branches: [ "main" ]
workflow_dispatch:
env:
MIX_ENV: prod
ELIXIR_VERSION: "1.18.4" # adjust as needed
@Tombarr
Tombarr / timezone-to-offset.js
Created November 14, 2025 15:47
JavaScript function mapping IANA time znoe names to UTC offsets in minutes. Originally intended for Cloudfront Functions
const offsets = [
-720, -660, -600, -570, -540, -480, -420, -360, -300, -240, -210, -180,
-150, -120, -60, 0, 60, 120, 180, 210, 240, 270, 300, 330, 345, 360,
390, 420, 480, 525, 540, 570, 600, 630, 660, 720, 765, 780, 840
];
const zones = {
Africa: {
15: 'Abidjan Accra Bamako Banjul Bissau Conakry Dakar Freetown Lome Monrovia Nouakchott Ouagadougou Sao_Tome Timbuktu',
16: 'Algiers Bangui Brazzaville Casablanca Ceuta Douala El_Aaiun Kinshasa Lagos Libreville Luanda Malabo Ndjamena Niamey Porto-Novo Tunis',
@Tombarr
Tombarr / collapse.js
Created February 16, 2025 05:52
Bootstrap Collapse without importing Bootstrap JS
document.querySelectorAll('[data-bs-toggle="collapse"]').forEach(button => {
button.addEventListener("click", (event) => {
event.preventDefault();
let targetSelector = button.getAttribute("data-bs-target");
let target = document.querySelector(targetSelector);
if (target) {
let isCollapsed = target.classList.contains("show");
if (isCollapsed) {
collapseElement(target);
@Tombarr
Tombarr / multi-upload.js
Created June 20, 2024 01:06
AWS SDK v3 - S3 Multipart Upload
const {
CreateMultipartUploadCommand,
UploadPartCommand,
CompleteMultipartUploadCommand,
AbortMultipartUploadCommand,
S3Client,
} = require('@aws-sdk/client-s3');
const path = require('path');
const fs = require('fs');
const crypto = require('crypto');
@Tombarr
Tombarr / InfiniteScroll.svelte
Created May 1, 2023 22:04
Infinite scroll Svelte component that appends DOM elements in increments of page sizes as the user scrolls beyond a threshold
<!--
InfiniteScroll.svelte
Author: Tom Barrasso
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
@Tombarr
Tombarr / object_iterator.js
Created May 7, 2019 00:55
Make all Objects iterable in ES6
Object.prototype[Symbol.iterator] = function() {
let props = Object.getOwnPropertyNames(this);
return {
next: () => {
let name = props.shift();
let done = (name === undefined);
let value = (done) ? undefined : [name, this[name]];
return { value, done };
}
}
const hashCode = str => Array.from(str)
.reduce((h, c) => Math.imul(31, h) + c.charCodeAt(0) | 0, 0)
@Tombarr
Tombarr / zip2.js
Created March 26, 2019 13:04
Zip multiple arrays (of equal length) using Symbol.iterator
function zip(...arrs) {
let i = -1;
return {
[Symbol.iterator]() {
return this;
},
next: () => ({
done: ++i === arrs[0].length,
value: arrs.map(arr => arr[i])
})
@Tombarr
Tombarr / function_passing.ex
Created January 19, 2019 23:22
Functions as arguments in Elixir
add_ten = fn (x) -> x + 10 end
do_a_thing_to_x = fn (thing, x) ->
thing.(x)
end
do_a_thing_to_x.(add_ten, 10) # 20
@Tombarr
Tombarr / function_passing.js
Created January 19, 2019 23:22
Functions as arguments in Javascript
const addTen = (x) => x + 10;
const doAThingToX = (thing, x) => thing(x);
doAThingToX(addTen, 10); // 20