Skip to content

Commit 5e7bc1d

Browse files
committed
Add ApiFunctionError handling in src/pages/api, move Sentry client init from root to directory, add GDPR compliance to API system
1 parent ae605e6 commit 5e7bc1d

20 files changed

Lines changed: 1074 additions & 220 deletions

File tree

‎.github/workflows/type-check.yml‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,18 @@ jobs:
1717
env:
1818
CONVERTKIT_API_KEY: ${{ secrets.CONVERTKIT_API_KEY }}
1919
CONVERTKIT_FORM_ID: ${{ secrets.CONVERTKIT_FORM_ID }}
20+
CRON_SECRET: ${{ secrets.CRON_SECRET }}
2021
RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }}
2122
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
2223
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
24+
SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
25+
SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }}
26+
SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }}
27+
KV_URL: ${{ secrets.KV_URL }}
28+
KV_REST_API_URL: ${{ secrets.KV_REST_API_URL }}
29+
KV_REST_API_TOKEN: ${{ secrets.KV_REST_API_TOKEN }}
30+
KV_REST_API_READ_ONLY_TOKEN: ${{ secrets.KV_REST_API_READ_ONLY_TOKEN }}
31+
REDIS_URL: ${{ secrets.REDIS_URL }}
2332
WEBMENTION_IO_TOKEN: ${{ secrets.WEBMENTION_IO_TOKEN }}
2433

2534
steps:

‎astro.config.ts‎

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,41 @@ import { packageRelease } from './src/integrations/PackageRelease'
3333
import { privacyPolicyVersion } from './src/integrations/PrivacyPolicyVersion'
3434
import { createSerializeFunction, pagesJsonWriter } from './src/integrations/sitemapSerialize'
3535

