diff --git a/.env.example b/.env.example index 1d9858c04..5287d997d 100644 --- a/.env.example +++ b/.env.example @@ -25,5 +25,11 @@ MAXMIND_ACCOUNT_ID=xxxxxxxx # optional global override for analytics # can be used to diable analytics in development -#NEXT_PUBLIC_DISABLE_ANALYTICS=true +#DISABLE_ANALYTICS=true + +# optional manual specification for installation ID. Useful in scenarios such as +# CI/CD where the installation ID cannot be automatically determined because +# there is no database. Also useful for ensuring consistent ID between DB +# resets. +#INSTALLATION_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx diff --git a/.github/workflows/lint.yml b/.github/workflows/build.yml similarity index 93% rename from .github/workflows/lint.yml rename to .github/workflows/build.yml index 73981ae5e..6fa203abf 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/build.yml @@ -12,6 +12,11 @@ jobs: build: runs-on: ubuntu-latest + env: + SKIP_ENV_VALIDATION: true + DISABLE_ANALYTICS: true + INSTALLATION_ID: gh-action + steps: - name: Checkout code uses: actions/checkout@v3 diff --git a/.github/workflows/push.yml b/.github/workflows/docker.yml similarity index 100% rename from .github/workflows/push.yml rename to .github/workflows/docker.yml diff --git a/analytics/utils.ts b/analytics/utils.ts index 65de462f3..1bd7ca847 100644 --- a/analytics/utils.ts +++ b/analytics/utils.ts @@ -1,24 +1,19 @@ import { makeEventTracker } from '@codaco/analytics'; import { cache } from 'react'; -import { api } from '~/trpc/server'; -import { getBaseUrl } from '~/trpc/shared'; +import { env } from '~/env.mjs'; +import { prisma } from '~/utils/db'; export const getInstallationId = cache(async () => { - const installationId = await api.appSettings.getInstallationId.query(); - - if (installationId) { - return installationId; + if (env.INSTALLATION_ID) { + return env.INSTALLATION_ID; } - return 'Unknown'; -}); + // eslint-disable-next-line local-rules/require-data-mapper + const appSettings = await prisma.appSettings.findFirst(); -// eslint-disable-next-line no-process-env -const globalAnalyticsEnabled = process.env.NEXT_PUBLIC_ANALYTICS_ENABLED; + return appSettings?.installationId ?? 'Unknown'; +}); -export const trackEvent = - globalAnalyticsEnabled !== 'false' - ? makeEventTracker({ - endpoint: getBaseUrl() + '/api/analytics', - }) - : () => {}; +export const trackEvent = !env.DISABLE_ANALYTICS + ? makeEventTracker() + : () => null; diff --git a/app/api/analytics/route.ts b/app/api/analytics/route.ts index a39bc92e8..07e45d283 100644 --- a/app/api/analytics/route.ts +++ b/app/api/analytics/route.ts @@ -3,12 +3,20 @@ import { env } from '~/env.mjs'; import { createRouteHandler } from '@codaco/analytics'; import { WebServiceClient } from '@maxmind/geoip2-node'; +const maxMindClient = new WebServiceClient( + env.MAXMIND_ACCOUNT_ID, + env.MAXMIND_LICENSE_KEY, + { + host: 'geolite.info', + }, +); + +const installationId = await getInstallationId(); + const routeHandler = createRouteHandler({ - maxMindAccountId: env.MAXMIND_ACCOUNT_ID, - maxMindLicenseKey: env.MAXMIND_LICENSE_KEY, - getInstallationId, + installationId, platformUrl: 'https://frescoanalytics.networkcanvas.dev', - WebServiceClient, + maxMindClient, }); export { routeHandler as POST }; diff --git a/env.mjs b/env.mjs index 6a271a4f0..75c8401b9 100644 --- a/env.mjs +++ b/env.mjs @@ -9,6 +9,10 @@ export const env = createEnv({ */ server: { DATABASE_URL: z.string().url(), + MAXMIND_ACCOUNT_ID: z.string(), + MAXMIND_LICENSE_KEY: z.string(), + + INSTALLATION_ID: z.string().optional(), }, /** @@ -23,9 +27,7 @@ export const env = createEnv({ NODE_ENV: z .enum(['development', 'test', 'production']) .default('development'), - MAXMIND_ACCOUNT_ID: z.string(), - MAXMIND_LICENSE_KEY: z.string(), - NEXT_PUBLIC_DISABLE_ANALYTICS: z.string().optional(), + DISABLE_ANALYTICS: z.boolean().optional(), }, /** * You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g. @@ -38,12 +40,12 @@ export const env = createEnv({ VERCEL_URL: process.env.VERCEL_URL, MAXMIND_ACCOUNT_ID: process.env.MAXMIND_ACCOUNT_ID, MAXMIND_LICENSE_KEY: process.env.MAXMIND_LICENSE_KEY, - NEXT_PUBLIC_DISABLE_ANALYTICS: process.env.NEXT_PUBLIC_DISABLE_ANALYTICS, + DISABLE_ANALYTICS: !!process.env.DISABLE_ANALYTICS, + INSTALLATION_ID: process.env.INSTALLATION_ID, }, /** * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially * useful for Docker builds. */ - // skipValidation: !!process.env.SKIP_ENV_VALIDATION, - skipValidation: true, + skipValidation: !!process.env.SKIP_ENV_VALIDATION, }); diff --git a/next.config.mjs b/next.config.mjs index 314abfd73..1913832dc 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -10,6 +10,7 @@ const config = { reactStrictMode: true, experimental: { typedRoutes: true, + webpackBuildWorker: true }, webpack: (config) => { config.module.rules.push({ diff --git a/package.json b/package.json index fc388bc42..33e17db99 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "seed": "tsx prisma/seed.ts" }, "dependencies": { - "@codaco/analytics": "1.0.1-alpha-1", + "@codaco/analytics": "^2.0.0", "@codaco/protocol-validation": "3.0.0-alpha.4", "@codaco/shared-consts": "^0.0.2", "@headlessui/react": "^1.7.17", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6a88a0d5e..bef9032a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@codaco/analytics': - specifier: 1.0.1-alpha-1 - version: 1.0.1-alpha-1(next@14.0.0) + specifier: ^2.0.0 + version: 2.0.0(@maxmind/geoip2-node@5.0.0)(next@14.0.0) '@codaco/protocol-validation': specifier: 3.0.0-alpha.4 version: 3.0.0-alpha.4(@types/eslint@8.44.6)(eslint-config-prettier@9.0.0)(eslint@8.52.0) @@ -1788,9 +1788,10 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true - /@codaco/analytics@1.0.1-alpha-1(next@14.0.0): - resolution: {integrity: sha512-opMtf/+44TjRAPNZtWuS/nj7Nza2gHsA4PE5DM6bZ2USGpu2+vx6euJFUin4uwlZGXqitgLPZfmHGxPchzbnHQ==} + /@codaco/analytics@2.0.0(@maxmind/geoip2-node@5.0.0)(next@14.0.0): + resolution: {integrity: sha512-HR9tlHVu+g2/Lwg11N9GmGXRNkai04uvRplLQpSJ92Ypszx2sc4xs19qEK10Sy5wJSotyCCNkTtvag1HQ6sFEQ==} peerDependencies: + '@maxmind/geoip2-node': ^5.0.0 next: 13 || 14 dependencies: '@maxmind/geoip2-node': 5.0.0