Skip to content

Instantly share code, notes, and snippets.

View khaledosman's full-sized avatar
🤘

Khaled Osman khaledosman

🤘
View GitHub Profile
@khaledosman
khaledosman / ADR.txt
Created November 9, 2021 09:21
Architecture Decision Records
An Architecture Decision Record (ADR) is a document that captures a decision, including the context of how & why the decision was made and the consequences of adopting the decision. 
Key topics to include:
[short title of problem and solution]
Status: [proposed | rejected | accepted ]
Date: [YYYY-MM-DD when the decision was last updated]
Technical Story: [description | ticket/issue URL]
Context and Problem Statement
[Describe the context and problem statement, e.g., in free form using two to three sentences. You may want to articulate the problem in form of a question.]
@khaledosman
khaledosman / documentation.txt
Created July 12, 2021 11:11
software documentation guidelines
Software documentation types:
https://ibb.co/0s7W7TD
Key topics to document
- Architecture of how microservices or system components interact with each others
- Decision documents
- architecture of each component or microservice on its own
- When/How to run Migrations and how to generate
- Design System documentation / storybook if applicable
- GUI for the database?
@khaledosman
khaledosman / index.js
Created March 7, 2021 15:23
replace all links of all md files in a folder recursively with a new downloaded file link
const fs = require('fs')
const path = require('path')
const http = require('https')
const { promisify } = require('util')
const promisifiedReadFile = promisify(fs.readFile)
const promisifiedWriteFile = promisify(fs.writeFile)
// loops over all files in a directory recursively and returns filepaths to .md files
function getMdFilePaths (startPath) {
if (!fs.existsSync(startPath)) {
@khaledosman
khaledosman / generate-time-array.js
Created November 2, 2020 16:30
Generate a time array (i.e for a graph)
function generateTimeArray (startTime, endTime, step) {
let pointer = startTime
const res = []
console.log(pointer, pointer <= endTime)
while (pointer <= endTime) {
res.push(pointer)
const dateObj = new Date(pointer)
pointer = dateObj.setHours(dateObj.getHours() + step)
}
return res
function retryIfRequestRateTooLarge (promiseFn, currentRetry = 0, maxRetries = 100) {
return promiseFn()
.catch(async err => {
if ((err.message.includes('StatusCode: 429')) || err.message.includes('RetryAfterMs')) {
// if you're stuck here you might want to increase the collection's throughput (RU/s) temporarily from cosmosdb then set it back to 400
const ms = err.message.split(',').find(str => str.includes('RetryAfterMs')).split('=')[1] || 1000
console.log({ ms, currentRetry, maxRetries })
if (currentRetry < maxRetries) {
return delay(Number(ms)).then(() => retryIfRequestRateTooLarge(promiseFn, currentRetry + 1, maxRetries))
} else {
@khaledosman
khaledosman / AppSync.md
Last active August 6, 2020 09:57
AppSync

apollographql/apollo-server#2129 (comment)

  1. No JS resolvers, ugly template mappings
  2. it replaces your entire backend and creates everything for you, which works fine if you just want to build another crud app, but if you want to have custom resolvers fetching data from external data sources then it gets annoying and you have to configure custom lambdas for each resolver. Plus I want to build my own custom backend, I couldve just used graphcool or graphCMS instead if I didnt want to build a backend.
  3. it forces you to use AWS services like Cognito for authentication and dynamoDB as a db which I hate because of its terrible syntax so I prefer to use a MongoDB Atlas backend instead. Dont want to use dynamoDB with appSync? you have to create another lambda to pipe the response to your external database.
  4. its more difficult to debug and you lose good monitoring solutions like Apollo Engine.
  5. it forces you to learn the AWS way of doing things instead of normal graphq
@khaledosman
khaledosman / apple-login-helpers.ts
Created February 11, 2020 13:53
google/facebook/apple login
import axios from 'axios'
import * as jwt from 'jsonwebtoken'
import NodeRSA from 'node-rsa'
const clientID = process.env.APPLE_CLIENT_ID
const ENDPOINT_URL = 'https://appleid.apple.com'
const TOKEN_ISSUER = 'https://appleid.apple.com'
async function getApplePublicKey (): Promise<any> {
const url = `${ENDPOINT_URL}/auth/keys`
@khaledosman
khaledosman / .yarnclean
Last active February 27, 2020 10:09
advanced yarnclean for minimal bundle size
# Optionally uncomment *.ts in production/when deploying only
# test directories
__tests__
test
tests
powered-test
__tests__
tests
powered-test
@khaledosman
khaledosman / Readme.md
Last active August 6, 2020 09:58
how to choose between MongoDB Embedded documents vs Separate collections
  1. Can you query events separately or are they always tied to a calendar? do you need pagination for events? Pagination for embedded documents is complicated or not as flexible/doable
  2. is it a one-to-one or one-to-many relations? can one event be in multiple calendars?
  3. if so can you edit/delete this event?, if you need to update the event and you have it as an embedded document instead of a separate collection, then you might have the problem of having to update the same event in multiple documents and ensuring data-consistency
  4. separate collection is usually cleaner, but its also less performant, because to get events for each calendar, you need to use .populate() which makes separate queries to get each event for each calendar when you query a calendar. A better idea is probably to query it the other way around (the events collection instead), i.e query all events by a specific calendar, thus reducing the number of queries needed if you were to query it the other way around.
  5. if you can think of ev