Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migration #486

Merged
merged 48 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
3e2f15a
update lint, use kitbook lz-string
jacob-8 Aug 29, 2024
e4b26d1
update optimizedDeps
jacob-8 Aug 29, 2024
70df9c9
update vite and vitest packages
jacob-8 Aug 29, 2024
1c62b6f
switch orama to main route
jacob-8 Aug 29, 2024
cbf6ee0
fix table header being over-displayed by ear icons and image icons
jacob-8 Aug 29, 2024
b3c2c45
improve entry modal
jacob-8 Aug 29, 2024
e089a63
fix print view issue
jacob-8 Aug 29, 2024
9776171
remove algolia
jacob-8 Aug 29, 2024
99c1a98
remove entries-algolia folder
jacob-8 Aug 29, 2024
d17edf6
add supabase notes on how to seed local db from production
jacob-8 Aug 30, 2024
73cb1de
add mixed option
jacob-8 Aug 30, 2024
02d0e1b
Merge branch 'main' into orama-priority
jacob-8 Sep 12, 2024
c45fb80
lint changes
jacob-8 Sep 12, 2024
27746d1
move generated types; add dialects table, prepare for migration tests
jacob-8 Sep 13, 2024
031daa6
merge Supabase types via script, entry, sense, dialect upsert functions
jacob-8 Oct 2, 2024
ae40fc1
solve type and shape issues
jacob-8 Oct 2, 2024
d8ae65b
get db tests running
jacob-8 Oct 2, 2024
3efc21a
connect photos and videos to senses
jacob-8 Oct 3, 2024
7699e56
connect dialect_ids
jacob-8 Oct 3, 2024
76f36f2
connect speaker_ids to audio and videos
jacob-8 Oct 3, 2024
871e2bb
speakers
jacob-8 Oct 5, 2024
e689ce9
combine sql files
jacob-8 Oct 5, 2024
de93d43
use speakers view
jacob-8 Oct 5, 2024
47ba5db
create hourly refreshing materialized entries view
jacob-8 Oct 5, 2024
29c5252
keep photos, videos, speakers, dialects (many-many items) out of entr…
jacob-8 Oct 7, 2024
39b0c74
finish backend prep
jacob-8 Oct 9, 2024
cc861ed
add in batching ability
jacob-8 Oct 9, 2024
1c3a42d
logging and user id improvements
jacob-8 Oct 10, 2024
d106b6e
cached data via passing entire db function
jacob-8 Oct 12, 2024
7c295db
finish data loading part of cached-data-store
jacob-8 Oct 12, 2024
ae521ee
progress
jacob-8 Oct 19, 2024
155d190
Merge branch 'main' into orama-priority
jacob-8 Oct 21, 2024
0da8257
remove functions from workspace install
jacob-8 Oct 21, 2024
dae8aa8
finish getting views working and edits running
jacob-8 Oct 21, 2024
c76fd21
get unit tests passing
jacob-8 Oct 21, 2024
f7684d2
get db tests passing
jacob-8 Oct 21, 2024
d7db84b
Merge branch 'main' into orama-priority
jacob-8 Oct 21, 2024
7dfceb1
Merge branch 'orama-priority' of github.com:livingtongues/living-dict…
jacob-8 Oct 21, 2024
571dc9c
comment out variants, export files, and tests that need updated still
jacob-8 Oct 21, 2024
8290cd5
don't fail on empty test file
jacob-8 Oct 21, 2024
a1d080a
run-through prep
jacob-8 Oct 22, 2024
42dd66c
run migration
jacob-8 Oct 22, 2024
313fcb1
small changes
jacob-8 Oct 23, 2024
56588e7
final-preps
jacob-8 Oct 23, 2024
6bb1134
progress
jacob-8 Oct 23, 2024
df14085
use rpc for entries view
jacob-8 Oct 24, 2024
04753f8
fix db test
jacob-8 Oct 24, 2024
9d5a5e3
handle entry store errors better
jacob-8 Oct 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .firebaserc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"projects": {
"default": "talking-dictionaries-dev",
"production": "talking-dictionaries-alpha"
"production": "talking-dictionaries-alpha",
}
}
2 changes: 1 addition & 1 deletion .github/workflows/lighthouse-audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
with:
urls: |
${{ github.event.deployment_status.target_url }}
${{ github.event.deployment_status.target_url }}/achi/entries/list
${{ github.event.deployment_status.target_url }}/achi/entries
${{ github.event.deployment_status.target_url }}/jaRhn6MAZim4Blvr1iEv/entry/yt9ja7ymh9xgba5i
# configPath: './.github/lighthouserc.json' # https://github.com/GoogleChrome/lighthouse-ci/blob/main/docs/getting-started.md https://github.com/GoogleChrome/lighthouse-ci/blob/main/docs/configuration.md#assert
uploadArtifacts: true
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ jobs:

