Skip to content

Commit

Permalink
chore: data migration/recon (#622)
Browse files Browse the repository at this point in the history
# Pull Request type



Please check the type of change your PR introduces:

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

## What is the current behavior?



Issue Number: N/A

## What is the new behavior?



-
-
-

## Does this introduce a breaking change?

- [ ] Yes
- [ ] No



## Other information




PR-URL: #622
Co-authored-by: Joe Karow <[email protected]>
Co-authored-by: InReach [Automated User] <[email protected]>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
  • Loading branch information
4 people authored Jul 13, 2023
2 parents fe070ff + 5bb4244 commit 19b409e
Show file tree
Hide file tree
Showing 101 changed files with 6,538 additions and 347 deletions.
68 changes: 39 additions & 29 deletions apps/app/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@ const nextConfig = {
typescript: {
ignoreBuildErrors: isVercelActiveDev,
},
webpack: (config, { isServer }) => {
webpack: (config, { isServer, webpack }) => {
if (isServer) {
config.plugins = [...config.plugins, new PrismaPlugin()]
}
config.plugins.push(new webpack.DefinePlugin({ __SENTRY_DEBUG__: false }))
return config
},
}
Expand All @@ -72,36 +73,45 @@ function defineNextConfig(config) {
// loadOtel()
return withBundleAnalyzer(withRoutes()(config))
}
/**
* Wraps NextJS config with the Sentry config.
*
* @template {typeof nextConfig} T
* @param {T} nextConfig
* @returns {T}
*/
const defineSentryConfig = (nextConfig) =>
withSentryConfig(
nextConfig,
{
// For all available options, see:
// https://github.com/getsentry/sentry-webpack-plugin#options

// Suppresses source map uploading logs during build
silent: true,

org: 'weareinreach',
project: 'inreach-app',
},
{
// For all available options, see:
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/

export default withSentryConfig(
defineNextConfig(nextConfig),
{
// For all available options, see:
// https://github.com/getsentry/sentry-webpack-plugin#options

// Suppresses source map uploading logs during build
silent: true,

org: 'weareinreach',
project: 'inreach-app',
},
{
// For all available options, see:
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/

// Upload a larger set of source maps for prettier stack traces (increases build time)
widenClientFileUpload: true,
// Upload a larger set of source maps for prettier stack traces (increases build time)
widenClientFileUpload: true,

// Transpiles SDK to be compatible with IE11 (increases bundle size)
transpileClientSDK: true,
// Transpiles SDK to be compatible with IE11 (increases bundle size)
transpileClientSDK: true,

// Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)
tunnelRoute: '/monitoring',
// Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)
tunnelRoute: '/monitoring',

// Hides source maps from generated client bundles
hideSourceMaps: true,
// Hides source maps from generated client bundles
hideSourceMaps: true,

// Automatically tree-shake Sentry logger statements to reduce bundle size
disableLogger: true,
}
)
// Automatically tree-shake Sentry logger statements to reduce bundle size
disableLogger: true,
}
)
// export default defineNextConfig(nextConfig)
export default defineSentryConfig(defineNextConfig(nextConfig))
4 changes: 2 additions & 2 deletions apps/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"@opentelemetry/sdk-trace-base": "1.14.0",
"@opentelemetry/sdk-trace-node": "1.14.0",
"@opentelemetry/semantic-conventions": "1.14.0",
"@prisma/instrumentation": "4.16.2",
"@prisma/instrumentation": "5.0.0",
"@sentry/nextjs": "7.57.0",
"@tanstack/react-query": "4.29.19",
"@tanstack/react-table": "8.9.3",
Expand Down Expand Up @@ -107,7 +107,7 @@
},
"devDependencies": {
"@playwright/test": "1.35.1",
"@prisma/nextjs-monorepo-workaround-plugin": "4.16.2",
"@prisma/nextjs-monorepo-workaround-plugin": "5.0.0",
"@tanstack/react-query-devtools": "4.29.19",
"@tanstack/react-table-devtools": "8.7.6",
"@total-typescript/ts-reset": "0.4.2",
Expand Down
2 changes: 2 additions & 0 deletions apps/app/sentry.server.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ Sentry.init({

// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: false,
// eslint-disable-next-line node/no-process-env
enabled: process.env.NODE_ENV === 'production',
})
2 changes: 1 addition & 1 deletion apps/app/src/pages/api/trpc/[trpc].ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default createNextApiHandler({
responseMeta(opts) {
const { ctx, errors, type } = opts

const shouldSkip = ctx?.skipCache ?? true
const shouldSkip = ctx?.skipCache ?? false
const allOk = errors.length === 0
const isQuery = type === 'query'

Expand Down
60 changes: 41 additions & 19 deletions apps/app/src/pages/org/[slug]/[orgLocationId]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { createStyles, Divider, Grid, Skeleton, Stack, Tabs, useMantineTheme } from '@mantine/core'
import { useMediaQuery } from '@mantine/hooks'
// import compact from 'just-compact'
import { type GetStaticPaths, type GetStaticProps, type NextPage } from 'next'
import { type GetStaticPaths, type GetStaticPropsContext, type NextPage } from 'next'
import Head from 'next/head'
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
import { type RoutedQuery } from 'nextjs-routes'
import { useEffect, useRef, useState } from 'react'
import { z } from 'zod'

Expand Down Expand Up @@ -181,32 +182,53 @@ export const getStaticPaths: GetStaticPaths = async () => {
fallback: true,
}
}
export const getStaticProps: GetStaticProps = async ({ locale, params }) => {
export const getStaticProps = async ({
locale,
params,
}: GetStaticPropsContext<RoutedQuery<'/org/[slug]/[orgLocationId]'>>) => {
const urlParams = z.object({ slug: z.string(), orgLocationId: z.string() }).safeParse(params)
if (!urlParams.success) return { notFound: true }
const { slug, orgLocationId } = urlParams.data

const ssg = await trpcServerClient({ session: null })
try {
const redirect = await ssg.organization.slugRedirect.fetch(slug)
if (redirect?.redirectTo) {
return {
redirect: {
permanent: true,
destination: `/org/${redirect.redirectTo}/${orgLocationId}`,
},
}
}

const orgId = await ssg.organization.getIdFromSlug.fetch({ slug })
if (!orgId?.id) return { notFound: true }
const orgId = await ssg.organization.getIdFromSlug.fetch({ slug })
if (!orgId?.id) return { notFound: true }

const [i18n] = await Promise.allSettled([
getServerSideTranslations(locale, ['common', 'services', 'attribute', 'phone-type', orgId.id]),
ssg.organization.getBySlug.prefetch({ slug }),
// ssg.organization.getIdFromSlug.prefetch({ slug }),
ssg.location.forLocationPage.prefetch({ id: orgLocationId }),
ssg.organization.forLocationPage.prefetch({ slug }),
])
const props = {
trpcState: ssg.dehydrate(),
// ...(await getServerSideTranslations(locale, ['common', 'services', 'attribute', 'phone-type', slug])),
...(i18n.status === 'fulfilled' ? i18n.value : {}),
}
const [i18n] = await Promise.allSettled([
getServerSideTranslations(locale, ['common', 'services', 'attribute', 'phone-type', orgId.id]),
ssg.organization.getBySlug.prefetch({ slug }),
// ssg.organization.getIdFromSlug.prefetch({ slug }),
ssg.location.forLocationPage.prefetch({ id: orgLocationId }),
ssg.organization.forLocationPage.prefetch({ slug }),
])
const props = {
trpcState: ssg.dehydrate(),
// ...(await getServerSideTranslations(locale, ['common', 'services', 'attribute', 'phone-type', slug])),
...(i18n.status === 'fulfilled' ? i18n.value : {}),
}

return {
props,
revalidate: 60 * 30, // 30 minutes
return {
props,
revalidate: 60 * 30, // 30 minutes
}
} catch (error) {
const TRPCError = (await import('@trpc/server')).TRPCError
if (error instanceof TRPCError) {
if (error.code === 'NOT_FOUND') {
return { notFound: true }
}
}
}
}

Expand Down
81 changes: 49 additions & 32 deletions apps/app/src/pages/org/[slug]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable i18next/no-literal-string */
import { createStyles, Divider, Grid, Skeleton, Stack, Tabs, useMantineTheme } from '@mantine/core'
import { useElementSize, useMediaQuery } from '@mantine/hooks'
import { type GetStaticPaths, type GetStaticProps, type NextPage } from 'next'
import { type GetStaticPaths, type GetStaticPropsContext, type InferGetStaticPropsType } from 'next'
import Head from 'next/head'
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
Expand Down Expand Up @@ -57,13 +57,15 @@ const useStyles = createStyles((theme) => ({
},
}))

const OrganizationPage: NextPage = () => {
const { t, i18n } = useTranslation()
const OrganizationPage = ({ slug }: InferGetStaticPropsType<typeof getStaticProps>) => {
const router = useRouter<'/org/[slug]'>()
const { query } = router
// const { query } = router
const { t, i18n } = useTranslation(['common', 'services', 'attribute', 'phone-type', slug], {
bindI18n: 'languageChanged loaded',
})
const [activeTab, setActiveTab] = useState<string | null>('services')
const [loading, setLoading] = useState(true)
const { data, status } = api.organization.forOrgPage.useQuery(query)
const { data, status } = api.organization.forOrgPage.useQuery({ slug }, { enabled: !!slug })
const { data: hasRemote } = api.service.forServiceInfoCard.useQuery(
{ parentId: data?.id ?? '', remoteOnly: true },
{
Expand All @@ -81,6 +83,7 @@ const OrganizationPage: NextPage = () => {
const photosRef = useRef<HTMLDivElement>(null)
const reviewsRef = useRef<HTMLDivElement>(null)

console.log('fallback?', router.isFallback)
useEffect(() => {
if (data && status === 'success') {
setLoading(false)
Expand All @@ -89,20 +92,14 @@ const OrganizationPage: NextPage = () => {
}, [data, status])

useEffect(() => {
if (query.slug)
i18n.reloadResources(i18n.resolvedLanguage, [
'common',
'services',
'attribute',
'phone-type',
query.slug,
])
slug &&
i18n.reloadResources(i18n.resolvedLanguage, ['common', 'services', 'attribute', 'phone-type', slug])
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

if (loading || !data || router.isFallback) return <LoadingState />

const { userLists, attributes, description, slug, reviews, locations, isClaimed, id: organizationId } = data
const { userLists, attributes, description, reviews, locations, isClaimed, id: organizationId } = data

const body =
locations?.length === 1 ? (
Expand Down Expand Up @@ -246,33 +243,53 @@ export const getStaticPaths: GetStaticPaths = async () => {
// }
}

export const getStaticProps: GetStaticProps<Record<string, unknown>, RoutedQuery<'/org/[slug]'>> = async ({
export const getStaticProps = async ({
locale,
params,
}) => {
}: GetStaticPropsContext<RoutedQuery<'/org/[slug]'>>) => {
if (!params) return { notFound: true }
const { slug } = params

const ssg = await trpcServerClient({ session: null })
const orgId = await ssg.organization.getIdFromSlug.fetch({ slug })
if (!orgId?.id) return { notFound: true }
try {
const redirect = await ssg.organization.slugRedirect.fetch(slug)
if (redirect?.redirectTo) {
return {
redirect: {
permanent: true,
destination: `/org/${redirect.redirectTo}`,
},
}
}

const [i18n] = await Promise.allSettled([
getServerSideTranslations(locale, ['common', 'services', 'attribute', 'phone-type', orgId.id]),
ssg.organization.forOrgPage.prefetch({ slug }),
])
// await ssg.organization.getBySlug.prefetch({ slug })
const orgId = await ssg.organization.getIdFromSlug.fetch({ slug })
// if (!orgId) return { notFound: true, props: {} }

const props = {
trpcState: ssg.dehydrate(),
organizationId: orgId.id,
// ...(await getServerSideTranslations(locale, ['common', 'services', 'attribute', 'phone-type', slug])),
...(i18n.status === 'fulfilled' ? i18n.value : {}),
}
const [i18n] = await Promise.allSettled([
orgId &&
getServerSideTranslations(locale, ['common', 'services', 'attribute', 'phone-type', orgId?.id]),
ssg.organization.forOrgPage.prefetch({ slug }),
])
// await ssg.organization.getBySlug.prefetch({ slug })

return {
props,
revalidate: 60 * 30, // 30 minutes
const props = {
trpcState: ssg.dehydrate(),
organizationId: orgId?.id,
slug,
...(i18n.status === 'fulfilled' ? i18n.value : {}),
}

return {
props,
revalidate: 60 * 30, // 30 minutes
}
} catch (error) {
const TRPCError = (await import('@trpc/server')).TRPCError
if (error instanceof TRPCError) {
if (error.code === 'NOT_FOUND') {
return { notFound: true }
}
}
}
}

Expand Down
30 changes: 30 additions & 0 deletions packages/api/cache/slugRedirect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { kv as redis } from '@vercel/kv'
import { Logger } from 'tslog'

const log = new Logger({ name: 'Cache - Slug redirect' })

export const readSlugRedirectCache = async (slug: string) => {
try {
if ((await redis.ping()) !== 'PONG') {
log.warn('Skipping cache read - Redis client not connected')
return null
}
const redirectedSlug = await redis.hget<string>('slugRedirect', slug)
return redirectedSlug
} catch (err) {
log.error(err)
return null
}
}

export const writeSlugRedirectCache = async (slug: string, redirectTo: string) => {
try {
if ((await redis.ping()) !== 'PONG') {
log.warn('Skipping cache write - Redis client not connected')
return
}
await redis.hset('slugRedirect', { [slug]: redirectTo })
} catch (err) {
log.error(err)
}
}
2 changes: 1 addition & 1 deletion packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"next": "13.4.9",
"p-queue": "7.3.4",
"prettier": "2.8.8",
"prisma": "4.16.2",
"prisma": "5.0.0",
"trpc-client-devtools-link": "0.2.1-next",
"trpc-panel": "1.3.4",
"type-fest": "3.12.0",
Expand Down
Loading

0 comments on commit 19b409e

Please sign in to comment.