mirror of
https://github.com/logos-co/logos-web.git
synced 2026-08-30 21:51:09 +00:00
* refactor(civi-crm): remove case management pages and API The Circle Case UI, its API routes and the CiviCRM query layer they used are gone. Keeps the app shell out entirely: no pages remain, so the layout, styles and UI dependencies go with them. * refactor(civi-crm): drop CiviCRM write from the intake endpoint Submissions now go to Notion and, for the steward form, n8n. The legacy afformCircleContactForm name was CiviCRM-only and is no longer accepted; the fields[] payload is ignored. * chore(web): remove CiviCRM afform generator scripts They fetched form definitions from the CiviCRM API, which is gone. The generated files under lib/civicrm are hand-maintained from now on. * refactor(web): trim funnel form definitions and move to lib/funnel-forms Fields keep only what renders the form: formKey, label, inputType, required, repeatable. The CiviCRM entity/join/fieldName plumbing and the fields[] POST payload are gone, along with the unused circle contact form. country was marked required but exempt from validation through its CiviCRM Address join, so it is now enforced like every other required select. * docs: rewrite civi-crm and funnel docs for the intake-only app Drops the CiviCRM API guide and the case management architecture, and updates the funnel reference to the Notion + n8n flow.
113 lines
3.7 KiB
TypeScript
113 lines
3.7 KiB
TypeScript
/**
|
|
* Typed and validated server-side environment access.
|
|
*
|
|
* Reading `process.env.X` directly is risky: a typo silently widens an
|
|
* `undefined` and downstream code makes the wrong choice (e.g. robots
|
|
* marked `index: false` for production). This module validates env vars
|
|
* once at import time and exposes a typed `env` object.
|
|
*
|
|
* Add new vars here, never reach into `process.env` from feature code.
|
|
*
|
|
* Kept dependency-free deliberately — `apps/web` doesn't ship zod, and
|
|
* runtime env validation that has its own bug is worse than the inline
|
|
* `process.env.X === '...'` it replaces.
|
|
*/
|
|
|
|
const NODE_ENV_VALUES = ['production', 'development', 'test'] as const
|
|
const API_MODE_VALUES = ['production', 'staging', 'development'] as const
|
|
|
|
type NodeEnv = (typeof NODE_ENV_VALUES)[number]
|
|
type ApiMode = (typeof API_MODE_VALUES)[number]
|
|
|
|
export type Env = {
|
|
NODE_ENV: NodeEnv
|
|
/**
|
|
* Toggle for production-only behaviour gates (search-engine indexing,
|
|
* analytics, etc.). Currently used by `lib/metadata.ts`.
|
|
*/
|
|
NEXT_PUBLIC_API_MODE: ApiMode | undefined
|
|
/**
|
|
* Public site URL (e.g. `https://logos-co-web.vercel.app`). Used for
|
|
* canonical, OG and Twitter absolute URLs. Set per environment.
|
|
*/
|
|
NEXT_PUBLIC_SITE_URL: string | undefined
|
|
/**
|
|
* Public CMS origin (e.g. `https://cms.logos.co` or `http://localhost:3001`).
|
|
* Optional — only required by features that read directly from the Payload
|
|
* REST/GraphQL API at runtime (preview tokens, draft fetches). The default
|
|
* content pipeline reads from local files, not this URL.
|
|
*/
|
|
NEXT_PUBLIC_CMS_URL: string | undefined
|
|
/**
|
|
* Public calendar API origin used at build time for Logos Broadcast Network.
|
|
*/
|
|
NEXT_PUBLIC_ADMIN_ACID_API_URL: string | undefined
|
|
/**
|
|
* Public origin of the intake app `apps/civi-crm` (e.g. `https://civi.logos.co`
|
|
* or `http://localhost:3002`), which hosts the endpoint the funnel forms post to.
|
|
*/
|
|
NEXT_PUBLIC_CIVI_CRM_URL: string | undefined
|
|
/**
|
|
* hCaptcha public sitekey for connect forms.
|
|
*/
|
|
NEXT_PUBLIC_HCAPTCHA_SITEKEY: string | undefined
|
|
}
|
|
|
|
function assertOneOf<T extends string>(
|
|
raw: string | undefined,
|
|
allowed: ReadonlyArray<T>,
|
|
name: string,
|
|
optional: false
|
|
): T
|
|
function assertOneOf<T extends string>(
|
|
raw: string | undefined,
|
|
allowed: ReadonlyArray<T>,
|
|
name: string,
|
|
optional: true
|
|
): T | undefined
|
|
function assertOneOf<T extends string>(
|
|
raw: string | undefined,
|
|
allowed: ReadonlyArray<T>,
|
|
name: string,
|
|
optional: boolean
|
|
): T | undefined {
|
|
if (raw === undefined || raw === '') {
|
|
if (optional) return undefined
|
|
throw new Error(`${name} is required (one of: ${allowed.join(', ')})`)
|
|
}
|
|
if (!allowed.includes(raw as T)) {
|
|
throw new Error(
|
|
`${name}="${raw}" is invalid; must be one of: ${allowed.join(', ')}`
|
|
)
|
|
}
|
|
return raw as T
|
|
}
|
|
|
|
function readOptionalString(raw: string | undefined): string | undefined {
|
|
if (raw === undefined || raw === '') return undefined
|
|
return raw
|
|
}
|
|
|
|
export const env: Env = {
|
|
NODE_ENV:
|
|
assertOneOf(process.env.NODE_ENV, NODE_ENV_VALUES, 'NODE_ENV', true) ??
|
|
'development',
|
|
NEXT_PUBLIC_API_MODE: assertOneOf(
|
|
process.env.NEXT_PUBLIC_API_MODE,
|
|
API_MODE_VALUES,
|
|
'NEXT_PUBLIC_API_MODE',
|
|
true
|
|
),
|
|
NEXT_PUBLIC_SITE_URL: readOptionalString(process.env.NEXT_PUBLIC_SITE_URL),
|
|
NEXT_PUBLIC_CMS_URL: readOptionalString(process.env.NEXT_PUBLIC_CMS_URL),
|
|
NEXT_PUBLIC_ADMIN_ACID_API_URL: readOptionalString(
|
|
process.env.NEXT_PUBLIC_ADMIN_ACID_API_URL
|
|
),
|
|
NEXT_PUBLIC_CIVI_CRM_URL: readOptionalString(
|
|
process.env.NEXT_PUBLIC_CIVI_CRM_URL
|
|
),
|
|
NEXT_PUBLIC_HCAPTCHA_SITEKEY: readOptionalString(
|
|
process.env.NEXT_PUBLIC_HCAPTCHA_SITEKEY
|
|
),
|
|
}
|