- uses: pnpm/action-setup@v2
with:
version: 8.6.0
version: 9.6.0

- uses: actions/setup-node@v3
with:
node-version: 18
node-version: 20
cache: pnpm

- run: pnpm install
Expand Down
7 changes: 4 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
},
// Silence stylistic rules in IDE, but still auto fix them
"eslint.rules.customizations": [
{ "rule": "@stylistic/*", "severity": "off" },
{ "rule": "style*", "severity": "off" },
{ "rule": "*indent", "severity": "off" },
{ "rule": "style/*", "severity": "off" },
{ "rule": "format/*", "severity": "off" },
{ "rule": "*-indent", "severity": "off" },
{ "rule": "*-spacing", "severity": "off" },
{ "rule": "*-spaces", "severity": "off" },
{ "rule": "*-order", "severity": "off" },
Expand All @@ -47,6 +47,7 @@
{ "rule": "import/order", "severity": "off" },
{ "rule": "sort-imports", "severity": "off" },
{ "rule": "ts/no-empty-function", "severity": "off" },
{ "rule": "svelte/indent", "severity": "off" },
],
"eslint.validate": [
"javascript",
Expand Down
18 changes: 4 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,12 @@ A mobile-first community focused dictionary-building web app built by [Living To
[<img src="https://img.shields.io/badge/Svelte-4-orange.svg"></a>](https://svelte.dev/)
[<img src="https://img.shields.io/badge/SvelteKit-2-orange.svg"></a>](https://kit.svelte.dev/)
[<img src="https://img.shields.io/badge/UnoCSS-Svelte_Scoped-blue.svg"></a>](https://unocss.dev/integrations/svelte-scoped)
[<img src="https://img.shields.io/badge/Supabase-teal.svg"></a>](https://firebase.google.com/)
[<img src="https://img.shields.io/badge/Firebase_(deprecated)-9-orange.svg"></a>](https://firebase.google.com/)
[<img src="https://img.shields.io/badge/Supabase-Auth_Database-teal.svg"></a>](https://firebase.google.com/)
[<img src="https://img.shields.io/badge/Vercel-SSR-black.svg"></a>](https://vercel.com/)
[<img src="https://img.shields.io/badge/Algolia-Instantsearch.js-blue.svg"></a>](https://www.algolia.com/)

Firebase is used for:

- Authentication
- Cloud Firestore
- Storage

These functions are being transitioned to Supabase with the exception of Storage, images will remain in GCP. Supabase may support this directly in the future.
[<img src="https://img.shields.io/badge/Orama-Search-purple.svg"></a>](https://www.orama.com/)
[<img src="https://img.shields.io/badge/GCP-Storage-blue.svg"></a>](https://cloud.google.com/storage)

## Contributing

- Choose an already approved task from the [Development Roadmap](https://github.com/jwrunner/Living-Dictionaries/projects/1) or [create an issue](https://github.com/jwrunner/Living-Dictionaries/issues) to propose a new feature (please await discussion before creating a pull request).
- Choose an already approved task from the [Development Roadmap](https://github.com/jwrunner/Living-Dictionaries/projects/1) or [create an issue](https://github.com/jwrunner/Living-Dictionaries/issues) to propose a new feature (please await discussion before creating a pull request).
- Read [CONTRIBUTING](https://livingdictionaries.app/kitbook/docs/CONTRIBUTING) and then move on to all the other pages under "Docs" in the Kitbook to understand how to set up a dev environment, repo conventions, commit conventions, and more.


20 changes: 11 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"type": "module",
"scripts": {
"dev": "pnpm --filter=site dev",
"prod": "pnpm --filter=site prod",
"mixed": "pnpm --filter=site mixed",
"dev:open": "pnpm --filter=site dev --open",
"build": "pnpm --filter=site build",
"preview": "pnpm --filter=site preview",
Expand All @@ -19,22 +21,22 @@
"lint:inspect": "npx @eslint/config-inspector",
"lint:inspect-future": "eslint --inspect-config",
"reset-db": "pnpm --filter=site reset-db",
"generate-types": "supabase gen types typescript --local --schema public > packages/site/src/lib/supabase/generated.types.ts",
"generate-types": "supabase gen types typescript --local --schema public > packages/types/supabase/generated.types.ts",
"check-packages": "pnpm update --interactive --recursive --latest"
},
"devDependencies": {
"@antfu/eslint-config": "^2.12.1",
"@typescript-eslint/eslint-plugin": "6.21.0",
"eslint": "^8.56.0",
"eslint-plugin-svelte": "^2.33.2",
"@antfu/eslint-config": "^2.27.3",
"@typescript-eslint/eslint-plugin": "8.3.0",
"eslint": "^9.9.1",
"eslint-plugin-svelte": "^2.43.0",
"eslint-plugin-svelte-stylistic": "^0.0.4",
"lint-staged": "^13.2.2",
"simple-git-hooks": "^2.11.0",
"start-server-and-test": "^2.0.3",
"lint-staged": "^15.2.9",
"simple-git-hooks": "^2.11.1",
"start-server-and-test": "^2.0.5",
"supabase": "^1.145.4",
"svelte": "^4.2.12",
"typescript": "~5.1.6",
"vitest": "^1.4.0"
"vitest": "^2.1.3"
},
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"
Expand Down
2 changes: 1 addition & 1 deletion packages/functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@
"@types/node": "^18.11.18",
"node-fetch": "^2.6.7",
"typescript": "^5.1.6",
"vitest": "^1.4.0"
"vitest": "^2.0.5"
}
}
3 changes: 2 additions & 1 deletion packages/scripts/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ logs
service-account*
.env
sheets-viewer-SA.json
.env.supabase
.env.supabase
.env.production.supabase
12 changes: 2 additions & 10 deletions packages/scripts/config-firebase.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import fs from 'node:fs'
import { program } from 'commander'
import { cert, initializeApp } from 'firebase-admin/app'
import { FieldValue, getFirestore } from 'firebase-admin/firestore'
Expand All @@ -7,8 +6,7 @@ import { getAuth } from 'firebase-admin/auth'
// import serviceAccountDev from './service-account-dev.json';
// import serviceAccountProd from './service-account-prod.json';
import { serviceAccountDev, serviceAccountProd } from './service-accounts'

/// LOGGER///
import './record-logs'

program
// .version('0.0.1')
Expand All @@ -34,11 +32,5 @@ export const db = getFirestore()
export const timestamp = FieldValue.serverTimestamp()
export const storage = getStorage()
export const auth = getAuth()
const logFile = fs.createWriteStream(`./logs/${Date.now()}.txt`, { flags: 'w' }) // 'a' to append, 'w' to truncate the file every time the process starts.
console.log = function (data: any) {
logFile.write(`${JSON.stringify(data)}\n`)
process.stdout.write(`${JSON.stringify(data)}\n`)
}
/// END-LOGGER///

console.log(`Running on ${environment}`)
console.log(`Firebase running on ${environment}`)
68 changes: 50 additions & 18 deletions packages/scripts/config-supabase.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,63 @@
import PG from 'pg'
import { createClient } from '@supabase/supabase-js'
import type { Database } from '@living-dictionaries/site/src/lib/supabase/database.types'
import type { Database } from '@living-dictionaries/types'
import * as dotenv from 'dotenv'
import './record-logs'

dotenv.config({ path: '.env.supabase' })
// TODO: change to .env.development and .env.production
dotenv.config({ path: '.env.supabase' }) // local project variables
// dotenv.config({ path: '.env.production.supabase' }) // production project variables

export const supabase = createClient<Database>(process.env.PUBLIC_SUPABASE_API_URL, process.env.SUPABASE_SERVICE_ROLE_KEY)
export const admin_supabase = createClient<Database>(process.env.PUBLIC_SUPABASE_API_URL, process.env.SUPABASE_SERVICE_ROLE_KEY)
export const anon_supabase = createClient<Database>(process.env.PUBLIC_SUPABASE_API_URL, process.env.PUBLIC_SUPABASE_ANON_KEY)
export const jacob_ld_user_id = 'de2d3715-6337-45a3-a81a-d82c3210b2a7'

export async function executeQuery(query: string) {
const client = new PG.Client({
class DB {
private pool: PG.Pool

private config: PG.PoolConfig = {
user: 'postgres',
host: '127.0.0.1',
// host: 'db.actkqboqpzniojhgtqzw.supabase.co',
database: 'postgres',
password: 'postgres',
// password: '**',
port: 54322,
// port: 5432,
})
try {
await client.connect()
await client.query(query)
} catch (error) {
console.error('Error in connection/executing query:', error)
} finally {
await client.end().catch((error) => {
console.error('Error ending client connection:', error)
})

// user: 'postgres.actkqboqpzniojhgtqzw',
// host: 'aws-0-us-west-1.pooler.supabase.com',
// database: 'postgres',
// password: '**',
// port: 6543,

max: 10,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000,
allowExitOnIdle: false,
}

async get_db_connection(): Promise<PG.PoolClient> {
if (!this.pool) {
this.pool = new PG.Pool(this.config)
const client = await this.pool.connect()
console.info(`----> √ Postgres DB connection established! <----`)
return client
}
return this.pool.connect()
}

async execute_query(query: string): Promise<void> {
const client = await this.get_db_connection()
try {
await client.query(query)
} catch (error) {
console.error('Error executing query:', error)
throw new Error(error)
} finally {
client.release()
}
}
}

export const postgres = new DB()

const environment = 'dev'
console.log(`Supabase running on ${environment}`)
4 changes: 4 additions & 0 deletions packages/scripts/import/post-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export async function post_request<T extends Record<string, any>, ExpectedRespon
fetch?: typeof fetch
headers?: RequestInit['headers']
}): Promise<Return<ExpectedResponse>> {
console.info(data)
// for running through data without db involved
// return { data: { speaker_id: data?.speaker_id, dialect_id: data?.dialect_id }, error: null }

const fetch_to_use = options?.fetch || fetch

const response = await fetch_to_use(route, {
Expand Down
2 changes: 0 additions & 2 deletions packages/scripts/migrate-to-supabase/.gitignore

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import fs from 'node:fs'
import Chain from 'stream-chain'
import Parser from 'stream-json'
import StreamArray from 'stream-json/streamers/StreamArray'
import { admin_supabase, jacob_ld_user_id } from '../config-supabase'
import { remove_seconds_underscore } from './utils/remove-seconds-underscore'
import { convert_entry } from './convert-entries'

export async function ensure_all_current_senses_have_entry_placeholders() {
// load
const { data: senses } = await admin_supabase.from('senses')
.select('id, entry_id')
const { data: entries } = await admin_supabase.from('entries')
.select('id')

const entries_needing_added = new Set<string>()
for (const sense of senses) {
if (!entries.find(entry => entry.id === sense.entry_id)) {
console.log(`need placeholder entry for sense ${sense.id}, entry ${sense.entry_id}`)
entries_needing_added.add(sense.entry_id)
}
}
console.log({ entries_to_add: entries_needing_added.size })

const pipeline = Chain.chain([
fs.createReadStream('./migrate-to-supabase/firestore-data/firestore-entries.json'),
Parser.parser(),
StreamArray.streamArray(),
])

try {
for await (const { value: fb_entry } of pipeline) {
if (entries_needing_added.has(fb_entry.id)) {
const corrected_fb_entry = remove_seconds_underscore(fb_entry)
const [, supa_data] = convert_entry(JSON.parse(JSON.stringify(corrected_fb_entry)))
const { entry } = supa_data

const { data: dictionary } = await admin_supabase.from('dictionaries').select().eq('id', entry.dictionary_id).single()
if (!dictionary) {
console.log({ creating_dict: entry.dictionary_id })
const { error } = await admin_supabase.from('dictionaries').insert({
created_by: jacob_ld_user_id,
updated_by: jacob_ld_user_id,
id: entry.dictionary_id,
name: 'CHANGE',
})
if (error) {
console.info({ entry })
throw new Error(error.message)
}
}

const insert = {
id: entry.id,
dictionary_id: entry.dictionary_id,
lexeme: {},
created_by: entry.created_by,
created_at: entry.created_at,
updated_by: entry.updated_by,
updated_at: entry.updated_at,
}
console.log({ insert })
await admin_supabase.from('entries').insert(insert)
}
}
console.log('finished')
} catch (err) {
console.error(err)
pipeline.destroy()
pipeline.input.destroy()
}
}
12 changes: 5 additions & 7 deletions packages/scripts/migrate-to-supabase/auth.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import type { UserRecord } from 'firebase-admin/auth'
import { auth } from '../config-firebase'
import { executeQuery } from '../config-supabase'
import { postgres } from '../config-supabase'
import { write_users_insert } from './write-users-insert'

migrate_users()

async function migrate_users() {
export async function migrate_users() {
const users = await get_users()
console.log({ total_users: users.length })
for (const user of users)
Expand All @@ -14,12 +12,12 @@ async function migrate_users() {
console.log(user.toJSON())
const sql = write_users_insert(users)
console.log(sql)
await executeQuery(sql)
await postgres.execute_query(sql)
}

const BATCH_SIZE = 1000

async function get_users(): Promise<UserRecord[]> {
export async function get_users(): Promise<UserRecord[]> {
try {
const listUsersResult = await auth.listUsers()
const { users, pageToken } = listUsersResult
Expand All @@ -29,7 +27,7 @@ async function get_users(): Promise<UserRecord[]> {
if (pageToken) {
const listUsersResult = await auth.listUsers(BATCH_SIZE, pageToken)
const { users: nextUsers } = listUsersResult
// const nextUsers = await get_users(pageToken)
// const nextUsers = await get_users(pageToken) // had issue
return [...users, ...nextUsers]
}

Expand Down
Loading
Loading