Skip to content

Commit

Permalink
feat(api): lazy load handlers (#700)
Browse files Browse the repository at this point in the history
# Pull Request type



Please check the type of change your PR introduces:

- [ ] Bugfix
- [x] Feature
- [ ] Code style update (formatting, renaming)
- [x] Refactoring (no functional changes, no API changes)
- [ ] Build-related changes
- [ ] Documentation content changes
- [ ] Other (please describe):

## What is the current behavior?



Issue Number: 
- IN-911
- IN-912

## What is the new behavior?



-
-
-

## Does this introduce a breaking change?

- [ ] Yes
- [ ] No



## Other information




PR-URL: #700
Co-authored-by: Joe Karow <[email protected]>
Co-authored-by: InReach [Automated User] <[email protected]>
  • Loading branch information
3 people authored Aug 14, 2023
2 parents 34bbb77 + 620558b commit 22d3dd3
Show file tree
Hide file tree
Showing 364 changed files with 10,419 additions and 6,833 deletions.
15 changes: 9 additions & 6 deletions apps/app/src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { Footer } from '@weareinreach/ui/components/sections/Footer'
import { Navbar } from '@weareinreach/ui/components/sections/Navbar'
import { useScreenSize } from '@weareinreach/ui/hooks/useScreenSize'
import { BodyGrid } from '@weareinreach/ui/layouts/BodyGrid'
import { GoogleMapsProvider } from '@weareinreach/ui/providers/GoogleMaps'
import { SearchStateProvider } from '@weareinreach/ui/providers/SearchState'
import { appCache, appTheme } from '@weareinreach/ui/theme'
import { api } from '~app/utils/api'
Expand Down Expand Up @@ -88,12 +89,14 @@ const MyApp = (appProps: AppPropsWithGridSwitch) => {
>
<ModalsProvider>
<SearchStateProvider>
<PageLoadProgress />
<Navbar />
{PageContent}
{(isMobile || isTablet) && <Space h={80} />}
<Footer />
<Notifications transitionDuration={500} />
<GoogleMapsProvider>
<PageLoadProgress />
<Navbar />
{PageContent}
{(isMobile || isTablet) && <Space h={80} />}
<Footer />
<Notifications transitionDuration={500} />
</GoogleMapsProvider>
</SearchStateProvider>
</ModalsProvider>
<ReactQueryDevtools initialIsOpen={false} toggleButtonProps={{ style: { zIndex: 99998 } }} />
Expand Down
4 changes: 2 additions & 2 deletions apps/app/src/pages/api/i18n/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { context, trace } from '@opentelemetry/api'
import { type NextApiRequest, type NextApiResponse } from 'next'
import { z } from 'zod'

import { createSubLog } from '@weareinreach/util/logger'
import { createLoggerInstance } from '@weareinreach/util/logger'
import { crowdinOpts } from '~app/data/crowdinOta'
import { crowdinDistTimestamp, fetchCrowdinDbKey, fetchCrowdinFile } from '~app/utils/crowdin'
import { redisReadCache, redisWriteCache } from '~app/utils/vercel-kv'
Expand All @@ -14,7 +14,7 @@ const QuerySchema = z.object({
ns: z.string(),
})
const tracer = trace.getTracer('inreach-app')
const log = createSubLog('i18n Loader')
const log = createLoggerInstance('i18n Loader')

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const query = QuerySchema.parse(req.query)
Expand Down
4 changes: 2 additions & 2 deletions apps/app/src/pages/api/trpc/[trpc].ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { createNextApiHandler } from '@trpc/server/adapters/next'

import { appRouter, createContext } from '@weareinreach/api'
import { createSubLog } from '@weareinreach/util/logger'
import { createLoggerInstance } from '@weareinreach/util/logger'

const log = createSubLog('tRPC')
const log = createLoggerInstance('tRPC')

/* Creating a handler for the tRPC endpoint. */
export default createNextApiHandler({
Expand Down
2 changes: 1 addition & 1 deletion apps/app/src/pages/org/[slug]/[orgLocationId]/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const OrgLocationPage: NextPage = () => {
const { data: orgData, status: orgDataStatus } = api.organization.getBySlug.useQuery(query, {
enabled: router.isReady,
})
const { data, status } = api.location.getById.useQuery({ id: orgLocationId })
const { data, status } = api.location.forLocationPage.useQuery({ id: orgLocationId })
const { data: isSaved } = api.savedList.isSaved.useQuery(orgData?.id as string, {
enabled: orgDataStatus === 'success' && Boolean(orgData?.id),
})
Expand Down
12 changes: 7 additions & 5 deletions apps/app/src/pages/org/[slug]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,11 @@ const useStyles = createStyles((theme) => ({
const OrganizationPage = ({ slug }: InferGetStaticPropsType<typeof getStaticProps>) => {
const router = useRouter<'/org/[slug]'>()
// const { query } = router
const { t, i18n } = useTranslation(['common', 'services', 'attribute', 'phone-type', slug], {
bindI18n: 'languageChanged loaded',
})
const {
t,
i18n,
ready: i18nReady,
} = useTranslation(['common', 'services', 'attribute', 'phone-type', slug])
const [activeTab, setActiveTab] = useState<string | null>('services')
const [loading, setLoading] = useState(true)
const { data, status } = api.organization.forOrgPage.useQuery({ slug }, { enabled: !!slug })
Expand All @@ -84,11 +86,11 @@ const OrganizationPage = ({ slug }: InferGetStaticPropsType<typeof getStaticProp
const reviewsRef = useRef<HTMLDivElement>(null)

useEffect(() => {
if (data && status === 'success') {
if (i18nReady && data && status === 'success') {
setLoading(false)
if (data.locations?.length > 1) setActiveTab('locations')
}
}, [data, status])
}, [data, status, i18nReady])

useEffect(() => {
data?.id &&
Expand Down
4 changes: 2 additions & 2 deletions apps/app/src/utils/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { devtoolsLink } from 'trpc-client-devtools-link'
import { type AppRouter } from '@weareinreach/api'
import { transformer } from '@weareinreach/api/lib/transformer'
import { getEnv } from '@weareinreach/env'
import { createSubLog } from '@weareinreach/util/logger'
import { createLoggerInstance } from '@weareinreach/util/logger'

const log = createSubLog('tRPC')
const log = createLoggerInstance('tRPC')
const getBaseUrl = () => {
if (typeof window !== 'undefined') return '' // browser should use relative url
if (getEnv('VERCEL_URL')) return `https://${getEnv('VERCEL_URL')}` // SSR should use vercel url
Expand Down
10 changes: 7 additions & 3 deletions apps/app/src/utils/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { type Namespace } from 'i18next'
// eslint-disable-next-line no-restricted-imports
/* eslint-disable no-restricted-imports */
import { type DefaultNamespace } from 'i18next'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { type LiteralUnion } from 'type-fest'

import { type Namespaces } from '@weareinreach/db/generated/namespaces'

import i18nextConfig from '../../next-i18next.config.mjs'

// type ArrayElementOrSelf<T> = T extends Array<infer U> ? U[] : T[]

type Namespace = LiteralUnion<Namespaces, string>
type NamespaceSSR = string | string[] | undefined
export const getServerSideTranslations = async (
locale = 'en',
namespacesRequired?: Namespace,
namespacesRequired: Namespace | Namespace[] = i18nextConfig.defaultNS as DefaultNamespace,
extraLocales?: string[] | false
) => serverSideTranslations(locale, namespacesRequired as NamespaceSSR, i18nextConfig, extraLocales)

Expand Down
4 changes: 2 additions & 2 deletions apps/app/src/utils/vercel-kv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { flatten, unflatten } from 'flat'
import sizeof from 'object-sizeof'
import formatBytes from 'pretty-bytes'

import { createSubLog } from '@weareinreach/util/logger'
import { createLoggerInstance } from '@weareinreach/util/logger'

const redisTTL = 86400
const log = createSubLog('Vercel KV')
const log = createLoggerInstance('Vercel KV')
const tracer = trace.getTracer('inreach-app')

export const redisReadCache = async (namespaces: string[], lang: string, otaManifestTimestamp: number) => {
Expand Down
4 changes: 2 additions & 2 deletions packages/api/cache/slugRedirect.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { kv as redis } from '@vercel/kv'

import { createSubLog } from '@weareinreach/util/logger'
import { createLoggerInstance } from '@weareinreach/util/logger'

const log = createSubLog('Cache - Slug redirect')
const log = createLoggerInstance('Cache - Slug redirect')

export const readSlugRedirectCache = async (slug: string) => {
try {
Expand Down
4 changes: 2 additions & 2 deletions packages/api/cache/slugToOrgId.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { kv as redis } from '@vercel/kv'

import { createSubLog } from '@weareinreach/util/logger'
import { createLoggerInstance } from '@weareinreach/util/logger'

const log = createSubLog('Cache - Slug to OrgId')
const log = createLoggerInstance('Cache - Slug to OrgId')

export const readSlugCache = async (slug: string) => {
try {
Expand Down
3 changes: 3 additions & 0 deletions packages/api/google/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Client } from '@googlemaps/google-maps-services-js'

export const googleMapsApi = new Client()
9 changes: 9 additions & 0 deletions packages/api/lib/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ const orgWebsite = {
updateOrgWebsite: 'editSingleOrg',
} satisfies PermissionDefs

const reviews = {
viewUserReviews: ['viewUserReviews'],
hideUserReview: ['hideUserReview'],
unHideUserReview: ['showUserReview'],
deleteUserReview: ['deleteUserReview'],
undeleteUserReview: ['undeleteUserReview'],
} satisfies PermissionDefs

const system = {
createPermission: 'adminPermissions',
getDetails: ['dataPortalBasic'],
Expand All @@ -67,6 +75,7 @@ const permissions = {
...orgService,
...orgSocialMedia,
...orgWebsite,
...reviews,
...system,
} satisfies PermissionDefs

Expand Down
1 change: 1 addition & 0 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
},
"devDependencies": {
"@types/eslint": "8.44.2",
"@types/google.maps": "3.53.6",
"@types/luxon": "3.3.1",
"@types/node": "18.17.4",
"@types/prettier": "2.7.3",
Expand Down
30 changes: 26 additions & 4 deletions packages/api/router/attribute/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
import { mergeRouters } from '~api/lib/trpc'
import { defineRouter, publicProcedure, staffProcedure } from '~api/lib/trpc'

// import { mutations } from './mutations'
import { queries } from './queries'
import * as schema from './schemas'

export const attributeRouter = mergeRouters(queries /*mutations*/)
type AttributeQueryHandlerCache = {
getFilterOptions: typeof import('./query.getFilterOptions.handler').getFilterOptions
getOne: typeof import('./query.getOne.handler').getOne
}

const HandlerCache: Partial<AttributeQueryHandlerCache> = {}
export const attributeRouter = defineRouter({
getFilterOptions: publicProcedure.query(async ({ ctx }) => {
if (!HandlerCache.getFilterOptions)
HandlerCache.getFilterOptions = await import('./query.getFilterOptions.handler').then(
(mod) => mod.getFilterOptions
)

if (!HandlerCache.getFilterOptions) throw new Error('Failed to load handler')
return HandlerCache.getFilterOptions()
}),
getOne: staffProcedure.input(schema.ZGetOneSchema).query(async ({ ctx, input }) => {
if (!HandlerCache.getOne)
HandlerCache.getOne = await import('./query.getOne.handler').then((mod) => mod.getOne)

if (!HandlerCache.getOne) throw new Error('Failed to load handler')
return HandlerCache.getOne({ ctx, input })
}),
})
52 changes: 0 additions & 52 deletions packages/api/router/attribute/queries.ts

This file was deleted.

25 changes: 25 additions & 0 deletions packages/api/router/attribute/query.getFilterOptions.handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { prisma } from '@weareinreach/db'

export const getFilterOptions = async () => {
const result = await prisma.attribute.findMany({
where: {
AND: {
filterType: {
not: null,
},
active: true,
},
},
select: {
id: true,
tsKey: true,
tsNs: true,
filterType: true,
},
orderBy: {
tsKey: 'asc',
},
})

return result
}
26 changes: 26 additions & 0 deletions packages/api/router/attribute/query.getOne.handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { prisma } from '@weareinreach/db'
import { type TRPCHandlerParams } from '~api/types/handler'

import { type TGetOneSchema } from './query.getOne.schema'

export const getOne = async ({ input }: TRPCHandlerParams<TGetOneSchema>) => {
const result = await prisma.attribute.findUniqueOrThrow({
where: input,
select: {
id: true,
tag: true,
tsKey: true,
tsNs: true,
icon: true,
iconBg: true,
active: true,
requireBoolean: true,
requireData: true,
requireDataSchema: { select: { definition: true } },
requireGeo: true,
requireLanguage: true,
requireText: true,
},
})
return result
}
4 changes: 4 additions & 0 deletions packages/api/router/attribute/query.getOne.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { z } from 'zod'

export const ZGetOneSchema = z.object({ id: z.string() }).or(z.object({ tag: z.string() }))
export type TGetOneSchema = z.infer<typeof ZGetOneSchema>
3 changes: 3 additions & 0 deletions packages/api/router/attribute/schemas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// codegen:start {preset: barrel, include: ./*.schema.ts}
export * from './query.getOne.schema'
// codegen:end
Loading

0 comments on commit 22d3dd3

Please sign in to comment.