create-authhero 0.41.2 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,7 +16,7 @@ const widgetPath = path.resolve(
16
16
 
17
17
  const adminDistPath = path.resolve(
18
18
  __dirname,
19
- "../node_modules/@authhero/react-admin/dist",
19
+ "../node_modules/@authhero/admin/dist",
20
20
  );
21
21
  const adminIndexPath = path.join(adminDistPath, "index.html");
22
22
 
@@ -27,7 +27,14 @@ function ensureCertificates() {
27
27
  execFileSync("which", ["mkcert"], { stdio: "ignore" });
28
28
  execFileSync(
29
29
  "mkcert",
30
- ["-key-file", keyPath, "-cert-file", certPath, "localhost", "127.0.0.1"],
30
+ [
31
+ "-key-file",
32
+ keyPath,
33
+ "-cert-file",
34
+ certPath,
35
+ "localhost",
36
+ "127.0.0.1",
37
+ ],
31
38
  { stdio: "inherit" },
32
39
  );
33
40
  console.log("✅ Certificates generated with mkcert");
@@ -0,0 +1,54 @@
1
+ # AuthHero Proxy
2
+
3
+ A Cloudflare Worker that proxies incoming requests to upstream services based on the request's `Host` header. Built on [@authhero/proxy](https://www.npmjs.com/package/@authhero/proxy).
4
+
5
+ ## Configure your routes
6
+
7
+ Edit [src/proxy.config.ts](src/proxy.config.ts) to map each public hostname to one or more upstream routes. Path patterns support `*` and `:param` segments, and routes are matched in priority order (lower wins).
8
+
9
+ ```ts
10
+ export const proxyConfig: StaticProxyAdapterOptions = {
11
+ hosts: {
12
+ "id.example.com": {
13
+ tenant_id: "example",
14
+ routes: [
15
+ {
16
+ path_pattern: "/*",
17
+ upstream_type: "http",
18
+ upstream_url: "https://upstream.example.com",
19
+ },
20
+ ],
21
+ },
22
+ },
23
+ };
24
+ ```
25
+
26
+ ## Caching
27
+
28
+ Resolved hosts are cached in-memory per Worker isolate with a stale-while-revalidate strategy:
29
+
30
+ - **Fresh** for 5 minutes — served directly from cache.
31
+ - **Stale** for the next hour — served from cache while a background refresh runs.
32
+ - **Negative** (host not found) — cached for 30 seconds so newly-added hosts come online quickly.
33
+
34
+ For the static adapter the "refresh" is just a re-read of the in-memory config, so the SWR window mainly matters when you swap to an HTTP- or database-backed adapter.
35
+
36
+ ## Develop locally
37
+
38
+ ```bash
39
+ npm run dev
40
+ ```
41
+
42
+ The worker is served at `http://localhost:8787`. To exercise a specific host, send the `Host` header:
43
+
44
+ ```bash
45
+ curl http://localhost:8787/login -H "Host: id.example.com"
46
+ ```
47
+
48
+ ## Deploy
49
+
50
+ ```bash
51
+ npm run deploy
52
+ ```
53
+
54
+ Add a custom-domain route in `wrangler.toml` for each hostname you've configured, or attach the worker to existing routes in the Cloudflare dashboard.
@@ -0,0 +1,40 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import {
3
+ createProxyApp,
4
+ createStaticProxyAdapter,
5
+ } from "@authhero/proxy";
6
+ import { proxyConfig } from "./proxy.config";
7
+
8
+ // AsyncLocalStorage threads each request's ExecutionContext through to the
9
+ // host cache so background SWR refreshes keep running after the response
10
+ // returns. Requires the `nodejs_compat` compatibility flag.
11
+ interface RequestCtx {
12
+ waitUntil: (promise: Promise<unknown>) => void;
13
+ }
14
+ const requestCtx = new AsyncLocalStorage<RequestCtx>();
15
+
16
+ const data = createStaticProxyAdapter(proxyConfig);
17
+
18
+ const app = createProxyApp({
19
+ data,
20
+ cache: {
21
+ // Serve cached values directly for 5 minutes.
22
+ freshTtlMs: 5 * 60_000,
23
+ // For the next hour, keep serving the cached value and refresh in the
24
+ // background. After that, the next request blocks on a fresh fetch.
25
+ staleTtlMs: 60 * 60_000,
26
+ // Don't cache "host not found" for as long — new hosts should become
27
+ // reachable quickly after being added to the config.
28
+ negativeTtlMs: 30_000,
29
+ waitUntil: (promise) => requestCtx.getStore()?.waitUntil(promise),
30
+ },
31
+ });
32
+
33
+ export default {
34
+ fetch(request: Request, _env: unknown, ctx: ExecutionContext) {
35
+ return requestCtx.run(
36
+ { waitUntil: ctx.waitUntil.bind(ctx) },
37
+ () => app.fetch(request),
38
+ );
39
+ },
40
+ };
@@ -0,0 +1,22 @@
1
+ import type { StaticProxyAdapterOptions } from "@authhero/proxy";
2
+
3
+ // Map each public hostname to the routes the proxy should serve for it.
4
+ // Routes are matched in priority order (lower priority wins). The path
5
+ // pattern supports `*` and `:param` segments.
6
+ //
7
+ // Edit this file to add your hosts, then re-deploy.
8
+ export const proxyConfig: StaticProxyAdapterOptions = {
9
+ hosts: {
10
+ "id.example.com": {
11
+ tenant_id: "example",
12
+ routes: [
13
+ {
14
+ path_pattern: "/*",
15
+ upstream_type: "http",
16
+ upstream_url: "https://upstream.example.com",
17
+ preserve_host: false,
18
+ },
19
+ ],
20
+ },
21
+ },
22
+ };
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "types": ["@cloudflare/workers-types", "node"]
11
+ },
12
+ "include": ["src/**/*"],
13
+ "exclude": ["node_modules"]
14
+ }
@@ -0,0 +1,22 @@
1
+ # ════════════════════════════════════════════════════════════════════════════
2
+ # AuthHero Proxy — Cloudflare Worker Configuration
3
+ # ════════════════════════════════════════════════════════════════════════════
4
+
5
+ name = "authhero-proxy"
6
+ main = "src/index.ts"
7
+ compatibility_date = "2025-05-23"
8
+ compatibility_flags = ["nodejs_compat"]
9
+
10
+ # ════════════════════════════════════════════════════════════════════════════
11
+ # OPTIONAL: Custom Domains
12
+ # ════════════════════════════════════════════════════════════════════════════
13
+ # Route the public hostnames you configured in src/proxy.config.ts to this
14
+ # worker. Each host should be a custom domain (or have a route added) in your
15
+ # Cloudflare account.
16
+ #
17
+ # [[routes]]
18
+ # pattern = "id.example.com"
19
+ # custom_domain = true
20
+
21
+ [observability]
22
+ enabled = true
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "type": "git",
6
6
  "url": "https://github.com/markusahlstrand/authhero"
7
7
  },
8
- "version": "0.41.2",
8
+ "version": "0.43.0",
9
9
  "type": "module",
10
10
  "main": "dist/create-authhero.js",
11
11
  "bin": {
@@ -19,10 +19,10 @@
19
19
  "@rollup/plugin-commonjs": "^26.0.1",
20
20
  "@rollup/plugin-node-resolve": "^15.2.3",
21
21
  "@types/inquirer": "^9.0.7",
22
- "@types/node": "^20.14.9",
23
- "tsx": "^4.19.4",
22
+ "@types/node": "^20.19.41",
23
+ "tsx": "^4.22.3",
24
24
  "typescript": "^5.5.2",
25
- "vite": "^5.3.2"
25
+ "vite": "^8.0.14"
26
26
  },
27
27
  "dependencies": {
28
28
  "commander": "^12.1.0",