Skip to content

Instantly share code, notes, and snippets.

View pmn4's full-sized avatar

Pat Newell pmn4

View GitHub Profile
@pmn4
pmn4 / promise-predicates.ts
Created November 3, 2023 14:38
Predicates for Cleanly Handling Settled Promises
// Filtering
export function isFulfilled<T>(
value: PromiseSettledResult<T>,
_index?: number,
_array?: PromiseSettledResult<T>[],
): value is PromiseFulfilledResult<T> {
return value.status === 'fulfilled';
}
@pmn4
pmn4 / typed-api-request.d.ts
Created September 20, 2023 19:31
Why is the NextApiResponse type generic, but `NextApiRequest` is not?
// Add type safety to NextApiRequest
type TypedNextApiRequest<Q, B> = Omit<NextApiRequest, 'body' | 'query'> & {
// make req.query have the keys we expect, but AsQuery will turn the values
// into strings or string arrays. Partial is there because you never know
// whether the request will be well-formed
query: Partial<AsQuery<Q>>;
// make req.body have the keys and value types we expect, however, know that
// the data will be deserialized from JSON, so, for example, Dates will be
// strings. again Partial is there to enforce defensive code
body: Partial<Deserialized<B>>;
@pmn4
pmn4 / path-params.d.ts
Last active September 20, 2023 19:28
a TypeScript type for parsing URL path parameters
/*
I find that the edges of serialization are the greatest weaknesses for
TypeScript projects. Further, with API routes, I like to be as declarative
as possible, so the code (the types) can be documentation for both client
and server.
With this type, URL path parameters can be extracted from path string:
*/
// URL param values come in as a string or an array of strings
@pmn4
pmn4 / deserialized.d.ts
Created September 20, 2023 17:34
TypeScript: Deserialized
/*
TypeScript can struggle with deserialization. Reading from localStorage,
dealing with user input, or receiving data from an API are all cases where the
data coming in may not have the EXACT type we want it to have. Dates are a
perfect example, in that they are typically serialized as a string, which
makes deserializing them impossible since we cannot distinguish between a
string that is intended to be a Date and one that is intended to be the string
representation of a date.
Hence, the Deserialized type:
@pmn4
pmn4 / kwarg_struct.rb
Created January 14, 2021 14:25
A Ruby Struct, but with a keyword argument constructor, allowing for optional parameters
class KwargsStruct < Struct
def initialize(*args, **kwargs)
# assumes the keyword argument takes priority
super *members.each_with_index.map { |k, i| kwargs[k] || args[i] }
end
end
@pmn4
pmn4 / insert_record_with_valid_unique_token.sql
Last active October 12, 2020 13:15
Create new Records with Unique Randomized Token using a Single Query
# Insert into table with a unique token column without a loop
# using `LEFT(UUID(), 8)` as the unique string generator for simplicity,
# feel free to use whatever method you'd like, including generating those
# in memory and putting raw strings into your query
INSERT INTO table(column1, column2, token_column)
SELECT "column1_value", "column2_value", token FROM (
# create a derived table containing five (feel free to increase)
# potential unique strings
SELECT LEFT(UUID(), 8) as token
@pmn4
pmn4 / most_recent_by.rb
Last active April 28, 2020 18:28
ActiveRecord: Max By with Group
module MostRecentBy
def self.included(klass)
klass.scope :most_recent_by, ->(group_by_col, max_by_col) {
from(
<<~SQL
(
SELECT #{table_name}.*
FROM #{table_name} JOIN (
SELECT #{group_by_col}, MAX(#{max_by_col}) AS #{max_by_col}
FROM #{table_name}
module InflateHasMany
# what #inflate is to `belongs_to` associations, #inflate_has_many is
# to `has_many` associations
# see: https://gist.github.com/pmn4/eb497edad63065304383bdfcf8d60b47
#
# returns a flatmap of all resources
def inflate_has_many(models, foreign_key, key = self.name.underscore.pluralize.to_sym, resources: nil)
models = Array(models)
# determine the set of unique, non-nil model ids
@pmn4
pmn4 / inflate_belongs_to.rb
Last active April 4, 2020 00:51
Inflate an array of models with a foreign key relationship in a single query (relationship: Belongs To)
module InflateBelongsTo
# when you have an array of models, but want to include (or even map)
# an associated resource, this method puts together a single query to
# fetch the data, then appends it to the model, cutting down on total
# database calls.
# this does the exact same work as eager loading when you first query
# for a set of models, but is especially useful if you the original
# query is uneditable (not written by you) or you wish to get results
# conditionally (i.e., you only want _some_ associations loaded)
#
@pmn4
pmn4 / SimpleSchema to GraphQL Schema Definition.js
Last active April 3, 2019 14:19
Copy/Paste/Execute in your Node REPL (or `meteor shell`) to create a method for converting an instance of `SimpleSchema` to a Graph QL Schema definition
.editor
var os = require("os");
function schemaToGraphQl(schema) {
const definitions = Object.keys(schema._schema).map((name) => {
const s = schema._schema[name];
return [
s.label && ` "${s.label}"`,
` ${name}: ${s.type.definitions[0].type.name}` // brittle
].filter(s => s).join(os.EOL)