mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-30 21:01:54 +08:00
fix: address review findings for the HEXCLAVE_* env rename
- e2e helpers: also expand the port-prefix placeholder in HEXCLAVE_*/
NEXT_PUBLIC_HEXCLAVE_* vars (the renamed .env.development keys no longer
matched the STACK_-only prefix filter, leaving literal ${...} in every URL).
- docker/local-emulator/generate-env-development.mjs: read source keys under
the canonical HEXCLAVE_* name with STACK_* fallback and emit canonical keys
(the exact-name lookups threw after the source env files were renamed).
- prisma.config.ts: resolve the datasource URL from
HEXCLAVE_DATABASE_CONNECTION_STRING with legacy fallback (Prisma's env()
helper only knew the legacy name); same for the psql-inner script.
- backend vitest: accept both env prefixes and dual-read the DB connection
string in the auto-migration tests.
- getProcessEnv: empty-as-unset fallback (||), consistent with getEnvVariable —
an empty HEXCLAVE_* template placeholder must not shadow a real legacy value.
- errors.tsx debugger flag and dashboard next.config emulator flag: dual-read
the canonical name.
- Vite examples and docs snippets: VITE_STACK_* → VITE_HEXCLAVE_* (the old
names were dead after their .env.development files were renamed).
This commit is contained in:
parent
e55938308d
commit
f87c9c92c1
@ -27,7 +27,7 @@
|
||||
"codegen-route-info:watch": "pnpm run with-env tsx watch --clear-screen=false scripts/generate-route-info.ts",
|
||||
"codegen": "pnpm run with-env pnpm run generate-migration-imports && pnpm run with-env bash -c 'if [ \"$STACK_ACCELERATE_ENABLED\" = \"true\" ]; then pnpm run prisma generate --no-engine; else pnpm run codegen-prisma; fi' && pnpm run generate-private-sign-up-risk-engine && pnpm run codegen-docs && pnpm run codegen-route-info",
|
||||
"codegen:watch": "pnpm run generate-private-sign-up-risk-engine && concurrently -n \"prisma,private-risk-engine,docs,route-info,migration-imports\" -k \"pnpm run codegen-prisma:watch\" \"pnpm run generate-private-sign-up-risk-engine:watch\" \"pnpm run codegen-docs:watch\" \"pnpm run codegen-route-info:watch\" \"pnpm run generate-migration-imports:watch\"",
|
||||
"psql-inner": "psql $(echo $STACK_DATABASE_CONNECTION_STRING | sed 's/\\?.*$//')",
|
||||
"psql-inner": "psql $(echo ${HEXCLAVE_DATABASE_CONNECTION_STRING:-$STACK_DATABASE_CONNECTION_STRING} | sed 's/\\?.*$//')",
|
||||
"clickhouse": "pnpm run with-env clickhouse-client --host localhost --port ${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}37 --user stackframe --password PASSWORD-PLACEHOLDER--9gKyMxJeMx",
|
||||
"psql": "pnpm run with-env:dev pnpm run psql-inner",
|
||||
"prisma-studio": "pnpm run with-env:dev prisma studio --port ${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}06 --browser none",
|
||||
|
||||
@ -8,7 +8,10 @@ export default defineConfig({
|
||||
seed: 'pnpm run db-seed-script',
|
||||
},
|
||||
datasource: {
|
||||
url: env('STACK_DATABASE_CONNECTION_STRING'),
|
||||
// Hexclave rebrand: prefer the canonical name, fall back to the legacy one
|
||||
// (empty counts as unset — the checked-in .env templates define empty placeholders).
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
url: env(process.env.HEXCLAVE_DATABASE_CONNECTION_STRING ? 'HEXCLAVE_DATABASE_CONNECTION_STRING' : 'STACK_DATABASE_CONNECTION_STRING'),
|
||||
},
|
||||
experimental: {
|
||||
externalTables: true,
|
||||
|
||||
@ -8,9 +8,9 @@ const TEST_DB_PREFIX = 'stack_auth_test_db';
|
||||
|
||||
const getTestDbURL = (testDbName: string) => {
|
||||
// @ts-ignore - ImportMeta.env is provided by Vite
|
||||
const base = import.meta.env.STACK_DATABASE_CONNECTION_STRING.replace(/\/[^/]*$/, '');
|
||||
const base = (import.meta.env.HEXCLAVE_DATABASE_CONNECTION_STRING || import.meta.env.STACK_DATABASE_CONNECTION_STRING).replace(/\/[^/]*$/, '');
|
||||
// @ts-ignore - ImportMeta.env is provided by Vite
|
||||
const query = import.meta.env.STACK_DATABASE_CONNECTION_STRING.split('?')[1] ?? '';
|
||||
const query = (import.meta.env.HEXCLAVE_DATABASE_CONNECTION_STRING || import.meta.env.STACK_DATABASE_CONNECTION_STRING).split('?')[1] ?? '';
|
||||
return {
|
||||
full: `${base}/${testDbName}`,
|
||||
base,
|
||||
|
||||
@ -14,7 +14,7 @@ const TEST_DB_PREFIX = 'stack_migration_test';
|
||||
|
||||
const getTestDbURL = (testDbName: string) => {
|
||||
// @ts-ignore - ImportMeta.env is provided by Vite
|
||||
const connString: string = import.meta.env.STACK_DATABASE_CONNECTION_STRING;
|
||||
const connString: string = (import.meta.env.HEXCLAVE_DATABASE_CONNECTION_STRING || import.meta.env.STACK_DATABASE_CONNECTION_STRING);
|
||||
const base = connString.replace(/\/[^/]*(\?.*)?$/, '');
|
||||
const query = connString.split('?')[1] ?? '';
|
||||
return { full: `${base}/${testDbName}`, base, query };
|
||||
|
||||
@ -21,6 +21,6 @@ export default mergeConfig(
|
||||
}
|
||||
},
|
||||
envDir: __dirname,
|
||||
envPrefix: 'STACK_',
|
||||
envPrefix: ['HEXCLAVE_', 'STACK_'],
|
||||
})
|
||||
)
|
||||
|
||||
@ -100,7 +100,7 @@ const nextConfig = {
|
||||
},
|
||||
|
||||
async headers() {
|
||||
const isLocalEmulator = process.env.NEXT_PUBLIC_STACK_IS_LOCAL_EMULATOR === "true";
|
||||
const isLocalEmulator = (process.env.NEXT_PUBLIC_HEXCLAVE_IS_LOCAL_EMULATOR || process.env.NEXT_PUBLIC_STACK_IS_LOCAL_EMULATOR) === "true";
|
||||
return [
|
||||
{
|
||||
source: "/(.*)",
|
||||
|
||||
@ -299,7 +299,7 @@ function expandHexclavePortPrefix(value?: string | null) {
|
||||
return prefix ? value.replace(/\$\{NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81\}/g, prefix) : value;
|
||||
}
|
||||
for (const [key, value] of Object.entries(process.env)) {
|
||||
if (key.startsWith("STACK_") || key.startsWith("NEXT_PUBLIC_STACK_")) {
|
||||
if (key.startsWith("STACK_") || key.startsWith("NEXT_PUBLIC_STACK_") || key.startsWith("HEXCLAVE_") || key.startsWith("NEXT_PUBLIC_HEXCLAVE_")) {
|
||||
const replaced = expandHexclavePortPrefix(value ?? undefined);
|
||||
if (replaced !== undefined) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
|
||||
@ -41,23 +41,28 @@ const parseEnvFile = (filePath) => {
|
||||
const backendEnv = parseEnvFile(backendEnvPath);
|
||||
const dashboardEnv = parseEnvFile(dashboardEnvPath);
|
||||
|
||||
// Hexclave rebrand: the source env files use the canonical HEXCLAVE_* names,
|
||||
// but accept the legacy STACK_* spelling as a fallback. Emitted keys are
|
||||
// always canonical.
|
||||
const toCanonicalKey = (key) => key.includes("STACK_") ? key.replace("STACK_", "HEXCLAVE_") : key;
|
||||
|
||||
const getRequiredEnvValue = (sourceName, envMap, key) => {
|
||||
const value = envMap.get(key);
|
||||
const value = envMap.get(toCanonicalKey(key)) ?? envMap.get(key);
|
||||
if (value == null) {
|
||||
throw new Error(`Missing ${key} in ${sourceName}; update the generator or source env file.`);
|
||||
throw new Error(`Missing ${toCanonicalKey(key)} in ${sourceName}; update the generator or source env file.`);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
const fromSource = (sourceName, envMap, key) => ({
|
||||
type: "entry",
|
||||
key,
|
||||
key: toCanonicalKey(key),
|
||||
value: getRequiredEnvValue(sourceName, envMap, key),
|
||||
});
|
||||
|
||||
const literal = (key, value) => ({
|
||||
type: "entry",
|
||||
key,
|
||||
key: toCanonicalKey(key),
|
||||
value,
|
||||
});
|
||||
|
||||
|
||||
@ -80,8 +80,8 @@ STACK_SECRET_SERVER_KEY=<your-secret-server-key>`,
|
||||
language: 'JavaScript',
|
||||
framework: 'React',
|
||||
code: `# Store these in environment variables or directly in the client file during development
|
||||
VITE_STACK_PROJECT_ID=<your-project-id>
|
||||
VITE_STACK_PUBLISHABLE_CLIENT_KEY=<your-publishable-client-key>`,
|
||||
VITE_HEXCLAVE_PROJECT_ID=<your-project-id>
|
||||
VITE_HEXCLAVE_PUBLISHABLE_CLIENT_KEY=<your-publishable-client-key>`,
|
||||
highlightLanguage: 'bash',
|
||||
filename: '.env'
|
||||
},
|
||||
@ -172,8 +172,8 @@ export const stackClientApp = new StackClientApp({
|
||||
// import { useNavigate } from "@tanstack/react-router"; // TanStack Router
|
||||
|
||||
export const stackClientApp = new StackClientApp({
|
||||
projectId: process.env.VITE_STACK_PROJECT_ID || "your-project-id",
|
||||
publishableClientKey: process.env.VITE_STACK_PUBLISHABLE_CLIENT_KEY || "your-publishable-client-key",
|
||||
projectId: process.env.VITE_HEXCLAVE_PROJECT_ID || "your-project-id",
|
||||
publishableClientKey: process.env.VITE_HEXCLAVE_PUBLISHABLE_CLIENT_KEY || "your-publishable-client-key",
|
||||
tokenStore: "cookie",
|
||||
// redirectMethod: { useNavigate }, // Set this for non-Next.js frameworks
|
||||
});`,
|
||||
|
||||
@ -12,17 +12,17 @@ export const viteExamples = {
|
||||
declare global {
|
||||
interface ImportMeta {
|
||||
env: {
|
||||
VITE_STACK_API_URL: string;
|
||||
VITE_STACK_PROJECT_ID: string;
|
||||
VITE_STACK_PUBLISHABLE_CLIENT_KEY: string;
|
||||
VITE_HEXCLAVE_API_URL: string;
|
||||
VITE_HEXCLAVE_PROJECT_ID: string;
|
||||
VITE_HEXCLAVE_PUBLISHABLE_CLIENT_KEY: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const stackClientApp = new StackClientApp({
|
||||
baseUrl: import.meta.env.VITE_STACK_API_URL,
|
||||
projectId: import.meta.env.VITE_STACK_PROJECT_ID,
|
||||
publishableClientKey: import.meta.env.VITE_STACK_PUBLISHABLE_CLIENT_KEY,
|
||||
baseUrl: import.meta.env.VITE_HEXCLAVE_API_URL,
|
||||
projectId: import.meta.env.VITE_HEXCLAVE_PROJECT_ID,
|
||||
publishableClientKey: import.meta.env.VITE_HEXCLAVE_PUBLISHABLE_CLIENT_KEY,
|
||||
tokenStore: "cookie",
|
||||
urls: {
|
||||
oauthCallback: window.location.origin + "/oauth",
|
||||
|
||||
@ -3,9 +3,9 @@
|
||||
import { StackClientApp } from "@hexclave/js";
|
||||
|
||||
export const hexclaveClientApp = new StackClientApp({
|
||||
baseUrl: import.meta.env.VITE_STACK_API_URL,
|
||||
projectId: import.meta.env.VITE_STACK_PROJECT_ID,
|
||||
publishableClientKey: import.meta.env.VITE_STACK_PUBLISHABLE_CLIENT_KEY,
|
||||
baseUrl: import.meta.env.VITE_HEXCLAVE_API_URL,
|
||||
projectId: import.meta.env.VITE_HEXCLAVE_PROJECT_ID,
|
||||
publishableClientKey: import.meta.env.VITE_HEXCLAVE_PUBLISHABLE_CLIENT_KEY,
|
||||
tokenStore: "cookie",
|
||||
urls: {
|
||||
oauthCallback: window.location.origin + "/oauth",
|
||||
|
||||
@ -3,9 +3,9 @@ import { useNavigate } from "react-router-dom";
|
||||
|
||||
export const hexclaveClientApp = new StackClientApp({
|
||||
tokenStore: "cookie",
|
||||
baseUrl: import.meta.env.VITE_STACK_API_URL,
|
||||
projectId: import.meta.env.VITE_STACK_PROJECT_ID,
|
||||
publishableClientKey: import.meta.env.VITE_STACK_PUBLISHABLE_CLIENT_KEY,
|
||||
baseUrl: import.meta.env.VITE_HEXCLAVE_API_URL,
|
||||
projectId: import.meta.env.VITE_HEXCLAVE_PROJECT_ID,
|
||||
publishableClientKey: import.meta.env.VITE_HEXCLAVE_PUBLISHABLE_CLIENT_KEY,
|
||||
redirectMethod: {
|
||||
useNavigate,
|
||||
},
|
||||
|
||||
@ -4,9 +4,9 @@ import { StackClientApp } from "@hexclave/react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
export const hexclaveClientApp = new StackClientApp({
|
||||
projectId: import.meta.env.VITE_STACK_PROJECT_ID,
|
||||
publishableClientKey: import.meta.env.VITE_STACK_PUBLISHABLE_CLIENT_KEY,
|
||||
baseUrl: import.meta.env.VITE_STACK_API_URL,
|
||||
projectId: import.meta.env.VITE_HEXCLAVE_PROJECT_ID,
|
||||
publishableClientKey: import.meta.env.VITE_HEXCLAVE_PUBLISHABLE_CLIENT_KEY,
|
||||
baseUrl: import.meta.env.VITE_HEXCLAVE_API_URL,
|
||||
tokenStore: "cookie",
|
||||
redirectMethod: {
|
||||
useNavigate,
|
||||
|
||||
@ -9,7 +9,7 @@ function replaceHexclavePortPrefix(value: string): string {
|
||||
}
|
||||
|
||||
function getStackApiUrl(): string {
|
||||
const configured = import.meta.env.VITE_STACK_API_URL as string | undefined;
|
||||
const configured = import.meta.env.VITE_HEXCLAVE_API_URL as string | undefined;
|
||||
return configured ? replaceHexclavePortPrefix(configured) : `http://localhost:${getPortPrefix()}02`;
|
||||
}
|
||||
|
||||
|
||||
@ -114,6 +114,8 @@ export function getProcessEnv(name: string): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
// Hexclave rebrand: prefer the HEXCLAVE_*-prefixed equivalent, fall back to the STACK_* name.
|
||||
// Empty counts as unset — the checked-in .env templates define empty HEXCLAVE_* placeholders,
|
||||
// which must not shadow a real value under the legacy name.
|
||||
const hexclaveName = getHexclaveEnvVarName(name);
|
||||
return (hexclaveName ? process.env[hexclaveName] : undefined) ?? process.env[name];
|
||||
return (hexclaveName ? process.env[hexclaveName] : undefined) || process.env[name];
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ export class HexclaveAssertionError extends Error {
|
||||
|
||||
// Use literal dot-form (guarded with `typeof process`) so Next.js / webpack
|
||||
// DefinePlugin can inline the value at build time. See getProcessEnv in ./env.
|
||||
if ((typeof process !== "undefined" ? process.env.NEXT_PUBLIC_STACK_DEBUGGER_ON_ASSERTION_ERROR : undefined) === "true") {
|
||||
if ((typeof process !== "undefined" ? (process.env.NEXT_PUBLIC_HEXCLAVE_DEBUGGER_ON_ASSERTION_ERROR || process.env.NEXT_PUBLIC_STACK_DEBUGGER_ON_ASSERTION_ERROR) : undefined) === "true") {
|
||||
debugger;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user