History

feat(cloud): manage cloudflared installation and relay defaults

Julius Marminge committed 5 months ago

Commit 91e8bff1 parent b9c613a38 files · +1557 −74Browse files

Showing the changes to scripts (3 of 38 files). Show all

Unified · Split

3 files
  1. scripts/dev-runner.ts +4 −0
  2. scripts/lib/public-config.test.ts +74 −0
  3. scripts/lib/public-config.ts +78 −0
scripts/dev-runner.ts+4−0
@@ -17,6 +17,10 @@ import * as Schema from "effect/Schema"; · 16 unmodified lines
17import { Argument, Command, Flag } from "effect/unstable/cli";17import { Argument, Command, Flag } from "effect/unstable/cli";
18import { ChildProcess } from "effect/unstable/process";18import { ChildProcess } from "effect/unstable/process";
19 19
20import { loadRepoEnv } from "./lib/public-config.ts";
21
22Object.assign(process.env, loadRepoEnv());
23
20const BASE_SERVER_PORT = 13773;24const BASE_SERVER_PORT = 13773;
21const BASE_WEB_PORT = 5733;25const BASE_WEB_PORT = 5733;
22const MAX_HASH_OFFSET = 3000;26const MAX_HASH_OFFSET = 3000;
scripts/lib/public-config.test.ts+74−0
@@ -0,0 +1,74 @@
1// @effect-diagnostics nodeBuiltinImport:off - Tests exercise root env file precedence directly.
2import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
3import { tmpdir } from "node:os";
4import { join } from "node:path";
5import { afterEach, describe, expect, it } from "vitest";
6
7import { DEFAULT_PUBLIC_CONFIG, loadRepoEnv, resolvePublicConfig } from "./public-config.ts";
8
9const temporaryDirectories: string[] = [];
10
11afterEach(() => {
12 for (const directory of temporaryDirectories.splice(0)) {
13 rmSync(directory, { recursive: true, force: true });
14 }
15});
16
17describe("loadRepoEnv", () => {
18 it("projects checked-in public defaults into Vite and Expo aliases", () => {
19 const env = loadRepoEnv({ baseEnv: {}, repoRoot: makeTemporaryDirectory() });
20
21 expect(env.T3CODE_CLERK_PUBLISHABLE_KEY).toBe(DEFAULT_PUBLIC_CONFIG.clerkPublishableKey);
22 expect(env.VITE_CLERK_PUBLISHABLE_KEY).toBe(DEFAULT_PUBLIC_CONFIG.clerkPublishableKey);
23 expect(env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY).toBe(DEFAULT_PUBLIC_CONFIG.clerkPublishableKey);
24 expect(env.T3_RELAY_URL).toBe(DEFAULT_PUBLIC_CONFIG.relayUrl);
25 expect(env.VITE_T3_RELAY_URL).toBe(DEFAULT_PUBLIC_CONFIG.relayUrl);
26 });
27
28 it("applies process, root local, root, and checked-in precedence in that order", () => {
29 const repoRoot = makeTemporaryDirectory();
30 writeFileSync(
31 join(repoRoot, ".env"),
32 "T3CODE_CLERK_PUBLISHABLE_KEY=pk_root\nT3_RELAY_URL=https://root.example.test\n",
33 );
34 writeFileSync(
35 join(repoRoot, ".env.local"),
36 "T3CODE_CLERK_PUBLISHABLE_KEY=pk_local\nT3_RELAY_URL=https://local.example.test\n",
37 );
38
39 expect(loadRepoEnv({ baseEnv: {}, repoRoot }).T3_RELAY_URL).toBe("https://local.example.test");
40 expect(
41 loadRepoEnv({
42 baseEnv: {
43 T3CODE_CLERK_PUBLISHABLE_KEY: "pk_ci",
44 T3_RELAY_URL: "https://ci.example.test",
45 },
46 repoRoot,
47 }),
48 ).toMatchObject({
49 T3CODE_CLERK_PUBLISHABLE_KEY: "pk_ci",
50 VITE_CLERK_PUBLISHABLE_KEY: "pk_ci",
51 EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY: "pk_ci",
52 T3_RELAY_URL: "https://ci.example.test",
53 VITE_T3_RELAY_URL: "https://ci.example.test",
54 });
55 });
56
57 it("accepts legacy framework aliases as root overrides", () => {
58 expect(
59 resolvePublicConfig({
60 VITE_CLERK_PUBLISHABLE_KEY: "pk_legacy",
61 VITE_T3_RELAY_URL: "https://legacy.example.test",
62 }),
63 ).toEqual({
64 clerkPublishableKey: "pk_legacy",
65 relayUrl: "https://legacy.example.test",
66 });
67 });
68});
69
70function makeTemporaryDirectory() {
71 const directory = mkdtempSync(join(tmpdir(), "t3code-public-config-"));
72 temporaryDirectories.push(directory);
73 return directory;
74}
scripts/lib/public-config.ts+78−0
@@ -0,0 +1,78 @@
1// @effect-diagnostics nodeBuiltinImport:off - Build bootstrap reads optional root env files before an Effect runtime exists.
2import * as NodeFS from "node:fs";
3import * as NodePath from "node:path";
4import * as NodeURL from "node:url";
5import * as NodeUtil from "node:util";
6
7import { DEFAULT_T3_CLERK_PUBLISHABLE_KEY, DEFAULT_T3_RELAY_URL } from "@t3tools/shared/relayAuth";
8
9export interface T3CodePublicConfig {
10 readonly clerkPublishableKey: string;
11 readonly relayUrl: string;
12}
13
14type Environment = Readonly<Record<string, string | undefined>>;
15
16const REPO_ROOT = NodePath.dirname(
17 NodePath.dirname(NodePath.dirname(NodeURL.fileURLToPath(import.meta.url))),
18);
19
20// These values are intentionally public. Client builds embed them so a fresh clone can use
21// T3 Cloud without local setup. Use root .env files or CI environment variables to override them.
22export const DEFAULT_PUBLIC_CONFIG: T3CodePublicConfig = {
23 clerkPublishableKey: DEFAULT_T3_CLERK_PUBLISHABLE_KEY,
24 relayUrl: DEFAULT_T3_RELAY_URL,
25};
26
27export function loadRepoEnv({
28 baseEnv = process.env,
29 repoRoot = REPO_ROOT,
30}: {
31 readonly baseEnv?: Environment;
32 readonly repoRoot?: string;
33} = {}): Record<string, string | undefined> {
34 const rootEnv = readEnvFile(NodePath.join(repoRoot, ".env"));
35 const localEnv = readEnvFile(NodePath.join(repoRoot, ".env.local"));
36 const config = resolvePublicConfig(baseEnv, localEnv, rootEnv);
37
38 return {
39 ...rootEnv,
40 ...localEnv,
41 ...baseEnv,
42 T3CODE_CLERK_PUBLISHABLE_KEY: config.clerkPublishableKey,
43 T3_RELAY_URL: config.relayUrl,
44 VITE_CLERK_PUBLISHABLE_KEY: config.clerkPublishableKey,
45 VITE_T3_RELAY_URL: config.relayUrl,
46 EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY: config.clerkPublishableKey,
47 };
48}
49
50export function resolvePublicConfig(...sources: readonly Environment[]): T3CodePublicConfig {
51 return {
52 clerkPublishableKey:
53 firstNonEmpty(
54 sources,
55 "T3CODE_CLERK_PUBLISHABLE_KEY",
56 "VITE_CLERK_PUBLISHABLE_KEY",
57 "EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY",
58 ) ?? DEFAULT_PUBLIC_CONFIG.clerkPublishableKey,
59 relayUrl:
60 firstNonEmpty(sources, "T3_RELAY_URL", "VITE_T3_RELAY_URL") ?? DEFAULT_PUBLIC_CONFIG.relayUrl,
61 };
62}
63
64function firstNonEmpty(sources: readonly Environment[], ...names: readonly string[]) {
65 for (const source of sources) {
66 for (const name of names) {
67 const value = source[name]?.trim();
68 if (value) {
69 return value;
70 }
71 }
72 }
73 return undefined;
74}
75
76function readEnvFile(path: string): Record<string, string | undefined> {
77 return NodeFS.existsSync(path) ? NodeUtil.parseEnv(NodeFS.readFileSync(path, "utf8")) : {};
78}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t