mirror of
https://github.com/dsprenkels/backpack.git
synced 2026-05-04 03:00:05 -04:00
Use superjson
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import { configureStore, createAction, createAsyncThunk, createListenerMiddleware, createReducer } from '@reduxjs/toolkit'
|
||||
import DEFAULT_BRINGLIST_TEMPLATE from '@/lib/template'
|
||||
import { trpc } from '@/client/trpc'
|
||||
import SuperJSON from 'superjson'
|
||||
|
||||
const LOCAL_STORAGE_KEY_V1 = 'com.electricdusk.backpack.v1.state'
|
||||
const LOCAL_STORAGE_KEY_V2 = 'com.electricdusk.backpack.v2.state'
|
||||
const LOCAL_STORAGE_KEY_LATEST = LOCAL_STORAGE_KEY_V2
|
||||
|
||||
// --- Type Definitions ---
|
||||
export interface KeyValueDict<T> {
|
||||
@@ -10,8 +15,8 @@ export interface KeyValueDict<T> {
|
||||
export interface State {
|
||||
bringList: {
|
||||
bringListTemplate: string,
|
||||
tags: string[],
|
||||
checked: string[],
|
||||
tags: Set<string>,
|
||||
checked: Set<string>,
|
||||
nights: number,
|
||||
header: string,
|
||||
},
|
||||
@@ -39,8 +44,8 @@ function startingState(): State {
|
||||
return {
|
||||
bringList: {
|
||||
bringListTemplate: DEFAULT_BRINGLIST_TEMPLATE,
|
||||
tags: [],
|
||||
checked: [],
|
||||
tags: new Set(),
|
||||
checked: new Set(),
|
||||
nights: 3,
|
||||
header: '',
|
||||
},
|
||||
@@ -49,8 +54,15 @@ function startingState(): State {
|
||||
}
|
||||
|
||||
function initialState(): State {
|
||||
const stored = localStorage.getItem('com.electricdusk.backpack.v1.state')
|
||||
return (stored ? JSON.parse(stored) : startingState())
|
||||
let stored = localStorage.getItem(LOCAL_STORAGE_KEY_V2)
|
||||
if (stored) {
|
||||
return SuperJSON.parse(stored) as State
|
||||
}
|
||||
stored = localStorage.getItem(LOCAL_STORAGE_KEY_V1)
|
||||
if (stored) {
|
||||
return JSON.parse(stored) as State
|
||||
}
|
||||
return startingState()
|
||||
}
|
||||
|
||||
// --- Reducers ---
|
||||
@@ -60,20 +72,20 @@ const bringListReducer = createReducer(initialState, builder => {
|
||||
})
|
||||
.addCase(setTagEnabled, (state, action) => {
|
||||
const [tag, enabled] = action.payload
|
||||
state.bringList.tags = new Set(state.bringList.tags)
|
||||
if (enabled) {
|
||||
state.bringList.tags.push(tag)
|
||||
state.bringList.tags.sort()
|
||||
state.bringList.tags.add(tag)
|
||||
} else {
|
||||
state.bringList.tags = state.bringList.tags.filter(t => t !== tag)
|
||||
state.bringList.tags.delete(tag)
|
||||
}
|
||||
})
|
||||
.addCase(setChecked, (state, action) => {
|
||||
const [item, checked] = action.payload
|
||||
state.bringList.checked = new Set(state.bringList.checked)
|
||||
if (checked) {
|
||||
state.bringList.checked.push(item)
|
||||
state.bringList.checked.sort()
|
||||
state.bringList.checked.add(item)
|
||||
} else {
|
||||
state.bringList.checked = state.bringList.checked.filter(t => t !== item)
|
||||
state.bringList.checked.delete(item)
|
||||
}
|
||||
})
|
||||
.addCase(setNights, (state, action) => {
|
||||
@@ -98,7 +110,7 @@ localStorageMiddleware.startListening({
|
||||
predicate: (action) => action.type.startsWith('bringlist/'),
|
||||
effect: (action, api) => {
|
||||
const state = api.getState() as State
|
||||
localStorage.setItem('com.electricdusk.backpack.v1.state', JSON.stringify(state))
|
||||
localStorage.setItem(LOCAL_STORAGE_KEY_LATEST, SuperJSON.stringify(state))
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { createTRPCProxyClient, httpBatchLink } from "@trpc/client";
|
||||
import type { AppRouter } from "@/server/main";
|
||||
import type { AppRouter } from "@/server/index";
|
||||
import superjson from "superjson";
|
||||
|
||||
export const trpc = createTRPCProxyClient<AppRouter>({
|
||||
links: [
|
||||
httpBatchLink({
|
||||
transformer: superjson,
|
||||
url: '/backpack/api/hello',
|
||||
}),
|
||||
],
|
||||
|
||||
40
package-lock.json
generated
40
package-lock.json
generated
@@ -18,6 +18,7 @@
|
||||
"react-dom": "^18",
|
||||
"react-redux": "^9",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"superjson": "^2.2.2",
|
||||
"tailwindcss": "^4.0.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -3173,6 +3174,21 @@
|
||||
"node": ">=6.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/copy-anything": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz",
|
||||
"integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-what": "^4.1.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.13"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/mesqueeb"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
@@ -5020,6 +5036,18 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-what": {
|
||||
"version": "4.1.16",
|
||||
"resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz",
|
||||
"integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.13"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/mesqueeb"
|
||||
}
|
||||
},
|
||||
"node_modules/isarray": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
||||
@@ -7243,6 +7271,18 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/superjson": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz",
|
||||
"integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"copy-anything": "^3.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"react-dom": "^18",
|
||||
"react-redux": "^9",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"superjson": "^2.2.2",
|
||||
"tailwindcss": "^4.0.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -5,6 +5,7 @@ import * as trpcExpress from '@trpc/server/adapters/express'
|
||||
import { Pool, } from 'pg'
|
||||
import { autoMigrate } from '@/server/migrations'
|
||||
import { initTRPC } from '@trpc/server'
|
||||
import superjson from 'superjson'
|
||||
|
||||
// Create a PostgreSQL connection pool
|
||||
for (const envVar of ['PGUSER', 'PGPASSWORD', 'PGHOST', 'PGPORT', 'PGDATABASE']) {
|
||||
@@ -32,7 +33,9 @@ try {
|
||||
}
|
||||
|
||||
// Define tRPC router
|
||||
const t = initTRPC.create()
|
||||
const t = initTRPC.create({
|
||||
transformer: superjson,
|
||||
})
|
||||
const appRouter = t.router({
|
||||
hello: t.procedure.query(() => {
|
||||
const rand = Math.floor(Math.random() * 1000)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"sourceMap": true,
|
||||
@@ -20,6 +21,6 @@
|
||||
"isolatedModules": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["server", "lib"],
|
||||
"include": ["client", "server", "lib"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
Reference in New Issue
Block a user