Skip to content

Instantly share code, notes, and snippets.

View PaulieScanlon's full-sized avatar

Paul Scanlon PaulieScanlon

View GitHub Profile
@PaulieScanlon
PaulieScanlon / google-spreadsheet.ts
Created June 16, 2024 14:29
Google Sheet service
// ./services/google-spreadsheet.ts
import { GoogleSpreadsheet } from 'google-spreadsheet';
import { JWT } from 'google-auth-library';
const serviceAccountAuth = new JWT({
email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
key: process.env.GOOGLE_PRIVATE_KEY.split(String.raw`\n`).join('\n'),
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
});
@PaulieScanlon
PaulieScanlon / .shell
Created June 16, 2024 14:27
Install Google Sheets dependancies
npm install google-spreadsheet google-auth-library
@PaulieScanlon
PaulieScanlon / db-backup.yml
Last active October 18, 2024 07:01
Finished GitHub Action
name: Backup Neon | paulie-dev (us-east-1)
on:
schedule:
# Runs at midnight ET (us-east-1)
- cron: '0 0 * * *'
workflow_dispatch:
jobs:
db-backup:
@PaulieScanlon
PaulieScanlon / bucket-policy.yml
Created June 3, 2024 22:17
Update S3 Bucket policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::627917386332:role/paulie-dev-2023-github-action"
},
"Action": [
"s3:ListBucket",
@PaulieScanlon
PaulieScanlon / visitors-list-component.tsx
Created May 17, 2024 21:47
Example React component
import type { FunctionComponent } from 'react';
import type { AnalyticsType } from '../../schema';
type PickedProps = Pick<AnalyticsType, 'city' | 'country' | 'flag'>;
interface Props {
analyticsData: PickedProps[];
}
const VisitorsList: FunctionComponent<Props> = ({ analyticsData }) => {
@PaulieScanlon
PaulieScanlon / visitors-list-usage.tsx
Created May 17, 2024 21:46
Example React component usage
<VisitorsList analyticsData={results} />
@PaulieScanlon
PaulieScanlon / analytics-query.ts
Created May 17, 2024 21:45
Example analytics query
const results = await db
.select({
city: analytics.city,
country: analytics.country,
flag: analytics.flag,
})
.from(analytics)
.where(eq(analytics.country, 'US'))
.orderBy(analytics.date)
.limit(10);
@PaulieScanlon
PaulieScanlon / schema.diff
Last active May 17, 2024 21:58
Example InferSectionModel
import { pgTable, serial, varchar, timestamp, decimal} from 'drizzle-orm/pg-core';
+ import { type InferSelectModel } from 'drizzle-orm';
export const analytics = pgTable('analytics', {
id: serial('id').primaryKey(),
date: timestamp('date').notNull(),
slug: varchar('slug', { length: 255 }).notNull(),
referrer: varchar('referrer', { length: 255 }),
flag: varchar('flag', { length: 16 }),
@PaulieScanlon
PaulieScanlon / alter-schema.diff
Created May 17, 2024 21:42
Alter table example
- import { pgTable, serial, varchar } from 'drizzle-orm/pg-core';
+ import { pgTable, serial, varchar, date } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
user_id: serial('user_id').primaryKey(),
first_name: varchar('first_name', { length: 100 }),
last_name: varchar('last_name', { length: 100 }),
email: varchar('email', { length: 80 }).unique(),
role: varchar('role', { length: 20 }),
+ date_of_birth: date('date_of_birth')
@PaulieScanlon
PaulieScanlon / happiest-cities.ts
Created May 17, 2024 21:39
Happy Reactions Production Drizzle ORM query
.select({
city: analytics.city,
country: analytics.country,
flag: analytics.flag,
count: sql`COUNT(${reactions.id})`.as('count'),
})
.from(analytics)
.innerJoin(reactions, eq(analytics.slug, reactions.slug))
.where(and(eq(reactions.reaction, 'happy'), gte(analytics.date, new Date(new Date().getTime() - 30 * 24 * 60 * 60 * 1000))))
.groupBy(analytics.city, analytics.country, analytics.flag)