36+
const sharedTestIntegrations = [
37+
icon(),
38+
]
39+
40+
const standardIntegrations = [
41+
AstroPWA(serviceWorkerConfig),
42+
...sharedTestIntegrations,
43+
mdx(markdownConfig),
44+
/** Generate favicons and PWA icons from source SVG */
45+
faviconGenerator(),
46+
/** Verify number of call to actions included in Markdown files */
47+
callToActionValidator({
48+
/** Enable debug logging to see validation details */
49+
debug: true,
50+
}),
51+
/** Inject package release (name@version) for tracking regressions between releases */
52+
packageRelease(),
53+
/** Inject privacy policy version from git commit date for GDPR record keeping */
54+
privacyPolicyVersion(),
55+
/** Only include Sentry integration in Vercel environments */
56+
...(isVercel() ? [sentry({
57+
project: "webstack-builders-corporate-website",
58+
org: "webstack-builders",
59+
authToken: getSentryAuthToken(),
60+
})] : []),
61+
sitemap({
62+
serialize: createSerializeFunction({
63+
exclude: ['downloads', 'social-shares', '/articles/demo'],
64+
}),
65+
}),
66+
pagesJsonWriter(),
67+
/** Debugging tools for Astro View Transition API */
68+
vtbot(),
69+
]
70+
3671
export default defineConfig({
3772
adapter: vercelStatic(vercelConfig),
3873
devToolbar: {
@@ -46,36 +81,7 @@ export default defineConfig({
4681
* can change config, they're ran when the helper's called. This causes problems for
4782
* unit testing integrations.
4883
*/
49-
integrations: isUnitTest() ? [] : [
50-
AstroPWA(serviceWorkerConfig),
51-
icon(),
52-
mdx(markdownConfig),
53-
/** Generate favicons and PWA icons from source SVG */
54-
faviconGenerator(),
55-
/** Verify number of call to actions included in Markdown files */
56-
callToActionValidator({
57-
/** Enable debug logging to see validation details */
58-
debug: true,
59-
}),
60-
/** Inject package release (name@version) for tracking regressions between releases */
61-
packageRelease(),
62-
/** Inject privacy policy version from git commit date for GDPR record keeping */
63-
privacyPolicyVersion(),
64-
/** Only include Sentry integration in Vercel environments */
65-
...(isVercel() ? [sentry({
66-
project: "webstack-builders-corporate-website",
67-
org: "webstack-builders",
68-
authToken: getSentryAuthToken(),
69-
})] : []),
70-
sitemap({
71-
serialize: createSerializeFunction({
72-
exclude: ['downloads', 'social-shares', '/articles/demo'],
73-
}),
74-
}),
75-
pagesJsonWriter(),
76-
/** Debugging tools for Astro View Transition API */
77-
vtbot(),
78-
],
84+
integrations: isUnitTest() ? sharedTestIntegrations : standardIntegrations,
7985
/** API routes are marked in their files for SSR */
8086
output: 'static',
8187
prefetch: true,
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import * as Sentry from "@sentry/astro"
2-
import { SENTRY_DSN } from "astro:env/client"
3-
import { getPackageRelease, isDev, isProd } from '@lib/config'
1+
import {init as sentryInit } from '@sentry/astro'
2+
import { SENTRY_DSN } from 'astro:env/client'
3+
import { getPackageRelease, isDev, isProd } from './src/lib/config'
4+
45
/**
56
* Server-side Sentry initialization
67
*
@@ -13,7 +14,7 @@ import { getPackageRelease, isDev, isProd } from '@lib/config'
1314

1415
// Initialize Sentry in production if DSN is available
1516
if (isProd()) {
16-
Sentry.init({
17+
sentryInit({
1718
dsn: SENTRY_DSN,
1819

1920
/** Release name to track regressions between releases */

‎src/components/scripts/utils/environmentClient.ts‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
/**
2+
* This file cannot be used in API endpoint code. See
3+
* src/lib/config/environmentServer.ts for details.
4+
*/
5+
import {
6+
PACKAGE_RELEASE_VERSION,
7+
PRIVACY_POLICY_VERSION,
8+
} from 'astro:env/client'
9+
import { ClientScriptError } from '@components/scripts/errors'
110

211
/**
312
* We are setting the VITEST env var in vitest.config.ts for unit tests.
@@ -36,3 +45,51 @@ export const isDev = () => {
3645
export const isProd = () => {
3746
return import.meta.env.PROD && !isUnitTest()
3847
}
48+
49+
/**
50+
* Privacy Policy Version Utility
51+
*
52+
* Provides access to the privacy policy version that's injected at build time
53+
* via the PrivacyPolicyVersion Astro integration.
54+
*
55+
* @see src/integrations/PrivacyPolicyVersion/index.ts
56+
*/
57+
58+
/**
59+
* Provides access to the privacy policy version that is injected
60+
* at build time via the PrivacyPolicyVersion Astro integration.
61+
*
62+
* @returns The privacy policy version in YYYY-MM-DD format
63+
* @throws {ClientScriptError} If PRIVACY_POLICY_VERSION is not set
64+
*/
65+
export function getPrivacyPolicyVersion(): string {
66+
if (!PRIVACY_POLICY_VERSION) {
67+
throw new ClientScriptError(
68+
'PRIVACY_POLICY_VERSION environment variable is not set. This should be injected by the PrivacyPolicyVersion integration.',
69+
)
70+
}
71+
return PRIVACY_POLICY_VERSION
72+
}
73+
74+
/**
75+
* Package Release Utility
76+
*
77+
* Provides access to the package release version that is injected at build time
78+
* via the PackageRelease Astro integration.
79+
*
80+
* @see src/integrations/PackageRelease/index.ts
81+
*/
82+
83+
/**
84+
* Gets the package release from the build-time environment variable
85+
* @returns The package release in name@version format
86+
* @throws {ClientScriptError} If PACKAGE_RELEASE_VERSION is not set
87+
*/
88+
export function getPackageRelease(): string {
89+
if (!PACKAGE_RELEASE_VERSION) {
90+
throw new ClientScriptError(
91+
'PACKAGE_RELEASE_VERSION environment variable is not set. This should be injected by the PackageRelease integration.',
92+
)
93+
}
94+
return PACKAGE_RELEASE_VERSION
95+
}

‎src/integrations/CtaValidator/componentDiscovery.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55
import { readdir, readFile } from 'fs/promises'
66
import { join, resolve } from 'path'
7-
import { BuildError } from '../../lib/errors'
7+
import { BuildError } from '../../lib/errors/BuildError'
88
import type { CallToActionComponent } from './@types'
99
import { generateImportPatterns } from './parsers'
1010

‎src/integrations/CtaValidator/index.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
*/
3030
import type { AstroIntegration, AstroConfig } from 'astro'
3131
import { fileURLToPath } from 'url'
32-
import { BuildError } from '../../lib/errors'
32+
import { BuildError } from '../../lib/errors/BuildError'
3333
import type { CallToActionValidatorOptions, CallToActionComponent } from './@types'
3434
import { discoverCallToActionComponents } from './componentDiscovery'
3535
import { validateAllPages, validateCtaRequirements } from './validation'
Lines changed: 10 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
/**
22
* This file needs to be importable by config files, so no path aliases.
33
*/
4-
import { BuildError } from '../errors'
4+
import { BuildError } from '../errors/BuildError'
5+
6+
/**
7+
* Used for getting build-time and SSR serverless function environment
8+
*/
59

610
/**
711
* We are setting the VITEST env var in vitest.config.ts for unit tests.
@@ -26,6 +30,11 @@ export const isDev = () => {
2630
return import.meta.env.DEV
2731
}
2832

33+
/**
34+
* The value of import.meta.env.PROD is included in the serverless function
35+
* bundle. Astro, which uses Vite under the hood, performs a static replacement
36+
* of import.meta.env.* variables at build time.
37+
*/
2938
export const isProd = () => {
3039
return import.meta.env.PROD && !isUnitTest()
3140
}
@@ -56,53 +65,3 @@ export function getSentryAuthToken(): string {
5665
}
5766
return token
5867
}
59-
60-
/**
61-
* Privacy Policy Version Utility
62-
*
63-
* Provides access to the privacy policy version that's injected at build time
64-
* via the PrivacyPolicyVersion Astro integration.
65-
*
66-
* @see src/integrations/PrivacyPolicyVersion/index.ts
67-
*/
68-
69-
/**
70-
* Gets the privacy policy version from the build-time environment variable
71-
* @returns The privacy policy version in YYYY-MM-DD format
72-
* @throws {BuildError} If PRIVACY_POLICY_VERSION is not set
73-
*/
74-
export function getPrivacyPolicyVersion(): string {
75-
const version = import.meta.env['PRIVACY_POLICY_VERSION']
76-
if (!version) {
77-
throw new BuildError(
78-
'PRIVACY_POLICY_VERSION environment variable is not set. This should be injected by the PrivacyPolicyVersion integration.',
79-
{ phase: 'runtime' },
80-
)
81-
}
82-
return version
83-
}
84-
85-
/**
86-
* Package Release Utility
87-
*
88-
* Provides access to the package release version that's injected at build time
89-
* via the PackageRelease Astro integration.
90-
*
91-
* @see src/integrations/PackageRelease/index.ts
92-
*/
93-
94-
/**
95-
* Gets the package release from the build-time environment variable
96-
* @returns The package release in name@version format
97-
* @throws {BuildError} If PACKAGE_RELEASE_VERSION is not set
98-
*/
99-
export function getPackageRelease(): string {
100-
const release = import.meta.env['PACKAGE_RELEASE_VERSION']
101-
if (!release) {
102-
throw new BuildError(
103-
'PACKAGE_RELEASE_VERSION environment variable is not set. This should be injected by the PackageRelease integration.',
104-
{ phase: 'runtime' },
105-
)
106-
}
107-
return release
108-
}

‎src/lib/config/environmentalVariableValidation.ts‎

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@ import type { AstroUserConfig } from 'astro'
2929

3030
export const environmentalVariablesConfig: AstroUserConfig['env'] = {
3131
schema: {
32+
PACKAGE_RELEASE_VERSION: envField.string({
33+
access: 'public',
34+
context: 'client',
35+
default: 'unknown@0.0.0',
36+
optional: true,
37+
}),
38+
PRIVACY_POLICY_VERSION: envField.string({
39+
access: 'public',
40+
context: 'client',
41+
default: '1970-01-01',
42+
optional: true,
43+
}),
3244
/**
3345
* Set in Vitest config for unit tests
3446
*/
@@ -127,18 +139,18 @@ export const environmentalVariablesConfig: AstroUserConfig['env'] = {
127139
/**
128140
* Site uses Suprabase for managing GDPR consent records
129141
*/
130-
SUPABASE_URL: envField.string({
142+
SUPABASE_KEY: envField.string({
131143
access: 'public',
132144
context: 'client',
133145
optional: false,
134146
}),
135-
SUPABASE_KEY: envField.string({
147+
SUPABASE_URL: envField.string({
136148
access: 'public',
137-
context: 'server',
149+
context: 'client',
138150
optional: false,
139151
}),
140152
SUPABASE_SERVICE_ROLE_KEY: envField.string({
141-
access: 'secret',
153+
access: 'public',
142154
context: 'server',
143155
optional: false,
144156
}),

‎src/lib/errors/BuildError.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/**
22
* Custom error class for build-time errors with enhanced context
33
*
4-
* Used for errors that occur during build processes, compilation, file operations,
5-
* and other build-time activities.
4+
* Used for errors that occur during build processes, Astro integrations,
5+
* compilation, file operations, and other build-time activities.
66
*/
77

88
export interface BuildErrorParams {

0 commit comments

Comments
 (0)